Skip to content

Commit cf29a21

Browse files
authored
Merge pull request #655 from bradh/makepoint_2025-08-07
Add ST_MakePoint alias for ST_Point
2 parents aa54108 + d06ffbb commit cf29a21

File tree

5 files changed

+193
-0
lines changed

5 files changed

+193
-0
lines changed

src/spatial/modules/main/spatial_functions.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct CoreVectorOperations {
1717
public:
1818
static void Point2DToVarchar(Vector &source, Vector &result, idx_t count);
1919
static void Point3DToVarchar(Vector &source, Vector &result, idx_t count);
20+
static void Point4DToVarchar(Vector &source, Vector &result, idx_t count);
2021
static void LineString2DToVarchar(Vector &source, Vector &result, idx_t count);
2122
static void LineString3DToVarchar(Vector &source, Vector &result, idx_t count);
2223
static void Polygon2DToVarchar(Vector &source, Vector &result, idx_t count);

src/spatial/modules/main/spatial_functions_cast.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,61 @@ struct PointCasts {
329329
return true;
330330
}
331331

332+
//------------------------------------------------------------------------------------------------------------------
333+
// POINT_4D -> VARCHAR
334+
//------------------------------------------------------------------------------------------------------------------
335+
static bool ToVarcharCast4D(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
336+
CoreVectorOperations::Point4DToVarchar(source, result, count);
337+
return true;
338+
}
339+
340+
//------------------------------------------------------------------------------------------------------------------
341+
// POINT_4D -> GEOMETRY
342+
//------------------------------------------------------------------------------------------------------------------
343+
static bool ToGeometryCast4D(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
344+
using POINT_TYPE = StructTypeQuaternary<double, double, double, double>;
345+
using GEOMETRY_TYPE = PrimitiveType<string_t>;
346+
347+
auto &lstate = LocalState::ResetAndGet(parameters);
348+
349+
GenericExecutor::ExecuteUnary<POINT_TYPE, GEOMETRY_TYPE>(source, result, count, [&](const POINT_TYPE &point) {
350+
const double buffer[4] = {point.a_val, point.b_val, point.c_val, point.d_val};
351+
sgl::geometry geom(sgl::geometry_type::POINT, true, true);
352+
geom.set_vertex_array(buffer, 1);
353+
354+
return lstate.Serialize(result, geom);
355+
});
356+
return true;
357+
}
358+
359+
//------------------------------------------------------------------------------------------------------------------
360+
// GEOMETRY -> POINT_4D
361+
//------------------------------------------------------------------------------------------------------------------
362+
static bool FromGeometryCast4D(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
363+
using POINT_TYPE = StructTypeQuaternary<double, double, double, double>;
364+
using GEOMETRY_TYPE = PrimitiveType<string_t>;
365+
366+
auto &lstate = LocalState::ResetAndGet(parameters);
367+
368+
GenericExecutor::ExecuteUnary<GEOMETRY_TYPE, POINT_TYPE>(source, result, count, [&](const GEOMETRY_TYPE &blob) {
369+
sgl::geometry geom;
370+
lstate.Deserialize(blob.val, geom);
371+
372+
if (geom.get_type() != sgl::geometry_type::POINT) {
373+
throw ConversionException("Cannot cast non-point GEOMETRY to POINT_4D");
374+
}
375+
if (geom.is_empty()) {
376+
// TODO: Maybe make this return NULL instead
377+
throw ConversionException("Cannot cast empty point GEOMETRY to POINT_4D");
378+
}
379+
const auto vertex = geom.get_vertex_xyzm(0);
380+
return POINT_TYPE {vertex.x, vertex.y, vertex.z, vertex.m};
381+
});
382+
383+
return true;
384+
}
385+
386+
332387
//------------------------------------------------------------------------------------------------------------------
333388
// Register
334389
//------------------------------------------------------------------------------------------------------------------
@@ -351,8 +406,17 @@ struct PointCasts {
351406
BoundCastInfo(FromGeometryCast3D, nullptr, LocalState::InitCast), 1);
352407
// POINT_3D -> POINT_2D
353408
loader.RegisterCastFunction(GeoTypes::POINT_3D(), GeoTypes::POINT_2D(), ToPoint2DCast, 1);
409+
410+
// POINT_4D -> VARCHAR
411+
loader.RegisterCastFunction(GeoTypes::POINT_4D(), LogicalType::VARCHAR, BoundCastInfo(ToVarcharCast4D), 1);
354412
// POINT_4D -> POINT_2D
355413
loader.RegisterCastFunction(GeoTypes::POINT_4D(), GeoTypes::POINT_2D(), ToPoint2DCast, 1);
414+
// POINT_4D -> GEOMETRY
415+
loader.RegisterCastFunction(GeoTypes::POINT_4D(), GeoTypes::GEOMETRY(),
416+
BoundCastInfo(ToGeometryCast4D, nullptr, LocalState::InitCast), 1);
417+
// GEOMETRY -> POINT_4D
418+
loader.RegisterCastFunction(GeoTypes::GEOMETRY(), GeoTypes::POINT_4D(),
419+
BoundCastInfo(FromGeometryCast4D, nullptr, LocalState::InitCast), 1);
356420
}
357421
};
358422

