Skip to content

Commit 0e55fa9

Browse files
authored
feat(query): ST_CONTAINS (#15994)
* ST_CONTAINS Signed-off-by: Fan Yang <[email protected]> * ST_CONTAINS Signed-off-by: Fan Yang <[email protected]> --------- Signed-off-by: Fan Yang <[email protected]>
1 parent 2338e00 commit 0e55fa9

File tree

9 files changed

+173
-57
lines changed

9 files changed

+173
-57
lines changed

scripts/benchmark/query/load/tpch10.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ select version();
77
SQL
88

99
for t in customer lineitem nation orders partsupp part region supplier; do
10-
echo "DROP TABLE IF EXISTS $t;" | bendsql
10+
echo "DROP TABLE IF EXISTS $t;" | bendsql
1111
done
1212

1313
cat <<SQL | bendsql
@@ -113,8 +113,8 @@ cat <<SQL | bendsql
113113
SQL
114114

115115
for t in customer lineitem nation orders partsupp part region supplier; do
116-
echo "loading into $t ..."
117-
cat <<SQL | bendsql
116+
echo "loading into $t ..."
117+
cat <<SQL | bendsql
118118
COPY INTO $t FROM 's3://repo.databend.com/datasets/tpch10/${t}/' connection=(connection_name='repo') pattern ='${t}.*'
119119
file_format=(type='CSV' field_delimiter='|' record_delimiter='\\n' skip_header=0);
120120
ANALYZE TABLE "${t}";

scripts/benchmark/query/load/tpch100.sh

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ select version();
77
SQL
88

99
for t in customer lineitem nation orders partsupp part region supplier; do
10-
echo "DROP TABLE IF EXISTS $t;" | bendsql
10+
echo "DROP TABLE IF EXISTS $t;" | bendsql
1111
done
1212

1313
cat <<SQL | bendsql
@@ -113,8 +113,8 @@ cat <<SQL | bendsql
113113
SQL
114114

115115
for t in nation region; do
116-
echo "loading into $t ..."
117-
cat <<SQL | bendsql
116+
echo "loading into $t ..."
117+
cat <<SQL | bendsql
118118
COPY INTO $t FROM 's3://repo.databend.com/tpch100/${t}.tbl'
119119
credentials=(access_key_id ='$REPO_ACCESS_KEY_ID' secret_access_key ='$REPO_SECRET_ACCESS_KEY')
120120
file_format=(type='CSV' field_delimiter='|' record_delimiter='\\n' skip_header=1);
@@ -124,8 +124,8 @@ SQL
124124
done
125125

126126
for t in customer lineitem orders partsupp part supplier; do
127-
echo "loading into $t ..."
128-
cat <<SQL | bendsql
127+
echo "loading into $t ..."
128+
cat <<SQL | bendsql
129129
COPY INTO $t FROM 's3://repo.databend.com/tpch100/${t}/' connection=(connection_name='repo') pattern ='${t}.tbl.*'
130130
file_format=(type='CSV' field_delimiter='|' record_delimiter='\\n' skip_header=1);
131131
ANALYZE TABLE "${t}";

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

+41
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use databend_common_exception::ErrorCode;
1616
use databend_common_expression::types::geometry::GeometryType;
1717
use databend_common_expression::types::BinaryType;
18+
use databend_common_expression::types::BooleanType;
1819
use databend_common_expression::types::Int32Type;
1920
use databend_common_expression::types::NullableType;
2021
use databend_common_expression::types::NumberType;
@@ -34,6 +35,7 @@ use databend_common_io::Extremum;
3435
use databend_common_io::GeometryDataType;
3536
use geo::dimensions::Dimensions;
3637
use geo::BoundingRect;
38+
use geo::Contains;
3739
use geo::EuclideanDistance;
3840
use geo::EuclideanLength;
3941
use geo::HasDimensions;
@@ -214,6 +216,45 @@ pub fn register(registry: &mut FunctionRegistry) {
214216
}),
215217
);
216218

