[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha2-152-g4c7c065

git at osgeo.org git at osgeo.org
Fri Nov 6 06:17:13 PST 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  4c7c06574de31f50397e128abbadabc38b8ca71e (commit)
       via  22d9f04fcff523d6100f543f4a12ff52ef890b23 (commit)
      from  5b2e3cbd52408a9870a9886e5896123e4ff86118 (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 4c7c06574de31f50397e128abbadabc38b8ca71e
Author: Raúl Marín <git at rmr.ninja>
Date:   Fri Oct 30 15:00:20 2020 +0100

    Be clever and only deserialize with copy when necessary
    
    Closes #4775
    Closes https://github.com/postgis/postgis/pull/586

diff --git a/libpgcommon/gserialized_gist.c b/libpgcommon/gserialized_gist.c
index 41db342..093ad50 100644
--- a/libpgcommon/gserialized_gist.c
+++ b/libpgcommon/gserialized_gist.c
@@ -147,7 +147,16 @@ void gbox_from_gidx(GIDX *a, GBOX *gbox, int flags)
 int
 gserialized_datum_get_gidx_p(Datum gsdatum, GIDX *gidx)
 {
-	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	GSERIALIZED *gpart = NULL;
+	int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((struct varlena *)gsdatum);
+	if (need_detoast)
+	{
+		gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	}
+	else
+	{
+		gpart = (GSERIALIZED *)gsdatum;
+	}
 
 	/* Do we even have a serialized bounding box? */
 	if (gserialized_has_bbox(gpart))
@@ -179,9 +188,9 @@ gserialized_datum_get_gidx_p(Datum gsdatum, GIDX *gidx)
 		/* No, we need to calculate it from the full object. */
 		LWGEOM *lwgeom;
 		GBOX gbox;
-		/* If we haven't, read the whole gserialized object */
-		if (LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
+		if (need_detoast && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
 		{
+			/* If we haven't, read the whole gserialized object */
 			POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
 			gpart = (GSERIALIZED *)PG_DETOAST_DATUM(gsdatum);
 		}
diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h
index fd692f1..96a6647 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -89,9 +89,12 @@ void pg_install_lwgeom_handlers(void);
 /* Argument handling macros */
 #define PG_GETARG_GSERIALIZED_P(varno) ((GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(varno)))
 #define PG_GETARG_GSERIALIZED_P_COPY(varno) ((GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(varno)))
-#define PG_GETARG_GSERIALIZED_P_SLICE(varno, start, size) ((GSERIALIZED *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(varno), start, size))
+#define PG_GSERIALIZED_DATUM_NEEDS_DETOAST(datum) \
+	(VARATT_IS_EXTENDED((datum)) || VARATT_IS_EXTERNAL((datum)) || VARATT_IS_COMPRESSED((datum)))
 #define PG_GETARG_GSERIALIZED_HEADER(varno) \
-	((GSERIALIZED *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(varno), 0, gserialized_max_header_size()))
+	PG_GSERIALIZED_DATUM_NEEDS_DETOAST(PG_GETARG_DATUM(varno)) \
+	? ((GSERIALIZED *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(varno), 0, gserialized_max_header_size())) \
+	: ((GSERIALIZED *)(PG_GETARG_DATUM(varno)))
 
 /* Debugging macros */
 #if POSTGIS_DEBUG_LEVEL > 0
diff --git a/postgis/gserialized_gist_2d.c b/postgis/gserialized_gist_2d.c
index 1c5a74c..198a4e9 100644
--- a/postgis/gserialized_gist_2d.c
+++ b/postgis/gserialized_gist_2d.c
@@ -458,21 +458,19 @@ static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
 int
 gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid)
 {
-	GSERIALIZED *gpart;
 	int result = LW_SUCCESS;
+	GSERIALIZED *gpart = NULL;
+	int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((struct varlena *)gsdatum);
+	if (need_detoast)
+	{
+		gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	}
+	else
+	{
+		gpart = (GSERIALIZED *)gsdatum;
+	}
 
-	/*
-	** Because geometry is declared as "storage = main" anything large
-	** enough to take serious advantage of PG_DETOAST_DATUM_SLICE will have
-	** already been compressed, which means the entire object will be
-	** fetched and decompressed before a slice is taken, thus removing
-	** any efficiencies gained from slicing.
-	** As of Pg12 we can partially decompress a toasted object
-	** (though we still need to fully retrieve it from TOAST)
-	** which makes slicing worthwhile.
-	*/
-	gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
-	if (!gserialized_has_bbox(gpart) && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
+	if (!gserialized_has_bbox(gpart) && need_detoast && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
 	{
 		/* The headers don't contain a bbox and the object is larger than what we retrieved, so
 		 * we now detoast it completely */
@@ -513,7 +511,16 @@ int
 gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
 {
 	int result = LW_SUCCESS;
-	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	GSERIALIZED *gpart = NULL;
+	int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((struct varlena *)gsdatum);
+	if (need_detoast)
+	{
+		gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+	}
+	else
+	{
+		gpart = (GSERIALIZED *)gsdatum;
+	}
 
 	if (gserialized_has_bbox(gpart))
 	{
@@ -525,7 +532,7 @@ gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
 	else
 	{
 		GBOX gbox = {0};
-		if (LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
+		if (need_detoast && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
 		{
 			/* The headers don't contain a bbox and the object is larger than what we retrieved, so
 			 * we now detoast it completely and recheck */

commit 22d9f04fcff523d6100f543f4a12ff52ef890b23
Author: Raúl Marín <git at rmr.ninja>
Date:   Fri Oct 23 16:21:05 2020 +0200

    Re-specialize gserialized_datum_get_box2df_p

diff --git a/postgis/gserialized_gist_2d.c b/postgis/gserialized_gist_2d.c
index 202ba25..1c5a74c 100644
--- a/postgis/gserialized_gist_2d.c
+++ b/postgis/gserialized_gist_2d.c
@@ -474,7 +474,7 @@ gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, u
 	gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
 	if (!gserialized_has_bbox(gpart) && LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
 	{
-		/* The headers don't contain a bbox and there is the object is larger than what we retrieved, so
+		/* The headers don't contain a bbox and 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);
@@ -506,14 +506,41 @@ gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
 	return gserialized_datum_get_internals_p(gsdatum, gbox, &flags, &type, &srid);
 }
 
+/* Note that this duplicates code from gserialized_datum_get_internals_p. It does so because
+ * accessing only the BOX2DF (as floats) is faster and this is a hot path function in indexes
+ */
 int
 gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
 {
-	GBOX gbox = {0};
-	if (gserialized_datum_get_gbox_p(gsdatum, &gbox) == LW_FAILURE)
-		return LW_FAILURE;
+	int result = LW_SUCCESS;
+	GSERIALIZED *gpart = (GSERIALIZED *)PG_DETOAST_DATUM_SLICE(gsdatum, 0, gserialized_max_header_size());
+
+	if (gserialized_has_bbox(gpart))
+	{
+		size_t box_ndims;
+		const float *f = gserialized_get_float_box_p(gpart, &box_ndims);
+		memcpy(box2df, f, sizeof(BOX2DF));
+		result = LW_SUCCESS;
+	}
+	else
+	{
+		GBOX gbox = {0};
+		if (LWSIZE_GET(gpart->size) >= gserialized_max_header_size())
+		{
+			/* The headers don't contain a bbox and the object is larger than what we retrieved, so
+			 * we now detoast it completely and recheck */
+			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);
+		}
+	}
 
-	return box2df_from_gbox_p(&gbox, box2df);
+	POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
+	return result;
 }
 
 /**

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

Summary of changes:
 libpgcommon/gserialized_gist.c | 15 +++++++--
 libpgcommon/lwgeom_pg.h        |  7 +++--
 postgis/gserialized_gist_2d.c  | 70 +++++++++++++++++++++++++++++++-----------
 3 files changed, 69 insertions(+), 23 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list