common_function/scalars/geo/
s2.rs1use std::sync::LazyLock;
16
17use common_query::error::{InvalidFuncArgsSnafu, Result};
18use datafusion_expr::{Signature, TypeSignature, Volatility};
19use datatypes::arrow::datatypes::DataType;
20use datatypes::scalars::ScalarVectorBuilder;
21use datatypes::value::Value;
22use datatypes::vectors::{MutableVector, StringVectorBuilder, UInt64VectorBuilder, VectorRef};
23use derive_more::Display;
24use s2::cellid::{CellID, MAX_LEVEL};
25use s2::latlng::LatLng;
26use snafu::ensure;
27
28use crate::function::{Function, FunctionContext};
29use crate::scalars::geo::helpers::{ensure_and_coerce, ensure_columns_len, ensure_columns_n};
30
31static CELL_TYPES: LazyLock<Vec<DataType>> =
32 LazyLock::new(|| vec![DataType::Int64, DataType::UInt64]);
33
34static COORDINATE_TYPES: LazyLock<Vec<DataType>> =
35 LazyLock::new(|| vec![DataType::Float32, DataType::Float64]);
36
37static LEVEL_TYPES: &[DataType] = datafusion_expr::type_coercion::aggregates::INTEGERS;
38
39#[derive(Clone, Debug, Default, Display)]
43#[display("{}", self.name())]
44pub struct S2LatLngToCell;
45
46impl Function for S2LatLngToCell {
47 fn name(&self) -> &str {
48 "s2_latlng_to_cell"
49 }
50
51 fn return_type(&self, _: &[DataType]) -> Result<DataType> {
52 Ok(DataType::UInt64)
53 }
54
55 fn signature(&self) -> Signature {
56 let mut signatures = Vec::with_capacity(COORDINATE_TYPES.len());
57 for coord_type in COORDINATE_TYPES.as_slice() {
58 signatures.push(TypeSignature::Exact(vec![
59 coord_type.clone(),
61 coord_type.clone(),
63 ]));
64 }
65 Signature::one_of(signatures, Volatility::Stable)
66 }
67
68 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
69 ensure_columns_n!(columns, 2);
70
71 let lat_vec = &columns[0];
72 let lon_vec = &columns[1];
73
74 let size = lat_vec.len();
75 let mut results = UInt64VectorBuilder::with_capacity(size);
76
77 for i in 0..size {
78 let lat = lat_vec.get(i).as_f64_lossy();
79 let lon = lon_vec.get(i).as_f64_lossy();
80
81 let result = match (lat, lon) {
82 (Some(lat), Some(lon)) => {
83 let coord = LatLng::from_degrees(lat, lon);
84 ensure!(
85 coord.is_valid(),
86 InvalidFuncArgsSnafu {
87 err_msg: "The input coordinates are invalid",
88 }
89 );
90 let cellid = CellID::from(coord);
91 let encoded: u64 = cellid.0;
92 Some(encoded)
93 }
94 _ => None,
95 };
96
97 results.push(result);
98 }
99
100 Ok(results.to_vector())
101 }
102}
103
104#[derive(Clone, Debug, Default, Display)]
106#[display("{}", self.name())]
107pub struct S2CellLevel;
108
109impl Function for S2CellLevel {
110 fn name(&self) -> &str {
111 "s2_cell_level"
112 }
113
114 fn return_type(&self, _: &[DataType]) -> Result<DataType> {
115 Ok(DataType::UInt64)
116 }
117
118 fn signature(&self) -> Signature {
119 signature_of_cell()
120 }
121
122 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
123 ensure_columns_n!(columns, 1);
124
125 let cell_vec = &columns[0];
126 let size = cell_vec.len();
127 let mut results = UInt64VectorBuilder::with_capacity(size);
128
129 for i in 0..size {
130 let cell = cell_from_value(cell_vec.get(i));
131 let res = cell.map(|cell| cell.level());
132
133 results.push(res);
134 }
135
136 Ok(results.to_vector())
137 }
138}
139
140#[derive(Clone, Debug, Default, Display)]
142#[display("{}", self.name())]
143pub struct S2CellToToken;
144
145impl Function for S2CellToToken {
146 fn name(&self) -> &str {
147 "s2_cell_to_token"
148 }
149
150 fn return_type(&self, _: &[DataType]) -> Result<DataType> {
151 Ok(DataType::Utf8)
152 }
153
154 fn signature(&self) -> Signature {
155 signature_of_cell()
156 }
157
158 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
159 ensure_columns_n!(columns, 1);
160
161 let cell_vec = &columns[0];
162 let size = cell_vec.len();
163 let mut results = StringVectorBuilder::with_capacity(size);
164
165 for i in 0..size {
166 let cell = cell_from_value(cell_vec.get(i));
167 let res = cell.map(|cell| cell.to_token());
168
169 results.push(res.as_deref());
170 }
171
172 Ok(results.to_vector())
173 }
174}
175
176#[derive(Clone, Debug, Default, Display)]
178#[display("{}", self.name())]
179pub struct S2CellParent;
180
181impl Function for S2CellParent {
182 fn name(&self) -> &str {
183 "s2_cell_parent"
184 }
185
186 fn return_type(&self, _: &[DataType]) -> Result<DataType> {
187 Ok(DataType::UInt64)
188 }
189
190 fn signature(&self) -> Signature {
191 signature_of_cell_and_level()
192 }
193
194 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
195 ensure_columns_n!(columns, 2);
196
197 let cell_vec = &columns[0];
198 let level_vec = &columns[1];
199 let size = cell_vec.len();
200 let mut results = UInt64VectorBuilder::with_capacity(size);
201
202 for i in 0..size {
203 let cell = cell_from_value(cell_vec.get(i));
204 let level = value_to_level(level_vec.get(i))?;
205 let result = cell.map(|cell| cell.parent(level).0);
206
207 results.push(result);
208 }
209
210 Ok(results.to_vector())
211 }
212}
213
214fn signature_of_cell() -> Signature {
215 let mut signatures = Vec::with_capacity(CELL_TYPES.len());
216 for cell_type in CELL_TYPES.as_slice() {
217 signatures.push(TypeSignature::Exact(vec![cell_type.clone()]));
218 }
219
220 Signature::one_of(signatures, Volatility::Stable)
221}
222
223fn signature_of_cell_and_level() -> Signature {
224 let mut signatures = Vec::with_capacity(CELL_TYPES.len() * LEVEL_TYPES.len());
225 for cell_type in CELL_TYPES.as_slice() {
226 for level_type in LEVEL_TYPES {
227 signatures.push(TypeSignature::Exact(vec![
228 cell_type.clone(),
229 level_type.clone(),
230 ]));
231 }
232 }
233 Signature::one_of(signatures, Volatility::Stable)
234}
235
236fn cell_from_value(v: Value) -> Option<CellID> {
237 match v {
238 Value::Int64(v) => Some(CellID(v as u64)),
239 Value::UInt64(v) => Some(CellID(v)),
240 _ => None,
241 }
242}
243
244fn value_to_level(v: Value) -> Result<u64> {
245 match v {
246 Value::Int8(v) => ensure_and_coerce!(v >= 0 && v <= MAX_LEVEL as i8, v as u64),
247 Value::Int16(v) => ensure_and_coerce!(v >= 0 && v <= MAX_LEVEL as i16, v as u64),
248 Value::Int32(v) => ensure_and_coerce!(v >= 0 && v <= MAX_LEVEL as i32, v as u64),
249 Value::Int64(v) => ensure_and_coerce!(v >= 0 && v <= MAX_LEVEL as i64, v as u64),
250 Value::UInt8(v) => ensure_and_coerce!(v <= MAX_LEVEL as u8, v as u64),
251 Value::UInt16(v) => ensure_and_coerce!(v <= MAX_LEVEL as u16, v as u64),
252 Value::UInt32(v) => ensure_and_coerce!(v <= MAX_LEVEL as u32, v as u64),
253 Value::UInt64(v) => ensure_and_coerce!(v <= MAX_LEVEL, v),
254 _ => unreachable!(),
255 }
256}