~ubuntu-branches/ubuntu/trusty/postgis/trusty-security

« back to all changes in this revision

Viewing changes to loader/shp2pgsql.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2009-12-11 13:10:34 UTC
  • mfrom: (1.1.9 upstream) (5.2.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20091211131034-wmsz69wxvt95pe5r
Tags: 1.4.0-2
* Upload to unstable.
* Better parameterized debian/rules against postgis $(VERSION).
* Added dblatex and libcunit1-dev among build-deps.
* Added postgis_comments.sql to contrib/ SQL templates.
* Dropping 8.3 support, no more supported for squeeze.
  (closes: #559587)
* Do not stop on error in postrm if the target dir does not exist.
  (closes: #560409)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**********************************************************************
2
 
 * $Id: shp2pgsql.c 3560 2009-01-22 18:15:42Z robe $
 
2
 * $Id: shp2pgsql.c 4204 2009-06-24 11:18:29Z mcayland $
3
3
 *
4
4
 * PostGIS - Spatial Types for PostgreSQL
5
5
 * http://postgis.refractions.net
6
6
 * Copyright 2001-2003 Refractions Research Inc.
7
7
 *
8
8
 * This is free software; you can redistribute and/or modify it under
9
 
 * the terms of hte 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
 
9
 * the terms of the GNU General Public Licence. See the COPYING file.
 
10
 */
 
11
 
 
12
 /** *********************************************************************
 
13
 * \file Using shapelib 1.2.8, this program reads in shape files and
 
14
 *      processes it's contents into a Insert statements which can be
 
15
 *      easily piped into a database frontend.
 
16
 *      Specifically designed to insert type 'geometry' (a custom
 
17
 *      written PostgreSQL type) for the shape files and PostgreSQL
 
18
 *      standard types for all attributes of the entity.
 
19
 *
 
20
 *      Original Author: Jeff Lounsbury, jeffloun@refractions.net
 
21
 *
 
22
 *      Maintainer: Sandro Santilli, strk@refractions.net
22
23
 *
23
24
 **********************************************************************/
24
25
 
25
 
#include "../config.h"
 
26
#include "../postgis_config.h"
26
27
#include "shapefil.h"
27
28
#include <stdio.h>
28
29
#include <string.h>
33
34
#include <unistd.h>
34
35
#include <errno.h>
35
36
#include "getopt.h"
36
 
#ifdef HAVE_ICONV_H
 
37
#ifdef HAVE_ICONV
37
38
#include <iconv.h>
38
39
#endif
39
40
 
 
41
#include "../liblwgeom/liblwgeom.h"
 
42
 
40
43
 
41
44
#define POINTTYPE       1
42
45
#define LINETYPE        2
49
52
#define WKBZOFFSET 0x80000000
50
53
#define WKBMOFFSET 0x40000000
51
54
 
52
 
/*#define DEBUG 1 */
53
 
 
54
55
typedef struct {double x, y, z, m;} Point;
55
56
 
56
57
typedef struct Ring {
60
61
        unsigned int linked;    /* number of "next" rings */
61
62
} Ring;
62
63
 
63
 
/* Values for null_policy global */
 
64
/** @brief Values for null_policy global */
64
65
enum {
65
66
        insert_null,
66
67
        skip_null,
82
83
unsigned int wkbtype;
83
84
char    *shp_file = NULL;
84
85
int     hwgeom = 0; /* old (hwgeom) mode */
85
 
#ifdef USE_ICONV
 
86
#ifdef HAVE_ICONV
86
87
char    *encoding=NULL;
87
88
#endif
88
89
int null_policy = insert_null;
101
102
 
102
103
/* Prototypes */
103
104
int Insert_attributes(DBFHandle hDBFHandle, int row);
104
 
char *make_good_string(char *str);
105
 
char *protect_quotes_string(char *str);
 
105
char *escape_copy_string(char *str);
 
106
char *escape_insert_string(char *str);
106
107
int PIP( Point P, Point* V, int n );
107
108
void *safe_malloc(size_t size);
108
109
void CreateTable(void);
109
110
void CreateIndex(void);
110
111
void usage(char *me, int exitcode, FILE* out);
111
112
void InsertPoint(void);
112
 
void InsertPointWKT(void);
113
113
void InsertMultiPoint(void);
114
114
void InsertPolygon(void);
115
 
void InsertPolygonWKT(void);
116
 
void InsertLineString(int id);
117
 
void InsertLineStringWKT(int id);
 
115
void InsertLineString(void);
 
116
void OutputGeometry(char *geometry);
118
117
int ParseCmdline(int ARGC, char **ARGV);
119
118
void SetPgType(void);
120
119
char *dump_ring(Ring *ring);
121
 
#ifdef USE_ICONV
 
120
#ifdef HAVE_ICONV
122
121
char *utf8(const char *fromcode, char *inputbuf);
123
122
#endif
124
123
int FindPolygons(SHPObject *obj, Ring ***Out);
130
129
void LowerCase(char *s);
131
130
void Cleanup(void);
132
131
 
133
 
 
134
 
/* WKB */
135
 
static char getEndianByte(void);
136
 
static void print_wkb_bytes(unsigned char* ptr, unsigned int cnt, size_t size);
137
 
static void print_wkb_byte(unsigned char val);
138
 
static void print_wkb_int(int val);
139
 
static void print_wkb_double(double val);
140
 
 
141
132
static char rcsid[] =
142
 
  "$Id: shp2pgsql.c 3560 2009-01-22 18:15:42Z robe $";
 
133
  "$Id: shp2pgsql.c 4204 2009-06-24 11:18:29Z mcayland $";
 
134
 
 
135
 
 
136
/* liblwgeom allocator callback - install the defaults (malloc/free/stdout/stderr) */
 
137
void lwgeom_init_allocators()
 
138
{
 
139
        lwgeom_install_default_allocators();
 
140
}
 
141
 
143
142
 
144
143
void *safe_malloc(size_t size)
145
144
{
154
153
#define malloc(x) safe_malloc(x)
155
154
 
156
155
 
 
156
/**
 
157
 * @brief Escape input string suitable for COPY
 
158
 */
 
159
 
157
160
char *
158
 
make_good_string(char *str)
 
161
escape_copy_string(char *str)
159
162
{
160
163
        /*
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
 
164
         * Escape the following characters by adding a preceding backslash
 
165
         *      tab, backslash, cr, lf
 
166
         *
 
167
         * 1. find # of escaped characters
 
168
         * 2. make new string
 
169
         *
167
170
         */
168
171
 
169
172
        char *result;
170
173
        char *ptr, *optr;
171
174
        int toescape = 0;
172
175
        size_t size;
173
 
#ifdef USE_ICONV
 
176
#ifdef HAVE_ICONV
174
177
        char *utf8str=NULL;
175
178
 
176
179
        if ( encoding )
177
180
        {
178
181
                utf8str=utf8(encoding, str);
179
182
                if ( ! utf8str ) exit(1);
180
 
                str = utf8str; 
 
183
                str = utf8str;
181
184
        }
182
185
#endif
183
186
 
184
187
        ptr = str;
185
188
 
186
189
        while (*ptr) {
187
 
                if ( *ptr == '\t' || *ptr == '\\' ) toescape++;
 
190
                if ( *ptr == '\t' || *ptr == '\\' ||
 
191
                        *ptr == '\n' || *ptr == '\r' )
 
192
                                toescape++;
188
193
                ptr++;
189
194
        }
190
195
 
197
202
        optr=result;
198
203
        ptr=str;
199
204
        while (*ptr) {
200
 
                if ( *ptr == '\t' || *ptr == '\\' ) *optr++='\\';
201
 
                *optr++=*ptr++;
 
205
                if ( *ptr == '\t' || *ptr == '\\' ||
 
206
                        *ptr == '\n' || *ptr == '\r' )
 
207
                                *optr++='\\';
 
208
                                *optr++=*ptr++;
202
209
        }
203
210
        *optr='\0';
204
211
 
205
 
#ifdef USE_ICONV
 
212
#ifdef HAVE_ICONV
206
213
        if ( encoding ) free(str);
207
214
#endif
208
215
 
209
216
        return result;
210
 
        
 
217
 
211
218
}
212
219
 
213
220
char *
214
 
protect_quotes_string(char *str)
 
221
escape_insert_string(char *str)
215
222
{
216
223
        /*
217
 
         * find all quotes and make them \quotes
218
 
         * find all '\' and make them '\\'
219
 
         *       
 
224
         * Escape single quotes by adding a preceding single quote
 
225
         *
220
226
         * 1. find # of characters
221
 
         * 2. make new string 
 
227
         * 2. make new string
222
228
         */
223
229
 
224
230
        char    *result;
225
231
        char    *ptr, *optr;
226
232
        int     toescape = 0;
227
233
        size_t size;
228
 
#ifdef USE_ICONV
 
234
#ifdef HAVE_ICONV
229
235
        char *utf8str=NULL;
230
236
 
231
237
        if ( encoding )
232
238
        {
233
239
                utf8str=utf8(encoding, str);
234
240
                if ( ! utf8str ) exit(1);
235
 
                str = utf8str; 
 
241
                str = utf8str;
236
242
        }
237
243
#endif
238
244
 
239
245
        ptr = str;
240
246
 
241
247
        while (*ptr) {
242
 
                if ( *ptr == '\'' || *ptr == '\\' ) toescape++;
 
248
                if ( *ptr == '\'' ) toescape++;
243
249
                ptr++;
244
250
        }
245
251
 
246
252
        if (toescape == 0) return str;
247
 
        
 
253
 
248
254
        size = ptr-str+toescape+1;
249
255
 
250
256
        result = calloc(1, size);
252
258
        optr=result;
253
259
        ptr=str;
254
260
        while (*ptr) {
255
 
                if ( *ptr == '\\' ) *optr++='\\';
256
 
                if ( *ptr == '\'') *optr++='\'';
 
261
                                if ( *ptr == '\'') *optr++='\'';
257
262
                *optr++=*ptr++;
258
263
        }
259
264
        *optr='\0';
260
265
 
261
 
#ifdef USE_ICONV
 
266
#ifdef HAVE_ICONV
262
267
        if ( encoding ) free(str);
263
268
#endif
264
269
 
267
272
 
268
273
 
269
274
 
270
 
/*
271
 
 * PIP(): crossing number test for a point in a polygon
 
275
/**
 
276
 * @brief PIP(): crossing number test for a point in a polygon
272
277
 *      input:   P = a point,
273
278
 *               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
274
 
 *      returns: 0 = outside, 1 = inside
 
279
 * @return   0 = outside, 1 = inside
275
280
 */
276
281
int
277
282
PIP( Point P, Point* V, int n )
279
284
        int cn = 0;    /* the crossing number counter */
280
285
        int i;
281
286
 
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) */
 
287
        /* loop through all edges of the polygon */
 
288
        for (i=0; i<n-1; i++) {    /* edge from V[i] to V[i+1] */
 
289
           if (((V[i].y <= P.y) && (V[i+1].y > P.y))    /* an upward crossing */
 
290
                || ((V[i].y > P.y) && (V[i+1].y <= P.y))) { /* a downward crossing */
 
291
                        double vt = (float)(P.y - V[i].y) / (V[i+1].y - V[i].y);
 
292
                        if (P.x < V[i].x + vt * (V[i+1].x - V[i].x)) /* P.x < intersect */
 
293
                                ++cn;   /* a valid crossing of y=P.y right of P.x */
 
294
                }
 
295
        }
 
296
        return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
292
297
 
293
298
}
294
299
 
295
300
 
296
 
/*Insert the attributes from the correct row of dbf file */
 
301
/**
 
302
 * @brief Insert the attributes from the correct row of dbf file
 
303
 */
297
304
 
298
305
int
299
306
Insert_attributes(DBFHandle hDBFHandle, int row)
305
312
   num_fields = DBFGetFieldCount( hDBFHandle );
306
313
   for( i = 0; i < num_fields; i++ )
307
314
   {
308
 
      if(DBFIsAttributeNULL( hDBFHandle, row, i))
309
 
      {
 
315
          if(DBFIsAttributeNULL( hDBFHandle, row, i))
 
316
          {
310
317
 
311
318
                if(dump_format)
312
319
                {
320
327
                }
321
328
          }
322
329
 
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
 
 
 
330
          else /* Attribute NOT NULL */
 
331
          {
 
332
                 switch (types[i])
 
333
                 {
 
334
                        case FTInteger:
 
335
                        case FTDouble:
 
336
                           if ( -1 == snprintf(val, 1024, "%s",
 
337
                                         DBFReadStringAttribute(hDBFHandle, row, i)) )
 
338
                           {
 
339
                                  fprintf(stderr, "Warning: field %d name truncated\n", i);
 
340
                                  val[1023] = '\0';
 
341
                           }
 
342
                   /* pg_atoi() does not do this */
 
343
                   if ( val[0] == '\0' ) { val[0] = '0'; val[1] = '\0'; }
 
344
                   if ( val[strlen(val)-1] == '.' ) val[strlen(val)-1] = '\0';
 
345
                           break;
 
346
 
 
347
                        case FTString:
 
348
                        case FTLogical:
 
349
                case FTDate:
 
350
                           if ( -1 == snprintf(val, 1024, "%s",
 
351
                                         DBFReadStringAttribute(hDBFHandle, row, i)) )
 
352
                           {
 
353
                                  fprintf(stderr, "Warning: field %d name truncated\n", i);
 
354
                                  val[1023] = '\0';
 
355
                           }
 
356
                           break;
 
357
 
 
358
                        default:
 
359
                           fprintf(stderr,
 
360
                                  "Error: field %d has invalid or unknown field type (%d)\n",
 
361
                                  i, types[i]);
 
362
                           exit(1);
 
363
                 }
 
364
 
358
365
                        if (dump_format) {
359
 
                                escval = make_good_string(val);
 
366
                                escval = escape_copy_string(val);
360
367
                                printf("%s", escval);
361
368
                                //printf("\t");
362
369
                        } else {
363
 
                                escval = protect_quotes_string(val);
 
370
                                escval = escape_insert_string(val);
364
371
                                printf("'%s'", escval);
365
372
                                //printf(",");
366
373
                        }
370
377
                if(readshape == 1 || i < (num_fields - 1))
371
378
                {
372
379
                        if (dump_format){
373
 
                           printf("\t");   
 
380
                           printf("\t");
374
381
                        }
375
382
                        else {
376
 
                                printf(",");   
 
383
                                printf(",");
377
384
                        }
378
385
                }
379
386
        }
383
390
 
384
391
 
385
392
 
386
 
/*
387
 
 * main()     
388
 
 * see description at the top of this file
 
393
/**
 
394
 * main()
 
395
 * @brief see description at the top of this file
389
396
 */
390
397
int
391
398
main (int ARGC, char **ARGV)
401
408
         */
402
409
        OpenShape();
403
410
 
404
 
        if (readshape == 1){    
 
411
        if (readshape == 1){
405
412
                /*
406
413
                 * Compute output geometry type
407
414
                 */
408
 
                 
 
415
 
409
416
                SetPgType();
410
 
        
 
417
 
411
418
                fprintf(stderr, "Shapefile type: %s\n", SHPTypeName(shpfiletype));
412
419
                fprintf(stderr, "Postgis type: %s[%d]\n", pgtype, pgdims);
413
420
        }
414
421
 
415
 
#ifdef USE_ICONV
 
422
#ifdef HAVE_ICONV
416
423
        if ( encoding )
417
424
        {
418
425
                printf("SET CLIENT_ENCODING TO UTF8;\n");
419
426
        }
420
 
#endif /* defined USE_ICONV */
 
427
#endif /* defined HAVE_ICONV */
 
428
 
 
429
        /*
 
430
         * Use SQL-standard string escaping rather than PostgreSQL standard
 
431
         */
 
432
        printf("SET STANDARD_CONFORMING_STRINGS TO ON;\n");
421
433
 
422
434
        /*
423
435
         * Drop table if requested
450
462
        printf("END;\n"); /* End the last transaction */
451
463
 
452
464
 
453
 
        return 0; 
 
465
        return 0;
454
466
}/*end main() */
455
467
 
456
468
void
475
487
        if (readshape == 1)
476
488
        {
477
489
                hSHPHandle = SHPOpen( shp_file, "rb" );
478
 
                if (hSHPHandle == NULL) 
 
490
                if (hSHPHandle == NULL)
479
491
                {
480
492
                        fprintf(stderr, "%s: shape (.shp) or index files (.shx) can not be opened, will just import attribute data.\n", shp_file);
481
493
                        readshape = 0;
482
494
                }
483
495
        }
484
 
        
 
496
 
485
497
        hDBFHandle = DBFOpen( shp_file, "rb" );
486
498
        if ((hSHPHandle == NULL && readshape == 1) || hDBFHandle == NULL){
487
499
                fprintf(stderr, "%s: dbf file (.dbf) can not be opened.\n",shp_file);
488
500
                exit(-1);
489
501
        }
490
 
        
 
502
 
491
503
        if (readshape == 1)
492
504
        {
493
505
                SHPGetInfo(hSHPHandle, &num_entities, &shpfiletype, NULL, NULL);
494
 
        
 
506
 
495
507
                if ( null_policy == abort_on_null )
496
508
                {
497
509
                        for (j=0; j<num_entities; j++)
524
536
        int field_precision, field_width;
525
537
        DBFFieldType type = -1;
526
538
 
527
 
        /* 
 
539
        /*
528
540
         * Create a table for inserting the shapes into with appropriate
529
541
         * columns and types
530
542
         */
574
586
                        {
575
587
                                printf ("int8");
576
588
                        }
577
 
                        else 
 
589
                        else
578
590
                        {
579
591
                                printf("numeric(%d,0)",
580
592
                                        field_width);
622
634
void
623
635
CreateIndex(void)
624
636
{
625
 
        /* 
 
637
        /*
626
638
         * Create gist index
627
639
         */
628
640
        if ( schema )
655
667
 
656
668
 
657
669
        /**************************************************************
658
 
         * 
 
670
         *
659
671
         *   MAIN SHAPE OBJECTS SCAN
660
 
         * 
 
672
         *
661
673
         **************************************************************/
662
674
        for (j=0; j<num_entities; j++)
663
675
        {
673
685
                trans++;
674
686
                /* transaction stuff done */
675
687
 
676
 
                /*skip the record if it has been deleted*/
 
688
                /* skip the record if it has been deleted */
677
689
                if(readshape != 1 && DBFReadDeleted(hDBFHandle, j)) {
678
 
                  continue; 
 
690
                        continue;
679
691
                }
680
692
 
681
 
 
682
 
                /*open the next object */
 
693
                /* open the next object */
683
694
                if (readshape == 1)
684
695
                {
685
696
                        obj = SHPReadObject(hSHPHandle,j);
688
699
                                fprintf(stderr, "Error reading shape object %d\n", j);
689
700
                                exit(1);
690
701
                        }
691
 
        
 
702
 
692
703
                        if ( null_policy == skip_null && obj->nVertices == 0 )
693
704
                        {
694
705
                                SHPDestroyObject(obj);
695
706
                                continue;
696
707
                        }
697
708
                }
698
 
                
 
709
 
699
710
                if (!dump_format)
700
711
                {
701
712
                        if ( schema )
702
713
                        {
703
714
                                printf("INSERT INTO \"%s\".\"%s\" %s VALUES (",
704
 
                                        schema, table, col_names);
 
715
                                                                                schema, table, col_names);
705
716
                        }
706
717
                        else
707
718
                        {
708
 
                                printf("INSERT INTO \"%s\" %s VALUES (",
 
719
                                printf("INSERT INTO \"%s\" %s VALUES (",
709
720
                                        table, col_names);
710
721
                        }
711
722
                }
712
723
                Insert_attributes(hDBFHandle,j);
713
724
 
714
 
                if (readshape == 1) 
 
725
                if (readshape == 1)
715
726
                {
716
727
                        /* ---------- NULL SHAPE ----------------- */
717
728
                        if (obj->nVertices == 0)
718
729
                        {
719
730
                                if (dump_format) printf("\\N\n");
720
731
                                else printf("NULL);\n");
721
 
                                SHPDestroyObject(obj);  
 
732
                                SHPDestroyObject(obj);
722
733
                                continue;
723
734
                        }
724
 
        
 
735
 
725
736
                        switch (obj->nSHPType)
726
737
                        {
727
738
                                case SHPT_POLYGON:
728
739
                                case SHPT_POLYGONM:
729
740
                                case SHPT_POLYGONZ:
730
 
                                        if ( hwgeom ) InsertPolygonWKT();
731
 
                                        else InsertPolygon();
 
741
                                        InsertPolygon();
732
742
                                        break;
733
 
        
 
743
 
734
744
                                case SHPT_POINT:
735
745
                                case SHPT_POINTM:
736
746
                                case SHPT_POINTZ:
737
 
                                        if ( hwgeom ) InsertPointWKT();
738
 
                                        else InsertPoint();
739
 
                                        break;
740
 
        
741
747
                                case SHPT_MULTIPOINT:
742
748
                                case SHPT_MULTIPOINTM:
743
749
                                case SHPT_MULTIPOINTZ:
744
 
                                        if ( hwgeom ) InsertPointWKT();
745
 
                                        else InsertMultiPoint();
 
750
                                        InsertPoint();
746
751
                                        break;
747
 
        
 
752
 
748
753
                                case SHPT_ARC:
749
754
                                case SHPT_ARCM:
750
755
                                case SHPT_ARCZ:
751
 
                                        if ( hwgeom ) InsertLineStringWKT(j);
752
 
                                        else InsertLineString(j);
 
756
                                        InsertLineString();
753
757
                                        break;
754
 
        
 
758
 
755
759
                                default:
756
760
                                        printf ("\n\n**** Type is NOT SUPPORTED, type id = %d ****\n\n",
757
761
                                                obj->nSHPType);
758
762
                                        break;
759
 
        
 
763
 
760
764
                        }
761
 
                        
762
 
                        SHPDestroyObject(obj);  
 
765
 
 
766
                        SHPDestroyObject(obj);
763
767
                }
764
 
                else 
 
768
                else
765
769
                        if (dump_format){ /*close for dbf only dump format */
766
770
                                printf("\n");
767
771
                        }
768
772
                        else { /*close for dbf only sql insert format */
769
773
                                printf(");\n");
770
774
                        }
771
 
        
 
775
 
772
776
        } /* END of MAIN SHAPE OBJECT LOOP */
773
 
        
 
777
 
774
778
 
775
779
 
776
780
        if ((dump_format) ) {
777
781
                printf("\\.\n");
778
782
 
779
 
        } 
 
783
        }
780
784
}
781
785
 
782
786
void
783
787
usage(char *me, int exitcode, FILE* out)
784
788
{
785
 
    fprintf(out, "RCSID: %s RELEASE: %s\n", rcsid, POSTGIS_VERSION);
 
789
        fprintf(out, "RCSID: %s RELEASE: %s\n", rcsid, POSTGIS_VERSION);
786
790
        fprintf(out, "USAGE: %s [<options>] <shapefile> [<schema>.]<table>\n", me);
787
791
        fprintf(out, "OPTIONS:\n");
788
792
        fprintf(out, "  -s <srid>  Set the SRID field. If not specified it defaults to -1.\n");
793
797
        fprintf(out, "          exactly the same table schema.\n");
794
798
        fprintf(out, "      -c  Creates a new table and populates it, this is the\n");
795
799
        fprintf(out, "          default if you do not specify any options.\n");
796
 
        fprintf(out, "      -p  Prepare mode, only creates the table.\n");
 
800
        fprintf(out, "      -p  Prepare mode, only creates the table.\n");
797
801
        fprintf(out, "  -g <geometry_column> Specify the name of the geometry column\n");
798
802
        fprintf(out, "     (mostly useful in append mode).\n");
799
803
        fprintf(out, "  -D  Use postgresql dump format (defaults to sql insert statments.\n");
802
806
        fprintf(out, "  -I  Create a GiST index on the geometry column.\n");
803
807
        fprintf(out, "  -S  Generate simple geometries instead of MULTI geometries.\n");
804
808
        fprintf(out, "  -w  Use wkt format (for postgis-0.x support - drops M - drifts coordinates).\n");
805
 
#ifdef USE_ICONV
 
809
#ifdef HAVE_ICONV
806
810
        fprintf(out, "  -W <encoding> Specify the character encoding of Shape's\n");
807
811
        fprintf(out, "     attribute column. (default : \"ASCII\")\n");
808
812
#endif
809
813
        fprintf(out, "  -N <policy> Specify NULL geometries handling policy (insert,skip,abort)\n");
810
814
        fprintf(out, "  -n  Only import DBF file.\n");
811
 
    fprintf(out, "  -? Display this help screen\n");
 
815
        fprintf(out, "  -? Display this help screen\n");
812
816
        exit (exitcode);
813
817
}
814
818
 
815
819
void
816
 
InsertLineString(int id)
817
 
{
818
 
        int pi; /* part index */
819
 
        unsigned int subtype = LINETYPE | (wkbtype&WKBZOFFSET) | 
820
 
                (wkbtype&WKBMOFFSET);
821
 
 
822
 
        /* Invalid (MULTI)Linestring */
823
 
        if ( obj->nVertices < 2 )
824
 
        {
825
 
                fprintf(stderr,
826
 
                        "MULTILINESTRING %d as %d vertices, set to NULL\n",
827
 
                        id, obj->nVertices);
828
 
                if (dump_format) printf("\\N\n");
829
 
                else printf("NULL);\n");
830
 
 
831
 
                return;
832
 
        }
833
 
 
834
 
        if (!dump_format) printf("'");
835
 
        if ( sr_id > 0 ) printf("SRID=%d;", sr_id);
836
 
 
837
 
        if (simple_geometries==0) // We write MULTI geometries, so generate Header 
838
 
        {
839
 
                print_wkb_byte(getEndianByte());
840
 
                print_wkb_int(wkbtype);
841
 
                print_wkb_int(obj->nParts); /* npolys */
842
 
        } 
843
 
        else if ((obj->nParts)!=1) // We write Non-MULTI geometries, but have several parts: 
844
 
        {
845
 
                fprintf(stderr, "We have a MultiLineString with %d parts, can't use -S switch!\n", obj->nParts);
846
 
                exit(1);                
847
 
        }
848
 
 
849
 
        for (pi=0; pi<obj->nParts; pi++)
850
 
        {
851
 
                int vi; /* vertex index */
852
 
                int vs; /* start vertex */
853
 
                int ve; /* end vertex */
854
 
 
855
 
                print_wkb_byte(getEndianByte());
856
 
                print_wkb_int(subtype);
857
 
 
858
 
                /* Set start and end vertexes */
859
 
                if ( pi==obj->nParts-1 ) ve = obj->nVertices;
860
 
                else ve = obj->panPartStart[pi+1];
861
 
                vs = obj->panPartStart[pi];
862
 
 
863
 
                print_wkb_int(ve-vs);
864
 
                for ( vi=vs; vi<ve; vi++)
865
 
                {
866
 
                        print_wkb_double(obj->padfX[vi]);
867
 
                        print_wkb_double(obj->padfY[vi]);
868
 
                        if ( wkbtype & WKBZOFFSET )
869
 
                                print_wkb_double(obj->padfZ[vi]);
870
 
                        if ( wkbtype & WKBMOFFSET )
871
 
                                print_wkb_double(obj->padfM[vi]);
872
 
                }
873
 
        }
874
 
 
875
 
        if (dump_format) printf("\n");
876
 
        else printf("');\n");
877
 
}
878
 
 
879
 
void
880
 
InsertLineStringWKT(int id)
881
 
{
882
 
        int pi; /* part index */
883
 
 
884
 
        /* Invalid (MULTI)Linestring */
885
 
        if ( obj->nVertices < 2 )
886
 
        {
887
 
                fprintf(stderr,
888
 
                        "MULTILINESTRING %d as %d vertices, set to NULL\n",
889
 
                        id, obj->nVertices);
890
 
                if (dump_format) printf("\\N\n");
891
 
                else printf("NULL);\n");
892
 
 
893
 
                return;
894
 
        }
895
 
 
896
 
        if (dump_format) printf("SRID=%d;",sr_id );
897
 
        else printf("GeometryFromText('");
898
 
        
899
 
        if (simple_geometries==0) // We write MULTI geometries, so generate Header 
900
 
        {
901
 
                printf("MULTILINESTRING(");
902
 
        }
903
 
        else if ((obj->nParts)==1)
904
 
        {
905
 
                printf("LINESTRING");
906
 
        }
907
 
        else // We write Non-MULTI geometries, but have several parts: 
 
820
InsertLineString()
 
821
{
 
822
        LWCOLLECTION *lwcollection;
 
823
 
 
824
        LWGEOM **lwmultilinestrings;
 
825
        uchar *serialized_lwgeom;
 
826
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
827
 
 
828
        DYNPTARRAY **dpas;
 
829
        POINT4D point4d;
 
830
 
 
831
        int dims = 0, hasz = 0, hasm = 0;
 
832
        int result;
 
833
        int u, v, start_vertex, end_vertex;
 
834
 
 
835
        /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
 
836
           the M coordinate */
 
837
        if (wkbtype & WKBZOFFSET) hasz = 1;
 
838
        if (!hwgeom)
 
839
                if (wkbtype & WKBMOFFSET) hasm = 1;
 
840
        TYPE_SETZM(dims, hasz, hasm);
 
841
 
 
842
        if (simple_geometries == 1 && obj->nParts > 1)
908
843
        {
909
844
                fprintf(stderr, "We have a Multilinestring with %d parts, can't use -S switch!\n", obj->nParts);
910
 
                exit(1);                
911
 
        } 
912
 
 
913
 
        for (pi=0; pi<obj->nParts; pi++)
 
845
                exit(1);
 
846
        }
 
847
 
 
848
        /* Allocate memory for our array of LWLINEs and our dynptarrays */
 
849
        lwmultilinestrings = malloc(sizeof(LWPOINT *) * obj->nParts);
 
850
        dpas = malloc(sizeof(DYNPTARRAY *) * obj->nParts);
 
851
 
 
852
        /* We need an array of pointers to each of our sub-geometries */
 
853
        for (u = 0; u < obj->nParts; u++)
914
854
        {
915
 
                int vi; /* vertex index */
916
 
                int vs; /* start vertex */
917
 
                int ve; /* end vertex */
918
 
 
919
 
                if (pi) printf(",");
920
 
                printf("(");
921
 
 
922
 
                /* Set start and end vertexes */
923
 
                if ( pi==obj->nParts-1 ) ve = obj->nVertices;
924
 
                else ve = obj->panPartStart[pi+1];
925
 
                vs = obj->panPartStart[pi];
926
 
 
927
 
                for ( vi=vs; vi<ve; vi++)
 
855
                /* Create a dynptarray containing the line points */
 
856
                dpas[u] = dynptarray_create(obj->nParts, dims);
 
857
 
 
858
                /* Set the start/end vertices depending upon whether this is
 
859
                a MULTILINESTRING or not */
 
860
                if ( u == obj->nParts-1 )
 
861
                        end_vertex = obj->nVertices;
 
862
                else
 
863
                        end_vertex = obj->panPartStart[u + 1];
 
864
 
 
865
                start_vertex = obj->panPartStart[u];
 
866
 
 
867
                for (v = start_vertex; v < end_vertex; v++)
928
868
                {
929
 
                        if ( vi > vs ) printf(",");
930
 
                        printf("%.15g %.15g",
931
 
                                obj->padfX[vi],
932
 
                                obj->padfY[vi]);
933
 
                        if ( wkbtype & WKBZOFFSET )
934
 
                                printf(" %.15g", obj->padfZ[vi]);
 
869
                        /* Generate the point */
 
870
                        point4d.x = obj->padfX[v];
 
871
                        point4d.y = obj->padfY[v];
 
872
 
 
873
                        if (wkbtype & WKBZOFFSET)
 
874
                                point4d.z = obj->padfZ[v];
 
875
                        if (wkbtype & WKBMOFFSET)
 
876
                                point4d.m = obj->padfM[v];
 
877
 
 
878
                        dynptarray_addPoint4d(dpas[u], &point4d, 0);
935
879
                }
936
880
 
937
 
                printf(")");
938
 
                                
939
 
        }
940
 
 
941
 
        if (simple_geometries==0) printf(")");
942
 
 
943
 
        if (dump_format) printf("\n");
944
 
        else printf("',%d) );\n",sr_id);
 
881
                /* Generate the LWLINE */
 
882
                lwmultilinestrings[u] = lwline_as_lwgeom(lwline_construct(sr_id, NULL, dpas[u]->pa));
 
883
        }
 
884
 
 
885
        /* If using MULTILINESTRINGs then generate the serialized collection, otherwise just a single LINESTRING */
 
886
        if (simple_geometries == 0)
 
887
        {
 
888
                lwcollection = lwcollection_construct(MULTILINETYPE, sr_id, NULL, obj->nParts, lwmultilinestrings);
 
889
                serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
 
890
        }
 
891
        else
 
892
        {
 
893
                serialized_lwgeom = lwgeom_serialize(lwmultilinestrings[0]);
 
894
        }
 
895
 
 
896
        if (!hwgeom)
 
897
                result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE, -1);
 
898
        else
 
899
                result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE);
 
900
 
 
901
        if (result)
 
902
        {
 
903
                fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
 
904
                exit(1);
 
905
        }
 
906
 
 
907
        OutputGeometry(lwg_unparser_result.wkoutput);
 
908
 
 
909
        /* Free all of the allocated items */
 
910
                lwfree(lwg_unparser_result.wkoutput);
 
911
                lwfree(serialized_lwgeom);
 
912
 
 
913
        for (u = 0; u < obj->nParts; u++)
 
914
        {
 
915
                        lwline_free(lwgeom_as_lwline(lwmultilinestrings[u]));
 
916
                        lwfree(dpas[u]);
 
917
        }
 
918
 
 
919
        lwfree(dpas);
 
920
        lwfree(lwmultilinestrings);
945
921
}
946
922
 
947
923
int
953
929
        int in_index=0;  /* Count of Inner rings */
954
930
        int pi; /* part index */
955
931
 
956
 
#ifdef DEBUG
 
932
#if POSTGIS_DEBUG_LEVEL > 0
957
933
        static int call = -1;
958
934
        call++;
959
 
 
960
 
        fprintf(stderr, "FindPolygons[%d]: allocated space for %d rings\n",
961
 
                call, obj->nParts);
962
935
#endif
963
936
 
 
937
        LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts);
 
938
 
964
939
        /* Allocate initial memory */
965
940
        Outer = (Ring**)malloc(sizeof(Ring*)*obj->nParts);
966
941
        Inner = (Ring**)malloc(sizeof(Ring*)*obj->nParts);
1002
977
                        ring->list[vi-vs].m = obj->padfM[vi];
1003
978
 
1004
979
                        area += (obj->padfX[vi] * obj->padfY[vn]) -
1005
 
                                (obj->padfY[vi] * obj->padfX[vn]); 
 
980
                                (obj->padfY[vi] * obj->padfX[vn]);
1006
981
                }
1007
982
 
1008
983
                /* Close the ring with first vertex  */
1024
999
                }
1025
1000
        }
1026
1001
 
1027
 
#ifdef DEBUG
1028
 
        fprintf(stderr, "FindPolygons[%d]: found %d Outer, %d Inners\n",
1029
 
                call, out_index, in_index);
1030
 
#endif
 
1002
        LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index);
1031
1003
 
1032
1004
        /* Put the inner rings into the list of the outer rings */
1033
1005
        /* of which they are within */
1066
1038
                {
1067
1039
                        /* The ring wasn't within any outer rings, */
1068
1040
                        /* assume it is a new outer ring. */
1069
 
#ifdef DEBUG
1070
 
                        fprintf(stderr,
1071
 
                                "FindPolygons[%d]: hole %d is orphan\n",
1072
 
                                call, pi);
1073
 
#endif
 
1041
                        LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi);
 
1042
 
1074
1043
                        Outer[out_index] = inner;
1075
1044
                        out_index++;
1076
1045
                }
1098
1067
                        free(temp);
1099
1068
                }
1100
1069
        }
 
1070
        free(polys);
1101
1071
}
1102
1072
 
1103
 
/*This function basically deals with the polygon case. */
1104
 
/*it sorts the polys in order of outer,inner,inner, so that inners */
1105
 
/*always come after outers they are within  */
 
1073
/** @brief This function basically deals with the polygon case. */
 
