Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions contrib/babelfishpg_common/sql/geography.sql
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,33 @@ CREATE OR REPLACE FUNCTION sys.Geography__stgeomfromtext(sys.NVARCHAR, integer)
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE OR REPLACE FUNCTION sys.Geography__STMPointFromText(sys.NVARCHAR, srid integer)
RETURNS sys.GEOGRAPHY
AS $$
DECLARE
Geomtype text;
geog sys.GEOGRAPHY;
BEGIN
IF $2 IS NULL THEN
RAISE EXCEPTION '''geography::STMPointFromText'' failed because parameter 2 is not allowed to be null.';
ELSIF $1 IS NULL THEN
RETURN NULL;
ELSIF $2 < 0 THEN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this check since we already have SRID validity check later on

RAISE EXCEPTION 'SRID value must be non-negative.';
END IF;

geog = sys.geogfromtext_helper($1::text, $2);
Geomtype = sys.ST_GeometryType(geog::sys.GEOMETRY);

IF Geomtype = 'ST_MultiPoint' THEN
RETURN geog;
ELSE
RAISE EXCEPTION 'Expected "MULTIPOINT" at Position 1. The input has %s', $1;
END IF;
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;


CREATE OR REPLACE FUNCTION sys.STAsText(sys.GEOGRAPHY)
RETURNS sys.NVARCHAR
AS $$
Expand Down
26 changes: 26 additions & 0 deletions contrib/babelfishpg_common/sql/geometry.sql
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,32 @@ CREATE OR REPLACE FUNCTION sys.Geometry__STPolyFromText(sys.NVARCHAR,srid intege
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE OR REPLACE FUNCTION sys.Geometry__STMPointFromText(sys.NVARCHAR, srid integer)
RETURNS sys.GEOMETRY
AS $$
DECLARE
Geomtype text;
geom sys.GEOMETRY;
BEGIN
IF $2 IS NULL THEN
RAISE EXCEPTION '''geometry::STMPointFromText'' failed because parameter 2 is not allowed to be null.';
ELSIF $1 IS NULL THEN
RETURN NULL;
ELSIF $2 < 0 THEN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

RAISE EXCEPTION 'SRID value must be non-negative.';
END IF;

geom = sys.geomfromtext_helper($1::text, $2);
Geomtype = sys.ST_GeometryType(geom);

IF Geomtype = 'ST_MultiPoint' THEN
RETURN geom;
ELSE
RAISE EXCEPTION 'Expected "MULTIPOINT" at Position 1. The input has %s', $1;
END IF;
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

CREATE OR REPLACE FUNCTION sys.ST_GeometryType(sys.GEOMETRY)
RETURNS text
AS '$libdir/postgis-3', 'geometry_geometrytype'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,61 @@ CREATE OR REPLACE FUNCTION sys.STGeometryType(geog sys.GEOGRAPHY)
RAISE EXCEPTION 'Unexpected geometry type format: %. Expected ST_* prefix.', geom_type;
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

--geometry
--STMPointFromText

CREATE OR REPLACE FUNCTION sys.Geometry__STMPointFromText(sys.NVARCHAR, srid integer)
RETURNS sys.GEOMETRY
AS $$
DECLARE
Geomtype text;
geom sys.GEOMETRY;
BEGIN
IF $2 IS NULL THEN
RAISE EXCEPTION '''geometry::STMPointFromText'' failed because parameter 2 is not allowed to be null.';
ELSIF $1 IS NULL THEN
RETURN NULL;
ELSIF $2 < 0 THEN
RAISE EXCEPTION 'SRID value must be non-negative.';
END IF;

geom = sys.geomfromtext_helper($1::text, $2);
Geomtype = sys.ST_GeometryType(geom);

IF Geomtype = 'ST_MultiPoint' THEN
RETURN geom;
ELSE
RAISE EXCEPTION 'Expected "MULTIPOINT" at Position 1. The input has %s', $1;
END IF;
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;

--Geography
--STMPointFromText

CREATE OR REPLACE FUNCTION sys.Geography__STMPointFromText(sys.NVARCHAR, srid integer)
RETURNS sys.GEOGRAPHY
AS $$
DECLARE
Geomtype text;
geog sys.GEOGRAPHY;
BEGIN
IF $2 IS NULL THEN
RAISE EXCEPTION '''geography::STMPointFromText'' failed because parameter 2 is not allowed to be null.';
ELSIF $1 IS NULL THEN
RETURN NULL;
ELSIF $2 < 0 THEN
RAISE EXCEPTION 'SRID value must be non-negative.';
END IF;

