[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha2-20-g90a15b1

git at osgeo.org git at osgeo.org
Wed Jul 29 04:16:20 PDT 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  90a15b199ff55e946281c7200e0930e28dfdd585 (commit)
       via  d873d27ed6fe7f58d6268fc04ee62b003edd1f42 (commit)
       via  5a8548cef1237bdffd9f65edba48b34970af4e23 (commit)
       via  7b3effebd8b00be30c046c8d2291eccc28fbd7bc (commit)
       via  864294821174c073fb3492650ae496a75cbf6a60 (commit)
       via  24252fb7f7651d0fa328f7f4acdad52af72c1d04 (commit)
       via  bc11c9271266454dc93c84b40af6ef8eb2615b70 (commit)
       via  465e203abc3603802b38b9943584625f62bf4dc9 (commit)
       via  99c6135196fab1f6925553528a6569d6195be0df (commit)
      from  9cac001ba8d0f874e96845315f56a0b6a4b6fe87 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 90a15b199ff55e946281c7200e0930e28dfdd585
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 28 15:31:29 2020 +0200

    Adjust SQL function costs
    
    Closes #4686
    Closes https://github.com/postgis/postgis/pull/572

diff --git a/NEWS b/NEWS
index 357c5a5..4cfdb46 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,11 @@ Only tickets not included in 3.1.0alpha2
         - The default precision is the same (9 for GeoJSON, 15 for everything else).
   - #4729, WKT/KML: Print doubles directly into stringbuffers (Raúl Marín)
   - #4533, Use the standard coordinate printing system for box types (Raúl Marín)
+  - #4686, Avoid decompressing geographies when possible (Raúl Marín)
+           Affects ANALYZE, _ST_PointOutside, postgis_geobbox, ST_CombineBbox(box2d, geometry),
+           ST_ClipByBox2D when the geometry is fully inside or outside the bbox and
+           ST_BoundingDiagonal.
+
 
 * Bug fixes *
   -
diff --git a/postgis/geography.sql.in b/postgis/geography.sql.in
index 3b43617..6a2d3d9 100644
--- a/postgis/geography.sql.in
+++ b/postgis/geography.sql.in
@@ -617,7 +617,7 @@ CREATE OR REPLACE FUNCTION _ST_PointOutside(geography)
 	RETURNS geography
 	AS 'MODULE_PATHNAME','geography_point_outside'
 	LANGUAGE 'c' IMMUTABLE STRICT
-	_COST_MEDIUM;
+	_COST_DEFAULT;
 
 -- Availability: 2.1.0
 CREATE OR REPLACE FUNCTION ST_Segmentize(geog geography, max_segment_length float8)
diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in
index 92d685d..0dfa55e 100644
--- a/postgis/postgis.sql.in
+++ b/postgis/postgis.sql.in
@@ -1477,7 +1477,7 @@ CREATE OR REPLACE FUNCTION ST_BoundingDiagonal(geom geometry, fits boolean DEFAU
 	RETURNS geometry
 	AS 'MODULE_PATHNAME', 'ST_BoundingDiagonal'
 	LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE
-	_COST_LOW;
+	_COST_DEFAULT;
 
 -- Availability: 1.2.2
 CREATE OR REPLACE FUNCTION ST_Reverse(geometry)
@@ -3848,7 +3848,7 @@ CREATE OR REPLACE FUNCTION ST_CombineBbox(box2d,geometry)
 	RETURNS box2d
 	AS 'MODULE_PATHNAME', 'BOX2D_combine'
 	LANGUAGE 'c' IMMUTABLE PARALLEL SAFE
-	_COST_LOW;
+	_COST_DEFAULT;
 
 -- Availability: 1.2.2
 -- Changed: 2.2.0 to use non-deprecated ST_CombineBBox (r13535)

commit d873d27ed6fe7f58d6268fc04ee62b003edd1f42
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 18:36:24 2020 +0200

    Speed up ST_BoundingDiagonal with compressed geometries and no fits

diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h
index 8908d9b..fd692f1 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -185,7 +185,7 @@ void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const i
 * Fails on empty.
 */
 int gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox);
-int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, uint8_t *type, int32_t *srid);
+int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid);
 
 /* PG-exposed */
 Datum BOX2D_same(PG_FUNCTION_ARGS);
diff --git a/postgis/gserialized_gist_2d.c b/postgis/gserialized_gist_2d.c
index 5193b27..1dc159d 100644
--- a/postgis/gserialized_gist_2d.c
+++ b/postgis/gserialized_gist_2d.c
@@ -456,7 +456,7 @@ static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
  * return #LW_FAILURE, otherwise #LW_SUCCESS.
  */
 int
-gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, uint8_t *type, int32_t *srid)
+gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid)
 {
 	GSERIALIZED *gpart;
 	int result = LW_SUCCESS;
@@ -481,11 +481,11 @@ gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, uint8_t *type, int3
 	}
 
 	result = gserialized_get_gbox_p(gpart, gbox);
-	POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
-
+	*flags = gserialized_get_lwflags(gpart);
 	*srid = gserialized_get_srid(gpart);
 	*type = gserialized_get_type(gpart);
 
+	POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
 	return result;
 }
 
@@ -501,8 +501,9 @@ gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
 {
 	uint8_t type;
 	int32_t srid;
+	lwflags_t flags;
 
-	return gserialized_datum_get_internals_p(gsdatum, gbox, &type, &srid);
+	return gserialized_datum_get_internals_p(gsdatum, gbox, &flags, &type, &srid);
 }
 
 int
diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c
index 743e64b..e6b76d8 100644
--- a/postgis/lwgeom_functions_basic.c
+++ b/postgis/lwgeom_functions_basic.c
@@ -2899,49 +2899,56 @@ Datum ST_BoundingDiagonal(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(ST_BoundingDiagonal);
 Datum ST_BoundingDiagonal(PG_FUNCTION_ARGS)
 {
-	GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0);
 	GSERIALIZED *geom_out;
 	bool fits = PG_GETARG_BOOL(1);
-	LWGEOM *lwgeom_in = lwgeom_from_gserialized(geom_in);
-	LWGEOM *lwgeom_out;
-	const GBOX *gbox;
-	int hasz = FLAGS_GET_Z(lwgeom_in->flags);
-	int hasm = FLAGS_GET_M(lwgeom_in->flags);
-	int32_t srid = lwgeom_in->srid;
+	LWGEOM *lwgeom_out = NULL;
+
+	GBOX gbox = {0};
+	int hasz;
+	int hasm;
+	int32_t srid;
+
 	POINT4D pt;
 	POINTARRAY *pa;
 
 	if (fits)
 	{
-		/* unregister any cached bbox to ensure it's recomputed */
-		lwgeom_in->bbox = NULL;
+		GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0);
+		LWGEOM *lwgeom_in = lwgeom_from_gserialized(geom_in);
+		lwgeom_calculate_gbox(lwgeom_in, &gbox);
+		hasz = FLAGS_GET_Z(lwgeom_in->flags);
+		hasm = FLAGS_GET_M(lwgeom_in->flags);
+		srid = lwgeom_in->srid;
 	}
-
-	gbox = lwgeom_get_bbox(lwgeom_in);
-
-	if (!gbox)
+	else
 	{
-		lwgeom_out = lwgeom_construct_empty(LINETYPE, srid, hasz, hasm);
+		uint8_t type;
+		lwflags_t flags;
+		int res = gserialized_datum_get_internals_p(PG_GETARG_DATUM(0), &gbox, &flags, &type, &srid);
+		hasz = FLAGS_GET_Z(flags);
+		hasm = FLAGS_GET_M(flags);
+		if (res == LW_FAILURE)
+		{
+			lwgeom_out = lwgeom_construct_empty(LINETYPE, srid, hasz, hasm);
+		}
 	}
-	else
+
+	if (!lwgeom_out)
 	{
 		pa = ptarray_construct_empty(hasz, hasm, 2);
-		pt.x = gbox->xmin;
-		pt.y = gbox->ymin;
-		pt.z = gbox->zmin;
-		pt.m = gbox->mmin;
+		pt.x = gbox.xmin;
+		pt.y = gbox.ymin;
+		pt.z = gbox.zmin;
+		pt.m = gbox.mmin;
 		ptarray_append_point(pa, &pt, LW_TRUE);
-		pt.x = gbox->xmax;
-		pt.y = gbox->ymax;
-		pt.z = gbox->zmax;
-		pt.m = gbox->mmax;
+		pt.x = gbox.xmax;
+		pt.y = gbox.ymax;
+		pt.z = gbox.zmax;
+		pt.m = gbox.mmax;
 		ptarray_append_point(pa, &pt, LW_TRUE);
 		lwgeom_out = lwline_as_lwgeom(lwline_construct(srid, NULL, pa));
 	}
 
-	lwgeom_free(lwgeom_in);
-	PG_FREE_IF_COPY(geom_in, 0);
-
 	geom_out = geometry_serialize(lwgeom_out);
 	lwgeom_free(lwgeom_out);
 
diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c
index a303e50..e7fd51a 100644
--- a/postgis/lwgeom_geos.c
+++ b/postgis/lwgeom_geos.c
@@ -1509,8 +1509,9 @@ Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
 	GBOX *bbox2;
 	uint8_t type;
 	int32_t srid;
+	lwflags_t flags;
 
