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