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 1276 of file shp2pgsql-core.c.

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