@@ -947,6 +1011,27 @@ void CoreVectorOperations::Point3DToVarchar(Vector &source, Vector &result, idx_
9471011
});
9481012
}
9491013

1014+
//------------------------------------------------------------------------------
1015+
// POINT_4D -> VARCHAR
1016+
//------------------------------------------------------------------------------
1017+
void CoreVectorOperations::Point4DToVarchar(Vector &source, Vector &result, idx_t count) {
1018+
using POINT_TYPE = StructTypeQuaternary<double, double, double, double>;
1019+
using VARCHAR_TYPE = PrimitiveType<string_t>;
1020+
1021+
GenericExecutor::ExecuteUnary<POINT_TYPE, VARCHAR_TYPE>(source, result, count, [&](POINT_TYPE &point) {
1022+
auto x = point.a_val;
1023+
auto y = point.b_val;
1024+
auto z = point.c_val;
1025+
auto m = point.d_val;
1026+
1027+
if (std::isnan(x) || std::isnan(y) || std::isnan(z) || std::isnan(m)) {
1028+
return StringVector::AddString(result, "POINT EMPTY");
1029+
}
1030+
1031+
return StringVector::AddString(result, StringUtil::Format("POINT ZM (%s)", MathUtil::format_coord(x, y, z, m)));
1032+
});
1033+
}
1034+
9501035
//------------------------------------------------------------------------------
9511036
// LINESTRING_2D -> VARCHAR
9521037
//------------------------------------------------------------------------------

src/spatial/modules/main/spatial_functions_scalar.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7732,9 +7732,24 @@ struct ST_Point {
77327732
Creates a GEOMETRY point
77337733
)";
77347734

7735+
static constexpr auto DESCRIPTION_MAKE_POINT = R"(
7736+
Creates a GEOMETRY point from an pair of floating point numbers.
7737+
7738+
For geodetic coordinate systems, x is typically the longitude value and y is the latitude value.
7739+
7740+
Note that ST_Point is equivalent. ST_MakePoint is provided for PostGIS compatibility.
7741+
)";
7742+
77357743
// TODO: example
77367744
static constexpr auto EXAMPLE = "";
77377745

7746+
// TODO: example
7747+
static constexpr auto EXAMPLE_MAKE_POINT = R"(
7748+
SELECT ST_AsText(ST_MakePoint(143.3, -24.2));
7749+
----
7750+
POINT (143.3 -24.2)
7751+
)";
7752+
77387753
//------------------------------------------------------------------------------------------------------------------
77397754
// Register
77407755
//------------------------------------------------------------------------------------------------------------------
@@ -7770,6 +7785,23 @@ struct ST_Point {
77707785
func.SetTag("category", "construction");
77717786
});
77727787

