PostGIS  3.4.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 1275 of file shp2pgsql-core.c.

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