[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha1-95-g3ced96f

git at osgeo.org git at osgeo.org
Fri May 1 02:30:43 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  3ced96fc1a79831a26c33311a17d1f32e3c5c732 (commit)
      from  b28cfb9b923d2190877065fc6dd47a1a6bd961bb (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 3ced96fc1a79831a26c33311a17d1f32e3c5c732
Author: Raúl Marín <git at rmr.ninja>
Date:   Fri May 1 11:09:36 2020 +0200

    Internal cache now persists until the end of the transaction
    
    Closes #4674

diff --git a/NEWS b/NEWS
index e79c549..9758de6 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,7 @@ PostGIS 3.1.0XXXX
 Only tickets not included in 3.1.0alpha1
 
 * Breaking changes *
-  -
+  - #4674, Internal cache now persists until the end of the transaction (Raúl Marín)
 
 * New features *
   - #4656, Cast a geojson_text::geometry for implicit GeoJSON ingestion (Raúl Marín)
diff --git a/libpgcommon/lwgeom_cache.c b/libpgcommon/lwgeom_cache.c
index b57e6f0..797fb66 100644
--- a/libpgcommon/lwgeom_cache.c
+++ b/libpgcommon/lwgeom_cache.c
@@ -11,7 +11,9 @@
  **********************************************************************/
 
 #include "postgres.h"
+#include "executor/spi.h"
 #include "fmgr.h"
+#include "utils/memutils.h"
 
 #include "../postgis_config.h"
 
@@ -56,13 +58,25 @@ typedef struct {
 } GenericCacheCollection;
 
 /**
-* Utility function to read the upper memory context off a function call
-* info data.
-*/
-static MemoryContext
-FIContext(FunctionCallInfo fcinfo)
+ * Utility function to read the upper memory context off a function call
+ * info data.
+ * This used to return flinfo->fn_mcxt (the function memory context) but that has the issue
+ * that is cleaned up once the function is finished, which on pure SQL functions (like ST_AsGML(geometry))
+ * is an issue as the cache will die after every _ST_AsGML call (thus being worthless).
+ * Instead we use CurTransactionContext which will live until the end of the transaction
+ */
+MemoryContext
+PostgisCacheContext(FunctionCallInfo fcinfo)
+{
+	return CurTransactionContext;
+}
+
+static GenericCacheCollection *internal_cache = NULL;
+
+static void
+PostgisResetInternalCache(void *v)
 {
-	return fcinfo->flinfo->fn_mcxt;
+	internal_cache = NULL;
 }
 
 /**
@@ -72,15 +86,19 @@ FIContext(FunctionCallInfo fcinfo)
 static GenericCacheCollection *
 GetGenericCacheCollection(FunctionCallInfo fcinfo)
 {
-	GenericCacheCollection* cache = fcinfo->flinfo->fn_extra;
-
-	if ( ! cache )
+	if (!internal_cache)
 	{
-		cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(GenericCacheCollection));
-		memset(cache, 0, sizeof(GenericCacheCollection));
-		fcinfo->flinfo->fn_extra = cache;
+		internal_cache = MemoryContextAlloc(PostgisCacheContext(fcinfo), sizeof(GenericCacheCollection));
+		memset(internal_cache, 0, sizeof(GenericCacheCollection));
+
+		MemoryContextCallback *cb =
+		    MemoryContextAlloc(PostgisCacheContext(fcinfo), sizeof(MemoryContextCallback));
+		cb->func = PostgisResetInternalCache;
+		cb->arg = NULL;
+		MemoryContextRegisterResetCallback(PostgisCacheContext(fcinfo), cb);
 	}
-	return cache;
+
+	return internal_cache;
 }
 
 
@@ -97,17 +115,16 @@ GetPROJSRSCache(FunctionCallInfo fcinfo)
 	if ( ! cache )
 	{
 		/* Allocate in the upper context */
-		cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(PROJPortalCache));
+		cache = MemoryContextAlloc(PostgisCacheContext(fcinfo), sizeof(PROJPortalCache));
 
 		if (cache)
 		{
 			POSTGIS_DEBUGF(3,
 				       "Allocating PROJCache for portal with transform() MemoryContext %p",
-				       FIContext(fcinfo));
+				       PostgisCacheContext(fcinfo));
 			memset(cache->PROJSRSCache, 0, sizeof(PROJSRSCacheItem) * PROJ_CACHE_ITEMS);
 			cache->type = PROJ_CACHE_ENTRY;
 			cache->PROJSRSCacheCount = 0;
-			cache->PROJSRSCacheContext = FIContext(fcinfo);
 
 			/* Store the pointer in GenericCache */
 			generic_cache->entry[PROJ_CACHE_ENTRY] = (GenericCache*)cache;
@@ -142,7 +159,7 @@ GetGeomCache(FunctionCallInfo fcinfo,
 
 	if ( ! cache )
 	{
-		old_context = MemoryContextSwitchTo(FIContext(fcinfo));
+		old_context = MemoryContextSwitchTo(PostgisCacheContext(fcinfo));
 		/* Allocate in the upper context */
 		cache = cache_methods->GeomCacheAllocator();
 		MemoryContextSwitchTo(old_context);
@@ -201,7 +218,7 @@ GetGeomCache(FunctionCallInfo fcinfo,
 
 		/* Save the tree and supporting geometry in the cache */
 		/* memory context */
-		old_context = MemoryContextSwitchTo(FIContext(fcinfo));
+		old_context = MemoryContextSwitchTo(PostgisCacheContext(fcinfo));
 		lwgeom = lwgeom_from_gserialized(geom);
 		cache->argnum = 0;
 
@@ -231,7 +248,7 @@ GetGeomCache(FunctionCallInfo fcinfo,
 	{
 		if ( cache->geom1 ) pfree(cache->geom1);
 		cache->geom1_size = VARSIZE(g1);
-		cache->geom1 = MemoryContextAlloc(FIContext(fcinfo), cache->geom1_size);
+		cache->geom1 = MemoryContextAlloc(PostgisCacheContext(fcinfo), cache->geom1_size);
 		memcpy(cache->geom1, g1, cache->geom1_size);
 	}
 	/* Argument two didn't match, so copy the new value in. */
@@ -239,7 +256,7 @@ GetGeomCache(FunctionCallInfo fcinfo,
 	{
 		if ( cache->geom2 ) pfree(cache->geom2);
 		cache->geom2_size = VARSIZE(g2);
-		cache->geom2 = MemoryContextAlloc(FIContext(fcinfo), cache->geom2_size);
+		cache->geom2 = MemoryContextAlloc(PostgisCacheContext(fcinfo), cache->geom2_size);
 		memcpy(cache->geom2, g2, cache->geom2_size);
 	}
 
@@ -256,7 +273,7 @@ ToastCacheGet(FunctionCallInfo fcinfo)
 	ToastCache* cache = (ToastCache*)(generic_cache->entry[entry_number]);
 	if (!cache)
 	{
-		cache = MemoryContextAllocZero(FIContext(fcinfo), sizeof(ToastCache));
+		cache = MemoryContextAllocZero(PostgisCacheContext(fcinfo), sizeof(ToastCache));
 		cache->type = entry_number;
 		generic_cache->entry[entry_number] = (GenericCache*)cache;
 	}
@@ -299,7 +316,7 @@ ToastCacheGetGeometry(FunctionCallInfo fcinfo, uint32_t argnum)
 			return arg->geom;
 
 		/* Take a copy into the upper context */
-		MemoryContext old_context = MemoryContextSwitchTo(FIContext(fcinfo));
+		MemoryContext old_context = MemoryContextSwitchTo(PostgisCacheContext(fcinfo));
 		arg->geom = (GSERIALIZED*)PG_DETOAST_DATUM_COPY(datum);
 		MemoryContextSwitchTo(old_context);
 		return arg->geom;
diff --git a/libpgcommon/lwgeom_cache.h b/libpgcommon/lwgeom_cache.h
index 745e178..4bdd310 100644
--- a/libpgcommon/lwgeom_cache.h
+++ b/libpgcommon/lwgeom_cache.h
@@ -30,6 +30,8 @@
 
 #define NUM_CACHE_ENTRIES 8
 
+/* Returns the MemoryContext used to store the caches */
+MemoryContext PostgisCacheContext(FunctionCallInfo fcinfo);
 
 /*
 * A generic GeomCache just needs space for the cache type,
diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index cacccd1..9c9601c 100644
--- a/libpgcommon/lwgeom_transform.c
+++ b/libpgcommon/lwgeom_transform.c
@@ -54,7 +54,8 @@ typedef struct {
 } PjStrs;
 
 /* Internal Cache API */
-static LWPROJ *AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
+static LWPROJ *
+AddToPROJSRSCache(FunctionCallInfo fcinfo, PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
 static void DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, uint32_t position);
 
 static void
@@ -345,7 +346,7 @@ GetProj4String(int32_t srid)
  * which is the definition for the other half of the transformation.
  */
 static LWPROJ *
-AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to)
+AddToPROJSRSCache(FunctionCallInfo fcinfo, PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to)
 {
 	MemoryContext oldContext;
 
@@ -363,7 +364,7 @@ AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to
 	if (!pjstrs_has_entry(&to_strs))
 		elog(ERROR, "got NULL for SRID (%d)", srid_to);
 
-	oldContext = MemoryContextSwitchTo(PROJCache->PROJSRSCacheContext);
+	oldContext = MemoryContextSwitchTo(PostgisCacheContext(fcinfo));
 
 #if POSTGIS_PROJ_VERSION < 60
 	PJ *projection = palloc(sizeof(PJ));
@@ -452,10 +453,10 @@ AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to
 
 	/* We register a new callback to delete the projection on exit */
 	MemoryContextCallback *callback =
-	    MemoryContextAlloc(PROJCache->PROJSRSCacheContext, sizeof(MemoryContextCallback));
+	    MemoryContextAlloc(PostgisCacheContext(fcinfo), sizeof(MemoryContextCallback));
 	callback->func = PROJSRSDestroyPJ;
 	callback->arg = (void *)projection;
-	MemoryContextRegisterResetCallback(PROJCache->PROJSRSCacheContext, callback);
+	MemoryContextRegisterResetCallback(PostgisCacheContext(fcinfo), callback);
 
 	PROJCache->PROJSRSCache[cache_position].srid_from = srid_from;
 	PROJCache->PROJSRSCache[cache_position].srid_to = srid_to;
@@ -502,7 +503,7 @@ GetPJUsingFCInfo(FunctionCallInfo fcinfo, int32_t srid_from, int32_t srid_to, LW
 	*pj = GetProjectionFromPROJCache(proj_cache, srid_from, srid_to);
 	if (*pj == NULL)
 	{
-		*pj = AddToPROJSRSCache(proj_cache, srid_from, srid_to);
+		*pj = AddToPROJSRSCache(fcinfo, proj_cache, srid_from, srid_to);
 	}
 
 	return pj != NULL;
diff --git a/libpgcommon/lwgeom_transform.h b/libpgcommon/lwgeom_transform.h
index 2d2cd2d..a8ecdb0 100644
--- a/libpgcommon/lwgeom_transform.h
+++ b/libpgcommon/lwgeom_transform.h
@@ -32,8 +32,6 @@ char *GetProj4String(int32_t srid);
  */
 typedef void *ProjCache ;
 
-bool IsInPROJCache(ProjCache cache, int32_t srid_from, int32_t srid_to);
-PJ *GetPJFromPROJCache(ProjCache cache, int32_t srid_from, int32_t srid_to);
 int GetPJUsingFCInfo(FunctionCallInfo fcinfo, int32_t srid_from, int32_t srid_to, LWPROJ **pj);
 int spheroid_init_from_srid(FunctionCallInfo fcinfo, int32_t srid, SPHEROID *s);
 void srid_check_latlong(FunctionCallInfo fcinfo, int32_t srid);

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

Summary of changes:
 NEWS                           |  2 +-
 libpgcommon/lwgeom_cache.c     | 61 +++++++++++++++++++++++++++---------------
 libpgcommon/lwgeom_cache.h     |  2 ++
 libpgcommon/lwgeom_transform.c | 13 ++++-----
 libpgcommon/lwgeom_transform.h |  2 --
 5 files changed, 49 insertions(+), 31 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list