geo_coder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ **********************************************************************/