geog = sys.geogfromtext_helper($1::text, $2);
Geomtype = sys.ST_GeometryType(geog::sys.GEOMETRY);

IF Geomtype = 'ST_MultiPoint' THEN
RETURN geog;
ELSE
RAISE EXCEPTION 'Expected "MULTIPOINT" at Position 1. The input has %s', $1;
END IF;
END;
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
87 changes: 87 additions & 0 deletions contrib/babelfishpg_common/src/geo.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,90 @@ rewrite_dim_polygon_query(PointArrayList *pal)

return output.data;
}

char*
rewrite_multipoint_wkt(PointArray *pa)
{
DimensionType type;
StringInfoData output;

if (!pa)
return NULL;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we return pstrdup("MULTIPOINT EMPTY") instead similar to rewrite_dim_multipoint_wkt?


if (pa->count == 0)
{
if (pa->points)
pfree(pa->points);
pfree(pa);
return pstrdup("MULTIPOINT EMPTY");
}
initStringInfo(&output);

type = determine_ptarray_type(pa);

appendStringInfoString(&output, "MULTIPOINT");

if (type == M)
appendStringInfoString(&output, " M");

appendStringInfoChar(&output, '(');

transform_points(pa, type);

for (int i = 0; i < pa->count; i++)
{
POINT p = pa->points[i];

appendStringInfoChar(&output, '(');
format_tsql_point_coordinates(&output, p);
appendStringInfoChar(&output, ')');

if (i < pa->count - 1)
appendStringInfoString(&output, ", ");
}

appendStringInfoChar(&output, ')');

pfree(pa->points);
pfree(pa);

return output.data;
}


char*
rewrite_dim_multipoint_wkt(PointArray *pa)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the above function share a lot of common code, can we extract the logic to helper function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

{
StringInfoData output;

if (!pa || pa->count == 0)
{
if (pa) {
pfree(pa->points);
pfree(pa);
}
return pstrdup("MULTIPOINT EMPTY");
}

initStringInfo(&output);
appendStringInfoString(&output, "MULTIPOINT(");

for (int i = 0; i < pa->count; i++)
{
POINT p = pa->points[i];

appendStringInfoChar(&output, '(');
format_postgis_point_coordinates(&output, p);
appendStringInfoChar(&output, ')');

if (i < pa->count - 1)
appendStringInfoString(&output, ", ");
}

appendStringInfoChar(&output, ')');

pfree(pa->points);
pfree(pa);

return output.data;
}
4 changes: 4 additions & 0 deletions contrib/babelfishpg_common/src/geo_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,9 @@ char* rewrite_polygon_query(PointArrayList *pal);
char* rewrite_dim_polygon_query(PointArrayList *pal);
DimensionType determine_ring_type(PointArrayList *pal);

char* rewrite_multipoint_wkt(PointArray *pa);
char* rewrite_dim_multipoint_wkt(PointArray *pa);


#endif /* GEO_DATA_H */

95 changes: 95 additions & 0 deletions contrib/babelfishpg_common/src/geo_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ static int scanbuflen;
%type <pointarray> ptarray ptarraym ptarrayzm ptarrayz
%type <pointarraylist> ringlist ringlistm ringlistz ringlistzm
%type <str> geospatial_query point_query linestring_query polygon_query
%type <str> multipoint_query
%type <pointarray> mpoint_list mpoint_list_z mpoint_list_m mpoint_list_zm

%start geospatial_query
%define api.prefix {geo_yy}
Expand All @@ -39,6 +41,7 @@ geospatial_query:
linestring_query { $$ = $1; *result = $$; }
| point_query { $$ = $1; *result = $$; }
| polygon_query { $$ = $1; *result = $$; }
| multipoint_query { $$ = $1; *result = $$; }
;

point_query:
Expand Down Expand Up @@ -230,6 +233,98 @@ coordinate:
{ $$ = create_point($1, $2, 0, $4, 0, 1); }
;

