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