1074
/*              it sorts the polys in order of outer,inner,inner, so that inners */
 
1075
/*              always come after outers they are within  */
1106
1076
void
1107
1077
InsertPolygon(void)
1108
1078
{
1109
 
        unsigned int subtype = POLYGONTYPE | (wkbtype&WKBZOFFSET) | 
1110
 
                (wkbtype&WKBMOFFSET);
1111
1079
        Ring **Outer;
1112
 
        int out_index;
1113
 
        int pi; /* part index */
1114
 
 
1115
 
        out_index = FindPolygons(obj, &Outer);
1116
 
 
1117
 
        if (!dump_format) printf("'");
1118
 
        if ( sr_id > 0 ) printf("SRID=%d;", sr_id);
1119
 
 
1120
 
        if (simple_geometries==0) // We write MULTI geometries, so generate Header 
1121
 
        {
1122
 
                print_wkb_byte(getEndianByte());
1123
 
                print_wkb_int(wkbtype);
1124
 
                print_wkb_int(out_index); /* npolys */
1125
 
        } 
1126
 
        else if (out_index!=1) // We write Non-MULTI geometries, but have several parts: 
1127
 
        {
1128
 
                fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", out_index);
1129
 
                exit(1);                
1130
 
        }
1131
 
 
1132
 
        /* Write the coordinates */
1133
 
        for(pi=0; pi<out_index; pi++)
1134
 
        {
1135
 
                Ring *poly;
1136
 
 
1137
 
                poly = Outer[pi];
1138
 
 
1139
 
                print_wkb_byte(getEndianByte());
1140
 
                print_wkb_int(subtype);
1141
 
                print_wkb_int(poly->linked+1); /* nrings */
1142
 
 
1143
 
                while(poly)
1144
 
                {
1145
 
                        int vi; /* vertex index */
1146
 
 
1147
 
                        print_wkb_int(poly->n); /* npoints */
1148
 
 
1149
 
                        for(vi=0; vi<poly->n; vi++)
1150
 
                        {
1151
 
                                print_wkb_double(poly->list[vi].x);
1152
 
                                print_wkb_double(poly->list[vi].y);
1153
 
                                if ( wkbtype & WKBZOFFSET )
1154
 
                                        print_wkb_double(poly->list[vi].z);
1155
 
                                if ( wkbtype & WKBMOFFSET )
1156
 
                                        print_wkb_double(poly->list[vi].m);
1157
 
                        }
1158
 
 
1159
 
                        poly = poly->next;
1160
 
                }
1161
 
 
1162
 
        }
1163
 
 
1164
 
        if (dump_format) printf("\n");
1165
 
        else printf("');\n");
1166
 
 
1167
 
        /* Release all memory */
1168
 
        ReleasePolygons(Outer, out_index);
1169
 
        free(Outer);
1170
 
}
1171
 
 
1172
 
