PostGIS  3.3.9dev-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 1278 of file shp2pgsql-core.c.

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