multipoint_query:
MPOINT_TOK LPAREN mpoint_list RPAREN
{ $$ = rewrite_multipoint_wkt($3); }
| MPOINT_TOK LPAREN ptarray RPAREN
{ $$ = rewrite_multipoint_wkt($3); }
| MPOINT_TOK EMPTY_TOK
{ $$ = pstrdup("MULTIPOINT EMPTY"); }
| MPOINT_TOK Z_TOK LPAREN mpoint_list_z RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK M_TOK LPAREN mpoint_list_m RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK ZM_TOK LPAREN mpoint_list_zm RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK Z_TOK LPAREN ptarrayz RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK M_TOK LPAREN ptarraym RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK ZM_TOK LPAREN ptarrayzm RPAREN
{ $$ = rewrite_dim_multipoint_wkt($4); }
| MPOINT_TOK Z_TOK EMPTY_TOK
{ $$ = pstrdup("MULTIPOINT EMPTY"); }
| MPOINT_TOK M_TOK EMPTY_TOK
{ $$ = pstrdup("MULTIPOINT EMPTY"); }
| MPOINT_TOK ZM_TOK EMPTY_TOK
{ $$ = pstrdup("MULTIPOINT EMPTY"); }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need rules for these like : MULTIPOINT M EMPTY, TSQL doesn't allow it, does postgis create these ?

;


/* 2D MULTIPOINT: MULTIPOINT((x y), (x y), ...) */
mpoint_list:
LPAREN coordinate RPAREN
{
PointArray *pa = palloc(sizeof(PointArray));
init_point_array(pa);
add_point(pa, $2);
$$ = pa;
}
| mpoint_list COMMA_TOK LPAREN coordinate RPAREN
{
add_point($1, $4);
$$ = $1;
}
;

/* Z MULTIPOINT: MULTIPOINT Z((x y z), (x y z), ...) */
mpoint_list_z:
LPAREN coordz RPAREN
{
PointArray *pa = palloc(sizeof(PointArray));
init_point_array(pa);
add_point(pa, $2);
$$ = pa;
}
| mpoint_list_z COMMA_TOK LPAREN coordz RPAREN
{
add_point($1, $4);
$$ = $1;
}
;

/* M MULTIPOINT: MULTIPOINT M((x y m), (x y m), ...) */
mpoint_list_m:
LPAREN coordm RPAREN
{
PointArray *pa = palloc(sizeof(PointArray));
init_point_array(pa);
add_point(pa, $2);
$$ = pa;
}
| mpoint_list_m COMMA_TOK LPAREN coordm RPAREN
{
add_point($1, $4);
$$ = $1;
}
;

/* ZM MULTIPOINT: MULTIPOINT ZM((x y z m), (x y z m), ...) */
mpoint_list_zm:
LPAREN coordzm RPAREN
{
PointArray *pa = palloc(sizeof(PointArray));
init_point_array(pa);
add_point(pa, $2);
$$ = pa;
}
| mpoint_list_zm COMMA_TOK LPAREN coordzm RPAREN
{
add_point($1, $4);
$$ = $1;
}
;

%%

/* Include lexer after parser to avoid circular dependencies and ensure shared context */
Expand Down
2 changes: 1 addition & 1 deletion contrib/babelfishpg_common/src/geo_scan.l
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ POINT { return POINT_TOK; }
LINESTRING { return LINESTRING_TOK; }
POLYGON { return POLYGON_TOK; }
CIRCULARSTRING { yyerror(NULL, "CIRCULARSTRING is not supported"); return CIRCULARSTRING_TOK; }
MULTIPOINT { yyerror(NULL, "MULTIPOINT is not supported"); return MPOINT_TOK; }
MULTIPOINT { return MPOINT_TOK; }
MULTILINESTRING { yyerror(NULL, "MULTILINESTRING is not supported"); return MLINESTRING_TOK; }
MULTIPOLYGON { yyerror(NULL, "MULTIPOLYGON is not supported"); return MPOLYGON_TOK; }
CURVEPOLYGON { yyerror(NULL, "CURVEPOLYGON is not supported"); return CURVEPOLYGON_TOK; }
Expand Down
Loading
Loading