[postgis] 01/07: Imported Upstream version 2.3.0~rc1+dfsg

Bas Couwenberg sebastic at debian.org
Mon Sep 19 10:23:36 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch experimental
in repository postgis.

commit 28814812ed50c9d028aaf616878fdf6bdca2e5f5
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Mon Sep 19 09:57:24 2016 +0200

    Imported Upstream version 2.3.0~rc1+dfsg
---
 .drone.yml                                         |   2 +-
 .editorconfig                                      |   3 +
 NEWS                                               |  29 ++--
 Version.config                                     |   2 +-
 doc/faq_raster.xml                                 |   2 +-
 doc/reference_constructor.xml                      |   2 +-
 doc/reference_raster.xml                           |  29 ++--
 extensions/address_standardizer/Makefile           |   6 +-
 .../address_standardizer.control                   |   2 +-
 .../address_standardizer_data_us.control           |   2 +-
 extensions/postgis/Makefile                        |   2 +-
 extensions/postgis/postgis.control                 |   2 +-
 extensions/postgis_sfcgal/Makefile                 |   2 +-
 extensions/postgis_sfcgal/postgis_sfcgal.control   |   2 +-
 extensions/postgis_tiger_geocoder/Makefile         |   2 +-
 .../postgis_tiger_geocoder.control                 |   2 +-
 extensions/postgis_topology/Makefile               |   2 +-
 .../postgis_topology/postgis_topology.control      |   2 +-
 extensions/upgradeable_versions.mk                 |   4 +-
 liblwgeom/cunit/cu_algorithm.c                     |  41 +++++
 liblwgeom/liblwgeom.h.in                           |   8 +-
 liblwgeom/lwpoly.c                                 |  40 +++++
 postgis/gserialized_estimate.c                     |   6 +-
 postgis/lwgeom_export.c                            |   4 +-
 postgis/lwgeom_functions_analytic.c                |  58 +++++++-
 postgis/lwgeom_functions_basic.c                   |   7 +-
 postgis/lwgeom_in_encoded_polyline.c               |   4 +-
 postgis/postgis.sql.in                             |   6 +-
 postgis/sqldefines.h                               |   8 +-
 postgis_svn_revision.h                             |   2 +-
 raster/rt_pg/Makefile.in                           |  18 +--
 raster/rt_pg/rtpostgis.sql.in                      |  17 ++-
 raster/test/regress/rt_createoverview.sql          |  86 +++++++++++
 raster/test/regress/rt_createoverview_expected     |  14 ++
 regress/estimatedextent_expected                   |  39 +++--
 regress/in_encodedpolyline.sql                     |   2 +-
 regress/in_encodedpolyline_expected                |   2 +-
 regress/in_geojson.sql                             |   3 +
 regress/in_geojson_expected                        |   1 +
 regress/out_geometry_expected                      |   2 +-
 regress/run_test.pl                                | 165 +++++++++++----------
 regress/sfcgal/tickets_expected                    |  12 +-
 regress/swapordinates.sql                          |   3 +
 regress/swapordinates_expected                     |   2 +
 regress/tickets.sql                                |  15 +-
 regress/tickets_expected                           |   6 +-
 topology/postgis_topology.c                        | 165 ++++++++++++++++-----
 topology/sql/populate.sql.in                       |   4 +-
 48 files changed, 619 insertions(+), 220 deletions(-)

diff --git a/.drone.yml b/.drone.yml
index 65af6c0..cb788af 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -6,7 +6,7 @@ test-image: &test-image docker.kbt.io/postgis/build-test:trisquel
 pipeline:
   clone:
     image: git
-    depth: 50
+    depth: 20
     recursive: false
   build:
     image: *test-image
diff --git a/.editorconfig b/.editorconfig
index abd632c..2ce5421 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +10,9 @@ end_of_line = lf
 trim_trailing_whitespace = true
 insert_final_newline = true
 
+[*_expected]
+trim_trailing_whitespace = false
+
 # C files want tab indentation
 [*.{c,h}]
 indent_style = tab
diff --git a/NEWS b/NEWS
index 976a788..197296d 100644
--- a/NEWS
+++ b/NEWS
@@ -6,9 +6,11 @@ PostGIS 2.3.0
   - #3466, Casting from box3d to geometry now returns a 3D
            geometry (Julien Rouhaud of Dalibo)
 
-  - #3604, pgcommon/Makefile.in orders 
-	       CFLAGS incorrectly leading to wrong liblwgeom.h
-		   (Greg Troxel)
+  - #3604, pgcommon/Makefile.in orders CFLAGS incorrectly leading to
+           wrong liblwgeom.h (Greg Troxel)
+   
+  - #3396, ST_EstimatedExtent, throw WARNING instead of ERROR
+           (Regina Obe)
 
  * Deprecated signatures *
 
@@ -37,26 +39,27 @@ PostGIS 2.3.0
   - #3465, ST_ClusterKMeans (Paul Ramsey)
   - #3469, ST_MakeLine with MULTIPOINTs (Paul Norman)
   - #3549, Support PgSQL 9.6 parallel query mode, as far as possible
-    (Paul Ramsey, Regina Obe)
+           (Paul Ramsey, Regina Obe)
   - #3557, Geometry function costs based on query stats (Paul Norman)
   - #3591, Add support for BRIN indexes. PostgreSQL 9.4+ required.
-		  (Giuseppe Broccolo of 2nd Quadrant, Julien Rouhaud and Ronan Dunklau of Dalibo)
-  - #3496, Make postgis non-relocateable (for extension install), 
-		schema qualify calls in functions (Regina Obe)
-		Should resolve once and for all for extensions #3494, #3486, #3076 
-		
+           (Giuseppe Broccolo of 2nd Quadrant, Julien Rouhaud
+            and Ronan Dunklau of Dalibo)
+  - #3496, Make postgis non-relocateable for extension install,
+           schema qualify calls in functions (Regina Obe)
+           Should resolve once and for all for extensions #3494, #3486, #3076
   - #3547, Update tiger geocoder to support TIGER 2016
-   and to support both http and ftp.
+           and to support both http and ftp.
 
  * Performance Enhancements *
 
   - #75, Enhancement to PIP short circuit (Dan Baston)
   - #3383, Avoid deserializing small geometries during index operations
-    (Dan Baston)
+           (Dan Baston)
   - #3400, Minor optimization of PIP routines (Dan Baston)
   - Make adding a line to topology interruptible (Sandro Santilli)
-  - #3613, Segmentize geography using equal length segments, (Hugo Mercier of Oslandia) 
-  
+  - #3613, Segmentize geography using equal length segments
+           (Hugo Mercier of Oslandia)
+
 PostGIS 2.3.0beta1
 2016/09/06
 See PostGIS 2.3.0 section for details
diff --git a/Version.config b/Version.config
index c58a33d..b3dd177 100644
--- a/Version.config
+++ b/Version.config
@@ -5,7 +5,7 @@
 
 POSTGIS_MAJOR_VERSION=2
 POSTGIS_MINOR_VERSION=3
-POSTGIS_MICRO_VERSION=0beta1
+POSTGIS_MICRO_VERSION=0rc1
 
 # Liblwgeom interface versioning, reset to 0:0:0 (cur:age:rev)
 # when changing POSTGIS_MINOR_VERSION
diff --git a/doc/faq_raster.xml b/doc/faq_raster.xml
index cd588cb..b9ef448 100644
--- a/doc/faq_raster.xml
+++ b/doc/faq_raster.xml
@@ -248,7 +248,7 @@ END
       </question>
 
       <answer>
-        <para>The function is not unique error happens if one of your arguments is a textual representation of a geometry instead of a geometry.  In these cases, PostgreSQL marks the textual representation as an unknown type, which means it can fall into the st_intersects(raster, geometry) or st_intersects(raster,raster) thus resulting in a non-unique case since both functions can in theory support your request.  To prevent this, you need to cast the geometry to a geometry.</para>
+        <para>The function is not unique error happens if one of your arguments is a textual representation of a geometry instead of a geometry.  In these cases, PostgreSQL marks the textual representation as an unknown type, which means it can fall into the st_intersects(raster, geometry) or st_intersects(raster,raster) thus resulting in a non-unique case since both functions can in theory support your request.  To prevent this, you need to cast the textual representation of the geometr [...]
         <para>For example if your code looks like this:</para>
         <programlisting>SELECT rast
  FROM my_raster
diff --git a/doc/reference_constructor.xml b/doc/reference_constructor.xml
index e82573e..9efb10d 100644
--- a/doc/reference_constructor.xml
+++ b/doc/reference_constructor.xml
@@ -425,7 +425,7 @@ LINESTRING(-113.98 39.198,-113.981 39.195)
 \\312Q\\300\\366{b\\235*!E@\\225|\\354.P\\312Q
 \\300p\\231\\323e1!E@');</programlisting>
 
-		<note><para>In PostgreSQL 9.1+ - standard_conforming_strings is set to on by default, where as in past versions it was set to on.  You can change defaults as needed
+		<note><para>In PostgreSQL 9.1+ - standard_conforming_strings is set to on by default, where as in past versions it was set to off.  You can change defaults as needed
 		    for a single query or at the database or server level.  Below is how you would do it with standard_conforming_strings = on.  In this case we escape the ' with standard ansi ',
 		    but slashes are not escaped</para></note>
 	<programlisting>
diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml
index be6ba16..dfd85ad 100644
--- a/doc/reference_raster.xml
+++ b/doc/reference_raster.xml
@@ -6423,12 +6423,17 @@ SELECT ST_PixelWidth(ST_Rescale(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.
 					<title>Examples</title>
 					<para>A simple example reskewing a raster from a skew of 0.0 to a skew of 0.0015.</para>
 
-					<programlisting>-- the original raster pixel size
-SELECT ST_Rotation(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0))
+					<programlisting>-- the original raster non-rotated
+SELECT ST_Rotation(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0));
 
--- the rescaled raster raster pixel size
-SELECT ST_Rotation(ST_Reskew(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0), 0.0015))
-                    </programlisting>
+-- result
+0
+					
+-- the reskewed raster raster rotation
+SELECT ST_Rotation(ST_Reskew(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0), 0.0015));
+
+-- result
+-0.982793723247329</programlisting>
 
 			</refsection>
 
@@ -6506,12 +6511,16 @@ SELECT ST_Rotation(ST_Reskew(ST_AddBand(ST_MakeEmptyRaster(100, 100, 0, 0, 0.001
 					<title>Examples</title>
 					<para>A simple example snapping a raster to a slightly different grid.</para>
 
-					<programlisting>-- the original raster pixel size
-SELECT ST_UpperLeftX(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0))
+					<programlisting>-- the original raster upper left X
+SELECT ST_UpperLeftX(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0));
+-- result
+0
+					
+-- the upper left of raster after snapping
+SELECT ST_UpperLeftX(ST_SnapToGrid(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0), 0.0002, 0.0002));
 
--- the rescaled raster raster pixel size
-SELECT ST_UpperLeftX(ST_SnapToGrid(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0.001, -0.001, 0, 0, 4269), '8BUI'::text, 1, 0), 0.0002, 0.0002))
-                    </programlisting>
+--result
+-0.0008</programlisting>
 
 			</refsection>
 
diff --git a/extensions/address_standardizer/Makefile b/extensions/address_standardizer/Makefile
index 407307e..d47d433 100644
--- a/extensions/address_standardizer/Makefile
+++ b/extensions/address_standardizer/Makefile
@@ -30,14 +30,14 @@ POSTGIS_PGSQL_VERSION=95
 SQLPP = /usr/bin/cpp -traditional-cpp -w -P
 GREP=/bin/grep
 PERL=/usr/bin/perl
-EXTVERSION    = 2.3.0beta1
+EXTVERSION    = 2.3.0rc1
 MINORVERSION  = 2.3
 MODULE_big = address_standardizer-2.3
 EXTENSION = address_standardizer
 DATA = address_standardizer_data_us.control sql/$(EXTENSION).sql sql/$(EXTENSION)_data_us.sql
 
 all:  sql/address_standardizer.sql sql/address_standardizer--1.0--$(EXTVERSION).sql sql/address_standardizer--$(EXTVERSION).sql sql/address_standardizer--$(EXTVERSION)--$(EXTVERSION)next.sql sql/address_standardizer--$(EXTVERSION)next--$(EXTVERSION).sql \
- sql/$(EXTENSION)_data_us.sql sql/address_standardizer--2.3.0beta1.sql sql/$(EXTENSION)_data_us--2.3.0beta1.sql  sql/$(EXTENSION)_data_us--$(EXTVERSION)--$(EXTVERSION)next.sql \
+ sql/$(EXTENSION)_data_us.sql sql/address_standardizer--2.3.0rc1.sql sql/$(EXTENSION)_data_us--2.3.0rc1.sql  sql/$(EXTENSION)_data_us--$(EXTVERSION)--$(EXTVERSION)next.sql \
 sql/$(EXTENSION)_data_us--$(EXTVERSION)next--$(EXTVERSION).sql \
 sql/test-init-extensions.sql sql/test-parseaddress.sql sql/test-standardize_address_1.sql sql/test-standardize_address_2.sql
 
@@ -68,7 +68,7 @@ sql/%.sql: %.sql.in
 	$(SQLPP) -I../libpgcommon $< | grep -v '^#' | \
 	$(PERL) -lpe "s'MODULE_PATHNAME'\$$libdir/${EXTENSION}-${MINORVERSION}'g" > $@
 	
-sql/address_standardizer--2.3.0beta1.sql: sql/address_standardizer_types.sql \
+sql/address_standardizer--2.3.0rc1.sql: sql/address_standardizer_types.sql \
     sql/address_standardizer_functions.sql
 	cat $^ > $@
 	
diff --git a/extensions/address_standardizer/address_standardizer.control b/extensions/address_standardizer/address_standardizer.control
index 4b2ad10..0155c7e 100644
--- a/extensions/address_standardizer/address_standardizer.control
+++ b/extensions/address_standardizer/address_standardizer.control
@@ -1,4 +1,4 @@
 # address_standardizer extension
 comment = 'Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 relocatable = true
diff --git a/extensions/address_standardizer/address_standardizer_data_us.control b/extensions/address_standardizer/address_standardizer_data_us.control
index 03c28e3..56160cf 100644
--- a/extensions/address_standardizer/address_standardizer_data_us.control
+++ b/extensions/address_standardizer/address_standardizer_data_us.control
@@ -1,4 +1,4 @@
 # address standardizer us dataset
 comment = 'Address Standardizer US dataset example'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 relocatable = true
diff --git a/extensions/postgis/Makefile b/extensions/postgis/Makefile
index 4d8e905..72a0f07 100644
--- a/extensions/postgis/Makefile
+++ b/extensions/postgis/Makefile
@@ -1,7 +1,7 @@
 include ../upgradeable_versions.mk
 
 EXTENSION     = postgis
-EXTVERSION    = 2.3.0beta1
+EXTVERSION    = 2.3.0rc1
 MINORVERSION  = 2.3
 GREP = /bin/grep
 PERL = /usr/bin/perl
diff --git a/extensions/postgis/postgis.control b/extensions/postgis/postgis.control
index 537a7e3..33f5b2f 100644
--- a/extensions/postgis/postgis.control
+++ b/extensions/postgis/postgis.control
@@ -1,5 +1,5 @@
 # postgis extension
 comment = 'PostGIS geometry, geography, and raster spatial types and functions'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 module_pathname = '$libdir/postgis-2.3'
 relocatable = false
diff --git a/extensions/postgis_sfcgal/Makefile b/extensions/postgis_sfcgal/Makefile
index 160869c..86e9e3d 100644
--- a/extensions/postgis_sfcgal/Makefile
+++ b/extensions/postgis_sfcgal/Makefile
@@ -1,7 +1,7 @@
 include ../upgradeable_versions.mk
 
 EXTENSION    = postgis_sfcgal
-EXTVERSION    = 2.3.0beta1
+EXTVERSION    = 2.3.0rc1
 MINORVERSION  = 2.3
 GREP = /bin/grep
 PERL = /usr/bin/perl
diff --git a/extensions/postgis_sfcgal/postgis_sfcgal.control b/extensions/postgis_sfcgal/postgis_sfcgal.control
index f74e22f..61f56f3 100644
--- a/extensions/postgis_sfcgal/postgis_sfcgal.control
+++ b/extensions/postgis_sfcgal/postgis_sfcgal.control
@@ -1,5 +1,5 @@
 # postgis topology extension
 comment = 'PostGIS SFCGAL functions'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 relocatable = true
 requires = postgis
diff --git a/extensions/postgis_tiger_geocoder/Makefile b/extensions/postgis_tiger_geocoder/Makefile
index 65000c9..1ef9c6f 100644
--- a/extensions/postgis_tiger_geocoder/Makefile
+++ b/extensions/postgis_tiger_geocoder/Makefile
@@ -1,7 +1,7 @@
 include ../upgradeable_versions.mk
 
 EXTENSION    = postgis_tiger_geocoder
-EXTVERSION    = 2.3.0beta1
+EXTVERSION    = 2.3.0rc1
 MINORVERSION  = 2011.2.3
 GREP = /bin/grep
 PERL = /usr/bin/perl
diff --git a/extensions/postgis_tiger_geocoder/postgis_tiger_geocoder.control b/extensions/postgis_tiger_geocoder/postgis_tiger_geocoder.control
index 15d1b33..2089692 100644
--- a/extensions/postgis_tiger_geocoder/postgis_tiger_geocoder.control
+++ b/extensions/postgis_tiger_geocoder/postgis_tiger_geocoder.control
@@ -1,6 +1,6 @@
 # postgis tiger geocoder extension
 comment = 'PostGIS tiger geocoder and reverse geocoder'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 relocatable = false
 schema = tiger
 requires = 'postgis,fuzzystrmatch'
diff --git a/extensions/postgis_topology/Makefile b/extensions/postgis_topology/Makefile
index f2bf6cf..d97d917 100644
--- a/extensions/postgis_topology/Makefile
+++ b/extensions/postgis_topology/Makefile
@@ -1,7 +1,7 @@
 include ../upgradeable_versions.mk
 
 EXTENSION     = postgis_topology
-EXTVERSION    = 2.3.0beta1
+EXTVERSION    = 2.3.0rc1
 MINORVERSION  = 2.3
 GREP = /bin/grep
 PERL = /usr/bin/perl
diff --git a/extensions/postgis_topology/postgis_topology.control b/extensions/postgis_topology/postgis_topology.control
index 4419af9..c9a53b5 100644
--- a/extensions/postgis_topology/postgis_topology.control
+++ b/extensions/postgis_topology/postgis_topology.control
@@ -1,6 +1,6 @@
 # postgis topology extension
 comment = 'PostGIS topology spatial types and functions'
-default_version = '2.3.0beta1'
+default_version = '2.3.0rc1'
 relocatable = false
 schema = topology
 requires = postgis
diff --git a/extensions/upgradeable_versions.mk b/extensions/upgradeable_versions.mk
index e10616d..d0a6586 100644
--- a/extensions/upgradeable_versions.mk
+++ b/extensions/upgradeable_versions.mk
@@ -20,7 +20,9 @@ UPGRADEABLE_VERSIONS = \
 	2.2.0 \
 	2.2.1 \
 	2.2.2 \
-	2.3.0dev
+	2.3.0dev \
+	2.3.0beta1 \
+	2.3.0rc1dev
 
 # This is to avoid forcing "check-installed-upgrades" as a default
 # rule, see https://trac.osgeo.org/postgis/ticket/3420
diff --git a/liblwgeom/cunit/cu_algorithm.c b/liblwgeom/cunit/cu_algorithm.c
index da44104..aed358f 100644
--- a/liblwgeom/cunit/cu_algorithm.c
+++ b/liblwgeom/cunit/cu_algorithm.c
@@ -1102,6 +1102,46 @@ static void test_point_density(void)
 	lwgeom_free(geom);
 }
 
+static void test_lwpoly_construct_circle(void)
+{
+	LWPOLY* p;
+	GBOX* g;
+	const int srid = 4326;
+	const int segments_per_quad = 17;
+	const int x = 10;
+	const int y = 20;
+	const int r = 5;
+
+	/* With normal arguments you should get something circle-y */
+	p = lwpoly_construct_circle(srid, x, y, r, segments_per_quad, LW_TRUE);
+
+	ASSERT_INT_EQUAL(lwgeom_count_vertices(p), segments_per_quad * 4 + 1);
+	ASSERT_INT_EQUAL(lwgeom_get_srid(lwpoly_as_lwgeom(p)), srid)
+
+	g = lwgeom_get_bbox(lwpoly_as_lwgeom(p));
+	CU_ASSERT_DOUBLE_EQUAL(g->xmin, x-r, 0.1);
+	CU_ASSERT_DOUBLE_EQUAL(g->xmax, x+r, 0.1);
+	CU_ASSERT_DOUBLE_EQUAL(g->ymin, y-r, 0.1);
+	CU_ASSERT_DOUBLE_EQUAL(g->ymax, y+r, 0.1);
+
+	CU_ASSERT_DOUBLE_EQUAL(lwgeom_area(p), M_PI*5*5, 0.1);
+
+	lwpoly_free(p);
+
+	/* No segments? No circle. */
+	p = lwpoly_construct_circle(srid, x, y, r, 0, LW_TRUE);
+	CU_ASSERT_TRUE(p == NULL);
+
+	/* Negative radius? No circle. */
+	p = lwpoly_construct_circle(srid, x, y, -1e-3, segments_per_quad, LW_TRUE);
+	CU_ASSERT_TRUE(p == NULL);
+
+	/* Zero radius? Invalid circle */
+	p = lwpoly_construct_circle(srid, x, y, 0, segments_per_quad, LW_TRUE);
+	CU_ASSERT_TRUE(p != NULL);
+	lwpoly_free(p);
+}
+
 static void test_kmeans(void)
 {
 	static int cluster_size = 100;
@@ -1172,4 +1212,5 @@ void algorithms_suite_setup(void)
 	PG_ADD_TEST(suite,test_kmeans);
 	PG_ADD_TEST(suite,test_median_handles_3d_correctly);
 	PG_ADD_TEST(suite,test_median_robustness);
+	PG_ADD_TEST(suite,test_lwpoly_construct_circle);
 }
diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index 653132e..e96839e 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1042,7 +1042,12 @@ extern LWCURVEPOLY* lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly);
 
 extern int lwcollection_ngeoms(const LWCOLLECTION *col);
 
-/* Given a generic geometry/collection, return the "simplest" form. */
+/* Given a generic geometry/collection, return the "simplest" form.
+ * The elements of the homogenized collection are references to the
+ * input geometry; a deep clone is not performed.
+ * TODO: consider returning a geometry that does not reference the
+ * input
+ * */
 extern LWGEOM *lwgeom_homogenize(const LWGEOM *geom);
 
 
@@ -1352,6 +1357,7 @@ extern LWLINE *lwline_removepoint(LWLINE *line, uint32_t which);
 extern void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint);
 extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes);
 extern LWPOLY* lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4);
+extern LWPOLY* lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior);
 extern LWTRIANGLE *lwtriangle_from_lwline(const LWLINE *shell);
 extern LWMPOINT *lwmpoint_from_lwgeom(const LWGEOM *g); /* Extract the coordinates of an LWGEOM into an LWMPOINT */
 
diff --git a/liblwgeom/lwpoly.c b/liblwgeom/lwpoly.c
index 115c0a5..2931330 100644
--- a/liblwgeom/lwpoly.c
+++ b/liblwgeom/lwpoly.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include "liblwgeom_internal.h"
 #include "lwgeom_log.h"
 
@@ -94,6 +95,45 @@ lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2,
 }
 
 LWPOLY*
+lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
+{
+	const int segments = 4*segments_per_quarter;
+	const double theta = 2*M_PI / segments;
+	LWPOLY *lwpoly;
+	POINTARRAY *pa;
+	POINT4D pt;
+	uint32_t i;
+
+	if (segments_per_quarter < 1)
+	{
+		lwerror("Need at least one segment per quarter-circle.");
+		return NULL;
+	}
+
+	if (radius < 0)
+	{
+		lwerror("Radius must be positive.");
+		return NULL;
+	}
+
+	lwpoly = lwpoly_construct_empty(srid, LW_FALSE, LW_FALSE);
+	pa = ptarray_construct_empty(LW_FALSE, LW_FALSE, segments + 1);
+
+	if (exterior)
+		radius *= sqrt(1 + pow(tan(theta/2), 2));
+
+	for (i = 0; i <= segments; i++)
+	{
+		pt.x = x + radius*sin(i * theta);
+		pt.y = y + radius*cos(i * theta);
+		ptarray_append_point(pa, &pt, LW_TRUE);
+	}
+
+	lwpoly_add_ring(lwpoly, pa);
+	return lwpoly;
+}
+
+LWPOLY*
 lwpoly_construct_empty(int srid, char hasz, char hasm)
 {
 	LWPOLY *result = lwalloc(sizeof(LWPOLY));
diff --git a/postgis/gserialized_estimate.c b/postgis/gserialized_estimate.c
index a8a9000..06180a7 100644
--- a/postgis/gserialized_estimate.c
+++ b/postgis/gserialized_estimate.c
@@ -2253,8 +2253,10 @@ Datum gserialized_estimated_extent(PG_FUNCTION_ARGS)
 	nd_stats = pg_get_nd_stats_by_name(tbl_oid, col, 2, only_parent);
 	
 	/* Error out on no stats */
-	if ( ! nd_stats )
-		elog(ERROR, "stats for \"%s.%s\" do not exist", tbl, text2cstring(col));
+	if ( ! nd_stats ) {
+		elog(WARNING, "stats for \"%s.%s\" do not exist", tbl, text2cstring(col));
+		PG_RETURN_NULL();
+	}
 
 	/* Construct the box */
 	gbox = palloc(sizeof(GBOX));
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index 1d684f9..a3aaeee 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -637,9 +637,9 @@ Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
 	lwgeom = lwgeom_from_gserialized(geom);
 	PG_FREE_IF_COPY(geom, 0);
 	
-	if (PG_NARGS() >2 && !PG_ARGISNULL(2))
+	if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
 	{
-		precision = PG_GETARG_INT32(2);
+		precision = PG_GETARG_INT32(1);
 		if ( precision < 0 ) precision = 5;
 	}
 
diff --git a/postgis/lwgeom_functions_analytic.c b/postgis/lwgeom_functions_analytic.c
index c1dbb97..922f5d9 100644
--- a/postgis/lwgeom_functions_analytic.c
+++ b/postgis/lwgeom_functions_analytic.c
@@ -53,6 +53,7 @@ Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_SetEffectiveArea(PG_FUNCTION_ARGS);
 Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS);
 Datum ST_MinimumBoundingRadius(PG_FUNCTION_ARGS);
+Datum ST_MinimumBoundingCircle(PG_FUNCTION_ARGS);
 Datum ST_GeometricMedian(PG_FUNCTION_ARGS);
 
 
@@ -1110,7 +1111,7 @@ Datum ST_MinimumBoundingRadius(PG_FUNCTION_ARGS)
 		input = lwgeom_from_gserialized(geom);
 		mbc = lwgeom_calculate_mbc(input);
 
-		if (!mbc)
+		if (!(mbc && mbc->center))
 		{
 			lwpgerror("Error calculating minimum bounding circle.");
 			lwgeom_free(input);
@@ -1144,6 +1145,61 @@ Datum ST_MinimumBoundingRadius(PG_FUNCTION_ARGS)
 
 /**********************************************************************
  *
+ * ST_MinimumBoundingCircle
+ *
+ **********************************************************************/
+
+PG_FUNCTION_INFO_V1(ST_MinimumBoundingCircle);
+Datum ST_MinimumBoundingCircle(PG_FUNCTION_ARGS)
+{
+	GSERIALIZED* geom;
+	LWGEOM* input;
+	LWBOUNDINGCIRCLE* mbc = NULL;
+	LWGEOM* lwcircle;
+	GSERIALIZED* center;
+	int segs_per_quarter;
+
+	if (PG_ARGISNULL(0))
+		PG_RETURN_NULL();
+
+	geom = PG_GETARG_GSERIALIZED_P(0);
+	segs_per_quarter = PG_GETARG_INT32(1);
+
+	/* Empty geometry? Return POINT EMPTY */
+	if (gserialized_is_empty(geom))
+	{
+		lwcircle = (LWGEOM*) lwpoint_construct_empty(gserialized_get_srid(geom), LW_FALSE, LW_FALSE);
+	}
+	else
+	{
+		input = lwgeom_from_gserialized(geom);
+		mbc = lwgeom_calculate_mbc(input);
+
+		if (!(mbc && mbc->center))
+		{
+			lwpgerror("Error calculating minimum bounding circle.");
+			lwgeom_free(input);
+			PG_RETURN_NULL();
+		}
+
+		/* Zero radius? Return a point. */
+		if (mbc->radius == 0)
+			lwcircle = lwpoint_as_lwgeom(lwpoint_make2d(input->srid, mbc->center->x, mbc->center->y));
+		else
+			lwcircle = lwpoly_as_lwgeom(lwpoly_construct_circle(input->srid, mbc->center->x, mbc->center->y, mbc->radius, segs_per_quarter, LW_TRUE));
+
+		lwboundingcircle_destroy(mbc);
+		lwgeom_free(input);
+	}
+
+	center = geometry_serialize(lwcircle);
+	lwgeom_free(lwcircle);
+
+	PG_RETURN_POINTER(center);
+}
+
+/**********************************************************************
+ *
  * ST_GeometricMedian
  *
  **********************************************************************/
diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c
index 34e85f3..1b78e5a 100644
--- a/postgis/lwgeom_functions_basic.c
+++ b/postgis/lwgeom_functions_basic.c
@@ -2643,14 +2643,17 @@ Datum ST_CollectionHomogenize(PG_FUNCTION_ARGS)
 
 	lwoutput = lwgeom_homogenize(lwgeom);
 	lwgeom_free(lwgeom);
-	PG_FREE_IF_COPY(input, 0);
 
 	if ( ! lwoutput )
+	{
 		PG_RETURN_NULL();
+		PG_FREE_IF_COPY(input, 0);
+	}
 
 	output = geometry_serialize(lwoutput);
 	lwgeom_free(lwoutput);
 
+	PG_FREE_IF_COPY(input, 0);
 	PG_RETURN_POINTER(output);
 }
 
@@ -2701,7 +2704,7 @@ Datum ST_FlipCoordinates(PG_FUNCTION_ARGS)
 static LWORD ordname2ordval(char n)
 {
   if ( n == 'x' || n == 'X' ) return LWORD_X;
-  if ( n == 'y' || n == 'y' ) return LWORD_Y;
+  if ( n == 'y' || n == 'Y' ) return LWORD_Y;
   if ( n == 'z' || n == 'Z' ) return LWORD_Z;
   if ( n == 'm' || n == 'M' ) return LWORD_M;
   lwpgerror("Invalid ordinate name '%c'. Expected x,y,z or m", n);
diff --git a/postgis/lwgeom_in_encoded_polyline.c b/postgis/lwgeom_in_encoded_polyline.c
index bbba36b..053d2fc 100644
--- a/postgis/lwgeom_in_encoded_polyline.c
+++ b/postgis/lwgeom_in_encoded_polyline.c
@@ -47,9 +47,9 @@ Datum line_from_encoded_polyline(PG_FUNCTION_ARGS)
   encodedpolyline_input = PG_GETARG_TEXT_P(0);
   encodedpolyline = text2cstring(encodedpolyline_input);
 
-  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
+  if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
   {
-    precision = PG_GETARG_INT32(2);
+    precision = PG_GETARG_INT32(1);
     if ( precision < 0 ) precision = 5;
   }
 
diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in
index d97f82b..8c33224 100644
--- a/postgis/postgis.sql.in
+++ b/postgis/postgis.sql.in
@@ -3305,9 +3305,9 @@ CREATE OR REPLACE FUNCTION ST_MinimumBoundingRadius(geometry, OUT center geometr
 
 -- Availability: 1.4.0
 CREATE OR REPLACE FUNCTION ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer DEFAULT 48)
-	RETURNS geometry
-    AS $$ SELECT @extschema at .ST_Buffer(center, radius, segs_per_quarter) FROM @extschema at .ST_MinimumBoundingRadius($1) sq $$
-	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;
+    RETURNS geometry
+    AS 'MODULE_PATHNAME', 'ST_MinimumBoundingCircle'
+    LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;
 
 -- Availability: 2.0.0 - requires GEOS-3.2 or higher
 CREATE OR REPLACE FUNCTION ST_OffsetCurve(line geometry, distance float8, params text DEFAULT '')
diff --git a/postgis/sqldefines.h b/postgis/sqldefines.h
index 12f8fb6..0318de1 100644
--- a/postgis/sqldefines.h
+++ b/postgis/sqldefines.h
@@ -9,7 +9,7 @@
 #define POSTGIS_PGSQL_VERSION 95
 #define POSTGIS_GEOS_VERSION 35
 #define POSTGIS_PROJ_VERSION 49
-#define POSTGIS_LIB_VERSION '2.3.0beta1'
+#define POSTGIS_LIB_VERSION '2.3.0rc1'
 #define POSTGIS_LIBXML2_VERSION 2.9.4
 #define POSTGIS_SFCGAL_VERSION 13
 
@@ -25,12 +25,12 @@
  * won't substitute within apostrophes)
  */
 #define _POSTGIS_SQL_SELECT_POSTGIS_VERSION 'SELECT ''2.3 USE_GEOS=1 USE_PROJ=1 USE_STATS=1''::text AS version'
-#define _POSTGIS_SQL_SELECT_POSTGIS_BUILD_DATE 'SELECT ''2016-09-06 06:24:58''::text AS version'
+#define _POSTGIS_SQL_SELECT_POSTGIS_BUILD_DATE 'SELECT ''2016-09-19 05:38:21''::text AS version'
 
 #if POSTGIS_SVN_REVISION
-#define _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION $$ SELECT '2.3.0beta1'::text || ' r' || POSTGIS_SVN_REVISION::text AS version $$
+#define _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION $$ SELECT '2.3.0rc1'::text || ' r' || POSTGIS_SVN_REVISION::text AS version $$
 #else
-#define _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION $$ SELECT '2.3.0beta1'::text AS version $$
+#define _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION $$ SELECT '2.3.0rc1'::text AS version $$
 #endif
 
 #define SRID_USR_MAX 998999
diff --git a/postgis_svn_revision.h b/postgis_svn_revision.h
index 9f4be6a..b6ad93e 100644
--- a/postgis_svn_revision.h
+++ b/postgis_svn_revision.h
@@ -1 +1 @@
-#define POSTGIS_SVN_REVISION 15063
+#define POSTGIS_SVN_REVISION 15121
diff --git a/raster/rt_pg/Makefile.in b/raster/rt_pg/Makefile.in
index 46bf574..ed54859 100644
--- a/raster/rt_pg/Makefile.in
+++ b/raster/rt_pg/Makefile.in
@@ -54,7 +54,7 @@ OBJS = \
 # Note: we specify liblwgeom.a directly in SHLIB_LINK rather than using
 # -L... -l options to prevent issues with some platforms trying to link
 # to an existing liblwgeom.so in the PostgreSQL $libdir supplied by an
-# older version of PostGIS, rather than with the static liblwgeom.a 
+# older version of PostGIS, rather than with the static liblwgeom.a
 # supplied with newer versions of PostGIS
 #
 LIBLWGEOM_LDFLAGS=../../liblwgeom/.libs/liblwgeom.a
@@ -67,13 +67,13 @@ LIBPROJ_CFLAGS=@PROJ_CPPFLAGS@
 
 override CFLAGS := $(LIBLWGEOM_CFLAGS) $(CFLAGS)
 PG_CPPFLAGS+= @CPPFLAGS@ $(LIBGDAL_CFLAGS) $(LIBPGCOMMON_CFLAGS) $(LIBPROJ_CFLAGS) -I../rt_core
-SHLIB_LINK_F = ../rt_core/librtcore.a $(LIBLWGEOM_LDFLAGS) $(LIBPGCOMMON_LDFLAGS) $(LIBGDAL_LDFLAGS) @SHLIB_LINK@ 
+SHLIB_LINK_F = ../rt_core/librtcore.a $(LIBLWGEOM_LDFLAGS) $(LIBPGCOMMON_LDFLAGS) $(LIBGDAL_LDFLAGS) @SHLIB_LINK@
 
 # Extra files to remove during 'make clean'
-EXTRA_CLEAN=$(SQL_OBJS) $(DATA_built) rtpostgis_upgrade.sql.in
+EXTRA_CLEAN=$(SQL_OBJS) $(DATA_built) rtpostgis_upgrade.sql.in rtpostgis_upgrade_for_extension.sql.in
 
 # PGXS information
-PG_CONFIG = @PG_CONFIG@ 
+PG_CONFIG = @PG_CONFIG@
 PGXS := @PGXS@
 # NO_TEMP_INSTALL is a workaround for a 9.5dev bug. See:
 # http://www.postgresql.org/message-id/CAB7nPqTsR5o3g-fBi6jbsVdhfPiLFWQ_0cGU5=94Rv_8W3qvFA@mail.gmail.com
@@ -103,7 +103,7 @@ endif
 %.sql: %.sql.in
 	$(SQLPP) -I../../postgis/ -I../../ $< | grep -v '^#' | \
 	$(PERL) -lpe "s'MODULE_PATHNAME'\$$libdir/rtpostgis- at POSTGIS_MAJOR_VERSION@. at POSTGIS_MINOR_VERSION@'g;s'@extschema@\.''g" > $@
-	
+
 rtpostgis_for_extension.sql: rtpostgis.sql.in
 	$(SQLPP) -I../../postgis/ -I../../ $< | grep -v '^#' | \
 	$(PERL) -lpe "s'MODULE_PATHNAME'\$$libdir/rtpostgis- at POSTGIS_MAJOR_VERSION@. at POSTGIS_MINOR_VERSION@'g" > $@
@@ -128,10 +128,10 @@ $(SQL_OBJS): ../../postgis/sqldefines.h ../../postgis_svn_revision.h
 #this is redundant but trying to fold in with the  other just hangs
 rtpostgis_upgrade.sql.in: rtpostgis.sql ../../utils/postgis_proc_upgrade.pl
 	$(PERL) ../../utils/postgis_proc_upgrade.pl $< UNUSED > $@
-	
+
 rtpostgis_upgrade_for_extension.sql.in: rtpostgis_for_extension.sql ../../utils/postgis_proc_upgrade.pl
 	$(PERL) ../../utils/postgis_proc_upgrade.pl $< UNUSED > $@
-	
+
 rtpostgis_proc_set_search_path.sql: rtpostgis.sql ../../utils/postgis_proc_set_search_path.pl
 	$(PERL) ../../utils/postgis_proc_set_search_path.pl $< UNUSED > $@
 
@@ -139,14 +139,14 @@ rtpostgis_upgrade.sql: rtpostgis_upgrade_cleanup.sql rtpostgis_upgrade.sql.in rt
 	echo 'BEGIN;' > $@
 	cat $^ | sed -e 's/^BEGIN;$$//' -e 's/^COMMIT;$$//' >> $@
 	echo 'COMMIT;' >> $@
-	
+
 #this keeps the @extschema at . in place since extension machinery will replace during install
 rtpostgis_upgrade_for_extension.sql: rtpostgis_upgrade_cleanup.sql rtpostgis_upgrade_for_extension.sql.in rtpostgis_drop.sql
 	echo 'BEGIN;' > $@
 	cat $^ | sed -e 's/^BEGIN;$$//' -e 's/^COMMIT;$$//' >> $@
 	echo 'COMMIT;' >> $@
 
-uninstall_rtpostgis.sql: rtpostgis.sql ../../utils/create_undef.pl 
+uninstall_rtpostgis.sql: rtpostgis.sql ../../utils/create_undef.pl
 	$(PERL) ../../utils/create_undef.pl $< $(POSTGIS_PGSQL_VERSION) > $@
 
 distclean: clean
diff --git a/raster/rt_pg/rtpostgis.sql.in b/raster/rt_pg/rtpostgis.sql.in
index a5aba3b..15a08d2 100644
--- a/raster/rt_pg/rtpostgis.sql.in
+++ b/raster/rt_pg/rtpostgis.sql.in
@@ -7148,7 +7148,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_extent(rastschema name, rastta
 
 		cn := 'enforce_max_extent_' || $3;
 
-		sql := 'SELECT st_ashexewkb(st_envelope(st_collect(st_envelope('
+		sql := 'SELECT @extschema at .st_ashexewkb( @extschema at .st_envelope( @extschema at .st_union( @extschema at .st_envelope('
 			|| quote_ident($3)
 			|| ')))) FROM '
 			|| fqtn;
@@ -7202,7 +7202,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_alignment(rastschema name, ras
 
 		cn := 'enforce_same_alignment_' || $3;
 
-		sql := 'SELECT st_makeemptyraster(1, 1, upperleftx, upperlefty, scalex, scaley, skewx, skewy, srid) FROM st_metadata((SELECT '
+		sql := 'SELECT @extschema at .st_makeemptyraster(1, 1, upperleftx, upperlefty, scalex, scaley, skewx, skewy, srid) FROM @extschema at .st_metadata((SELECT '
 			|| quote_ident($3)
 			|| ' FROM ' || fqtn || ' LIMIT 1))';
 		BEGIN
@@ -7342,7 +7342,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_coverage_tile(rastschema name,
 
 		-- metadata
 		BEGIN
-			sql := 'WITH foo AS (SELECT ST_Metadata(' || quote_ident($3) || ') AS meta, ST_ConvexHull(' || quote_ident($3) || ') AS hull FROM ' || fqtn || ') SELECT max((meta).scalex), max((meta).scaley), max((meta).skewx), max((meta).skewy), max((meta).width), max((meta).height), ST_Union(hull) FROM foo';
+			sql := 'WITH foo AS (SELECT @extschema at .ST_Metadata(' || quote_ident($3) || ') AS meta, @extschema at .ST_ConvexHull(' || quote_ident($3) || ') AS hull FROM ' || fqtn || ') SELECT max((meta).scalex), max((meta).scaley), max((meta).skewx), max((meta).skewy), max((meta).width), max((meta).height), @extschema at .ST_Union(hull) FROM foo';
 			EXECUTE sql INTO _scalex, _scaley, _skewx, _skewy, _tilewidth, _tileheight, _covextent;
 		EXCEPTION WHEN OTHERS THEN
 			RAISE DEBUG 'Unable to get coverage metadata for %.%: % (%)',
@@ -7352,7 +7352,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_coverage_tile(rastschema name,
 
 		-- rasterize extent
 		BEGIN
-			_covrast := ST_AsRaster(_covextent, _scalex, _scaley, '8BUI', 1, 0, NULL, NULL, _skewx, _skewy);
+			_covrast := @extschema at .ST_AsRaster(_covextent, _scalex, _scaley, '8BUI', 1, 0, NULL, NULL, _skewx, _skewy);
 			IF _covrast IS NULL THEN
 				RAISE NOTICE 'Unable to create coverage raster. Cannot add coverage tile constraint: % (%)',
           SQLERRM, SQLSTATE;
@@ -7441,7 +7441,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_num_bands(rastschema name, ras
 
 		cn := 'enforce_num_bands_' || $3;
 
-		sql := 'SELECT st_numbands(' || quote_ident($3)
+		sql := 'SELECT @extschema at .st_numbands(' || quote_ident($3)
 			|| ') FROM ' || fqtn
 			|| ' LIMIT 1';
 		BEGIN
@@ -7454,7 +7454,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_num_bands(rastschema name, ras
 
 		sql := 'ALTER TABLE ' || fqtn
 			|| ' ADD CONSTRAINT ' || quote_ident(cn)
-			|| ' CHECK (st_numbands(' || quote_ident($3)
+			|| ' CHECK (@extschema at .st_numbands(' || quote_ident($3)
 			|| ') = ' || attr
 			|| ')';
 		RETURN  @extschema at ._add_raster_constraint(cn, sql);
@@ -7703,7 +7703,7 @@ CREATE OR REPLACE FUNCTION _add_raster_constraint_out_db(rastschema name, rastta
 
 		sql := 'ALTER TABLE ' || fqtn
 			|| ' ADD CONSTRAINT ' || quote_ident(cn)
-			|| ' CHECK (_raster_constraint_out_db(' || quote_ident($3)
+			|| ' CHECK ( @extschema at ._raster_constraint_out_db(' || quote_ident($3)
 			|| ') = ''{';
 		FOR x in 1..max LOOP
 			IF attr[x] IS FALSE THEN
@@ -8775,7 +8775,8 @@ BEGIN
   PERFORM  @extschema at .AddOverviewConstraints(sinfo.sch, ttab, col,
                                  sinfo.sch, sinfo.tab, col, factor);
 
-  RETURN ttab;
+    -- return the schema as well as the table
+  RETURN sinfo.sch||'.'||ttab;
 END;
 $$ LANGUAGE 'plpgsql' VOLATILE STRICT;
 
diff --git a/raster/test/regress/rt_createoverview.sql b/raster/test/regress/rt_createoverview.sql
index 3cc172c..46cf51d 100644
--- a/raster/test/regress/rt_createoverview.sql
+++ b/raster/test/regress/rt_createoverview.sql
@@ -1,4 +1,5 @@
 SET client_min_messages TO warning;
+-- Test for table without explicit schema
 CREATE TABLE res1 AS SELECT
   ST_AddBand(
     ST_MakeEmptyRaster(10, 10, x, y, 1, -1, 0, 0, 0)
@@ -46,9 +47,94 @@ SELECT 'count',
 (SELECT count(*) r16 from o_16_res1)
 ;
 
+-- End of overview test on table without explicit schema
 
 DROP TABLE o_16_res1;
 DROP TABLE o_8_res1;
 DROP TABLE o_4_res1;
 DROP TABLE o_2_res1;
+-- Keep the source table 
+
+
+-- Test overview with table in schema
+-- 
+CREATE SCHEMA oschm;
+-- offset the schema tableto distinguish it from original
+-- let it be small to reduce time cost. 
+CREATE TABLE oschm.res1 AS SELECT
+  ST_AddBand(
+    ST_MakeEmptyRaster(10, 10, x, y, 1, -1, 0, 0, 0)
+    , 1, '8BUI', 0, 0
+  ) r
+FROM generate_series(100, 270, 10) x,
+     generate_series(140, -30, -10) y;
+SELECT addrasterconstraints('oschm'::name,'res1'::name, 'r'::name);
+
+-- add overview with explicit schema
+SELECT ST_CreateOverview('oschm.res1', 'r', 8)::text = 'oschm.o_8_res1';
+
+-- set search path to 'oschm' first
+SET search_path to oschm,public;
+
+-- create overview with schema in search_path
+SELECT ST_CreateOverview('res1', 'r', 4)::text = 'o_4_res1';
+
+-- Create overview for table in public schema with explict path
+-- at same factor of schema table
+SELECT ST_CreateOverview('public.res1', 'r', 8)::text = 'public.o_8_res1';
+ 
+-- Reset the search_path
+SET search_path to public;
+
+-- Create public overview of public table with same name
+-- and scale as schema table above using reset search path.
+SELECT ST_CreateOverview('res1', 'r', 4)::text = 'o_4_res1';
+
+-- Check scale and extent 
+-- Offset means that original raster overviews won't match
+-- extent and values only mach on schema table not public one
+SELECT r_table_schema, r_table_name tab, r_raster_column c,
+ srid s, scale_x sx, scale_y sy,
+ blocksize_x w, blocksize_y h, same_alignment a,
+ -- regular_blocking (why not regular?)
+ --extent::box2d e,
+ st_covers(extent::box2d, 'BOX(100 -30,270 140)'::box2d) ec,
+ st_xmin(extent::box2d) = 100 as eix,
+ st_ymax(extent::box2d) = 140 as eiy,
+ (st_xmax(extent::box2d) - 280) <= scale_x as eox,
+ --(st_xmax(extent::box2d) - 170) eoxd,
+ abs(st_ymin(extent::box2d) + 40) <= abs(scale_y) as eoy
+ --,abs(st_ymin(extent::box2d) + 80) eoyd
+ FROM raster_columns
+WHERE r_table_name like '%res1'
+ORDER BY r_table_schema, scale_x, r_table_name;
+
+-- this test may be redundant - it's just confirming that the
+-- overview factor is correct, which we do for the original table.
+SELECT o_table_schema, o_table_name, o_raster_column,
+       r_table_schema, r_table_name, r_raster_column, overview_factor
+FROM raster_overviews
+WHERE r_table_name = 'res1'
+AND   r_table_schema = 'oschm'
+ORDER BY o_table_schema,overview_factor;
+-- get the oschm table sizes
+SELECT 'count',
+(SELECT count(*) r1 from oschm.res1),
+(SELECT count(*) r4 from oschm.o_4_res1),
+(SELECT count(*) r8 from oschm.o_8_res1) ;
+
+-- clean up scheam oschm
+DROP TABLE oschm.o_8_res1;
+DROP TABLE oschm.o_4_res1;
+DROP TABLE oschm.res1;
+DROP SCHEMA oschm;
+
+-- Drop the tables for noschema test
+DROP TABLE o_8_res1;
+DROP TABLE o_4_res1;
 DROP TABLE res1;
+
+-- Reset the session environment 
+-- possibly a bit harsh, but we had to set the search_path
+-- and need to reset it back to default.
+DISCARD ALL;
diff --git a/raster/test/regress/rt_createoverview_expected b/raster/test/regress/rt_createoverview_expected
index 7173bca..e3afec4 100644
--- a/raster/test/regress/rt_createoverview_expected
+++ b/raster/test/regress/rt_createoverview_expected
@@ -13,3 +13,17 @@ o_4_res1|r|res1|r|4
 o_8_res1|r|res1|r|8
 o_16_res1|r|res1|r|16
 count|544|136|36|10|3
+t
+t
+t
+t
+t
+oschm|res1|r|0|1|-1|10|10|t|t|t|t|t|t
+oschm|o_4_res1|r|0|4|-4|10|10|t|t|t|t|t|t
+oschm|o_8_res1|r|0|8|-8|10|10|t|t|t|t|t|t
+public|res1|r|0|1|-1|10|10|t|f|f|f|t|f
+public|o_4_res1|r|0|4|-4|10|10|t|f|f|f|t|f
+public|o_8_res1|r|0|8|-8|10|10|t|f|f|f|t|f
+oschm|o_4_res1|r|oschm|res1|r|4
+oschm|o_8_res1|r|oschm|res1|r|8
+count|324|25|9
diff --git a/regress/estimatedextent_expected b/regress/estimatedextent_expected
index d3ae7c3..f51bedb 100644
--- a/regress/estimatedextent_expected
+++ b/regress/estimatedextent_expected
@@ -1,15 +1,23 @@
-ERROR:  stats for "t.g" do not exist
-ERROR:  stats for "t.g" do not exist
+WARNING:  stats for "t.g" do not exist
+#877.1|
+WARNING:  stats for "t.g" do not exist
+#877.2|
 WARNING:  ST_Estimated_Extent signature was deprecated in 2.1.0. Please use ST_EstimatedExtent
-ERROR:  stats for "t.g" do not exist
-ERROR:  stats for "t.g" do not exist
+WARNING:  stats for "t.g" do not exist
+#877.2.deprecated|
+WARNING:  stats for "t.g" do not exist
+#877.3||||
 #877.4|-10.15000|20.15000|-50.40000|30.40000
 #877.5|-10.15000|20.15000|-50.40000|30.40000
-ERROR:  stats for "c1.g" do not exist
-ERROR:  stats for "c2.g" do not exist
-ERROR:  stats for "p.g" do not exist
+WARNING:  stats for "c1.g" do not exist
+#3391.1||||
+WARNING:  stats for "c2.g" do not exist
+#3391.2||||
+WARNING:  stats for "p.g" do not exist
+#3391.3||||
 #3391.4|0.00|1.00|0.00|1.00
-ERROR:  stats for "c2.g" do not exist
+WARNING:  stats for "c2.g" do not exist
+#3391.5||||
 #3391.6|0.00|1.00|0.00|1.00
 #3391.7|0.00|1.00|0.00|1.00
 #3391.8|-1.00|0.00|-1.00|0.00
@@ -17,12 +25,17 @@ ERROR:  stats for "c2.g" do not exist
 #3391.10|0.00|1.00|0.00|1.00
 #3391.11|-1.00|0.00|-1.00|0.00
 #3391.12|-1.01|2.02|-1.01|2.02
-ERROR:  stats for "p.g" do not exist
-ERROR:  stats for "p.g" do not exist
-ERROR:  stats for "c1.g" do not exist
-ERROR:  stats for "c1.g" do not exist
+WARNING:  stats for "p.g" do not exist
+#3391.13||||
+WARNING:  stats for "p.g" do not exist
+#3391.14||||
+WARNING:  stats for "c1.g" do not exist
+#3391.15||||
+WARNING:  stats for "c1.g" do not exist
+#3391.16||||
 #3391.17|0.00|1.00|0.00|1.00
-ERROR:  stats for "p.g" do not exist
+WARNING:  stats for "p.g" do not exist
+#3391.18||||
 #3391.19|0.00|1.00|0.00|1.00
 #3391.20|0.00|1.00|0.00|1.00
 NOTICE:  drop cascades to 2 other objects
diff --git a/regress/in_encodedpolyline.sql b/regress/in_encodedpolyline.sql
index 604fbc1..1fba56a 100644
--- a/regress/in_encodedpolyline.sql
+++ b/regress/in_encodedpolyline.sql
@@ -1,2 +1,2 @@
 select 'linefromencodedpolyline_01',st_asewkt(st_linefromencodedpolyline('_p~iF~ps|U_ulLnnqC_mqNvxq`@'));
-select 'linefromencodedpolyline_02',st_asewkt(st_linefromencodedpolyline('_p~iFlhz|UuksL`wjCivjNvxq`@', 6));
+select 'linefromencodedpolyline_02',st_asewkt(ST_SnapToGrid(st_linefromencodedpolyline('_izlhAj}oidF{}jgCrotj at chtxCn`{nI', 6),0.001));
diff --git a/regress/in_encodedpolyline_expected b/regress/in_encodedpolyline_expected
index 7024958..b0d6262 100644
--- a/regress/in_encodedpolyline_expected
+++ b/regress/in_encodedpolyline_expected
@@ -1,2 +1,2 @@
 linefromencodedpolyline_01|SRID=4326;LINESTRING(-120.2 38.5,-120.95 40.7,-126.453 43.252)
-linefromencodedpolyline_02|SRID=4326;LINESTRING(-120.23447 38.5,-120.95 40.73435,-126.453 43.252)
+linefromencodedpolyline_02|SRID=4326;LINESTRING(-120.234 38.5,-120.95 40.734,-126.453 43.252)
diff --git a/regress/in_geojson.sql b/regress/in_geojson.sql
index e535f42..8e41fc4 100644
--- a/regress/in_geojson.sql
+++ b/regress/in_geojson.sql
@@ -45,3 +45,6 @@ SELECT 'geomfromgeojson_srs_1', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryC
 SELECT 'geomfromgeojson_srs_2', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}'));
 SELECT 'geomfromgeojson_srs_3', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","props":{"name":"urn:ogc:def:crs:EPSG::4326"}}}'));
 SELECT 'geomfromgeojson_srs_4', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"nm":"EPSG:4326"}}}'));
+
+-- #3583
+SELECT '#3583', ST_AsText(ST_GeomFromGeoJSON('{"type":"MultiPolygon", "coordinates":[[[139.10030364990232,35.16777444430609],5842.4224490305424]]}'));
diff --git a/regress/in_geojson_expected b/regress/in_geojson_expected
index ddedb90..fc66ab8 100644
--- a/regress/in_geojson_expected
+++ b/regress/in_geojson_expected
@@ -27,3 +27,4 @@ geomfromgeojson_srs_1|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
 geomfromgeojson_srs_2|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
 geomfromgeojson_srs_3|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
 geomfromgeojson_srs_4|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
+#3583|MULTIPOLYGON Z (EMPTY)
diff --git a/regress/out_geometry_expected b/regress/out_geometry_expected
index 9e6b084..f045640 100644
--- a/regress/out_geometry_expected
+++ b/regress/out_geometry_expected
@@ -41,7 +41,7 @@ kml_projection_01|<Point><coordinates>-74.078,4.596</coordinates></Point>
 encoded_polyline_01|_p~iF~ps|U_ulLnnqC_mqNvxq`@
 encoded_polyline_02|_p~iF~ps|U_ulLnnqC_mqNvxq`@
 ERROR:  Only SRID 4326 is supported.
-encoded_polyline_04|_p~iFlhz|UuksL`wjCivjNvxq`@
+encoded_polyline_04|_izlhAd}oidF{}jgCxotj at chtxCn`{nI
 svg_empty_geom|
 svg_option_01|M 1 -1 L 4 -4 5 -7
 svg_option_02|M 1 -1 l 3 -3 1 -3
diff --git a/regress/run_test.pl b/regress/run_test.pl
index 5eabf43..9237d8f 100755
--- a/regress/run_test.pl
+++ b/regress/run_test.pl
@@ -22,11 +22,18 @@ use Cwd 'abs_path';
 use Getopt::Long;
 use strict;
 
+##################################################################
+# Add . to @INC if removed for CVE-2016-1238
+##################################################################
+BEGIN {
+	push @INC, "." if(!grep /^\.$/, @INC);
+}
+
 
 ##################################################################
 # Usage ./run_test.pl <testname> [<testname>]
 #
-#  Create the spatial database 'postgis_reg' (or whatever $DB 
+#  Create the spatial database 'postgis_reg' (or whatever $DB
 #  is set to) if it doesn't already exist.
 #
 #  Run the <testname>.sql script
@@ -67,7 +74,7 @@ my $VERBOSE = 0;
 GetOptions (
 	'verbose' => \$VERBOSE,
 	'clean' => \$OPT_CLEAN,
-	'nodrop' => \$OPT_NODROP, 
+	'nodrop' => \$OPT_NODROP,
 	'upgrade' => \$OPT_UPGRADE,
 	'upgrade-path=s' => \$OPT_UPGRADE_PATH,
 	'dumprestore' => \$OPT_DUMPRESTORE,
@@ -90,7 +97,7 @@ if ( $OPT_UPGRADE_PATH )
   {
     die "--upgrade-path is only supported with --extension"
   }
-  $OPT_UPGRADE = 1; # implied 
+  $OPT_UPGRADE = 1; # implied
   my @path = split ('--', $OPT_UPGRADE_PATH);
   $OPT_UPGRADE_FROM = $path[0]
     || die "Malformed upgrade path, <from>--<to> expected, $OPT_UPGRADE_PATH given";
@@ -163,7 +170,7 @@ foreach my $exec ( ($SHP2PGSQL, $PGSQL2SHP) )
 		print "failed\n";
 		die "Unable to find $exec executable.\n";
 	}
-	
+
 }
 
 if ( $OPT_WITH_RASTER )
@@ -386,13 +393,13 @@ foreach $TEST (@ARGV)
 
 	start_test($TEST);
 
-	# Check for a "-pre.pl" file in case there are setup commands 
+	# Check for a "-pre.pl" file in case there are setup commands
     eval_file("${TEST}-pre.pl");
 
 	# Check for a "-pre.sql" file in case there is setup SQL needed before
 	# the test can be run.
 	if ( -r "${TEST}-pre.sql" )
-	{	
+	{
 		run_simple_sql("${TEST}-pre.sql");
 		show_progress();
 	}
@@ -435,18 +442,18 @@ foreach $TEST (@ARGV)
 			print " ... but cleanup sql failed!";
 		}
 	}
-	
-	# Check for a "-post.pl" file in case there are teardown commands 
+
+	# Check for a "-post.pl" file in case there are teardown commands
     eval_file("${TEST}-post.pl");
-	
+
 }
 
 
-################################################################### 
+###################################################################
 # Uninstall postgis (serves as an uninstall test)
 ##################################################################
 
-# We only test uninstall if we've been asked to drop 
+# We only test uninstall if we've been asked to drop
 # and we did create
 # and nobody requested raster or topology
 # (until they have an uninstall script themself)
@@ -490,7 +497,7 @@ exit($FAIL);
 # Utility functions
 #
 
-sub usage 
+sub usage
 {
 	die qq{
 Usage: $0 [<options>] <testname> [<testname>]
@@ -533,7 +540,7 @@ sub show_progress
 	print ".";
 }
 
-# pass <msg> 
+# pass <msg>
 sub pass
 {
   my $msg = shift;
@@ -567,10 +574,10 @@ sub fail
 	$FAIL++;
 }
 
-  
+
 
 ##################################################################
-# run_simple_sql 
+# run_simple_sql
 #   Run an sql script and hide results unless it fails.
 #   SQL input file name is $1
 ##################################################################
@@ -578,7 +585,7 @@ sub run_simple_sql
 {
 	my $sql = shift;
 
-	if ( ! -r $sql ) 
+	if ( ! -r $sql )
 	{
 		fail("can't read $sql");
 		return 0;
@@ -590,18 +597,18 @@ sub run_simple_sql
 	#print($cmd);
 	my $rv = system($cmd);
 	# Check if psql errored out.
-	if ( $rv != 0 ) 
+	if ( $rv != 0 )
 	{
 		fail("Unable to run sql script $sql", $tmpfile);
 		return 0;
 	}
-	
+
 	# Check for ERROR lines
 	open FILE, "$tmpfile";
 	my @lines = <FILE>;
 	close FILE;
 	my @errors = grep(/^ERROR/, @lines);
-	
+
 	if ( @errors > 0 )
 	{
 		fail("Errors while running sql script $sql", $tmpfile);
@@ -617,7 +624,7 @@ sub drop_table
 	my $tblname = shift;
 	my $cmd = "psql -tXA -d $DB -c \"DROP TABLE IF EXISTS $tblname\" >> $REGRESS_LOG 2>&1";
 	my $rv = system($cmd);
-	die "Could not run: $cmd\n" if $rv;	
+	die "Could not run: $cmd\n" if $rv;
 }
 
 sub sql
@@ -643,7 +650,7 @@ sub eval_file
 }
 
 ##################################################################
-# run_simple_test 
+# run_simple_test
 #   Run an sql script and compare results with the given expected output
 #   SQL input is ${TEST}.sql, expected output is {$TEST}_expected
 ##################################################################
@@ -658,7 +665,7 @@ sub run_simple_test
 		fail("can't read $sql");
 		return 0;
 	}
-	
+
 	if ( ! $OPT_EXPECT )
 	{
 		if ( ! -r "$expected" )
@@ -706,7 +713,7 @@ sub run_simple_test
 	@lines = grep(!/^(INSERT|DELETE|UPDATE|SELECT|COPY|DO)/, @lines);
 	@lines = grep(!/^(CONTEXT|RESET|ANALYZE)/, @lines);
 	@lines = grep(!/^(DROP|CREATE|ALTER|VACUUM)/, @lines);
-	@lines = grep(!/^(LOG|SET|TRUNCATE)/, @lines);
+	@lines = grep(!/^(LOG|SET|TRUNCATE|DISCARD)/, @lines);
 	@lines = grep(!/^LINE \d/, @lines);
 	@lines = grep(!/^\s+$/, @lines);
 
@@ -721,10 +728,10 @@ sub run_simple_test
 		$lines[$i] =~ s/^ROLLBACK/COMMIT/;
 		$lines[$i] =~ s/^psql.*(NOTICE|WARNING|ERROR):/\1:/g;
 	}
-	
+
 	# Write out output file
 	open(FILE, ">$outfile");
-	foreach my $l (@lines) 
+	foreach my $l (@lines)
 	{
 		print FILE $l;
 	}
@@ -732,7 +739,7 @@ sub run_simple_test
 
 	# Clean up interim stuff
 	#remove_tree($betmpdir);
-	
+
 	if ( $OPT_EXPECT )
 	{
 		print " (expected)";
@@ -755,7 +762,7 @@ sub run_simple_test
 			return 1;
 		}
 	}
-	
+
 	return 1;
 }
 
@@ -788,7 +795,7 @@ sub run_loader_and_check_output
 	my ( $cmd, $rv );
 	my $outfile = "${TMPDIR}/loader.out";
 	my $errfile = "${TMPDIR}/loader.err";
-	
+
 	# ON_ERROR_STOP is used by psql to return non-0 on an error
 	my $psql_opts = " --no-psqlrc --variable ON_ERROR_STOP=true";
 
@@ -816,7 +823,7 @@ sub run_loader_and_check_output
 				return 0;
 			}
 		}
-		
+
 		# Run the loader SQL script.
 		show_progress();
 		$cmd = "psql $psql_opts -f $outfile $DB > $errfile 2>&1";
@@ -858,13 +865,13 @@ sub run_dumper_and_check_output
 
 	my ($cmd, $rv);
 	my $errfile = "${TMPDIR}/dumper.err";
-	
-	if ( $run_always || -r $expected_shp_file ) 
+
+	if ( $run_always || -r $expected_shp_file )
 	{
 		show_progress();
 		$cmd = "${PGSQL2SHP} -f ${TMPDIR}/dumper $DB $tblname > $errfile 2>&1";
 		$rv = system($cmd);
-	
+
 		if ( $rv )
 		{
 			fail("$description: dumping loaded table", $errfile);
@@ -872,11 +879,11 @@ sub run_dumper_and_check_output
 		}
 
 		# Compare with expected output if there is any.
-		
+
 		if ( -r $expected_shp_file )
 		{
 			show_progress();
-			
+
 			my $diff = diff($expected_shp_file,  "$TMPDIR/dumper.shp");
 			if ( $diff )
 			{
@@ -915,7 +922,7 @@ sub run_raster_loader_and_check_output
 	my $expected_select_results_file = shift;
 	my $loader_options = shift;
 	my $run_always = shift;
-	
+
 	# ON_ERROR_STOP is used by psql to return non-0 on an error
 	my $psql_opts="--no-psqlrc --variable ON_ERROR_STOP=true";
 
@@ -923,20 +930,20 @@ sub run_raster_loader_and_check_output
 	my $outfile = "${TMPDIR}/loader.out";
 	my $errfile = "${TMPDIR}/loader.err";
 
-	if ( $run_always || -r $expected_sql_file || -r $expected_select_results_file ) 
+	if ( $run_always || -r $expected_sql_file || -r $expected_select_results_file )
 	{
 		show_progress();
 
 		# Produce the output SQL file.
 		$cmd = "$RASTER2PGSQL $loader_options ${TEST}.tif $tblname > $outfile 2> $errfile";
 		$rv = system($cmd);
-		
+
 		if ( $rv )
 		{
 		    fail("$description: running raster2pgsql", $errfile);
 		    return 0;
 	    }
-	    
+
 	    if ( -r $expected_sql_file )
 	    {
 	        show_progress();
@@ -946,7 +953,7 @@ sub run_raster_loader_and_check_output
 				fail(" $description: actual SQL does not match expected.", "$outfile");
 				return 0;
 			}
-	        
+
         }
 
 		# Run the loader SQL script.
@@ -966,26 +973,26 @@ sub run_raster_loader_and_check_output
     		return 0 if ( ! $rv );
     	}
 	}
-    	
+
     return 1;
 }
 
 
 
 ##################################################################
-#  run_loader_test 
+#  run_loader_test
 #
 #  Load a shapefile with different methods, create a 'select *' SQL
-#  test and run simple test with provided expected output. 
+#  test and run simple test with provided expected output.
 #
 #  SHP input is ${TEST}.shp, expected output is {$TEST}.expected
 ##################################################################
-sub run_loader_test 
+sub run_loader_test
 {
 	# See if there is a custom command-line options file
 	my $opts_file = "${TEST}.opts";
 	my $custom_opts="";
-	
+
 	if ( -r $opts_file )
 	{
 		open(FILE, $opts_file);
@@ -1053,22 +1060,22 @@ sub run_loader_test
 		}
 		drop_table($tblname);
 	}
-	
+
 	return 1;
 }
 
 ##################################################################
-#  run_dumper_test 
+#  run_dumper_test
 #
 #  Run dumper and compare output with various expectances
-#  test and run simple test with provided expected output. 
+#  test and run simple test with provided expected output.
 #
 # input is ${TEST}.dmp, where last line is considered to be the
 # [table|query] argument for pgsql2shp and all the previous lines,
-# if any are 
+# if any are
 #
 ##################################################################
-sub run_dumper_test 
+sub run_dumper_test
 {
   my $dump_file  = "${TEST}.dmp";
 
@@ -1142,14 +1149,14 @@ sub run_dumper_test
 
 
 ##################################################################
-#  run_raster_loader_test 
+#  run_raster_loader_test
 ##################################################################
 sub run_raster_loader_test
 {
 	# See if there is a custom command-line options file
 	my $opts_file = "${TEST}.opts";
 	my $custom_opts="";
-	
+
 	if ( -r $opts_file )
 	{
 		open(FILE, $opts_file);
@@ -1167,9 +1174,9 @@ sub run_raster_loader_test
 	{
 		return 0;
 	}
-	
+
 	drop_table($tblname);
-	
+
 	return 1;
 }
 
@@ -1180,15 +1187,15 @@ sub run_raster_loader_test
 sub count_db_objects
 {
 	my $count = sql("WITH counts as (
-		select count(*) from pg_type union all 
-		select count(*) from pg_proc union all 
+		select count(*) from pg_type union all
+		select count(*) from pg_proc union all
 		select count(*) from pg_cast union all
 		select count(*) from pg_aggregate union all
 		select count(*) from pg_operator union all
 		select count(*) from pg_opclass union all
 		select count(*) from pg_namespace
 			where nspname NOT LIKE 'pg_%' union all
-		select count(*) from pg_opfamily ) 
+		select count(*) from pg_opfamily )
 		select sum(count) from counts");
 
  	return $count;
@@ -1204,7 +1211,7 @@ sub create_db
 	return system($cmd);
 }
 
-sub create_spatial 
+sub create_spatial
 {
 	my ($cmd, $rv);
 	print "Creating database '$DB' \n";
@@ -1217,7 +1224,7 @@ sub create_spatial
 	# Count database objects before installing anything
 	$OBJ_COUNT_PRE = count_db_objects();
 
-	if ( $OPT_EXTENSIONS ) 
+	if ( $OPT_EXTENSIONS )
 	{
 		prepare_spatial_extensions();
 	}
@@ -1232,12 +1239,12 @@ sub load_sql_file
 {
 	my $file = shift;
 	my $strict = shift;
-	
+
 	if ( $strict && ! -e $file )
 	{
-		die "Unable to find $file\n"; 
+		die "Unable to find $file\n";
 	}
-	
+
 	if ( -e $file )
 	{
 		# ON_ERROR_STOP is used by psql to return non-0 on an error
@@ -1268,7 +1275,7 @@ sub prepare_spatial_extensions
 		$sql .= " VERSION '" . $OPT_UPGRADE_FROM . "'";
 	}
 
-	print "Preparing db '${DB}' using: ${sql}\n"; 
+	print "Preparing db '${DB}' using: ${sql}\n";
 
 	my $cmd = "psql $psql_opts -c \"". $sql . "\" $DB >> $REGRESS_LOG 2>&1";
 	my $rv = system($cmd);
@@ -1318,14 +1325,14 @@ sub prepare_spatial
 	load_sql_file("${STAGED_SCRIPTS_DIR}/postgis.sql", 1);
 	load_sql_file("${STAGED_SCRIPTS_DIR}/postgis_comments.sql", 0);
 	load_sql_file("${STAGED_SCRIPTS_DIR}/postgis_proc_set_search_path.sql", 0);
-	
+
 	if ( $OPT_WITH_TOPO )
 	{
 		print "Loading Topology into '${DB}'\n";
 		load_sql_file("${STAGED_SCRIPTS_DIR}/topology.sql", 1);
 		load_sql_file("${STAGED_SCRIPTS_DIR}/topology_comments.sql", 0);
 	}
-	
+
 	if ( $OPT_WITH_RASTER )
 	{
 		print "Loading Raster into '${DB}'\n";
@@ -1361,8 +1368,8 @@ sub upgrade_spatial
     {
         die "$script not found\n";
     }
-    
-    if ( $OPT_WITH_TOPO ) 
+
+    if ( $OPT_WITH_TOPO )
     {
         my $script = `ls ${STAGED_SCRIPTS_DIR}/topology_upgrade.sql`;
         chomp($script);
@@ -1376,8 +1383,8 @@ sub upgrade_spatial
             die "$script not found\n";
         }
     }
-    
-    if ( $OPT_WITH_RASTER ) 
+
+    if ( $OPT_WITH_RASTER )
     {
         my $script = `ls ${STAGED_SCRIPTS_DIR}/rtpostgis_upgrade.sql`;
         chomp($script);
@@ -1416,7 +1423,7 @@ sub upgrade_spatial_extensions
       die;
     }
 
-    if ( $OPT_WITH_TOPO ) 
+    if ( $OPT_WITH_TOPO )
     {
       my $sql = "ALTER EXTENSION postgis_topology UPDATE TO '${nextver}'";
       my $cmd = "psql $psql_opts -c \"" . $sql . "\" $DB >> $REGRESS_LOG 2>&1";
@@ -1426,7 +1433,7 @@ sub upgrade_spatial_extensions
         die;
       }
     }
-    
+
     return 1;
 }
 
@@ -1455,9 +1462,9 @@ sub drop_spatial_extensions
 {
     # ON_ERROR_STOP is used by psql to return non-0 on an error
     my $psql_opts="--no-psqlrc --variable ON_ERROR_STOP=true";
-    my $ok = 1; 
+    my $ok = 1;
     my ($cmd, $rv);
-    
+
     if ( $OPT_WITH_TOPO )
     {
         # NOTE: "manually" dropping topology schema as EXTENSION does not
@@ -1474,7 +1481,7 @@ sub drop_spatial_extensions
         $rv = system($cmd);
         $ok = 0 if $rv;
     }
-    
+
     $cmd = "psql $psql_opts -c \"DROP EXTENSION postgis\" $DB >> $REGRESS_LOG 2>&1";
     $rv = system($cmd);
   	die "\nError encountered dropping EXTENSION POSTGIS, see $REGRESS_LOG for details\n\n"
@@ -1488,9 +1495,9 @@ sub uninstall_spatial
 {
 	my $ok;
 	start_test("uninstall");
-	
+
 	if ( $OPT_EXTENSIONS )
-	{	
+	{
 		$ok = drop_spatial_extensions();
 	}
 	else
@@ -1498,11 +1505,11 @@ sub uninstall_spatial
 		$ok = drop_spatial();
 	}
 
-	if ( $ok ) 
+	if ( $ok )
 	{
 		show_progress(); # on to objects count
 		$OBJ_COUNT_POST = count_db_objects();
-		
+
 		if ( $OBJ_COUNT_POST != $OBJ_COUNT_PRE )
 		{
 			fail("Object count pre-install ($OBJ_COUNT_PRE) != post-uninstall ($OBJ_COUNT_POST)");
@@ -1514,9 +1521,9 @@ sub uninstall_spatial
 			return 1;
 		}
 	}
-	
+
 	return 0;
-}  
+}
 
 # Dump and restore the database
 sub dump_restore
diff --git a/regress/sfcgal/tickets_expected b/regress/sfcgal/tickets_expected
index 3cfe2aa..9451b95 100644
--- a/regress/sfcgal/tickets_expected
+++ b/regress/sfcgal/tickets_expected
@@ -143,11 +143,15 @@ ERROR:  First argument must be a LINESTRING
 #1060|FFFFFFFF2
 #1273|t
 #1273.1|t
-ERROR:  stats for "t.g" do not exist
-ERROR:  stats for "t.g" do not exist
+WARNING:  stats for "t.g" do not exist
+#877.1|
+WARNING:  stats for "t.g" do not exist
+#877.2|
 WARNING:  ST_Estimated_Extent signature was deprecated in 2.1.0. Please use ST_EstimatedExtent
-ERROR:  stats for "t.g" do not exist
-ERROR:  stats for "t.g" do not exist
+WARNING:  stats for "t.g" do not exist
+#877.2.deprecated|
+WARNING:  stats for "t.g" do not exist
+#877.3||||
 #877.4|-10.15000|20.15000|-50.40000|30.40000
 #877.5|-10.15000|20.15000|-50.40000|30.40000
 #1292|GEOMETRYCOLLECTION(POINT(180 90),POLYGON((140 50,150 50,180 50,140 50),(140 60,150 60,180 60,140 60)))
diff --git a/regress/swapordinates.sql b/regress/swapordinates.sql
index 382a2b6..53d329e 100644
--- a/regress/swapordinates.sql
+++ b/regress/swapordinates.sql
@@ -13,3 +13,6 @@ SELECT 'swap1', ST_AsText(ST_SwapOrdinates('POINTZ(0 1 2)','xz'));
 SELECT 'swap2', ST_AsText(ST_SwapOrdinates('POINTM(0 1 2)','my'));
 SELECT 'swap3', ST_AsText(ST_SwapOrdinates('POINTZM(0 1 2 3)','mz'));
 SELECT 'swap4', ST_AsText(ST_SwapOrdinates('MULTICURVE ZM ((5 5 1 3, 3 5 2 2, 3 3 3 1, 0 3 1 1), CIRCULARSTRING ZM (0 0 0 0, 0.2 1 3 -2, 0.5 1.4 1 2), COMPOUNDCURVE ZM (CIRCULARSTRING ZM (0 0 0 0,1 1 1 2,1 0 0 1),(1 0 0 1,0 1 5 4)))','my'));
+
+select '#3628.1', ST_AsText(ST_SwapOrdinates('POINT(1 2 3)', 'XY'));
+select '#3628.2', ST_AsText(ST_SwapOrdinates('POINT(1 2 3)', 'YZ'));
diff --git a/regress/swapordinates_expected b/regress/swapordinates_expected
index c498bba..57ecf15 100644
--- a/regress/swapordinates_expected
+++ b/regress/swapordinates_expected
@@ -8,3 +8,5 @@ swap1|POINT Z (2 1 0)
 swap2|POINT M (0 2 1)
 swap3|POINT ZM (0 1 3 2)
 swap4|MULTICURVE ZM ((5 3 1 5,3 2 2 5,3 1 3 3,0 1 1 3),CIRCULARSTRING ZM (0 0 0 0,0.2 -2 3 1,0.5 2 1 1.4),COMPOUNDCURVE ZM (CIRCULARSTRING ZM (0 0 0 0,1 2 1 1,1 1 0 0),(1 1 0 0,0 4 5 1)))
+#3628.1|POINT Z (2 1 3)
+#3628.2|POINT Z (1 3 2)
diff --git a/regress/tickets.sql b/regress/tickets.sql
index 8c23f67..9672c67 100644
--- a/regress/tickets.sql
+++ b/regress/tickets.sql
@@ -966,6 +966,13 @@ SELECT '#3437e' AS t, count(*) FROM mp INNER JOIN p ON ST_Within(p.geom, mp.geom
 SELECT '#3470', ST_Polygonize(ARRAY[NULL]::geometry[]) IS NULL;
 SELECT '#3470b', ST_Area(ST_Polygonize(ARRAY[NULL, 'LINESTRING (0 0, 10 0, 10 10)', NULL, 'LINESTRING (0 0, 10 10)', NULL]::geometry[]));
 
+-- #3569
+WITH clustr AS (
+      SELECT ST_Polygonize(ST_MakeEnvelope(1, 2, 3, 4)) AS geom
+    )
+    SELECT '#3569', ST_CollectionHomogenize(geom)::box2d
+    FROM clustr;
+
 -- #3579
 with
         params as (
@@ -990,9 +997,13 @@ select
     ST_Intersects(ST_Buffer(road.geom, sidewalk_offset + epsilon), sidewalks.geom) -- should be true
 from road, sidewalks, params;
 
--- #3583
-Select '#3583', ST_AsText(ST_GeomFromGeoJSON('{"type":"MultiPolygon", "coordinates":[[[139.10030364990232,35.16777444430609],5842.4224490305424]]}')); 
+-- #3620
+SELECT '#3620a', ST_AsText(ST_MinimumBoundingCircle('POINT (3 7)'));
+SELECT '#3620b', ST_AsText(ST_MinimumBoundingCircle('LINESTRING (2 8, 2 8)'));
 
+-- #3627
+SELECT '#3627a', ST_AsEncodedPolyline('SRID=4326;LINESTRING(-0.250691 49.283048,-0.250633 49.283376,-0.250502 49.283972,-0.251245 49.284028,-0.251938 49.284232,-0.251938 49.2842)', 6);
+SELECT '#3627b', ST_Equals(geom, ST_LineFromEncodedPolyline(ST_AsEncodedPolyline(geom, 7), 7)) FROM (VALUES ('SRID=4326;LINESTRING (0 0, 1 1)')) AS v (geom);
 
 -- Clean up
 DELETE FROM spatial_ref_sys;
diff --git a/regress/tickets_expected b/regress/tickets_expected
index 77e21f0..b5bdf48 100644
--- a/regress/tickets_expected
+++ b/regress/tickets_expected
@@ -294,5 +294,9 @@ ERROR:  invalid KML representation
 #3437e|5
 #3470|t
 #3470b|50
+#3569|BOX(1 2,3 4)
 #3579|f|t
-#3583|MULTIPOLYGON Z (EMPTY)
+#3620a|POINT(3 7)
+#3620b|POINT(2 8)
+#3627a|o}~~|AdshNoSsBgd at eGoBlm@wKhj@~@?
+#3627b|t
diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c
index 2e73530..c7e8894 100644
--- a/topology/postgis_topology.c
+++ b/topology/postgis_topology.c
@@ -203,6 +203,7 @@ cb_loadTopologyByName(const LWT_BE_DATA* be, const char *name)
   dat = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);
   if ( isnull ) {
 		cberror(be, "Topology '%s' has null identifier", name);
+    SPI_freetuptable(SPI_tuptable);
     return NULL;
   }
   topo->id = DatumGetInt32(dat);
@@ -210,6 +211,7 @@ cb_loadTopologyByName(const LWT_BE_DATA* be, const char *name)
   dat = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &isnull);
   if ( isnull ) {
 		cberror(be, "Topology '%s' has null SRID", name);
+    SPI_freetuptable(SPI_tuptable);
     return NULL;
   }
   topo->srid = DatumGetInt32(dat);
@@ -235,6 +237,8 @@ cb_loadTopologyByName(const LWT_BE_DATA* be, const char *name)
                     "id %d, srid %d, precision %g",
              name, topo->id, topo->srid, topo->precision);
 
+  SPI_freetuptable(SPI_tuptable);
+
   return topo;
 }
 
@@ -594,6 +598,7 @@ fillEdgeFields(LWT_ISO_EDGE* edge, HeapTuple row, TupleDesc rowdesc, int fields)
   Datum dat;
   int val;
   GSERIALIZED *geom;
+  LWGEOM *lwg;
   int colno = 0;
 
   POSTGIS_DEBUGF(2, "fillEdgeFields: got %d atts and fields %x",
@@ -604,12 +609,13 @@ fillEdgeFields(LWT_ISO_EDGE* edge, HeapTuple row, TupleDesc rowdesc, int fields)
     if ( isnull ) {
       lwpgwarning("Found edge with NULL edge_id");
       edge->edge_id = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (edge_id)"
+                        " has int32 val of %d",
+                        colno, val);
+      edge->edge_id = val;
     }
-    val = DatumGetInt32(dat);
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (edge_id)"
-                      " has int32 val of %d",
-                      colno, val);
-    edge->edge_id = val;
 
   }
   if ( fields & LWT_COL_EDGE_START_NODE ) {
@@ -617,73 +623,85 @@ fillEdgeFields(LWT_ISO_EDGE* edge, HeapTuple row, TupleDesc rowdesc, int fields)
     if ( isnull ) {
       lwpgwarning("Found edge with NULL start_node");
       edge->start_node = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (start_node)"
+                        " has int32 val of %d", colno, val);
+      edge->start_node = val;
     }
-    val = DatumGetInt32(dat);
-    edge->start_node = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (start_node)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_END_NODE ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( isnull ) {
       lwpgwarning("Found edge with NULL end_node");
-      edge->start_node = -1;
+      edge->end_node = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (end_node)"
+                        " has int32 val of %d", colno, val);
+      edge->end_node = val;
     }
-    val = DatumGetInt32(dat);
-    edge->end_node = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (end_node)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_FACE_LEFT ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( isnull ) {
       lwpgwarning("Found edge with NULL face_left");
-      edge->start_node = -1;
+      edge->face_left = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (face_left)"
+                        " has int32 val of %d", colno, val);
+      edge->face_left = val;
     }
-    val = DatumGetInt32(dat);
-    edge->face_left = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (face_left)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_FACE_RIGHT ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( isnull ) {
       lwpgwarning("Found edge with NULL face_right");
-      edge->start_node = -1;
+      edge->face_right = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (face_right)"
+                        " has int32 val of %d", colno, val);
+      edge->face_right = val;
     }
-    val = DatumGetInt32(dat);
-    edge->face_right = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (face_right)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_NEXT_LEFT ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( isnull ) {
       lwpgwarning("Found edge with NULL next_left");
-      edge->start_node = -1;
+      edge->next_left = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (next_left)"
+                        " has int32 val of %d", colno, val);
+      edge->next_left = val;
     }
-    val = DatumGetInt32(dat);
-    edge->next_left = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (next_left)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_NEXT_RIGHT ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( isnull ) {
       lwpgwarning("Found edge with NULL next_right");
-      edge->start_node = -1;
+      edge->next_right = -1;
+    } else {
+      val = DatumGetInt32(dat);
+      POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (next_right)"
+                        " has int32 val of %d", colno, val);
+      edge->next_right = val;
     }
-    val = DatumGetInt32(dat);
-    edge->next_right = val;
-    POSTGIS_DEBUGF(2, "fillEdgeFields: colno%d (next_right)"
-                      " has int32 val of %d", colno, val);
   }
   if ( fields & LWT_COL_EDGE_GEOM ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
-    if ( ! isnull ) {
-      geom = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(dat);
-      edge->geom = lwgeom_as_lwline(lwgeom_from_gserialized(geom));
-    } else {
+    if ( ! isnull ) {{
+      MemoryContext oldcontext = CurrentMemoryContext;
+      geom = (GSERIALIZED *)PG_DETOAST_DATUM(dat);
+      lwg = lwgeom_from_gserialized(geom);
+      MemoryContextSwitchTo( TopMemoryContext );
+      edge->geom = lwgeom_as_lwline(lwgeom_clone_deep(lwg));
+      MemoryContextSwitchTo( oldcontext ); /* switch back */
+      lwgeom_free(lwg);
+      if ( DatumGetPointer(dat) != (Pointer)geom ) pfree(geom); /* IF_COPY */
+    }} else {
       lwpgwarning("Found edge with NULL geometry !");
       edge->geom = NULL;
     }
@@ -696,6 +714,7 @@ fillNodeFields(LWT_ISO_NODE* node, HeapTuple row, TupleDesc rowdesc, int fields)
   bool isnull;
   Datum dat;
   GSERIALIZED *geom;
+  LWGEOM *lwg;
   int colno = 0;
 
   if ( fields & LWT_COL_NODE_NODE_ID ) {
@@ -710,8 +729,11 @@ fillNodeFields(LWT_ISO_NODE* node, HeapTuple row, TupleDesc rowdesc, int fields)
   if ( fields & LWT_COL_NODE_GEOM ) {
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( ! isnull ) {
-      geom = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(dat);
-      node->geom = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom));
+      geom = (GSERIALIZED *)PG_DETOAST_DATUM(dat);
+      lwg = lwgeom_from_gserialized(geom);
+      node->geom = lwgeom_as_lwpoint(lwgeom_clone_deep(lwg));
+      lwgeom_free(lwg);
+      if ( DatumGetPointer(dat) != (Pointer)geom ) pfree(geom); /* IF_COPY */
     } else {
       lwpgnotice("Found node with NULL geometry !");
       node->geom = NULL;
@@ -737,7 +759,7 @@ fillFaceFields(LWT_ISO_FACE* face, HeapTuple row, TupleDesc rowdesc, int fields)
     dat = SPI_getbinval(row, rowdesc, ++colno, &isnull);
     if ( ! isnull ) {
       /* NOTE: this is a geometry of which we want to take (and clone) the BBOX */
-      geom = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(dat);
+      geom = (GSERIALIZED *)PG_DETOAST_DATUM(dat);
       g = lwgeom_from_gserialized(geom);
       box = lwgeom_get_bbox(g);
       if ( box ) {
@@ -746,6 +768,8 @@ fillFaceFields(LWT_ISO_FACE* face, HeapTuple row, TupleDesc rowdesc, int fields)
         lwpgnotice("Found face with EMPTY MBR !");
         face->mbr = NULL;
       }
+      lwgeom_free(g);
+      if ( DatumGetPointer(dat) != (Pointer)geom ) pfree(geom);
     } else {
       /* NOTE: perfectly fine for universe face */
       POSTGIS_DEBUG(1, "Found face with NULL MBR");
@@ -812,6 +836,8 @@ cb_getEdgeById(const LWT_BE_TOPOLOGY* topo,
     fillEdgeFields(&edges[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -868,6 +894,8 @@ cb_getEdgeByNode(const LWT_BE_TOPOLOGY* topo,
     fillEdgeFields(&edges[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -944,6 +972,8 @@ cb_getEdgeByFace(const LWT_BE_TOPOLOGY* topo,
     fillEdgeFields(&edges[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -994,6 +1024,8 @@ cb_getFacesById(const LWT_BE_TOPOLOGY* topo,
     fillFaceFields(&faces[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return faces;
 }
 
@@ -1068,6 +1100,8 @@ cb_getRingEdges(const LWT_BE_TOPOLOGY* topo,
                       " is edge %d", i, edge, val);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -1116,6 +1150,8 @@ cb_getNodeById(const LWT_BE_TOPOLOGY* topo,
     fillNodeFields(&nodes[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return nodes;
 }
 
@@ -1172,6 +1208,8 @@ cb_getNodeByFace(const LWT_BE_TOPOLOGY* topo,
     fillNodeFields(&nodes[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return nodes;
 }
 
@@ -1240,6 +1278,9 @@ cb_getEdgeWithinDistance2D(const LWT_BE_TOPOLOGY* topo,
       *numelems = exists ? 1 : 0;
       POSTGIS_DEBUGF(1, "cb_getEdgeWithinDistance2D: exists ? %d", *numelems);
     }
+
+    SPI_freetuptable(SPI_tuptable);
+
     return NULL;
   }
 
@@ -1250,6 +1291,8 @@ cb_getEdgeWithinDistance2D(const LWT_BE_TOPOLOGY* topo,
     fillEdgeFields(&edges[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -1323,6 +1366,9 @@ cb_getNodeWithinDistance2D(const LWT_BE_TOPOLOGY* topo,
       exists = DatumGetBool(dat);
       *numelems = exists ? 1 : 0;
     }
+
+    SPI_freetuptable(SPI_tuptable);
+
     return NULL;
   }
   else
@@ -1334,6 +1380,9 @@ cb_getNodeWithinDistance2D(const LWT_BE_TOPOLOGY* topo,
       fillNodeFields(&nodes[i], row, SPI_tuptable->tupdesc, fields);
     }
     *numelems = SPI_processed;
+
+    SPI_freetuptable(SPI_tuptable);
+
     return nodes;
   }
 }
@@ -1388,6 +1437,8 @@ cb_insertNodes( const LWT_BE_TOPOLOGY* topo,
       SPI_tuptable->tupdesc, LWT_COL_NODE_NODE_ID);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return 1;
 }
 
@@ -1445,6 +1496,8 @@ cb_insertEdges( const LWT_BE_TOPOLOGY* topo,
     }
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return SPI_processed;
 }
 
@@ -1501,6 +1554,8 @@ cb_insertFaces( const LWT_BE_TOPOLOGY* topo,
     }
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return SPI_processed;
 }
 
@@ -1860,6 +1915,9 @@ cb_getNextEdgeId( const LWT_BE_TOPOLOGY* topo )
 	  return -1;
   }
   edge_id = DatumGetInt64(dat); /* sequences return 64bit integers */
+
+  SPI_freetuptable(SPI_tuptable);
+
   return edge_id;
 }
 
@@ -1959,6 +2017,9 @@ cb_updateTopoGeomEdgeSplit ( const LWT_BE_TOPOLOGY* topo,
           topogeo_id, layer_id, negate ? -new_edge2 : new_edge2, element_type);
       }
     }
+
+    SPI_freetuptable(SPI_tuptable);
+
     POSTGIS_DEBUGF(1, "cb_updateTopoGeomEdgeSplit query: %s", sql->data);
     spi_result = SPI_execute(sql->data, false, 0);
     MemoryContextSwitchTo( oldcontext ); /* switch back */
@@ -2079,6 +2140,8 @@ cb_updateTopoGeomFaceSplit ( const LWT_BE_TOPOLOGY* topo,
       }
     }
 
+    SPI_freetuptable(SPI_tuptable);
+
     POSTGIS_DEBUGF(1, "cb_updateTopoGeomFaceSplit query: %s", sql->data);
     spi_result = SPI_execute(sql->data, false, 0);
     MemoryContextSwitchTo( oldcontext ); /* switch back */
@@ -2088,6 +2151,7 @@ cb_updateTopoGeomFaceSplit ( const LWT_BE_TOPOLOGY* topo,
       pfree(sqldata.data);
       return 0;
     }
+
     if ( SPI_processed ) topo->be_data->data_changed = true;
   }
 
@@ -2143,6 +2207,8 @@ cb_checkTopoGeomRemEdge ( const LWT_BE_TOPOLOGY* topo,
     table_name = SPI_getvalue(row, tdesc, 4);
     col_name = SPI_getvalue(row, tdesc, 5);
 
+    SPI_freetuptable(SPI_tuptable);
+
     cberror(topo->be_data, "TopoGeom %s in layer %s "
                            "(%s.%s.%s) cannot be represented "
                            "dropping edge %" LWTFMT_ELEMID,
@@ -2199,6 +2265,8 @@ cb_checkTopoGeomRemEdge ( const LWT_BE_TOPOLOGY* topo,
       table_name = SPI_getvalue(row, tdesc, 4);
       col_name = SPI_getvalue(row, tdesc, 5);
 
+      SPI_freetuptable(SPI_tuptable);
+
       cberror(topo->be_data, "TopoGeom %s in layer %s "
                              "(%s.%s.%s) cannot be represented "
                              "healing faces %" LWTFMT_ELEMID
@@ -2261,6 +2329,8 @@ cb_checkTopoGeomRemNode ( const LWT_BE_TOPOLOGY* topo,
     table_name = SPI_getvalue(row, tdesc, 4);
     col_name = SPI_getvalue(row, tdesc, 5);
 
+    SPI_freetuptable(SPI_tuptable);
+
     cberror(topo->be_data, "TopoGeom %s in layer %s "
                            "(%s.%s.%s) cannot be represented "
                            "healing edges %" LWTFMT_ELEMID
@@ -2486,10 +2556,12 @@ cb_getFaceContainingPoint( const LWT_BE_TOPOLOGY* topo, const LWPOINT* pt )
   dat = SPI_getbinval( SPI_tuptable->vals[0],
                        SPI_tuptable->tupdesc, 1, &isnull );
   if ( isnull ) {
+    SPI_freetuptable(SPI_tuptable);
 		cberror(topo->be_data, "corrupted topology: face with NULL face_id");
 	  return -2;
   }
   face_id = DatumGetInt32(dat);
+  SPI_freetuptable(SPI_tuptable);
   return face_id;
 }
 
@@ -2624,6 +2696,7 @@ cb_getNodeWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
       bool isnull, exists;
       dat = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);
       exists = DatumGetBool(dat);
+      SPI_freetuptable(SPI_tuptable);
       *numelems = exists ? 1 : 0;
       POSTGIS_DEBUGF(1, "cb_getNodeWithinBox2D: exists ? %d", *numelems);
     }
@@ -2637,6 +2710,8 @@ cb_getNodeWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
     fillNodeFields(&nodes[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return nodes;
 }
 
@@ -2697,6 +2772,7 @@ cb_getEdgeWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
       dat = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);
       exists = DatumGetBool(dat);
       *numelems = exists ? 1 : 0;
+      SPI_freetuptable(SPI_tuptable);
       POSTGIS_DEBUGF(1, "cb_getEdgeWithinBox2D: exists ? %d", *numelems);
     }
     return NULL;
@@ -2709,6 +2785,8 @@ cb_getEdgeWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
     fillEdgeFields(&edges[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return edges;
 }
 
@@ -2771,6 +2849,9 @@ cb_getFaceWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
       *numelems = exists ? 1 : 0;
       POSTGIS_DEBUGF(1, "cb_getFaceWithinBox2D: exists ? %d", *numelems);
     }
+
+    SPI_freetuptable(SPI_tuptable);
+
     return NULL;
   }
 
@@ -2781,6 +2862,8 @@ cb_getFaceWithinBox2D ( const LWT_BE_TOPOLOGY* topo, const GBOX* box,
     fillFaceFields(&faces[i], row, SPI_tuptable->tupdesc, fields);
   }
 
+  SPI_freetuptable(SPI_tuptable);
+
   return faces;
 }
 
diff --git a/topology/sql/populate.sql.in b/topology/sql/populate.sql.in
index 4cdfae9..1c105ad 100644
--- a/topology/sql/populate.sql.in
+++ b/topology/sql/populate.sql.in
@@ -437,7 +437,9 @@ BEGIN
     RAISE EXCEPTION 'Face geometry must be a polygon';
   END IF;
 
-  for rrec IN SELECT (ST_DumpRings(ST_ForceRHR(apoly))).geom
+  for rrec IN SELECT (d).* FROM (
+    SELECT ST_DumpRings(ST_ForceRHR(apoly)) d
+  ) foo
   LOOP -- {
     --
     -- Find all bounds edges, forcing right-hand-rule

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/postgis.git



More information about the Pkg-grass-devel mailing list