[postgis-tickets] r15788 - Make ST_AsMVT tolerant of NULL input and return '':bytea
Paul Ramsey
pramsey at cleverelephant.ca
Thu Sep 21 15:11:59 PDT 2017
Author: pramsey
Date: 2017-09-21 15:11:59 -0700 (Thu, 21 Sep 2017)
New Revision: 15788
Modified:
trunk/postgis/lwgeom_out_mvt.c
trunk/postgis/mvt.c
trunk/regress/mvt.sql
trunk/regress/mvt_expected
Log:
Make ST_AsMVT tolerant of NULL input and return '':bytea
(zero length bytea) when provided with only null inputs, or no
inputs. (References #3857)
Modified: trunk/postgis/lwgeom_out_mvt.c
===================================================================
--- trunk/postgis/lwgeom_out_mvt.c 2017-09-21 21:45:16 UTC (rev 15787)
+++ trunk/postgis/lwgeom_out_mvt.c 2017-09-21 22:11:59 UTC (rev 15788)
@@ -125,12 +125,16 @@
PG_RETURN_NULL();
#else
struct mvt_agg_context *ctx;
- uint8_t *buf;
+ bytea *buf;
if (!AggCheckCallContext(fcinfo, NULL))
elog(ERROR, "pgis_asmvt_finalfn called in non-aggregate context");
if (PG_ARGISNULL(0))
- PG_RETURN_NULL();
+ {
+ bytea *emptybuf = palloc(VARHDRSZ);
+ SET_VARSIZE(emptybuf, VARHDRSZ);
+ PG_RETURN_BYTEA_P(emptybuf);
+ }
ctx = (struct mvt_agg_context *) PG_GETARG_POINTER(0);
buf = mvt_agg_finalfn(ctx);
Modified: trunk/postgis/mvt.c
===================================================================
--- trunk/postgis/mvt.c 2017-09-21 21:45:16 UTC (rev 15787)
+++ trunk/postgis/mvt.c 2017-09-21 22:11:59 UTC (rev 15788)
@@ -302,7 +302,9 @@
int natts = tupdesc->natts;
uint32_t i;
bool geom_found = false;
+ char *key;
POSTGIS_DEBUG(2, "parse_column_keys called");
+
for (i = 0; i < natts; i++) {
#if POSTGIS_PGSQL_VERSION < 110
Oid typoid = getBaseType(tupdesc->attrs[i]->atttypid);
@@ -315,18 +317,17 @@
if (typoid == JSONBOID)
continue;
#endif
- char *key = palloc(strlen(tkey) + 1);
- strcpy(key, tkey);
+ key = pstrdup(tkey);
if (ctx->geom_name == NULL) {
if (!geom_found && typoid == TypenameGetTypid("geometry")) {
ctx->geom_index = i;
- geom_found = 1;
+ geom_found = true;
continue;
}
} else {
if (!geom_found && strcmp(key, ctx->geom_name) == 0) {
ctx->geom_index = i;
- geom_found = 1;
+ geom_found = true;
continue;
}
}
@@ -796,7 +797,7 @@
*/
void mvt_agg_transfn(struct mvt_agg_context *ctx)
{
- bool isnull;
+ bool isnull = false;
Datum datum;
GSERIALIZED *gs;
LWGEOM *lwgeom;
@@ -813,21 +814,28 @@
POSTGIS_DEBUGF(3, "mvt_agg_transfn new_capacity: %zd", new_capacity);
}
+ if (layer->n_features == 0)
+ parse_column_keys(ctx);
+
+ datum = GetAttributeByNum(ctx->row, ctx->geom_index + 1, &isnull);
+ POSTGIS_DEBUGF(3, "mvt_agg_transfn ctx->geom_index: %d", ctx->geom_index);
+ POSTGIS_DEBUGF(3, "mvt_agg_transfn isnull: %u", isnull);
+ POSTGIS_DEBUGF(3, "mvt_agg_transfn datum: %lu", datum);
+ if (isnull) /* Skip rows that have null geometry */
+ {
+ POSTGIS_DEBUG(3, "mvt_agg_transfn got null geom");
+ return;
+ }
+
feature = palloc(sizeof(*feature));
vector_tile__tile__feature__init(feature);
ctx->feature = feature;
- if (layer->n_features == 0)
- parse_column_keys(ctx);
- datum = GetAttributeByNum(ctx->row, ctx->geom_index + 1, &isnull);
- if (!datum)
- elog(ERROR, "mvt_agg_transfn: geometry column cannot be null");
gs = (GSERIALIZED *) PG_DETOAST_DATUM(datum);
lwgeom = lwgeom_from_gserialized(gs);
- POSTGIS_DEBUGF(3, "mvt_agg_transfn encoded feature count: %zd",
- layer->n_features);
+ POSTGIS_DEBUGF(3, "mvt_agg_transfn encoded feature count: %zd", layer->n_features);
layer->features[layer->n_features++] = feature;
encode_geometry(ctx, lwgeom);
@@ -850,7 +858,16 @@
uint8_t *buf;
POSTGIS_DEBUG(2, "mvt_agg_finalfn called");
+ POSTGIS_DEBUGF(2, "mvt_agg_finalfn n_features == %zd", ctx->layer->n_features);
+ /* Zero features => empty bytea output */
+ if (ctx->layer->n_features == 0)
+ {
+ buf = palloc(VARHDRSZ);
+ SET_VARSIZE(buf, VARHDRSZ);
+ return buf;
+ }
+
encode_keys(ctx);
encode_values(ctx);
Modified: trunk/regress/mvt.sql
===================================================================
--- trunk/regress/mvt.sql 2017-09-21 21:45:16 UTC (rev 15787)
+++ trunk/regress/mvt.sql 2017-09-21 22:11:59 UTC (rev 15788)
@@ -112,7 +112,24 @@
UNION
SELECT 2::int AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom) AS q;
+SELECT 'TA9', length(ST_AsMVT(q))
+FROM (
+ SELECT 1 AS c1, -1 AS c2,
+ ST_Normalize(ST_AsMVTGeom(
+ 'POINT(25 17)'::geometry,
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(4, 4))
+ )) AS geom
+) AS q;
+SELECT 'TA10', length(ST_AsMVT(q))
+FROM (
+ SELECT 1 AS c1, -1 AS c2,
+ ST_Normalize(ST_AsMVTGeom(
+ 'POINT(25 17)'::geometry,
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(48, 48))
+ )) AS geom
+) AS q;
+
-- default values tests
SELECT 'D1', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1, 'abcd'::text AS c2,
ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
@@ -141,6 +158,5 @@
-- unsupported input
SELECT 'TU2';
SELECT encode(ST_AsMVT(1, 'test', 4096, 'geom'), 'base64');
-SELECT 'TU3';
-SELECT encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64')
+SELECT 'TU3', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64')
FROM (SELECT NULL::integer AS c1, NULL AS geom) AS q;
Modified: trunk/regress/mvt_expected
===================================================================
--- trunk/regress/mvt_expected 2017-09-21 21:45:16 UTC (rev 15787)
+++ trunk/regress/mvt_expected 2017-09-21 22:11:59 UTC (rev 15788)
@@ -29,6 +29,8 @@
CW90aGVydGVzdCIGCgR0ZXN0KIAgeAI=
TA8|GkEKBHRlc3QSDBICAAAYASIECTLePxIMEgIAABgBIgQJNNw/EgwSAgABGAEiBAk03D8aAmMxIgIo
ASICKAIogCB4Ag==
+TA9|0
+TA10|49
D1|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
D2|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
D3|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
@@ -38,5 +40,4 @@
D7|POINT(1 4094)
TU2
ERROR: pgis_asmvt_transfn: parameter row cannot be other than a rowtype
-TU3
-ERROR: mvt_agg_transfn: geometry column cannot be null
+TU3|
More information about the postgis-tickets
mailing list