Skip to content

Commit 87ff737

Browse files
feat(rust/sedona-functions): Add ST_Translate() (#267)
Co-authored-by: Peter Nguyen <petern0408@gmail.com>
1 parent 2138d34 commit 87ff737

File tree

6 files changed

+348
-13
lines changed

6 files changed

+348
-13
lines changed

benchmarks/test_transform.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
import pytest
18+
from test_bench_base import TestBenchBase
19+
from sedonadb.testing import (
20+
DuckDBSingleThread,
21+
SedonaDBSingleThread,
22+
)
23+
24+
25+
class TestBenchTransform(TestBenchBase):
26+
@pytest.mark.parametrize("eng", [SedonaDBSingleThread, DuckDBSingleThread])
27+
@pytest.mark.parametrize(
28+
"table",
29+
[
30+
"points_simple",
31+
"collections_complex",
32+
],
33+
)
34+
def test_st_translate(self, benchmark, eng, table):
35+
eng = self._get_eng(eng)
36+
37+
def queries():
38+
eng.execute_and_collect(
39+
f"SELECT ST_Translate(geom1, 1.0, 2.0) from {table}"
40+
)
41+
42+
benchmark(queries)

python/sedonadb/tests/functions/test_transforms.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
import pytest
1817
import pyproj
19-
from sedonadb.testing import geom_or_null, PostGIS, SedonaDB, val_or_null
18+
import pytest
19+
from sedonadb.testing import PostGIS, SedonaDB, geom_or_null, val_or_null
2020

2121

2222
@pytest.mark.parametrize("eng", [SedonaDB, PostGIS])
@@ -93,3 +93,56 @@ def test_st_crs_sedonadb(eng):
9393
"SELECT ST_CRS(ST_SetCrs(ST_GeomFromText('POINT (1 1)'), NULL))",
9494
None,
9595
)
96+
97+
98+
@pytest.mark.parametrize("eng", [SedonaDB, PostGIS])
99+
@pytest.mark.parametrize(
100+
("geom", "dx", "dy", "expected"),
101+
[
102+
# Nulls
103+
(None, None, None, None),
104+
(None, 1.0, 2.0, None),
105+
("POINT (0 1)", None, 2.0, None),
106+
("POINT (0 1)", 1.0, None, None),
107+
("POINT (0 1)", 1.0, 2.0, "POINT (1 3)"), # Positives
108+
("POINT (0 1)", -1.0, -2.0, "POINT (-1 -1)"), # Negatives
109+
("POINT (0 1)", 0.0, 0.0, "POINT (0 1)"), # Zeroes
110+
("POINT (0 1)", 1, 2, "POINT (1 3)"), # Integers
111+
("POINT Z (0 1 2)", 1.0, 2.0, "POINT Z (1 3 2)"), # Z
112+
("POINT M (0 1 2)", 1.0, 2.0, "POINT M (1 3 2)"), # M
113+
("POINT ZM (0 1 2 3)", 1.0, 2.0, "POINT ZM (1 3 2 3)"), # ZM
114+
# Not points
115+
("LINESTRING (0 1, 2 3)", 1.0, 2.0, "LINESTRING (1 3, 3 5)"),
116+
("POLYGON ((0 0, 1 0, 0 1, 0 0))", 1.0, 2.0, "POLYGON ((1 2, 2 2, 1 3, 1 2))"),
117+
("MULTIPOINT (0 1, 2 3)", 1.0, 2.0, "MULTIPOINT (1 3, 3 5)"),
118+
("MULTILINESTRING ((0 1, 2 3))", 1.0, 2.0, "MULTILINESTRING ((1 3, 3 5))"),
119+
(
120+
"MULTIPOLYGON (((0 0, 1 0, 0 1, 0 0)))",
121+
1.0,
122+
2.0,
123+
"MULTIPOLYGON (((1 2, 2 2, 1 3, 1 2)))",
124+
),
125+
(
126+
"GEOMETRYCOLLECTION (POINT (0 1))",
127+
1.0,
128+
2.0,
129+
"GEOMETRYCOLLECTION (POINT (1 3))",
130+
),
131+
# WKT output of geoarrow-c is causing this (both correctly output
132+
# empties)
133+
("POINT EMPTY", 1.0, 2.0, "POINT (nan nan)"),
134+
("POINT Z EMPTY", 1.0, 2.0, "POINT Z (nan nan nan)"),
135+
("LINESTRING EMPTY", 1.0, 2.0, "LINESTRING EMPTY"),
136+
("POLYGON EMPTY", 1.0, 2.0, "POLYGON EMPTY"),
137+
("MULTIPOINT EMPTY", 1.0, 2.0, "MULTIPOINT EMPTY"),
138+
("MULTILINESTRING EMPTY", 1.0, 2.0, "MULTILINESTRING EMPTY"),
139+
("MULTIPOLYGON EMPTY", 1.0, 2.0, "MULTIPOLYGON EMPTY"),
140+
("GEOMETRYCOLLECTION EMPTY", 1.0, 2.0, "GEOMETRYCOLLECTION EMPTY"),
141+
],
142+
)
143+
def test_st_translate(eng, geom, dx, dy, expected):
144+
eng = eng.create_or_skip()
145+
eng.assert_query_result(
146+
f"SELECT ST_Translate({geom_or_null(geom)}, {val_or_null(dx)}, {val_or_null(dy)})",
147+
expected,
148+
)

