PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
shp2pgsql-cli.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://www.postgis.org
5 * Copyright 2008 OpenGeo.org
6 * Copyright 2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
7 *
8 * This is free software; you can redistribute and/or modify it under
9 * the terms of the GNU General Public Licence. See the COPYING file.
10 *
11 * Maintainer: Paul Ramsey <pramsey@opengeo.org>
12 *
13 **********************************************************************/
14
15#include "../postgis_config.h"
16
17#include "shp2pgsql-core.h"
18#include "../liblwgeom/liblwgeom.h" /* for SRID_UNKNOWN */
19
20#define xstr(s) str(s)
21#define str(s) #s
22
23static void
25{
26 printf(_( "RELEASE: %s (%s)\n" ),
27 POSTGIS_LIB_VERSION, xstr(POSTGIS_REVISION));
28 printf(_( "USAGE: shp2pgsql [<options>] <shapefile> [[<schema>.]<table>]\n"
29 "OPTIONS:\n" ));
30 printf(_( " -s [<from>:]<srid> Set the SRID field. Defaults to %d.\n"
31 " Optionally reprojects from given SRID.\n"),
33 printf(_( " (-d|a|c|p) These are mutually exclusive options:\n"
34 " -d Drops the table, then recreates it and populates\n"
35 " it with current shape file data.\n"
36 " -a Appends shape file into current table, must be\n"
37 " exactly the same table schema.\n"
38 " -c Creates a new table and populates it, this is the\n"
39 " default if you do not specify any options.\n"
40 " -p Prepare mode, only creates the table.\n" ));
41 printf(_( " -g <geocolumn> Specify the name of the geometry/geography column\n"
42 " (mostly useful in append mode).\n" ));
43 printf(_( " -D Use postgresql dump format (defaults to SQL insert statements).\n" ));
44 printf(_( " -e Execute each statement individually, do not use a transaction.\n"
45 " Not compatible with -D.\n" ));
46 printf(_( " -G Use geography type (requires lon/lat data or -s to reproject).\n" ));
47 printf(_( " -k Keep postgresql identifiers case.\n" ));
48 printf(_( " -i Use int4 type for all integer dbf fields.\n" ));
49 printf(_( " -I Create a spatial index on the geocolumn.\n" ));
50 printf(_(" -m <filename> Specify a file containing a set of mappings of (long) column\n"
51 " names to 10 character DBF column names. The content of the file is one or\n"
52 " more lines of two names separated by white space and no trailing or\n"
53 " leading space. For example:\n"
54 " COLUMNNAME DBFFIELD1\n"
55 " AVERYLONGCOLUMNNAME DBFFIELD2\n" ));
56 printf(_( " -S Generate simple geometries instead of MULTI geometries.\n" ));
57 printf(_( " -t <dimensionality> Force geometry to be one of '2D', '3DZ', '3DM', or '4D'\n" ));
58
59 printf(_( " -w Output WKT instead of WKB. Note that this can result in\n"
60 " coordinate drift.\n" ));
61 printf(_( " -W <encoding> Specify the character encoding of Shape's\n"
62 " attribute column. (default: \"UTF-8\")\n" ));
63 printf(_( " -N <policy> NULL geometries handling policy (insert*,skip,abort).\n" ));
64 printf(_( " -n Only import DBF file.\n" ));
65 printf(_( " -T <tablespace> Specify the tablespace for the new table.\n"
66 " Note that indexes will still use the default tablespace unless the\n"
67 " -X flag is also used.\n"));
68 printf(_( " -X <tablespace> Specify the tablespace for the table's indexes.\n"
69 " This applies to the primary key, and the spatial index if\n"
70 " the -I flag is used.\n" ));
71 printf(_( " -Z Prevent tables from being analyzed.\n" ));
72 printf(_( " -? Display this help screen.\n" ));
73 printf( "\n" );
74 printf(_( " An argument of `--' disables further option processing.\n" ));
75 printf(_( " (useful for unusual file names starting with '-')\n" ));
76}
77
78
79int
80main (int argc, char **argv)
81{
82 SHPLOADERCONFIG *config;
83 SHPLOADERSTATE *state;
84 char *header, *footer, *record;
85 int c;
86 int ret, i;
87
88#ifdef ENABLE_NLS
89#ifdef PGSQL_LOCALEDIR
90 setlocale (LC_ALL, "");
91 bindtextdomain (PACKAGE, PGSQL_LOCALEDIR);
92 textdomain (PACKAGE);
93#endif
94#endif
95
96 /* If no options are specified, display usage */
97 if (argc == 1)
98 {
99 usage();
100 exit(0);
101 }
102
103 /* Parse command line options and set configuration */
104 config = malloc(sizeof(SHPLOADERCONFIG));
106
107 /* Keep the flag list alphabetic so it's easy to see what's left. */
108 while ((c = pgis_getopt(argc, argv, "-?acdeg:ikm:nps:t:wDGIN:ST:W:X:Z")) != EOF)
109 {
110 // can not do this inside the switch case
111 if ('-' == c)
112 break;
113
114 switch (c)
115 {
116 case 'c':
117 case 'd':
118 case 'a':
119 case 'p':
120 config->opt = c;
121 break;
122
123 case 'D':
124 config->dump_format = 1;
125 break;
126
127 case 'G':
128 config->geography = 1;
129 break;
130
131 case 'Z':
132 config->analyze = 0;
133 break;
134
135 case 'S':
136 config->simple_geometries = 1;
137 break;
138
139 case 's':
140 if (pgis_optarg)
141 {
142 char *ptr = strchr(pgis_optarg, ':');
143 if (ptr)
144 {
145 *ptr++ = '\0';
146 sscanf(pgis_optarg, "%d", &config->shp_sr_id);
147 sscanf(ptr, "%d", &config->sr_id);
148 }
149 else
150 {
151 /* Only TO_SRID specified */
152 sscanf(pgis_optarg, "%d", &config->sr_id);
153 }
154 }
155 else
156 {
157 /* With -s, user must specify TO_SRID or FROM_SRID:TO_SRID */
158 fprintf(stderr, "The -s parameter must be specified in the form [FROM_SRID:]TO_SRID\n");
159 exit(1);
160 }
161 break;
162 case 'g':
163 config->geo_col = pgis_optarg;
164 break;
165 case 'm':
167 break;
168
169 case 'k':
170 config->quoteidentifiers = 1;
171 break;
172
173 case 'i':
174 config->forceint4 = 1;
175 break;
176
177 case 'I':
178 config->createindex = 1;
179 break;
180
181 case 'w':
182 config->use_wkt = 1;
183 break;
184
185 case 'n':
186 config->readshape = 0;
187 break;
188
189 case 'W':
190 free(config->encoding);
191 config->encoding = strdup(pgis_optarg);
192 break;
193
194 case 'N':
195 switch (pgis_optarg[0])
196 {
197 case 'a':
199 break;
200 case 'i':
202 break;
203 case 's':
205 break;
206 default:
207 fprintf(stderr, "Unsupported NULL geometry handling policy.\nValid policies: insert, skip, abort\n");
208 exit(1);
209 }
210 break;
211
212 case 't':
213 if (strcasecmp(pgis_optarg, "2D") == 0)
214 {
216 }
217 else if (strcasecmp(pgis_optarg, "3DZ") == 0 )
218 {
220 }
221 else if (strcasecmp(pgis_optarg, "3DM") == 0 )
222 {
224 }
225 else if (strcasecmp(pgis_optarg, "4D") == 0 )
226 {
228 }
229 else
230 {
231 fprintf(stderr, "Unsupported output type: %s\nValid output types are 2D, 3DZ, 3DM and 4D\n", pgis_optarg);
232 exit(1);
233 }
234 break;
235
236 case 'T':
237 config->tablespace = pgis_optarg;
238 break;
239
240 case 'X':
241 config->idxtablespace = pgis_optarg;
242 break;
243
244 case 'e':
245 config->usetransaction = 0;
246 break;
247
248 case '?':
249 usage();
250 exit(0);
251
252 default:
253 usage();
254 exit(0);
255 }
256 }
257
258 /* Once we have parsed the arguments, make sure certain combinations are valid */
259 if (config->dump_format && !config->usetransaction)
260 {
261 fprintf(stderr, "Invalid argument combination - cannot use both -D and -e\n");
262 exit(1);
263 }
264
265 /* Determine the shapefile name from the next argument, if no shape file, exit. */
266 if (pgis_optind < argc)
267 {
268 config->shp_file = argv[pgis_optind];
269 pgis_optind++;
270 }
271 else
272 {
273 usage();
274 exit(0);
275 }
276
277 /* Determine the table and schema names from the next argument */
278 if (pgis_optind < argc)
279 {
280 char *strptr = argv[pgis_optind];
281 char *chrptr = strchr(strptr, '.');
282
283 /* OK, this is a schema-qualified table name... */
284 if (chrptr)
285 {
286 if ( chrptr == strptr )
287 {
288 /* ".something" ??? */
289 usage();
290 exit(0);
291 }
292 /* Null terminate at the '.' */
293 *chrptr = '\0';
294 /* Copy in the parts */
295 config->schema = strdup(strptr);
296 config->table = strdup(chrptr+1);
297 }
298 else
299 {
300 config->table = strdup(strptr);
301 }
302 }
303
304 /* If the table parameter is not provided, use the shape file name as a proxy value.
305 Strip out the .shp and the leading path information first. */
306 if ( config->shp_file && config->table == NULL)
307 {
308 char *shp_file = strdup(config->shp_file);
309 char *ptr;
310
311 if ( shp_file == NULL )
312 {
313 fprintf(stderr, "Unable to allocate memory for shapefile name\n");
314 exit(1);
315 }
316
317 /* Remove the extension, if present */
318 for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
319 {
320 if ( *ptr == '.' )
321 {
322 *ptr = '\0';
323 break;
324 }
325 }
326
327 /* The remaining non-path section is the table name */
328 for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
329 {
330 if ( *ptr == '/' || *ptr == '\\' )
331 {
332 ptr++;
333 break;
334 }
335 }
336 config->table = strdup(ptr);
337 free(shp_file);
338 }
339
340
341 /* Transform table name to lower case if no quoting specified */
342 if (!config->quoteidentifiers)
343 {
344 if ( config->table )
345 strtolower(config->table);
346 if ( config->schema )
347 strtolower(config->schema);
348 }
349
350 /* Create the shapefile state object */
351 state = ShpLoaderCreate(config);
352
353 /* Open the shapefile */
354 ret = ShpLoaderOpenShape(state);
355 if (ret != SHPLOADEROK)
356 {
357 fprintf(stderr, "%s\n", state->message);
358
359 if (ret == SHPLOADERERR)
360 exit(1);
361 }
362
363 /* If reading the whole shapefile, display its type */
364 if (state->config->readshape)
365 {
366 fprintf(stderr, "Shapefile type: %s\n", SHPTypeName(state->shpfiletype));
367 fprintf(stderr, "Postgis type: %s[%d]\n", state->pgtype, state->pgdims);
368 }
369
370 /* Print the header to stdout */
371 ret = ShpLoaderGetSQLHeader(state, &header);
372 if (ret != SHPLOADEROK)
373 {
374 fprintf(stderr, "%s\n", state->message);
375
376 if (ret == SHPLOADERERR)
377 exit(1);
378 }
379
380 printf("%s", header);
381 free(header);
382
383 /* If we are not in "prepare" mode, go ahead and write out the data. */
384 if ( state->config->opt != 'p' )
385 {
386
387 /* If in COPY mode, output the COPY statement */
388 if (state->config->dump_format)
389 {
390 ret = ShpLoaderGetSQLCopyStatement(state, &header);
391 if (ret != SHPLOADEROK)
392 {
393 fprintf(stderr, "%s\n", state->message);
394
395 if (ret == SHPLOADERERR)
396 exit(1);
397 }
398
399 printf("%s", header);
400 free(header);
401 }
402
403 /* Main loop: iterate through all of the records and send them to stdout */
404 for (i = 0; i < ShpLoaderGetRecordCount(state); i++)
405 {
406 ret = ShpLoaderGenerateSQLRowStatement(state, i, &record);
407
408 switch (ret)
409 {
410 case SHPLOADEROK:
411 /* Simply display the geometry */
412 printf("%s\n", record);
413 free(record);
414 break;
415
416 case SHPLOADERERR:
417 /* Display the error message then stop */
418 fprintf(stderr, "%s\n", state->message);
419 exit(1);
420 break;
421
422 case SHPLOADERWARN:
423 /* Display the warning, but continue */
424 fprintf(stderr, "%s\n", state->message);
425 printf("%s\n", record);
426 free(record);
427 break;
428
430 /* Record is marked as deleted - ignore */
431 break;
432
434 /* Record is NULL and should be ignored according to NULL policy */
435 break;
436 }
437 }
438
439 /* If in COPY mode, terminate the COPY statement */
440 if (state->config->dump_format)
441 printf("\\.\n");
442
443 }
444
445 /* Print the footer to stdout */
446 ret = ShpLoaderGetSQLFooter(state, &footer);
447 if (ret != SHPLOADEROK)
448 {
449 fprintf(stderr, "%s\n", state->message);
450
451 if (ret == SHPLOADERERR)
452 exit(1);
453 }
454
455 printf("%s", footer);
456 free(footer);
457
458
459 /* Free the state object */
460 ShpLoaderDestroy(state);
461
462 /* Free configuration variables */
463 free(config->schema);
464 free(config->table);
465 free(config->encoding);
466 free(config);
467
468 return 0;
469}
int pgis_optind
Definition getopt.c:39
int pgis_getopt(int argc, char **argv, char *opts)
Definition getopt.c:44
char * pgis_optarg
Definition getopt.c:41
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
void * malloc(YYSIZE_T)
void free(void *)
int main(void)
const char SHPAPI_CALL1 * SHPTypeName(int nSHPType);const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType
Definition shpopen.c:2562
static void usage()
#define xstr(s)
int ShpLoaderGetRecordCount(SHPLOADERSTATE *state)
void strtolower(char *s)
void ShpLoaderDestroy(SHPLOADERSTATE *state)
SHPLOADERSTATE * ShpLoaderCreate(SHPLOADERCONFIG *config)
int ShpLoaderGetSQLCopyStatement(SHPLOADERSTATE *state, char **strheader)
int ShpLoaderOpenShape(SHPLOADERSTATE *state)
int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord)
void set_loader_config_defaults(SHPLOADERCONFIG *config)
int ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter)
int ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
#define FORCE_OUTPUT_4D
#define POLICY_NULL_ABORT
#define FORCE_OUTPUT_2D
#define SHPLOADERRECISNULL
#define SHPLOADERWARN
#define FORCE_OUTPUT_3DM
#define POLICY_NULL_SKIP
#define POLICY_NULL_INSERT
#define SHPLOADERRECDELETED
#define SHPLOADERERR
#define SHPLOADEROK
#define FORCE_OUTPUT_3DZ
#define _(String)
Definition shpcommon.h:24
#define POSTGIS_LIB_VERSION
Definition sqldefines.h:13
char message[SHPLOADERMSGLEN]
SHPLOADERCONFIG * config