[postgis-tickets] r17856 - Restore ST_Union() aggregate signature and re-work
Paul Ramsey
pramsey at cleverelephant.ca
Fri Oct 4 11:25:46 PDT 2019
Author: pramsey
Date: 2019-10-04 11:25:46 -0700 (Fri, 04 Oct 2019)
New Revision: 17856
Added:
trunk/postgis/lwgeom_accum.h
Modified:
trunk/postgis/lwgeom_accum.c
trunk/postgis/lwgeom_geos.c
trunk/postgis/postgis.sql.in
trunk/postgis/postgis_after_upgrade.sql
trunk/postgis/postgis_before_upgrade.sql
trunk/regress/run_test.pl
Log:
Restore ST_Union() aggregate signature and re-work
performance/size enhancement to continue to avoid
using Array type during ST_Union(), hopefully
avoiding Array size limitations.
Modified: trunk/postgis/lwgeom_accum.c
===================================================================
--- trunk/postgis/lwgeom_accum.c 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/postgis/lwgeom_accum.c 2019-10-04 18:25:46 UTC (rev 17856)
@@ -37,12 +37,12 @@
#include "lwgeom_geos.h"
#include "lwgeom_pg.h"
#include "lwgeom_transform.h"
+#include "lwgeom_accum.h"
/* Local prototypes */
Datum PGISDirectFunctionCall1(PGFunction func, Datum arg1);
Datum PGISDirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2);
Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS);
-Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS);
Datum pgis_geometry_collect_finalfn(PG_FUNCTION_ARGS);
Datum pgis_geometry_polygonize_finalfn(PG_FUNCTION_ARGS);
Datum pgis_geometry_makeline_finalfn(PG_FUNCTION_ARGS);
@@ -58,49 +58,22 @@
Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS);
-/** @file
-** Versions of PostgreSQL < 8.4 perform array accumulation internally using
-** pass by value, which is very slow working with large/many geometries.
-** Hence PostGIS currently implements its own aggregate for building
-** geometry arrays using pass by reference, which is significantly faster and
-** similar to the method used in PostgreSQL 8.4.
-**
-** Hence we can revert this to the original aggregate functions from 1.3 at
-** whatever point PostgreSQL 8.4 becomes the minimum version we support :)
-*/
-
-
/**
-** To pass the internal ArrayBuildState pointer between the
-** transfn and finalfn we need to wrap it into a custom type first,
-** the pgis_abs type in our case. The extra "data" member can optionally
-** be used to pass an additional constant argument to a finalizer function.
+** The transfer function builds a List of LWGEOM* allocated
+** in the aggregate memory context. The pgis_accum_finalfn
+** converts that List into a Pg Array.
*/
-
-typedef struct
-{
- ArrayBuildState *a;
- Datum data;
-}
-pgis_abs;
-
-
-/**
-** The transfer function hooks into the PostgreSQL accumArrayResult()
-** function (present since 8.0) to build an array in a side memory
-** context.
-*/
PG_FUNCTION_INFO_V1(pgis_geometry_accum_transfn);
Datum
pgis_geometry_accum_transfn(PG_FUNCTION_ARGS)
{
- Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
- MemoryContext aggcontext;
- ArrayBuildState *state;
- pgis_abs *p;
- Datum elem;
+ MemoryContext aggcontext, old;
+ CollectionBuildState *state;
+ LWGEOM *geom = NULL;
+ GSERIALIZED *gser = NULL;
+ Datum argType = get_fn_expr_argtype(fcinfo->flinfo, 1);
- if (arg1_typeid == InvalidOid)
+ if (argType == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data type")));
@@ -114,52 +87,64 @@
if ( PG_ARGISNULL(0) )
{
- MemoryContext old = MemoryContextSwitchTo(aggcontext);
- p = (pgis_abs*) palloc(sizeof(pgis_abs));
- p->a = NULL;
- p->data = (Datum) NULL;
+ int n = ((PG_NARGS()-2) <= CollectionBuildStateDataSize) ? (PG_NARGS()-2) : CollectionBuildStateDataSize;
- if (PG_NARGS() == 3)
+ state = MemoryContextAlloc(aggcontext, sizeof(CollectionBuildState));
+ state->geoms = NULL;
+ state->geomOid = argType;
+
+ for (int i = 0; i < n; i++)
{
- Datum argument = PG_GETARG_DATUM(2);
- Oid dataOid = get_fn_expr_argtype(fcinfo->flinfo, 2);
-
- p->data = datumCopy(argument, get_typbyval(dataOid), get_typlen(dataOid));
-
+ Datum argument = PG_GETARG_DATUM(i+2);
+ Oid dataOid = get_fn_expr_argtype(fcinfo->flinfo, i+2);
+ state->data[i] = datumCopy(argument, get_typbyval(dataOid), get_typlen(dataOid));
}
- MemoryContextSwitchTo(old);
}
else
{
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ state = (CollectionBuildState*) PG_GETARG_POINTER(0);
}
- state = p->a;
- elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
- state = accumArrayResult(state,
- elem,
- PG_ARGISNULL(1),
- arg1_typeid,
- aggcontext);
- p->a = state;
- PG_RETURN_POINTER(p);
+ if (!PG_ARGISNULL(1))
+ gser = PG_GETARG_GSERIALIZED_P(1);
+
+ /* Take a copy of the geometry into the aggregate context */
+ old = MemoryContextSwitchTo(aggcontext);
+ if (gser)
+ geom = lwgeom_clone_deep(lwgeom_from_gserialized(gser));
+
+ /* Initialize or append to list as necessary */
+ if (state->geoms)
+ state->geoms = lappend(state->geoms, geom);
+ else
+ state->geoms = list_make1(geom);
+
+ MemoryContextSwitchTo(old);
+
+ PG_RETURN_POINTER(state);
}
+Datum pgis_accum_finalfn(CollectionBuildState *state, MemoryContext mctx, FunctionCallInfo fcinfo);
-Datum pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo);
-
/**
-** The final function rescues the built array from the side memory context
-** using the PostgreSQL built-in function makeMdArrayResult
+** The final function reads the List of LWGEOM* from the aggregate
+** memory context and constructs an Array using construct_md_array()
*/
Datum
-pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, __attribute__((__unused__)) FunctionCallInfo fcinfo)
+pgis_accum_finalfn(CollectionBuildState *state, MemoryContext mctx, __attribute__((__unused__)) FunctionCallInfo fcinfo)
{
+ ListCell *l;
+ size_t nelems = 0;
+ Datum *elems;
+ bool *nulls;
+ int16 elmlen;
+ bool elmbyval;
+ char elmalign;
+ size_t i = 0;
+ ArrayType *arr;
int dims[1];
- int lbs[1];
- ArrayBuildState *state;
- Datum result;
+ int lbs[1] = {1};
/* cannot be called directly because of internal-type argument */
Assert(fcinfo->context &&
@@ -167,11 +152,40 @@
IsA(fcinfo->context, WindowAggState))
);
- state = p->a;
- dims[0] = state->nelems;
- lbs[0] = 1;
- result = makeMdArrayResult(state, 1, dims, lbs, mctx, false);
- return result;
+ /* Retrieve geometry type metadata */
+ get_typlenbyvalalign(state->geomOid, &elmlen, &elmbyval, &elmalign);
+ nelems = list_length(state->geoms);
+
+ /* Build up an array, because that's what we pass to all the */
+ /* specific final functions */
+ elems = palloc(nelems * sizeof(Datum));
+ nulls = palloc(nelems * sizeof(bool));
+
+ foreach (l, state->geoms)
+ {
+ LWGEOM *geom = (LWGEOM*)(lfirst(l));
+ Datum elem = (Datum)0;
+ bool isNull = true;
+ if (geom)
+ {
+ GSERIALIZED *gser = geometry_serialize(geom);
+ elem = PointerGetDatum(gser);
+ isNull = false;
+ }
+ elems[i] = elem;
+ nulls[i] = isNull;
+ i++;
+
+ if (i >= nelems)
+ break;
+ }
+
+ /* Turn element array into PgSQL array */
+ dims[0] = nelems;
+ arr = construct_md_array(elems, nulls, 1, dims, lbs, state->geomOid,
+ elmlen, elmbyval, elmalign);
+
+ return PointerGetDatum(arr);
}
/**
@@ -182,7 +196,7 @@
Datum
pgis_geometry_collect_finalfn(PG_FUNCTION_ARGS)
{
- pgis_abs *p;
+ CollectionBuildState *p;
Datum result = 0;
Datum geometry_array = 0;
@@ -189,7 +203,7 @@
if (PG_ARGISNULL(0))
PG_RETURN_NULL(); /* returns null iff no input values */
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ p = (CollectionBuildState*) PG_GETARG_POINTER(0);
geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
result = PGISDirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
@@ -208,7 +222,7 @@
Datum
pgis_geometry_polygonize_finalfn(PG_FUNCTION_ARGS)
{
- pgis_abs *p;
+ CollectionBuildState *p;
Datum result = 0;
Datum geometry_array = 0;
@@ -215,7 +229,7 @@
if (PG_ARGISNULL(0))
PG_RETURN_NULL(); /* returns null iff no input values */
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ p = (CollectionBuildState*) PG_GETARG_POINTER(0);
geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
result = PGISDirectFunctionCall1( polygonize_garray, geometry_array );
@@ -233,7 +247,7 @@
Datum
pgis_geometry_makeline_finalfn(PG_FUNCTION_ARGS)
{
- pgis_abs *p;
+ CollectionBuildState *p;
Datum result = 0;
Datum geometry_array = 0;
@@ -240,7 +254,7 @@
if (PG_ARGISNULL(0))
PG_RETURN_NULL(); /* returns null iff no input values */
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ p = (CollectionBuildState*) PG_GETARG_POINTER(0);
geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
result = PGISDirectFunctionCall1( LWGEOM_makeline_garray, geometry_array );
@@ -258,7 +272,7 @@
Datum
pgis_geometry_clusterintersecting_finalfn(PG_FUNCTION_ARGS)
{
- pgis_abs *p;
+ CollectionBuildState *p;
Datum result = 0;
Datum geometry_array = 0;
@@ -265,7 +279,7 @@
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ p = (CollectionBuildState*) PG_GETARG_POINTER(0);
geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
result = PGISDirectFunctionCall1( clusterintersecting_garray, geometry_array );
if (!result)
@@ -282,7 +296,7 @@
Datum
pgis_geometry_clusterwithin_finalfn(PG_FUNCTION_ARGS)
{
- pgis_abs *p;
+ CollectionBuildState *p;
Datum result = 0;
Datum geometry_array = 0;
@@ -289,9 +303,9 @@
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
- p = (pgis_abs*) PG_GETARG_POINTER(0);
+ p = (CollectionBuildState*) PG_GETARG_POINTER(0);
- if (!p->data)
+ if (!p->data[0])
{
elog(ERROR, "Tolerance not defined");
PG_RETURN_NULL();
@@ -298,7 +312,7 @@
}
geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
- result = PGISDirectFunctionCall2( cluster_within_distance_garray, geometry_array, p->data);
+ result = PGISDirectFunctionCall2( cluster_within_distance_garray, geometry_array, p->data[0]);
if (!result)
PG_RETURN_NULL();
Added: trunk/postgis/lwgeom_accum.h
===================================================================
--- trunk/postgis/lwgeom_accum.h (rev 0)
+++ trunk/postgis/lwgeom_accum.h 2019-10-04 18:25:46 UTC (rev 17856)
@@ -0,0 +1,44 @@
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.net
+ *
+ * PostGIS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * PostGIS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
+ *
+ **********************************************************************
+ *
+ * Copyright (c) 2019, Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ **********************************************************************/
+
+#ifndef _LWGEOM_ACCUM_H
+#define _LWGEOM_ACCUM_H 1
+
+/**
+** To pass the internal state of our collection between the
+** transfn and finalfn we need to wrap it into a custom type first,
+** the CollectionBuildState type in our case. The extra "data" member
+** can optionally be used to pass additional constant
+** arguments to a finalizer function.
+*/
+#define CollectionBuildStateDataSize 2
+typedef struct CollectionBuildState
+{
+ List *geoms; /* collected geometries */
+ Datum data[CollectionBuildStateDataSize];
+ Oid geomOid;
+} CollectionBuildState;
+
+
+#endif /* _LWGEOM_ACCUM_H */
Modified: trunk/postgis/lwgeom_geos.c
===================================================================
--- trunk/postgis/lwgeom_geos.c 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/postgis/lwgeom_geos.c 2019-10-04 18:25:46 UTC (rev 17856)
@@ -27,6 +27,8 @@
#include "../postgis_config.h"
+#include "float.h" /* for DBL_DIG */
+
/* PostgreSQL */
#include "postgres.h"
#include "funcapi.h"
@@ -34,10 +36,8 @@
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/numeric.h"
-
#include "access/htup_details.h"
-
/* PostGIS */
#include "lwgeom_functions_analytic.h" /* for point_in_polygon */
#include "lwgeom_geos.h"
@@ -44,7 +44,7 @@
#include "liblwgeom.h"
#include "lwgeom_rtree.h"
#include "lwgeom_geos_prepared.h"
-#include "float.h" /* for DBL_DIG */
+#include "lwgeom_accum.h"
/* Return NULL on GEOS error
@@ -107,6 +107,7 @@
Datum ST_DelaunayTriangles(PG_FUNCTION_ARGS);
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS);
+Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS);
/*
** Prototypes end
@@ -505,135 +506,62 @@
PG_RETURN_POINTER(gser_out);
}
-typedef struct UnionBuildState
-{
- MemoryContext mcontext; /* where all the temp stuff is kept */
- GEOSGeometry **geoms; /* collected GEOS geometries*/
- int empty_type;
- uint32_t alen; /* allocated length of above arrays */
- uint32_t ngeoms; /* number of valid entries in above arrays */
- int32_t srid;
- bool is3d;
-} UnionBuildState;
-PG_FUNCTION_INFO_V1(pgis_geometry_union_transfn);
-Datum pgis_geometry_union_transfn(PG_FUNCTION_ARGS)
+PG_FUNCTION_INFO_V1(pgis_geometry_union_finalfn);
+Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS)
{
- MemoryContext aggcontext;
- MemoryContext old;
- UnionBuildState *state;
- GSERIALIZED *gser_in;
- uint32_t curgeom;
- GEOSGeometry *g;
+ CollectionBuildState *state;
+ ListCell *l;
+ LWGEOM **geoms;
+ GSERIALIZED *gser_out;
+ size_t ngeoms = 0;
+ int empty_type = 0;
+ bool first = true;
+ int32_t srid = SRID_UNKNOWN;
+ int has_z = LW_FALSE;
- if (!AggCheckCallContext(fcinfo, &aggcontext))
- {
- /* cannot be called directly because of dummy-type argument */
- elog(ERROR, "%s called in non-aggregate context", __func__);
- aggcontext = NULL; /* keep compiler quiet */
- }
+ if (PG_ARGISNULL(0))
+ PG_RETURN_NULL(); /* returns null iff no input values */
- if (!PG_ARGISNULL(0))
- {
- state = (UnionBuildState *)PG_GETARG_POINTER(0);
- }
- else
- {
- old = MemoryContextSwitchTo(aggcontext);
- state = (UnionBuildState *)palloc(sizeof(UnionBuildState));
+ state = (CollectionBuildState *)PG_GETARG_POINTER(0);
+ geoms = palloc(list_length(state->geoms) * sizeof(LWGEOM*));
- state->mcontext = aggcontext;
- state->alen = 10;
- state->ngeoms = 0;
- state->geoms = palloc(sizeof(GEOSGeometry *) * state->alen);
- state->is3d = false;
- state->srid = 0;
- state->empty_type = 0;
-
- initGEOS(lwpgnotice, lwgeom_geos_error);
-
- MemoryContextSwitchTo(old);
- };
-
- /* do we have geometry to push? */
- if (!PG_ARGISNULL(1))
+ /* Read contents of list into an array of only non-null values */
+ foreach (l, state->geoms)
{
- old = MemoryContextSwitchTo(state->mcontext);
- gser_in = PG_GETARG_GSERIALIZED_P_COPY(1);
- MemoryContextSwitchTo(old);
-
- if (state->ngeoms > 0)
+ LWGEOM *geom = (LWGEOM*)(lfirst(l));
+ if (geom)
{
- if (state->srid != gserialized_get_srid(gser_in))
- for (curgeom = 0; curgeom < state->ngeoms; curgeom++)
- GEOSGeom_destroy(state->geoms[curgeom]);
-
- gserialized_error_if_srid_mismatch_reference(gser_in, state->srid, __func__);
- }
-
- if (!gserialized_is_empty(gser_in))
- {
- if (state->ngeoms == 0)
+ if (!lwgeom_is_empty(geom))
{
- state->srid = gserialized_get_srid(gser_in);
- state->is3d = gserialized_has_z(gser_in);
+ geoms[ngeoms++] = geom;
+ if (first)
+ {
+ srid = lwgeom_get_srid(geom);
+ has_z = lwgeom_has_z(geom);
+ first = false;
+ }
}
-
- old = MemoryContextSwitchTo(state->mcontext);
- g = POSTGIS2GEOS(gser_in);
- MemoryContextSwitchTo(old);
-
- if (!g)
+ else
{
- for (curgeom = 0; curgeom < state->ngeoms; curgeom++)
- GEOSGeom_destroy(state->geoms[curgeom]);
- HANDLE_GEOS_ERROR("One of the geometries in the set could not be converted to GEOS");
+ int type = lwgeom_get_type(geom);
+ empty_type = type > empty_type ? type : empty_type;
}
-
- curgeom = state->ngeoms;
- state->ngeoms++;
-
- if (state->ngeoms > state->alen)
- {
- old = MemoryContextSwitchTo(state->mcontext);
- state->alen *= 2;
- state->geoms = repalloc(state->geoms, sizeof(GEOSGeometry *) * state->alen);
- MemoryContextSwitchTo(old);
- }
-
- state->geoms[curgeom] = g;
}
- else
- {
- int gser_type = gserialized_get_type(gser_in);
- if (gser_type > state->empty_type)
- state->empty_type = gser_type;
- }
}
- PG_RETURN_POINTER(state);
-}
-
-PG_FUNCTION_INFO_V1(pgis_geometry_union_finalfn);
-Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS)
-{
- UnionBuildState *state;
- GSERIALIZED *gser_out = NULL;
- GEOSGeometry *g = NULL;
- GEOSGeometry *g_union = NULL;
-
- if (PG_ARGISNULL(0))
- PG_RETURN_NULL(); /* returns null iff no input values */
-
- state = (UnionBuildState *)PG_GETARG_POINTER(0);
-
/*
- ** Take our GEOS geometries and turn them into a GEOS collection,
+ ** Take our array of LWGEOM* and turn it into a GEOS collection,
** then pass that into cascaded union.
*/
- if (state->ngeoms > 0)
+ if (ngeoms > 0)
{
- g = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, state->geoms, state->ngeoms);
+ GEOSGeometry *g = NULL;
+ GEOSGeometry *g_union = NULL;
+ LWCOLLECTION* col = lwcollection_construct(COLLECTIONTYPE, srid, NULL, ngeoms, geoms);
+
+ initGEOS(lwpgnotice, lwgeom_geos_error);
+ g = LWGEOM2GEOS((LWGEOM*)col, LW_FALSE);
if (!g)
HANDLE_GEOS_ERROR("Could not create GEOS COLLECTION from geometry array");
@@ -642,8 +570,8 @@
if (!g_union)
HANDLE_GEOS_ERROR("GEOSUnaryUnion");
- GEOSSetSRID(g_union, state->srid);
- gser_out = GEOS2POSTGIS(g_union, state->is3d);
+ GEOSSetSRID(g_union, srid);
+ gser_out = GEOS2POSTGIS(g_union, has_z);
GEOSGeom_destroy(g_union);
}
/* No real geometries in our array, any empties? */
@@ -650,9 +578,9 @@
else
{
/* If it was only empties, we'll return the largest type number */
- if (state->empty_type > 0)
+ if (empty_type > 0)
PG_RETURN_POINTER(
- geometry_serialize(lwgeom_construct_empty(state->empty_type, state->srid, state->is3d, 0)));
+ geometry_serialize(lwgeom_construct_empty(empty_type, srid, has_z, 0)));
/* Nothing but NULL, returns NULL */
else
@@ -668,6 +596,8 @@
PG_RETURN_POINTER(gser_out);
}
+
+
/**
* @example ST_UnaryUnion {@link #geomunion} SELECT ST_UnaryUnion(
* 'POLYGON((0 0, 10 0, 0 10, 10 10, 0 0))'
Modified: trunk/postgis/postgis.sql.in
===================================================================
--- trunk/postgis/postgis.sql.in 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/postgis/postgis.sql.in 2019-10-04 18:25:46 UTC (rev 17856)
@@ -3835,12 +3835,6 @@
AS 'MODULE_PATHNAME'
LANGUAGE 'c' _PARALLEL;
--- Availability: 3.0.0
-CREATE OR REPLACE FUNCTION pgis_geometry_union_transfn(internal, geometry)
- RETURNS internal
- AS 'MODULE_PATHNAME'
- LANGUAGE 'c' _PARALLEL;
-
-- Availability: 1.4.0
-- Changed: 2.5.0 use 'internal' transfer type
CREATE OR REPLACE FUNCTION pgis_geometry_union_finalfn(internal)
@@ -3894,9 +3888,8 @@
-- we don't want to force drop of this agg since its often used in views
-- parallel handling dealt with in postgis_after_upgrade.sql
-- Changed: 2.5.0 use 'internal' stype
--- Changed: 3.0.0 transfn now converts to GEOS
CREATE AGGREGATE ST_Union (geometry) (
- sfunc = pgis_geometry_union_transfn,
+ sfunc = pgis_geometry_accum_transfn,
stype = internal,
#if POSTGIS_PGSQL_VERSION >= 96
parallel = safe,
Modified: trunk/postgis/postgis_after_upgrade.sql
===================================================================
--- trunk/postgis/postgis_after_upgrade.sql 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/postgis/postgis_after_upgrade.sql 2019-10-04 18:25:46 UTC (rev 17856)
@@ -227,6 +227,8 @@
DROP FUNCTION IF EXISTS st_combine_bbox(box2d, geometry);
DROP FUNCTION IF EXISTS st_distance_sphere(geometry, geometry);
+-- dev function 3.0 cycle
+DROP FUNCTION IF EXISTS pgis_geometry_union_transfn(internal, geometry);
-- pgis_abs type was increased from 8 bytes in 2.1 to 16 bytes in 2.2
-- See #3460
Modified: trunk/postgis/postgis_before_upgrade.sql
===================================================================
--- trunk/postgis/postgis_before_upgrade.sql 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/postgis/postgis_before_upgrade.sql 2019-10-04 18:25:46 UTC (rev 17856)
@@ -198,7 +198,6 @@
-- This signature was superseeded
DROP FUNCTION IF EXISTS st_buffer(geometry, double precision); -- Does not conflict
-
-- FUNCTION ST_CurveToLine changed to add defaults in 2.5
-- These signatures were superseeded
DROP FUNCTION IF EXISTS ST_CurveToLine(geometry, integer); -- Does not conflict
Modified: trunk/regress/run_test.pl
===================================================================
--- trunk/regress/run_test.pl 2019-10-03 09:49:41 UTC (rev 17855)
+++ trunk/regress/run_test.pl 2019-10-04 18:25:46 UTC (rev 17856)
@@ -299,6 +299,25 @@
exit(1);
}
+ $query = "insert into upgrade_test(g1,g2) values ";
+ $query .= "('POINT(0 0)', 'LINESTRING(0 0, 1 1)'), ";
+ $query .= "('POINT(1 0)', 'LINESTRING(0 1, 1 1)');";
+ my $ret = sql($query);
+ unless ( $ret =~ /^INSERT/ ) {
+ `dropdb $DB`;
+ print "\nSomething went wrong populating upgrade_test table: $ret.\n";
+ exit(1);
+ }
+
+ my $query = "create view upgrade_view_test as ";
+ $query .= "select st_union(g1) from upgrade_test;";
+ my $ret = sql($query);
+ unless ( $ret =~ /^CREATE/ ) {
+ `dropdb $DB`;
+ print "\nSomething went wrong creating upgrade_view_test view: $ret.\n";
+ exit(1);
+ }
+
if ( $OPT_WITH_RASTER )
{
$query = "insert into upgrade_test(r) ";
@@ -328,6 +347,13 @@
{
# TODO: allow passing the "upgrade-cleanup" script via commandline
+ my $ret = sql("drop view upgrade_view_test;");
+ unless ( $ret =~ /^DROP/ ) {
+ `dropdb $DB`;
+ print "\nSomething went wrong dropping spatial view: $ret.\n";
+ exit(1);
+ }
+
my $ret = sql("drop table upgrade_test;");
unless ( $ret =~ /^DROP/ ) {
`dropdb $DB`;
More information about the postgis-tickets
mailing list