void
1173
 
InsertPolygonWKT(void)
1174
 
{
1175
 
        Ring **Outer;    /* Pointers to Outer rings */
1176
 
        int out_index=0; /* Count of Outer rings */
1177
 
        int pi; /* part index */
1178
 
 
1179
 
#ifdef DEBUG
1180
 
        static int call = -1;
1181
 
        call++;
1182
 
 
1183
 
        fprintf(stderr, "InsertPolygon[%d]: allocated space for %d rings\n",
1184
 
                call, obj->nParts);
1185
 
#endif
1186
 
 
1187
 
        out_index = FindPolygons(obj, &Outer);
1188
 
 
1189
 
        if (dump_format) printf("SRID=%d;",sr_id );
1190
 
        else printf("GeometryFromText('");
1191
 
        
1192
 
        if (simple_geometries==0) // We write MULTI geometries, so generate Header 
1193
 
        {
1194
 
                printf("MULTIPOLYGON(");
1195
 
        } 
1196
 
        else if (out_index==1) 
1197
 
        {
1198
 
                printf("POLYGON");
1199
 
        }
1200
 
        else
1201
 
        { // We write Non-MULTI geometries, but have several parts: 
1202
 
                fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", out_index);
1203
 
                exit(1);                
1204
 
        }
1205
 
 
1206
 
        /* Write the coordinates */
1207
 
        for(pi=0; pi<out_index; pi++)
1208
 
        {
1209
 
                Ring *poly;
1210
 
 
1211
 
                poly = Outer[pi];
1212
 
 
1213
 
                if ( pi ) printf(",");
1214
 
                printf("(");
1215
 
 
1216
 
                while(poly)
1217
 
                {
1218
 
                        int vi; /* vertex index */
1219
 
 
1220
 
                        printf("(");
1221
 
                        for(vi=0; vi<poly->n; vi++)
1222
 
                        {
1223
 
                                if ( vi ) printf(",");
1224
 
                                printf("%.15g %.15g",
1225
 
                                        poly->list[vi].x,
1226
 
                                        poly->list[vi].y);
1227
 
                                if ( wkbtype & WKBZOFFSET )
1228
 
                                        printf(" %.15g", poly->list[vi].z);
1229
 
                        }
1230
 
                        printf(")");
1231
 
 
1232
 
                        poly = poly->next;
1233
 
                        if ( poly ) printf(",");
1234
 
                }
1235
 
 
1236
 
                printf(")");
1237
 
 
1238
 
        }
1239
 
 
1240
 
        if (simple_geometries==0) printf(")");
1241
 
        
1242
 
        if (dump_format) printf("\n");
1243
 
        else printf("',%d) );\n",sr_id);
1244
 
 
1245
 
        /* Release all memory */
1246
 
        ReleasePolygons(Outer, out_index);
1247
 
        free(Outer);
1248
 
}
1249
 
 
 
