Skip to content

Commit e0da4f8

Browse files
authored
feat: add geometry data type (#352)
1 parent 83f0288 commit e0da4f8

File tree

8 files changed

+49
-10
lines changed

8 files changed

+49
-10
lines changed

bindings/nodejs/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl ToNapiValue for Value {
9595
databend_driver::Value::Tuple(_) => String::to_napi_value(env, format!("{}", val.0)),
9696
databend_driver::Value::Bitmap(s) => String::to_napi_value(env, s),
9797
databend_driver::Value::Variant(s) => String::to_napi_value(env, s),
98+
databend_driver::Value::Geometry(s) => String::to_napi_value(env, s),
9899
}
99100
}
100101
}

bindings/python/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl IntoPy<PyObject> for Value {
7676
}
7777
databend_driver::Value::Bitmap(s) => s.into_py(py),
7878
databend_driver::Value::Variant(s) => s.into_py(py),
79+
databend_driver::Value::Geometry(s) => s.into_py(py),
7980
}
8081
}
8182
}

cli/src/ast/tokenizer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ pub enum TokenKind {
286286
BETWEEN,
287287
#[token("BIGINT", ignore(ascii_case))]
288288
BIGINT,
289+
#[token("BITMAP", ignore(ascii_case))]
290+
BITMAP,
289291
#[token("BOOL", ignore(ascii_case))]
290292
BOOL,
291293
#[token("BOOLEAN", ignore(ascii_case))]
@@ -478,6 +480,8 @@ pub enum TokenKind {
478480
FUSE,
479481
#[token("GET", ignore(ascii_case))]
480482
GET,
483+
#[token("GEOMETRY", ignore(ascii_case))]
484+
GEOMETRY,
481485
#[token("GLOBAL", ignore(ascii_case))]
482486
GLOBAL,
483487
#[token("GRAPH", ignore(ascii_case))]

cli/src/display.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -567,13 +567,7 @@ fn create_table(
567567
let mut header = Vec::with_capacity(column_count);
568568
let mut aligns = Vec::with_capacity(column_count);
569569

570-
render_head(
571-
schema,
572-
&mut widths,
573-
&mut column_map,
574-
&mut header,
575-
&mut aligns,
576-
);
570+
render_head(schema, &mut widths, &column_map, &mut header, &mut aligns);
577571
table.set_header(header);
578572

579573
// render the top rows
@@ -681,7 +675,7 @@ fn create_table(
681675
fn render_head(
682676
schema: SchemaRef,
683677
widths: &mut [usize],
684-
column_map: &mut Vec<i32>,
678+
column_map: &[i32],
685679
header: &mut Vec<Cell>,
686680
aligns: &mut Vec<CellAlignment>,
687681
) {

sql/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ flight-sql = ["dep:arrow-array", "dep:arrow-schema", "dep:tonic"]
1717
databend-client = { workspace = true }
1818

1919
chrono = { version = "0.4", default-features = false }
20+
geozero = { version = "0.12.0", features = ["default", "with-wkb"] }
2021
glob = "0.3"
2122
itertools = "0.12"
2223
jsonb = "0.3"

sql/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use geozero::error::GeozeroError;
16+
1517
#[derive(Debug)]
1618
pub struct ConvertError {
1719
target: &'static str,
@@ -186,3 +188,9 @@ impl From<ConvertError> for Error {
186188
Error::Convert(e)
187189
}
188190
}
191+
192+
impl From<GeozeroError> for Error {
193+
fn from(e: GeozeroError) -> Self {
194+
Error::Parsing(e.to_string())
195+
}
196+
}

sql/src/schema.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub(crate) const ARROW_EXT_TYPE_EMPTY_MAP: &str = "EmptyMap";
2828
pub(crate) const ARROW_EXT_TYPE_VARIANT: &str = "Variant";
2929
#[cfg(feature = "flight-sql")]
3030
pub(crate) const ARROW_EXT_TYPE_BITMAP: &str = "Bitmap";
31+
#[cfg(feature = "flight-sql")]
32+
pub(crate) const ARROW_EXT_TYPE_GEOMETRY: &str = "Geometry";
3133

3234
use databend_client::response::SchemaField as APISchemaField;
3335

@@ -86,6 +88,7 @@ pub enum DataType {
8688
Tuple(Vec<DataType>),
8789
Variant,
8890
Bitmap,
91+
Geometry,
8992
// Generic(usize),
9093
}
9194

@@ -139,6 +142,7 @@ impl std::fmt::Display for DataType {
139142
}
140143
DataType::Variant => write!(f, "Variant"),
141144
DataType::Bitmap => write!(f, "Bitmap"),
145+
DataType::Geometry => write!(f, "Geometry"),
142146
}
143147
}
144148
}
@@ -246,6 +250,7 @@ impl TryFrom<&TypeDesc<'_>> for DataType {
246250
}
247251
"Variant" => DataType::Variant,
248252
"Bitmap" => DataType::Bitmap,
253+
"Geometry" => DataType::Geometry,
249254
_ => return Err(Error::Parsing(format!("Unknown type: {:?}", desc))),
250255
};
251256
Ok(dt)
@@ -289,6 +294,7 @@ impl TryFrom<&Arc<ArrowField>> for Field {
289294
ARROW_EXT_TYPE_EMPTY_MAP => DataType::EmptyMap,
290295
ARROW_EXT_TYPE_VARIANT => DataType::Variant,
291296
ARROW_EXT_TYPE_BITMAP => DataType::Bitmap,
297+
ARROW_EXT_TYPE_GEOMETRY => DataType::Geometry,
292298
_ => {
293299
return Err(Error::Parsing(format!(
294300
"Unsupported extension datatype for arrow field: {:?}",

sql/src/value.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ use crate::{
2020
schema::{DecimalDataType, DecimalSize},
2121
};
2222

23+
use geozero::wkb::FromWkb;
24+
use geozero::wkb::WkbDialect;
25+
use geozero::wkt::Ewkt;
2326
use std::fmt::Write;
2427

2528
// Thu 1970-01-01 is R.D. 719163
@@ -30,7 +33,7 @@ const NULL_VALUE: &str = "NULL";
3033
use {
3134
crate::schema::{
3235
ARROW_EXT_TYPE_BITMAP, ARROW_EXT_TYPE_EMPTY_ARRAY, ARROW_EXT_TYPE_EMPTY_MAP,
33-
ARROW_EXT_TYPE_VARIANT, EXTENSION_KEY,
36+
ARROW_EXT_TYPE_GEOMETRY, ARROW_EXT_TYPE_VARIANT, EXTENSION_KEY,
3437
},
3538
arrow_array::{
3639
Array as ArrowArray, BinaryArray, BooleanArray, Date32Array, Decimal128Array,
@@ -77,6 +80,7 @@ pub enum Value {
7780
Tuple(Vec<Value>),
7881
Bitmap(String),
7982
Variant(String),
83+
Geometry(String),
8084
}
8185

8286
impl Value {
@@ -126,6 +130,7 @@ impl Value {
126130
}
127131
Self::Bitmap(_) => DataType::Bitmap,
128132
Self::Variant(_) => DataType::Variant,
133+
Self::Geometry(_) => DataType::Geometry,
129134
}
130135
}
131136
}
@@ -191,6 +196,7 @@ impl TryFrom<(&DataType, &str)> for Value {
191196
)),
192197
DataType::Bitmap => Ok(Self::Bitmap(v.to_string())),
193198
DataType::Variant => Ok(Self::Variant(v.to_string())),
199+
DataType::Geometry => Ok(Self::Geometry(v.to_string())),
194200

195201
DataType::Nullable(inner) => {
196202
if v == NULL_VALUE {
@@ -244,6 +250,18 @@ impl TryFrom<(&ArrowField, &Arc<dyn ArrowArray>, usize)> for Value {
244250
None => Err(ConvertError::new("bitmap", format!("{:?}", array)).into()),
245251
};
246252
}
253+
ARROW_EXT_TYPE_GEOMETRY => {
254+
if field.is_nullable() && array.is_null(seq) {
255+
return Ok(Value::Null);
256+
}
257+
return match array.as_any().downcast_ref::<LargeBinaryArray>() {
258+
Some(array) => {
259+
let wkt = parse_geometry(array.value(seq))?;
260+
Ok(Value::Geometry(wkt))
261+
}
262+
None => Err(ConvertError::new("geometry", format!("{:?}", array)).into()),
263+
};
264+
}
247265
_ => {
248266
return Err(ConvertError::new(
249267
"extension",
@@ -605,7 +623,7 @@ fn encode_value(f: &mut std::fmt::Formatter<'_>, val: &Value, raw: bool) -> std:
605623
Value::Boolean(b) => write!(f, "{}", b),
606624
Value::Number(n) => write!(f, "{}", n),
607625
Value::Binary(s) => write!(f, "{}", hex::encode_upper(s)),
608-
Value::String(s) | Value::Bitmap(s) | Value::Variant(s) => {
626+
Value::String(s) | Value::Bitmap(s) | Value::Variant(s) | Value::Geometry(s) => {
609627
if raw {
610628
write!(f, "{}", s)
611629
} else {
@@ -800,3 +818,9 @@ pub fn parse_decimal(text: &str, size: DecimalSize) -> Result<NumberValue> {
800818
}
801819
}
802820
}
821+
822+
pub fn parse_geometry(raw_data: &[u8]) -> Result<String> {
823+
let mut data = std::io::Cursor::new(raw_data);
824+
let wkt = Ewkt::from_wkb(&mut data, WkbDialect::Ewkb);
825+
wkt.map(|g| g.0).map_err(|e| e.into())
826+
}

0 commit comments

Comments
 (0)