geo_coder 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +32 -0
  3. data/History.txt +6 -0
  4. data/Makefile +13 -0
  5. data/Manifest.txt +18 -0
  6. data/README.rdoc +197 -0
  7. data/Rakefile +53 -0
  8. data/TODO.txt +8 -0
  9. data/VERSION +1 -0
  10. data/bin/build_indexes +8 -0
  11. data/bin/rebuild_cluster +22 -0
  12. data/bin/rebuild_metaphones +23 -0
  13. data/bin/tiger_import +59 -0
  14. data/demos/demo/app/ext/geocodewrap.rb +84 -0
  15. data/demos/demo/app/views/index.builder +13 -0
  16. data/demos/demo/app/views/index.erb +71 -0
  17. data/demos/demo/config.ru +12 -0
  18. data/demos/demo/config/bootstraps.rb +130 -0
  19. data/demos/demo/config/geoenvironment.rb +25 -0
  20. data/demos/demo/geocoder_helper.rb +12 -0
  21. data/demos/demo/geocom_geocode.rb +10 -0
  22. data/demos/demo/main.rb +3 -0
  23. data/demos/demo/rakefile.rb +17 -0
  24. data/demos/demo/tmp/restart.txt +0 -0
  25. data/demos/simpledemo/views/index.builder +13 -0
  26. data/demos/simpledemo/views/index.erb +69 -0
  27. data/demos/simpledemo/ws.rb +83 -0
  28. data/doc/Makefile +7 -0
  29. data/doc/html4css1.css +279 -0
  30. data/doc/lookup.rst +193 -0
  31. data/doc/parsing.rst +125 -0
  32. data/doc/voidspace.css +147 -0
  33. data/geo_coder.gemspec +172 -0
  34. data/lib/geocoder/us.rb +21 -0
  35. data/lib/geocoder/us/address.rb +290 -0
  36. data/lib/geocoder/us/constants.rb +670 -0
  37. data/lib/geocoder/us/database.rb +745 -0
  38. data/lib/geocoder/us/import.rb +181 -0
  39. data/lib/geocoder/us/import/tiger.rb +13 -0
  40. data/lib/geocoder/us/numbers.rb +58 -0
  41. data/navteq/README +4 -0
  42. data/navteq/convert.sql +37 -0
  43. data/navteq/navteq_import +39 -0
  44. data/navteq/prepare.sql +92 -0
  45. data/sql/cluster.sql +16 -0
  46. data/sql/convert.sql +80 -0
  47. data/sql/create.sql +37 -0
  48. data/sql/index.sql +12 -0
  49. data/sql/place.csv +104944 -0
  50. data/sql/place.sql +104948 -0
  51. data/sql/setup.sql +78 -0
  52. data/src/Makefile +13 -0
  53. data/src/README +14 -0
  54. data/src/liblwgeom/Makefile +75 -0
  55. data/src/liblwgeom/box2d.c +54 -0
  56. data/src/liblwgeom/lex.yy.c +4799 -0
  57. data/src/liblwgeom/liblwgeom.h +1405 -0
  58. data/src/liblwgeom/lwalgorithm.c +946 -0
  59. data/src/liblwgeom/lwalgorithm.h +52 -0
  60. data/src/liblwgeom/lwcircstring.c +759 -0
  61. data/src/liblwgeom/lwcollection.c +541 -0
  62. data/src/liblwgeom/lwcompound.c +118 -0
  63. data/src/liblwgeom/lwcurvepoly.c +86 -0
  64. data/src/liblwgeom/lwgeom.c +886 -0
  65. data/src/liblwgeom/lwgeom_api.c +2201 -0
  66. data/src/liblwgeom/lwgparse.c +1219 -0
  67. data/src/liblwgeom/lwgunparse.c +1054 -0
  68. data/src/liblwgeom/lwline.c +525 -0
  69. data/src/liblwgeom/lwmcurve.c +125 -0
  70. data/src/liblwgeom/lwmline.c +137 -0
  71. data/src/liblwgeom/lwmpoint.c +138 -0
  72. data/src/liblwgeom/lwmpoly.c +141 -0
  73. data/src/liblwgeom/lwmsurface.c +129 -0
  74. data/src/liblwgeom/lwpoint.c +439 -0
  75. data/src/liblwgeom/lwpoly.c +579 -0
  76. data/src/liblwgeom/lwsegmentize.c +1047 -0
  77. data/src/liblwgeom/lwutil.c +369 -0
  78. data/src/liblwgeom/measures.c +861 -0
  79. data/src/liblwgeom/postgis_config.h +93 -0
  80. data/src/liblwgeom/ptarray.c +847 -0
  81. data/src/liblwgeom/vsprintf.c +179 -0
  82. data/src/liblwgeom/wktparse.h +126 -0
  83. data/src/liblwgeom/wktparse.lex +74 -0
  84. data/src/liblwgeom/wktparse.tab.c +2353 -0
  85. data/src/liblwgeom/wktparse.tab.h +145 -0
  86. data/src/liblwgeom/wktparse.y +385 -0
  87. data/src/libsqlite3_geocoder/Makefile +22 -0
  88. data/src/libsqlite3_geocoder/Makefile.nix +15 -0
  89. data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
  90. data/src/libsqlite3_geocoder/extension.c +121 -0
  91. data/src/libsqlite3_geocoder/extension.h +13 -0
  92. data/src/libsqlite3_geocoder/levenshtein.c +42 -0
  93. data/src/libsqlite3_geocoder/metaphon.c +278 -0
  94. data/src/libsqlite3_geocoder/util.c +37 -0
  95. data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
  96. data/src/metaphone/Makefile +7 -0
  97. data/src/metaphone/README +49 -0
  98. data/src/metaphone/extension.c +37 -0
  99. data/src/metaphone/metaphon.c +251 -0
  100. data/src/shp2sqlite/Makefile +37 -0
  101. data/src/shp2sqlite/Makefile.nix +36 -0
  102. data/src/shp2sqlite/Makefile.redhat +35 -0
  103. data/src/shp2sqlite/dbfopen.c +1595 -0
  104. data/src/shp2sqlite/getopt.c +695 -0
  105. data/src/shp2sqlite/getopt.h +127 -0
  106. data/src/shp2sqlite/shapefil.h +500 -0
  107. data/src/shp2sqlite/shp2sqlite.c +1974 -0
  108. data/src/shp2sqlite/shpopen.c +1894 -0
  109. data/tests/address.rb +236 -0
  110. data/tests/benchmark.rb +20 -0
  111. data/tests/constants.rb +57 -0
  112. data/tests/data/address-sample.csv +52 -0
  113. data/tests/data/db-test.csv +57 -0
  114. data/tests/data/locations.csv +4 -0
  115. data/tests/database.rb +137 -0
  116. data/tests/generate.rb +34 -0
  117. data/tests/numbers.rb +46 -0
  118. data/tests/run.rb +11 -0
  119. metadata +237 -0
