[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha1-98-g07ca520

git at osgeo.org git at osgeo.org
Fri May 1 07:50:30 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  07ca520a78c4c12fe94c5f0541887b4a15eeca16 (commit)
       via  d427c87f27da94a67f98d4a256ed4854baa59eaa (commit)
       via  b38079d4f1fac448c2a23681034521464d743cb6 (commit)
      from  3ced96fc1a79831a26c33311a17d1f32e3c5c732 (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 07ca520a78c4c12fe94c5f0541887b4a15eeca16
Author: Raúl Marín <git at rmr.ninja>
Date:   Fri May 1 12:18:09 2020 +0200

    Cache getSRIDbySRS
    
    Closes #4672
    Closes https://github.com/postgis/postgis/pull/557

diff --git a/NEWS b/NEWS
index 9758de6..4edb5b1 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Only tickets not included in 3.1.0alpha1
   - #4651: ST_Simplify: Don't copy if nothing is removed (Raúl Marín)
   - #4657: Avoid De-TOASTing where possible (Paul Ramsey)
   - #4490, Tweak function costs (Raúl Marín)
+  - #4672, Cache getSRSbySRID and getSRIDbySRS (Raúl Marín)
 
 * Bug fixes *
   - #4652, Fix several memory related bugs in ST_GeomFromGML (Raúl Marín)
diff --git a/libpgcommon/lwgeom_cache.c b/libpgcommon/lwgeom_cache.c
index 33e2371..d505021 100644
--- a/libpgcommon/lwgeom_cache.c
+++ b/libpgcommon/lwgeom_cache.c
@@ -11,6 +11,8 @@
  **********************************************************************/
 
 #include "postgres.h"
+
+#include "catalog/pg_type.h" /* for CSTRINGOID */
 #include "executor/spi.h"
 #include "fmgr.h"
 #include "utils/memutils.h"
@@ -438,4 +440,108 @@ GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
 		arg->srs = getSRSbySRID(fcinfo, srid, short_crs);
 	}
 	return arg->srs;
+}
+
+/*
+ * Retrieve an SRID from a given SRS
+ * Require valid spatial_ref_sys table entry
+ *
+ */
+static int32_t
+getSRIDbySRS(FunctionCallInfo fcinfo, const char *srs)
+{
+	static const int16_t max_query_size = 512;
+	char query[512];
+	Oid argtypes[] = {CSTRINGOID};
+	Datum values[] = {CStringGetDatum(srs)};
+	int32_t srid, err;
+
+	postgis_initialize_cache(fcinfo);
+	snprintf(query,
+		 max_query_size,
+		 "SELECT srid "
+		 "FROM %s, "
+		 "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
+		 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
+		 postgis_spatial_ref_sys());
+
+	if (!srs)
+		return 0;
+
+	if (SPI_OK_CONNECT != SPI_connect())
+	{
+		elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
+		return 0;
+	}
+
+	err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
+	if (err < 0)
+	{
+		elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
+		SPI_finish();
+		return 0;
+	}
+
+	/* no entry in spatial_ref_sys */
+	if (SPI_processed <= 0)
+	{
+		snprintf(query,
+			 max_query_size,
+			 "SELECT srid "
+			 "FROM %s, "
+			 "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
+			 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
+			 postgis_spatial_ref_sys());
+
+		err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
+		if (err < 0)
+		{
+			elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
+			SPI_finish();
+			return 0;
+		}
+
+		if (SPI_processed <= 0)
+		{
+			SPI_finish();
+			return 0;
+		}
+	}
+
+	srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));
+	SPI_finish();
+
+	return srid;
+}
+
+static inline SRIDCache *
+SRIDCacheGet(FunctionCallInfo fcinfo)
+{
+	const uint32_t entry_number = SRID_CACHE_ENTRY;
+	GenericCacheCollection *generic_cache = GetGenericCacheCollection(fcinfo);
+	SRIDCache *cache = (SRIDCache *)(generic_cache->entry[entry_number]);
+	if (!cache)
+	{
+		cache = MemoryContextAllocZero(PostgisCacheContext(fcinfo), sizeof(SRIDCache));
+		cache->type = entry_number;
+		generic_cache->entry[entry_number] = (GenericCache *)cache;
+	}
+	return cache;
+}
+
+int32_t
+GetSRIDCacheBySRS(FunctionCallInfo fcinfo, const char *srs)
+{
+	SRIDCache *cache = SRIDCacheGet(fcinfo);
+	SRIDCacheArgument *arg = &(cache->arg[0]);
+
+	if (!arg->srid || strcmp(srs, arg->srs) != 0)
+	{
+		size_t size = strlen(srs) + 1;
+		arg->srid = getSRIDbySRS(fcinfo, srs);
+		arg->srs = MemoryContextAlloc(PostgisCacheContext(fcinfo), size);
+		memcpy(arg->srs, srs, size);
+	}
+
+	return arg->srid;
 }
\ No newline at end of file
diff --git a/libpgcommon/lwgeom_cache.h b/libpgcommon/lwgeom_cache.h
index 77ab5bd..825701e 100644
--- a/libpgcommon/lwgeom_cache.h
+++ b/libpgcommon/lwgeom_cache.h
@@ -28,6 +28,7 @@
 #define RECT_CACHE_ENTRY 4
 #define TOAST_CACHE_ENTRY 5
 #define SRSDESC_CACHE_ENTRY 6
+#define SRID_CACHE_ENTRY 7
 
 #define NUM_CACHE_ENTRIES 8
 
@@ -149,4 +150,19 @@ typedef struct {
 
 const char *GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs);
 
+/******************************************************************************/
+
+#define SRIDCacheSize 1
+typedef struct {
+	char *srs;
+	int32_t srid;
+} SRIDCacheArgument;
+
+typedef struct {
+	int type;
+	SRIDCacheArgument arg[SRIDCacheSize];
+} SRIDCache;
+
+int32_t GetSRIDCacheBySRS(FunctionCallInfo fcinfo, const char *srs);
+
 #endif /* LWGEOM_CACHE_H_ */
diff --git a/postgis/geography_inout.c b/postgis/geography_inout.c
index 44dec05..2e899ac 100644
--- a/postgis/geography_inout.c
+++ b/postgis/geography_inout.c
@@ -42,7 +42,6 @@
 #include "lwgeom_cache.h"
 #include "lwgeom_pg.h"       /* For debugging macros. */
 #include "geography.h"	     /* For utility functions. */
-#include "lwgeom_export.h"   /* For export functions. */
 #include "lwgeom_transform.h"
 
 Datum geography_in(PG_FUNCTION_ARGS);
diff --git a/postgis/gserialized_typmod.c b/postgis/gserialized_typmod.c
index ef1eb79..50bedac 100644
--- a/postgis/gserialized_typmod.c
+++ b/postgis/gserialized_typmod.c
@@ -41,7 +41,6 @@
 #include "liblwgeom.h"         /* For standard geometry types. */
 #include "lwgeom_pg.h"       /* For debugging macros. */
 #include "geography.h"	     /* For utility functions. */
-#include "lwgeom_export.h"   /* For export functions. */
 #include "lwgeom_transform.h" /* for srid_is_latlon */
 
 
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index 7a71f51..572be45 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -31,7 +31,6 @@
 #include "float.h" /* for DBL_DIG */
 
 #include "postgres.h"
