PostGIS 3.6.2dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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();
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
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
void stringbuffer_clear(stringbuffer_t *s)
Reset the stringbuffer_t.
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.
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
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 main(), and pgui_action_import().

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