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

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