-	if (!gserialized_datum_get_internals_p(PG_GETARG_DATUM(geom_idx), &bbox1, &type, &srid))
+	if (!gserialized_datum_get_internals_p(PG_GETARG_DATUM(geom_idx), &bbox1, &flags, &type, &srid))
 	{
 		/* empty clips to empty, no matter rect */
 		PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
diff --git a/regress/core/lwgeom_regress.sql b/regress/core/lwgeom_regress.sql
index e95818d..c31487c 100644
--- a/regress/core/lwgeom_regress.sql
+++ b/regress/core/lwgeom_regress.sql
@@ -130,24 +130,30 @@ SELECT '#2902', replace(ST_Summary(PostGIS_GEOS_Noop(
 
 -- ST_BoundingDiagonal
 
-SELECT 'BoundingDiagonal1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
-    'SRID=4326;POINT(1e+15 1e+15)'::geometry
-)));
-SELECT 'BoundingDiagonal2', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
-    'SRID=4326;POINT(1e+15 1e+15)'::geometry
-), true));
-SELECT 'BoundingDiagonal3', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
-    'SRID=4326;POINT(1e+15 1e+15)'::geometry
-), false));
-SELECT 'BoundingDiagonal4', ST_AsEwkt(ST_BoundingDiagonal(
-    'SRID=3857;LINESTRING(1 2 3 4, 0 1 -8 2, -1 -2 -3 9)'::geometry
-));
-SELECT 'BoundingDiagonal5', ST_AsEwkt(ST_BoundingDiagonal(
-    'SRID=3857;LINESTRING M (5 4 0,4 4 1)'::geometry
-));
-SELECT 'BoundingDiagonal6', ST_AsEwkt(ST_BoundingDiagonal(
-    'SRID=3857;POLYGON M EMPTY'::geometry
-));
+SELECT 'BoundingDiagonal1  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=4326;POINT(1e+15 1e+15)'::geometry));
+SELECT 'BoundingDiagonal1.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=4326;POINT(1e+15 1e+15)'::geometry)));
+
+SELECT 'BoundingDiagonal2  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=4326;POINT(1e+15 1e+15)'::geometry, true));
+SELECT 'BoundingDiagonal2.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=4326;POINT(1e+15 1e+15)'::geometry), true));
+
+SELECT 'BoundingDiagonal3  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=4326;POINT(1e+15 1e+15)'::geometry, false));
+SELECT 'BoundingDiagonal3.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=4326;POINT(1e+15 1e+15)'::geometry), false));
+
+SELECT 'BoundingDiagonal4  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;LINESTRING(1 2 3 4, 0 1 -8 2, -1 -2 -3 9)'::geometry));
+SELECT 'BoundingDiagonal4.1', ST_AsEwkt(postgis_addbbox(ST_BoundingDiagonal('SRID=3857;LINESTRING(1 2 3 4, 0 1 -8 2, -1 -2 -3 9)'::geometry)));
+
+SELECT 'BoundingDiagonal5  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;LINESTRING M (5 4 0,4 4 1)'::geometry));
+SELECT 'BoundingDiagonal5.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=3857;LINESTRING M (5 4 0,4 4 1)'::geometry)));
+SELECT 'BoundingDiagonal5.2', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;LINESTRING Z (5 4 0,4 4 1)'::geometry));
+SELECT 'BoundingDiagonal5.3', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=3857;LINESTRING Z (5 4 0,4 4 1)'::geometry)));
+
+SELECT 'BoundingDiagonal6  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;POLYGON M EMPTY'::geometry));
+SELECT 'BoundingDiagonal6.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=3857;POLYGON M EMPTY'::geometry)));
+
+SELECT 'BoundingDiagonal7  ', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;MULTILINESTRING M ((5 4 0,4 4 1))'::geometry));
+SELECT 'BoundingDiagonal7.1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=3857;MULTILINESTRING M ((5 4 0,4 4 1))'::geometry)));
+SELECT 'BoundingDiagonal7.2', ST_AsEwkt(ST_BoundingDiagonal('SRID=3857;MULTILINESTRING Z ((5 4 0,4 4 1))'::geometry));
+SELECT 'BoundingDiagonal7.3', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox('SRID=3857;MULTILINESTRING Z ((5 4 0,4 4 1))'::geometry)));
 
 --- ST_Azimuth
 SELECT 'ST_Azimuth_regular' , round(ST_Azimuth(geom1,geom2)::numeric,4)
diff --git a/regress/core/lwgeom_regress_expected b/regress/core/lwgeom_regress_expected
index 8f1954b..dc3a70e 100644
--- a/regress/core/lwgeom_regress_expected
+++ b/regress/core/lwgeom_regress_expected
@@ -24,12 +24,24 @@ BOX3D(0 0.1 -55,11 12 12)
 #3069|BOX(1 1,1 1)
 #3069|BOX(0 0,1 1)
 #2902|GeometryCollection[ZBS] with 3 elements:   Polygon[ZS] with 1 ring:    ring 0 has 5 points   Point[ZS]   MultiLineString[ZS] with 1 element:     LineString[ZS] with 2 points
-BoundingDiagonal1|SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
-BoundingDiagonal2|SRID=4326;LINESTRING(1e+15 1e+15,1e+15 1e+15)
-BoundingDiagonal3|SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
-BoundingDiagonal4|SRID=3857;LINESTRING(-1 -2 -8 2,1 2 3 9)
-BoundingDiagonal5|SRID=3857;LINESTRINGM(4 4 0,5 4 1)
-BoundingDiagonal6|SRID=3857;LINESTRINGM EMPTY
+BoundingDiagonal1  |SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
+BoundingDiagonal1.1|SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
+BoundingDiagonal2  |SRID=4326;LINESTRING(1e+15 1e+15,1e+15 1e+15)
+BoundingDiagonal2.1|SRID=4326;LINESTRING(1e+15 1e+15,1e+15 1e+15)
+BoundingDiagonal3  |SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
+BoundingDiagonal3.1|SRID=4326;LINESTRING(999999986991104 999999986991104,1.000000054099968e+15 1.000000054099968e+15)
+BoundingDiagonal4  |SRID=3857;LINESTRING(-1 -2 -8 2,1 2 3 9)
+BoundingDiagonal4.1|SRID=3857;LINESTRING(-1 -2 -8 2,1 2 3 9)
+BoundingDiagonal5  |SRID=3857;LINESTRINGM(4 4 0,5 4 1)
+BoundingDiagonal5.1|SRID=3857;LINESTRINGM(4 4 0,5 4 1)
+BoundingDiagonal5.2|SRID=3857;LINESTRING(4 4 0,5 4 1)
+BoundingDiagonal5.3|SRID=3857;LINESTRING(4 4 0,5 4 1)
+BoundingDiagonal6  |SRID=3857;LINESTRINGM EMPTY
+BoundingDiagonal6.1|SRID=3857;LINESTRINGM EMPTY
+BoundingDiagonal7  |SRID=3857;LINESTRINGM(4 4 0,5 4 1)
+BoundingDiagonal7.1|SRID=3857;LINESTRINGM(4 4 0,5 4 1)
+BoundingDiagonal7.2|SRID=3857;LINESTRING(4 4 0,5 4 1)
+BoundingDiagonal7.3|SRID=3857;LINESTRING(4 4 0,5 4 1)
 ST_Azimuth_regular|2.3562
 ST_Azimuth_same_point|
 ERROR:  Operation on mixed SRID geometries

