[SCM] PostGIS branch master updated. 3.6.0rc2-648-gc4bae99fc

git at osgeo.org git at osgeo.org
Sun Jun 21 10:58:35 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  c4bae99fc25aabfc512dd0c14f1474b66b3e7730 (commit)
      from  a0b3925cf59cea943ac9bd1d2130692a559ff64f (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 c4bae99fc25aabfc512dd0c14f1474b66b3e7730
Author: Darafei Praliaskouski <me at komzpa.net>
Date:   Sun Jun 21 21:51:30 2026 +0400

    Generate pgsql2shp DBF id for geometry-only dumps
    
    When pgsql2shp exports a result with a geometry or geography column but no DBF attributes, add a generated integer GID field and populate it for each output record so the DBF record count remains aligned with the SHP records.
    
    Propagate the generated-field warning to callers and guard dumper state allocation failures in the CLI and GUI paths.
    
    Closes #2623
    
    Closes https://github.com/postgis/postgis/pull/1019

diff --git a/NEWS b/NEWS
index d0f6e212d..7f37d0986 100644
--- a/NEWS
+++ b/NEWS
@@ -87,6 +87,8 @@ To take advantage of all postgis_sfcgal extension features SFCGAL 2.3+ is needed
           (Darafei Praliaskouski)
  - #2832, [raster] Avoid padding single-tile raster2pgsql overviews
           when padding is not requested (Darafei Praliaskouski)
+ - #2623, Generate a pgsql2shp GID field when exporting geometry-only
+          shapefiles (Darafei Praliaskouski)
  - Fix WKB and TWKB parser resource exhaustion on malformed input
           (Darafei Praliaskouski)
  - #6083, Pass configured dependency include paths to fuzzer smoke builds
diff --git a/loader/pgsql2shp-cli.c b/loader/pgsql2shp-cli.c
index 21ab0b7b1..4ce700521 100644
--- a/loader/pgsql2shp-cli.c
+++ b/loader/pgsql2shp-cli.c
@@ -178,6 +178,12 @@ main(int argc, char **argv)
 	}
 
 	state = ShpDumperCreate(config);
+	if (!state)
+	{
+		fprintf(stderr, "%s\n", _("Out of memory allocating dumper state"));
+		fflush(stderr);
+		exit(1);
+	}
 
 	ret = ShpDumperConnectDatabase(state);
 	if (ret != SHPDUMPEROK)
diff --git a/loader/pgsql2shp-core.c b/loader/pgsql2shp-core.c
index 47d2daf11..14da7a716 100644
--- a/loader/pgsql2shp-core.c
+++ b/loader/pgsql2shp-core.c
@@ -1161,6 +1161,9 @@ ShpDumperCreate(SHPDUMPERCONFIG *config)
 
 	/* Create a new state object and assign the config to it */
 	state = malloc(sizeof(SHPDUMPERSTATE));
+	if (!state)
+		return NULL;
+
 	state->config = config;
 
 	/* Set any state defaults */
@@ -1179,6 +1182,7 @@ ShpDumperCreate(SHPDUMPERCONFIG *config)
 	state->pgfieldnames = NULL;
 	state->pgfieldlens = NULL;
 	state->pgfieldtypmods = NULL;
+	state->generate_dbf_id = LW_FALSE;
 	state->message[0] = '\0';
 	colmap_init(&state->column_map);
 
@@ -1317,16 +1321,18 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
 	PGresult *res;
 
 	char buf[256];
-	int gidfound = 0, i, j, ret, status;
+	int gidfound = 0, i, j, status;
+	int ret = SHPDUMPEROK;
 	stringbuffer_t sb;
 	char *quoted = NULL;
 
 	/* Open the column map if one was specified */
 	if (state->config->column_map_filename)
 	{
-		ret = colmap_read(state->config->column_map_filename,
-		                  &state->column_map, state->message, SHPDUMPERMSGLEN);
-		if (!ret) return SHPDUMPERERR;
+		int colmap_ret = colmap_read(
+		    state->config->column_map_filename, &state->column_map, state->message, SHPDUMPERMSGLEN);
+		if (!colmap_ret)
+			return SHPDUMPERERR;
 	}
 
 	/* If a user-defined query has been specified, create and point the state to our new table */
@@ -1787,6 +1793,25 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
 		}
 	}
 
+	if (state->geo_col_name && !state->fieldcount)
+	{
+		if (DBFAddField(state->dbf, "GID", FTInteger, 11, 0) == -1)
+		{
+			snprintf(
+			    state->message, SHPDUMPERMSGLEN, _("Error: generated field GID could not be created."));
+			PQclear(res);
+			return SHPDUMPERERR;
+		}
+
+		state->generate_dbf_id = LW_TRUE;
+		snprintf(buf,
+			 sizeof(buf),
+			 _("Warning: no DBF attributes found, generating a GID field for compatibility.\n"));
+		if (SHPDUMPERMSGLEN > (strlen(state->message) + 1))
+			strncat(state->message, buf, SHPDUMPERMSGLEN - (strlen(state->message) + 1));
+		ret = SHPDUMPERWARN;
+	}
+
 	/* Now we have generated the field lists, grab some info about the table */
 	status = getTableInfo(state);
 	if (status == SHPDUMPERERR)
