PostGIS  2.2.7dev-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 }
69 
70 
71 int
72 main (int argc, char **argv)
73 {
74  SHPLOADERCONFIG *config;
75  SHPLOADERSTATE *state;
76  char *header, *footer, *record;
77  int c;
78  int ret, i;
79 
80 #ifdef ENABLE_NLS
81  setlocale (LC_ALL, "");
82  bindtextdomain (PACKAGE, PGSQL_LOCALEDIR);
83  textdomain (PACKAGE);
84 #endif
85 
86  /* If no options are specified, display usage */
87  if (argc == 1)
88  {
89  usage();
90  exit(0);
91  }
92 
93  /* Parse command line options and set configuration */
94  config = malloc(sizeof(SHPLOADERCONFIG));
96 
97  /* Keep the flag list alphabetic so it's easy to see what's left. */
98  while ((c = pgis_getopt(argc, argv, "acdeg:ikm:nps:t:wDGIN:ST:W:X:")) != EOF)
99  {
100  switch (c)
101  {
102  case 'c':
103  case 'd':
104  case 'a':
105  case 'p':
106  config->opt = c;
107  break;
108 
109  case 'D':
110  config->dump_format = 1;
111  break;
112 
113  case 'G':
114  config->geography = 1;
115  break;
116 
117  case 'S':
118  config->simple_geometries = 1;
119  break;
120 
121  case 's':
122  if (pgis_optarg)
123  {
124  char *ptr = strchr(pgis_optarg, ':');
125  if (ptr)
126  {
127  *ptr++ = '\0';
128  sscanf(pgis_optarg, "%d", &config->shp_sr_id);
129  sscanf(ptr, "%d", &config->sr_id);
130  }
131  else
132  {
133  /* Only TO_SRID specified */
134  sscanf(pgis_optarg, "%d", &config->sr_id);
135  }
136  }
137  else
138  {
139  /* With -s, user must specify TO_SRID or FROM_SRID:TO_SRID */
140  fprintf(stderr, "The -s parameter must be specified in the form [FROM_SRID:]TO_SRID\n");
141  exit(1);
142  }
143  break;
144  case 'g':
145  config->geo_col = pgis_optarg;
146  break;
147  case 'm':
149  break;
150 
151  case 'k':
152  config->quoteidentifiers = 1;
153  break;
154 
155  case 'i':
156  config->forceint4 = 1;
157  break;
158 
159  case 'I':
160  config->createindex = 1;
161  break;
162 
163  case 'w':
164  config->use_wkt = 1;
165  break;
166 
167  case 'n':
168  config->readshape = 0;
169  break;
170 
171  case 'W':
172  config->encoding = strdup(pgis_optarg);
173  break;
174 
175  case 'N':
176  switch (pgis_optarg[0])
177  {
178  case 'a':
179  config->null_policy = POLICY_NULL_ABORT;
180  break;
181  case 'i':
183  break;
184  case 's':
185  config->null_policy = POLICY_NULL_SKIP;
186  break;
187  default:
188  fprintf(stderr, "Unsupported NULL geometry handling policy.\nValid policies: insert, skip, abort\n");
189  exit(1);
190  }
191  break;
192 
193  case 't':
194  if (strcasecmp(pgis_optarg, "2D") == 0)
195  {
196  config->force_output = FORCE_OUTPUT_2D;
197  }
198  else if (strcasecmp(pgis_optarg, "3DZ") == 0 )
199  {
200  config->force_output = FORCE_OUTPUT_3DZ;
201  }
202  else if (strcasecmp(pgis_optarg, "3DM") == 0 )
203  {
204  config->force_output = FORCE_OUTPUT_3DM;
205  }
206  else if (strcasecmp(pgis_optarg, "4D") == 0 )
207  {
208  config->force_output = FORCE_OUTPUT_4D;
209  }
210  else
211  {
212  fprintf(stderr, "Unsupported output type: %s\nValid output types are 2D, 3DZ, 3DM and 4D\n", pgis_optarg);
213  exit(1);
214  }
215  break;
216 
217  case 'T':
218  config->tablespace = pgis_optarg;
219  break;
220 
221  case 'X':
222  config->idxtablespace = pgis_optarg;
223  break;
224 
225  case 'e':
226  config->usetransaction = 0;
227  break;
228 
229  case '?':
230  usage();
231  exit(0);
232 
233  default:
234  usage();
235  exit(0);
236  }
237  }
238 
239  /* Once we have parsed the arguments, make sure certain combinations are valid */
240  if (config->dump_format && !config->usetransaction)
241  {
242  fprintf(stderr, "Invalid argument combination - cannot use both -D and -e\n");
243  exit(1);
244  }
245 
246  if (config->dump_format && config->shp_sr_id != SRID_UNKNOWN)
247  {
248  fprintf(stderr, "Invalid argument combination - cannot use -D with -s FROM_SRID:TO_SRID\n");
249  exit(1);
250  }
251 
252  /* Determine the shapefile name from the next argument, if no shape file, exit. */
253  if (pgis_optind < argc)
254  {
255  config->shp_file = argv[pgis_optind];
256  pgis_optind++;
257  }
258  else
259  {
260  usage();
261  exit(0);
262  }
263 
264  /* Determine the table and schema names from the next argument */
265  if (pgis_optind < argc)
266  {
267  char *strptr = argv[pgis_optind];
268  char *chrptr = strchr(strptr, '.');
269 
270  /* OK, this is a schema-qualified table name... */
271  if (chrptr)
272  {
273  if ( chrptr == strptr )
274  {
275  /* ".something" ??? */
276  usage();
277  exit(0);
278  }
279  /* Null terminate at the '.' */
280  *chrptr = '\0';
281  /* Copy in the parts */
282  config->schema = strdup(strptr);
283  config->table = strdup(chrptr+1);
284  }
285  else
286  {
287  config->table = strdup(strptr);
288  }
289  }
290 
291  /* If the table parameter is not provided, use the shape file name as a proxy value.
292  Strip out the .shp and the leading path information first. */
293  if ( config->shp_file && config->table == NULL)
294  {
295  char *shp_file = strdup(config->shp_file);
296  char *ptr;
297 
298  /* Remove the extension, if present */
299  for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
300  {
301  if ( *ptr == '.' )
302  {
303  *ptr = '\0';
304  break;
305  }
306  }
307 
308  /* The remaining non-path section is the table name */
309  for ( ptr = shp_file + strlen(shp_file); ptr > shp_file; ptr-- )
310  {
311  if ( *ptr == '/' || *ptr == '\\' )
312  {
313  ptr++;
314  break;
315  }
316  }
317  config->table = strdup(ptr);
318  free(shp_file);
319  }
320 
321 
322  /* Transform table name to lower case if no quoting specified */
323  if (!config->quoteidentifiers)
324  {
325  if ( config->table )
326  strtolower(config->table);
327  if ( config->schema )
328  strtolower(config->schema);
329  }
330 
331  /* Create the shapefile state object */
332  state = ShpLoaderCreate(config);
333 
334  /* Open the shapefile */
335  ret = ShpLoaderOpenShape(state);
336  if (ret != SHPLOADEROK)
337  {
338  fprintf(stderr, "%s\n", state->message);
339 
340  if (ret == SHPLOADERERR)
341  exit(1);
342  }
343 
344  /* If reading the whole shapefile, display its type */
345  if (state->config->readshape)
346  {
347  fprintf(stderr, "Shapefile type: %s\n", SHPTypeName(state->shpfiletype));
348  fprintf(stderr, "Postgis type: %s[%d]\n", state->pgtype, state->pgdims);
349  }
350 
351  /* Print the header to stdout */
352  ret = ShpLoaderGetSQLHeader(state, &header);
353  if (ret != SHPLOADEROK)
354  {
355  fprintf(stderr, "%s\n", state->message);
356 
357  if (ret == SHPLOADERERR)
358  exit(1);
359  }
360 
361  printf("%s", header);
362  free(header);
363 
364  /* If we are not in "prepare" mode, go ahead and write out the data. */
365  if ( state->config->opt != 'p' )
366  {
367 
368  /* If in COPY mode, output the COPY statement */
369  if (state->config->dump_format)
370  {
371  ret = ShpLoaderGetSQLCopyStatement(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 
384  /* Main loop: iterate through all of the records and send them to stdout */
385  for (i = 0; i < ShpLoaderGetRecordCount(state); i++)
386  {
387  ret = ShpLoaderGenerateSQLRowStatement(state, i, &record);
388 
389  switch (ret)
390  {
391  case SHPLOADEROK:
392  /* Simply display the geometry */
393  printf("%s\n", record);
394  free(record);
395  break;
396 
397  case SHPLOADERERR:
398  /* Display the error message then stop */
399  fprintf(stderr, "%s\n", state->message);
400  exit(1);
401  break;
402 
403  case SHPLOADERWARN:
404  /* Display the warning, but continue */
405  fprintf(stderr, "%s\n", state->message);
406  printf("%s\n", record);
407  free(record);
408  break;
409 
410  case SHPLOADERRECDELETED:
411  /* Record is marked as deleted - ignore */
412  break;
413 
414  case SHPLOADERRECISNULL:
415  /* Record is NULL and should be ignored according to NULL policy */
416  break;
417  }
418  }
419 
420  /* If in COPY mode, terminate the COPY statement */
421  if (state->config->dump_format)
422  printf("\\.\n");
423 
424  }
425 
426  /* Print the footer to stdout */
427  ret = ShpLoaderGetSQLFooter(state, &footer);
428  if (ret != SHPLOADEROK)
429  {
430  fprintf(stderr, "%s\n", state->message);
431 
432  if (ret == SHPLOADERERR)
433  exit(1);
434  }
435 
436  printf("%s", footer);
437  free(footer);
438 
439 
440  /* Free the state object */
441  ShpLoaderDestroy(state);
442 
443  /* Free configuration variables */
444  if (config->schema)
445  free(config->schema);
446  if (config->table)
447  free(config->table);
448  free(config);
449 
450  return 0;
451 }
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:72
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:172
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