[SCM] PostGIS branch master updated. 3.6.0rc2-651-g92903a731

git at osgeo.org git at osgeo.org
Sun Jun 21 12:09:29 PDT 2026


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  92903a731a5dc918318e57c0746ba407d84eccdc (commit)
      from  a401974f93be7586b3c7dbe9f7d686f3cad16061 (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 92903a731a5dc918318e57c0746ba407d84eccdc
Author: Darafei Praliaskouski <me at komzpa.net>
Date:   Sun Jun 21 23:01:47 2026 +0400

    loader: preserve numeric DBF metadata in pgsql2shp
    
    Decode numeric typmod precision and scale when selecting DBF field metadata so pgsql2shp preserves fixed numeric declarations that fit in the DBF field-width limit. Keep legacy 32,10 metadata for untyped numeric values.
    
    Add pgsql2shp dumper coverage for portable numeric typmods, and gate PostgreSQL 15+ negative-scale numeric coverage behind the configured PostgreSQL version.
    
    Closes #2850
    
    Closes https://github.com/postgis/postgis/pull/1020

diff --git a/.gitignore b/.gitignore
index 9b374cdea..57649dd75 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ doc/html/images/Makefile
 regression.out
 raster/test/regress/tests.mk
 regress/core/tests.mk
+regress/dumper/tests.mk
 sfcgal/regress/tests.mk
 
 
@@ -177,6 +178,7 @@ regress/Makefile
 regress/core/Makefile
 regress/core/tests.mk
 regress/dumper/Makefile
+regress/dumper/tests.mk
 regress/loader/Makefile
 regress/real/download_data
 regress/real/Makefile
diff --git a/GNUmakefile.in b/GNUmakefile.in
index e65fd23e4..961f53c9b 100644
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -288,7 +288,7 @@ postgis_revision.h:
 
 include $(top_builddir)/regress/core/tests.mk
 include $(top_srcdir)/regress/loader/tests.mk
-include $(top_srcdir)/regress/dumper/tests.mk
+include $(top_builddir)/regress/dumper/tests.mk
 ifeq ($(HAVE_SFCGAL),yes)
 	override RUNTESTFLAGS := $(RUNTESTFLAGS) --sfcgal
 	include $(top_builddir)/sfcgal/regress/tests.mk
diff --git a/NEWS b/NEWS
index 0f1dba4e5..117a044bc 100644
--- a/NEWS
+++ b/NEWS
@@ -94,6 +94,8 @@ To take advantage of all postgis_sfcgal extension features SFCGAL 2.3+ is needed
           shapefiles (Darafei Praliaskouski)
  - Fix WKB and TWKB parser resource exhaustion on malformed input
           (Darafei Praliaskouski)
+ - #2850, Preserve pgsql2shp numeric precision and scale in DBF metadata
+          (Darafei Praliaskouski)
  - #6083, Pass configured dependency include paths to fuzzer smoke builds
           (Darafei Praliaskouski)
  - #3103, Add regression coverage for exact-schema find_srid and
diff --git a/configure.ac b/configure.ac
index 57157d133..9324966ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1902,6 +1902,7 @@ AC_CONFIG_FILES([GNUmakefile
    regress/core/Makefile
    regress/core/tests.mk
    regress/dumper/Makefile
+   regress/dumper/tests.mk
    regress/loader/Makefile
    doc/Makefile
    doc/Makefile.comments
diff --git a/loader/pgsql2shp-core.c b/loader/pgsql2shp-core.c
index 14da7a716..334b2b7c2 100644
--- a/loader/pgsql2shp-core.c
+++ b/loader/pgsql2shp-core.c
@@ -59,6 +59,8 @@ static char *nullDBFValue(char fieldType);
 static int getMaxFieldSize(PGconn *conn, char *schema, char *table, char *fname);
 static int getTableInfo(SHPDUMPERSTATE *state);
 static int projFileCreate(SHPDUMPERSTATE *state);
+static int numeric_typmod_precision(int typmod);
+static int numeric_typmod_scale(int typmod);
 
 /**
  * @brief Make appropriate formatting of a DBF value based on type.
@@ -87,6 +89,24 @@ core_asprintf(const char* format, ...)
     return value;
 }
 
+static int
+numeric_typmod_precision(int typmod)
+{
+	return ((typmod - 4) >> 16) & 0xffff;
+}
+
+static int
+numeric_typmod_scale(int typmod)
+{
+	int scale = (typmod - 4) & 0x7ff;
+
+	/* PostgreSQL stores numeric scale as an 11-bit signed value. */
+	if (scale & 0x400)
+		scale |= ~0x7ff;
+
+	return scale;
+}
+
 static SHPObject *
 create_point_empty(SHPDUMPERSTATE *state, LWPOINT *lwpoint)
 {
@@ -1613,21 +1633,52 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
 		}
 
 		/*
-		 * double or numeric types:
+		 * double types:
 		 *    700: float4
 		 *    701: float8
-		 *   1700: numeric
-		 *
-		 *
-		 * TODO: stricter handling of sizes
 		 */
-		else if (pgfieldtype == 700 || pgfieldtype == 701 || pgfieldtype == 1700)
+		else if (pgfieldtype == 700 || pgfieldtype == 701)
 		{
 			dbffieldtype = FTDouble;
 			dbffieldsize = 32;
 			dbffielddecs = 10;
 		}
 
+		/*
+		 * Numeric type (1700). Preserve declared precision and scale
+		 * when PostgreSQL exposes a typmod and DBF can represent it.
+		 */
+		else if (pgfieldtype == 1700)
+		{
+			dbffieldtype = FTDouble;
+			dbffieldsize = 32;
+			dbffielddecs = 10;
+
+			if (pgtypmod >= 0)
+			{
+				int precision = numeric_typmod_precision(pgtypmod);
+				int scale = numeric_typmod_scale(pgtypmod);
+				int integral_digits = precision - scale;
+				int dbfsize;
+
+				if (integral_digits < 1)
+					integral_digits = 1;
+
+				if (scale > 0)
+					dbfsize = 1 + integral_digits + 1 + scale;
+				else
+					dbfsize = 1 + precision - scale;
+
+				if (dbfsize <= MAX_DBF_FIELD_SIZE)
+				{
+					dbffieldsize = dbfsize;
+					dbffielddecs = (scale > 0) ? scale : 0;
+					if (dbffielddecs == 0)
+						dbffieldtype = FTInteger;
+				}
+			}
+		}
+
 		/*
 		 * Boolean field, we use FTLogical
 		 */
diff --git a/regress/Makefile.in b/regress/Makefile.in
index cc4b8dfff..32f6d41c2 100644
--- a/regress/Makefile.in
+++ b/regress/Makefile.in
@@ -57,7 +57,7 @@ check-unit:
 
 include $(builddir)/core/tests.mk
 include $(srcdir)/loader/tests.mk
-include $(srcdir)/dumper/tests.mk
+include $(builddir)/dumper/tests.mk
 
 include $(srcdir)/runtest.mk
 
@@ -71,6 +71,7 @@ distclean: clean
 	rm -f core/tests.mk
 	rm -f loader/Makefile
 	rm -f dumper/Makefile
+	rm -f dumper/tests.mk
 
 staged-install-sfcgal:
 	@if test x"@SFCGAL@" != "x"; then \
diff --git a/regress/dumper/numeric.dmp b/regress/dumper/numeric.dmp
new file mode 100644
index 000000000..0614d2e2c
--- /dev/null
+++ b/regress/dumper/numeric.dmp
@@ -0,0 +1 @@
+SELECT 1.23::numeric(3,2) AS n32, 0.123456789012::numeric(12,12) AS n1212, 123::numeric(3,0) AS n30, (-123)::numeric(3,0) AS n30neg, 123.45::numeric(5,2) AS n52, 1.2345678901234::numeric AS nuntyped, ST_Point(0, 0) AS geom;
diff --git a/regress/dumper/numeric_expected.dbf b/regress/dumper/numeric_expected.dbf
new file mode 100644
index 000000000..fed815fc7
Binary files /dev/null and b/regress/dumper/numeric_expected.dbf differ
diff --git a/regress/dumper/numeric_expected.shp b/regress/dumper/numeric_expected.shp
new file mode 100644
index 000000000..0112cd743
Binary files /dev/null and b/regress/dumper/numeric_expected.shp differ
diff --git a/regress/dumper/numeric_expected.shx b/regress/dumper/numeric_expected.shx
new file mode 100644
index 000000000..cc0b42ae7
Binary files /dev/null and b/regress/dumper/numeric_expected.shx differ
diff --git a/regress/dumper/numeric_negative_scale.dmp b/regress/dumper/numeric_negative_scale.dmp
new file mode 100644
index 000000000..9820a6b38
--- /dev/null
+++ b/regress/dumper/numeric_negative_scale.dmp
@@ -0,0 +1 @@
+SELECT 1200::numeric(4,-2) AS n4m2, ST_Point(0, 0) AS geom;
diff --git a/regress/dumper/numeric_negative_scale_expected.dbf b/regress/dumper/numeric_negative_scale_expected.dbf
new file mode 100644
index 000000000..b3377c107
Binary files /dev/null and b/regress/dumper/numeric_negative_scale_expected.dbf differ
diff --git a/regress/dumper/numeric_negative_scale_expected.shp b/regress/dumper/numeric_negative_scale_expected.shp
new file mode 100644
index 000000000..0112cd743
Binary files /dev/null and b/regress/dumper/numeric_negative_scale_expected.shp differ
diff --git a/regress/dumper/numeric_negative_scale_expected.shx b/regress/dumper/numeric_negative_scale_expected.shx
new file mode 100644
index 000000000..cc0b42ae7
Binary files /dev/null and b/regress/dumper/numeric_negative_scale_expected.shx differ
diff --git a/regress/dumper/tests.mk b/regress/dumper/tests.mk.in
similarity index 71%
rename from regress/dumper/tests.mk
rename to regress/dumper/tests.mk.in
index d3417dc8f..5d82f2ddf 100644
--- a/regress/dumper/tests.mk
+++ b/regress/dumper/tests.mk.in
@@ -4,16 +4,25 @@
 # * http://postgis.net
 # *
 # * Copyright (C) 2020 Sandro Santilli <strk at kbt.io>
+# * Copyright (C) 2026 Darafei Praliaskouski <me at komzpa.net>
 # *
 # * This is free software; you can redistribute and/or modify it under
 # * the terms of the GNU General Public Licence. See the COPYING file.
 # *
 # **********************************************************************
 
+POSTGIS_PGSQL_VERSION=@POSTGIS_PGSQL_VERSION@
+
 TESTS += \
 	$(top_srcdir)/regress/dumper/mfiledmp \
 	$(top_srcdir)/regress/dumper/literalsrid \
 	$(top_srcdir)/regress/dumper/realtable \
 	$(top_srcdir)/regress/dumper/nullsintable \
 	$(top_srcdir)/regress/dumper/null3d \
+	$(top_srcdir)/regress/dumper/numeric \
 	$(top_srcdir)/regress/dumper/withclause
+
+ifeq ($(shell expr "$(POSTGIS_PGSQL_VERSION)" ">=" 150),1)
+	TESTS += \
+		$(top_srcdir)/regress/dumper/numeric_negative_scale
+endif

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

Summary of changes:
 .gitignore                                         |   2 +
 GNUmakefile.in                                     |   2 +-
 NEWS                                               |   2 +
 configure.ac                                       |   1 +
 loader/pgsql2shp-core.c                            |  63 +++++++++++++++++++--
 regress/Makefile.in                                |   3 +-
 regress/dumper/numeric.dmp                         |   1 +
 regress/dumper/numeric_expected.dbf                | Bin 0 -> 293 bytes
 ...teralsrid_expected.shp => numeric_expected.shp} | Bin
 ...teralsrid_expected.shx => numeric_expected.shx} | Bin
 regress/dumper/numeric_negative_scale.dmp          |   1 +
 regress/dumper/numeric_negative_scale_expected.dbf | Bin 0 -> 73 bytes
 ...ted.shp => numeric_negative_scale_expected.shp} | Bin
 ...ted.shx => numeric_negative_scale_expected.shx} | Bin
 regress/dumper/{tests.mk => tests.mk.in}           |   9 +++
 15 files changed, 76 insertions(+), 8 deletions(-)
 create mode 100644 regress/dumper/numeric.dmp
 create mode 100644 regress/dumper/numeric_expected.dbf
 copy regress/dumper/{literalsrid_expected.shp => numeric_expected.shp} (100%)
 copy regress/dumper/{literalsrid_expected.shx => numeric_expected.shx} (100%)
 create mode 100644 regress/dumper/numeric_negative_scale.dmp
 create mode 100644 regress/dumper/numeric_negative_scale_expected.dbf
 copy regress/dumper/{literalsrid_expected.shp => numeric_negative_scale_expected.shp} (100%)
 copy regress/dumper/{literalsrid_expected.shx => numeric_negative_scale_expected.shx} (100%)
 rename regress/dumper/{tests.mk => tests.mk.in} (71%)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list