@@ -1956,7 +1981,7 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
 	/* Generate the fetch query */
 	state->fetch_query = core_asprintf("FETCH %d FROM cur", state->config->fetchsize);
 
-	return SHPDUMPEROK;
+	return ret;
 }
 
 
@@ -2033,6 +2058,19 @@ int ShpLoaderGenerateShapeRow(SHPDUMPERSTATE *state)
 		}
 	}
 
+	if (state->generate_dbf_id)
+	{
+		if (!DBFWriteIntegerAttribute(state->dbf, state->currow, 0, state->currow + 1))
+		{
+			snprintf(state->message,
+				 SHPDUMPERMSGLEN,
+				 _("Error: generated GID for record %d could not be created"),
+				 state->currow);
+			PQclear(state->fetchres);
+			return SHPDUMPERERR;
+		}
+	}
+
 	/* Now process the geo field, if present */
 	if (state->geo_col_name)
 	{
diff --git a/loader/pgsql2shp-core.h b/loader/pgsql2shp-core.h
index 6b26702e3..564836d91 100644
--- a/loader/pgsql2shp-core.h
+++ b/loader/pgsql2shp-core.h
@@ -142,6 +142,9 @@ typedef struct shp_dumper_state
 	/* Number of non-spatial fields in DBF output file */
 	int fieldcount;
 
+	/* Generate a DBF id field when the source has no non-spatial fields */
+	int generate_dbf_id;
+
 	/* Number of rows in the database table */
 	int num_records;
 
diff --git a/loader/shp2pgsql-gui.c b/loader/shp2pgsql-gui.c
index 51307ccba..37a9a04d0 100644
--- a/loader/shp2pgsql-gui.c
+++ b/loader/shp2pgsql-gui.c
@@ -1864,6 +1864,9 @@ pgui_action_export(GtkWidget *widget, gpointer data)
 		/* Grab the SHPDUMPERCONFIG for this row */
 		gtk_tree_model_get(GTK_TREE_MODEL(export_table_list_store), &iter, EXPORT_POINTER_COLUMN, &gptr, -1);
 		dumper_table_config = (SHPDUMPERCONFIG *)gptr;
+		state = NULL;
+		output_shapefile = NULL;
+		orig_shapefile = dumper_table_config->shp_file;
 
 		pgui_logf("\n==============================");
 		pgui_logf("Exporting with configuration: %s, %s, %s", dumper_table_config->table, dumper_table_config->schema, dumper_table_config->shp_file);
@@ -1881,11 +1884,25 @@ pgui_action_export(GtkWidget *widget, gpointer data)
 
 		/* Create the state for each configuration */
 		state = ShpDumperCreate(dumper_table_config);
+		if (!state)
+		{
+			pgui_seterr(_("Out of memory allocating dumper state"));
+			pgui_raise_error_dialogue();
+
+			break;
+		}
 		state->config->conn = conn;
 
 		/* Save the original shapefile name, then create a temporary version containing the full path */
-		orig_shapefile = dumper_table_config->shp_file;
 		output_shapefile = malloc(strlen(folder_path) + strlen(dumper_table_config->shp_file) + 2);
+		if (!output_shapefile)
+		{
+			pgui_seterr(_("Out of memory allocating output shapefile path"));
+			pgui_raise_error_dialogue();
+
+			ShpDumperDestroy(state);
+			break;
+		}
 		strcpy(output_shapefile, folder_path);
 		strcat(output_shapefile, G_DIR_SEPARATOR_S);
 		strcat(output_shapefile, dumper_table_config->shp_file);
@@ -1987,6 +2004,7 @@ export_cleanup:
 
 		/* Reset shapefile back to original form (without full path) */
 		dumper_table_config->shp_file = orig_shapefile;
+		free(output_shapefile);
 
 		/* Get next entry */
 		is_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(export_table_list_store), &iter);
diff --git a/regress/dumper/null3d_expected.dbf b/regress/dumper/null3d_expected.dbf
index 3db507ed5..8c1feb282 100644
Binary files a/regress/dumper/null3d_expected.dbf and b/regress/dumper/null3d_expected.dbf differ

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

Summary of changes:
 NEWS                               |   2 ++
 loader/pgsql2shp-cli.c             |   6 +++++
 loader/pgsql2shp-core.c            |  48 +++++++++++++++++++++++++++++++++----
 loader/pgsql2shp-core.h            |   3 +++
 loader/shp2pgsql-gui.c             |  20 +++++++++++++++-
 regress/dumper/null3d_expected.dbf | Bin 33 -> 89 bytes
 6 files changed, 73 insertions(+), 6 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list