rust/sedona-functions/benches/native-functions.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ fn criterion_benchmark(c: &mut Criterion) {
3636
benchmark::scalar(c, &f, "native", "st_flipcoordinates", Point);
3737
benchmark::scalar(c, &f, "native", "st_flipcoordinates", LineString(10));
3838

39+
benchmark::scalar(
40+
c,
41+
&f,
42+
"native",
43+
"st_translate",
44+
BenchmarkArgs::ArrayScalarScalar(Point, Float64(0.0, 1.0), Float64(2.0, 3.0)),
45+
);
46+
benchmark::scalar(
47+
c,
48+
&f,
49+
"native",
50+
"st_translate",
51+
BenchmarkArgs::ArrayScalarScalar(LineString(10), Float64(0.0, 1.0), Float64(2.0, 3.0)),
52+
);
53+
3954
benchmark::scalar(c, &f, "native", "st_geometrytype", Point);
4055
benchmark::scalar(c, &f, "native", "st_geometrytype", LineString(10));
4156

rust/sedona-functions/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ mod st_setsrid;
5454
mod st_srid;
5555
mod st_start_point;
5656
mod st_transform;
57+
mod st_translate;
5758
pub mod st_union_aggr;
5859
mod st_xyzm;
5960
mod st_xyzm_minmax;

rust/sedona-functions/src/register.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,30 +87,31 @@ pub fn default_function_set() -> FunctionSet {
8787
crate::st_point::st_geogpoint_udf,
8888
crate::st_point::st_point_udf,
8989
crate::st_pointn::st_pointn_udf,
90-
crate::st_points::st_points_udf,
9190
crate::st_points::st_npoints_udf,
92-
crate::st_pointzm::st_pointz_udf,
91+
crate::st_points::st_points_udf,
9392
crate::st_pointzm::st_pointm_udf,
93+
crate::st_pointzm::st_pointz_udf,
9494
crate::st_pointzm::st_pointzm_udf,
95-
crate::st_transform::st_transform_udf,
9695
crate::st_setsrid::st_set_crs_udf,
9796
crate::st_setsrid::st_set_srid_udf,
9897
crate::st_srid::st_crs_udf,
9998
crate::st_srid::st_srid_udf,
10099
crate::st_start_point::st_end_point_udf,
101100
crate::st_start_point::st_start_point_udf,
101+
crate::st_transform::st_transform_udf,
102+
crate::st_translate::st_translate_udf,
103+
crate::st_xyzm_minmax::st_mmax_udf,
104+
crate::st_xyzm_minmax::st_mmin_udf,
105+
crate::st_xyzm_minmax::st_xmax_udf,
106+
crate::st_xyzm_minmax::st_xmin_udf,
107+
crate::st_xyzm_minmax::st_ymax_udf,
108+
crate::st_xyzm_minmax::st_ymin_udf,
109+
crate::st_xyzm_minmax::st_zmax_udf,
110+
crate::st_xyzm_minmax::st_zmin_udf,
102111
crate::st_xyzm::st_m_udf,
103112
crate::st_xyzm::st_x_udf,
104113
crate::st_xyzm::st_y_udf,
105114
crate::st_xyzm::st_z_udf,
106-
crate::st_xyzm_minmax::st_xmin_udf,
107-
crate::st_xyzm_minmax::st_ymin_udf,
108-
crate::st_xyzm_minmax::st_xmax_udf,
109-
crate::st_xyzm_minmax::st_ymax_udf,
110-
crate::st_xyzm_minmax::st_zmin_udf,
111-
crate::st_xyzm_minmax::st_zmax_udf,
112-
crate::st_xyzm_minmax::st_mmin_udf,
113-
crate::st_xyzm_minmax::st_mmax_udf,
114115
crate::st_zmflag::st_zmflag_udf,
115116
);
116117

0 commit comments

Comments
 (0)