PostGIS  3.7.0dev-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 #define xstr(s) str(s)
21 #define str(s) #s
22 
23 static 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"),
32  SRID_UNKNOWN);
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 
79 int
80 main (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':
198  config->null_policy = POLICY_NULL_ABORT;
199  break;
200  case 'i':
202  break;
203  case 's':
204  config->null_policy = POLICY_NULL_SKIP;
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  {
215  config->force_output = FORCE_OUTPUT_2D;
216  }
217  else if (strcasecmp(pgis_optarg, "3DZ") == 0 )
218  {
219  config->force_output = FORCE_OUTPUT_3DZ;
220  }
221  else if (strcasecmp(pgis_optarg, "3DM") == 0 )
222  {
223  config->force_output = FORCE_OUTPUT_3DM;
224  }
225  else if (strcasecmp(pgis_optarg, "4D") == 0 )
226  {
227  config->force_output = FORCE_OUTPUT_4D;
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  /* Remove the extension, if present */
312  for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
313  {
314  if ( *ptr == '.' )
315  {
316  *ptr = '\0';
317  break;
318  }
319  }
320 
321  /* The remaining non-path section is the table name */
322  for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
323  {
324  if ( *ptr == '/' || *ptr == '\\' )
325  {
326  ptr++;
327  break;
328  }
329  }
330  config->table = strdup(ptr);
331  free(shp_file);
332  }
333 
334 
335  /* Transform table name to lower case if no quoting specified */
336  if (!config->quoteidentifiers)
337  {
338  if ( config->table )
339  strtolower(config->table);
340  if ( config->schema )
341  strtolower(config->schema);
342  }
343 
344  /* Create the shapefile state object */
345  state = ShpLoaderCreate(config);
346 
347  /* Open the shapefile */
348  ret = ShpLoaderOpenShape(state);
349  if (ret != SHPLOADEROK)
350  {
351  fprintf(stderr, "%s\n", state->message);
352 
353  if (ret == SHPLOADERERR)
354  exit(1);
355  }
356 
357  /* If reading the whole shapefile, display its type */
358  if (state->config->readshape)
359  {
360  fprintf(stderr, "Shapefile type: %s\n", SHPTypeName(state->shpfiletype));
361  fprintf(stderr, "Postgis type: %s[%d]\n", state->pgtype, state->pgdims);
362  }
363 
364  /* Print the header to stdout */
365  ret = ShpLoaderGetSQLHeader(state, &header);
366  if (ret != SHPLOADEROK)
367  {
368  fprintf(stderr, "%s\n", state->message);
369 
370  if (ret == SHPLOADERERR)
371  exit(1);
372  }
373 
374  printf("%s", header);
375  free(header);
376 
377  /* If we are not in "prepare" mode, go ahead and write out the data. */
378  if ( state->config->opt != 'p' )
379  {
380 
381  /* If in COPY mode, output the COPY statement */
382  if (state->config->dump_format)
383  {
384  ret = ShpLoaderGetSQLCopyStatement(state, &header);
385  if (ret != SHPLOADEROK)
386  {
387  fprintf(stderr, "%s\n", state->message);
388 
389  if (ret == SHPLOADERERR)
390  exit(1);
391  }
392 
393  printf("%s", header);
394  free(header);
395  }
396 
397  /* Main loop: iterate through all of the records and send them to stdout */
398  for (i = 0; i < ShpLoaderGetRecordCount(state); i++)
399  {
400  ret = ShpLoaderGenerateSQLRowStatement(state, i, &record);
401 
402  switch (ret)
403  {
404  case SHPLOADEROK:
405  /* Simply display the geometry */
406  printf("%s\n", record);
407  free(record);
408  break;
409 
410  case SHPLOADERERR:
411  /* Display the error message then stop */
412  fprintf(stderr, "%s\n", state->message);
413  exit(1);
414  break;
415 
416  case SHPLOADERWARN:
417  /* Display the warning, but continue */
418  fprintf(stderr, "%s\n", state->message);
419  printf("%s\n", record);
420  free(record);
421  break;
422 
423  case SHPLOADERRECDELETED:
424  /* Record is marked as deleted - ignore */
425  break;
426 
427  case SHPLOADERRECISNULL:
428  /* Record is NULL and should be ignored according to NULL policy */
429  break;
430  }
431  }
432 
433  /* If in COPY mode, terminate the COPY statement */
434  if (state->config->dump_format)
435  printf("\\.\n");
436 
437  }
438 
439  /* Print the footer to stdout */
440  ret = ShpLoaderGetSQLFooter(state, &footer);
441  if (ret != SHPLOADEROK)
442  {
443  fprintf(stderr, "%s\n", state->message);
444 
445  if (ret == SHPLOADERERR)
446  exit(1);
447  }
448 
449  printf("%s", footer);
450  free(footer);
451 
452 
453  /* Free the state object */
454  ShpLoaderDestroy(state);
455 
456  /* Free configuration variables */
457  free(config->schema);
458  free(config->table);
459  free(config->encoding);
460  free(config);
461 
462  return 0;
463 }
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
int main(int argc, char *argv[])
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
void * malloc(YYSIZE_T)
void free(void *)
const char SHPAPI_CALL1 * SHPTypeName(int nSHPType);const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType
Definition: shpopen.c:2551
static void usage()
Definition: shp2pgsql-cli.c:24
#define xstr(s)
Definition: shp2pgsql-cli.c:20
int ShpLoaderGetRecordCount(SHPLOADERSTATE *state)
void strtolower(char *s)
void ShpLoaderDestroy(SHPLOADERSTATE *state)
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)
SHPLOADERSTATE * ShpLoaderCreate(SHPLOADERCONFIG *config)
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