Skip to content

Commit dcbae32

Browse files
authored
feat(query): implement ST_XMAX (#15406)
ST_XMAX Signed-off-by: Fan Yang <yangfanlinux@gmail.com>
1 parent 49ee26a commit dcbae32

File tree

5 files changed

+195
-0
lines changed

5 files changed

+195
-0
lines changed

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

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use databend_common_io::parse_to_subtype;
3333
use databend_common_io::read_ewkb_srid;
3434
use databend_common_io::GeometryDataType;
3535
use geo::dimensions::Dimensions;
36+
use geo::BoundingRect;
3637
use geo::HasDimensions;
3738
use geo::MultiPoint;
3839
use geo::Point;
@@ -1009,6 +1010,38 @@ pub fn register(registry: &mut FunctionRegistry) {
10091010
),
10101011
);
10111012

1013+
registry.register_combine_nullable_1_arg::<GeometryType, NumberType<F64>, _, _>(
1014+
"st_xmax",
1015+
|_, _| FunctionDomain::MayThrow,
1016+
vectorize_with_builder_1_arg::<GeometryType, NullableType<NumberType<F64>>>(
1017+
|geometry, builder, ctx| {
1018+
if let Some(validity) = &ctx.validity {
1019+
if !validity.get_bit(builder.len()) {
1020+
builder.push_null();
1021+
return;
1022+
}
1023+
}
1024+
1025+
let geo: geo_types::Geometry = match Ewkb(geometry).to_geo() {
1026+
Ok(geo) => geo,
1027+
Err(e) => {
1028+
ctx.set_error(
1029+
builder.len(),
1030+
ErrorCode::GeometryError(e.to_string()).to_string(),
1031+
);
1032+
builder.push_null();
1033+
return;
1034+
}
1035+
};
1036+
1037+
match st_xmax(&geo) {
1038+
None => builder.push_null(),
1039+
Some(x_max) => builder.push(F64::from(AsPrimitive::<f64>::as_(x_max))),
1040+
};
1041+
},
1042+
),
1043+
);
1044+
10121045
registry.register_passthrough_nullable_1_arg::<GeometryType, StringType, _, _>(
10131046
"to_string",
10141047
|_, _| FunctionDomain::MayThrow,
@@ -1575,3 +1608,68 @@ fn point_to_geohash(
15751608
Err(e) => Err(ErrorCode::GeometryError(e.to_string())),
15761609
}
15771610
}
1611+
1612+
fn st_xmax(geometry: &geo_types::Geometry<f64>) -> Option<f64> {
1613+
match geometry {
1614+
geo_types::Geometry::Point(point) => Some(point.x()),
1615+
geo_types::Geometry::MultiPoint(multi_point) => {
1616+
let mut xmax: Option<f64> = None;
1617+
for point in multi_point {
1618+
if let Some(x) = st_xmax(&geo_types::Geometry::Point(*point)) {
1619+
if let Some(existing_xmax) = xmax {
1620+
xmax = Some(existing_xmax.max(x));
1621+
} else {
1622+
xmax = Some(x);
1623+
}
1624+
}
1625+
}
1626+
xmax
1627+
}
1628+
geo_types::Geometry::Line(line) => Some(line.bounding_rect().max().x),
1629+
geo_types::Geometry::MultiLineString(multi_line) => {
1630+
let mut xmax: Option<f64> = None;
1631+
for line in multi_line {
1632+
if let Some(x) = st_xmax(&geo_types::Geometry::LineString(line.clone())) {
1633+
if let Some(existing_xmax) = xmax {
1634+
xmax = Some(existing_xmax.max(x));
1635+
} else {
1636+
xmax = Some(x);
1637+
}
1638+
}
1639+
}
1640+
xmax
1641+
}
1642+
geo_types::Geometry::Polygon(polygon) => Some(polygon.bounding_rect().unwrap().max().x),
1643+
geo_types::Geometry::MultiPolygon(multi_polygon) => {
1644+
let mut xmax: Option<f64> = None;
1645+
for polygon in multi_polygon {
1646+
if let Some(x) = st_xmax(&geo_types::Geometry::Polygon(polygon.clone())) {
1647+
if let Some(existing_xmax) = xmax {
1648+
xmax = Some(existing_xmax.max(x));
1649+
} else {
1650+
xmax = Some(x);
1651+
}
1652+
}
1653+
}
1654+
xmax
1655+
}
1656+
geo_types::Geometry::GeometryCollection(geometry_collection) => {
1657+
let mut xmax: Option<f64> = None;
1658+
for geometry in geometry_collection {
1659+
if let Some(x) = st_xmax(geometry) {
1660+
if let Some(existing_xmax) = xmax {
1661+
xmax = Some(existing_xmax.max(x));
1662+
} else {
1663+
xmax = Some(x);
1664+
}
1665+
}
1666+
}
1667+
xmax
1668+
}
1669+
geo_types::Geometry::LineString(line_string) => {
1670+
line_string.bounding_rect().map(|rect| rect.max().x)
1671+
}
1672+
geo_types::Geometry::Rect(rect) => Some(rect.max().x),
1673+
geo_types::Geometry::Triangle(triangle) => Some(triangle.bounding_rect().max().x),
1674+
}
1675+
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn test_geometry() {
4949
test_try_to_geometry(file);
5050
test_st_geometryfromwkb(file);
5151
test_st_geometryfromwkt(file);
52+
test_st_xmax(file);
5253
// test_st_transform(file);
5354
}
5455

@@ -455,6 +456,30 @@ fn test_st_geometryfromwkt(file: &mut impl Write) {
455456
]);
456457
}
457458