219+
registry.register_combine_nullable_2_arg::<GeometryType, GeometryType, BooleanType, _, _>(
220+
"st_contains",
221+
|_, _, _| FunctionDomain::MayThrow,
222+
vectorize_with_builder_2_arg::<GeometryType, GeometryType, NullableType<BooleanType>>(
223+
|l_geometry, r_geometry, builder, ctx| {
224+
let l_ewkb = Ewkb(l_geometry);
225+
let r_ewkb = Ewkb(r_geometry);
226+
let l_geos: Geometry = l_ewkb.to_geos().unwrap();
227+
let r_geos: Geometry = r_ewkb.to_geos().unwrap();
228+
let l_srid = l_geos.srid();
229+
let r_srid = r_geos.srid();
230+
if l_srid != r_srid {
231+
builder.push_null();
232+
ctx.set_error(
233+
builder.len(),
234+
ErrorCode::GeometryError("Srid does not match!").to_string(),
235+
);
236+
} else {
237+
let l_geo: geo::Geometry = l_geos.to_geo().unwrap();
238+
let r_geo: geo::Geometry = r_geos.to_geo().unwrap();
239+
if matches!(l_geo, geo::Geometry::GeometryCollection(_))
240+
|| matches!(r_geo, geo::Geometry::GeometryCollection(_))
241+
{
242+
builder.push_null();
243+
ctx.set_error(
244+
builder.len(),
245+
ErrorCode::GeometryError(
246+
"A GEOMETRY object that is a GeometryCollection",
247+
)
248+
.to_string(),
249+
);
250+
} else {
251+
builder.push(l_geo.contains(&r_geo));
252+
}
253+
}
254+
},
255+
),
256+
);
257+
217258
registry.register_combine_nullable_2_arg::<GeometryType, GeometryType, NumberType<F64>, _, _>(
218259
"st_distance",
219260
|_, _, _| FunctionDomain::MayThrow,

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

+24
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn test_geometry() {
3131
test_st_aswkb(file);
3232
test_st_asewkt(file);
3333
test_st_aswkt(file);
34+
test_st_contains(file);
3435
test_st_endpoint(file);
3536
test_st_dimension(file);
3637
test_st_distance(file);
@@ -180,6 +181,29 @@ fn test_st_asgeojson(file: &mut impl Write) {
180181
);
181182
}
182183

184+
fn test_st_contains(file: &mut impl Write) {
185+
run_ast(
186+
file,
187+
"ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'))",
188+
&[],
189+
);
190+
run_ast(
191+
file,
192+
"ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))'))",
193+
&[],
194+
);
195+
run_ast(
196+
file,
197+
"ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1))'))",
198+
&[],
199+
);
200+
run_ast(
201+
file,
202+
"ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-2 0, 0 0, 0 1))'))",
203+
&[],
204+
);
205+
}
206+
183207
fn test_st_endpoint(file: &mut impl Write) {
184208
run_ast(
185209
file,

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

+2
Original file line numberDiff line numberDiff line change
@@ -3552,6 +3552,8 @@ Functions overloads:
35523552
1 st_aswkb(Geometry NULL) :: Binary NULL
35533553
0 st_aswkt(Geometry) :: String
35543554
1 st_aswkt(Geometry NULL) :: String NULL
3555+
0 st_contains(Geometry, Geometry) :: Boolean NULL
3556+
1 st_contains(Geometry NULL, Geometry NULL) :: Boolean NULL
35553557
0 st_dimension(Geometry) :: Int32 NULL
35563558
1 st_dimension(Geometry NULL) :: Int32 NULL
35573559
0 st_distance(Geometry, Geometry) :: Float64 NULL

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

+36
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,42 @@ output domain : {"LINESTRING(0.75 0.75,-10 20)"..="LINESTRING(0.75 0.75,-10 20)
7979
output : 'LINESTRING(0.75 0.75,-10 20)'
8080

8181

82+
ast : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'))
83+
raw expr : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'))
84+
checked expr : st_contains<Geometry, Geometry>(to_geometry<String>("POLYGON((-2 0, 0 2, 2 0, -2 0))"), to_geometry<String>("POLYGON((-2 0, 0 2, 2 0, -2 0))"))
85+
optimized expr : true
86+
output type : Boolean NULL
87+
output domain : {TRUE}
88+
output : true
89+
90+
91+
ast : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))'))
92+
raw expr : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))'))
93+
checked expr : st_contains<Geometry, Geometry>(to_geometry<String>("POLYGON((-2 0, 0 2, 2 0, -2 0))"), to_geometry<String>("POLYGON((-1 0, 0 1, 1 0, -1 0))"))
94+
optimized expr : true
95+
output type : Boolean NULL
96+
output domain : {TRUE}
97+
output : true
98+
99+
100+
ast : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1))'))
101+
raw expr : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1))'))
102+
checked expr : st_contains<Geometry, Geometry>(to_geometry<String>("POLYGON((-2 0, 0 2, 2 0, -2 0))"), to_geometry<String>("LINESTRING(-1 1, 0 2, 1 1))"))
103+
optimized expr : false
104+
output type : Boolean NULL
105+
output domain : {FALSE}
106+
output : false
107+
108+
109+
ast : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-2 0, 0 0, 0 1))'))
110+
raw expr : ST_CONTAINS(TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))'), TO_GEOMETRY('LINESTRING(-2 0, 0 0, 0 1))'))
111+
checked expr : st_contains<Geometry, Geometry>(to_geometry<String>("POLYGON((-2 0, 0 2, 2 0, -2 0))"), to_geometry<String>("LINESTRING(-2 0, 0 0, 0 1))"))
112+
optimized expr : true
113+
output type : Boolean NULL
114+
output domain : {TRUE}
115+
output : true
116+
117+
82118
ast : st_endpoint(to_geometry('LINESTRING(1 1, 2 2, 3 3, 4 4)'))
83119
raw expr : st_endpoint(to_geometry('LINESTRING(1 1, 2 2, 3 3, 4 4)'))
84120
checked expr : st_endpoint<Geometry>(to_geometry<String>("LINESTRING(1 1, 2 2, 3 3, 4 4)"))