1080
        int polygon_total, ring_total;
 
1081
        int pi, vi; // part index and vertex index
 
1082
        int u;
 
1083
 
 
1084
        LWCOLLECTION *lwcollection = NULL;
 
1085
 
 
1086
        LWGEOM **lwpolygons;
 
1087
        uchar *serialized_lwgeom;
 
1088
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
1089
 
 
1090
        LWPOLY *lwpoly;
 
1091
        DYNPTARRAY *dpas;
 
1092
        POINTARRAY ***pas;
 
1093
        POINT4D point4d;
 
1094
 
 
1095
        int dims = 0, hasz = 0, hasm = 0;
 
1096
        int result;
 
1097
 
 
1098
        /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
 
1099
           the M coordinate */
 
1100
        if (wkbtype & WKBZOFFSET) hasz = 1;
 
1101
        if (!hwgeom)
 
1102
                if (wkbtype & WKBMOFFSET) hasm = 1;
 
1103
        TYPE_SETZM(dims, hasz, hasm);
 
1104
 
 
1105
        polygon_total = FindPolygons(obj, &Outer);
 
1106
 
 
1107
        if (simple_geometries == 1 && polygon_total != 1) /* We write Non-MULTI geometries, but have several parts: */
 
1108
        {
 
1109
                fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", polygon_total);
 
1110
                exit(1);
 
1111
        }
 