459+
fn test_st_xmax(file: &mut impl Write) {
460+
run_ast(file, "st_xmax(to_geometry('POINT(-180 0)'))", &[]);
461+
run_ast(
462+
file,
463+
"st_xmax(to_geometry('LINESTRING(-179 0, 179 0)'))",
464+
&[],
465+
);
466+
run_ast(
467+
file,
468+
"st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))'))",
469+
&[],
470+
);
471+
run_ast(
472+
file,
473+
"st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)'))",
474+
&[],
475+
);
476+
run_ast(
477+
file,
478+
"st_xmax(to_geometry('MULTILINESTRING ((10 10, 20 20, 10 40), EMPTY)'))",
479+
&[],
480+
);
481+
}
482+
458483
// fn test_st_transform(file: &mut impl Write) {
459484
// // just to_srid
460485
// run_ast(

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,6 +3554,8 @@ Functions overloads:
35543554
1 st_startpoint(Geometry NULL) :: Geometry NULL
35553555
0 st_x(Geometry) :: Float64 NULL
35563556
1 st_x(Geometry NULL) :: Float64 NULL
3557+
0 st_xmax(Geometry) :: Float64 NULL
3558+
1 st_xmax(Geometry NULL) :: Float64 NULL
35573559
0 st_y(Geometry) :: Float64 NULL
35583560
1 st_y(Geometry NULL) :: Float64 NULL
35593561
0 strcmp(String, String) :: Int8

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,3 +856,48 @@ evaluation (internal):
856856
+--------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
857857

858858

859+
ast : st_xmax(to_geometry('POINT(-180 0)'))
860+
raw expr : st_xmax(to_geometry('POINT(-180 0)'))
861+
checked expr : st_xmax<Geometry>(to_geometry<String>("POINT(-180 0)"))
862+
optimized expr : -180_f64
863+
output type : Float64 NULL
864+
output domain : {-180..=-180}
865+
output : -180
866+
867+
868+
ast : st_xmax(to_geometry('LINESTRING(-179 0, 179 0)'))
869+
raw expr : st_xmax(to_geometry('LINESTRING(-179 0, 179 0)'))
870+
checked expr : st_xmax<Geometry>(to_geometry<String>("LINESTRING(-179 0, 179 0)"))
871+
optimized expr : 179_f64
872+
output type : Float64 NULL
873+
output domain : {179..=179}
874+
output : 179
875+
876+
877+
ast : st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))'))
878+
raw expr : st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))'))
879+
checked expr : st_xmax<Geometry>(to_geometry<String>("GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))"))
880+
optimized expr : 45_f64
881+
output type : Float64 NULL
882+
output domain : {45..=45}
883+
output : 45
884+
885+
886+
ast : st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)'))
887+
raw expr : st_xmax(to_geometry('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)'))
888+
checked expr : st_xmax<Geometry>(to_geometry<String>("GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)"))
889+
optimized expr : 40_f64
890+
output type : Float64 NULL
891+
output domain : {40..=40}
892+
output : 40
893+
894+
895+
ast : st_xmax(to_geometry('MULTILINESTRING ((10 10, 20 20, 10 40), EMPTY)'))
896+
raw expr : st_xmax(to_geometry('MULTILINESTRING ((10 10, 20 20, 10 40), EMPTY)'))
897+
checked expr : st_xmax<Geometry>(to_geometry<String>("MULTILINESTRING ((10 10, 20 20, 10 40), EMPTY)"))
898+
optimized expr : 20_f64
899+
output type : Float64 NULL
900+
output domain : {20..=20}
901+
output : 20
902+
903+

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,31 @@ SELECT ST_X(ST_MAKEGEOMPOINT(NULL, NULL)), ST_Y(ST_MAKEGEOMPOINT(NULL, NULL)),ST
458458
----
459459
NULL NULL NULL NULL
460460

461+
query T
462+
SELECT ST_XMAX(TO_GEOMETRY('POINT(-180 0)'))
463+
----
464+
-180.0
465+
466+
query T
467+
SELECT ST_XMAX(TO_GEOMETRY('LINESTRING(-179 0, 179 0)'))
468+
----
469+
179.0
470+
471+
query T
472+
SELECT ST_XMAX(TO_GEOMETRY('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POLYGON((40 40,20 45,45 30,40 40)))'))
473+
----
474+
45.0
475+
476+
query T
477+
SELECT ST_XMAX(TO_GEOMETRY('GEOMETRYCOLLECTION(POINT(40 10),LINESTRING(10 10,20 20,10 40),POINT EMPTY)'))
478+
----
479+
40.0
480+
481+
query T
482+
SELECT ST_XMAX(TO_GEOMETRY('MULTILINESTRING ((10 10, 20 20, 10 40), EMPTY)'))
483+
----
484+
20.0
485+
461486
statement ok
462487
SET enable_geo_create_table=0
463488

0 commit comments

Comments
 (0)