[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