-#include "catalog/pg_type.h" /* for CSTRINGOID */
 #include "executor/spi.h"
 #include "utils/builtins.h"
 #include "utils/jsonb.h"
@@ -40,7 +39,6 @@
 #include "lwgeom_cache.h"
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
-#include "lwgeom_export.h"
 
 Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
 Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);
@@ -51,78 +49,6 @@ Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
 Datum geometry_to_json(PG_FUNCTION_ARGS);
 Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
 
-/*
-* Retrieve an SRID from a given SRS
-* Require valid spatial_ref_sys table entry
-*
-*/
-int
-getSRIDbySRS(FunctionCallInfo fcinfo, const char *srs)
-{
-	static const int16_t max_query_size = 512;
-	char query[512];
-	Oid argtypes[] = {CSTRINGOID};
-	Datum values[] = {CStringGetDatum(srs)};
-	int32_t srid, err;
-
-	postgis_initialize_cache(fcinfo);
-	snprintf(query,
-		 max_query_size,
-		 "SELECT srid "
-		 "FROM %s, "
-		 "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
-		 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
-		 postgis_spatial_ref_sys());
-
-	if (!srs) return 0;
-
-	if (SPI_OK_CONNECT != SPI_connect())
-	{
-		elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
-		return 0;
-	}
-
-	err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
-	if (err < 0)
-	{
-		elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
-		SPI_finish();
-		return 0;
-	}
-
-	/* no entry in spatial_ref_sys */
-	if (SPI_processed <= 0)
-	{
-		snprintf(query,
-			 max_query_size,
-			 "SELECT srid "
-			 "FROM %s, "
-			 "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
-			 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
-			 postgis_spatial_ref_sys());
-
-		err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
-		if (err < 0)
-		{
-			elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
-			SPI_finish();
-			return 0;
-		}
-
-		if (SPI_processed <= 0)
-		{
-			SPI_finish();
-			return 0;
-		}
-	}
-
-	srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));
-	SPI_finish();
-
-	return srid;
-}
-
-
 /**
  * Encode feature in GML
  */
diff --git a/postgis/lwgeom_export.h b/postgis/lwgeom_export.h
deleted file mode 100644
index cd803e4..0000000
--- a/postgis/lwgeom_export.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/**********************************************************************
- *
- * 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 2009 Olivier Courtin <olivier.courtin at oslandia.com>
- *
- **********************************************************************/
-
-int getSRIDbySRS(FunctionCallInfo fcinfo, const char *SRS);
diff --git a/postgis/lwgeom_in_geohash.c b/postgis/lwgeom_in_geohash.c
index f95afd6..3f7c4ad 100644
--- a/postgis/lwgeom_in_geohash.c
+++ b/postgis/lwgeom_in_geohash.c
@@ -42,7 +42,6 @@ static void geohash_lwpgerror(char *msg, __attribute__((__unused__)) int error_c
 	lwpgerror("%s", msg);
 }
 
-#include "lwgeom_export.h"
 
 static GBOX*
 parse_geohash(char *geohash, int precision)
diff --git a/postgis/lwgeom_in_geojson.c b/postgis/lwgeom_in_geojson.c
index 58cef93..f5bd9b5 100644
--- a/postgis/lwgeom_in_geojson.c
+++ b/postgis/lwgeom_in_geojson.c
@@ -30,7 +30,7 @@
 #include "../postgis_config.h"
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
-#include "lwgeom_export.h"
+#include "lwgeom_cache.h"
 
 #if defined(HAVE_LIBJSON)
 
@@ -110,7 +110,7 @@ Datum geom_from_geojson(PG_FUNCTION_ARGS)
 
 	if (srs)
 	{
-		srid = getSRIDbySRS(fcinfo, srs);
+		srid = GetSRIDCacheBySRS(fcinfo, srs);
 		lwfree(srs);
 	}
 
diff --git a/postgis/lwgeom_inout.c b/postgis/lwgeom_inout.c
index 5a1ae15..0757de0 100644
--- a/postgis/lwgeom_inout.c
+++ b/postgis/lwgeom_inout.c
@@ -45,7 +45,7 @@
 #include "funcapi.h"
 
 #include "liblwgeom.h"
-#include "lwgeom_export.h"
+#include "lwgeom_cache.h"
 #include "lwgeom_pg.h"
 #include "geography.h" /* for lwgeom_valid_typmod */
 #include "lwgeom_transform.h"
@@ -147,7 +147,7 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS)
 		lwgeom = lwgeom_from_geojson(str, &srs);
 		if (srs)
 		{
-			srid = getSRIDbySRS(fcinfo, srs);
+			srid = GetSRIDCacheBySRS(fcinfo, srs);
 			lwfree(srs);
 			lwgeom_set_srid(lwgeom, srid);
 		}

commit d427c87f27da94a67f98d4a256ed4854baa59eaa
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Apr 28 19:54:21 2020 +0200

    ST_AsX3D: Stop calculating the srs
    
    It was never used and amounted to 90% of the time

diff --git a/liblwgeom/cunit/cu_out_x3d.c b/liblwgeom/cunit/cu_out_x3d.c
index 3e10d35..a7f6893 100644
--- a/liblwgeom/cunit/cu_out_x3d.c
+++ b/liblwgeom/cunit/cu_out_x3d.c
@@ -17,10 +17,10 @@
 #include "liblwgeom_internal.h"
 #include "cu_tester.h"
 
-static void do_x3d3_test(char * in, char * out, char * srs, int precision, int option)
+static void do_x3d3_test(char * in, char * out, int precision, int option)
 {
 	LWGEOM *g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE);
-	lwvarlena_t *v = lwgeom_to_x3d3(g, srs, precision, option, "");
+	lwvarlena_t *v = lwgeom_to_x3d3(g, precision, option, "");
 
 	ASSERT_VARLENA_EQUAL(v, out);
 
@@ -32,7 +32,7 @@ static void do_x3d3_test(char * in, char * out, char * srs, int precision, int o
 static void do_x3d3_unsupported(char * in, char * out)
 {
 	LWGEOM *g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE);
-	lwvarlena_t *v = lwgeom_to_x3d3(g, NULL, 0, 0, "");
+	lwvarlena_t *v = lwgeom_to_x3d3(g, 0, 0, "");
 
 	ASSERT_STRING_EQUAL(out, cu_error_msg);
 	cu_error_msg_reset();
@@ -48,23 +48,23 @@ static void out_x3d3_test_precision(void)
 	do_x3d3_test(
 	    "POINT(1.1111111111111 1.1111111111111 2.11111111111111)",
 	    "1 1 2",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* 3 digits precision */
 	do_x3d3_test(
 	    "POINT(1.1111111111111 1.1111111111111 2.11111111111111)",
 	    "1.111 1.111 2.111",
-	    NULL, 3, 0);
+	    3, 0);
 
 	/* 9 digits precision */
 	do_x3d3_test(
 	    "POINT(1.2345678901234 1.2345678901234 4.123456789001)",
 	    "1.23456789 1.23456789 4.123456789",
-	    NULL, 9, 0);
+	    9, 0);
 
 	/* huge data */
 	do_x3d3_test(
-	    "POINT(1E300 -105E-153 4E300)", "1e+300 0 4e+300", NULL, 0, 0);
+	    "POINT(1E300 -105E-153 4E300)", "1e+300 0 4e+300", 0, 0);
 }
 
 