1112
 
 
1113
        /* Allocate memory for our array of LWPOLYs */
 
1114
        lwpolygons = malloc(sizeof(LWPOLY *) * polygon_total);
 
1115
 
 
1116
        /* Allocate memory for our POINTARRAY pointers for each polygon */
 
1117
        pas = malloc(sizeof(POINTARRAY **) * polygon_total);
 
1118
 
 
1119
        /* Cycle through each individual polygon */
 
1120
        for(pi = 0; pi < polygon_total; pi++)
 
1121
        {
 
1122
                Ring *polyring;
 
1123
                int ring_index = 0;
 
1124
 
 
1125
                /* Firstly count through the total number of rings in this polygon */
 
1126
                ring_total = 0;
 
1127
                polyring = Outer[pi];
 
1128
                while (polyring)
 
1129
                {
 
1130
                        ring_total++;
 
1131
                        polyring = polyring->next;
 
1132
                }
 
1133
 
 
1134
                /* Reserve memory for the POINTARRAYs representing each ring */
 
1135
                pas[pi] = malloc(sizeof(POINTARRAY *) * ring_total);
 
1136
 
 
1137
                /* Cycle through each ring within the polygon, starting with the outer */
 
1138
                polyring = Outer[pi];
 
1139
 
 
1140
                while (polyring)
 
1141
                {
 
1142
                        /* Create a DYNPTARRAY containing the points making up the ring */
 
1143
                        dpas = dynptarray_create(polyring->n, dims);
 
1144
 
 
1145
                        for(vi = 0; vi < polyring->n; vi++)
 
1146
                        {
 
1147
                                /* Build up a point array of all the points in this ring */
 
1148
                                point4d.x = polyring->list[vi].x;
 
1149
                                point4d.y = polyring->list[vi].y;
 
1150
 
 
1151
                                if (wkbtype & WKBZOFFSET)
 
1152
                                        point4d.z = polyring->list[vi].z;
 
1153
                                if (wkbtype & WKBMOFFSET)
 
1154
                                        point4d.m = polyring->list[vi].m;
 
1155
 
 
1156
                                dynptarray_addPoint4d(dpas, &point4d, 0);
 
1157
                        }
 
1158
 
 
1159
                        /* Copy the POINTARRAY pointer from the DYNPTARRAY structure so we can
 
1160
                         use the LWPOLY constructor */
 
1161
                        pas[pi][ring_index] = dpas->pa;
 
1162
 
 
1163
                        /* Free the DYNPTARRAY structure (we don't need this part anymore as we
 
1164
                        have the reference to the internal POINTARRAY) */
 
1165
                        lwfree(dpas);
 
1166
 
 
1167
                        polyring = polyring->next;
 
1168
                        ring_index++;
 
1169
                }
 
1170
 
 
1171
                /* Generate the LWGEOM */
 
1172
                lwpoly = lwpoly_construct(sr_id, NULL, ring_total, pas[pi]);
 
1173
                lwpolygons[pi] = lwpoly_as_lwgeom(lwpoly);
 
1174
        }
 
1175
 
 
1176
        ReleasePolygons(Outer, polygon_total);
 
1177
 
 
1178
        /* If using MULTIPOLYGONS then generate the serialized collection, otherwise just a single POLYGON */
 
1179
        if (simple_geometries == 0)
 
1180
        {
 
1181
                lwcollection = lwcollection_construct(MULTIPOLYGONTYPE, sr_id, NULL, polygon_total, lwpolygons);
 
1182
                serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
 
1183
        }
 
1184
        else
 
1185
        {
 
1186
                serialized_lwgeom = lwgeom_serialize(lwpolygons[0]);
 
1187
        }
 
1188
 
 
1189
        if (!hwgeom)
 
1190
                result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE, -1);
 
1191
        else
 
1192
                result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE);
 
1193
 
 
1194
        if (result)
 
1195
        {
 
1196
                fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
 
1197
                exit(1);
 
1198
        }
 
1199
 
 
1200
        OutputGeometry(lwg_unparser_result.wkoutput);
 
1201
 
 
1202
        /* Free all of the allocated items */
 
1203
                lwfree(lwg_unparser_result.wkoutput);
 
1204
                lwfree(serialized_lwgeom);
 
1205
 
 
1206
        /* Cycle through each polygon, freeing everything we need... */
 
1207
        for (u = 0; u < polygon_total; u++)
 
1208
                lwpoly_free(lwgeom_as_lwpoly(lwpolygons[u]));
 
1209
 
 
1210
        /* Free the pointer arrays */
 
1211
        lwfree(pas);
 
1212
        lwfree(lwpolygons);
 
1213
        if (simple_geometries == 0)
 
1214
                lwfree(lwcollection);
 
1215
}
 
1216
 
 
1217
/**
 
1218
 * @brief Insert either a POINT or MULTIPOINT into the output stream
 
1219
 */
1250
1220
void
1251
1221
InsertPoint(void)
1252
1222
{
1253
 
        if (!dump_format) printf("'");
1254
 
        if ( sr_id > 0 ) printf("SRID=%d;", sr_id);
1255
 
 
1256
 
        print_wkb_byte(getEndianByte());
1257
 
        print_wkb_int(wkbtype);
1258
 
        print_wkb_double(obj->padfX[0]);
1259
 
        print_wkb_double(obj->padfY[0]);
1260
 
        if ( wkbtype & WKBZOFFSET ) print_wkb_double(obj->padfZ[0]);
1261
 
        if ( wkbtype & WKBMOFFSET ) print_wkb_double(obj->padfM[0]);
1262
 
 
1263
 
        if (dump_format) printf("\n");
1264
 
        else printf("');\n");
1265
 
}
1266
 
 
1267
 
void
1268
 
InsertPointWKT(void)
1269
 
{
1270
 
        unsigned int u;
1271
 
        if (dump_format) printf("SRID=%d;%s(", sr_id, pgtype);
1272
 
        else printf("GeometryFromText('%s(", pgtype);
1273
 
 
1274
 
        for (u=0;u<obj->nVertices; u++){
1275
 
                if (u>0) printf(",");
1276
 
                printf("%.15g %.15g",obj->padfX[u],obj->padfY[u]);
1277
 
                if ( wkbtype & WKBZOFFSET ) printf(" %.15g", obj->padfZ[u]);
1278
 
        }
1279
 
        if (dump_format) printf(")\n");
1280
 
        else printf(")',%d) );\n",sr_id);
1281
 
 
1282
 
}
1283
 
 
1284
 
void
1285
 
InsertMultiPoint(void)
1286
 
{
1287
 
        unsigned int u;
1288
 
        unsigned int subtype = POINTTYPE | (wkbtype&WKBZOFFSET) | 
1289
 
                (wkbtype&WKBMOFFSET);
1290
 
 
1291
 
        if (!dump_format) printf("'");
1292
 
        if ( sr_id > 0 ) printf("SRID=%d;", sr_id);
1293
 
 
1294
 
        print_wkb_byte(getEndianByte());
1295
 
        print_wkb_int(wkbtype);
1296
 
        print_wkb_int(obj->nVertices);
1297
 
        
1298
 
        for (u=0;u<obj->nVertices; u++)
1299
 
        {
1300
 
                print_wkb_byte(getEndianByte());
1301
 
                print_wkb_int(subtype);
1302
 
                print_wkb_double(obj->padfX[u]);
1303
 
                print_wkb_double(obj->padfY[u]);
1304
 
                if ( wkbtype & WKBZOFFSET ) print_wkb_double(obj->padfZ[u]);
1305
 
                if ( wkbtype & WKBMOFFSET ) print_wkb_double(obj->padfM[u]);
1306
 
        }
1307
 
 
1308
 
        if (dump_format) printf("\n");
1309
 
        else printf("');\n");
1310
 
}
 
1223
        LWCOLLECTION *lwcollection;
 
1224
 
 
1225
        LWGEOM **lwmultipoints;
 
1226
        uchar *serialized_lwgeom;
 
1227
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
1228
 
 
1229
        DYNPTARRAY **dpas;
 
1230
        POINT4D point4d;
 
1231
 
 
1232
        int dims = 0, hasz = 0, hasm = 0;
 
1233
        int result;
 
1234
        int u;
 
1235
 
 
1236
        /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use
 
1237
           the M coordinate */
 
1238
        if (wkbtype & WKBZOFFSET) hasz = 1;
 
1239
        if (!hwgeom)
 
1240
                if (wkbtype & WKBMOFFSET) hasm = 1;
 
1241
        TYPE_SETZM(dims, hasz, hasm);
 
1242
 
 
1243
        /* Allocate memory for our array of LWPOINTs and our dynptarrays */
 
1244
        lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices);
 
1245
        dpas = malloc(sizeof(DYNPTARRAY *) * obj->nVertices);
 
1246
 
 
1247
        /* We need an array of pointers to each of our sub-geometries */
 
1248
        for (u = 0; u < obj->nVertices; u++)
 
1249
        {
 
1250
                /* Generate the point */
 
1251
                point4d.x = obj->padfX[u];
 
1252
                point4d.y = obj->padfY[u];
 
1253
 
 
1254
                if (wkbtype & WKBZOFFSET)
 
1255
                        point4d.z = obj->padfZ[u];
 
1256
                if (wkbtype & WKBMOFFSET)
 
1257
                        point4d.m = obj->padfM[u];
 
1258
 
 
1259
                /* Create a dynptarray containing a single point */
 
1260
                dpas[u] = dynptarray_create(1, dims);
 
1261
                dynptarray_addPoint4d(dpas[u], &point4d, 0);
 
1262
 
 
1263
                /* Generate the LWPOINT */
 
1264
                lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(sr_id, NULL, dpas[u]->pa));
 
1265
        }
 
1266
 
 
1267
        /* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT
 
1268
        rather than a POINT */
 
1269
        if (obj->nVertices > 1)
 
1270
        {
 
1271
                lwcollection = lwcollection_construct(MULTIPOINTTYPE, sr_id, NULL, obj->nVertices, lwmultipoints);
 
1272
                serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection));
 
1273
        }
 
1274
        else
 
1275
        {
 
1276
                serialized_lwgeom = lwgeom_serialize(lwmultipoints[0]);
 
1277
        }
 
1278
 
 
1279
        if (!hwgeom)
 
1280
                result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE, -1);
 
1281
        else
 
1282
                result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE);
 
1283
 
 
1284
        if (result)
 
1285
        {
 
1286
                fprintf(stderr, "ERROR: %s\n", lwg_unparser_result.message);
 
1287
                exit(1);
 
1288
        }
 
1289
 
 
1290
        OutputGeometry(lwg_unparser_result.wkoutput);
 
1291
 
 
1292
        /* Free all of the allocated items */
 
1293
                lwfree(lwg_unparser_result.wkoutput);
 
1294
                lwfree(serialized_lwgeom);
 
1295
 
 
1296
        for (u = 0; u < obj->nVertices; u++)
 
1297
        {
 
1298
                        lwpoint_free(lwgeom_as_lwpoint(lwmultipoints[u]));
 
1299
                        lwfree(dpas[u]);
 
1300
        }
 
1301
 
 
1302
        lwfree(dpas);
 
1303
        lwfree(lwmultipoints);
 
1304
}
 
1305
 
 
1306
void
 
1307
OutputGeometry(char *geometry)
 
1308
{
 
1309
        /* This function outputs the specified geometry string (WKB or WKT) formatted
 
1310
         * according to whether we have specified dump format or hwgeom format */
 
1311
 
 
1312
        if (hwgeom)
 
1313
        {
 
1314
                if (!dump_format)
 
1315
                        printf("GeomFromText('");
 
1316
                else
 
1317
                {
 
1318
                        /* Output SRID if relevant */
 
1319
                        if (sr_id != 0)
 
1320
                                printf("SRID=%d;", sr_id);
 
1321
                }
 
1322
 
 
1323
                printf("%s", geometry);
 
1324
 
 
1325
                if (!dump_format)
 
1326
                {
 
1327
                        printf("'");
 
1328
 
 
1329
                        /* Output SRID if relevant */
 
1330
                        if (sr_id != 0)
 
1331
                                printf(", %d)", sr_id);
 
1332
 
 
1333
                        printf(");\n");
 
1334
                }
 
1335
                else
 
1336
                        printf("\n");
 
1337
        }
 
1338
        else
 
1339
        {
 
1340
                if (!dump_format)
 
1341
                        printf("'");
 
1342
 
 
1343
                printf("%s", geometry);
 
1344
 
 
1345
                if (!dump_format)
 
1346
                        printf("');\n");
 
1347
                else
 
1348
                        printf("\n");
 
1349
        }
 
1350
}
 
1351
 
1311
1352
 
1312
1353
int
1313
1354
ParseCmdline(int ARGC, char **ARGV)
1355
1396
                                simple_geometries =1;
1356
1397
                                break;
1357
1398
                        case 's':
1358
 
                    (void)sscanf(optarg, "%d", &sr_id);
 
1399
                                (void)sscanf(optarg, "%d", &sr_id);
1359
1400
                                break;
1360
1401
                        case 'g':
1361
1402
                                geom = optarg;
1376
1417
                                readshape = 0;
1377
1418
                                break;
1378
1419
                        case 'W':
1379
 
