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