@@ -74,13 +74,13 @@ static void out_x3d3_test_geoms(void)
 	do_x3d3_test(
 	    "LINESTRING(0 1 5,2 3 6,4 5 7)",
 	    "<LineSet  vertexCount='3'><Coordinate point='0 1 5 2 3 6 4 5 7' /></LineSet>",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* Polygon **/
 	do_x3d3_test(
 	    "POLYGON((15 10 3,13.536 6.464 3,10 5 3,6.464 6.464 3,5 10 3,6.464 13.536 3,10 15 3,13.536 13.536 3,15 10 3))",
 	    "<IndexedFaceSet  convex='false' coordIndex='0 1 2 3 4 5 6 7'><Coordinate point='15 10 3 13.536 6.464 3 10 5 3 6.464 6.464 3 5 10 3 6.464 13.536 3 10 15 3 13.536 13.536 3 ' /></IndexedFaceSet>",
-	    NULL, 3, 0);
+	    3, 0);
 
 	/* TODO: Polygon - with internal ring - the answer is clearly wrong */
 	/** do_x3d3_test(
@@ -92,30 +92,30 @@ static void out_x3d3_test_geoms(void)
 	do_x3d3_test(
 	    "MULTIPOINT(0 1,2 3,4 5)",
 	    "<Polypoint2D  point='0 1 2 3 4 5 ' />",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* 3D MultiPoint */
 	do_x3d3_test(
 	    "MULTIPOINT Z(0 1 1,2 3 4,4 5 5)",
 	    "<PointSet ><Coordinate point='0 1 1 2 3 4 4 5 5 ' /></PointSet>",
-	    NULL, 0, 0);
+	    0, 0);
 	/* 3D Multiline */
 	do_x3d3_test(
 	    "MULTILINESTRING Z((0 1 1,2 3 4,4 5 5),(6 7 5,8 9 8,10 11 5))",
 	    "<IndexedLineSet  coordIndex='0 1 2 -1 3 4 5'><Coordinate point='0 1 1 2 3 4 4 5 5 6 7 5 8 9 8 10 11 5 ' /></IndexedLineSet>",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* MultiPolygon */
 	do_x3d3_test(
 	    "MULTIPOLYGON(((0 1 1,2 3 1,4 5 1,0 1 1)),((6 7 1,8 9 1,10 11 1,6 7 1)))",
 	    "<IndexedFaceSet  convex='false' coordIndex='0 1 2 -1 3 4 5'><Coordinate point='0 1 1 2 3 1 4 5 1 6 7 1 8 9 1 10 11 1 ' /></IndexedFaceSet>",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* PolyhedralSurface */
 	do_x3d3_test(
 	    "POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )",
 	    "<IndexedFaceSet convex='false'  coordIndex='0 1 2 3 -1 4 5 6 7 -1 8 9 10 11 -1 12 13 14 15 -1 16 17 18 19 -1 20 21 22 23'><Coordinate point='0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 1 1 0 1 1 1 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 1 0 1 1' /></IndexedFaceSet>",
-	    NULL, 0, 0);
+	    0, 0);
 
 	/* TODO: returns garbage at moment correctly implement GeometryCollection -- */
 	/** do_x3d3_test(
@@ -147,19 +147,19 @@ static void out_x3d3_test_option(void)
 	do_x3d3_test(
 	    "POINT(3.1111111111111 1.1111111111111 2.11111111111111)",
 	    "1 3 2",
-	    NULL, 0, 1);
+	    0, 1);
 
 	/* geocoordinate long,lat*/
 	do_x3d3_test(
 	    "SRID=4326;POLYGON((15 10 3,13.536 6.464 3,10 5 3,6.464 6.464 3,5 10 3,6.464 13.536 3,10 15 3,13.536 13.536 3,15 10 3))",
 	    "<IndexedFaceSet  convex='false' coordIndex='0 1 2 3 4 5 6 7'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='15 10 3 13.536 6.464 3 10 5 3 6.464 6.464 3 5 10 3 6.464 13.536 3 10 15 3 13.536 13.536 3 ' /></IndexedFaceSet>",
-	    NULL, 3, 2);
+	    3, 2);
 
 	/* geocoordinate lat long*/
 	do_x3d3_test(
 	    "SRID=4326;POLYGON((15 10 3,13.536 6.464 3,10 5 3,6.464 6.464 3,5 10 3,6.464 13.536 3,10 15 3,13.536 13.536 3,15 10 3))",
 	    "<IndexedFaceSet  convex='false' coordIndex='0 1 2 3 4 5 6 7'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"latitude_first\"' point='10 15 3 6.464 13.536 3 5 10 3 6.464 6.464 3 10 5 3 13.536 6.464 3 15 10 3 13.536 13.536 3 ' /></IndexedFaceSet>",
-	    NULL, 3, 3);
+	    3, 3);
 }
 
 
diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index 6635920..7c573b5 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1700,7 +1700,7 @@ extern lwvarlena_t* lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, i
 extern lwvarlena_t* lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id);
 extern lwvarlena_t* lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix);
 extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, const char *srs, int precision, int has_bbox);
-extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid);
+extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, int precision, int opts, const char *defid);
 extern lwvarlena_t* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
 extern lwvarlena_t* lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision);
 
diff --git a/liblwgeom/lwout_x3d.c b/liblwgeom/lwout_x3d.c
index 12dd23b..c70ab82 100644
--- a/liblwgeom/lwout_x3d.c
+++ b/liblwgeom/lwout_x3d.c
@@ -34,7 +34,7 @@
  */
 /* takes a GEOMETRY and returns a X3D representation */
 lwvarlena_t *
-lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid)
+lwgeom_to_x3d3(const LWGEOM *geom, int precision, int opts, const char *defid)
 {
 	stringbuffer_t *sb;
 	int rv;
@@ -48,7 +48,7 @@ lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, con
 	}
 
 	sb = stringbuffer_create();
-	rv = lwgeom_to_x3d3_sb(geom, srs, precision, opts, defid, sb);
+	rv = lwgeom_to_x3d3_sb(geom, precision, opts, defid, sb);
 
 	if ( rv == LW_FAILURE )
 	{
@@ -63,17 +63,17 @@ lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, con
 }
 /* takes a GEOMETRY and appends to string buffer the x3d output */
 static int
-lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+lwgeom_to_x3d3_sb(const LWGEOM *geom, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	int type = geom->type;
 
 	switch (type)
 	{
 	case POINTTYPE:
-		return asx3d3_point_sb((LWPOINT*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_point_sb((LWPOINT *)geom, precision, opts, defid, sb);
 
 	case LINETYPE:
-		return asx3d3_line_sb((LWLINE*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_line_sb((LWLINE *)geom, precision, opts, defid, sb);
 
 	case POLYGONTYPE:
 	{
@@ -81,27 +81,27 @@ lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts,
 		* seems like the simplest way to go so treat just like a mulitpolygon
 		*/
 		LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom);
-		asx3d3_multi_sb(tmp, srs, precision, opts, defid, sb);
+		asx3d3_multi_sb(tmp, precision, opts, defid, sb);
 		lwcollection_free(tmp);
 		return LW_SUCCESS;
 	}
 
 	case TRIANGLETYPE:
-		return asx3d3_triangle_sb((LWTRIANGLE*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_triangle_sb((LWTRIANGLE *)geom, precision, opts, defid, sb);
 
 	case MULTIPOINTTYPE:
 	case MULTILINETYPE:
 	case MULTIPOLYGONTYPE:
-		return asx3d3_multi_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_multi_sb((LWCOLLECTION *)geom, precision, opts, defid, sb);
 
 	case POLYHEDRALSURFACETYPE:
-		return asx3d3_psurface_sb((LWPSURFACE*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_psurface_sb((LWPSURFACE *)geom, precision, opts, defid, sb);
 
 	case TINTYPE:
-		return asx3d3_tin_sb((LWTIN*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_tin_sb((LWTIN *)geom, precision, opts, defid, sb);
 
 	case COLLECTIONTYPE:
-		return asx3d3_collection_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
+		return asx3d3_collection_sb((LWCOLLECTION *)geom, precision, opts, defid, sb);
 
 	default:
 		lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));
@@ -110,8 +110,11 @@ lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts,
 }
 
 static int
-asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) const char *srs, int precision,
-		int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
+asx3d3_point_sb(const LWPOINT *point,
+		int precision,
+		int opts,
+		__attribute__((__unused__)) const char *defid,
+		stringbuffer_t *sb)
 {
 	/** for point we just output the coordinates **/
 	return ptarray_to_x3d3_sb(point->point, precision, opts, 0, sb);
@@ -215,8 +218,11 @@ asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb)
 
 /** Return the linestring as an X3D LineSet */
 static int
-asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) const char *srs, int precision,
-	       int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
+asx3d3_line_sb(const LWLINE *line,
+	       int precision,
+	       int opts,
+	       __attribute__((__unused__)) const char *defid,
+	       stringbuffer_t *sb)
 {
 
 	/* int dimension=2; */
@@ -242,8 +248,12 @@ asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) const char *srs,
 
 /** Compute the X3D coordinates of the polygon and add to string buffer **/
 static int
-asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__))  const char *srs, int precision,
-	       int opts, __attribute__((__unused__)) int is_patch, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
+asx3d3_poly_sb(const LWPOLY *poly,
+	       int precision,
+	       int opts,
+	       __attribute__((__unused__)) int is_patch,
+	       __attribute__((__unused__)) const char *defid,
+	       stringbuffer_t *sb)
 {
 	uint32_t i;
 	for (i=0; i<poly->nrings; i++)
@@ -255,8 +265,11 @@ asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__))  const char *srs,
 }
 
 static int
-asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__))  const char *srs, int precision,
-		   int opts, __attribute__((__unused__))  const char *defid, stringbuffer_t *sb)
+asx3d3_triangle_sb(const LWTRIANGLE *triangle,
+		   int precision,
+		   int opts,
+		   __attribute__((__unused__)) const char *defid,
+		   stringbuffer_t *sb)
 {
 	return  ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb);
 }
@@ -266,7 +279,7 @@ asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__))  cons
  * Don't call this with single-geoms inspected!
  */
 static int
-asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_multi_sb(const LWCOLLECTION *col, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	char *x3dtype;
 	uint32_t i;
@@ -317,7 +330,7 @@ asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char
 		subgeom = col->geoms[i];
 		if (subgeom->type == POINTTYPE)
 		{
-			asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
+			asx3d3_point_sb((LWPOINT *)subgeom, precision, opts, defid, sb);
 			stringbuffer_aprintf(sb, " ");
 		}
 		else if (subgeom->type == LINETYPE)
@@ -327,7 +340,7 @@ asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char
 		}
 		else if (subgeom->type == POLYGONTYPE)
 		{
-			asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb);
+			asx3d3_poly_sb((LWPOLY *)subgeom, precision, opts, 0, defid, sb);
 			stringbuffer_aprintf(sb, " ");
 		}
 	}
@@ -345,7 +358,7 @@ asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char
  * Don't call this with single-geoms inspected!
  */
 static int
-asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_psurface_sb(const LWPSURFACE *psur, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	uint32_t j;
@@ -383,7 +396,7 @@ asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int o
 
 	for (i=0; i<psur->ngeoms; i++)
 	{
-		asx3d3_poly_sb(psur->geoms[i], srs, precision, opts, 1, defid, sb);
+		asx3d3_poly_sb(psur->geoms[i], precision, opts, 1, defid, sb);
 		if (i < (psur->ngeoms - 1) )
 		{
 			stringbuffer_aprintf(sb, " "); /* only add a trailing space if its not the last polygon in the set */
@@ -398,7 +411,7 @@ asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int o
  * Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer)
  */
 static int
-asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) const char *srs,  int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_tin_sb(const LWTIN *tin, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	uint32_t k;
@@ -422,8 +435,7 @@ asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) const char *srs,  in
 
 	for (i=0; i<tin->ngeoms; i++)
 	{
-		asx3d3_triangle_sb(tin->geoms[i], 0, precision,
-		                           opts, defid, sb);
+		asx3d3_triangle_sb(tin->geoms[i], precision, opts, defid, sb);
 		if (i < (tin->ngeoms - 1) )
 		{
 			stringbuffer_aprintf(sb, " ");
@@ -436,7 +448,7 @@ asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) const char *srs,  in
 }
 
 static int
-asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_collection_sb(const LWCOLLECTION *col, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	LWGEOM *subgeom;
@@ -454,32 +466,30 @@ asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, in
 		stringbuffer_aprintf(sb, "<Shape%s>", defid);
 		if ( subgeom->type == POINTTYPE )
 		{
-			asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
+			asx3d3_point_sb((LWPOINT *)subgeom, precision, opts, defid, sb);
 		}
 		else if ( subgeom->type == LINETYPE )
 		{
-			asx3d3_line_sb((LWLINE*)subgeom, 0, precision, opts, defid, sb);
+			asx3d3_line_sb((LWLINE *)subgeom, precision, opts, defid, sb);
 		}
 		else if ( subgeom->type == POLYGONTYPE )
 		{
-			asx3d3_poly_sb((LWPOLY*)subgeom, 0,  precision, opts, 0, defid, sb);
+			asx3d3_poly_sb((LWPOLY *)subgeom, precision, opts, 0, defid, sb);
 		}
 		else if ( subgeom->type == TINTYPE )
 		{
-			asx3d3_tin_sb((LWTIN*)subgeom, srs,  precision, opts,  defid, sb);
-
+			asx3d3_tin_sb((LWTIN *)subgeom, precision, opts, defid, sb);
 		}
 		else if ( subgeom->type == POLYHEDRALSURFACETYPE )
 		{
-			asx3d3_psurface_sb((LWPSURFACE*)subgeom, srs, precision, opts,  defid, sb);
-
+			asx3d3_psurface_sb((LWPSURFACE *)subgeom, precision, opts, defid, sb);
 		}
 		else if ( lwgeom_is_collection(subgeom) )
 		{
 			if ( subgeom->type == COLLECTIONTYPE )
-				asx3d3_collection_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
+				asx3d3_collection_sb((LWCOLLECTION *)subgeom, precision, opts, defid, sb);
 			else
-				asx3d3_multi_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
+				asx3d3_multi_sb((LWCOLLECTION *)subgeom, precision, opts, defid, sb);
 		}
 		else
 			lwerror("asx3d3_collection_buf: unknown geometry type");
diff --git a/liblwgeom/lwout_x3d.h b/liblwgeom/lwout_x3d.h
index a5fc752..ca8c6db 100644
--- a/liblwgeom/lwout_x3d.h
+++ b/liblwgeom/lwout_x3d.h
@@ -31,16 +31,18 @@
 #include "stringbuffer.h"
 
 /** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/
-static int lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int lwgeom_to_x3d3_sb(const LWGEOM *geom, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_point_sb(const LWPOINT *point, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_line_sb(const LWLINE *line, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_point_sb(const LWPOINT *point, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_line_sb(const LWLINE *line, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int
+asx3d3_triangle_sb(const LWTRIANGLE *triangle, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_multi_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_tin_sb(const LWTIN *tin, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_multi_sb(const LWCOLLECTION *col, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_psurface_sb(const LWPSURFACE *psur, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_tin_sb(const LWTIN *tin, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int
+asx3d3_collection_sb(const LWCOLLECTION *col, int precision, int opts, const char *defid, stringbuffer_t *sb);
 static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb );
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index 22eb58f..7a71f51 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -388,8 +388,6 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 	GSERIALIZED *geom;
 	LWGEOM *lwgeom;
 	int version;
-	const char *srs;
-	int32_t srid;
 	int option = 0;
 	int precision = DBL_DIG;
 	static const char* default_defid = "x3d:"; /* default defid */
@@ -424,7 +422,6 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 		option = PG_GETARG_INT32(3);
 
 
-
 	/* retrieve defid */
 	if (PG_NARGS() >4 && !PG_ARGISNULL(4))
 	{
@@ -447,15 +444,10 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 	}
 
 	lwgeom = lwgeom_from_gserialized(geom);
-	srid = gserialized_get_srid(geom);
-	if (srid == SRID_UNKNOWN)      srs = NULL;
-	else if (option & 1)
-		srs = GetSRSCacheBySRID(fcinfo, srid, false);
-	else
-		srs = GetSRSCacheBySRID(fcinfo, srid, true);
 
 	if (option & LW_X3D_USE_GEOCOORDS) {
-		if (srid != 4326) {
+		if (lwgeom->srid != 4326)
+		{
 			PG_FREE_IF_COPY(geom, 0);
 			/** TODO: we need to support UTM and other coordinate systems supported by X3D eventually
 			http://www.web3d.org/documents/specifications/19775-1/V3.2/Part01/components/geodata.html#t-earthgeoids **/
@@ -464,7 +456,7 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 		}
 	}
 
-	PG_RETURN_TEXT_P(lwgeom_to_x3d3(lwgeom, srs, precision, option, defid));
+	PG_RETURN_TEXT_P(lwgeom_to_x3d3(lwgeom, precision, option, defid));
 }
 
 /**

commit b38079d4f1fac448c2a23681034521464d743cb6
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Apr 28 19:10:49 2020 +0200

    Cache getSRSbySRID

diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index aa7f74c..6635920 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1699,8 +1699,8 @@ extern lwvarlena_t* lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, i
 extern lwvarlena_t* lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix);
 extern lwvarlena_t* lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id);
 extern lwvarlena_t* lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix);
-extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int has_bbox);
-extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid);
+extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, const char *srs, int precision, int has_bbox);
+extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid);
 extern lwvarlena_t* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
 extern lwvarlena_t* lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision);
 
diff --git a/liblwgeom/lwout_geojson.c b/liblwgeom/lwout_geojson.c
index 3b53f83..2a5a6ce 100644
--- a/liblwgeom/lwout_geojson.c
+++ b/liblwgeom/lwout_geojson.c
@@ -28,14 +28,14 @@
 #include <string.h>	/* strlen */
 #include <assert.h>
 
-static lwvarlena_t *asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_triangle(const LWTRIANGLE *tri, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision);
-static lwvarlena_t *asgeojson_collection(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_point(const LWPOINT *point, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_line(const LWLINE *line, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_triangle(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_poly(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_multipoint(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_multiline(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_multipolygon(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision);
+static lwvarlena_t *asgeojson_collection(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision);
 static size_t asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision);
 static size_t asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision);
 
@@ -46,7 +46,7 @@ static size_t pointArray_geojson_size(POINTARRAY *pa, int precision);
  * Takes a GEOMETRY and returns a GeoJson representation
  */
 lwvarlena_t *
-lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox)
+lwgeom_to_geojson(const LWGEOM *geom, const char *srs, int precision, int has_bbox)
 {
 	int type = geom->type;
 	GBOX *bbox = NULL;
@@ -96,7 +96,7 @@ lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox)
  * Handle SRS
  */
 static size_t
-asgeojson_srs_size(char *srs)
+asgeojson_srs_size(const char *srs)
 {
 	int size;
 
@@ -108,7 +108,7 @@ asgeojson_srs_size(char *srs)
 }
 
 static size_t
-asgeojson_srs_buf(char *output, char *srs)
+asgeojson_srs_buf(char *output, const char *srs)
 {
 	char *ptr = output;
 
@@ -166,7 +166,7 @@ asgeojson_bbox_buf(char *output, GBOX *bbox, int hasz, int precision)
  */
 
 static size_t
-asgeojson_point_size(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
+asgeojson_point_size(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
 {
 	int size;
 
@@ -184,7 +184,7 @@ asgeojson_point_size(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
 }
 
 static size_t
-asgeojson_point_buf(const LWPOINT *point, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_point_buf(const LWPOINT *point, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	char *ptr = output;
 
@@ -202,7 +202,7 @@ asgeojson_point_buf(const LWPOINT *point, char *srs, char *output, GBOX *bbox, i
 }
 
 static lwvarlena_t *
-asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
+asgeojson_point(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_point_size(point, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -216,7 +216,7 @@ asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
  */
 
 static size_t
-asgeojson_triangle_size(const LWTRIANGLE *tri, char *srs, GBOX *bbox, int precision)
+asgeojson_triangle_size(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
 {
 	int size;
 
@@ -232,7 +232,7 @@ asgeojson_triangle_size(const LWTRIANGLE *tri, char *srs, GBOX *bbox, int precis
 }
 
 static size_t
-asgeojson_triangle_buf(const LWTRIANGLE *tri, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_triangle_buf(const LWTRIANGLE *tri, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	char *ptr = output;
 
@@ -249,7 +249,7 @@ asgeojson_triangle_buf(const LWTRIANGLE *tri, char *srs, char *output, GBOX *bbo
 }
 
 static lwvarlena_t *
-asgeojson_triangle(const LWTRIANGLE *tri, char *srs, GBOX *bbox, int precision)
+asgeojson_triangle(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_triangle_size(tri, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -263,7 +263,7 @@ asgeojson_triangle(const LWTRIANGLE *tri, char *srs, GBOX *bbox, int precision)
  */
 
 static size_t
-asgeojson_line_size(const LWLINE *line, char *srs, GBOX *bbox, int precision)
+asgeojson_line_size(const LWLINE *line, const char *srs, GBOX *bbox, int precision)
 {
 	int size;
 
@@ -277,7 +277,7 @@ asgeojson_line_size(const LWLINE *line, char *srs, GBOX *bbox, int precision)
 }
 
 static size_t
-asgeojson_line_buf(const LWLINE *line, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_line_buf(const LWLINE *line, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	char *ptr=output;
 
@@ -292,7 +292,7 @@ asgeojson_line_buf(const LWLINE *line, char *srs, char *output, GBOX *bbox, int
 }
 
 static lwvarlena_t *
-asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision)
+asgeojson_line(const LWLINE *line, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_line_size(line, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -308,7 +308,7 @@ asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision)
  */
 
 static size_t
-asgeojson_poly_size(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
+asgeojson_poly_size(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision)
 {
 	size_t size;
 	uint32_t i;
@@ -329,7 +329,7 @@ asgeojson_poly_size(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
 }
 
 static size_t
-asgeojson_poly_buf(const LWPOLY *poly, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_poly_buf(const LWPOLY *poly, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	uint32_t i;
 
@@ -352,7 +352,7 @@ asgeojson_poly_buf(const LWPOLY *poly, char *srs, char *output, GBOX *bbox, int
 }
 
 static lwvarlena_t *
-asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
+asgeojson_poly(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_poly_size(poly, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -368,7 +368,7 @@ asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
  */
 
 static size_t
-asgeojson_multipoint_size(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
+asgeojson_multipoint_size(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision)
 {
 	LWPOINT * point;
 	int size;
@@ -390,7 +390,7 @@ asgeojson_multipoint_size(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int pre
 }
 
 static size_t
-asgeojson_multipoint_buf(const LWMPOINT *mpoint, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_multipoint_buf(const LWMPOINT *mpoint, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	LWPOINT *point;
 	uint32_t i;
@@ -413,7 +413,7 @@ asgeojson_multipoint_buf(const LWMPOINT *mpoint, char *srs, char *output, GBOX *
 }
 
 static lwvarlena_t *
-asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
+asgeojson_multipoint(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_multipoint_size(mpoint, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -429,7 +429,7 @@ asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precisio
  */
 
 static size_t
-asgeojson_multiline_size(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
+asgeojson_multiline_size(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision)
 {
 	LWLINE * line;
 	int size;
@@ -452,7 +452,7 @@ asgeojson_multiline_size(const LWMLINE *mline, char *srs, GBOX *bbox, int precis
 }
 
 static size_t
-asgeojson_multiline_buf(const LWMLINE *mline, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_multiline_buf(const LWMLINE *mline, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	LWLINE *line;
 	uint32_t i;
@@ -478,7 +478,7 @@ asgeojson_multiline_buf(const LWMLINE *mline, char *srs, char *output, GBOX *bbo
 }
 
 static lwvarlena_t *
-asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
+asgeojson_multiline(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_multiline_size(mline, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -494,7 +494,7 @@ asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
  */
 
 static size_t
-asgeojson_multipolygon_size(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
+asgeojson_multipolygon_size(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision)
 {
 	LWPOLY *poly;
 	int size;
@@ -522,7 +522,7 @@ asgeojson_multipolygon_size(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int pre
 }
 
 static size_t
-asgeojson_multipolygon_buf(const LWMPOLY *mpoly, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_multipolygon_buf(const LWMPOLY *mpoly, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	LWPOLY *poly;
 	uint32_t i, j;
@@ -552,7 +552,7 @@ asgeojson_multipolygon_buf(const LWMPOLY *mpoly, char *srs, char *output, GBOX *
 }
 
 static lwvarlena_t *
-asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
+asgeojson_multipolygon(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_multipolygon_size(mpoly, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
@@ -568,7 +568,7 @@ asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precisio
  */
 
 static size_t
-asgeojson_collection_size(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
+asgeojson_collection_size(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t i;
 	size_t size;
@@ -591,7 +591,7 @@ asgeojson_collection_size(const LWCOLLECTION *col, char *srs, GBOX *bbox, int pr
 }
 
 static size_t
-asgeojson_collection_buf(const LWCOLLECTION *col, char *srs, char *output, GBOX *bbox, int precision)
+asgeojson_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, GBOX *bbox, int precision)
 {
 	uint32_t i;
 	char *ptr=output;
@@ -615,7 +615,7 @@ asgeojson_collection_buf(const LWCOLLECTION *col, char *srs, char *output, GBOX
 }
 
 static lwvarlena_t *
-asgeojson_collection(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
+asgeojson_collection(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision)
 {
 	uint32_t size = asgeojson_collection_size(col, srs, bbox, precision);
 	lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
diff --git a/liblwgeom/lwout_x3d.c b/liblwgeom/lwout_x3d.c
index 0564406..12dd23b 100644
--- a/liblwgeom/lwout_x3d.c
+++ b/liblwgeom/lwout_x3d.c
@@ -34,7 +34,7 @@
  */
 /* takes a GEOMETRY and returns a X3D representation */
 lwvarlena_t *
-lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
+lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid)
 {
 	stringbuffer_t *sb;
 	int rv;
@@ -63,7 +63,7 @@ lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const cha
 }
 /* takes a GEOMETRY and appends to string buffer the x3d output */
 static int
-lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	int type = geom->type;
 
@@ -110,7 +110,7 @@ lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const
 }
 
 static int
-asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) char *srs, int precision,
+asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) const char *srs, int precision,
 		int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
 {
 	/** for point we just output the coordinates **/
@@ -215,7 +215,7 @@ asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb)
 
 /** Return the linestring as an X3D LineSet */
 static int
-asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int precision,
+asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) const char *srs, int precision,
 	       int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
 {
 
@@ -242,7 +242,7 @@ asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int pr
 
 /** Compute the X3D coordinates of the polygon and add to string buffer **/
 static int
-asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__))  char *srs, int precision,
+asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__))  const char *srs, int precision,
 	       int opts, __attribute__((__unused__)) int is_patch, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
@@ -255,7 +255,7 @@ asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__))  char *srs, int p
 }
 
 static int
-asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__))  char *srs, int precision,
+asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__))  const char *srs, int precision,
 		   int opts, __attribute__((__unused__))  const char *defid, stringbuffer_t *sb)
 {
 	return  ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb);
@@ -266,7 +266,7 @@ asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__))  char
  * Don't call this with single-geoms inspected!
  */
 static int
-asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	char *x3dtype;
 	uint32_t i;
@@ -345,7 +345,7 @@ asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs,
  * Don't call this with single-geoms inspected!
  */
 static int
-asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	uint32_t j;
@@ -398,7 +398,7 @@ asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, c
  * Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer)
  */
 static int
-asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs,  int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) const char *srs,  int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	uint32_t k;
@@ -436,7 +436,7 @@ asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs,  int prec
 }
 
 static int
-asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
 	uint32_t i;
 	LWGEOM *subgeom;
diff --git a/liblwgeom/lwout_x3d.h b/liblwgeom/lwout_x3d.h
index 31a3515..a5fc752 100644
--- a/liblwgeom/lwout_x3d.h
+++ b/liblwgeom/lwout_x3d.h
@@ -31,16 +31,16 @@
 #include "stringbuffer.h"
 
 /** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/
-static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_point_sb(const LWPOINT *point, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_line_sb(const LWLINE *line, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
-static int asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_multi_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_tin_sb(const LWTIN *tin, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb );
diff --git a/libpgcommon/lwgeom_cache.c b/libpgcommon/lwgeom_cache.c
index 797fb66..33e2371 100644
--- a/libpgcommon/lwgeom_cache.c
+++ b/libpgcommon/lwgeom_cache.c
@@ -333,3 +333,109 @@ ToastCacheGetGeometry(FunctionCallInfo fcinfo, uint32_t argnum)
 		return (GSERIALIZED*)PG_DETOAST_DATUM(datum);
 	}
 }
+
+/*
+ * Retrieve an SRS from a given SRID
+ * Require valid spatial_ref_sys table entry
+ *
+ * Could return SRS as short one (i.e EPSG:4326)
+ * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
+ */
+static char *
+getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
+{
+	static const uint16_t max_query_size = 512;
+	char query[512];
+	char *srs, *srscopy;
+	int size, err;
+	postgis_initialize_cache(fcinfo);
+
+	if (SPI_OK_CONNECT != SPI_connect())
+	{
+		elog(NOTICE, "%s: could not connect to SPI manager", __func__);
+		SPI_finish();
+		return NULL;
+	}
+
+	if (short_crs)
+		snprintf(query,
+			 max_query_size,
+			 "SELECT auth_name||':'||auth_srid \
+		        FROM %s WHERE srid='%d'",
+			 postgis_spatial_ref_sys(),
+			 srid);
+	else
+		snprintf(query,
+			 max_query_size,
+			 "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
+		        FROM %s WHERE srid='%d'",
+			 postgis_spatial_ref_sys(),
+			 srid);
+
+	err = SPI_exec(query, 1);
+	if (err < 0)
+	{
+		elog(NOTICE, "%s: error executing query %d", __func__, err);
+		SPI_finish();
+		return NULL;
+	}
+
+	/* no entry in spatial_ref_sys */
+	if (SPI_processed <= 0)
+	{
+		SPI_finish();
+		return NULL;
+	}
+
+	/* get result  */
+	srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
+
+	/* NULL result */
+	if (!srs)
+	{
+		SPI_finish();
+		return NULL;
+	}
+
+	size = strlen(srs) + 1;
+
+	srscopy = MemoryContextAllocZero(PostgisCacheContext(fcinfo), size);
+	memcpy(srscopy, srs, size);
+
+	/* disconnect from SPI */
+	SPI_finish();
+
+	return srscopy;
+}
+
+static inline SRSDescCache *
+SRSDescCacheGet(FunctionCallInfo fcinfo)
+{
+	const uint32_t entry_number = SRSDESC_CACHE_ENTRY;
+	GenericCacheCollection *generic_cache = GetGenericCacheCollection(fcinfo);
+	SRSDescCache *cache = (SRSDescCache *)(generic_cache->entry[entry_number]);
+	if (!cache)
+	{
+		cache = MemoryContextAllocZero(PostgisCacheContext(fcinfo), sizeof(SRSDescCache));
+		cache->type = entry_number;
+		generic_cache->entry[entry_number] = (GenericCache *)cache;
+	}
+	return cache;
+}
+
+const char *
+GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
+{
+	SRSDescCache *cache = SRSDescCacheGet(fcinfo);
+	SRSDescCacheArgument *arg = &(cache->arg[0]);
+
+	if (arg->srid != srid || arg->short_mode != short_crs || !arg->srs)
+	{
+		arg->srid = srid;
+		arg->short_mode = short_crs;
+		if (arg->srs)
+			pfree(arg->srs);
+		arg->srs = getSRSbySRID(fcinfo, srid, short_crs);
+	}
+	return arg->srs;
+}
\ No newline at end of file
diff --git a/libpgcommon/lwgeom_cache.h b/libpgcommon/lwgeom_cache.h
index 4bdd310..77ab5bd 100644
--- a/libpgcommon/lwgeom_cache.h
+++ b/libpgcommon/lwgeom_cache.h
@@ -27,6 +27,7 @@
 #define CIRC_CACHE_ENTRY 3
 #define RECT_CACHE_ENTRY 4
 #define TOAST_CACHE_ENTRY 5
+#define SRSDESC_CACHE_ENTRY 6
 
 #define NUM_CACHE_ENTRIES 8
 
@@ -132,5 +133,20 @@ typedef struct
 
 GSERIALIZED* ToastCacheGetGeometry(FunctionCallInfo fcinfo, uint32_t argnum);
 
+/******************************************************************************/
+
+#define SRSDescCacheSize 1
+typedef struct {
+	int32_t srid;
+	bool short_mode;
+	char *srs;
+} SRSDescCacheArgument;
+
+typedef struct {
+	int type;
+	SRSDescCacheArgument arg[SRSDescCacheSize];
+} SRSDescCache;
+
+const char *GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs);
 
 #endif /* LWGEOM_CACHE_H_ */
diff --git a/postgis/geography_inout.c b/postgis/geography_inout.c
index 8db14c8..44dec05 100644
--- a/postgis/geography_inout.c
+++ b/postgis/geography_inout.c
@@ -39,6 +39,7 @@
 #include "catalog/pg_type.h" /* for CSTRINGOID */
 
 #include "liblwgeom.h"         /* For standard geometry types. */
+#include "lwgeom_cache.h"
 #include "lwgeom_pg.h"       /* For debugging macros. */
 #include "geography.h"	     /* For utility functions. */
 #include "lwgeom_export.h"   /* For export functions. */
@@ -206,7 +207,7 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
 	GSERIALIZED *g = NULL;
 	lwvarlena_t *v;
 	int version;
-	char *srs;
+	const char *srs;
 	int32_t srid = SRID_DEFAULT;
 	int precision = DBL_DIG;
 	int option = 0;
@@ -283,9 +284,9 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
 	}
 
 	if (option & 1)
-		srs = getSRSbySRID(fcinfo, srid, false);
+		srs = GetSRSCacheBySRID(fcinfo, srid, false);
 	else
-		srs = getSRSbySRID(fcinfo, srid, true);
+		srs = GetSRSCacheBySRID(fcinfo, srid, true);
 	if (!srs)
 	{
 		elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
@@ -397,7 +398,7 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
 {
 	lwvarlena_t *geojson;
 	int has_bbox = 0;
-	char * srs = NULL;
+	const char *srs = NULL;
 	GSERIALIZED *g = PG_GETARG_GSERIALIZED_P(0);
 	int precision = PG_GETARG_INT32(1);
 	int option = PG_GETARG_INT32(2);
@@ -419,9 +420,9 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
 	{
 		/* Geography only handle srid SRID_DEFAULT */
 		if (option & 2)
-			srs = getSRSbySRID(fcinfo, SRID_DEFAULT, true);
+			srs = GetSRSCacheBySRID(fcinfo, SRID_DEFAULT, true);
 		if (option & 4)
-			srs = getSRSbySRID(fcinfo, SRID_DEFAULT, false);
+			srs = GetSRSCacheBySRID(fcinfo, SRID_DEFAULT, false);
 
 		if (!srs)
 		{
@@ -435,7 +436,6 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
 	geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
 	lwgeom_free(lwgeom);
 	PG_FREE_IF_COPY(g, 0);
-	if (srs) pfree(srs);
 
 	PG_RETURN_TEXT_P(geojson);
 }
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index 585dcce..22eb58f 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -37,6 +37,7 @@
 #include "utils/jsonb.h"
 
 #include "../postgis_config.h"
+#include "lwgeom_cache.h"
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
 #include "lwgeom_export.h"
@@ -51,81 +52,6 @@ Datum geometry_to_json(PG_FUNCTION_ARGS);
 Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
 
 /*
- * Retrieve an SRS from a given SRID
- * Require valid spatial_ref_sys table entry
- *
- * Could return SRS as short one (i.e EPSG:4326)
- * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
- */
-char *
-getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
-{
-	static const uint16_t max_query_size = 512;
-	char query[512];
-	char *srs, *srscopy;
-	int size, err;
-	postgis_initialize_cache(fcinfo);
-
-	if (SPI_OK_CONNECT != SPI_connect ())
-	{
-		elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
-		SPI_finish();
-		return NULL;
-	}
-
-	if (short_crs)
-		snprintf(query,
-			 max_query_size,
-			 "SELECT auth_name||':'||auth_srid \
-		        FROM %s WHERE srid='%d'",
-			 postgis_spatial_ref_sys(),
-			 srid);
-	else
-		snprintf(query,
-			 max_query_size,
-			 "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
-		        FROM %s WHERE srid='%d'",
-			 postgis_spatial_ref_sys(),
-			 srid);
-
-	err = SPI_exec(query, 1);
-	if ( err < 0 )
-	{
-		elog(NOTICE, "getSRSbySRID: error executing query %d", err);
-		SPI_finish();
-		return NULL;
-	}
-
-	/* no entry in spatial_ref_sys */
-	if (SPI_processed <= 0)
-	{
-		SPI_finish();
-		return NULL;
-	}
-
-	/* get result  */
-	srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
-
-	/* NULL result */
-	if ( ! srs )
-	{
-		SPI_finish();
-		return NULL;
-	}
-
-	/* copy result to upper executor context */
-	size = strlen(srs)+1;
-	srscopy = SPI_palloc(size);
-	memcpy(srscopy, srs, size);
-
-	/* disconnect from SPI */
-	SPI_finish();
-
-	return srscopy;
-}
-
-
-/*
 * Retrieve an SRID from a given SRS
 * Require valid spatial_ref_sys table entry
 *
@@ -207,7 +133,7 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
 	LWGEOM *lwgeom;
 	lwvarlena_t *v = NULL;
 	int version;
-	char *srs;
+	const char *srs;
 	int32_t srid;
 	int option = 0;
 	int lwopts = LW_GML_IS_DIMS;
@@ -286,9 +212,9 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
 	srid = gserialized_get_srid(geom);
 	if (srid == SRID_UNKNOWN)      srs = NULL;
 	else if (option & 1)
-		srs = getSRSbySRID(fcinfo, srid, false);
+		srs = GetSRSCacheBySRID(fcinfo, srid, false);
 	else
-		srs = getSRSbySRID(fcinfo, srid, true);
+		srs = GetSRSCacheBySRID(fcinfo, srid, true);
 
 	if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
 	if (option & 4) lwopts |= LW_GML_SHORTLINE;
@@ -334,13 +260,12 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
 {
 	GSERIALIZED *geom;
 	LWGEOM *lwgeom;
-	lwvarlena_t *geojson;
 	int precision = DBL_DIG;
 	int output_bbox = LW_FALSE;
 	int output_long_crs = LW_FALSE;
 	int output_short_crs = LW_FALSE;
 	int output_guess_short_srid = LW_FALSE;
-	char *srs = NULL;
+	const char *srs = NULL;
 	int32_t srid;
 
 	/* Get the geometry */
@@ -383,7 +308,7 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
 
 	if (srid != SRID_UNKNOWN && (output_short_crs || output_long_crs))
 	{
-		srs = getSRSbySRID(fcinfo, srid, !output_long_crs);
+		srs = GetSRSCacheBySRID(fcinfo, srid, !output_long_crs);
 
 		if (!srs)
 		{
@@ -393,13 +318,7 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
 	}
 
 	lwgeom = lwgeom_from_gserialized(geom);
-	geojson = lwgeom_to_geojson(lwgeom, srs, precision, output_bbox);
-	lwgeom_free(lwgeom);
-
-	if (srs) pfree(srs);
-
-	PG_FREE_IF_COPY(geom, 0);
-	PG_RETURN_TEXT_P(geojson);
+	PG_RETURN_TEXT_P(lwgeom_to_geojson(lwgeom, srs, precision, output_bbox));
 }
 
 
@@ -469,7 +388,7 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 	GSERIALIZED *geom;
 	LWGEOM *lwgeom;
 	int version;
-	char *srs;
+	const char *srs;
 	int32_t srid;
 	int option = 0;
 	int precision = DBL_DIG;
@@ -531,9 +450,9 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
 	srid = gserialized_get_srid(geom);
 	if (srid == SRID_UNKNOWN)      srs = NULL;
 	else if (option & 1)
-		srs = getSRSbySRID(fcinfo, srid, false);
+		srs = GetSRSCacheBySRID(fcinfo, srid, false);
 	else
-		srs = getSRSbySRID(fcinfo, srid, true);
+		srs = GetSRSCacheBySRID(fcinfo, srid, true);
 
 	if (option & LW_X3D_USE_GEOCOORDS) {
 		if (srid != 4326) {
diff --git a/postgis/lwgeom_export.h b/postgis/lwgeom_export.h
index b5de2ba..cd803e4 100644
--- a/postgis/lwgeom_export.h
+++ b/postgis/lwgeom_export.h
@@ -22,5 +22,4 @@
  *
  **********************************************************************/
 
-char *getSRSbySRID(FunctionCallInfo fcinfo, int32_t SRID, bool short_crs);
 int getSRIDbySRS(FunctionCallInfo fcinfo, const char *SRS);

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

Summary of changes:
 NEWS                         |   1 +
 liblwgeom/cunit/cu_out_x3d.c |  34 +++----
 liblwgeom/liblwgeom.h.in     |   4 +-
 liblwgeom/lwout_geojson.c    |  70 +++++++-------
 liblwgeom/lwout_x3d.c        |  84 +++++++++--------
 liblwgeom/lwout_x3d.h        |  18 ++--
 libpgcommon/lwgeom_cache.c   | 212 +++++++++++++++++++++++++++++++++++++++++++
 libpgcommon/lwgeom_cache.h   |  32 +++++++
 postgis/geography_inout.c    |  15 ++-
 postgis/gserialized_typmod.c |   1 -
 postgis/lwgeom_export.c      | 183 ++-----------------------------------
 postgis/lwgeom_export.h      |  26 ------
 postgis/lwgeom_in_geohash.c  |   1 -
 postgis/lwgeom_in_geojson.c  |   4 +-
 postgis/lwgeom_inout.c       |   4 +-
 15 files changed, 377 insertions(+), 312 deletions(-)
 delete mode 100644 postgis/lwgeom_export.h


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list