From ff866506ae80df7ad7b6439d53d60308dc1130c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20BIDON?=
st_makebox2d(geometry_a: geometry, geometry_b: geometry) → box2d
Creates a box2d from two points. Errors if arguments are not two non-empty points.
st_makeenvelope(xmin: float, ymin: float, xmax: float, ymax: float) → geometry
Creates a rectangular Polygon from the minimum and maximum values for X and Y with SRID 0.
+st_makeenvelope(xmin: float, ymin: float, xmax: float, ymax: float, srid: int) → geometry
Creates a rectangular Polygon from the minimum and maximum values for X and Y with the given SRID.
+st_makepoint(x: float, y: float) → geometry
Returns a new Point with the given X and Y coordinates.
st_makepoint(x: float, y: float, z: float) → geometry
Returns a new Point with the given X, Y, and Z coordinates.
diff --git a/pkg/sql/logictest/testdata/logic_test/geospatial b/pkg/sql/logictest/testdata/logic_test/geospatial index 2c9733d9114f..d431cde88ea4 100644 --- a/pkg/sql/logictest/testdata/logic_test/geospatial +++ b/pkg/sql/logictest/testdata/logic_test/geospatial @@ -5892,3 +5892,14 @@ FROM ( VALUES ---- false false false false false false + +# ST_MakeEnvelope +query T +SELECT ST_AsEWKT(ST_MakeEnvelope(30.01,50.01,72.01,52.01,4326)) +---- +SRID=4326;POLYGON ((30.010000000000002 50.009999999999998, 30.010000000000002 52.009999999999998, 72.010000000000005 52.009999999999998, 72.010000000000005 50.009999999999998, 30.010000000000002 50.009999999999998)) + +query T +SELECT ST_AsEWKT(ST_MakeEnvelope(30.01,50.01,72.01,52.01)) +---- +POLYGON ((30.010000000000002 50.009999999999998, 30.010000000000002 52.009999999999998, 72.010000000000005 52.009999999999998, 72.010000000000005 50.009999999999998, 30.010000000000002 50.009999999999998)) diff --git a/pkg/sql/sem/builtins/geo_builtins.go b/pkg/sql/sem/builtins/geo_builtins.go index d1053efee2fc..e778d6516ee9 100644 --- a/pkg/sql/sem/builtins/geo_builtins.go +++ b/pkg/sql/sem/builtins/geo_builtins.go @@ -5302,7 +5302,7 @@ The calculations are done on a sphere.`, }, Info: infoBuilder{ info: `Snaps the vertices and segments of input geometry the target geometry's vertices. -Tolerance is used to control where snapping is performed. The result geometry is the input geometry with the vertices snapped. +Tolerance is used to control where snapping is performed. The result geometry is the input geometry with the vertices snapped. If no snapping occurs then the input geometry is returned unchanged.`, }.String(), Volatility: volatility.Immutable, @@ -5558,6 +5558,42 @@ Bottom Left.`, Volatility: volatility.Immutable, }, ), + "st_makeenvelope": makeBuiltin( + defProps(), + tree.Overload{ + Types: tree.ArgTypes{ + {"xmin", types.Float}, + {"ymin", types.Float}, + {"xmax", types.Float}, + {"ymax", types.Float}, + {"srid", types.Int}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(_ *eval.Context, args tree.Datums) (tree.Datum, error) { + return stEnvelopeFromArgs(args) + }, + Info: infoBuilder{ + info: "Creates a rectangular Polygon from the minimum and maximum values for X and Y with the given SRID.", + }.String(), + Volatility: volatility.Immutable, + }, + tree.Overload{ + Types: tree.ArgTypes{ + {"xmin", types.Float}, + {"ymin", types.Float}, + {"xmax", types.Float}, + {"ymax", types.Float}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(_ *eval.Context, args tree.Datums) (tree.Datum, error) { + return stEnvelopeFromArgs(args) + }, + Info: infoBuilder{ + info: "Creates a rectangular Polygon from the minimum and maximum values for X and Y with SRID 0.", + }.String(), + Volatility: volatility.Immutable, + }, + ), "st_flipcoordinates": makeBuiltin( defProps(), tree.Overload{ @@ -6768,7 +6804,7 @@ May return a Point or LineString in the case of degenerate inputs.`, return tree.NewDInt(tree.DInt(ret)), nil }, Info: infoBuilder{ - info: `Returns an interger value defining behavior of crossing of lines: + info: `Returns an interger value defining behavior of crossing of lines: 0: lines do not cross, -1: linestring_b crosses linestring_a from right to left, 1: linestring_b crosses linestring_a from left to right, @@ -7502,3 +7538,28 @@ func applyGeoindexConfigStorageParams( } return indexDesc.GeoConfig, nil } + +// stEnvelopeFromArgs builds a rectangle geometry from types.Float bounds as datums +func stEnvelopeFromArgs(args tree.Datums) (tree.Datum, error) { + xmin := float64(tree.MustBeDFloat(args[0])) + ymin := float64(tree.MustBeDFloat(args[1])) + xmax := float64(tree.MustBeDFloat(args[2])) + ymax := float64(tree.MustBeDFloat(args[3])) + + var srid int + if len(args) > 4 { + srid = int(tree.MustBeDInt(args[4])) + } + + extent, err := geo.MakeGeometryFromGeomT( + geom.NewBounds(geom.XY). + Set(xmin, ymin, xmax, ymax). + Polygon(). + SetSRID(srid), + ) + if err != nil { + return nil, err + } + + return tree.NewDGeometry(extent), nil +}