PostGIS 3.7.0dev-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 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();
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
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: