PostGIS  3.3.9dev-r@@SVN_REVISION@@
shp2pgsql-core.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright (C) 2008 OpenGeo.org
7  * Copyright (C) 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@cleverelephant.ca>
13  *
14  **********************************************************************/
15 
16 #include "../postgis_config.h"
17 
18 #include "shp2pgsql-core.h"
19 #include "../liblwgeom/liblwgeom.h"
20 #include "../liblwgeom/lwgeom_log.h" /* for LWDEBUG macros */
21 
22 
23 
24 /* Internal ring/point structures */
25 typedef struct struct_point
26 {
27  double x, y, z, m;
29 
30 typedef struct struct_ring
31 {
32  Point *list; /* list of points */
33  struct struct_ring *next;
34  int n; /* number of points in list */
35  unsigned int linked; /* number of "next" rings */
36 } Ring;
37 
38 
39 /*
40  * Internal functions
41  */
42 
43 #define UTF8_GOOD_RESULT 0
44 #define UTF8_BAD_RESULT 1
45 #define UTF8_NO_RESULT 2
46 
47 char *escape_copy_string(char *str);
48 char *escape_insert_string(char *str);
49 
50 int GeneratePointGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry, int force_multi);
51 int GenerateLineStringGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry);
52 int PIP(Point P, Point *V, int n);
53 int FindPolygons(SHPObject *obj, Ring ***Out);
54 void ReleasePolygons(Ring **polys, int npolys);
55 int GeneratePolygonGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry);
56 
57 
58 /* Return allocated string containing UTF8 string converted from encoding fromcode */
59 static int
60 utf8(const char *fromcode, char *inputbuf, char **outputbuf)
61 {
62  iconv_t cd;
63  char *outputptr;
64  size_t outbytesleft;
65  size_t inbytesleft;
66 
67  inbytesleft = strlen(inputbuf);
68 
69  cd = iconv_open("UTF-8", fromcode);
70  if ( cd == ((iconv_t)(-1)) )
71  return UTF8_NO_RESULT;
72 
73  outbytesleft = inbytesleft * 3 + 1; /* UTF8 string can be 3 times larger */
74  /* then local string */
75  *outputbuf = (char *)malloc(outbytesleft);
76  if (!*outputbuf)
77  return UTF8_NO_RESULT;
78 
79  memset(*outputbuf, 0, outbytesleft);
80  outputptr = *outputbuf;
81 
82  /* Does this string convert cleanly? */
83  if ( iconv(cd, &inputbuf, &inbytesleft, &outputptr, &outbytesleft) == (size_t)-1 )
84  {
85 #ifdef HAVE_ICONVCTL
86  int on = 1;
87  /* No. Try to convert it while transliterating. */
88  iconvctl(cd, ICONV_SET_TRANSLITERATE, &on);
89  if ( iconv(cd, &inputbuf, &inbytesleft, &outputptr, &outbytesleft) == -1 )
90  {
91  /* No. Try to convert it while discarding errors. */
92  iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &on);
93  if ( iconv(cd, &inputbuf, &inbytesleft, &outputptr, &outbytesleft) == -1 )
94  {
95  /* Still no. Throw away the buffer and return. */
96  free(*outputbuf);
97  iconv_close(cd);
98  return UTF8_NO_RESULT;
99  }
100  }
101  iconv_close(cd);
102  return UTF8_BAD_RESULT;
103 #else
104  free(*outputbuf);
105  iconv_close(cd);
106  return UTF8_NO_RESULT;
107 #endif
108  }
109  /* Return a good result, converted string is in buffer. */
110  iconv_close(cd);
111  return UTF8_GOOD_RESULT;
112 }
113 
118 char *
120 {
121  /*
122  * Escape the following characters by adding a preceding backslash
123  * tab, backslash, cr, lf
124  *
125  * 1. find # of escaped characters
126  * 2. make new string
127  *
128  */
129 
130  char *result;
131  char *ptr, *optr;
132  int toescape = 0;
133  size_t size;
134 
135  ptr = str;
136 
137  /* Count how many characters we need to escape so we know the size of the string we need to return */
138  while (*ptr)
139  {
140  if (*ptr == '\t' || *ptr == '\\' || *ptr == '\n' || *ptr == '\r')
141  toescape++;
142 
143  ptr++;
144  }
145 
146  /* If we don't have to escape anything, simply return the input pointer */
147  if (toescape == 0)
148  return str;
149 
150  size = ptr - str + toescape + 1;
151  result = calloc(1, size);
152  optr = result;
153  ptr = str;
154 
155  while (*ptr)
156  {
157  if ( *ptr == '\t' || *ptr == '\\' || *ptr == '\n' || *ptr == '\r' )
158  *optr++ = '\\';
159 
160  *optr++ = *ptr++;
161  }
162 
163  *optr = '\0';
164 
165  return result;
166 }
167 
168 
173 char *
175 {
176  /*
177  * Escape single quotes by adding a preceding single quote
178  *
179  * 1. find # of characters
180  * 2. make new string
181  */
182 
183  char *result;
184  char *ptr, *optr;
185  int toescape = 0;
186  size_t size;
187 
188  ptr = str;
189 
190  /* Count how many characters we need to escape so we know the size of the string we need to return */
191  while (*ptr)
192  {
193  if (*ptr == '\'')
194  toescape++;
195 
196  ptr++;
197  }
198 
199  /* If we don't have to escape anything, simply return the input pointer */
200  if (toescape == 0)
201  return str;
202 
203  size = ptr - str + toescape + 1;
204  result = calloc(1, size);
205  optr = result;
206  ptr = str;
207 
208  while (*ptr)
209  {
210  if (*ptr == '\'')
211  *optr++='\'';
212 
213  *optr++ = *ptr++;
214  }
215 
216  *optr='\0';
217 
218  return result;
219 }
220 
221 
226 int
227 GeneratePointGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry, int force_multi)
228 {
229  LWGEOM **lwmultipoints;
230  LWGEOM *lwgeom = NULL;
231 
232  POINT4D point4d;
233 
234  int dims = 0;
235  int u;
236 
237  char *mem;
238  size_t mem_length;
239 
240  FLAGS_SET_Z(dims, state->has_z);
241  FLAGS_SET_M(dims, state->has_m);
242 
243  /* POINT EMPTY encoded as POINT(NaN NaN) */
244  if (obj->nVertices == 1 && isnan(obj->padfX[0]) && isnan(obj->padfY[0]))
245  {
246  lwgeom = lwpoint_as_lwgeom(lwpoint_construct_empty(state->from_srid, state->has_z, state->has_m));
247  }
248  /* Not empty */
249  else
250  {
251  /* Allocate memory for our array of LWPOINTs and our dynptarrays */
252  lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices);
253 
254  /* We need an array of pointers to each of our sub-geometries */
255  for (u = 0; u < obj->nVertices; u++)
256  {
257  /* Create a ptarray containing a single point */
258  POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, 1);
259 
260  /* Generate the point */
261  point4d.x = obj->padfX[u];
262  point4d.y = obj->padfY[u];
263 
264  if (state->has_z)
265  point4d.z = obj->padfZ[u];
266  if (state->has_m)
267  point4d.m = obj->padfM[u];
268 
269  /* Add in the point! */
270  ptarray_append_point(pa, &point4d, LW_TRUE);
271 
272  /* Generate the LWPOINT */
273  lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(state->from_srid, NULL, pa));
274  }
275 
276  /* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT
277  rather than a POINT */
278  if ((obj->nVertices > 1) || force_multi)
279  {
280  lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOINTTYPE, state->from_srid, NULL, obj->nVertices, lwmultipoints));
281  }
282  else
283  {
284  lwgeom = lwmultipoints[0];
285  lwfree(lwmultipoints);
286  }
287  }
288 
289  if (state->config->use_wkt)
290  {
291  mem = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, WKT_PRECISION, &mem_length);
292  }
293  else
294  {
295  mem = lwgeom_to_hexwkb_buffer(lwgeom, WKB_EXTENDED);
296  }
297 
298  if ( !mem )
299  {
300  snprintf(state->message, SHPLOADERMSGLEN, "unable to write geometry");
301  return SHPLOADERERR;
302  }
303 
304  /* Free all of the allocated items */
305  lwgeom_free(lwgeom);
306 
307  /* Return the string - everything ok */
308  *geometry = mem;
309 
310  return SHPLOADEROK;
311 }
312 
313 
317 int
319 {
320 
321  LWGEOM **lwmultilinestrings;
322  LWGEOM *lwgeom = NULL;
323  POINT4D point4d;
324  int dims = 0;
325  int u, v, start_vertex, end_vertex;
326  char *mem;
327  size_t mem_length;
328 
329 
330  FLAGS_SET_Z(dims, state->has_z);
331  FLAGS_SET_M(dims, state->has_m);
332 
333  if (state->config->simple_geometries == 1 && obj->nParts > 1)
334  {
335  snprintf(state->message, SHPLOADERMSGLEN, _("We have a Multilinestring with %d parts, can't use -S switch!"), obj->nParts);
336 
337  return SHPLOADERERR;
338  }
339 
340  /* Allocate memory for our array of LWLINEs and our dynptarrays */
341  lwmultilinestrings = malloc(sizeof(LWPOINT *) * obj->nParts);
342 
343  /* We need an array of pointers to each of our sub-geometries */
344  for (u = 0; u < obj->nParts; u++)
345  {
346  /* Create a ptarray containing the line points */
347  POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, obj->nParts);
348 
349  /* Set the start/end vertices depending upon whether this is
350  a MULTILINESTRING or not */
351  if ( u == obj->nParts-1 )
352  end_vertex = obj->nVertices;
353  else
354  end_vertex = obj->panPartStart[u + 1];
355 
356  start_vertex = obj->panPartStart[u];
357 
358  for (v = start_vertex; v < end_vertex; v++)
359  {
360  /* Generate the point */
361  point4d.x = obj->padfX[v];
362  point4d.y = obj->padfY[v];
363 
364  if (state->has_z)
365  point4d.z = obj->padfZ[v];
366  if (state->has_m)
367  point4d.m = obj->padfM[v];
368 
369  ptarray_append_point(pa, &point4d, LW_FALSE);
370  }
371 
372  /* Generate the LWLINE */
373  lwmultilinestrings[u] = lwline_as_lwgeom(lwline_construct(state->from_srid, NULL, pa));
374  }
375 
376  /* If using MULTILINESTRINGs then generate the serialized collection, otherwise just a single LINESTRING */
377  if (state->config->simple_geometries == 0)
378  {
379  lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTILINETYPE, state->from_srid, NULL, obj->nParts, lwmultilinestrings));
380  }
381  else
382  {
383  lwgeom = lwmultilinestrings[0];
384  lwfree(lwmultilinestrings);
385  }
386 
387  if (!state->config->use_wkt)
388  mem = lwgeom_to_hexwkb_buffer(lwgeom, WKB_EXTENDED);
389  else
390  mem = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, WKT_PRECISION, &mem_length);
391 
392  if ( !mem )
393  {
394  snprintf(state->message, SHPLOADERMSGLEN, "unable to write geometry");
395  return SHPLOADERERR;
396  }
397 
398  /* Free all of the allocated items */
399  lwgeom_free(lwgeom);
400 
401  /* Return the string - everything ok */
402  *geometry = mem;
403 
404  return SHPLOADEROK;
405 }
406 
407 
414 int
415 PIP(Point P, Point *V, int n)
416 {
417  int cn = 0; /* the crossing number counter */
418  int i;
419 
420  /* loop through all edges of the polygon */
421  for (i = 0; i < n-1; i++) /* edge from V[i] to V[i+1] */
422  {
423  if (((V[i].y <= P.y) && (V[i + 1].y > P.y)) /* an upward crossing */
424  || ((V[i].y > P.y) && (V[i + 1].y <= P.y))) /* a downward crossing */
425  {
426  double vt = (float)(P.y - V[i].y) / (V[i + 1].y - V[i].y);
427  if (P.x < V[i].x + vt * (V[i + 1].x - V[i].x)) /* P.x < intersect */
428  ++cn; /* a valid crossing of y=P.y right of P.x */
429  }
430  }
431 
432  return (cn&1); /* 0 if even (out), and 1 if odd (in) */
433 }
434 
435 
436 int
438 {
439  Ring **Outer; /* Pointers to Outer rings */
440  int out_index=0; /* Count of Outer rings */
441  Ring **Inner; /* Pointers to Inner rings */
442  int in_index=0; /* Count of Inner rings */
443  int pi; /* part index */
444 
445 #if POSTGIS_DEBUG_LEVEL > 0
446  static int call = -1;
447  call++;
448 #endif
449 
450  LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts);
451 
452  /* Allocate initial memory */
453  Outer = (Ring **)malloc(sizeof(Ring *) * obj->nParts);
454  Inner = (Ring **)malloc(sizeof(Ring *) * obj->nParts);
455 
456  /* Iterate over rings dividing in Outers and Inners */
457  for (pi=0; pi < obj->nParts; pi++)
458  {
459  int vi; /* vertex index */
460  int vs; /* start index */
461  int ve; /* end index */
462  int nv; /* number of vertex */
463  double area = 0.0;
464  Ring *ring;
465 
466  /* Set start and end vertexes */
467  if (pi == obj->nParts - 1)
468  ve = obj->nVertices;
469  else
470  ve = obj->panPartStart[pi + 1];
471 
472  vs = obj->panPartStart[pi];
473 
474  /* Compute number of vertexes */
475  nv = ve - vs;
476 
477  /* Allocate memory for a ring */
478  ring = (Ring *)malloc(sizeof(Ring));
479  ring->list = (Point *)malloc(sizeof(Point) * nv);
480  ring->n = nv;
481  ring->next = NULL;
482  ring->linked = 0;
483 
484  /* Iterate over ring vertexes */
485  for (vi = vs; vi < ve; vi++)
486  {
487  int vn = vi+1; /* next vertex for area */
488  if (vn == ve)
489  vn = vs;
490 
491  ring->list[vi - vs].x = obj->padfX[vi];
492  ring->list[vi - vs].y = obj->padfY[vi];
493  ring->list[vi - vs].z = obj->padfZ[vi];
494  ring->list[vi - vs].m = obj->padfM[vi];
495 
496  area += (obj->padfX[vi] * obj->padfY[vn]) -
497  (obj->padfY[vi] * obj->padfX[vn]);
498  }
499 
500  /* Close the ring with first vertex */
501  /*ring->list[vi].x = obj->padfX[vs]; */
502  /*ring->list[vi].y = obj->padfY[vs]; */
503  /*ring->list[vi].z = obj->padfZ[vs]; */
504  /*ring->list[vi].m = obj->padfM[vs]; */
505 
506  /* Clockwise (or single-part). It's an Outer Ring ! */
507  if (area < 0.0 || obj->nParts == 1)
508  {
509  Outer[out_index] = ring;
510  out_index++;
511  }
512  else
513  {
514  /* Counterclockwise. It's an Inner Ring ! */
515  Inner[in_index] = ring;
516  in_index++;
517  }
518  }
519 
520  LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index);
521 
522  /* Put the inner rings into the list of the outer rings */
523  /* of which they are within */
524  for (pi = 0; pi < in_index; pi++)
525  {
526  Point pt, pt2;
527  int i;
528  Ring *inner = Inner[pi], *outer = NULL;
529 
530  pt.x = inner->list[0].x;
531  pt.y = inner->list[0].y;
532 
533  pt2.x = inner->list[1].x;
534  pt2.y = inner->list[1].y;
535 
536  /*
537  * If we assume that the case of the "big polygon w/o hole
538  * containing little polygon w/ hold" is ordered so that the
539  * big polygon comes first, then checking the list in reverse
540  * will assign the little polygon's hole to the little polygon
541  * w/o a lot of extra fancy containment logic here
542  */
543  for (i = out_index - 1; i >= 0; i--)
544  {
545  int in;
546 
547  in = PIP(pt, Outer[i]->list, Outer[i]->n);
548  if ( in || PIP(pt2, Outer[i]->list, Outer[i]->n) )
549  {
550  outer = Outer[i];
551  break;
552  }
553  }
554 
555  if (outer)
556  {
557  outer->linked++;
558  while (outer->next)
559  outer = outer->next;
560 
561  outer->next = inner;
562  }
563  else
564  {
565  /* The ring wasn't within any outer rings, */
566  /* assume it is a new outer ring. */
567  LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi);
568 
569  Outer[out_index] = inner;
570  out_index++;
571  }
572  }
573 
574  *Out = Outer;
575  /*
576  * Only free the containing Inner array, not the ring elements, because
577  * the rings are now owned by the linked lists in the Outer array elements.
578  */
579  free(Inner);
580 
581  return out_index;
582 }
583 
584 
585 void
586 ReleasePolygons(Ring **polys, int npolys)
587 {
588  int pi;
589 
590  /* Release all memory */
591  for (pi = 0; pi < npolys; pi++)
592  {
593  Ring *Poly, *temp;
594  Poly = polys[pi];
595  while (Poly != NULL)
596  {
597  temp = Poly;
598  Poly = Poly->next;
599  free(temp->list);
600  free(temp);
601  }
602  }
603 
604  free(polys);
605 }
606 
607 
615 int
616 GeneratePolygonGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry)
617 {
618  Ring **Outer;
619  int polygon_total, ring_total;
620  int pi, vi; /* part index and vertex index */
621 
622  LWGEOM **lwpolygons;
623  LWGEOM *lwgeom;
624 
625  POINT4D point4d;
626 
627  int dims = 0;
628 
629  char *mem;
630  size_t mem_length;
631 
632  FLAGS_SET_Z(dims, state->has_z);
633  FLAGS_SET_M(dims, state->has_m);
634 
635  polygon_total = FindPolygons(obj, &Outer);
636 
637  if (state->config->simple_geometries == 1 && polygon_total != 1) /* We write Non-MULTI geometries, but have several parts: */
638  {
639  snprintf(state->message, SHPLOADERMSGLEN, _("We have a Multipolygon with %d parts, can't use -S switch!"), polygon_total);
640 
641  return SHPLOADERERR;
642  }
643 
644  /* Allocate memory for our array of LWPOLYs */
645  lwpolygons = malloc(sizeof(LWPOLY *) * polygon_total);
646 
647  /* Cycle through each individual polygon */
648  for (pi = 0; pi < polygon_total; pi++)
649  {
650  LWPOLY *lwpoly = lwpoly_construct_empty(state->from_srid, state->has_z, state->has_m);
651 
652  Ring *polyring;
653  int ring_index = 0;
654 
655  /* Firstly count through the total number of rings in this polygon */
656  ring_total = 0;
657  polyring = Outer[pi];
658  while (polyring)
659  {
660  ring_total = ring_total + 1;
661  polyring = polyring->next;
662  }
663 
664  /* Cycle through each ring within the polygon, starting with the outer */
665  polyring = Outer[pi];
666 
667  while (polyring)
668  {
669  /* Create a POINTARRAY containing the points making up the ring */
670  POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, polyring->n);
671 
672  for (vi = 0; vi < polyring->n; vi++)
673  {
674  /* Build up a point array of all the points in this ring */
675  point4d.x = polyring->list[vi].x;
676  point4d.y = polyring->list[vi].y;
677 
678  if (state->has_z)
679  point4d.z = polyring->list[vi].z;
680  if (state->has_m)
681  point4d.m = polyring->list[vi].m;
682 
683  ptarray_append_point(pa, &point4d, LW_TRUE);
684  }
685 
686  /* Copy the POINTARRAY pointer so we can use the LWPOLY constructor */
687  lwpoly_add_ring(lwpoly, pa);
688 
689  polyring = polyring->next;
690  ring_index = ring_index + 1;
691  }
692 
693  /* Generate the LWGEOM */
694  lwpolygons[pi] = lwpoly_as_lwgeom(lwpoly);
695  }
696 
697  /* If using MULTIPOLYGONS then generate the serialized collection, otherwise just a single POLYGON */
698  if (state->config->simple_geometries == 0)
699  {
700  lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOLYGONTYPE, state->from_srid, NULL, polygon_total, lwpolygons));
701  }
702  else
703  {
704  lwgeom = lwpolygons[0];
705  lwfree(lwpolygons);
706  }
707 
708  if (!state->config->use_wkt)
709  mem = lwgeom_to_hexwkb_buffer(lwgeom, WKB_EXTENDED);
710  else
711  mem = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, WKT_PRECISION, &mem_length);
712 
713  if ( !mem )
714  {
715  /* Free the linked list of rings */
716  ReleasePolygons(Outer, polygon_total);
717 
718  snprintf(state->message, SHPLOADERMSGLEN, "unable to write geometry");
719  return SHPLOADERERR;
720  }
721 
722  /* Free all of the allocated items */
723  lwgeom_free(lwgeom);
724 
725  /* Free the linked list of rings */
726  ReleasePolygons(Outer, polygon_total);
727 
728  /* Return the string - everything ok */
729  *geometry = mem;
730 
731  return SHPLOADEROK;
732 }
733 
734 
735 /*
736  * External functions (defined in shp2pgsql-core.h)
737  */
738 
739 
740 /* Convert the string to lower case */
741 void
742 strtolower(char *s)
743 {
744  size_t j;
745 
746  for (j = 0; j < strlen(s); j++)
747  s[j] = tolower(s[j]);
748 }
749 
750 
751 /* Default configuration settings */
752 void
754 {
755  config->opt = 'c';
756  config->table = NULL;
757  config->schema = NULL;
758  config->geo_col = NULL;
759  config->shp_file = NULL;
760  config->dump_format = 0;
761  config->simple_geometries = 0;
762  config->geography = 0;
763  config->quoteidentifiers = 0;
764  config->forceint4 = 0;
765  config->createindex = 0;
766  config->analyze = 1;
767  config->readshape = 1;
769  config->encoding = strdup(ENCODING_DEFAULT);
771  config->sr_id = SRID_UNKNOWN;
772  config->shp_sr_id = SRID_UNKNOWN;
773  config->use_wkt = 0;
774  config->tablespace = NULL;
775  config->idxtablespace = NULL;
776  config->usetransaction = 1;
777  config->column_map_filename = NULL;
778 }
779 
780 /* Create a new shapefile state object */
783 {
784  SHPLOADERSTATE *state;
785 
786  /* Create a new state object and assign the config to it */
787  state = malloc(sizeof(SHPLOADERSTATE));
788  state->config = config;
789 
790  /* Set any state defaults */
791  state->hSHPHandle = NULL;
792  state->hDBFHandle = NULL;
793  state->has_z = 0;
794  state->has_m = 0;
795  state->types = NULL;
796  state->widths = NULL;
797  state->precisions = NULL;
798  state->col_names = NULL;
799  state->field_names = NULL;
800  state->num_fields = 0;
801  state->pgfieldtypes = NULL;
802 
803  state->from_srid = config->shp_sr_id;
804  state->to_srid = config->sr_id;
805 
806  /* If only one has a valid SRID, use it for both. */
807  if (state->to_srid == SRID_UNKNOWN)
808  {
809  if (config->geography)
810  {
811  state->to_srid = 4326;
812  }
813  else
814  {
815  state->to_srid = state->from_srid;
816  }
817  }
818 
819  if (state->from_srid == SRID_UNKNOWN)
820  {
821  state->from_srid = state->to_srid;
822  }
823 
824  /* If the geo col name is not set, use one of the defaults. */
825  state->geo_col = config->geo_col;
826 
827  if (!state->geo_col)
828  {
830  }
831 
832  colmap_init(&state->column_map);
833 
834  return state;
835 }
836 
837 
838 /* Open the shapefile and extract the relevant field information */
839 int
841 {
842  SHPObject *obj = NULL;
843  int ret = SHPLOADEROK;
844  char name[MAXFIELDNAMELEN];
845  char name2[MAXFIELDNAMELEN];
847  char *utf8str;
848 
849  /* If we are reading the entire shapefile, open it */
850  if (state->config->readshape == 1)
851  {
852  state->hSHPHandle = SHPOpen(state->config->shp_file, "rb");
853 
854  if (state->hSHPHandle == NULL)
855  {
856  snprintf(state->message, SHPLOADERMSGLEN, _("%s: shape (.shp) or index files (.shx) can not be opened, will just import attribute data."), state->config->shp_file);
857  state->config->readshape = 0;
858 
859  ret = SHPLOADERWARN;
860  }
861  }
862 
863  /* Open the DBF (attributes) file */
864  state->hDBFHandle = DBFOpen(state->config->shp_file, "rb");
865  if ((state->hSHPHandle == NULL && state->config->readshape == 1) || state->hDBFHandle == NULL)
866  {
867  snprintf(state->message, SHPLOADERMSGLEN, _("%s: dbf file (.dbf) can not be opened."), state->config->shp_file);
868 
869  return SHPLOADERERR;
870  }
871 
872 
873  /* Open the column map if one was specified */
874  if (state->config->column_map_filename)
875  {
876  ret = colmap_read(state->config->column_map_filename,
877  &state->column_map, state->message, SHPLOADERMSGLEN);
878  if (!ret) return SHPLOADERERR;
879  }
880 
881  /* User hasn't altered the default encoding preference... */
882  if ( strcmp(state->config->encoding, ENCODING_DEFAULT) == 0 )
883  {
884  /* But the file has a code page entry... */
885  if ( state->hDBFHandle->pszCodePage )
886  {
887  /* And we figured out what iconv encoding it maps to, so use it! */
888  char *newencoding = NULL;
889  if ( (newencoding = codepage2encoding(state->hDBFHandle->pszCodePage)) )
890  {
891  lwfree(state->config->encoding);
892  state->config->encoding = newencoding;
893  }
894  }
895  }
896 
897  /* If reading the whole shapefile (not just attributes)... */
898  if (state->config->readshape == 1)
899  {
900  SHPGetInfo(state->hSHPHandle, &state->num_entities, &state->shpfiletype, NULL, NULL);
901 
902  /* If null_policy is set to abort, check for NULLs */
903  if (state->config->null_policy == POLICY_NULL_ABORT)
904  {
905  /* If we abort on null items, scan the entire file for NULLs */
906  for (int j = 0; j < state->num_entities; j++)
907  {
908  obj = SHPReadObject(state->hSHPHandle, j);
909 
910  if (!obj)
911  {
912  snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), j);
913  return SHPLOADERERR;
914  }
915 
916  if (obj->nVertices == 0)
917  {
918  snprintf(state->message, SHPLOADERMSGLEN, _("Empty geometries found, aborted.)"));
919  return SHPLOADERERR;
920  }
921 
922  SHPDestroyObject(obj);
923  }
924  }
925 
926  /* Check the shapefile type */
927  int geomtype = 0;
928  switch (state->shpfiletype)
929  {
930  case SHPT_POINT:
931  /* Point */
932  state->pgtype = "POINT";
933  geomtype = POINTTYPE;
934  state->pgdims = 2;
935  break;
936 
937  case SHPT_ARC:
938  /* PolyLine */
939  state->pgtype = "MULTILINESTRING";
940  geomtype = MULTILINETYPE ;
941  state->pgdims = 2;
942  break;
943 
944  case SHPT_POLYGON:
945  /* Polygon */
946  state->pgtype = "MULTIPOLYGON";
947  geomtype = MULTIPOLYGONTYPE;
948  state->pgdims = 2;
949  break;
950 
951  case SHPT_MULTIPOINT:
952  /* MultiPoint */
953  state->pgtype = "MULTIPOINT";
954  geomtype = MULTIPOINTTYPE;
955  state->pgdims = 2;
956  break;
957 
958  case SHPT_POINTM:
959  /* PointM */
960  geomtype = POINTTYPE;
961  state->has_m = 1;
962  state->pgtype = "POINTM";
963  state->pgdims = 3;
964  break;
965 
966  case SHPT_ARCM:
967  /* PolyLineM */
968  geomtype = MULTILINETYPE;
969  state->has_m = 1;
970  state->pgtype = "MULTILINESTRINGM";
971  state->pgdims = 3;
972  break;
973 
974  case SHPT_POLYGONM:
975  /* PolygonM */
976  geomtype = MULTIPOLYGONTYPE;
977  state->has_m = 1;
978  state->pgtype = "MULTIPOLYGONM";
979  state->pgdims = 3;
980  break;
981 
982  case SHPT_MULTIPOINTM:
983  /* MultiPointM */
984  geomtype = MULTIPOINTTYPE;
985  state->has_m = 1;
986  state->pgtype = "MULTIPOINTM";
987  state->pgdims = 3;
988  break;
989 
990  case SHPT_POINTZ:
991  /* PointZ */
992  geomtype = POINTTYPE;
993  state->has_m = 1;
994  state->has_z = 1;
995  state->pgtype = "POINT";
996  state->pgdims = 4;
997  break;
998 
999  case SHPT_ARCZ:
1000  /* PolyLineZ */
1001  state->pgtype = "MULTILINESTRING";
1002  geomtype = MULTILINETYPE;
1003  state->has_z = 1;
1004  state->has_m = 1;
1005  state->pgdims = 4;
1006  break;
1007 
1008  case SHPT_POLYGONZ:
1009  /* MultiPolygonZ */
1010  state->pgtype = "MULTIPOLYGON";
1011  geomtype = MULTIPOLYGONTYPE;
1012  state->has_z = 1;
1013  state->has_m = 1;
1014  state->pgdims = 4;
1015  break;
1016 
1017  case SHPT_MULTIPOINTZ:
1018  /* MultiPointZ */
1019  state->pgtype = "MULTIPOINT";
1020  geomtype = MULTIPOINTTYPE;
1021  state->has_z = 1;
1022  state->has_m = 1;
1023  state->pgdims = 4;
1024  break;
1025 
1026  default:
1027  state->pgtype = "GEOMETRY";
1028  geomtype = COLLECTIONTYPE;
1029  state->has_z = 1;
1030  state->has_m = 1;
1031  state->pgdims = 4;
1032 
1033  snprintf(state->message, SHPLOADERMSGLEN, _("Unknown geometry type: %d\n"), state->shpfiletype);
1034  return SHPLOADERERR;
1035 
1036  break;
1037  }
1038 
1039  /* Force Z/M-handling if configured to do so */
1040  switch(state->config->force_output)
1041  {
1042  case FORCE_OUTPUT_2D:
1043  state->has_z = 0;
1044  state->has_m = 0;
1045  state->pgdims = 2;
1046  break;
1047 
1048  case FORCE_OUTPUT_3DZ:
1049  state->has_z = 1;
1050  state->has_m = 0;
1051  state->pgdims = 3;
1052  break;
1053 
1054  case FORCE_OUTPUT_3DM:
1055  state->has_z = 0;
1056  state->has_m = 1;
1057  state->pgdims = 3;
1058  break;
1059 
1060  case FORCE_OUTPUT_4D:
1061  state->has_z = 1;
1062  state->has_m = 1;
1063  state->pgdims = 4;
1064  break;
1065  default:
1066  /* Simply use the auto-detected values above */
1067  break;
1068  }
1069 
1070  /* If in simple geometry mode, alter names for CREATE TABLE by skipping MULTI */
1071  if (state->config->simple_geometries)
1072  {
1073  if ((geomtype == MULTIPOLYGONTYPE) || (geomtype == MULTILINETYPE) || (geomtype == MULTIPOINTTYPE))
1074  {
1075  /* Chop off the "MULTI" from the string. */
1076  state->pgtype += 5;
1077  }
1078  }
1079 
1080  }
1081  else
1082  {
1083  /* Otherwise just count the number of records in the DBF */
1084  state->num_entities = DBFGetRecordCount(state->hDBFHandle);
1085  }
1086 
1087 
1088  /* Get the field information from the DBF */
1089  state->num_fields = DBFGetFieldCount(state->hDBFHandle);
1090 
1091  state->num_records = DBFGetRecordCount(state->hDBFHandle);
1092 
1093  /* Allocate storage for field information */
1094  state->field_names = malloc(state->num_fields * sizeof(char*));
1095  state->types = (DBFFieldType *)malloc(state->num_fields * sizeof(int));
1096  state->widths = malloc(state->num_fields * sizeof(int));
1097  state->precisions = malloc(state->num_fields * sizeof(int));
1098  state->pgfieldtypes = malloc(state->num_fields * sizeof(char *));
1099  state->col_names = malloc((state->num_fields + 2) * sizeof(char) * MAXFIELDNAMELEN);
1100 
1101  strcpy(state->col_names, "" );
1102  /* Generate a string of comma separated column names of the form "col1, col2 ... colN" for the SQL
1103  insertion string */
1104 
1105  for (int j = 0; j < state->num_fields; j++)
1106  {
1107  int field_precision = 0, field_width = 0;
1108  type = DBFGetFieldInfo(state->hDBFHandle, j, name, &field_width, &field_precision);
1109 
1110  state->types[j] = type;
1111  state->widths[j] = field_width;
1112  state->precisions[j] = field_precision;
1113 /* fprintf(stderr, "XXX %s width:%d prec:%d\n", name, field_width, field_precision); */
1114 
1115  if (state->config->encoding)
1116  {
1117  char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.gnu.org/software/libiconv/.");
1118 
1119  int rv = utf8(state->config->encoding, name, &utf8str);
1120 
1121  if (rv != UTF8_GOOD_RESULT)
1122  {
1123  if ( rv == UTF8_BAD_RESULT )
1124  snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert field name \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg);
1125  else if ( rv == UTF8_NO_RESULT )
1126  snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert field name to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg);
1127  else
1128  snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()"));
1129 
1130  if ( rv == UTF8_BAD_RESULT )
1131  free(utf8str);
1132 
1133  return SHPLOADERERR;
1134  }
1135 
1136  strncpy(name, utf8str, MAXFIELDNAMELEN);
1137  name[MAXFIELDNAMELEN-1] = '\0';
1138  free(utf8str);
1139  }
1140 
1141  /* If a column map file has been passed in, use this to create the postgresql field name from
1142  the dbf column name */
1143  {
1144  const char *mapped = colmap_pg_by_dbf(&state->column_map, name);
1145  if (mapped)
1146  {
1147  strncpy(name, mapped, MAXFIELDNAMELEN);
1148  name[MAXFIELDNAMELEN-1] = '\0';
1149  }
1150  }
1151 
1152  /*
1153  * Make field names lowercase unless asked to
1154  * keep identifiers case.
1155  */
1156  if (!state->config->quoteidentifiers)
1157  strtolower(name);
1158 
1159  /*
1160  * Escape names starting with the
1161  * escape char (_), those named 'gid'
1162  * or after pgsql reserved attribute names
1163  */
1164  if (name[0] == '_' ||
1165  ! strcmp(name, "gid") || ! strcmp(name, "tableoid") ||
1166  ! strcmp(name, "cmin") ||
1167  ! strcmp(name, "cmax") ||
1168  ! strcmp(name, "xmin") ||
1169  ! strcmp(name, "xmax") ||
1170  ! strcmp(name, "primary") ||
1171  ! strcmp(name, "oid") || ! strcmp(name, "ctid"))
1172  {
1173  size_t len = strlen(name);
1174  if (len > (MAXFIELDNAMELEN - 2))
1175  len = MAXFIELDNAMELEN - 2;
1176  strncpy(name2 + 2, name, len);
1177  name2[MAXFIELDNAMELEN-1] = '\0';
1178  name2[len + 2] = '\0';
1179  name2[0] = '_';
1180  name2[1] = '_';
1181  strcpy(name, name2);
1182  }
1183 
1184  /* Avoid duplicating field names */
1185  for (int z = 0; z < j; z++)
1186  {
1187  if (strcmp(state->field_names[z], name) == 0)
1188  {
1189  strncat(name, "__", MAXFIELDNAMELEN - 1);
1190  snprintf(name + strlen(name),
1191  MAXFIELDNAMELEN - 1 - strlen(name),
1192  "%i",
1193  j);
1194  break;
1195  }
1196  }
1197 
1198  state->field_names[j] = strdup(name);
1199 
1200  /* Now generate the PostgreSQL type name string and width based upon the shapefile type */
1201  switch (state->types[j])
1202  {
1203  case FTString:
1204  state->pgfieldtypes[j] = strdup("varchar");
1205  break;
1206 
1207  case FTDate:
1208  state->pgfieldtypes[j] = strdup("date");
1209  break;
1210 
1211  case FTInteger:
1212  /* Determine exact type based upon field width */
1213  if (state->config->forceint4 || (state->widths[j] >=5 && state->widths[j] < 10))
1214  {
1215  state->pgfieldtypes[j] = strdup("int4");
1216  }
1217  else if (state->widths[j] >=10 && state->widths[j] < 19)
1218  {
1219  state->pgfieldtypes[j] = strdup("int8");
1220  }
1221  else if (state->widths[j] < 5)
1222  {
1223  state->pgfieldtypes[j] = strdup("int2");
1224  }
1225  else
1226  {
1227  state->pgfieldtypes[j] = strdup("numeric");
1228  }
1229  break;
1230 
1231  case FTDouble:
1232  /* Determine exact type based upon field width */
1233  fprintf(stderr, "Field %s is an FTDouble with width %d and precision %d\n",
1234  state->field_names[j], state->widths[j], state->precisions[j]);
1235  if (state->widths[j] > 18)
1236  {
1237  state->pgfieldtypes[j] = strdup("numeric");
1238  }
1239  else
1240  {
1241  state->pgfieldtypes[j] = strdup("float8");
1242  }
1243  break;
1244 
1245  case FTLogical:
1246  state->pgfieldtypes[j] = strdup("boolean");
1247  break;
1248 
1249  default:
1250  snprintf(state->message, SHPLOADERMSGLEN, _("Invalid type %x in DBF file"), state->types[j]);
1251  return SHPLOADERERR;
1252  }
1253 
1254  strcat(state->col_names, "\"");
1255  strcat(state->col_names, name);
1256 
1257  if (state->config->readshape == 1 || j < (state->num_fields - 1))
1258  {
1259  /* Don't include last comma if its the last field and no geometry field will follow */
1260  strcat(state->col_names, "\",");
1261  }
1262  else
1263  {
1264  strcat(state->col_names, "\"");
1265  }
1266  }
1267 
1268  /* Append the geometry column if required */
1269  if (state->config->readshape == 1)
1270  strcat(state->col_names, state->geo_col);
1271 
1272  /* Return status */
1273  return ret;
1274 }
1275 
1276 /* Return a pointer to an allocated string containing the header for the specified loader state */
1277 int
1278 ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
1279 {
1280  stringbuffer_t *sb;
1281  char *ret;
1282  int j;
1283 
1284  /* Create the stringbuffer containing the header; we use this API as it's easier
1285  for handling string resizing during append */
1286  sb = stringbuffer_create();
1287  stringbuffer_clear(sb);
1288 
1289  /* Set the client encoding if required */
1290  if (state->config->encoding)
1291  {
1292  stringbuffer_aprintf(sb, "SET CLIENT_ENCODING TO UTF8;\n");
1293  }
1294 
1295  /* Use SQL-standard string escaping rather than PostgreSQL standard */
1296  stringbuffer_aprintf(sb, "SET STANDARD_CONFORMING_STRINGS TO ON;\n");
1297 
1298  /* Drop table if requested */
1299  if (state->config->opt == 'd')
1300  {
1312  if (state->config->schema)
1313  {
1314  if (state->config->readshape == 1 && (! state->config->geography) )
1315  {
1316  stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('%s','%s','%s');\n",
1317  state->config->schema, state->config->table, state->geo_col);
1318  }
1319 
1320  stringbuffer_aprintf(sb, "DROP TABLE IF EXISTS \"%s\".\"%s\";\n", state->config->schema,
1321  state->config->table);
1322  }
1323  else
1324  {
1325  if (state->config->readshape == 1 && (! state->config->geography) )
1326  {
1327  stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('','%s','%s');\n",
1328  state->config->table, state->geo_col);
1329  }
1330 
1331  stringbuffer_aprintf(sb, "DROP TABLE IF EXISTS \"%s\";\n", state->config->table);
1332  }
1333  }
1334 
1335  /* Start of transaction if we are using one */
1336  if (state->config->usetransaction)
1337  {
1338  stringbuffer_aprintf(sb, "BEGIN;\n");
1339  }
1340 
1341  /* If not in 'append' mode create the spatial table */
1342  if (state->config->opt != 'a')
1343  {
1344  /*
1345  * Create a table for inserting the shapes into with appropriate
1346  * columns and types
1347  */
1348  if (state->config->schema)
1349  {
1350  stringbuffer_aprintf(sb, "CREATE TABLE \"%s\".\"%s\" (gid serial",
1351  state->config->schema, state->config->table);
1352  }
1353  else
1354  {
1355  stringbuffer_aprintf(sb, "CREATE TABLE \"%s\" (gid serial", state->config->table);
1356  }
1357 
1358  /* Generate the field types based upon the shapefile information */
1359  for (j = 0; j < state->num_fields; j++)
1360  {
1361  stringbuffer_aprintf(sb, ",\n\"%s\" ", state->field_names[j]);
1362 
1363  /* First output the raw field type string */
1364  stringbuffer_aprintf(sb, "%s", state->pgfieldtypes[j]);
1365 
1366  /* Some types do have typmods */
1367  /* Apply width typmod for varchar if there is positive width **/
1368  if (!strcmp("varchar", state->pgfieldtypes[j]) && state->widths[j] > 0)
1369  stringbuffer_aprintf(sb, "(%d)", state->widths[j]);
1370 
1371  if (!strcmp("numeric", state->pgfieldtypes[j]))
1372  {
1373  /* Doubles we just allow PostgreSQL to auto-detect the size */
1374  if (state->types[j] != FTDouble)
1375  stringbuffer_aprintf(sb, "(%d,0)", state->widths[j]);
1376  }
1377  }
1378 
1379  /* Add the geography column directly to the table definition, we don't
1380  need to do an AddGeometryColumn() call. */
1381  if (state->config->readshape == 1 && state->config->geography)
1382  {
1383  char *dimschar;
1384 
1385  if (state->pgdims == 4)
1386  dimschar = "ZM";
1387  else
1388  dimschar = "";
1389 
1390  if (state->to_srid == SRID_UNKNOWN ){
1391  state->to_srid = 4326;
1392  }
1393 
1394  stringbuffer_aprintf(sb, ",\n\"%s\" geography(%s%s,%d)", state->geo_col, state->pgtype, dimschar, state->to_srid);
1395  }
1396  stringbuffer_aprintf(sb, ")");
1397 
1398  /* Tablespace is optional. */
1399  if (state->config->tablespace != NULL)
1400  {
1401  stringbuffer_aprintf(sb, " TABLESPACE \"%s\"", state->config->tablespace);
1402  }
1403  stringbuffer_aprintf(sb, ";\n");
1404 
1405  /* Create the primary key. This is done separately because the index for the PK needs
1406  * to be in the correct tablespace. */
1407 
1408  /* TODO: Currently PostgreSQL does not allow specifying an index to use for a PK (so you get
1409  * a default one called table_pkey) and it does not provide a way to create a PK index
1410  * in a specific tablespace. So as a hacky solution we create the PK, then move the
1411  * index to the correct tablespace. Eventually this should be:
1412  * CREATE INDEX table_pkey on table(gid) TABLESPACE tblspc;
1413  * ALTER TABLE table ADD PRIMARY KEY (gid) USING INDEX table_pkey;
1414  * A patch has apparently been submitted to PostgreSQL to enable this syntax, see this thread:
1415  * http://archives.postgresql.org/pgsql-hackers/2011-01/msg01405.php */
1416  stringbuffer_aprintf(sb, "ALTER TABLE ");
1417 
1418  /* Schema is optional, include if present. */
1419  if (state->config->schema)
1420  {
1421  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1422  }
1423  stringbuffer_aprintf(sb, "\"%s\" ADD PRIMARY KEY (gid);\n", state->config->table);
1424 
1425  /* Tablespace is optional for the index. */
1426  if (state->config->idxtablespace != NULL)
1427  {
1428  stringbuffer_aprintf(sb, "ALTER INDEX ");
1429  if (state->config->schema)
1430  {
1431  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1432  }
1433 
1434  /* WARNING: We're assuming the default "table_pkey" name for the primary
1435  * key index. PostgreSQL may use "table_pkey1" or similar in the
1436  * case of a name conflict, so you may need to edit the produced
1437  * SQL in this rare case. */
1438  stringbuffer_aprintf(sb, "\"%s_pkey\" SET TABLESPACE \"%s\";\n",
1439  state->config->table, state->config->idxtablespace);
1440  }
1441 
1442  /* Create the geometry column with an addgeometry call */
1443  if (state->config->readshape == 1 && (!state->config->geography))
1444  {
1445  /* If they didn't specify a target SRID, see if they specified a source SRID. */
1446  int32_t srid = state->to_srid;
1447  if (state->config->schema)
1448  {
1449  stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('%s','%s','%s','%d',",
1450  state->config->schema, state->config->table, state->geo_col, srid);
1451  }
1452  else
1453  {
1454  stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('','%s','%s','%d',",
1455  state->config->table, state->geo_col, srid);
1456  }
1457 
1458  stringbuffer_aprintf(sb, "'%s',%d);\n", state->pgtype, state->pgdims);
1459  }
1460  }
1461 
1465  if (state->config->dump_format && state->to_srid != state->from_srid){
1467  stringbuffer_aprintf(sb, "CREATE TEMP TABLE \"pgis_tmp_%s\" AS SELECT * FROM ", state->config->table);
1468  /* Schema is optional, include if present. */
1469  if (state->config->schema)
1470  {
1471  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1472  }
1473  stringbuffer_aprintf(sb, "\"%s\" WHERE false;\n", state->config->table, state->geo_col);
1475  stringbuffer_aprintf(sb, "ALTER TABLE \"pgis_tmp_%s\" ALTER COLUMN \"%s\" TYPE geometry USING ( (\"%s\"::geometry) ); \n", state->config->table, state->geo_col, state->geo_col);
1476  }
1477 
1478  /* Copy the string buffer into a new string, destroying the string buffer */
1479  ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1);
1480  strcpy(ret, (char *)stringbuffer_getstring(sb));
1482 
1483  *strheader = ret;
1484 
1485  return SHPLOADEROK;
1486 }
1487 
1488 
1489 /* Return an allocated string containing the copy statement for this state */
1490 int
1492 {
1493  //char *copystr;
1494  stringbuffer_t *sb;
1495  char *ret;
1496  sb = stringbuffer_create();
1497  stringbuffer_clear(sb);
1498 
1499 
1500  /* Allocate the string for the COPY statement */
1501  if (state->config->dump_format)
1502  {
1503  stringbuffer_aprintf(sb, "COPY ");
1504 
1505  if (state->to_srid != state->from_srid){
1507  stringbuffer_aprintf(sb, " \"pgis_tmp_%s\" (%s) FROM stdin;\n", state->config->table, state->col_names);
1508  }
1509  else {
1510  if (state->config->schema)
1511  {
1512  stringbuffer_aprintf(sb, " \"%s\".", state->config->schema);
1513  }
1514 
1515  stringbuffer_aprintf(sb, "\"%s\" (%s) FROM stdin;\n", state->config->table, state->col_names);
1516  }
1517 
1518  /* Copy the string buffer into a new string, destroying the string buffer */
1519  ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1);
1520  strcpy(ret, (char *)stringbuffer_getstring(sb));
1522 
1523  *strheader = ret;
1524  return SHPLOADEROK;
1525  }
1526  else
1527  {
1528  /* Flag an error as something has gone horribly wrong */
1529  snprintf(state->message, SHPLOADERMSGLEN, _("Internal error: attempt to generate a COPY statement for data that hasn't been requested in COPY format"));
1530 
1531  return SHPLOADERERR;
1532  }
1533 }
1534 
1535 
1536 /* Return a count of the number of entities in this shapefile */
1537 int
1539 {
1540  return state->num_entities;
1541 }
1542 
1543 
1544 /* Return an allocated string representation of a specified record item */
1545 int
1546 ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord)
1547 {
1548  SHPObject *obj = NULL;
1549  stringbuffer_t *sb;
1550  stringbuffer_t *sbwarn;
1551  char val[MAXVALUELEN];
1552  char *escval;
1553  char *geometry=NULL, *ret;
1554  char *utf8str;
1555  int res, i;
1556  int rv;
1557 
1558  /* Clear the stringbuffers */
1559  sbwarn = stringbuffer_create();
1560  stringbuffer_clear(sbwarn);
1561  sb = stringbuffer_create();
1562  stringbuffer_clear(sb);
1563 
1564  /* Skip deleted records */
1565  if (state->hDBFHandle && DBFIsRecordDeleted(state->hDBFHandle, item))
1566  {
1567  *strrecord = NULL;
1568  return SHPLOADERRECDELETED;
1569  }
1570 
1571  /* If we are reading the shapefile, open the specified record */
1572  if (state->config->readshape == 1)
1573  {
1574  obj = SHPReadObject(state->hSHPHandle, item);
1575  if (!obj)
1576  {
1577  snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), item);
1578  return SHPLOADERERR;
1579  }
1580 
1581  /* If we are set to skip NULLs, return a NULL record status */
1582  if (state->config->null_policy == POLICY_NULL_SKIP && obj->nVertices == 0 )
1583  {
1584  SHPDestroyObject(obj);
1585 
1586  *strrecord = NULL;
1587  return SHPLOADERRECISNULL;
1588  }
1589  }
1590 
1591  /* If not in dump format, generate the INSERT string */
1592  if (!state->config->dump_format)
1593  {
1594  if (state->config->schema)
1595  {
1596  stringbuffer_aprintf(sb, "INSERT INTO \"%s\".\"%s\" (%s) VALUES (", state->config->schema,
1597  state->config->table, state->col_names);
1598  }
1599  else
1600  {
1601  stringbuffer_aprintf(sb, "INSERT INTO \"%s\" (%s) VALUES (", state->config->table,
1602  state->col_names);
1603  }
1604  }
1605 
1606 
1607  /* Read all of the attributes from the DBF file for this item */
1608  for (i = 0; i < DBFGetFieldCount(state->hDBFHandle); i++)
1609  {
1610  /* Special case for NULL attributes */
1611  if (DBFIsAttributeNULL(state->hDBFHandle, item, i))
1612  {
1613  if (state->config->dump_format)
1614  stringbuffer_aprintf(sb, "\\N");
1615  else
1616  stringbuffer_aprintf(sb, "NULL");
1617  }
1618  else
1619  {
1620  /* Attribute NOT NULL */
1621  switch (state->types[i])
1622  {
1623  case FTInteger:
1624  case FTDouble:
1625  rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i));
1626  if (rv >= MAXVALUELEN || rv == -1)
1627  {
1628  stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i);
1629  val[MAXVALUELEN - 1] = '\0';
1630  }
1631 
1632  /* If the value is an empty string, change to 0 */
1633  if (val[0] == '\0')
1634  {
1635  val[0] = '0';
1636  val[1] = '\0';
1637  }
1638 
1639  /* If the value ends with just ".", remove the dot */
1640  if (val[strlen(val) - 1] == '.')
1641  val[strlen(val) - 1] = '\0';
1642  break;
1643 
1644  case FTString:
1645  case FTLogical:
1646  rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i));
1647  if (rv >= MAXVALUELEN || rv == -1)
1648  {
1649  stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i);
1650  val[MAXVALUELEN - 1] = '\0';
1651  }
1652  break;
1653 
1654  case FTDate:
1655  rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i));
1656  if (rv >= MAXVALUELEN || rv == -1)
1657  {
1658  stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i);
1659  val[MAXVALUELEN - 1] = '\0';
1660  }
1661  if (strlen(val) == 0)
1662  {
1663  if (state->config->dump_format)
1664  stringbuffer_aprintf(sb, "\\N");
1665  else
1666  stringbuffer_aprintf(sb, "NULL");
1667  goto done_cell;
1668  }
1669  break;
1670 
1671  default:
1672  snprintf(state->message, SHPLOADERMSGLEN, _("Error: field %d has invalid or unknown field type (%d)"), i, state->types[i]);
1673 
1674  /* clean up and return err */
1675  SHPDestroyObject(obj);
1676  stringbuffer_destroy(sbwarn);
1678  return SHPLOADERERR;
1679  }
1680 
1681  if (state->config->encoding)
1682  {
1683  char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html.");
1684 
1685  rv = utf8(state->config->encoding, val, &utf8str);
1686 
1687  if (rv != UTF8_GOOD_RESULT)
1688  {
1689  if ( rv == UTF8_BAD_RESULT )
1690  snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg);
1691  else if ( rv == UTF8_NO_RESULT )
1692  snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg);
1693  else
1694  snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()"));
1695 
1696  if ( rv == UTF8_BAD_RESULT )
1697  free(utf8str);
1698 
1699  /* clean up and return err */
1700  SHPDestroyObject(obj);
1701  stringbuffer_destroy(sbwarn);
1703  return SHPLOADERERR;
1704  }
1705  strncpy(val, utf8str, MAXVALUELEN);
1706  val[MAXVALUELEN-1] = '\0';
1707  free(utf8str);
1708 
1709  }
1710 
1711  /* Escape attribute correctly according to dump format */
1712  if (state->config->dump_format)
1713  {
1714  escval = escape_copy_string(val);
1715  stringbuffer_aprintf(sb, "%s", escval);
1716  }
1717  else
1718  {
1719  escval = escape_insert_string(val);
1720  stringbuffer_aprintf(sb, "'%s'", escval);
1721  }
1722 
1723  /* Free the escaped version if required */
1724  if (val != escval)
1725  free(escval);
1726  }
1727 
1728 done_cell:
1729 
1730  /* Only put in delimeter if not last field or a shape will follow */
1731  if (state->config->readshape == 1 || i < DBFGetFieldCount(state->hDBFHandle) - 1)
1732  {
1733  if (state->config->dump_format)
1734  stringbuffer_aprintf(sb, "\t");
1735  else
1736  stringbuffer_aprintf(sb, ",");
1737  }
1738 
1739  /* End of DBF attribute loop */
1740  }
1741 
1742 
1743  /* Add the shape attribute if we are reading it */
1744  if (state->config->readshape == 1)
1745  {
1746  /* Force the locale to C */
1747  char *oldlocale = setlocale(LC_NUMERIC, "C");
1748 
1749  /* Handle the case of a NULL shape */
1750  if (obj->nVertices == 0)
1751  {
1752  if (state->config->dump_format)
1753  stringbuffer_aprintf(sb, "\\N");
1754  else
1755  stringbuffer_aprintf(sb, "NULL");
1756  }
1757  else
1758  {
1759  /* Handle all other shape attributes */
1760  switch (obj->nSHPType)
1761  {
1762  case SHPT_POLYGON:
1763  case SHPT_POLYGONM:
1764  case SHPT_POLYGONZ:
1765  res = GeneratePolygonGeometry(state, obj, &geometry);
1766  break;
1767 
1768  case SHPT_POINT:
1769  case SHPT_POINTM:
1770  case SHPT_POINTZ:
1771  res = GeneratePointGeometry(state, obj, &geometry, 0);
1772  break;
1773 
1774  case SHPT_MULTIPOINT:
1775  case SHPT_MULTIPOINTM:
1776  case SHPT_MULTIPOINTZ:
1777  /* Force it to multi unless using -S */
1778  res = GeneratePointGeometry(state, obj, &geometry,
1779  state->config->simple_geometries ? 0 : 1);
1780  break;
1781 
1782  case SHPT_ARC:
1783  case SHPT_ARCM:
1784  case SHPT_ARCZ:
1785  res = GenerateLineStringGeometry(state, obj, &geometry);
1786  break;
1787 
1788  default:
1789  snprintf(state->message, SHPLOADERMSGLEN, _("Shape type is not supported, type id = %d"), obj->nSHPType);
1790  SHPDestroyObject(obj);
1791  stringbuffer_destroy(sbwarn);
1793 
1794  return SHPLOADERERR;
1795  }
1796  /* The default returns out of the function, so res will always have been set. */
1797  if (res != SHPLOADEROK)
1798  {
1799  /* Error message has already been set */
1800  SHPDestroyObject(obj);
1801  stringbuffer_destroy(sbwarn);
1803 
1804  return SHPLOADERERR;
1805  }
1806 
1807  /* Now generate the geometry string according to the current configuration */
1808  if (!state->config->dump_format)
1809  {
1810  if (state->to_srid != state->from_srid)
1811  {
1812  stringbuffer_aprintf(sb, "ST_Transform(");
1813  }
1814  stringbuffer_aprintf(sb, "'");
1815  }
1816 
1817  stringbuffer_aprintf(sb, "%s", geometry);
1818 
1819  if (!state->config->dump_format)
1820  {
1821  stringbuffer_aprintf(sb, "'");
1822 
1823  /* Close the ST_Transform if reprojecting. */
1824  if (state->to_srid != state->from_srid)
1825  {
1826  /* We need to add an explicit cast to geography/geometry to ensure that
1827  PostgreSQL doesn't get confused with the ST_Transform() raster
1828  function. */
1829  if (state->config->geography)
1830  stringbuffer_aprintf(sb, "::geometry, %d)::geography", state->to_srid);
1831  else
1832  stringbuffer_aprintf(sb, "::geometry, %d)", state->to_srid);
1833  }
1834  }
1835 
1836  // free(geometry);
1837  }
1838 
1839  /* Tidy up everything */
1840  SHPDestroyObject(obj);
1841 
1842  setlocale(LC_NUMERIC, oldlocale);
1843  }
1844 
1845  /* Close the line correctly for dump/insert format */
1846  if (!state->config->dump_format)
1847  stringbuffer_aprintf(sb, ");");
1848 
1849 
1850  /* Copy the string buffer into a new string, destroying the string buffer */
1851  ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1);
1852  strcpy(ret, (char *)stringbuffer_getstring(sb));
1854 
1855  *strrecord = ret;
1856 
1857  /* If any warnings occurred, set the returned message string and warning status */
1858  if (strlen((char *)stringbuffer_getstring(sbwarn)) > 0)
1859  {
1860  snprintf(state->message, SHPLOADERMSGLEN, "%s", stringbuffer_getstring(sbwarn));
1861  stringbuffer_destroy(sbwarn);
1862 
1863  return SHPLOADERWARN;
1864  }
1865  else
1866  {
1867  /* Everything went okay */
1868  stringbuffer_destroy(sbwarn);
1869 
1870  return SHPLOADEROK;
1871  }
1872 }
1873 
1874 
1875 /* Return a pointer to an allocated string containing the header for the specified loader state */
1876 int
1877 ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter)
1878 {
1879  stringbuffer_t *sb;
1880  char *ret;
1881 
1882  /* Create the stringbuffer containing the header; we use this API as it's easier
1883  for handling string resizing during append */
1884  sb = stringbuffer_create();
1885  stringbuffer_clear(sb);
1886 
1887  if ( state->config->dump_format && state->to_srid != state->from_srid){
1889  stringbuffer_aprintf(sb, "ALTER TABLE \"pgis_tmp_%s\" ALTER COLUMN \"%s\" TYPE ", state->config->table, state->geo_col);
1890  if (state->config->geography){
1891  stringbuffer_aprintf(sb, "geography USING (ST_Transform(\"%s\", %d)::geography );\n", state->geo_col, state->to_srid);
1892  }
1893  else {
1894  stringbuffer_aprintf(sb, "geometry USING (ST_Transform(\"%s\", %d)::geometry );\n", state->geo_col, state->to_srid);
1895  }
1896  stringbuffer_aprintf(sb, "INSERT INTO ");
1897  // /* Schema is optional, include if present. */
1898  if (state->config->schema)
1899  {
1900  stringbuffer_aprintf(sb, "\"%s\".", state->config->schema);
1901  }
1902  stringbuffer_aprintf(sb, "\"%s\" (%s) ", state->config->table, state->col_names);
1903  stringbuffer_aprintf(sb, "SELECT %s FROM \"pgis_tmp_%s\";\n", state->col_names, state->config->table);
1904  }
1905 
1906  /* Create gist index if specified and not in "prepare" mode */
1907  if (state->config->readshape && state->config->createindex)
1908  {
1909  stringbuffer_aprintf(sb, "CREATE INDEX ON ");
1910  /* Schema is optional, include if present. */
1911  if (state->config->schema)
1912  {
1913  stringbuffer_aprintf(sb, "\"%s\".",state->config->schema);
1914  }
1915  stringbuffer_aprintf(sb, "\"%s\" USING GIST (\"%s\")", state->config->table, state->geo_col);
1916  /* Tablespace is also optional. */
1917  if (state->config->idxtablespace != NULL)
1918  {
1919  stringbuffer_aprintf(sb, " TABLESPACE \"%s\"", state->config->idxtablespace);
1920  }
1921  stringbuffer_aprintf(sb, ";\n");
1922  }
1923 
1924  /* End the transaction if there is one. */
1925  if (state->config->usetransaction)
1926  {
1927  stringbuffer_aprintf(sb, "COMMIT;\n");
1928  }
1929 
1930 
1931  if(state->config->analyze)
1932  {
1933  /* Always ANALYZE the resulting table, for better stats */
1934  stringbuffer_aprintf(sb, "ANALYZE ");
1935  if (state->config->schema)
1936  {
1937  stringbuffer_aprintf(sb, "\"%s\".", state->config->schema);
1938  }
1939  stringbuffer_aprintf(sb, "\"%s\";\n", state->config->table);
1940  }
1941 
1942  /* Copy the string buffer into a new string, destroying the string buffer */
1943  ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1);
1944  strcpy(ret, (char *)stringbuffer_getstring(sb));
1946 
1947  *strfooter = ret;
1948 
1949  return SHPLOADEROK;
1950 }
1951 
1952 
1953 void
1955 {
1956  /* Destroy a state object created with ShpLoaderOpenShape */
1957  int i;
1958  if (state != NULL)
1959  {
1960  if (state->hSHPHandle)
1961  SHPClose(state->hSHPHandle);
1962  if (state->hDBFHandle)
1963  DBFClose(state->hDBFHandle);
1964  if (state->field_names)
1965  {
1966  for (i = 0; i < state->num_fields; i++)
1967  free(state->field_names[i]);
1968 
1969  free(state->field_names);
1970  }
1971  if (state->pgfieldtypes)
1972  {
1973  for (i = 0; i < state->num_fields; i++)
1974  free(state->pgfieldtypes[i]);
1975 
1976  free(state->pgfieldtypes);
1977  }
1978  if (state->types)
1979  free(state->types);
1980  if (state->widths)
1981  free(state->widths);
1982  if (state->precisions)
1983  free(state->precisions);
1984  if (state->col_names)
1985  free(state->col_names);
1986 
1987  /* Free any column map fieldnames if specified */
1988  colmap_clean(&state->column_map);
1989 
1990  /* Free the state itself */
1991  free(state);
1992  }
1993 }
char * s
Definition: cu_in_wkt.c:23
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
Definition: dbfopen.c:1237
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
Definition: dbfopen.c:351
int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
Definition: dbfopen.c:1250
void SHPAPI_CALL DBFClose(DBFHandle psDBF)
Definition: dbfopen.c:599
int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
Definition: dbfopen.c:1217
int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
Definition: dbfopen.c:1741
const char SHPAPI_CALL1 * DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField){ return STATIC_CAST(const char *, DBFReadAttribute(psDBF, iRecord, iField, 'C')
DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
Definition: dbfopen.c:1265
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoint.c:151
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
#define LW_FALSE
Definition: liblwgeom.h:109
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:309
#define COLLECTIONTYPE
Definition: liblwgeom.h:123
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define MULTILINETYPE
Definition: liblwgeom.h:121
#define WKT_EXTENDED
Definition: liblwgeom.h:2168
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:329
#define MULTIPOINTTYPE
Definition: liblwgeom.h:120
char * lwgeom_to_hexwkb_buffer(const LWGEOM *geom, uint8_t variant)
Definition: lwout_wkb.c:845
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:247
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:117
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:122
void lwfree(void *mem)
Definition: lwutil.c:242
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
#define WKB_EXTENDED
Definition: liblwgeom.h:2159
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:708
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:147
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:42
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:108
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:188
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:230
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:187
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoly.c:161
#define str(s)
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
type
Definition: ovdump.py:42
tuple res
Definition: window.py:79
#define SHPT_ARCZ
Definition: shapefil.h:354
DBFFieldType
Definition: shapefil.h:638
@ FTDouble
Definition: shapefil.h:641
@ FTString
Definition: shapefil.h:639
@ FTInvalid
Definition: shapefil.h:644
@ FTLogical
Definition: shapefil.h:642
@ FTDate
Definition: shapefil.h:643
@ FTInteger
Definition: shapefil.h:640
SHPObject SHPAPI_CALL1 * SHPReadObject(SHPHandle hSHP, int iShape);int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape, SHPObject *psObject
Definition: shpopen.c:1831
#define SHPT_ARCM
Definition: shapefil.h:358
#define SHPT_POLYGONM
Definition: shapefil.h:359
#define SHPT_ARC
Definition: shapefil.h:350
void SHPAPI_CALL SHPClose(SHPHandle hSHP)
Definition: shpopen.c:879
#define SHPT_POLYGON
Definition: shapefil.h:351
void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject)
Definition: shpopen.c:2641
SHPHandle SHPAPI_CALL SHPOpen(const char *pszShapeFile, const char *pszAccess)
Definition: shpopen.c:291
#define SHPT_MULTIPOINT
Definition: shapefil.h:352
void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
Definition: shpopen.c:947
#define SHPT_POINTZ
Definition: shapefil.h:353
#define SHPT_MULTIPOINTZ
Definition: shapefil.h:356
#define SHPT_MULTIPOINTM
Definition: shapefil.h:360
#define SHPT_POINTM
Definition: shapefil.h:357
#define SHPT_POINT
Definition: shapefil.h:349
#define SHPT_POLYGONZ
Definition: shapefil.h:355
static int utf8(const char *fromcode, char *inputbuf, char **outputbuf)
int GeneratePointGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry, int force_multi)
Generate an allocated geometry string for shapefile object obj using the state parameters if "force_m...
struct struct_ring Ring
int ShpLoaderGetRecordCount(SHPLOADERSTATE *state)
int PIP(Point P, Point *V, int n)
PIP(): crossing number test for a point in a polygon input: P = a point, V[] = vertex points of a pol...
char * escape_insert_string(char *str)
Escape input string suitable for INSERT.
#define UTF8_GOOD_RESULT
#define UTF8_BAD_RESULT
int GeneratePolygonGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry)
Generate an allocated geometry string for shapefile object obj using the state parameters.
int FindPolygons(SHPObject *obj, Ring ***Out)
void strtolower(char *s)
void ShpLoaderDestroy(SHPLOADERSTATE *state)
char * escape_copy_string(char *str)
Escape input string suitable for COPY.
int ShpLoaderGetSQLCopyStatement(SHPLOADERSTATE *state, char **strheader)
int ShpLoaderOpenShape(SHPLOADERSTATE *state)
void ReleasePolygons(Ring **polys, int npolys)
int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord)
#define UTF8_NO_RESULT
void set_loader_config_defaults(SHPLOADERCONFIG *config)
int ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter)
struct struct_point Point
SHPLOADERSTATE * ShpLoaderCreate(SHPLOADERCONFIG *config)
int GenerateLineStringGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry)
Generate an allocated geometry string for shapefile object obj using the state parameters.
int ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
#define FORCE_OUTPUT_4D
#define WKT_PRECISION
#define POLICY_NULL_ABORT
#define GEOGRAPHY_DEFAULT
#define FORCE_OUTPUT_2D
#define SHPLOADERRECISNULL
#define SHPLOADERWARN
#define FORCE_OUTPUT_3DM
#define POLICY_NULL_SKIP
#define POLICY_NULL_INSERT
#define ENCODING_DEFAULT
#define FORCE_OUTPUT_DISABLE
#define SHPLOADERMSGLEN
#define GEOMETRY_DEFAULT
#define SHPLOADERRECDELETED
#define MAXVALUELEN
#define SHPLOADERERR
#define MAXFIELDNAMELEN
#define SHPLOADEROK
#define FORCE_OUTPUT_3DZ
int colmap_read(const char *filename, colmap *map, char *errbuf, size_t errbuflen)
Read the content of filename into a symbol map.
Definition: shpcommon.c:213
void colmap_init(colmap *map)
Definition: shpcommon.c:159
const char * colmap_pg_by_dbf(colmap *map, const char *dbfname)
Definition: shpcommon.c:199
void colmap_clean(colmap *map)
Definition: shpcommon.c:167
char * codepage2encoding(const char *cpg)
Definition: shpcommon.c:288
#define _(String)
Definition: shpcommon.h:24
void stringbuffer_clear(stringbuffer_t *s)
Reset the stringbuffer_t.
Definition: stringbuffer.c:88
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
Definition: stringbuffer.c:230
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:33
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:76
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:113
char * pszCodePage
Definition: shapefil.h:625
double m
Definition: liblwgeom.h:429
double x
Definition: liblwgeom.h:429
double z
Definition: liblwgeom.h:429
double y
Definition: liblwgeom.h:429
char message[SHPLOADERMSGLEN]
DBFFieldType * types
SHPHandle hSHPHandle
DBFHandle hDBFHandle
SHPLOADERCONFIG * config
Point * list
unsigned int linked
struct struct_ring * next
double * padfX
Definition: shapefil.h:390
int nVertices
Definition: shapefil.h:389
double * padfY
Definition: shapefil.h:391
int nSHPType
Definition: shapefil.h:381
double * padfZ
Definition: shapefil.h:392
int * panPartStart
Definition: shapefil.h:386
double * padfM
Definition: shapefil.h:393