tests/cloud_control_server/simple_server.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ def load_data_from_json():
4444
notification_history_data = json.load(f)
4545
notification_history = notification_pb2.NotificationHistory()
4646
json_format.ParseDict(notification_history_data, notification_history)
47-
NOTIFICATION_HISTORY_DB[notification_history.name] = (
48-
notification_history
49-
)
47+
NOTIFICATION_HISTORY_DB[
48+
notification_history.name
49+
] = notification_history
5050

5151

5252
def create_task_request_to_task(id, create_task_request):

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

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
statement ok
22
DROP TABLE IF EXISTS t1
33

4+
query T
5+
SELECT ST_CONTAINS(poly, poly_inside),
6+
ST_CONTAINS(poly, poly),
7+
ST_CONTAINS(poly, line_on_boundary),
8+
ST_CONTAINS(poly, line_inside)
9+
FROM (SELECT
10+
TO_GEOMETRY('POLYGON((-2 0, 0 2, 2 0, -2 0))') AS poly,
11+
TO_GEOMETRY('POLYGON((-1 0, 0 1, 1 0, -1 0))') AS poly_inside,
12+
TO_GEOMETRY('LINESTRING(-1 1, 0 2, 1 1)') AS line_on_boundary,
13+
TO_GEOMETRY('LINESTRING(-2 0, 0 0, 0 1)') AS line_inside);
14+
----
15+
1 1 0 1
16+
417
query T
518
SELECT haversine(40.7127, -74.0059, 34.0500, -118.2500);
619
----

tests/udf/udf_server.py

+46-46
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def json_concat(list: List[Any]) -> Any:
162162
result_type="TUPLE(VARIANT NULL, VARIANT NULL)",
163163
)
164164
def tuple_access(
165-
tup: Tuple[List[Any], int, str], idx1: int, idx2: int
165+
tup: Tuple[List[Any], int, str], idx1: int, idx2: int
166166
) -> Tuple[Any, Any]:
167167
v1 = None if idx1 == 0 or idx1 > len(tup) else tup[idx1 - 1]
168168
v2 = None if idx2 == 0 or idx2 > len(tup) else tup[idx2 - 1]
@@ -193,21 +193,21 @@ def tuple_access(
193193
result_type=f"TUPLE({','.join(f'{t} NULL' for t in ALL_SCALAR_TYPES)})",
194194
)
195195
def return_all(
196-
bool,
197-
i8,
198-
i16,
199-
i32,
200-
i64,
201-
u8,
202-
u16,
203-
u32,
204-
u64,
205-
f32,
206-
f64,
207-
date,
208-
timestamp,
209-
varchar,
210-
json,
196+
bool,
197+
i8,
198+
i16,
199+
i32,
200+
i64,
201+
u8,
202+
u16,
203+
u32,
204+
u64,
205+
f32,
206+
f64,
207+
date,
208+
timestamp,
209+
varchar,
210+
json,
211211
):
212212
return (
213213
bool,
@@ -233,21 +233,21 @@ def return_all(
233233
result_type=f"TUPLE({','.join(f'ARRAY({t})' for t in ALL_SCALAR_TYPES)})",
234234
)
235235
def return_all_arrays(
236-
bool,
237-
i8,
238-
i16,
239-
i32,
240-
i64,
241-
u8,
242-
u16,
243-
u32,
244-
u64,
245-
f32,
246-
f64,
247-
date,
248-
timestamp,
249-
varchar,
250-
json,
236+
bool,
237+
i8,
238+
i16,
239+
i32,
240+
i64,
241+
u8,
242+
u16,
243+
u32,
244+
u64,
245+
f32,
246+
f64,
247+
date,
248+
timestamp,
249+
varchar,
250+
json,
251251
):
252252
return (
253253
bool,
@@ -273,21 +273,21 @@ def return_all_arrays(
273273
result_type=f"TUPLE({','.join(f'{t}' for t in ALL_SCALAR_TYPES)})",
274274
)
275275
def return_all_non_nullable(
276-
bool,
277-
i8,
278-
i16,
279-
i32,
280-
i64,
281-
u8,
282-
u16,
283-
u32,
284-
u64,
285-
f32,
286-
f64,
287-
date,
288-
timestamp,
289-
varchar,
290-
json,
276+
bool,
277+
i8,
278+
i16,
279+
i32,
280+
i64,
281+
u8,
282+
u16,
283+
u32,
284+
u64,
285+
f32,
286+
f64,
287+
date,
288+
timestamp,
289+
varchar,
290+
json,
291291
):
292292
return (
293293
bool,

0 commit comments

Comments
 (0)