PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ ShpLoaderGetSQLHeader()

int ShpLoaderGetSQLHeader ( SHPLOADERSTATE state,
char **  strheader 
)

TODO: if the table has more then one geometry column the DROP TABLE call will leave spurious records in geometry_columns.

If the geometry column in the table being dropped does not match 'the_geom' or the name specified with -g an error is returned by DropGeometryColumn.

The table to be dropped might not exist.

If we are in dump mode and a transform was asked for need to create a temp table to store original data You may ask, why don't we go straight into the main table and then do an alter table alter column afterwards Main reason is so we don't incur the penalty of WAL logging when we change the typmod in final run.

create a temp table with same structure as main except for no restriction on geometry type

out input data is going to be in different srid from target, so need to remove type constraint

Definition at line 1280 of file shp2pgsql-core.c.

1281 {
1282  stringbuffer_t *sb;
1283  char *ret;
1284  int j;
1285 
1286  /* Create the stringbuffer containing the header; we use this API as it's easier
1287  for handling string resizing during append */
1288  sb = stringbuffer_create();
1289  stringbuffer_clear(sb);
1290 
1291  /* Set the client encoding if required */
1292  if (state->config->encoding)
1293  {
1294  stringbuffer_aprintf(sb, "SET CLIENT_ENCODING TO UTF8;\n");
1295  }
1296 
1297  /* Use SQL-standard string escaping rather than PostgreSQL standard */
1298  stringbuffer_aprintf(sb, "SET STANDARD_CONFORMING_STRINGS TO ON;\n");
1299 
1300  /* Drop table if requested */
1301  if (state->config->opt == 'd')
1302  {
1314  if (state->config->schema)
1315  {
1316  if (state->config->readshape == 1 && (! state->config->geography) )
1317  {
1318  stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('%s','%s','%s');\n",
1319  state->config->schema, state->config->table, state->geo_col);
1320  }
1321 
1322  stringbuffer_aprintf(sb, "DROP TABLE IF EXISTS \"%s\".\"%s\";\n", state->config->schema,
1323  state->config->table);
1324  }
1325  else
1326  {
1327  if (state->config->readshape == 1 && (! state->config->geography) )
1328  {
1329  stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('','%s','%s');\n",
1330  state->config->table, state->geo_col);
1331  }
1332 
1333  stringbuffer_aprintf(sb, "DROP TABLE IF EXISTS \"%s\";\n", state->config->table);
1334  }
1335  }
1336 
1337  /* Start of transaction if we are using one */
1338  if (state->config->usetransaction)
1339  {
1340  stringbuffer_aprintf(sb, "BEGIN;\n");
1341  }
1342 
1343  /* If not in 'append' mode create the spatial table */
1344  if (state->config->opt != 'a')
1345  {
1346  /*
1347  * Create a table for inserting the shapes into with appropriate
1348  * columns and types
1349  */
1350  if (state->config->schema)
1351  {
1352  stringbuffer_aprintf(sb, "CREATE TABLE \"%s\".\"%s\" (gid serial",
1353  state->config->schema, state->config->table);
1354  }
1355  else
1356  {
1357  stringbuffer_aprintf(sb, "CREATE TABLE \"%s\" (gid serial", state->config->table);
1358  }
1359 
1360  /* Generate the field types based upon the shapefile information */
1361  for (j = 0; j < state->num_fields; j++)
1362  {
1363  stringbuffer_aprintf(sb, ",\n\"%s\" ", state->field_names[j]);
1364 
1365  /* First output the raw field type string */
1366  stringbuffer_aprintf(sb, "%s", state->pgfieldtypes[j]);
1367 
1368  /* Some types do have typmods */
1369  /* Apply width typmod for varchar if there is positive width **/
1370  if (!strcmp("varchar", state->pgfieldtypes[j]) && state->widths[j] > 0)
1371  stringbuffer_aprintf(sb, "(%d)", state->widths[j]);
1372 
1373  if (!strcmp("numeric", state->pgfieldtypes[j]))
1374  {
1375  /* Doubles we just allow PostgreSQL to auto-detect the size */
1376  if (state->types[j] != FTDouble)
1377  stringbuffer_aprintf(sb, "(%d,0)", state->widths[j]);
1378  }
1379  }
1380 
1381  /* Add the geography column directly to the table definition, we don't
1382  need to do an AddGeometryColumn() call. */
1383  if (state->config->readshape == 1 && state->config->geography)
1384  {
1385  char *dimschar;
1386 
1387  if (state->pgdims == 4)
1388  dimschar = "ZM";
1389  else
1390  dimschar = "";
1391 
1392  if (state->to_srid == SRID_UNKNOWN ){
1393  state->to_srid = 4326;
1394  }
1395 
1396  stringbuffer_aprintf(sb, ",\n\"%s\" geography(%s%s,%d)", state->geo_col, state->pgtype, dimschar, state->to_srid);
1397  }
1398  stringbuffer_aprintf(sb, ")");
1399 
1400  /* Tablespace is optional. */
1401  if (state->config->tablespace != NULL)
1402  {
1403  stringbuffer_aprintf(sb, " TABLESPACE \"%s\"", state->config->tablespace);
1404  }
1405  stringbuffer_aprintf(sb, ";\n");
1406 
1407  /* Create the primary key. This is done separately because the index for the PK needs
1408  * to be in the correct tablespace. */
1409 
1410  /* TODO: Currently PostgreSQL does not allow specifying an index to use for a PK (so you get
1411  * a default one called table_pkey) and it does not provide a way to create a PK index
1412  * in a specific tablespace. So as a hacky solution we create the PK, then move the
1413  * index to the correct tablespace. Eventually this should be:
1414  * CREATE INDEX table_pkey on table(gid) TABLESPACE tblspc;
1415  * ALTER TABLE table ADD PRIMARY KEY (gid) USING INDEX table_pkey;
1416  * A patch has apparently been submitted to PostgreSQL to enable this syntax, see this thread:
1417  * http://archives.postgresql.org/pgsql-hackers/2011-01/msg01405.php */
1418  stringbuffer_aprintf(sb, "ALTER TABLE ");
1419 
1420  /* Schema is optional, include if present. */
1421  if (state->config->schema)
1422  {
1423  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1424  }
1425  stringbuffer_aprintf(sb, "\"%s\" ADD PRIMARY KEY (gid);\n", state->config->table);
1426 
1427  /* Tablespace is optional for the index. */
1428  if (state->config->idxtablespace != NULL)
1429  {
1430  stringbuffer_aprintf(sb, "ALTER INDEX ");
1431  if (state->config->schema)
1432  {
1433  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1434  }
1435 
1436  /* WARNING: We're assuming the default "table_pkey" name for the primary
1437  * key index. PostgreSQL may use "table_pkey1" or similar in the
1438  * case of a name conflict, so you may need to edit the produced
1439  * SQL in this rare case. */
1440  stringbuffer_aprintf(sb, "\"%s_pkey\" SET TABLESPACE \"%s\";\n",
1441  state->config->table, state->config->idxtablespace);
1442  }
1443 
1444  /* Create the geometry column with an addgeometry call */
1445  if (state->config->readshape == 1 && (!state->config->geography))
1446  {
1447  /* If they didn't specify a target SRID, see if they specified a source SRID. */
1448  int32_t srid = state->to_srid;
1449  if (state->config->schema)
1450  {
1451  stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('%s','%s','%s','%d',",
1452  state->config->schema, state->config->table, state->geo_col, srid);
1453  }
1454  else
1455  {
1456  stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('','%s','%s','%d',",
1457  state->config->table, state->geo_col, srid);
1458  }
1459 
1460  stringbuffer_aprintf(sb, "'%s',%d);\n", state->pgtype, state->pgdims);
1461  }
1462  }
1463 
1467  if (state->config->dump_format && state->to_srid != state->from_srid){
1469  stringbuffer_aprintf(sb, "CREATE TEMP TABLE \"pgis_tmp_%s\" AS SELECT * FROM ", state->config->table);
1470  /* Schema is optional, include if present. */
1471  if (state->config->schema)
1472  {
1473  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1474  }
1475  stringbuffer_aprintf(sb, "\"%s\" WHERE false;\n", state->config->table);
1477  stringbuffer_aprintf(sb, "ALTER TABLE \"pgis_tmp_%s\" ALTER COLUMN \"%s\" TYPE geometry USING ( (\"%s\"::geometry) ); \n", state->config->table, state->geo_col, state->geo_col);
1478  }
1479 
1480  /* Copy the string buffer into a new string, destroying the string buffer */
1481  ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1);
1482  strcpy(ret, (char *)stringbuffer_getstring(sb));
1484 
1485  *strheader = ret;
1486 
1487  return SHPLOADEROK;
1488 }
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
void * malloc(YYSIZE_T)
@ FTDouble
Definition: shapefil.h:641
#define SHPLOADEROK
void stringbuffer_clear(stringbuffer_t *s)
Reset the stringbuffer_t.
Definition: stringbuffer.c:100
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
Definition: stringbuffer.c:254
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:33
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:85
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:125
DBFFieldType * types
SHPLOADERCONFIG * config

References shp_loader_state::config, shp_loader_config::dump_format, shp_loader_config::encoding, shp_loader_state::field_names, shp_loader_state::from_srid, FTDouble, shp_loader_state::geo_col, shp_loader_config::geography, shp_loader_config::idxtablespace, malloc(), shp_loader_state::num_fields, shp_loader_config::opt, shp_loader_state::pgdims, shp_loader_state::pgfieldtypes, shp_loader_state::pgtype, shp_loader_config::readshape, shp_loader_config::schema, SHPLOADEROK, SRID_UNKNOWN, stringbuffer_aprintf(), stringbuffer_clear(), stringbuffer_create(), stringbuffer_destroy(), stringbuffer_getstring(), shp_loader_config::table, shp_loader_config::tablespace, shp_loader_state::to_srid, shp_loader_state::types, shp_loader_config::usetransaction, and shp_loader_state::widths.

Referenced by pgui_action_import().

Here is the call graph for this function:
Here is the caller graph for this function: