]> granicus.if.org Git - postgis/commitdiff
Make ST_AsMVT tolerant of NULL input and return '':bytea
authorPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 21 Sep 2017 22:11:59 +0000 (22:11 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 21 Sep 2017 22:11:59 +0000 (22:11 +0000)
(zero length bytea) when provided with only null inputs, or no
inputs. (References #3857)

git-svn-id: http://svn.osgeo.org/postgis/trunk@15788 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_out_mvt.c
postgis/mvt.c
regress/mvt.sql
regress/mvt_expected

index 7e886eadb4c7e1f3b31407cbae0b4ac105d24076..945d901c41a5e32bb849bcc19fae50a1819edd8f 100644 (file)
@@ -125,12 +125,16 @@ Datum pgis_asmvt_finalfn(PG_FUNCTION_ARGS)
        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);
index 613d69a644cbb07383c05c0c8cdf6f70dc3e1fcb..0ef1401ae7b0e4aec25c94ba8ac34074398cdcd1 100644 (file)
@@ -302,7 +302,9 @@ static void parse_column_keys(struct mvt_agg_context *ctx)
        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 @@ static void parse_column_keys(struct mvt_agg_context *ctx)
                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_init_context(struct mvt_agg_context *ctx)
  */
 void mvt_agg_transfn(struct mvt_agg_context *ctx)
 {
-       bool isnull;
+       bool isnull = false;
        Datum datum;
        GSERIALIZED *gs;
        LWGEOM *lwgeom;
@@ -813,21 +814,28 @@ void mvt_agg_transfn(struct mvt_agg_context *ctx)
                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,6 +858,15 @@ uint8_t *mvt_agg_finalfn(struct mvt_agg_context *ctx)
        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);
index f7baa1318f37f577a879cbafa4dd9c97021f55cb..dd8239db2d09df1fecbc7947772fe856a76edd3a 100644 (file)
@@ -112,6 +112,23 @@ SELECT 'TA8', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (
     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,
@@ -141,6 +158,5 @@ select 'D7', ST_AsText(ST_Normalize(ST_AsMVTGeom(
 -- 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;
index e94c0de3402fabdcdbe19348a46237a52baac055..4b699cc7c491eba80be4f456b9beae757f692ade 100644 (file)
@@ -29,6 +29,8 @@ TA7|Gk4KBHRlc3QSDBICAAAYASIECTTcPxIMEgIAARgBIgQJMt4/EgwSAgABGAEiBAk03D8aAmMxIgsK
 CW90aGVydGVzdCIGCgR0ZXN0KIAgeAI=
 TA8|GkEKBHRlc3QSDBICAAAYASIECTLePxIMEgIAABgBIgQJNNw/EgwSAgABGAEiBAk03D8aAmMxIgIo
 ASICKAIogCB4Ag==
+TA9|0
+TA10|49
 D1|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
 D2|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
 D3|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
@@ -38,5 +40,4 @@ D6|POINT(1 4094)
 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|