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