Skip to content

Commit 29f6bde

Browse files
authored
feat(query): implement st_geometryfromewkb function (#15118)
* impl st_geometryfromewkb * impl st_geometryfromewkb
1 parent 87713d1 commit 29f6bde

File tree

6 files changed

+283
-2
lines changed

6 files changed

+283
-2
lines changed

src/query/functions/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ geo = { workspace = true }
3737
geo-types = "0.7.13"
3838
geohash = "0.13.0"
3939
geos = { version = "8.3", features = ["static", "geo", "geo-types"] }
40-
geozero = { workspace = true }
40+
geozero = { workspace = true, features = ["with-geos"] }
4141
h3o = "0.4.0"
4242
hex = "0.4.3"
4343
itertools = { workspace = true }

src/query/functions/src/scalars/geometry.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
use databend_common_exception::ErrorCode;
1616
use databend_common_expression::types::geometry::GeometryType;
17+
use databend_common_expression::types::BinaryType;
1718
use databend_common_expression::types::Int32Type;
1819
use databend_common_expression::types::NumberType;
1920
use databend_common_expression::types::StringType;
@@ -32,6 +33,8 @@ use geos::Geom;
3233
use geos::Geometry;
3334
use geozero::wkb::Ewkb;
3435
use geozero::CoordDimensions;
36+
use geozero::GeozeroGeometry;
37+
use geozero::ToGeos;
3538
use geozero::ToWkb;
3639
use geozero::ToWkt;
3740

@@ -41,6 +44,12 @@ pub fn register(registry: &mut FunctionRegistry) {
4144
// aliases
4245
registry.register_aliases("st_makegeompoint", &["st_geom_point"]);
4346
registry.register_aliases("st_makeline", &["st_make_line"]);
47+
registry.register_aliases("st_geometryfromwkb", &[
48+
"st_geomfromwkb",
49+
"st_geometryfromewkb",
50+
"st_geomfromewkb",
51+
"to_geometry",
52+
]);
4453
registry.register_aliases("st_geometryfromwkt", &[
4554
"st_geomfromwkt",
4655
"st_geometryfromewkt",
@@ -164,6 +173,130 @@ pub fn register(registry: &mut FunctionRegistry) {
164173
),
165174
);
166175

176+
registry.register_passthrough_nullable_1_arg::<StringType, GeometryType, _, _>(
177+
"st_geometryfromwkb",
178+
|_, _| FunctionDomain::MayThrow,
179+
vectorize_with_builder_1_arg::<StringType, GeometryType>(|ewkb, builder, ctx| {
180+
if let Some(validity) = &ctx.validity {
181+
if !validity.get_bit(builder.len()) {
182+
builder.commit_row();
183+
return;
184+
}
185+
}
186+
187+
let b_ewkb = match hex::decode(ewkb) {
188+
Ok(b) => b,
189+
Err(e) => {
190+
ctx.set_error(
191+
builder.len(),
192+
ErrorCode::GeometryError(e.to_string()).to_string(),
193+
);
194+
return builder.put_str("");
195+
}
196+
};
197+
match Ewkb(&b_ewkb).to_geos() {
198+
Ok(_) => builder.put_slice(b_ewkb.as_slice()),
199+
Err(e) => ctx.set_error(builder.len(), e.to_string()),
200+
}
201+
builder.commit_row();
202+
}),
203+
);
204+
205+
registry.register_passthrough_nullable_1_arg::<BinaryType, GeometryType, _, _>(
206+
"st_geometryfromwkb",
207+
|_, _| FunctionDomain::MayThrow,
208+
vectorize_with_builder_1_arg::<BinaryType, GeometryType>(|ewkb, builder, ctx| {
209+
if let Some(validity) = &ctx.validity {
210+
if !validity.get_bit(builder.len()) {
211+
builder.commit_row();
212+
return;
213+
}
214+
}
215+
216+
match Ewkb(&ewkb).to_geos() {
217+
Ok(_) => builder.put_slice(ewkb),
218+
Err(e) => ctx.set_error(builder.len(), e.to_string()),
219+
}
220+
builder.commit_row();
221+
}),
222+
);
223+
224+
registry.register_passthrough_nullable_2_arg::<StringType, Int32Type, GeometryType, _, _>(
225+
"st_geometryfromwkb",
226+
|_, _, _| FunctionDomain::MayThrow,
227+
vectorize_with_builder_2_arg::<StringType, Int32Type, GeometryType>(
228+
|ewkb, srid, builder, ctx| {
229+
if let Some(validity) = &ctx.validity {
230+
if !validity.get_bit(builder.len()) {
231+
builder.commit_row();
232+
return;
233+
}
234+
}
235+
236+
let result = {
237+
hex::decode(ewkb)
238+
.map_err(|e| ErrorCode::from(e.to_string()))
239+
.and_then(|binary| {
240+
Ewkb(binary)
241+
.to_geos()
242+
.map_err(|e| ErrorCode::GeometryError(e.to_string()))
243+
.and_then(|geos| {
244+
geos.to_ewkb(geos.dims(), Some(srid))
245+
.map_err(|e| ErrorCode::GeometryError(e.to_string()))
246+
})
247+
})
248+
};
249+
250+
match result {
251+
Ok(data) => {
252+
builder.put_slice(data.as_slice());
253+
}
254+
Err(e) => {
255+
ctx.set_error(builder.len(), e.to_string());
256+
}
257+
}
258+
259+
builder.commit_row();
260+
},
261+
),
262+
);
263+
264+
registry.register_passthrough_nullable_2_arg::<BinaryType, Int32Type, GeometryType, _, _>(
265+
"st_geometryfromwkb",
266+
|_, _, _| FunctionDomain::MayThrow,
267+
vectorize_with_builder_2_arg::<BinaryType, Int32Type, GeometryType>(
268+
|ewkb, srid, builder, ctx| {
269+
if let Some(validity) = &ctx.validity {
270+
if !validity.get_bit(builder.len()) {
271+
builder.commit_row();
272+
return;
273+
}
274+
}
275+
276+
let result = {
277+
Ewkb(ewkb)
278+
.to_geos()
279+
.map_err(|e| ErrorCode::GeometryError(e.to_string()))
280+
.and_then(|geos| {
281+
geos.to_ewkb(geos.dims(), Some(srid))
282+
.map_err(|e| ErrorCode::GeometryError(e.to_string()))
283+
})
284+
};
285+
286+
match result {
287+
Ok(data) => {
288+
builder.put_slice(data.as_slice());
289+
}
290+
Err(e) => {
291+
ctx.set_error(builder.len(), e.to_string());
292+
}
293+
}
294+
295+
builder.commit_row();
296+
},
297+
),
298+
);
299+
167300
registry.register_passthrough_nullable_1_arg::<StringType, GeometryType, _, _>(
168301
"st_geometryfromwkt",
169302
|_, _| FunctionDomain::MayThrow,

src/query/functions/tests/it/scalars/geometry.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ fn test_geometry() {
2929
test_st_makeline(file);
3030
test_st_makepoint(file);
3131
test_to_string(file);
32+
test_st_geometryfromwkb(file);
3233
test_st_geometryfromwkt(file);
3334
// test_st_transform(file);
3435
}
@@ -74,6 +75,44 @@ fn test_to_string(file: &mut impl Write) {
7475
]);
7576
}
7677

78+
fn test_st_geometryfromwkb(file: &mut impl Write) {
79+
run_ast(
80+
file,
81+
"st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641')",
82+
&[],
83+
);
84+
85+
run_ast(
86+
file,
87+
"st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'))",
88+
&[],
89+
);
90+
91+
run_ast(
92+
file,
93+
"st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641', 4326)",
94+
&[],
95+
);
96+
97+
run_ast(
98+
file,
99+
"st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'), 4326)",
100+
&[],
101+
);
102+
103+
run_ast(file, "st_geometryfromwkb(a, b)", &[
104+
(
105+
"a",
106+
StringType::from_data(vec![
107+
"0101000020797f000066666666a9cb17411f85ebc19e325641",
108+
"0101000020797f000066666666a9cb17411f85ebc19e325641",
109+
"0101000020797f000066666666a9cb17411f85ebc19e325641",
110+
]),
111+
),
112+
("b", Int32Type::from_data(vec![32633, 4326, 3857])),
113+
]);
114+
}
115+
77116
fn test_st_geometryfromwkt(file: &mut impl Write) {
78117
// without srid
79118
run_ast(

src/query/functions/tests/it/scalars/testdata/function_list.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ rlike -> regexp
3535
sha1 -> sha
3636
siphash -> siphash64
3737
st_geom_point -> st_makegeompoint
38+
st_geometryfromewkb -> st_geometryfromwkb
3839
st_geometryfromewkt -> st_geometryfromwkt
3940
st_geometryfromtext -> st_geometryfromwkt
41+
st_geomfromewkb -> st_geometryfromwkb
4042
st_geomfromewkt -> st_geometryfromwkt
4143
st_geomfromtext -> st_geometryfromwkt
44+
st_geomfromwkb -> st_geometryfromwkb
4245
st_geomfromwkt -> st_geometryfromwkt
4346
st_make_line -> st_makeline
4447
str_to_date -> to_date
@@ -3495,6 +3498,14 @@ Functions overloads:
34953498
17 sqrt(Float32 NULL) :: Float64 NULL
34963499
18 sqrt(Float64) :: Float64
34973500
19 sqrt(Float64 NULL) :: Float64 NULL
3501+
0 st_geometryfromwkb(String) :: Geometry
3502+
1 st_geometryfromwkb(String NULL) :: Geometry NULL
3503+
2 st_geometryfromwkb(Binary) :: Geometry
3504+
3 st_geometryfromwkb(Binary NULL) :: Geometry NULL
3505+
4 st_geometryfromwkb(String, Int32) :: Geometry
3506+
5 st_geometryfromwkb(String NULL, Int32 NULL) :: Geometry NULL
3507+
6 st_geometryfromwkb(Binary, Int32) :: Geometry
3508+
7 st_geometryfromwkb(Binary NULL, Int32 NULL) :: Geometry NULL
34983509
0 st_geometryfromwkt(String) :: Geometry
34993510
1 st_geometryfromwkt(String NULL) :: Geometry NULL
35003511
2 st_geometryfromwkt(String, Int32) :: Geometry

src/query/functions/tests/it/scalars/testdata/geometry.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,66 @@ evaluation (internal):
104104
+--------+-----------------------------------------------------------------------------------------------------------------+
105105

106106

107+
ast : st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641')
108+
raw expr : st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641')
109+
checked expr : st_geometryfromwkb<String>("0101000020797f000066666666a9cb17411f85ebc19e325641")
110+
optimized expr : "SRID=32633;POINT(389866.35 5819003.03)"
111+
output type : Geometry
112+
output domain : Undefined
113+
output : 'SRID=32633;POINT(389866.35 5819003.03)'
114+
115+
116+
ast : st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'))
117+
raw expr : st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'))
118+
checked expr : st_geometryfromwkb<Binary>(from_hex<String>("0101000020797f000066666666a9cb17411f85ebc19e325641"))
119+
optimized expr : "SRID=32633;POINT(389866.35 5819003.03)"
120+
output type : Geometry
121+
output domain : Undefined
122+
output : 'SRID=32633;POINT(389866.35 5819003.03)'
123+
124+
125+
ast : st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641', 4326)
126+
raw expr : st_geometryfromwkb('0101000020797f000066666666a9cb17411f85ebc19e325641', 4326)
127+
checked expr : st_geometryfromwkb<String, Int32>("0101000020797f000066666666a9cb17411f85ebc19e325641", to_int32<UInt16>(4326_u16))
128+
optimized expr : "SRID=4326;POINT(389866.35 5819003.03)"
129+
output type : Geometry
130+
output domain : Undefined
131+
output : 'SRID=4326;POINT(389866.35 5819003.03)'
132+
133+
134+
ast : st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'), 4326)
135+
raw expr : st_geometryfromwkb(unhex('0101000020797f000066666666a9cb17411f85ebc19e325641'), 4326)
136+
checked expr : st_geometryfromwkb<Binary, Int32>(from_hex<String>("0101000020797f000066666666a9cb17411f85ebc19e325641"), to_int32<UInt16>(4326_u16))
137+
optimized expr : "SRID=4326;POINT(389866.35 5819003.03)"
138+
output type : Geometry
139+
output domain : Undefined
140+
output : 'SRID=4326;POINT(389866.35 5819003.03)'
141+
142+
143+
ast : st_geometryfromwkb(a, b)
144+
raw expr : st_geometryfromwkb(a::String, b::Int32)
145+
checked expr : st_geometryfromwkb<String, Int32>(a, b)
146+
optimized expr : st_geometryfromwkb<String, Int32>("0101000020797f000066666666a9cb17411f85ebc19e325641", b)
147+
evaluation:
148+
+--------+---------------------------------------------------------------------------------------------------------------+----------------+------------------------------------------+
149+
| | a | b | Output |
150+
+--------+---------------------------------------------------------------------------------------------------------------+----------------+------------------------------------------+
151+
| Type | String | Int32 | Geometry |
152+
| Domain | {"0101000020797f000066666666a9cb17411f85ebc19e325641"..="0101000020797f000066666666a9cb17411f85ebc19e325641"} | {3857..=32633} | Unknown |
153+
| Row 0 | '0101000020797f000066666666a9cb17411f85ebc19e325641' | 32633 | 'SRID=32633;POINT(389866.35 5819003.03)' |
154+
| Row 1 | '0101000020797f000066666666a9cb17411f85ebc19e325641' | 4326 | 'SRID=4326;POINT(389866.35 5819003.03)' |
155+
| Row 2 | '0101000020797f000066666666a9cb17411f85ebc19e325641' | 3857 | 'SRID=3857;POINT(389866.35 5819003.03)' |
156+
+--------+---------------------------------------------------------------------------------------------------------------+----------------+------------------------------------------+
157+
evaluation (internal):
158+
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
159+
| Column | Data |
160+
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
161+
| a | StringColumn { data: 0x303130313030303032303739376630303030363636363636363661396362313734313166383565626331396533323536343130313031303030303230373937663030303036363636363636366139636231373431316638356562633139653332353634313031303130303030323037393766303030303636363636363636613963623137343131663835656263313965333235363431, offsets: [0, 50, 100, 150] } |
162+
| b | Int32([32633, 4326, 3857]) |
163+
| Output | BinaryColumn { data: 0x0101000020797f000066666666a9cb17411f85ebc19e3256410101000020e610000066666666a9cb17411f85ebc19e3256410101000020110f000066666666a9cb17411f85ebc19e325641, offsets: [0, 25, 50, 75] } |
164+
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
165+
166+
107167
ast : st_geometryfromwkt('POINT(389866.35 5819003.03)')
108168
raw expr : st_geometryfromwkt('POINT(389866.35 5819003.03)')
109169
checked expr : st_geometryfromwkt<String>("POINT(389866.35 5819003.03)")

tests/sqllogictests/suites/query/02_function/02_0060_function_geometry.test

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,46 @@ SRID=32633;LINESTRING(1 2,3.5 4.5)
6767
SRID=4326;LINESTRING(1 2,1 2,10.1 5.5)
6868
LINESTRING(1 2,10.1 5.5,3.5 4.5,6.1 7.9)
6969

70+
statement ok
71+
DROP TABLE IF EXISTS t1;
72+
73+
statement ok
74+
CREATE TABLE t1 (b binary);
75+
76+
statement ok
77+
INSERT INTO t1 VALUES(UNHEX('0101000020797f000066666666a9cb17411f85ebc19e325641'));
78+
79+
query T
80+
SELECT TO_STRING(ST_GEOMETRYFROMWKB(b)) FROM t1;
81+
----
82+
SRID=32633;POINT(389866.35 5819003.03)
83+
84+
query T
85+
SELECT TO_STRING(ST_GEOMETRYFROMWKB(b, 4326)) FROM t1;
86+
----
87+
SRID=4326;POINT(389866.35 5819003.03)
88+
89+
statement ok
90+
DROP TABLE IF EXISTS t1;
91+
92+
statement ok
93+
CREATE TABLE t1 (b STRING);
94+
95+
statement ok
96+
INSERT INTO t1 VALUES('0101000020797f000066666666a9cb17411f85ebc19e325641');
97+
98+
query T
99+
SELECT TO_STRING(ST_GEOMETRYFROMWKB(b)) FROM t1;
100+
----
101+
SRID=32633;POINT(389866.35 5819003.03)
102+
103+
query T
104+
SELECT TO_STRING(ST_GEOMETRYFROMWKB(b, 4326)) FROM t1;
105+
----
106+
SRID=4326;POINT(389866.35 5819003.03)
107+
70108
statement ok
71109
SET enable_geo_create_table=0
72110

73111
statement ok
74-
DROP TABLE IF EXISTS t1
112+
DROP TABLE IF EXISTS t1;

0 commit comments

Comments
 (0)