commit 5a8548cef1237bdffd9f65edba48b34970af4e23
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 16:24:46 2020 +0200

    Reduce the overhead of reading multiple values from the headers

diff --git a/libpgcommon/gserialized_gist.c b/libpgcommon/gserialized_gist.c
index 89a391d..41db342 100644
--- a/libpgcommon/gserialized_gist.c
+++ b/libpgcommon/gserialized_gist.c
@@ -70,12 +70,6 @@ GIDX* gidx_new(int ndims)
 	return g;
 }
 
-static lwflags_t
-gserialized_datum_get_flags(Datum gsdatum)
-{
-	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
-	return gserialized_get_lwflags(gpart);
-}
 
 /* Convert a double-based GBOX into a float-based GIDX,
    ensuring the float box is larger than the double box */
@@ -145,36 +139,6 @@ void gbox_from_gidx(GIDX *a, GBOX *gbox, int flags)
 
 
 /**
-* Given a #GSERIALIZED datum, as quickly as possible (peaking into the top
-* of the memory) return the gbox extents. Does not deserialize the geometry,
-* but <em>WARNING</em> returns a slightly larger bounding box than actually
-* encompasses the objects. For geography objects returns geocentric bounding
-* box, for geometry objects returns cartesian bounding box.
-*/
-int
-gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
-{
-	char gboxmem[GIDX_MAX_SIZE];
-	GIDX *gidx = (GIDX*)gboxmem;
-
-	if( LW_FAILURE == gserialized_datum_get_gidx_p(gsdatum, gidx) )
-		return LW_FAILURE;
-
-	gbox->flags = gserialized_datum_get_flags(gsdatum);
-	gbox_from_gidx(gidx, gbox, gbox->flags);
-
-	return LW_SUCCESS;
-}
-
-void
-gserialized_datum_get_type_and_srid_p(Datum gsdatum, uint8_t *type, int32_t *srid)
-{
-	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
-	*type = gserialized_get_type(gpart);
-	*srid = gserialized_get_srid(gpart);
-}
-
-/**
 * Peak into a #GSERIALIZED datum to find the bounding box. If the
 * box is there, copy it out and return it. If not, calculate the box from the
 * full object and return the box based on that. If no box is available,
diff --git a/libpgcommon/gserialized_gist.h b/libpgcommon/gserialized_gist.h
index 91a961b..b3e0ca7 100644
--- a/libpgcommon/gserialized_gist.h
+++ b/libpgcommon/gserialized_gist.h
@@ -100,8 +100,9 @@ int box2df_to_gbox_p(BOX2DF *a, GBOX *box);
 ** Fast functions for pulling boxes out of serializations.
 */
 
-/* Pull out the #GIDX bounding box with a absolute minimum system overhead */
+/* Pull out the #GIDX bounding box and flags with a absolute minimum system overhead */
 int gserialized_datum_get_gidx_p(Datum gserialized_datum, GIDX *gidx);
+int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
 
 bool box2df_contains(const BOX2DF *a, const BOX2DF *b);
 void box2df_set_empty(BOX2DF *a);
@@ -123,4 +124,3 @@ void gidx_set_unknown(GIDX *a);
 bool gidx_overlaps(GIDX *a, GIDX *b);
 bool gidx_equals(GIDX *a, GIDX *b);
 bool gidx_contains(GIDX *a, GIDX *b);
-int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h
index 032678d..8908d9b 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -185,11 +185,7 @@ void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const i
 * Fails on empty.
 */
 int gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox);
-
-/**
- * Pull the type and srid of a datum (containing a GSERIALIZEDs)
- */
-void gserialized_datum_get_type_and_srid_p(Datum gsdatum, uint8_t *type, int32_t *srid);
+int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, uint8_t *type, int32_t *srid);
 
 /* PG-exposed */
 Datum BOX2D_same(PG_FUNCTION_ARGS);
diff --git a/postgis/gserialized_gist_2d.c b/postgis/gserialized_gist_2d.c
index e5b2c27..5193b27 100644
--- a/postgis/gserialized_gist_2d.c
+++ b/postgis/gserialized_gist_2d.c
@@ -450,21 +450,17 @@ static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
 	return FLT_MAX;
 }
 
-
 /**
-* Peak into a #GSERIALIZED datum to find the bounding box. If the
-* box is there, copy it out and return it. If not, calculate the box from the
-* full object and return the box based on that. If no box is available,
-* return #LW_FAILURE, otherwise #LW_SUCCESS.
-*/
+ * Peak into a #GSERIALIZED datum to find its bounding box and some other metadata. If the box is there, copy it out and
+ * return it. If not, calculate the box from the full object and return the box based on that. If no box is available,
+ * return #LW_FAILURE, otherwise #LW_SUCCESS.
+ */
 int
-gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
+gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, uint8_t *type, int32_t *srid)
 {
 	GSERIALIZED *gpart;
 	int result = LW_SUCCESS;
 
-	POSTGIS_DEBUG(4, "entered function");
-
 	/*
 	** Because geometry is declared as "storage = main" anything large
 	** enough to take serious advantage of PG_DETOAST_DATUM_SLICE will have
@@ -476,50 +472,48 @@ gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
 	** which makes slicing worthwhile.
 	*/
 	gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
-
-	POSTGIS_DEBUGF(4, "got flags %d", gpart->gflags);
-
-	/* Do we even have a serialized bounding box? */
-	if (gserialized_has_bbox(gpart))
+	if (!gserialized_has_bbox(gpart) && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
 	{
-		/* Yes! Copy it out into the box! */
-		size_t box_ndims;
-		const float *f = gserialized_get_float_box_p(gpart, &box_ndims);
-
-		POSTGIS_DEBUG(4, "copying box out of serialization");
-		memcpy(box2df, f, sizeof(BOX2DF));
-		result = LW_SUCCESS;
-	}
-	else
-	{
-		/* No, we need to calculate it from the full object. */
-		GBOX gbox;
-		gbox_init(&gbox);
-
-		/* If we haven't, read the whole gserialized object */
-		if (LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
-		{
-			POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
-			gpart = (GSERIALIZED *)PG_DETOAST_DATUM(gsdatum);
-		}
-
-		result = gserialized_get_gbox_p(gpart, &gbox);
-		if ( result == LW_SUCCESS )
-		{
-			result = box2df_from_gbox_p(&gbox, box2df);
-		}
-		else
-		{
-			POSTGIS_DEBUG(4, "could not calculate bbox");
-		}
+		/* The headers don't contain a bbox and there is the object is larger than what we retrieved, so
+		 * we now detoast it completely */
+		POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
+		gpart = (GSERIALIZED *)PG_DETOAST_DATUM(gsdatum);
 	}
 
+	result = gserialized_get_gbox_p(gpart, gbox);
 	POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
-	POSTGIS_DEBUGF(4, "result = %d, got box2df %s", result, result == LW_SUCCESS ? box2df_to_string(box2df) : "NONE");
+
+	*srid = gserialized_get_srid(gpart);
+	*type = gserialized_get_type(gpart);
 
 	return result;
 }
 
+/**
+ * Given a #GSERIALIZED datum, as quickly as possible (peaking into the top
+ * of the memory) return the gbox extents. Does not deserialize the geometry,
+ * but <em>WARNING</em> returns a slightly larger bounding box than actually
+ * encompasses the objects. For geography objects returns geocentric bounding
+ * box, for geometry objects returns cartesian bounding box.
+ */
+int
+gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
+{
+	uint8_t type;
+	int32_t srid;
+
+	return gserialized_datum_get_internals_p(gsdatum, gbox, &type, &srid);
+}
+
+int
+gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
+{
+	GBOX gbox;
+	if (gserialized_datum_get_gbox_p(gsdatum, &gbox) == LW_FAILURE)
+		return LW_FAILURE;
+
+	return box2df_from_gbox_p(&gbox, box2df);
+}
 
 /**
 * Support function. Based on two datums return true if
diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c
index 9c328d7..a303e50 100644
--- a/postgis/lwgeom_geos.c
+++ b/postgis/lwgeom_geos.c
@@ -1507,8 +1507,10 @@ Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
 	LWGEOM *lwgeom1, *lwresult ;
 	GBOX bbox1 = {0};
 	GBOX *bbox2;
+	uint8_t type;
+	int32_t srid;
 
-	if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &bbox1))
+	if (!gserialized_datum_get_internals_p(PG_GETARG_DATUM(geom_idx), &bbox1, &type, &srid))
 	{
 		/* empty clips to empty, no matter rect */
 		PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
@@ -1527,9 +1529,6 @@ Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
 	/* If bbox1 outside of bbox2, return empty */
 	if (!gbox_overlaps_2d(&bbox1, bbox2))
 	{
-		uint8_t type;
-		int32_t srid;
-		gserialized_datum_get_type_and_srid_p(PG_GETARG_DATUM(geom_idx), &type, &srid);
 		/* Get type and srid from datum */
 		lwresult = lwgeom_construct_empty(type, srid, 0, 0);
 		result = geometry_serialize(lwresult) ;

commit 7b3effebd8b00be30c046c8d2291eccc28fbd7bc
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 14:36:16 2020 +0200

    Optimize ST_ClipByBox2d(compressed_geom, bbox) when the geom is fully outside the bbox

diff --git a/libpgcommon/gserialized_gist.c b/libpgcommon/gserialized_gist.c
index 4aad26e..89a391d 100644
--- a/libpgcommon/gserialized_gist.c
+++ b/libpgcommon/gserialized_gist.c
@@ -166,6 +166,13 @@ gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
 	return LW_SUCCESS;
 }
 
+void
+gserialized_datum_get_type_and_srid_p(Datum gsdatum, uint8_t *type, int32_t *srid)
+{
+	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	*type = gserialized_get_type(gpart);
+	*srid = gserialized_get_srid(gpart);
+}
 
 /**
 * Peak into a #GSERIALIZED datum to find the bounding box. If the
@@ -176,16 +183,7 @@ gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
 int
 gserialized_datum_get_gidx_p(Datum gsdatum, GIDX *gidx)
 {
-	GSERIALIZED *gpart;
-
-	POSTGIS_DEBUG(4, "entered function");
-
-	/*
-	** The most info we need is the 8 bytes of serialized header plus the 32 bytes
-	** of floats necessary to hold the 8 floats of the largest XYZM index
-	** bounding box, so 40 bytes.
-	*/
-	gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
 
 	/* Do we even have a serialized bounding box? */
 	if (gserialized_has_bbox(gpart))
diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h
index 64e35ae..032678d 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -186,6 +186,11 @@ void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const i
 */
 int gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox);
 
+/**
+ * Pull the type and srid of a datum (containing a GSERIALIZEDs)
+ */
+void gserialized_datum_get_type_and_srid_p(Datum gsdatum, uint8_t *type, int32_t *srid);
+
 /* PG-exposed */
 Datum BOX2D_same(PG_FUNCTION_ARGS);
 Datum BOX2D_overlap(PG_FUNCTION_ARGS);
diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c
index c8ac4ff..9c328d7 100644
--- a/postgis/lwgeom_geos.c
+++ b/postgis/lwgeom_geos.c
@@ -1524,17 +1524,20 @@ Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
 		PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
 	}
 