7788+
FunctionBuilder::RegisterScalar(loader, "ST_MakePoint", [](ScalarFunctionBuilder &func) {
7789+
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
7790+
variant.AddParameter("x", LogicalType::DOUBLE);
7791+
variant.AddParameter("y", LogicalType::DOUBLE);
7792+
variant.SetReturnType(GeoTypes::POINT_2D());
7793+
7794+
variant.SetFunction(ExecutePoint2D);
7795+
variant.SetInit(LocalState::Init);
7796+
});
7797+
7798+
func.SetDescription(DESCRIPTION_MAKE_POINT);
7799+
func.SetExample(EXAMPLE_MAKE_POINT);
7800+
7801+
func.SetTag("ext", "spatial");
7802+
func.SetTag("category", "construction");
7803+
});
7804+
77737805
FunctionBuilder::RegisterScalar(loader, "ST_Point3D", [](ScalarFunctionBuilder &func) {
77747806
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
77757807
variant.AddParameter("x", LogicalType::DOUBLE);
@@ -7785,6 +7817,22 @@ struct ST_Point {
77857817
func.SetTag("category", "construction");
77867818
});
77877819

7820+
7821+
FunctionBuilder::RegisterScalar(loader, "ST_MakePoint", [](ScalarFunctionBuilder &func) {
7822+
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
7823+
variant.AddParameter("x", LogicalType::DOUBLE);
7824+
variant.AddParameter("y", LogicalType::DOUBLE);
7825+
variant.AddParameter("z", LogicalType::DOUBLE);
7826+
variant.SetReturnType(GeoTypes::POINT_3D());
7827+
variant.SetFunction(ExecutePoint3D);
7828+
7829+
variant.SetDescription("Creates a POINT_3D.");
7830+
});
7831+
7832+
func.SetTag("ext", "spatial");
7833+
func.SetTag("category", "construction");
7834+
});
7835+
77887836
FunctionBuilder::RegisterScalar(loader, "ST_Point4D", [](ScalarFunctionBuilder &func) {
77897837
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
77907838
variant.AddParameter("x", LogicalType::DOUBLE);
@@ -7800,6 +7848,22 @@ struct ST_Point {
78007848
func.SetTag("ext", "spatial");
78017849
func.SetTag("category", "construction");
78027850
});
7851+
7852+
FunctionBuilder::RegisterScalar(loader, "ST_MakePoint", [](ScalarFunctionBuilder &func) {
7853+
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
7854+
variant.AddParameter("x", LogicalType::DOUBLE);
7855+
variant.AddParameter("y", LogicalType::DOUBLE);
7856+
variant.AddParameter("z", LogicalType::DOUBLE);
7857+
variant.AddParameter("m", LogicalType::DOUBLE);
7858+
variant.SetReturnType(GeoTypes::POINT_4D());
7859+
variant.SetFunction(ExecutePoint4D);
7860+
7861+
variant.SetDescription("Creates a POINT_4D.");
7862+
});
7863+
7864+
func.SetTag("ext", "spatial");
7865+
func.SetTag("category", "construction");
7866+
});
78037867
}
78047868
};
78057869

test/sql/geometry/geometry_types.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,23 @@ FROM (
105105
POINT Z (1 2 0) POINT Z (1 2 0) POINT (1 2)
106106
POINT Z (1 2 3) POINT Z (1 2 3) POINT (1 2)
107107

108+
# POINT_4D
109+
query III
110+
SELECT geom::POINT_4D,
111+
(geom::POINT_4D)::GEOMETRY,
112+
(geom::POINT_4D)::POINT_2D,
113+
FROM (
114+
VALUES (ST_GeomFromText('POINT (1 2)')),
115+
(ST_GeomFromText('POINT ZM (1 2 3 4)'))
116+
) t(geom)
117+
----
118+
POINT ZM (1 2 0 0)
119+
POINT ZM (1 2 0 0)
120+
POINT (1 2)
121+
POINT ZM (1 2 3 4)
122+
POINT ZM (1 2 3 4)
123+
POINT (1 2)
124+
108125
# LINESTRING_2D
109126
query II
110127
SELECT geom::LINESTRING_2D,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require spatial
2+
3+
query I
4+
SELECT ST_AsText(ST_MakePoint(143.3, -24.2)::GEOMETRY);
5+
----
6+
POINT (143.3 -24.2)
7+
8+
query I
9+
SELECT ST_AsText(ST_MakePoint(143.3, -24.2, 2445.2)::GEOMETRY);
10+
----
11+
POINT Z (143.3 -24.2 2445.2)
12+
13+
query I
14+
SELECT ST_AsText(ST_MakePoint(143.3, -24.2, 365.2, 1.6)::GEOMETRY);
15+
----
16+
POINT ZM (143.3 -24.2 365.2 1.6)
17+
18+
query I
19+
SELECT ST_M(ST_MakePoint(143.3, -24.2, 365.2, 1.6));
20+
----
21+
1.6
22+
23+
query I
24+
SELECT ST_Z(ST_MakePoint(143.3, -24.2, 365.2, 1.6));
25+
----
26+
365.2

0 commit comments

Comments
 (0)