#ifdef USE_ICONV
1380
 
                                        encoding = optarg;
 
1420
#ifdef HAVE_ICONV
 
1421
                                encoding = optarg;
1381
1422
#else
1382
 
                                        fprintf(stderr, "WARNING: the -W switch will have no effect. UTF8 disabled at compile time\n");
 
1423
                                fprintf(stderr, "WARNING: the -W switch will have no effect. UTF8 disabled at compile time\n");
1383
1424
#endif
1384
1425
                                break;
1385
1426
                        case 'N':
1386
1427
                                switch (optarg[0])
1387
 
                                {       
 
1428
                                {
1388
1429
                                        case 'a':
1389
1430
                                                null_policy = abort_on_null;
1390
1431
                                                break;
1400
1441
                                }
1401
1442
                                break;
1402
1443
                        case '?':
1403
 
                                usage(ARGV[0], 0, stdout); 
1404
 
                        default:              
 
1444
                                usage(ARGV[0], 0, stdout);
 
1445
                        default:
1405
1446
                                return 0;
1406
1447
                }
1407
1448
        }
1426
1467
                }
1427
1468
                curindex++;
1428
1469
        }
1429
 
        
 
1470
 
1430
1471
        /*
1431
1472
         * Third argument (if present) is supported for compatibility
1432
1473
         * with old shp2pgsql versions taking also database name.
1435
1476
                return 0;
1436
1477
        }
1437
1478
 
1438
 
        /* 
 
1479
        /*
1439
1480
         * Transform table name to lower case unless asked
1440
1481
         * to keep original case (we'll quote it later on)
1441
1482
         */
1551
1592
                        break;
1552
1593
        }
1553
1594
 
1554
 
        if (simple_geometries)
1555
 
        {
1556
 
                // adjust geometry name for CREATE TABLE by skipping MULTI
1557
 
                if ((wkbtype & 0x7) == MULTIPOLYGONTYPE) pgtype += 5;
1558
 
                if ((wkbtype & 0x7) == MULTILINETYPE) pgtype += 5;
1559
 
        }                        
 
1595
                if (simple_geometries)
 
1596
                {
 
1597
                                // adjust geometry name for CREATE TABLE by skipping MULTI
 
1598
                                if ((wkbtype & 0x7) == MULTIPOLYGONTYPE) pgtype += 5;
 
1599
                                if ((wkbtype & 0x7) == MULTILINETYPE) pgtype += 5;
 
1600
                }
1560
1601
}
1561
1602
 
1562
1603
char *
1576
1617
        return buf;
1577
1618
}
1578
1619
 
1579
 
/*--------------- WKB handling  */
1580
 
 
1581
 
static char outchr[]={"0123456789ABCDEF"};
1582
 
 
1583
 
static int endian_check_int = 1; /* dont modify this!!! */
1584
 
 
1585
 
static char
1586
 
getEndianByte(void)
1587
 
{
1588
 
        /* 0 = big endian, 1 = little endian */
1589
 
        if ( *((char *) &endian_check_int) ) return 1;
1590
 
        else return 0;
1591
 
}
1592
 
 
1593
 
static void
1594
 
print_wkb_double(double val)
1595
 
{
1596
 
        print_wkb_bytes((unsigned char *)&val, 1, 8);
1597
 
}
1598
 
 
1599
 
static void
1600
 
print_wkb_byte(unsigned char val)
1601
 
{
1602
 
        print_wkb_bytes((unsigned char *)&val, 1, 1);
1603
 
}
1604
 
 
1605
 
static void
1606
 
print_wkb_int(int val)
1607
 
{
1608
 
        print_wkb_bytes((unsigned char *)&val, 1, 4);
1609
 
}
1610
 
 
1611
 
static void
1612
 
print_wkb_bytes(unsigned char *ptr, unsigned int cnt, size_t size)
1613
 
{
1614
 
        unsigned int bc; /* byte count */
1615
 
        static char buf[256];
1616
 
        char *bufp;
1617
 
 
1618
 
        if ( size*cnt*2 > 256 )
1619
 
        {
1620
 
                fprintf(stderr,
1621
 
                        "You found a bug! wkb_bytes does not allocate enough bytes");
1622
 
                exit(4);
1623
 
        }
1624
 
 
1625
 
        bufp = buf;
1626
 
        while(cnt--){
1627
 
                for(bc=0; bc<size; bc++)
1628
 
                {
1629
 
                        *bufp++ = outchr[ptr[bc]>>4];
1630
 
                        *bufp++ = outchr[ptr[bc]&0x0F];
1631
 
                }
1632
 
        }
1633
 
        *bufp = '\0';
1634
 
        /*fprintf(stderr, "\nwkbbytes:%s\n", buf); */
1635
 
        printf("%s", buf);
1636
 
}
1637
 
 
1638
1620
void
1639
1621
DropTable(char *schema, char *table, char *geom)
1640
1622
{
1641
 
                /*---------------Drop the table--------------------------
1642
 
                 * TODO: if the table has more then one geometry column
1643
 
                 * the DROP TABLE call will leave spurious records in
1644
 
                 * geometry_columns. 
 
1623
                /**---------------Drop the table--------------------------
 
1624
                 * TODO: \todo if the table has more then one geometry column
 
1625
                 *      the DROP TABLE call will leave spurious records in
 
1626
                 *      geometry_columns.
1645
1627
                 *
1646
1628
                 * If the geometry column in the table being dropped
1647
1629
                 * does not match 'the_geom' or the name specified with
1648
 
                 * -g an error is returned by DropGeometryColumn. 
 
1630
                 * -g an error is returned by DropGeometryColumn.
1649
1631
                 *
1650
1632
                 * The table to be dropped might not exist.
1651
1633
                 *
1681
1663
        char  name[MAXFIELDNAMELEN];
1682
1664
        char  name2[MAXFIELDNAMELEN];
1683
1665
        DBFFieldType type = -1;
1684
 
#ifdef USE_ICONV
 
1666
#ifdef HAVE_ICONV
1685
1667
        char *utf8str;
1686
1668
#endif
1687
1669
 
1703
1685
        /*fprintf(stderr, "Number of fields from DBF: %d\n", num_fields); */
1704
1686
        for(j=0;j<num_fields;j++)
1705
1687
        {
1706
 
                type = DBFGetFieldInfo(hDBFHandle, j, name, &field_width, &field_precision); 
 
1688
                type = DBFGetFieldInfo(hDBFHandle, j, name, &field_width, &field_precision);
1707
1689
 
1708
1690
/*fprintf(stderr, "Field %d (%s) width/decimals: %d/%d\n", j, name, field_width, field_precision); */
1709
1691
                types[j] = type;
1710
1692
                widths[j] = field_width;
1711
1693
                precisions[j] = field_precision;
1712
1694
 
1713
 
#ifdef USE_ICONV
 
1695
#ifdef HAVE_ICONV
1714
1696
                if ( encoding )
1715
1697
                {
1716
1698
                        utf8str = utf8(encoding, name);
1755
1737
                                sprintf(name+strlen(name),"%i",j);
1756
1738
                                break;
1757
1739
                        }
1758
 
                }       
 
1740
                }
1759
1741
 
1760
1742
                field_names[j] = malloc (strlen(name)+1);
1761
1743
                strcpy(field_names[j], name);
1778
1760
        strcat(col_names, ")");
1779
1761
}
1780
1762
 
1781
 
#ifdef USE_ICONV
 
1763
#ifdef HAVE_ICONV
1782
1764
 
1783
1765
char *
1784
1766
utf8 (const char *fromcode, char *inputbuf)
1820
1802
        return outputbuf;
1821
1803
}
1822
1804
 
1823
 
#endif /* defined USE_ICONV */
 
1805
#endif /* defined HAVE_ICONV */
1824
1806
 
1825
1807
/**********************************************************************
1826
1808
 * $Log$
1827
1809
 * Revision 1.109  2008/04/09 14:12:17  robe
1828
1810
 *         - Added support to load dbf-only files
1829
 
 * 
 
1811
 *
1830
1812
 * Revision 1.108  2006/06/16 14:12:17  strk
1831
1813
 *         - BUGFIX in pgsql2shp successful return code.
1832
1814
 *         - BUGFIX in shp2pgsql handling of MultiLine WKT.