-	lwgeom1 = lwgeom_from_gserialized(PG_GETARG_GSERIALIZED_P(geom_idx));
 	/* If bbox1 outside of bbox2, return empty */
 	if (!gbox_overlaps_2d(&bbox1, bbox2))
 	{
+		uint8_t type;
+		int32_t srid;
+		gserialized_datum_get_type_and_srid_p(PG_GETARG_DATUM(geom_idx), &type, &srid);
 		/* Get type and srid from datum */
-		lwresult = lwgeom_construct_empty(lwgeom1->type, lwgeom1->srid, 0, 0);
+		lwresult = lwgeom_construct_empty(type, srid, 0, 0);
 		result = geometry_serialize(lwresult) ;
 		lwgeom_free(lwresult) ;
 		PG_RETURN_POINTER(result);
 	}
 
+	lwgeom1 = lwgeom_from_gserialized(PG_GETARG_GSERIALIZED_P(geom_idx));
 	lwresult = lwgeom_clip_by_rect(lwgeom1, bbox2->xmin, bbox2->ymin,
 	                               bbox2->xmax, bbox2->ymax);
 

commit 864294821174c073fb3492650ae496a75cbf6a60
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 13:07:54 2020 +0200

    Optimize ST_ClipByBox2d(compressed_geom, bbox) when the geom is contained in the bbox

diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c
index ee1d4a4..c8ac4ff 100644
--- a/postgis/lwgeom_geos.c
+++ b/postgis/lwgeom_geos.c
@@ -1501,55 +1501,49 @@ Datum ST_ClipByBox2d(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(ST_ClipByBox2d);
 Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
 {
-	GSERIALIZED *geom1;
+	static const uint32_t geom_idx = 0;
+	static const uint32_t box2d_idx = 1;
 	GSERIALIZED *result;
 	LWGEOM *lwgeom1, *lwresult ;
-	const GBOX *bbox1;
+	GBOX bbox1 = {0};
 	GBOX *bbox2;
 
-	geom1 = PG_GETARG_GSERIALIZED_P(0);
-	lwgeom1 = lwgeom_from_gserialized(geom1) ;
-
-	bbox1 = lwgeom_get_bbox(lwgeom1);
-	if ( ! bbox1 )
+	if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &bbox1))
 	{
 		/* empty clips to empty, no matter rect */
-		lwgeom_free(lwgeom1);
-		PG_RETURN_POINTER(geom1);
+		PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
 	}
 
 	/* WARNING: this is really a BOX2DF, use only xmin and ymin fields */
-	bbox2 = (GBOX *)PG_GETARG_POINTER(1);
+	bbox2 = (GBOX *)PG_GETARG_POINTER(box2d_idx);
 	bbox2->flags = 0;
 
+	/* if bbox1 is covered by bbox2, return lwgeom1 */
+	if (gbox_contains_2d(bbox2, &bbox1))
+	{
+		PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
+	}
+
+	lwgeom1 = lwgeom_from_gserialized(PG_GETARG_GSERIALIZED_P(geom_idx));
 	/* If bbox1 outside of bbox2, return empty */
-	if ( ! gbox_overlaps_2d(bbox1, bbox2) )
+	if (!gbox_overlaps_2d(&bbox1, bbox2))
 	{
+		/* Get type and srid from datum */
 		lwresult = lwgeom_construct_empty(lwgeom1->type, lwgeom1->srid, 0, 0);
-		lwgeom_free(lwgeom1);
-		PG_FREE_IF_COPY(geom1, 0);
 		result = geometry_serialize(lwresult) ;
 		lwgeom_free(lwresult) ;
 		PG_RETURN_POINTER(result);
 	}
 
-	/* if bbox1 is covered by bbox2, return lwgeom1 */
-	if ( gbox_contains_2d(bbox2, bbox1) )
-	{
-		lwgeom_free(lwgeom1);
-		PG_RETURN_POINTER(geom1);
-	}
-
 	lwresult = lwgeom_clip_by_rect(lwgeom1, bbox2->xmin, bbox2->ymin,
 	                               bbox2->xmax, bbox2->ymax);
 
 	lwgeom_free(lwgeom1);
-	PG_FREE_IF_COPY(geom1, 0);
 
-	if (!lwresult) PG_RETURN_NULL();
+	if (!lwresult)
+		PG_RETURN_NULL();
 
 	result = geometry_serialize(lwresult) ;
-	lwgeom_free(lwresult) ;
 	PG_RETURN_POINTER(result);
 }
 

commit 24252fb7f7651d0fa328f7f4acdad52af72c1d04
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 12:26:29 2020 +0200

    Speed up ST_CombineBbox(box2d, geometry) for compressed values

diff --git a/postgis/lwgeom_box.c b/postgis/lwgeom_box.c
index 45c66cb..98b39ed 100644
--- a/postgis/lwgeom_box.c
+++ b/postgis/lwgeom_box.c
@@ -417,46 +417,44 @@ Datum BOX2D_to_BOX3D(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(BOX2D_combine);
 Datum BOX2D_combine(PG_FUNCTION_ARGS)
 {
-	Pointer box2d_ptr = PG_GETARG_POINTER(0);
-	Pointer geom_ptr = PG_GETARG_POINTER(1);
+	static const uint32_t box2d_idx = 0;
+	static const uint32_t geom_idx = 1;
 	GBOX *a,*b;
-	GSERIALIZED *lwgeom;
 	GBOX box, *result;
 
-	if  ( (box2d_ptr == NULL) && (geom_ptr == NULL) )
+	if (PG_ARGISNULL(box2d_idx) && PG_ARGISNULL(geom_idx))
 	{
 		PG_RETURN_NULL(); /* combine_box2d(null,null) => null */
 	}
 
 	result = (GBOX *)palloc(sizeof(GBOX));
 
-	if (box2d_ptr == NULL)
+	if (PG_ARGISNULL(box2d_idx))
 	{
-		lwgeom = PG_GETARG_GSERIALIZED_P(1);
 		/* empty geom would make getbox2d_p return NULL */
-		if ( ! gserialized_get_gbox_p(lwgeom, &box) ) PG_RETURN_NULL();
+		if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &box))
+			PG_RETURN_NULL();
 		memcpy(result, &box, sizeof(GBOX));
 		PG_RETURN_POINTER(result);
 	}
 
 	/* combine_bbox(BOX3D, null) => BOX3D */
-	if (geom_ptr == NULL)
+	if (PG_ARGISNULL(geom_idx))
 	{
-		memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(GBOX));
+		memcpy(result, (char *)PG_GETARG_DATUM(box2d_idx), sizeof(GBOX));
 		PG_RETURN_POINTER(result);
 	}
 
 	/*combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol) */
 
-	lwgeom = PG_GETARG_GSERIALIZED_P(1);
-	if ( ! gserialized_get_gbox_p(lwgeom, &box) )
+	if (!gserialized_datum_get_gbox_p(PG_GETARG_DATUM(geom_idx), &box))
 	{
 		/* must be the empty geom */
-		memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(GBOX));
+		memcpy(result, (char *)PG_GETARG_DATUM(box2d_idx), sizeof(GBOX));
 		PG_RETURN_POINTER(result);
 	}
 
-	a = (GBOX *)PG_GETARG_DATUM(0);
+	a = (GBOX *)PG_GETARG_DATUM(box2d_idx);
 	b = &box;
 
 	result->xmax = Max(a->xmax, b->xmax);

commit bc11c9271266454dc93c84b40af6ef8eb2615b70
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 12:15:13 2020 +0200

    Speed up postgis_getbbox for compressed values

diff --git a/postgis/lwgeom_box.c b/postgis/lwgeom_box.c
index b9cab7d..45c66cb 100644
--- a/postgis/lwgeom_box.c
+++ b/postgis/lwgeom_box.c
@@ -153,17 +153,13 @@ Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOM_to_BOX2DF);
 Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS)
 {
-	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
 	GBOX gbox;
-
-	if ( gserialized_get_gbox_p(geom, &gbox) == LW_FAILURE )
+	if (gserialized_datum_get_gbox_p(PG_GETARG_DATUM(0), &gbox) == LW_FAILURE)
 		PG_RETURN_NULL();
 
 	/* Strip out higher dimensions */
 	FLAGS_SET_Z(gbox.flags, 0);
 	FLAGS_SET_M(gbox.flags, 0);
-
-	PG_FREE_IF_COPY(geom, 0);
 	PG_RETURN_POINTER(gbox_copy(&gbox));
 }
 

commit 465e203abc3603802b38b9943584625f62bf4dc9
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 12:03:27 2020 +0200

    Use gserialized_datum_get_gbox_p in _ST_PointOutside

diff --git a/postgis/geography_measurement.c b/postgis/geography_measurement.c
index 79a231b..771ebb6 100644
--- a/postgis/geography_measurement.c
+++ b/postgis/geography_measurement.c
@@ -676,19 +676,14 @@ PG_FUNCTION_INFO_V1(geography_point_outside);
 Datum geography_point_outside(PG_FUNCTION_ARGS)
 {
 	GBOX gbox;
-	GSERIALIZED *g = NULL;
-	GSERIALIZED *g_out = NULL;
 	LWGEOM *lwpoint = NULL;
 	POINT2D pt;
 
-	/* Get our geometry object loaded into memory. */
-	g = PG_GETARG_GSERIALIZED_P(0);
-
 	/* We need the bounding box to get an outside point for area algorithm */
-	if ( gserialized_get_gbox_p(g, &gbox) == LW_FAILURE )
+	if (gserialized_datum_get_gbox_p(PG_GETARG_DATUM(0), &gbox) == LW_FAILURE)
 	{
-		POSTGIS_DEBUG(4,"gserialized_get_gbox_p returned LW_FAILURE");
-		elog(ERROR, "Error in gserialized_get_gbox_p calculation.");
+		POSTGIS_DEBUG(4, "gserialized_datum_get_gbox_p returned LW_FAILURE");
+		elog(ERROR, "Error in gserialized_datum_get_gbox_p calculation.");
 		PG_RETURN_NULL();
 	}
 	POSTGIS_DEBUGF(4, "got gbox %s", gbox_to_string(&gbox));
@@ -698,11 +693,7 @@ Datum geography_point_outside(PG_FUNCTION_ARGS)
 
 	lwpoint = (LWGEOM*) lwpoint_make2d(4326, pt.x, pt.y);
 
-	g_out = geography_serialize(lwpoint);
-
-	PG_FREE_IF_COPY(g, 0);
-	PG_RETURN_POINTER(g_out);
-
+	PG_RETURN_POINTER(geography_serialize(lwpoint));
 }
 
 /*

commit 99c6135196fab1f6925553528a6569d6195be0df
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jul 21 11:25:12 2020 +0200

    Avoid detoasting the datum during ANALYZE

diff --git a/postgis/gserialized_estimate.c b/postgis/gserialized_estimate.c
index fa4700e..21b3ccc 100644
--- a/postgis/gserialized_estimate.c
+++ b/postgis/gserialized_estimate.c
@@ -66,6 +66,11 @@ dimensionality cases. (2D geometry) &&& (3D column), etc.
 #include "access/gist.h"
 #include "access/gist_private.h"
 #include "access/gistscan.h"
+#if PG_VERSION_NUM < 130000
+#include "access/tuptoaster.h" /* For toast_raw_datum_size */
+#else
+#include "access/detoast.h" /* For toast_raw_datum_size */
+#endif
 #include "utils/datum.h"
 #include "access/heapam.h"
 #include "catalog/index.h"