@@ -0,0 +1,1974 @@
1
+ /**********************************************************************
2
+ * $Id: shp2pgsql.c 3623 2009-02-03 07:20:16Z pramsey $
3
+ *
4
+ * PostGIS - Spatial Types for PostgreSQL
5
+ * http://postgis.refractions.net
6
+ * Copyright 2001-2003 Refractions Research Inc.
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
+ **********************************************************************
12
+ * Using shapelib 1.2.8, this program reads in shape files and
13
+ * processes it's contents into a Insert statements which can be
14
+ * easily piped into a database frontend.
15
+ * Specifically designed to insert type 'geometry' (a custom
16
+ * written PostgreSQL type) for the shape files and PostgreSQL
17
+ * standard types for all attributes of the entity.
18
+ *
19
+ * Original Author: Jeff Lounsbury, jeffloun@refractions.net
20
+ *
21
+ * Maintainer: Sandro Santilli, strk@refractions.net
22
+ *
23
+ **********************************************************************/
24
+
25
+ #include "../liblwgeom/postgis_config.h"
26
+ #include "shapefil.h"
27
+ #include <stdio.h>
28
+ #include <string.h>
29
+ #include <stdlib.h>
30
+ #include <ctype.h>
31
+ #include <sys/types.h>
32
+ #include <sys/stat.h>
33
+ #include <unistd.h>
34
+ #include <errno.h>
35
+ #include "getopt.h"
36
+ #ifdef HAVE_ICONV
37
+ #include <iconv.h>
38
+ #endif
39
+
40
+ #include "../liblwgeom/liblwgeom.h"
41
+
42
+
43
+ #define POINTTYPE 1
44
+ #define LINETYPE 2
45
+ #define POLYGONTYPE 3
46
+ #define MULTIPOINTTYPE 4
47
+ #define MULTILINETYPE 5
48
+ #define MULTIPOLYGONTYPE 6
49
+ #define COLLECTIONTYPE 7
50
+
51
+ #define WKBZOFFSET 0x80000000
52
+ #define WKBMOFFSET 0x40000000
53
+
54
+ typedef struct {double x, y, z, m;} Point;
55
+
56
+ typedef struct Ring {
57
+ Point *list; /* list of points */
58
+ struct Ring *next;
59
+ int n; /* number of points in list */
60
+ unsigned int linked; /* number of "next" rings */
61
+ } Ring;
62
+
63
+ /* Values for null_policy global */
64
+ enum {
65
+ insert_null,
66
+ skip_null,
67
+ abort_on_null
68
+ };
69
+
70
+ /* globals */
71
+ int dump_format = 0; /* 0=insert statements, 1 = dump */
72
+ int sqlite_format = 1; /* 0=PostGIS GEOMETRY, 1=SQLite BLOB */
73
+ int simple_geometries = 0; /* 0 = MULTILINESTRING/MULTIPOLYGON, 1 = LINESTRING/POLYGON */
74
+ int quoteidentifiers = 0;
75
+ int forceint4 = 0;
76
+ int createindex = 0;
77
+ int readshape = 1;
78
+ char opt = ' ';
79
+ char *col_names = NULL;
80
+ char *pgtype;
81
+ int istypeM = 0;
82
+ int pgdims;
83
+ unsigned int wkbtype;
84
+ char *shp_file = NULL;
85
+ int hwgeom = 0; /* old (hwgeom) mode */
86
+ #ifdef HAVE_ICONV
87
+ char *encoding=NULL;
88
+ #endif
89
+ int null_policy = insert_null;
90
+
91
+ DBFFieldType *types; /* Fields type, width and precision */
92
+ SHPHandle hSHPHandle;
93
+ DBFHandle hDBFHandle;
94
+ int shpfiletype;
95
+ SHPObject *obj=NULL;
96
+ int *widths;
97
+ int *precisions;
98
+ char *table=NULL,*schema=NULL,*geom=NULL;
99
+ int num_fields,num_records,num_entities;
100
+ char **field_names;
101
+ int sr_id = 0;
102
+
103
+ /* Prototypes */
104
+ int Insert_attributes(DBFHandle hDBFHandle, int row);
105
+ char *make_good_string(char *str);
106
+ char *protect_quotes_string(char *str);
107
+ int PIP( Point P, Point* V, int n );
108
+ void *safe_malloc(size_t size);
109
+ void CreateTable(void);
110
+ void CreateIndex(void);
111
+ void usage(char *me, int exitcode, FILE* out);
112
+ void InsertPoint(void);
113
+ void InsertMultiPoint(void);
114
+ void InsertPolygon(void);
115
+ void InsertLineString(void);
116
+ void OutputGeometry(char *geometry);
117
+ int ParseCmdline(int ARGC, char **ARGV);
118
+ void SetPgType(void);
119
+ char *dump_ring(Ring *ring);
120
+ #ifdef HAVE_ICONV
121
+ char *utf8(const char *fromcode, char *inputbuf);
122
+ #endif
123
+ int FindPolygons(SHPObject *obj, Ring ***Out);
124
+ void ReleasePolygons(Ring **polys, int npolys);
125
+ void DropTable(char *schema, char *table, char *geom);
126
+ void GetFieldsSpec(void);
127
+ void LoadData(void);
128
+ void OpenShape(void);
129
+ void LowerCase(char *s);
130
+ void Cleanup(void);
131
+
132
+ /*
133
+ static char rcsid[] =
134
+ "$Id: shp2pgsql.c 3623 2009-02-03 07:20:16Z pramsey $";
135
+ */
136
+
137
+ /* liblwgeom allocator callback - install the defaults (malloc/free/stdout/stderr) */
138
+ void lwgeom_init_allocators()
139
+ {
140
+ lwgeom_install_default_allocators();
141
+ }
142
+
143
+
144
+ void *safe_malloc(size_t size)
145
+ {
146
+ void *ret = malloc(size);
147
+ if ( ! ret ) {
148
+ fprintf(stderr, "Out of virtual memory\n");
149
+ exit(1);
150
+ }
151
+ return ret;
152
+ }
153
+
154
+ #define malloc(x) safe_malloc(x)
155
+
156
+
157
+ char *
158
+ make_good_string(char *str)
159
+ {
160
+ /*
161
+ * find all the tabs and make them \<tab>s
162
+ *
163
+ * 1. find # of tabs
164
+ * 2. make new string
165
+ *
166
+ * we dont escape already escaped tabs
167
+ */
168
+
169
+ char *result;
170
+ char *ptr, *optr;
171
+ int toescape = 0;
172
+ size_t size;
173
+ #ifdef HAVE_ICONV
174
+ char *utf8str=NULL;
175
+
176
+ if ( encoding )
177
+ {
178
+ utf8str=utf8(encoding, str);
179
+ if ( ! utf8str ) exit(1);
180
+ str = utf8str;
181
+ }
182
+ #endif
183
+
184
+ ptr = str;
185
+
186
+ while (*ptr) {
187
+ if ( *ptr == '\t' || *ptr == '\\' ) toescape++;
188
+ ptr++;
189
+ }
190
+
191
+ if (toescape == 0) return str;
192
+
193
+ size = ptr-str+toescape+1;
194
+
195
+ result = calloc(1, size);
196
+
197
+ optr=result;
198
+ ptr=str;
199
+ while (*ptr) {
200
+ if ( *ptr == '\t' || *ptr == '\\' ) *optr++='\\';
201
+ *optr++=*ptr++;
202
+ }
203
+ *optr='\0';
204
+
205
+ #ifdef HAVE_ICONV
206
+ if ( encoding ) free(str);
207
+ #endif
208
+
209
+ return result;
210
+
211
+ }
212
+
213
+ char *
214
+ protect_quotes_string(char *str)
215
+ {
216
+ /*
217
+ * find all quotes and make them \quotes
218
+ * find all '\' and make them '\\'
219
+ *
220
+ * 1. find # of characters
221
+ * 2. make new string
222
+ */
223
+
224
+ char *result;
225
+ char *ptr, *optr;
226
+ int toescape = 0;
227
+ size_t size;
228
+ #ifdef HAVE_ICONV
229
+ char *utf8str=NULL;
230
+
231
+ if ( encoding )
232
+ {
233
+ utf8str=utf8(encoding, str);
234
+ if ( ! utf8str ) exit(1);
235
+ str = utf8str;
236
+ }
237
+ #endif
238
+
239
+ ptr = str;
240
+
241
+ while (*ptr) {
242
+ if ( *ptr == '\'' || *ptr == '\\' ) toescape++;
243
+ ptr++;
244
+ }
245
+
246
+ if (toescape == 0) return str;
247
+
248
+ size = ptr-str+toescape+1;
249
+
250
+ result = calloc(1, size);
251
+
252
+ optr=result;
253
+ ptr=str;
254
+ while (*ptr) {
255
+ /* SQLite doesn't support backslash escaping in strings */
256
+ if ( *ptr == '\\' && !sqlite_format ) *optr++='\\';
257
+ if ( *ptr == '\'') *optr++='\'';
258
+ *optr++=*ptr++;
259
+ }
260
+ *optr='\0';
261
+
262
+ #ifdef HAVE_ICONV
263
+ if ( encoding ) free(str);
264
+ #endif
265
+
266
+ return result;
267
+ }
268
+
269
+
270
+ /*
271
+ * PIP(): crossing number test for a point in a polygon
272
+ * input: P = a point,
273
+ * V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
274
+ * returns: 0 = outside, 1 = inside
275
+ */
276
+ int
277
+ PIP( Point P, Point* V, int n )
278
+ {
279
+ int cn = 0; /* the crossing number counter */
280
+ int i;
281
+
282
+ /* loop through all edges of the polygon */
283
+ for (i=0; i<n-1; i++) { /* edge from V[i] to V[i+1] */
284
+ if (((V[i].y <= P.y) && (V[i+1].y > P.y)) /* an upward crossing */
285
+ || ((V[i].y > P.y) && (V[i+1].y <= P.y))) { /* a downward crossing */
286
+ double vt = (float)(P.y - V[i].y) / (V[i+1].y - V[i].y);
287
+ if (P.x < V[i].x + vt * (V[i+1].x - V[i].x)) /* P.x < intersect */
288
+ ++cn; /* a valid crossing of y=P.y right of P.x */
289
+ }
290
+ }
291
+ return (cn&1); /* 0 if even (out), and 1 if odd (in) */
292
+
293
+ }
294
+
295
+
296
+ /*Insert the attributes from the correct row of dbf file */
297
+
298
+ int
299
+ Insert_attributes(DBFHandle hDBFHandle, int row)
300
+ {
301
+ int i,num_fields;
302
+ char val[1024];
303
+ char *escval;
304
+
305
+ num_fields = DBFGetFieldCount( hDBFHandle );
306
+ for( i = 0; i < num_fields; i++ )
307
+ {
308
+ if(DBFIsAttributeNULL( hDBFHandle, row, i))
309
+ {
310
+
311
+ if(dump_format)
312
+ {
313
+ printf("\\N");
314
+ //printf("\t");
315
+ }
316
+ else
317
+ {
318
+ printf("NULL");
319
+ //printf(",");
320
+ }
321
+ }
322
+
323
+ else /* Attribute NOT NULL */
324
+ {
325
+ switch (types[i])
326
+ {
327
+ case FTInteger:
328
+ case FTDouble:
329
+ if ( -1 == snprintf(val, 1024, "%s",
330
+ DBFReadStringAttribute(hDBFHandle, row, i)) )
331
+ {
332
+ fprintf(stderr, "Warning: field %d name truncated\n", i);
333
+ val[1023] = '\0';
334
+ }
335
+ /* pg_atoi() does not do this */
336
+ if ( val[0] == '\0' ) { val[0] = '0'; val[1] = '\0'; }
337
+ if ( val[strlen(val)-1] == '.' ) val[strlen(val)-1] = '\0';
338
+ break;
339
+
340
+ case FTString:
341
+ case FTLogical:
342
+ case FTDate:
343
+ if ( -1 == snprintf(val, 1024, "%s",
344
+ DBFReadStringAttribute(hDBFHandle, row, i)) )
345
+ {
346
+ fprintf(stderr, "Warning: field %d name truncated\n", i);
347
+ val[1023] = '\0';
348
+ }
349
+ break;
350
+
351
+ default:
352
+ fprintf(stderr,
353
+ "Error: field %d has invalid or unknown field type (%d)\n",
354
+ i, types[i]);
355
+ exit(1);
356
+ }
357
+
358
+ if (dump_format) {
359
+ escval = make_good_string(val);
360
+ printf("%s", escval);
361
+ //printf("\t");
362
+ } else {
363
+ escval = protect_quotes_string(val);
364
+ if (sqlite_format)
365
+ printf("'%s'", escval);
366
+ else
367
+ printf("E'%s'", escval);
368
+ //printf(",");
369
+ }
370
+ if ( val != escval ) free(escval);
371
+ }
372
+ //only put in delimeter if not last field or a shape will follow
373
+ if(readshape == 1 || i < (num_fields - 1))
374
+ {
375
+ if (dump_format){
376
+ printf("\t");
377
+ }
378
+ else {
379
+ printf(",");
380
+ }
381
+ }
382
+ }
383
+ return 1;
384
+ }
385
+
386
+
387
+
388
+
389
+ /*
390
+ * main()
391
+ * see description at the top of this file
392
+ */
393
+ int
394
+ main (int ARGC, char **ARGV)
395
+ {
396
+
397
+ /*
398
+ * Parse command line
399
+ */
400
+ if ( ! ParseCmdline(ARGC, ARGV) ) usage(ARGV[0], 2, stderr);
401
+
402
+ /*
403
+ * Open shapefile and initialize globals
404
+ */
405
+ OpenShape();
406
+
407
+ if (readshape == 1){
408
+ /*
409
+ * Compute output geometry type
410
+ */
411
+
412
+ SetPgType();
413
+
414
+ /*
415
+ fprintf(stderr, "Shapefile type: %s\n", SHPTypeName(shpfiletype));
416
+ fprintf(stderr, "Postgis type: %s[%d]\n", pgtype, pgdims);
417
+ */
418
+ }
419
+
420
+ #ifdef HAVE_ICONV
421
+ if ( encoding )
422
+ {
423
+ printf("SET CLIENT_ENCODING TO UTF8;\n");
424
+ }
425
+ #endif /* defined HAVE_ICONV */
426
+
427
+ /*
428
+ * Drop table if requested
429
+ */
430
+ if(opt == 'd') DropTable(schema, table, geom);
431
+
432
+ /*
433
+ * Get col names and types for table creation
434
+ * and data load.
435
+ */
436
+ GetFieldsSpec();
437
+
438
+ printf("BEGIN;\n");
439
+
440
+ /*
441
+ * If not in 'append' mode create the spatial table
442
+ */
443
+ if(opt != 'a') CreateTable();
444
+
445
+ /*
446
+ * Generate INSERT or COPY lines
447
+ */
448
+ if(opt != 'p') LoadData();
449
+
450
+ /*
451
+ * Create GiST index if requested
452
+ */
453
+ if(createindex) CreateIndex();
454
+
455
+ printf("END;\n"); /* End the last transaction */
456
+
457
+
458
+ return 0;
459
+ }/*end main() */
460
+
461
+ void
462
+ LowerCase(char *s)
463
+ {
464
+ int j;
465
+ for (j=0; j<strlen(s); j++) s[j] = tolower(s[j]);
466
+ }
467
+
468
+ void
469
+ Cleanup(void)
470
+ {
471
+ if ( col_names ) free(col_names);
472
+ }
473
+
474
+ void
475
+ OpenShape(void)
476
+ {
477
+ int j;
478
+ SHPObject *obj=NULL;
479
+
480
+ if (readshape == 1)
481
+ {
482
+ hSHPHandle = SHPOpen( shp_file, "rb" );
483
+ if (hSHPHandle == NULL)
484
+ {
485
+ fprintf(stderr, "%s: shape (.shp) or index files (.shx) can not be opened, will just import attribute data.\n", shp_file);
486
+ readshape = 0;
487
+ }
488
+ }
489
+
490
+ hDBFHandle = DBFOpen( shp_file, "rb" );
491
+ if ((hSHPHandle == NULL && readshape == 1) || hDBFHandle == NULL){
492
+ fprintf(stderr, "%s: dbf file (.dbf) can not be opened.\n",shp_file);
493
+ exit(-1);
494
+ }
495
+
496
+ if (readshape == 1)
497
+ {
498
+ SHPGetInfo(hSHPHandle, &num_entities, &shpfiletype, NULL, NULL);
499
+
500
+ if ( null_policy == abort_on_null )
501
+ {
502
+ for (j=0; j<num_entities; j++)
503
+ {
504
+ obj = SHPReadObject(hSHPHandle,j);
505
+ if ( ! obj )
506
+ {
507
+ fprintf(stderr, "Error reading shape object %d\n", j);
508
+ exit(1);
509
+ }
510
+ if ( obj->nVertices == 0 )
511
+ {
512
+ fprintf(stderr, "Empty geometries found, aborted.\n");
513
+ exit(1);
514
+ }
515
+ SHPDestroyObject(obj);
516
+ }
517
+ }
518
+ }
519
+ else {
520
+ num_entities = DBFGetRecordCount(hDBFHandle);
521
+ }
522
+
523
+ }
524
+
525
+ void
526
+ CreateTable(void)
527
+ {
528
+ int j;
529
+ int field_precision, field_width;
530
+ DBFFieldType type = -1;
531
+ const char *pk_type;
532
+
533
+ /*
534
+ * Create a table for inserting the shapes into with appropriate
535
+ * columns and types
536
+ */
537
+ if (sqlite_format)
538
+ pk_type = "integer";
539
+ else
540
+ pk_type = "serial";
541
+
542
+ if ( schema )
543
+ {
544
+ printf("CREATE TABLE \"%s\".\"%s\" (gid %s PRIMARY KEY",
545
+ schema, table, pk_type);
546
+ }
547
+ else
548
+ {
549
+ printf("CREATE TABLE \"%s\" (gid %s PRIMARY KEY",
550
+ table, pk_type);
551
+ }
552
+
553
+ for(j=0;j<num_fields;j++)
554
+ {
555
+ type = types[j];
556
+ field_width = widths[j];
557
+ field_precision = precisions[j];
558
+
559
+ printf(",\n\"%s\" ", field_names[j]);
560
+
561
+ if(type == FTString)
562
+ {
563
+ /* use DBF attribute size as maximum width */
564
+ printf ("varchar(%d)", field_width);
565
+ }
566
+ else if (type == FTDate)
567
+ {
568
+ printf ("date");
569
+ }
570
+ else if (type == FTInteger)
571
+ {
572
+ if ( forceint4 )
573
+ {
574
+ printf ("int4");
575
+ }
576
+ else if ( field_width < 5 )
577
+ {
578
+ printf ("int2");
579
+ }
580
+ else if ( field_width < 10 )
581
+ {
582
+ printf ("int4");
583
+ }
584
+ else if ( field_width < 19 )
585
+ {
586
+ printf ("int8");
587
+ }
588
+ else
589
+ {
590
+ printf("numeric(%d,0)",
591
+ field_width);
592
+ }
593
+ }
594
+ else if(type == FTDouble)
595
+ {
596
+ if( field_width > 18 )
597
+ {
598
+ printf ("numeric");
599
+ }
600
+ else
601
+ {
602
+ printf ("float8");
603
+ }
604
+ }
605
+ else if(type == FTLogical)
606
+ {
607
+ printf ("boolean");
608
+ }
609
+ else
610
+ {
611
+ printf ("Invalid type in DBF file");
612
+ }
613
+ }
614
+ printf (");\n");
615
+
616
+ /* Create the geometry column with an addgeometry call */
617
+ if (sqlite_format) {
618
+ /* SQLite doesn't have a GEOMETRY type */
619
+ printf("ALTER TABLE %s ADD COLUMN %s blob;", table, geom);
620
+ } else {
621
+ if ( schema && readshape == 1 )
622
+ {
623
+ printf("SELECT AddGeometryColumn('%s','%s','%s','%d',",
624
+ schema, table, geom, sr_id);
625
+ }
626
+ else if (readshape == 1)
627
+ {
628
+ printf("SELECT AddGeometryColumn('','%s','%s','%d',",
629
+ table, geom, sr_id);
630
+ }
631
+ if (pgtype)
632
+ { //pgtype will only be set if we are loading geometries
633
+ printf("'%s',%d);\n", pgtype, pgdims);
634
+ }
635
+ }
636
+ }
637
+
638
+ void
639
+ CreateIndex(void)
640
+ {
641
+ /*
642
+ * Create gist index
643
+ */
644
+ if ( schema )
645
+ {
646
+ printf("CREATE INDEX \"%s_%s_gist\" ON \"%s\".\"%s\" using gist (\"%s\" gist_geometry_ops);\n", table, geom, schema, table, geom);
647
+ }
648
+ else
649
+ {
650
+ printf("CREATE INDEX \"%s_%s_gist\" ON \"%s\" using gist (\"%s\" gist_geometry_ops);\n", table, geom, table, geom);
651
+ }
652
+ }
653
+
654
+ void
655
+ LoadData(void)
656
+ {
657
+ int j, trans=0;
658
+
659
+ if (dump_format){
660
+ if ( schema )
661
+ {
662
+ printf("COPY \"%s\".\"%s\" %s FROM stdin;\n",
663
+ schema, table, col_names);
664
+ }
665
+ else
666
+ {
667
+ printf("COPY \"%s\" %s FROM stdin;\n",
668
+ table, col_names);
669
+ }
670
+ }
671
+
672
+
673
+ /**************************************************************
674
+ *
675
+ * MAIN SHAPE OBJECTS SCAN
676
+ *
677
+ **************************************************************/
678
+ for (j=0; j<num_entities; j++)
679
+ {
680
+ /*wrap a transaction block around each 250 inserts... */
681
+ if ( ! dump_format )
682
+ {
683
+ if (trans == 250) {
684
+ trans=0;
685
+ printf("END;\n");
686
+ printf("BEGIN;\n");
687
+ }
688
+ }
689
+ trans++;
690
+ /* transaction stuff done */
691
+
692
+ /* skip the record if it has been deleted */
693
+ if(readshape != 1 && DBFReadDeleted(hDBFHandle, j)) {
694
+ continue;
695
+ }
696
+
697
+ /* open the next object */
698
+ if (readshape == 1)
699
+ {
700
+ obj = SHPReadObject(hSHPHandle,j);
701
+ if ( ! obj )
702
+ {
703
+ fprintf(stderr, "Error reading shape object %d\n", j);
704
+ exit(1);
705
+ }
706
+
707
+ if ( null_policy == skip_null && obj->nVertices == 0 )
708
+ {
709
+ SHPDestroyObject(obj);
710
+ continue;
711
+ }
712
+ }
713
+
714
+ if (!dump_format)
715
+ {
716
+ if ( schema )
717
+ {
718
+ printf("INSERT INTO \"%s\".\"%s\" %s VALUES (",
719
+ schema, table, col_names);
720
+ }
721
+ else
722
+ {
723
+ printf("INSERT INTO \"%s\" %s VALUES (",
724
+ table, col_names);
725
+ }
726
+ }
727
+ Insert_attributes(hDBFHandle,j);
728
+
729
+ if (readshape == 1)
730
+ {
731
+ /* ---------- NULL SHAPE ----------------- */
732
+ if (obj->nVertices == 0)
733
+ {
734
+ if (dump_format) printf("\\N\n");
735
+ else printf("NULL);\n");
736
+ SHPDestroyObject(obj);
737
+ continue;
738
+ }
739
+
740
+ switch (obj->nSHPType)
741
+ {
742
+ case SHPT_POLYGON:
743
+ case SHPT_POLYGONM:
744
+ case SHPT_POLYGONZ:
745
+ InsertPolygon();
746
+ break;
747
+
748
+ case SHPT_POINT:
749
+ case SHPT_POINTM:
750
+ case SHPT_POINTZ:
751
+ case SHPT_MULTIPOINT:
752
+ case SHPT_MULTIPOINTM:
753
+ case SHPT_MULTIPOINTZ:
754
+ InsertPoint();
755
+ break;
756
+
757
+ case SHPT_ARC:
758
+ case SHPT_ARCM:
759
+ case SHPT_ARCZ:
760
+ InsertLineString();
761
+ break;
762
+
763
+ default:
764
+ printf ("\n\n**** Type is NOT SUPPORTED, type id = %d ****\n\n",
765
+ obj->nSHPType);
766
+ break;
767
+
768
+ }
769
+
770
+ SHPDestroyObject(obj);
771
+ }
772
+ else
773
+ if (dump_format){ /*close for dbf only dump format */
774
+ printf("\n");
775
+ }
776
+ else { /*close for dbf only sql insert format */
777
+ printf(");\n");
778
+ }
779
+
780
+ } /* END of MAIN SHAPE OBJECT LOOP */
781
+
782
+
783
+
784
+ if ((dump_format) ) {
785
+ printf("\\.\n");
786
+
787
+ }
788
+ }
789
+
790
+ void
791
+ usage(char *me, int exitcode, FILE* out)
792
+ {
793
+ /*
794
+ fprintf(out, "RCSID: %s RELEASE: %s\n", rcsid, POSTGIS_VERSION);
795
+ */
796
+ fprintf(out, "USAGE: %s [<options>] <shapefile> [<schema>.]<table>\n", me);
797
+ fprintf(out, "OPTIONS:\n");
798
+ fprintf(out, " -s <srid> Set the SRID field. If not specified it defaults to -1.\n");
799
+ fprintf(out, " (-d|a|c|p) These are mutually exclusive options:\n");
800
+ fprintf(out, " -d Drops the table, then recreates it and populates\n");
801
+ fprintf(out, " it with current shape file data.\n");
802
+ fprintf(out, " -a Appends shape file into current table, must be\n");
803
+ fprintf(out, " exactly the same table schema.\n");
804
+ fprintf(out, " -c Creates a new table and populates it, this is the\n");
805
+ fprintf(out, " default if you do not specify any options.\n");
806
+ fprintf(out, " -p Prepare mode, only creates the table.\n");
807
+ fprintf(out, " -g <geometry_column> Specify the name of the geometry column\n");
808
+ fprintf(out, " (mostly useful in append mode).\n");
809
+ fprintf(out, " -i Use int4 type for all integer dbf fields.\n");
810
+ fprintf(out, " -S Generate simple geometries instead of MULTI geometries.\n");
811
+ fprintf(out, " -w Use wkt format (drops M - drifts coordinates).\n");
812
+ #ifdef HAVE_ICONV
813
+ fprintf(out, " -W <encoding> Specify the character encoding of Shape's\n");
814
+ fprintf(out, " attribute column. (default : \"ASCII\")\n");
815
+ #endif
816
+ fprintf(out, " -N <policy> Specify NULL geometries handling policy (insert,skip,abort)\n");
817
+ fprintf(out, " -n Only import DBF file.\n");
818
+ fprintf(out, " -? Display this help screen\n");
819
+ exit (exitcode);
820
+ }
821
+
822
+ void
823
+ InsertLineString()
824
+ {
825
+ LWCOLLECTION *lwcollection;
826
+
827
+ LWGEOM **lwmultilinestrings;
828
+ uchar *serialized_lwgeom;
829
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
830
+
831
+ DYNPTARRAY **dpas;
832
+ POINT4D point4d;
833
+
834
+ int dims = 0, hasz = 0, hasm = 0;
835
+ int result;
836
+ int u, v, start_vertex, end_vertex;
837
+
838
+ /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
839
+ the M coordinate */
840
+ if (wkbtype & WKBZOFFSET) hasz = 1;
841
+ if (!hwgeom)
842
+ if (wkbtype & WKBMOFFSET) hasm = 1;
843
+ TYPE_SETZM(dims, hasz, hasm);
844
+
845
+ if (simple_geometries == 1 && obj->nParts > 1)
846
+ {
847
+ fprintf(stderr, "We have a Multilinestring with %d parts, can't use -S switch!\n", obj->nParts);
848
+ exit(1);
849
+ }
850
+
851
+ /* Allocate memory for our array of LWLINEs and our dynptarrays */
852
+ lwmultilinestrings = malloc(sizeof(LWPOINT *) * obj->nParts);
853
+ dpas = malloc(sizeof(DYNPTARRAY *) * obj->nParts);
854
+
855
+ /* We need an array of pointers to each of our sub-geometries */
856
+ for (u = 0; u < obj->nParts; u++)
857
+ {
858
+ /* Create a dynptarray containing the line points */
859
+ dpas[u] = dynptarray_create(obj->nParts, dims);
860
+
861
+ /* Set the start/end vertices depending upon whether this is
862
+ a MULTILINESTRING or not */
863
+ if ( u == obj->nParts-1 )
864
+ end_vertex = obj->nVertices;
865
+ else
866
+ end_vertex = obj->panPartStart[u + 1];
867
+
868
+ start_vertex = obj->panPartStart[u];
869
+
870
+ for (v = start_vertex; v < end_vertex; v++)
871
+ {
872
+ /* Generate the point */
873
+ point4d.x = obj->padfX[v];
874
+ point4d.y = obj->padfY[v];
875
+
876
+ if (wkbtype & WKBZOFFSET)
877
+ point4d.z = obj->padfZ[v];
878
+ if (wkbtype & WKBMOFFSET)
879
+ point4d.m = obj->padfM[v];
880
+
881
+ dynptarray_addPoint4d(dpas[u], &point4d, 0);
882
+ }
883
+
884
+ /* Generate the LWLINE */
885
+ lwmultilinestrings[u] = lwline_as_lwgeom(lwline_construct(sr_id, NULL, dpas[u]->pa));
886
+ }
887
+
888
+ /* If using MULTILINESTRINGs then generate the serialized collection, otherwise just a single LINESTRING */
889
+ if (simple_geometries == 0)
890
+ {
891
+ lwcollection = lwcollection_construct(MULTILINETYPE, sr_id, NULL, obj->nParts, lwmultilinestrings);
892
+ serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
893
+ }
894
+ else
895
+ {
896
+ serialized_lwgeom = lwgeom_serialize(lwmultilinestrings[0]);
897
+ }
898
+
899
+ if (!hwgeom)
900
+ result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL, -1);
901
+ else
902
+ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL);
903
+
904
+ if (result)
905
+ {
906
+ fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
907
+ exit(1);
908
+ }
909
+
910
+ OutputGeometry(lwg_unparser_result.wkoutput);
911
+
912
+ /* Free all of the allocated items */
913
+ lwfree(lwg_unparser_result.wkoutput);
914
+ lwfree(serialized_lwgeom);
915
+
916
+ for (u = 0; u < obj->nParts; u++)
917
+ {
918
+ lwline_free(lwgeom_as_lwline(lwmultilinestrings[u]));
919
+ lwfree(dpas[u]);
920
+ }
921
+
922
+ lwfree(dpas);
923
+ lwfree(lwmultilinestrings);
924
+ }
925
+
926
+ int
927
+ FindPolygons(SHPObject *obj, Ring ***Out)
928
+ {
929
+ Ring **Outer; /* Pointers to Outer rings */
930
+ int out_index=0; /* Count of Outer rings */
931
+ Ring **Inner; /* Pointers to Inner rings */
932
+ int in_index=0; /* Count of Inner rings */
933
+ int pi; /* part index */
934
+
935
+ #if POSTGIS_DEBUG_LEVEL > 0
936
+ static int call = -1;
937
+ call++;
938
+ #endif
939
+
940
+ LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts);
941
+
942
+ /* Allocate initial memory */
943
+ Outer = (Ring**)malloc(sizeof(Ring*)*obj->nParts);
944
+ Inner = (Ring**)malloc(sizeof(Ring*)*obj->nParts);
945
+
946
+ /* Iterate over rings dividing in Outers and Inners */
947
+ for (pi=0; pi<obj->nParts; pi++)
948
+ {
949
+ int vi; /* vertex index */
950
+ int vs; /* start index */
951
+ int ve; /* end index */
952
+ int nv; /* number of vertex */
953
+ double area = 0.0;
954
+ Ring *ring;
955
+
956
+ /* Set start and end vertexes */
957
+ if ( pi==obj->nParts-1 ) ve = obj->nVertices;
958
+ else ve = obj->panPartStart[pi+1];
959
+ vs = obj->panPartStart[pi];
960
+
961
+ /* Compute number of vertexes */
962
+ nv = ve-vs;
963
+
964
+ /* Allocate memory for a ring */
965
+ ring = (Ring*)malloc(sizeof(Ring));
966
+ ring->list = (Point*)malloc(sizeof(Point)*nv);
967
+ ring->n = nv;
968
+ ring->next = NULL;
969
+ ring->linked = 0;
970
+
971
+ /* Iterate over ring vertexes */
972
+ for ( vi=vs; vi<ve; vi++)
973
+ {
974
+ int vn = vi+1; /* next vertex for area */
975
+ if ( vn==ve ) vn = vs;
976
+
977
+ ring->list[vi-vs].x = obj->padfX[vi];
978
+ ring->list[vi-vs].y = obj->padfY[vi];
979
+ ring->list[vi-vs].z = obj->padfZ[vi];
980
+ ring->list[vi-vs].m = obj->padfM[vi];
981
+
982
+ area += (obj->padfX[vi] * obj->padfY[vn]) -
983
+ (obj->padfY[vi] * obj->padfX[vn]);
984
+ }
985
+
986
+ /* Close the ring with first vertex */
987
+ /*ring->list[vi].x = obj->padfX[vs]; */
988
+ /*ring->list[vi].y = obj->padfY[vs]; */
989
+ /*ring->list[vi].z = obj->padfZ[vs]; */
990
+ /*ring->list[vi].m = obj->padfM[vs]; */
991
+
992
+ /* Clockwise (or single-part). It's an Outer Ring ! */
993
+ if(area < 0.0 || obj->nParts ==1) {
994
+ Outer[out_index] = ring;
995
+ out_index++;
996
+ }
997
+
998
+ /* Counterclockwise. It's an Inner Ring ! */
999
+ else {
1000
+ Inner[in_index] = ring;
1001
+ in_index++;
1002
+ }
1003
+ }
1004
+
1005
+ LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index);
1006
+
1007
+ /* Put the inner rings into the list of the outer rings */
1008
+ /* of which they are within */
1009
+ for(pi=0; pi<in_index; pi++)
1010
+ {
1011
+ Point pt,pt2;
1012
+ int i;
1013
+ Ring *inner=Inner[pi], *outer=NULL;
1014
+
1015
+ pt.x = inner->list[0].x;
1016
+ pt.y = inner->list[0].y;
1017
+
1018
+ pt2.x = inner->list[1].x;
1019
+ pt2.y = inner->list[1].y;
1020
+
1021
+ for(i=0; i<out_index; i++)
1022
+ {
1023
+ int in;
1024
+
1025
+ in = PIP(pt, Outer[i]->list, Outer[i]->n);
1026
+ if( in || PIP(pt2, Outer[i]->list, Outer[i]->n) )
1027
+ {
1028
+ outer = Outer[i];
1029
+ break;
1030
+ }
1031
+ /*fprintf(stderr, "!PIP %s\nOUTE %s\n", dump_ring(inner), dump_ring(Outer[i])); */
1032
+ }
1033
+
1034
+ if ( outer )
1035
+ {
1036
+ outer->linked++;
1037
+ while(outer->next) outer = outer->next;
1038
+ outer->next = inner;
1039
+ }
1040
+ else
1041
+ {
1042
+ /* The ring wasn't within any outer rings, */
1043
+ /* assume it is a new outer ring. */
1044
+ LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi);
1045
+
1046
+ Outer[out_index] = inner;
1047
+ out_index++;
1048
+ }
1049
+ }
1050
+
1051
+ *Out = Outer;
1052
+ free(Inner);
1053
+
1054
+ return out_index;
1055
+ }
1056
+
1057
+ void
1058
+ ReleasePolygons(Ring **polys, int npolys)
1059
+ {
1060
+ int pi;
1061
+ /* Release all memory */
1062
+ for(pi=0; pi<npolys; pi++)
1063
+ {
1064
+ Ring *Poly, *temp;
1065
+ Poly = polys[pi];
1066
+ while(Poly != NULL){
1067
+ temp = Poly;
1068
+ Poly = Poly->next;
1069
+ free(temp->list);
1070
+ free(temp);
1071
+ }
1072
+ }
1073
+ free(polys);
1074
+ }
1075
+
1076
+ /*This function basically deals with the polygon case. */
1077
+ /*it sorts the polys in order of outer,inner,inner, so that inners */
1078
+ /*always come after outers they are within */
1079
+ void
1080
+ InsertPolygon(void)
1081
+ {
1082
+ Ring **Outer;
1083
+ int polygon_total, ring_total;
1084
+ int pi, vi; // part index and vertex index
1085
+ int u;
1086
+
1087
+ LWCOLLECTION *lwcollection = NULL;
1088
+
1089
+ LWGEOM **lwpolygons;
1090
+ uchar *serialized_lwgeom;
1091
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
1092
+
1093
+ LWPOLY *lwpoly;
1094
+ DYNPTARRAY *dpas;
1095
+ POINTARRAY ***pas;
1096
+ POINT4D point4d;
1097
+
1098
+ int dims = 0, hasz = 0, hasm = 0;
1099
+ int result;
1100
+
1101
+ /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
1102
+ the M coordinate */
1103
+ if (wkbtype & WKBZOFFSET) hasz = 1;
1104
+ if (!hwgeom)
1105
+ if (wkbtype & WKBMOFFSET) hasm = 1;
1106
+ TYPE_SETZM(dims, hasz, hasm);
1107
+
1108
+ polygon_total = FindPolygons(obj, &Outer);
1109
+
1110
+ if (simple_geometries == 1 && polygon_total != 1) /* We write Non-MULTI geometries, but have several parts: */
1111
+ {
1112
+ fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", polygon_total);
1113
+ exit(1);
1114
+ }
1115
+
1116
+ /* Allocate memory for our array of LWPOLYs */
1117
+ lwpolygons = malloc(sizeof(LWPOLY *) * polygon_total);
1118
+
1119
+ /* Allocate memory for our POINTARRAY pointers for each polygon */
1120
+ pas = malloc(sizeof(POINTARRAY **) * polygon_total);
1121
+
1122
+ /* Cycle through each individual polygon */
1123
+ for(pi = 0; pi < polygon_total; pi++)
1124
+ {
1125
+ Ring *polyring;
1126
+ int ring_index = 0;
1127
+
1128
+ /* Firstly count through the total number of rings in this polygon */
1129
+ ring_total = 0;
1130
+ polyring = Outer[pi];
1131
+ while (polyring)
1132
+ {
1133
+ ring_total++;
1134
+ polyring = polyring->next;
1135
+ }
1136
+
1137
+ /* Reserve memory for the POINTARRAYs representing each ring */
1138
+ pas[pi] = malloc(sizeof(POINTARRAY *) * ring_total);
1139
+
1140
+ /* Cycle through each ring within the polygon, starting with the outer */
1141
+ polyring = Outer[pi];
1142
+
1143
+ while (polyring)
1144
+ {
1145
+ /* Create a DYNPTARRAY containing the points making up the ring */
1146
+ dpas = dynptarray_create(polyring->n, dims);
1147
+
1148
+ for(vi = 0; vi < polyring->n; vi++)
1149
+ {
1150
+ /* Build up a point array of all the points in this ring */
1151
+ point4d.x = polyring->list[vi].x;
1152
+ point4d.y = polyring->list[vi].y;
1153
+
1154
+ if (wkbtype & WKBZOFFSET)
1155
+ point4d.z = polyring->list[vi].z;
1156
+ if (wkbtype & WKBMOFFSET)
1157
+ point4d.m = polyring->list[vi].m;
1158
+
1159
+ dynptarray_addPoint4d(dpas, &point4d, 0);
1160
+ }
1161
+
1162
+ /* Copy the POINTARRAY pointer from the DYNPTARRAY structure so we can
1163
+ use the LWPOLY constructor */
1164
+ pas[pi][ring_index] = dpas->pa;
1165
+
1166
+ /* Free the DYNPTARRAY structure (we don't need this part anymore as we
1167
+ have the reference to the internal POINTARRAY) */
1168
+ lwfree(dpas);
1169
+
1170
+ polyring = polyring->next;
1171
+ ring_index++;
1172
+ }
1173
+
1174
+ /* Generate the LWGEOM */
1175
+ lwpoly = lwpoly_construct(sr_id, NULL, ring_total, pas[pi]);
1176
+ lwpolygons[pi] = lwpoly_as_lwgeom(lwpoly);
1177
+ }
1178
+
1179
+ ReleasePolygons(Outer, polygon_total);
1180
+
1181
+ /* If using MULTIPOLYGONS then generate the serialized collection, otherwise just a single POLYGON */
1182
+ if (simple_geometries == 0)
1183
+ {
1184
+ lwcollection = lwcollection_construct(MULTIPOLYGONTYPE, sr_id, NULL, polygon_total, lwpolygons);
1185
+ serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
1186
+ }
1187
+ else
1188
+ {
1189
+ serialized_lwgeom = lwgeom_serialize(lwpolygons[0]);
1190
+ }
1191
+
1192
+ if (!hwgeom)
1193
+ result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL, -1);
1194
+ else
1195
+ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL);
1196
+
1197
+ if (result)
1198
+ {
1199
+ fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
1200
+ exit(1);
1201
+ }
1202
+
1203
+ OutputGeometry(lwg_unparser_result.wkoutput);
1204
+
1205
+ /* Free all of the allocated items */
1206
+ lwfree(lwg_unparser_result.wkoutput);
1207
+ lwfree(serialized_lwgeom);
1208
+
1209
+ /* Cycle through each polygon, freeing everything we need... */
1210
+ for (u = 0; u < polygon_total; u++)
1211
+ lwpoly_free(lwgeom_as_lwpoly(lwpolygons[u]));
1212
+
1213
+ /* Free the pointer arrays */
1214
+ lwfree(pas);
1215
+ lwfree(lwpolygons);
1216
+ if (simple_geometries == 0)
1217
+ lwfree(lwcollection);
1218
+ }
1219
+
1220
+ /*
1221
+ * Insert either a POINT or MULTIPOINT into the output stream
1222
+ */
1223
+ void
1224
+ InsertPoint(void)
1225
+ {
1226
+ LWCOLLECTION *lwcollection;
1227
+
1228
+ LWGEOM **lwmultipoints;
1229
+ uchar *serialized_lwgeom;
1230
+ LWGEOM_UNPARSER_RESULT lwg_unparser_result;
1231
+
1232
+ DYNPTARRAY **dpas;
1233
+ POINT4D point4d;
1234
+
1235
+ int dims = 0, hasz = 0, hasm = 0;
1236
+ int result;
1237
+ int u;
1238
+
1239
+ /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
1240
+ the M coordinate */
1241
+ if (wkbtype & WKBZOFFSET) hasz = 1;
1242
+ if (!hwgeom)
1243
+ if (wkbtype & WKBMOFFSET) hasm = 1;
1244
+ TYPE_SETZM(dims, hasz, hasm);
1245
+
1246
+ /* Allocate memory for our array of LWPOINTs and our dynptarrays */
1247
+ lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices);
1248
+ dpas = malloc(sizeof(DYNPTARRAY *) * obj->nVertices);
1249
+
1250
+ /* We need an array of pointers to each of our sub-geometries */
1251
+ for (u = 0; u < obj->nVertices; u++)
1252
+ {
1253
+ /* Generate the point */
1254
+ point4d.x = obj->padfX[u];
1255
+ point4d.y = obj->padfY[u];
1256
+
1257
+ if (wkbtype & WKBZOFFSET)
1258
+ point4d.z = obj->padfZ[u];
1259
+ if (wkbtype & WKBMOFFSET)
1260
+ point4d.m = obj->padfM[u];
1261
+
1262
+ /* Create a dynptarray containing a single point */
1263
+ dpas[u] = dynptarray_create(1, dims);
1264
+ dynptarray_addPoint4d(dpas[u], &point4d, 0);
1265
+
1266
+ /* Generate the LWPOINT */
1267
+ lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(sr_id, NULL, dpas[u]->pa));
1268
+ }
1269
+
1270
+ /* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT
1271
+ rather than a POINT */
1272
+ if (obj->nVertices > 1)
1273
+ {
1274
+ lwcollection = lwcollection_construct(MULTIPOINTTYPE, sr_id, NULL, obj->nVertices, lwmultipoints);
1275
+ serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
1276
+ }
1277
+ else
1278
+ {
1279
+ serialized_lwgeom = lwgeom_serialize(lwmultipoints[0]);
1280
+ }
1281
+
1282
+ if (!hwgeom)
1283
+ result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL, -1);
1284
+ else
1285
+ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL);
1286
+
1287
+ if (result)
1288
+ {
1289
+ fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
1290
+ exit(1);
1291
+ }
1292
+
1293
+ OutputGeometry(lwg_unparser_result.wkoutput);
1294
+
1295
+ /* Free all of the allocated items */
1296
+ lwfree(lwg_unparser_result.wkoutput);
1297
+ lwfree(serialized_lwgeom);
1298
+
1299
+ for (u = 0; u < obj->nVertices; u++)
1300
+ {
1301
+ lwpoint_free(lwgeom_as_lwpoint(lwmultipoints[u]));
1302
+ lwfree(dpas[u]);
1303
+ }
1304
+
1305
+ lwfree(dpas);
1306
+ lwfree(lwmultipoints);
1307
+ }
1308
+
1309
+ void
1310
+ OutputGeometry(char *geometry)
1311
+ {
1312
+ /* This function outputs the specified geometry string (WKB or WKT) formatted
1313
+ * according to whether we have specified dump format or hwgeom format */
1314
+
1315
+ if (hwgeom)
1316
+ {
1317
+ if (!dump_format)
1318
+ printf("GeomFromText('");
1319
+ else
1320
+ {
1321
+ /* Output SRID if relevant */
1322
+ if (sr_id != 0)
1323
+ printf("SRID=%d;", sr_id);
1324
+ }
1325
+
1326
+ printf("%s", geometry);
1327
+
1328
+ if (!dump_format)
1329
+ {
1330
+ printf("'");
1331
+
1332
+ /* Output SRID if relevant */
1333
+ if (sr_id != 0)
1334
+ printf(", %d)", sr_id);
1335
+
1336
+ printf(");\n");
1337
+ }
1338
+ else
1339
+ printf("\n");
1340
+ }
1341
+ else
1342
+ {
1343
+ if (!dump_format) {
1344
+ if (sqlite_format)
1345
+ /* SQLite BLOBs are formatted as a string of hex
1346
+ * digits with an X before the leading quote. */
1347
+ printf("X'");
1348
+ else
1349
+ printf("'");
1350
+ }
1351
+
1352
+ printf("%s", geometry);
1353
+
1354
+ if (!dump_format)
1355
+ printf("');\n");
1356
+ else
1357
+ printf("\n");
1358
+ }
1359
+ }
1360
+
1361
+
1362
+ int
1363
+ ParseCmdline(int ARGC, char **ARGV)
1364
+ {
1365
+ int c;
1366
+ int curindex=0;
1367
+ char *ptr;
1368
+ extern char *optarg;
1369
+ extern int optind;
1370
+
1371
+ if ( ARGC == 1 ) {
1372
+ usage(ARGV[0], 0, stdout);
1373
+ }
1374
+
1375
+ while ((c = pgis_getopt(ARGC, ARGV, "kcdapDLs:Sg:iW:wIN:n")) != EOF){
1376
+ switch (c) {
1377
+ case 'c':
1378
+ if (opt == ' ')
1379
+ opt ='c';
1380
+ else
1381
+ return 0;
1382
+ break;
1383
+ case 'd':
1384
+ if (opt == ' ')
1385
+ opt ='d';
1386
+ else
1387
+ return 0;
1388
+ break;
1389
+ case 'a':
1390
+ if (opt == ' ')
1391
+ opt ='a';
1392
+ else
1393
+ return 0;
1394
+ break;
1395
+ case 'p':
1396
+ if (opt == ' ')
1397
+ opt ='p';
1398
+ else
1399
+ return 0;
1400
+ break;
1401
+ case 'D':
1402
+ dump_format =1;
1403
+ break;
1404
+ case 'L':
1405
+ sqlite_format=1;
1406
+ break;
1407
+ case 'S':
1408
+ simple_geometries =1;
1409
+ break;
1410
+ case 's':
1411
+ (void)sscanf(optarg, "%d", &sr_id);
1412
+ break;
1413
+ case 'g':
1414
+ geom = optarg;
1415
+ break;
1416
+ case 'k':
1417
+ quoteidentifiers = 1;
1418
+ break;
1419
+ case 'i':
1420
+ forceint4 = 1;
1421
+ break;
1422
+ case 'I':
1423
+ createindex = 1;
1424
+ break;
1425
+ case 'w':
1426
+ hwgeom = 1;
1427
+ break;
1428
+ case 'n':
1429
+ readshape = 0;
1430
+ break;
1431
+ case 'W':
1432
+ #ifdef HAVE_ICONV
1433
+ encoding = optarg;
1434
+ #else
1435
+ fprintf(stderr, "WARNING: the -W switch will have no effect. UTF8 disabled at compile time\n");
1436
+ #endif
1437
+ break;
1438
+ case 'N':
1439
+ switch (optarg[0])
1440
+ {
1441
+ case 'a':
1442
+ null_policy = abort_on_null;
1443
+ break;
1444
+ case 'i':
1445
+ null_policy = insert_null;
1446
+ break;
1447
+ case 's':
1448
+ null_policy = skip_null;
1449
+ break;
1450
+ default:
1451
+ fprintf(stderr, "Unsupported NULL geometry handling policy.\nValid policies: insert, skip, abort\n");
1452
+ exit(1);
1453
+ }
1454
+ break;
1455
+ case '?':
1456
+ usage(ARGV[0], 0, stdout);
1457
+ default:
1458
+ return 0;
1459
+ }
1460
+ }
1461
+
1462
+ if ( !sr_id ) sr_id = -1;
1463
+
1464
+ if ( !geom ) geom = "the_geom";
1465
+
1466
+ if ( opt==' ' ) opt = 'c';
1467
+
1468
+ for (; optind < ARGC; optind++){
1469
+ if(curindex ==0){
1470
+ shp_file = ARGV[optind];
1471
+ }else if(curindex == 1){
1472
+ table = ARGV[optind];
1473
+ if ( (ptr=strchr(table, '.')) )
1474
+ {
1475
+ *ptr = '\0';
1476
+ schema = table;
1477
+ table = ptr+1;
1478
+ }
1479
+ }
1480
+ curindex++;
1481
+ }
1482
+
1483
+ /*
1484
+ * Third argument (if present) is supported for compatibility
1485
+ * with old shp2pgsql versions taking also database name.
1486
+ */
1487
+ if(curindex < 2 || curindex > 3){
1488
+ return 0;
1489
+ }
1490
+
1491
+ /*
1492
+ * Transform table name to lower case unless asked
1493
+ * to keep original case (we'll quote it later on)
1494
+ */
1495
+ if ( ! quoteidentifiers )
1496
+ {
1497
+ LowerCase(table);
1498
+ if ( schema ) LowerCase(schema);
1499
+ }
1500
+
1501
+ return 1;
1502
+ }
1503
+
1504
+
1505
+ void
1506
+ SetPgType(void)
1507
+ {
1508
+ switch(shpfiletype)
1509
+ {
1510
+ case SHPT_POINT: /* Point */
1511
+ pgtype = "POINT";
1512
+ wkbtype = POINTTYPE;
1513
+ pgdims = 2;
1514
+ break;
1515
+ case SHPT_ARC: /* PolyLine */
1516
+ pgtype = "MULTILINESTRING";
1517
+ wkbtype = MULTILINETYPE ;
1518
+ pgdims = 2;
1519
+ break;
1520
+ case SHPT_POLYGON: /* Polygon */
1521
+ pgtype = "MULTIPOLYGON";
1522
+ wkbtype = MULTIPOLYGONTYPE;
1523
+ pgdims = 2;
1524
+ break;
1525
+ case SHPT_MULTIPOINT: /* MultiPoint */
1526
+ pgtype = "MULTIPOINT";
1527
+ wkbtype = MULTIPOINTTYPE;
1528
+ pgdims = 2;
1529
+ break;
1530
+ case SHPT_POINTM: /* PointM */
1531
+ wkbtype = POINTTYPE | WKBMOFFSET;
1532
+ if ( ! hwgeom ) {
1533
+ pgtype = "POINTM";
1534
+ pgdims = 3;
1535
+ istypeM = 1;
1536
+ } else {
1537
+ pgtype = "POINT";
1538
+ pgdims = 2;
1539
+ }
1540
+ break;
1541
+ case SHPT_ARCM: /* PolyLineM */
1542
+ wkbtype = MULTILINETYPE | WKBMOFFSET;
1543
+ if ( ! hwgeom ) {
1544
+ pgtype = "MULTILINESTRINGM";
1545
+ pgdims = 3;
1546
+ istypeM = 1;
1547
+ } else {
1548
+ pgtype = "MULTILINESTRING";
1549
+ pgdims = 2;
1550
+ }
1551
+ break;
1552
+ case SHPT_POLYGONM: /* PolygonM */
1553
+ wkbtype = MULTIPOLYGONTYPE | WKBMOFFSET;
1554
+ if ( ! hwgeom ) {
1555
+ pgtype = "MULTIPOLYGONM";
1556
+ pgdims = 3;
1557
+ istypeM = 1;
1558
+ } else {
1559
+ pgtype = "MULTIPOLYGON";
1560
+ pgdims = 2;
1561
+ }
1562
+ break;
1563
+ case SHPT_MULTIPOINTM: /* MultiPointM */
1564
+ wkbtype = MULTIPOINTTYPE | WKBMOFFSET;
1565
+ if ( ! hwgeom ) {
1566
+ pgtype = "MULTIPOINTM";
1567
+ pgdims = 3;
1568
+ istypeM = 1;
1569
+ } else {
1570
+ pgtype = "MULTIPOINT";
1571
+ pgdims = 2;
1572
+ }
1573
+ break;
1574
+ case SHPT_POINTZ: /* PointZ */
1575
+ wkbtype = POINTTYPE | WKBMOFFSET | WKBZOFFSET;
1576
+ pgtype = "POINT";
1577
+ if ( ! hwgeom ) pgdims = 4;
1578
+ else pgdims = 3;
1579
+ break;
1580
+ case SHPT_ARCZ: /* PolyLineZ */
1581
+ pgtype = "MULTILINESTRING";
1582
+ wkbtype = MULTILINETYPE | WKBZOFFSET | WKBMOFFSET;
1583
+ if ( ! hwgeom ) pgdims = 4;
1584
+ else pgdims = 3;
1585
+ break;
1586
+ case SHPT_POLYGONZ: /* MultiPolygonZ */
1587
+ pgtype = "MULTIPOLYGON";
1588
+ wkbtype = MULTIPOLYGONTYPE | WKBZOFFSET | WKBMOFFSET;
1589
+ if ( ! hwgeom ) pgdims = 4;
1590
+ else pgdims = 3;
1591
+ break;
1592
+ case SHPT_MULTIPOINTZ: /* MultiPointZ */
1593
+ pgtype = "MULTIPOINT";
1594
+ wkbtype = MULTIPOINTTYPE | WKBZOFFSET | WKBMOFFSET;
1595
+ if ( ! hwgeom ) pgdims = 4;
1596
+ else pgdims = 3;
1597
+ break;
1598
+ default:
1599
+ pgtype = "GEOMETRY";
1600
+ wkbtype = COLLECTIONTYPE | WKBZOFFSET | WKBMOFFSET;
1601
+ pgdims = 4;
1602
+ fprintf(stderr, "Unknown geometry type: %d\n",
1603
+ shpfiletype);
1604
+ break;
1605
+ }
1606
+
1607
+ if (simple_geometries)
1608
+ {
1609
+ // adjust geometry name for CREATE TABLE by skipping MULTI
1610
+ if ((wkbtype & 0x7) == MULTIPOLYGONTYPE) pgtype += 5;
1611
+ if ((wkbtype & 0x7) == MULTILINETYPE) pgtype += 5;
1612
+ }
1613
+ }
1614
+
1615
+ char *
1616
+ dump_ring(Ring *ring)
1617
+ {
1618
+ char *buf = malloc(256*ring->n);
1619
+ int i;
1620
+
1621
+ buf[0] = '\0';
1622
+ for (i=0; i<ring->n; i++)
1623
+ {
1624
+ if (i) strcat(buf, ",");
1625
+ sprintf(buf+strlen(buf), "%g %g",
1626
+ ring->list[i].x,
1627
+ ring->list[i].y);
1628
+ }
1629
+ return buf;
1630
+ }
1631
+
1632
+ void
1633
+ DropTable(char *schema, char *table, char *geom)
1634
+ {
1635
+ /*---------------Drop the table--------------------------
1636
+ * TODO: if the table has more then one geometry column
1637
+ * the DROP TABLE call will leave spurious records in
1638
+ * geometry_columns.
1639
+ *
1640
+ * If the geometry column in the table being dropped
1641
+ * does not match 'the_geom' or the name specified with
1642
+ * -g an error is returned by DropGeometryColumn.
1643
+ *
1644
+ * The table to be dropped might not exist.
1645
+ *
1646
+ */
1647
+ if ( schema )
1648
+ {
1649
+ if (readshape == 1){
1650
+ printf("SELECT DropGeometryColumn('%s','%s','%s');\n",
1651
+ schema, table, geom);
1652
+ }
1653
+ printf("DROP TABLE \"%s\".\"%s\";\n", schema, table);
1654
+ }
1655
+ else
1656
+ {
1657
+ if (readshape == 1){
1658
+ printf("SELECT DropGeometryColumn('','%s','%s');\n",
1659
+ table, geom);
1660
+ }
1661
+ printf("DROP TABLE \"%s\";\n", table);
1662
+ }
1663
+ }
1664
+
1665
+ void
1666
+ GetFieldsSpec(void)
1667
+ {
1668
+ /*
1669
+ * Shapefile (dbf) field name are at most 10chars + 1 NULL.
1670
+ * Postgresql field names are at most 63 bytes + 1 NULL.
1671
+ */
1672
+ #define MAXFIELDNAMELEN 64
1673
+ int field_precision, field_width;
1674
+ int j, z;
1675
+ char name[MAXFIELDNAMELEN];
1676
+ char name2[MAXFIELDNAMELEN];
1677
+ DBFFieldType type = -1;
1678
+ #ifdef HAVE_ICONV
1679
+ char *utf8str;
1680
+ #endif
1681
+
1682
+ num_fields = DBFGetFieldCount( hDBFHandle );
1683
+ num_records = DBFGetRecordCount(hDBFHandle);
1684
+ field_names = malloc(num_fields*sizeof(char*));
1685
+ types = (DBFFieldType *)malloc(num_fields*sizeof(int));
1686
+ widths = malloc(num_fields*sizeof(int));
1687
+ precisions = malloc(num_fields*sizeof(int));
1688
+ if (readshape == 1)
1689
+ {
1690
+ col_names = malloc((num_fields+2) * sizeof(char) * MAXFIELDNAMELEN);
1691
+ }
1692
+ { //for dbf only, we do not need to allocate slot for the_geom
1693
+ col_names = malloc((num_fields+1) * sizeof(char) * MAXFIELDNAMELEN);
1694
+ }
1695
+ strcpy(col_names, "(" );
1696
+
1697
+ /*fprintf(stderr, "Number of fields from DBF: %d\n", num_fields); */
1698
+ for(j=0;j<num_fields;j++)
1699
+ {
1700
+ type = DBFGetFieldInfo(hDBFHandle, j, name, &field_width, &field_precision);
1701
+
1702
+ /*fprintf(stderr, "Field %d (%s) width/decimals: %d/%d\n", j, name, field_width, field_precision); */
1703
+ types[j] = type;
1704
+ widths[j] = field_width;
1705
+ precisions[j] = field_precision;
1706
+
1707
+ #ifdef HAVE_ICONV
1708
+ if ( encoding )
1709
+ {
1710
+ utf8str = utf8(encoding, name);
1711
+ if ( ! utf8str ) exit(1);
1712
+ strcpy(name, utf8str);
1713
+ free(utf8str);
1714
+ }
1715
+ #endif
1716
+
1717
+
1718
+ /*
1719
+ * Make field names lowercase unless asked to
1720
+ * keep identifiers case.
1721
+ */
1722
+ if ( ! quoteidentifiers ) LowerCase(name);
1723
+
1724
+ /*
1725
+ * Escape names starting with the
1726
+ * escape char (_), those named 'gid'
1727
+ * or after pgsql reserved attribute names
1728
+ */
1729
+ if( name[0]=='_' ||
1730
+ ! strcmp(name,"gid") ||
1731
+ ! strcmp(name, "tableoid") ||
1732
+ ! strcmp(name, "cmax") ||
1733
+ ! strcmp(name, "xmax") ||
1734
+ ! strcmp(name, "cmin") ||
1735
+ ! strcmp(name, "primary") ||
1736
+ ! strcmp(name, "oid") ||
1737
+ ! strcmp(name, "ctid") )
1738
+ {
1739
+ strcpy(name2+2, name);
1740
+ name2[0] = '_';
1741
+ name2[1] = '_';
1742
+ strcpy(name, name2);
1743
+ }
1744
+
1745
+ /* Avoid duplicating field names */
1746
+ for(z=0; z < j ; z++){
1747
+ if(strcmp(field_names[z],name)==0){
1748
+ strcat(name,"__");
1749
+ sprintf(name+strlen(name),"%i",j);
1750
+ break;
1751
+ }
1752
+ }
1753
+
1754
+ field_names[j] = malloc (strlen(name)+1);
1755
+ strcpy(field_names[j], name);
1756
+
1757
+ /*sprintf(col_names, "%s\"%s\",", col_names, name);*/
1758
+ strcat(col_names, "\"");
1759
+ strcat(col_names, name);
1760
+ if (readshape == 1 || j < (num_fields - 1)){
1761
+ //don't include last comma if its the last field and no geometry field will follow
1762
+ strcat(col_names, "\",");
1763
+ }
1764
+ else {
1765
+ strcat(col_names, "\"");
1766
+ }
1767
+ }
1768
+ /*sprintf(col_names, "%s\"%s\")", col_names, geom);*/
1769
+ if (readshape == 1){
1770
+ strcat(col_names, geom);
1771
+ }
1772
+ strcat(col_names, ")");
1773
+ }
1774
+
1775
+ #ifdef HAVE_ICONV
1776
+
1777
+ char *
1778
+ utf8 (const char *fromcode, char *inputbuf)
1779
+ {
1780
+ iconv_t cd;
1781
+ char *outputptr;
1782
+ char *outputbuf;
1783
+ size_t outbytesleft;
1784
+ size_t inbytesleft;
1785
+
1786
+ inbytesleft = strlen (inputbuf);
1787
+
1788
+ cd = iconv_open ("UTF-8", fromcode);
1789
+ if (cd == (iconv_t) - 1)
1790
+ {
1791
+ fprintf(stderr, "utf8: iconv_open: %s\n", strerror (errno));
1792
+ return NULL;
1793
+ }
1794
+
1795
+ outbytesleft = inbytesleft*3+1; /* UTF8 string can be 3 times larger */
1796
+ /* then local string */
1797
+ outputbuf = (char *) malloc (outbytesleft);
1798
+ if (!outputbuf)
1799
+ {
1800
+ fprintf(stderr, "utf8: malloc: %s\n", strerror (errno));
1801
+ return NULL;
1802
+ }
1803
+ memset (outputbuf, 0, outbytesleft);
1804
+ outputptr = outputbuf;
1805
+
1806
+ if (-1==iconv(cd, &inputbuf, &inbytesleft, &outputptr, &outbytesleft))
1807
+ {
1808
+ fprintf(stderr, "utf8: %s", strerror (errno));
1809
+ return NULL;
1810
+ }
1811
+
1812
+ iconv_close (cd);
1813
+
1814
+ return outputbuf;
1815
+ }
1816
+
1817
+ #endif /* defined HAVE_ICONV */
1818
+
1819
+ /**********************************************************************
1820
+ * $Log$
1821
+ * Revision 1.109 2008/04/09 14:12:17 robe
1822
+ * - Added support to load dbf-only files
1823
+ *
1824
+ * Revision 1.108 2006/06/16 14:12:17 strk
1825
+ * - BUGFIX in pgsql2shp successful return code.
1826
+ * - BUGFIX in shp2pgsql handling of MultiLine WKT.
1827
+ *
1828
+ * Revision 1.107 2006/04/18 09:16:26 strk
1829
+ * Substituted bzero() use with memset()
1830
+ *
1831
+ * Revision 1.106 2006/01/16 10:42:58 strk
1832
+ * Added support for Bool and Date DBF<=>PGIS mapping
1833
+ *
1834
+ * Revision 1.105 2006/01/09 16:40:16 strk
1835
+ * ISO C90 comments, signedness mismatch fixes
1836
+ *
1837
+ * Revision 1.104 2005/11/01 09:25:47 strk
1838
+ * Reworked NULL geometries handling code letting user specify policy (insert,skip,abort). Insert is the default.
1839
+ *
1840
+ * Revision 1.103 2005/10/24 15:54:22 strk
1841
+ * fixed wrong assumption about maximum size of integer attributes (width is maximum size of text representation)
1842
+ *
1843
+ * Revision 1.102 2005/10/24 11:30:59 strk
1844
+ *
1845
+ * Fixed a bug in string attributes handling truncating values of maximum
1846
+ * allowed length, curtesy of Lars Roessiger.
1847
+ * Reworked integer attributes handling to be stricter in dbf->sql mapping
1848
+ * and to allow for big int8 values in sql->dbf conversion
1849
+ *
1850
+ * Revision 1.101 2005/10/21 11:33:55 strk
1851
+ * Applied patch by Lars Roessiger handling numerical values with a trailing decima
1852
+ * l dot
1853
+ *
1854
+ * Revision 1.100 2005/10/13 13:40:20 strk
1855
+ * Fixed return code from shp2pgsql
1856
+ *
1857
+ * Revision 1.99 2005/10/03 18:08:55 strk
1858
+ * Stricter string attributes lenght handling. DBF header will be used
1859
+ * to set varchar maxlenght, (var)char typmod will be used to set DBF header
1860
+ * len.
1861
+ *
1862
+ * Revision 1.98 2005/10/03 07:45:58 strk
1863
+ * Issued a warning when -W is specified and no UTF8 support has been compiled in.
1864
+ *
1865
+ * Revision 1.97 2005/09/30 08:59:29 strk
1866
+ * Fixed release of stack memory occurring when shp2pgsql is compiled with USE_ICONV defined, an attribute value needs to be escaped and no -W is used
1867
+ *
1868
+ * Revision 1.96 2005/08/29 22:36:25 strk
1869
+ * Removed premature object destruction in InsertLineString{WKT,} causing segfault
1870
+ *
1871
+ * Revision 1.95 2005/08/29 11:48:33 strk
1872
+ * Fixed sprintf() calls to avoid overlapping memory,
1873
+ * reworked not-null objects existance check to reduce startup costs.
1874
+ *
1875
+ * Revision 1.94 2005/07/27 02:47:14 strk
1876
+ * Support for multibyte field names in loader
1877
+ *
1878
+ * Revision 1.93 2005/07/27 02:35:50 strk
1879
+ * Minor cleanups in loader
1880
+ *
1881
+ * Revision 1.92 2005/07/27 02:07:01 strk
1882
+ * Fixed handling of POINT types as WKT (-w) in loader
1883
+ *
1884
+ * Revision 1.91 2005/07/04 09:47:03 strk
1885
+ * Added conservative iconv detection code
1886
+ *
1887
+ * Revision 1.90 2005/06/16 17:55:58 strk
1888
+ * Added -I switch for GiST index creation in loader
1889
+ *
1890
+ * Revision 1.89 2005/04/21 09:08:34 strk
1891
+ * Applied patch from Ron Mayer fixing a segfault in string escaper funx
1892
+ *
1893
+ * Revision 1.88 2005/04/14 12:58:59 strk
1894
+ * Applied patch by Gino Lucrezi fixing bug in string escaping code.
1895
+ *
1896
+ * Revision 1.87 2005/04/06 14:16:43 strk
1897
+ * Removed manual update of gid field.
1898
+ *
1899
+ * Revision 1.86 2005/04/06 14:02:08 mschaber
1900
+ * added -p option (prepare mode) that spits out the table schema without
1901
+ * inserting any data.
1902
+ *
1903
+ * Revision 1.85 2005/04/06 10:46:10 strk
1904
+ * Bugfix in -w (hwgeom) handling of ZM shapefiles.
1905
+ * Big reorganizzation of code to easy maintainance.
1906
+ *
1907
+ * Revision 1.84 2005/04/04 20:51:26 strk
1908
+ * Added -w flag to output old (WKT/HWGEOM) sql.
1909
+ *
1910
+ * Revision 1.83 2005/03/15 12:24:40 strk
1911
+ * hole-in-ring detector made more readable
1912
+ *
1913
+ * Revision 1.82 2005/03/14 22:02:31 strk
1914
+ * Fixed holes handling.
1915
+ *
1916
+ * Revision 1.81 2005/03/08 11:06:33 strk
1917
+ * modernized old-style parameter declarations
1918
+ *
1919
+ * Revision 1.80 2005/03/04 14:48:22 strk
1920
+ * Applied patch from Jonne Savolainen fixing multilines handling
1921
+ *
1922
+ * Revision 1.79 2005/01/31 22:15:22 strk
1923
+ * Added maintainer notice, to reduce Jeff-strk mail bounces
1924
+ *
1925
+ * Revision 1.78 2005/01/17 09:21:13 strk
1926
+ * Added one more bytes for terminating NULL in utf8 encoder
1927
+ *
1928
+ * Revision 1.77 2005/01/16 16:50:01 strk
1929
+ * String escaping algorithm made simpler and more robust.
1930
+ * Removed escaped strings leaking.
1931
+ * Fixed UTF8 encoder to allocate enough space for 3bytes chars strings.
1932
+ *
1933
+ * Revision 1.76 2005/01/12 17:03:20 strk
1934
+ * Added optional UTF8 output support as suggested by IIDA Tetsushi
1935
+ *
1936
+ * Revision 1.75 2004/11/15 10:51:35 strk
1937
+ * Fixed a bug in PIP invocation, added some debugging lines.
1938
+ *
1939
+ * Revision 1.74 2004/10/17 13:25:44 strk
1940
+ * removed USE_WKB partially-used define
1941
+ *
1942
+ * Revision 1.73 2004/10/17 13:24:44 strk
1943
+ * HEXWKB polygon
1944
+ *
1945
+ * Revision 1.72 2004/10/17 12:59:12 strk
1946
+ * HEXWKB multiline output
1947
+ *
1948
+ * Revision 1.71 2004/10/17 12:26:02 strk
1949
+ * Point and MultiPoint loaded using HEXWKB.
1950
+ *
1951
+ * Revision 1.70 2004/10/15 22:01:35 strk
1952
+ * Initial WKB functionalities
1953
+ *
1954
+ * Revision 1.69 2004/10/07 21:52:28 strk
1955
+ * Lots of rewriting/cleanup. TypeM/TypeZ supports.
1956
+ *
1957
+ * Revision 1.68 2004/10/07 06:54:24 strk
1958
+ * cleanups
1959
+ *
1960
+ * Revision 1.67 2004/10/06 10:11:16 strk
1961
+ * Other separator fixes
1962
+ *
1963
+ * Revision 1.66 2004/10/06 09:40:27 strk
1964
+ * Handled 0-DBF-attributes corner case.
1965
+ *
1966
+ * Revision 1.65 2004/09/20 17:13:31 strk
1967
+ * changed comments to better show shape type handling
1968
+ *
1969
+ * Revision 1.64 2004/08/20 08:14:37 strk
1970
+ * Whole output wrapped in transaction blocks.
1971
+ * Drops are out of transaction, and multiple transactions are used
1972
+ * for INSERT mode.
1973
+ *
1974
+ **********************************************************************/