@@ -1435,11 +1440,9 @@ compute_gserialized_stats_mode(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfu
 	for ( i = 0; i < sample_rows; i++ )
 	{
 		Datum datum;
-		GSERIALIZED *geom;
 		GBOX gbox;
 		ND_BOX *nd_box;
 		bool is_null;
-		bool is_copy;
 
 		datum = fetchfunc(stats, i, &is_null);
 
@@ -1452,9 +1455,7 @@ compute_gserialized_stats_mode(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfu
 		}
 
 		/* Read the bounds from the gserialized. */
-		geom = (GSERIALIZED *)PG_DETOAST_DATUM(datum);
-		is_copy = VARATT_IS_EXTENDED(datum);
-		if ( LW_FAILURE == gserialized_get_gbox_p(geom, &gbox) )
+		if (LW_FAILURE == gserialized_datum_get_gbox_p(datum, &gbox))
 		{
 			/* Skip empties too. */
 			POSTGIS_DEBUGF(3, " skipped empty geometry %d", i);
@@ -1494,7 +1495,7 @@ compute_gserialized_stats_mode(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfu
 		nd_box_merge(nd_box, &sample_extent);
 
 		/* How many bytes does this sample use? */
-		total_width += VARSIZE(geom);
+		total_width += toast_raw_datum_size(datum);
 
 		/* Add bounds coordinates to sums for stddev calculation */
 		for ( d = 0; d < ndims; d++ )
@@ -1506,10 +1507,6 @@ compute_gserialized_stats_mode(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfu
 		/* Increment our "good feature" count */
 		notnull_cnt++;
 
-		/* Free up memory if our sample geometry was copied */
-		if ( is_copy )
-			pfree(geom);
-
 		/* Give backend a chance of interrupting us */
 		vacuum_delay_point();
 	}
diff --git a/regress/core/regress_selectivity.sql b/regress/core/regress_selectivity.sql
index 7094b81..b5a23b7 100644
--- a/regress/core/regress_selectivity.sql
+++ b/regress/core/regress_selectivity.sql
@@ -2154,6 +2154,8 @@ create table regular_overdots as
 -- Generate the stats
 analyze regular_overdots;
 
+Select * from pg_stats where tablename = 'regular_overdots' ORDER BY attname;
+
 -- Baseline info
 select 'selectivity_00', count(*) from regular_overdots;
 
diff --git a/regress/core/regress_selectivity_expected b/regress/core/regress_selectivity_expected
index 1ce2528..a399aed 100644
--- a/regress/core/regress_selectivity_expected
+++ b/regress/core/regress_selectivity_expected
@@ -2,6 +2,7 @@ ERROR:  stats for "no_stats.g" do not exist
 ERROR:  stats for "no_stats.g" do not exist
 ERROR:  stats for "no_stats.g" do not exist
 ERROR:  stats for "no_stats_join.g" do not exist
+public|regular_overdots|g|f|0|32|-1|||||||
 selectivity_00|2127
 selectivity_01|1068
 selectivity_02|actual|0.502

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                      |  5 ++
 libpgcommon/gserialized_gist.c            | 40 +--------------
 libpgcommon/gserialized_gist.h            |  4 +-
 libpgcommon/lwgeom_pg.h                   |  1 +
 postgis/geography.sql.in                  |  2 +-
 postgis/geography_measurement.c           | 17 ++-----
 postgis/gserialized_estimate.c            | 17 +++----
 postgis/gserialized_gist_2d.c             | 85 +++++++++++++++----------------
 postgis/lwgeom_box.c                      | 30 +++++------
 postgis/lwgeom_functions_basic.c          | 59 +++++++++++----------
 postgis/lwgeom_geos.c                     | 45 ++++++++--------
 postgis/postgis.sql.in                    |  4 +-
 regress/core/lwgeom_regress.sql           | 42 ++++++++-------
 regress/core/lwgeom_regress_expected      | 24 ++++++---
 regress/core/regress_selectivity.sql      |  2 +
 regress/core/regress_selectivity_expected |  1 +
 16 files changed, 174 insertions(+), 204 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list