1 /*
2 
3  shapefiles.c -- implements shapefile support [import - export]
4 
5  version 5.0, 2020 August 1
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29 
30 Contributor(s): Brad Hards <bradh@frogmouth.net>
31 
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43 
44 */
45 
46 #if defined(_WIN32) && !defined(__MINGW32__)
47 /* MSVC strictly requires this include [off_t] */
48 #include <sys/types.h>
49 #endif
50 
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <math.h>
55 #include <float.h>
56 
57 #if defined(_WIN32) && !defined(__MINGW32__)
58 #include "config-msvc.h"
59 #else
60 #include "config.h"
61 #endif
62 
63 #include <spatialite/sqlite.h>
64 #include <spatialite/debug.h>
65 
66 #include <spatialite/gaiaaux.h>
67 #include <spatialite/gaiageo.h>
68 #include <spatialite.h>
69 #include <spatialite_private.h>
70 #include <spatialite/geojson.h>
71 
72 #ifndef OMIT_FREEXL
73 #include <freexl.h>
74 #endif
75 
76 #ifndef OMIT_PROJ		/* including PROJ */
77 #ifdef PROJ_NEW			/* supporting PROJ.6 */
78 #include <proj.h>
79 #endif
80 #endif
81 
82 #ifdef ENABLE_MINIZIP		/* MINIZIP is enabled */
83 #include <minizip/unzip.h>
84 #endif
85 
86 #if defined(_WIN32) && !defined(__MINGW32__)
87 #define strcasecmp	_stricmp
88 #define strncasecmp	_strnicmp
89 #endif
90 
91 /* 64 bit integer: portable format for printf() */
92 #if defined(_WIN32) && !defined(__MINGW32__)
93 #define FRMT64 "%I64d"
94 #else
95 #define FRMT64 "%lld"
96 #endif
97 
98 #define GAIA_ZIPFILE_SHP	1
99 #define GAIA_ZIPFILE_SHX	2
100 #define GAIA_ZIPFILE_DBF	3
101 #define GAIA_ZIPFILE_PRJ	4
102 
103 struct auxdbf_fld
104 {
105 /* auxiliary DBF field struct */
106     char already_used;
107     gaiaDbfFieldPtr dbf_field;
108     struct auxdbf_fld *next;
109 };
110 
111 struct auxdbf_list
112 {
113 /* auxiliary DBF struct */
114     struct auxdbf_fld *first;
115     struct auxdbf_fld *last;
116 };
117 
118 struct resultset_values
119 {
120 /* a struct wrapping values from a resultset */
121     int type;
122     sqlite3_int64 int_value;
123     double dbl_value;
124     unsigned char *txt_blob_value;
125     int txt_blob_size;
126 };
127 
128 struct resultset_comparator
129 {
130 /* object for comparing two rows of the same resultset */
131     struct resultset_values *previous;
132     struct resultset_values *current;
133     int num_columns;
134     sqlite3_int64 previous_rowid;
135     sqlite3_int64 current_rowid;
136 };
137 
138 struct aux_elemgeom_ignore
139 {
140 /* an Elementary Geometries Ignore option */
141     char *column;
142     struct aux_elemgeom_ignore *next;
143 };
144 
145 struct aux_elemgeom_options
146 {
147 /* Elementary Geometries Options */
148     struct aux_elemgeom_ignore *first;
149     struct aux_elemgeom_ignore *last;
150     int cast2multi;
151 };
152 
153 struct zip_mem_shapefile
154 {
155 /* a struct wrapping a Memory Shapefile from Zipfile */
156     gaiaMemFile shp;
157     gaiaMemFile shx;
158     gaiaMemFile dbf;
159     gaiaMemFile prj;
160 };
161 
162 struct zip_mem_shp_item
163 {
164 /* a Shapefile within a Zipfile */
165     char *basename;
166     int shp;
167     int shx;
168     int dbf;
169     int prj;
170     struct zip_mem_shp_item *next;
171 };
172 
173 struct zip_mem_shp_list
174 {
175 /* a list of Shapefiles within a Zipfile */
176     struct zip_mem_shp_item *first;
177     struct zip_mem_shp_item *last;
178 };
179 
180 SPATIALITE_PRIVATE const void *
gaiaElemGeomOptionsCreate()181 gaiaElemGeomOptionsCreate ()
182 {
183 /* creating an Elementary Geometries Options object */
184     struct aux_elemgeom_options *options =
185 	malloc (sizeof (struct aux_elemgeom_options));
186     options->first = NULL;
187     options->last = NULL;
188     options->cast2multi = 0;
189     return options;
190 }
191 
192 SPATIALITE_PRIVATE void
gaiaElemGeomOptionsDestroy(const void * opts)193 gaiaElemGeomOptionsDestroy (const void *opts)
194 {
195 /* destroying an Elementary Geometries Options object */
196     struct aux_elemgeom_ignore *ign;
197     struct aux_elemgeom_ignore *ign2;
198     struct aux_elemgeom_options *options = (struct aux_elemgeom_options *) opts;
199     if (options == NULL)
200 	return;
201 
202     ign = options->first;
203     while (ign != NULL)
204       {
205 	  ign2 = ign->next;
206 	  if (ign->column != NULL)
207 	      free (ign->column);
208 	  free (ign);
209 	  ign = ign2;
210       }
211     free (options);
212 }
213 
214 static void
ignore_column(struct aux_elemgeom_options * options,const char * column)215 ignore_column (struct aux_elemgeom_options *options, const char *column)
216 {
217 /* marking a Column to be ignored */
218     int len;
219     struct aux_elemgeom_ignore *ign;
220     if (options == NULL)
221 	return;
222 
223     ign = malloc (sizeof (struct aux_elemgeom_ignore));
224     len = strlen (column);
225     ign->column = malloc (len + 1);
226     strcpy (ign->column, column);
227     ign->next = NULL;
228 
229     if (options->first == NULL)
230 	options->first = ign;
231     if (options->last != NULL)
232 	options->last->next = ign;
233     options->last = ign;
234 }
235 
236 SPATIALITE_PRIVATE void
gaiaElemGeomOptionsAdd(const void * opts,const char * option)237 gaiaElemGeomOptionsAdd (const void *opts, const char *option)
238 {
239 /* adding an Elementary Geometries Option */
240     struct aux_elemgeom_options *options = (struct aux_elemgeom_options *) opts;
241     if (options == NULL)
242 	return;
243 
244     if (strncasecmp (option, "::cast2multi::", 14) == 0)
245 	options->cast2multi = 1;
246     if (strncasecmp (option, "::ignore::", 10) == 0)
247 	ignore_column (options, option + 10);
248 }
249 
250 static struct resultset_comparator *
create_resultset_comparator(int columns)251 create_resultset_comparator (int columns)
252 {
253 /* creating an empty resultset comparator object */
254     int i;
255     struct resultset_comparator *p =
256 	malloc (sizeof (struct resultset_comparator));
257     p->num_columns = columns;
258     p->previous_rowid = -1;
259     p->current_rowid = -1;
260     p->previous = malloc (sizeof (struct resultset_values) * columns);
261     p->current = malloc (sizeof (struct resultset_values) * columns);
262     for (i = 0; i < columns; i++)
263       {
264 	  struct resultset_values *value = p->previous + i;
265 	  value->type = SQLITE_NULL;
266 	  value->txt_blob_value = NULL;
267 	  value = p->current + i;
268 	  value->type = SQLITE_NULL;
269 	  value->txt_blob_value = NULL;
270       }
271     return p;
272 }
273 
274 static void
destroy_resultset_comparator(struct resultset_comparator * ptr)275 destroy_resultset_comparator (struct resultset_comparator *ptr)
276 {
277 /* memory cleanup - destroying a resultset comparator object */
278     int i;
279     if (ptr == NULL)
280 	return;
281     for (i = 0; i < ptr->num_columns; i++)
282       {
283 	  struct resultset_values *value = ptr->previous + i;
284 	  if (value->txt_blob_value != NULL)
285 	      free (value->txt_blob_value);
286 	  value = ptr->current + i;
287 	  if (value->txt_blob_value != NULL)
288 	      free (value->txt_blob_value);
289       }
290     if (ptr->previous != NULL)
291 	free (ptr->previous);
292     if (ptr->current != NULL)
293 	free (ptr->current);
294     free (ptr);
295 }
296 
297 static void
save_row_from_resultset(struct resultset_comparator * ptr,sqlite3_stmt * stmt)298 save_row_from_resultset (struct resultset_comparator *ptr, sqlite3_stmt * stmt)
299 {
300 /* saving the current row values */
301     int i;
302     int size;
303     const unsigned char *p;
304     if (ptr == NULL)
305 	return;
306     ptr->current_rowid = sqlite3_column_int64 (stmt, 0);
307     for (i = 0; i < ptr->num_columns; i++)
308       {
309 	  struct resultset_values *value = ptr->current + i;
310 	  value->type = sqlite3_column_type (stmt, i + 1);
311 	  switch (value->type)
312 	    {
313 	    case SQLITE_INTEGER:
314 		value->int_value = sqlite3_column_int64 (stmt, i + 1);
315 		break;
316 	    case SQLITE_FLOAT:
317 		value->dbl_value = sqlite3_column_double (stmt, i + 1);
318 		break;
319 	    case SQLITE_TEXT:
320 		p = sqlite3_column_text (stmt, i + 1);
321 		size = strlen ((const char *) p);
322 		value->txt_blob_value = malloc (size + 1);
323 		strcpy ((char *) (value->txt_blob_value), (const char *) p);
324 		break;
325 	    case SQLITE_BLOB:
326 		p = sqlite3_column_blob (stmt, i + 1);
327 		size = sqlite3_column_bytes (stmt, i + 1);
328 		value->txt_blob_value = malloc (size);
329 		memcpy (value->txt_blob_value, p, size);
330 		value->txt_blob_size = size;
331 		break;
332 	    };
333       }
334 }
335 
336 static int
resultset_rows_equals(struct resultset_comparator * ptr)337 resultset_rows_equals (struct resultset_comparator *ptr)
338 {
339 /* comparing the current and previous row from the resultset */
340     int i;
341     if (ptr == NULL)
342 	return 0;
343     for (i = 0; i < ptr->num_columns; i++)
344       {
345 	  struct resultset_values *val_prev = ptr->previous + i;
346 	  struct resultset_values *val_curr = ptr->current + i;
347 	  if (val_prev->type != val_curr->type)
348 	      return 0;
349 	  switch (val_prev->type)
350 	    {
351 	    case SQLITE_INTEGER:
352 		if (val_prev->int_value != val_curr->int_value)
353 		    return 0;
354 		break;
355 	    case SQLITE_FLOAT:
356 		if (val_prev->dbl_value != val_curr->dbl_value)
357 		    return 0;
358 		break;
359 	    case SQLITE_TEXT:
360 		if (strcmp
361 		    ((const char *) (val_prev->txt_blob_value),
362 		     (const char *) (val_curr->txt_blob_value)) != 0)
363 		    return 0;
364 		break;
365 	    case SQLITE_BLOB:
366 		if (val_prev->txt_blob_size != val_curr->txt_blob_size)
367 		    return 0;
368 		if (memcmp
369 		    (val_prev->txt_blob_value, val_curr->txt_blob_value,
370 		     val_curr->txt_blob_size) != 0)
371 		    return 0;
372 		break;
373 	    };
374       }
375     return 1;
376 }
377 
378 static sqlite3_int64
get_current_resultset_rowid(struct resultset_comparator * ptr)379 get_current_resultset_rowid (struct resultset_comparator *ptr)
380 {
381 /* returns the current ROWID */
382     if (ptr == NULL)
383 	return -1;
384     return ptr->current_rowid;
385 }
386 
387 static void
reset_resultset_current_row(struct resultset_comparator * ptr)388 reset_resultset_current_row (struct resultset_comparator *ptr)
389 {
390 /* resetting the resultset current row values */
391     int i;
392     if (ptr == NULL)
393 	return;
394     ptr->current_rowid = -1;
395     for (i = 0; i < ptr->num_columns; i++)
396       {
397 	  struct resultset_values *value = ptr->current + i;
398 	  value->type = SQLITE_NULL;
399 	  if (value->txt_blob_value != NULL)
400 	      free (value->txt_blob_value);
401 	  value->txt_blob_value = NULL;
402       }
403 }
404 
405 static void
swap_resultset_rows(struct resultset_comparator * ptr)406 swap_resultset_rows (struct resultset_comparator *ptr)
407 {
408 /* resetting the resultset comparator */
409     int i;
410     if (ptr == NULL)
411 	return;
412     ptr->previous_rowid = ptr->current_rowid;
413     ptr->current_rowid = -1;
414     for (i = 0; i < ptr->num_columns; i++)
415       {
416 	  struct resultset_values *val_prev = ptr->previous + i;
417 	  struct resultset_values *val_curr = ptr->current + i;
418 	  if (val_prev->txt_blob_value != NULL)
419 	      free (val_prev->txt_blob_value);
420 	  val_prev->type = val_curr->type;
421 	  val_prev->int_value = val_curr->int_value;
422 	  val_prev->dbl_value = val_curr->dbl_value;
423 	  val_prev->txt_blob_value = val_curr->txt_blob_value;
424 	  val_prev->txt_blob_size = val_curr->txt_blob_size;
425 	  val_curr->type = SQLITE_NULL;
426 	  val_curr->txt_blob_value = NULL;
427       }
428 }
429 
430 #ifndef OMIT_ICONV		/* ICONV enabled: supporting SHP */
431 
432 static struct auxdbf_list *
alloc_auxdbf(gaiaDbfListPtr dbf_list)433 alloc_auxdbf (gaiaDbfListPtr dbf_list)
434 {
435 /* allocating the auxiliary DBF struct */
436     gaiaDbfFieldPtr fld;
437     struct auxdbf_fld *fld_ex;
438     struct auxdbf_list *auxdbf = malloc (sizeof (struct auxdbf_list));
439     auxdbf->first = NULL;
440     auxdbf->last = NULL;
441     fld = dbf_list->First;
442     while (fld)
443       {
444 	  fld_ex = malloc (sizeof (struct auxdbf_fld));
445 	  fld_ex->already_used = 0;
446 	  fld_ex->dbf_field = fld;
447 	  fld_ex->next = NULL;
448 	  if (auxdbf->first == NULL)
449 	      auxdbf->first = fld_ex;
450 	  if (auxdbf->last != NULL)
451 	      auxdbf->last->next = fld_ex;
452 	  auxdbf->last = fld_ex;
453 	  fld = fld->Next;
454       }
455     return auxdbf;
456 }
457 
458 static void
free_auxdbf(struct auxdbf_list * auxdbf)459 free_auxdbf (struct auxdbf_list *auxdbf)
460 {
461 /* freeing an auxiliary DBF struct */
462     struct auxdbf_fld *n_fld;
463     struct auxdbf_fld *fld = auxdbf->first;
464     while (fld != NULL)
465       {
466 	  n_fld = fld->next;
467 	  free (fld);
468 	  fld = n_fld;
469       }
470     free (auxdbf);
471 }
472 
473 static gaiaDbfFieldPtr
getDbfField(struct auxdbf_list * aux,char * name)474 getDbfField (struct auxdbf_list *aux, char *name)
475 {
476 /* find a DBF attribute by name */
477     struct auxdbf_fld *fld = aux->first;
478     while (fld)
479       {
480 	  if (strcasecmp (fld->dbf_field->Name, name) == 0)
481 	    {
482 		fld->already_used = 1;
483 		return fld->dbf_field;
484 	    }
485 	  fld = fld->next;
486       }
487     fld = aux->first;
488     while (fld)
489       {
490 	  if (fld->already_used)
491 	    {
492 		fld = fld->next;
493 		continue;
494 	    }
495 	  if (strncasecmp (fld->dbf_field->Name, name, 9) == 0)
496 	    {
497 		fld->already_used = 1;
498 		return fld->dbf_field;
499 	    }
500 	  fld = fld->next;
501       }
502     return NULL;
503 }
504 
505 static int
do_check_shp_unique_pk_values(sqlite3 * sqlite,gaiaShapefilePtr shp,int srid,int text_dates,const char * pk_name,int pk_type)506 do_check_shp_unique_pk_values (sqlite3 * sqlite, gaiaShapefilePtr shp, int srid,
507 			       int text_dates, const char *pk_name, int pk_type)
508 {
509 /* checking for duplicate PK values */
510     char *sql;
511     sqlite3_stmt *stmt = NULL;
512     gaiaDbfFieldPtr dbf_field;
513     int ret;
514     int duplicates = 0;
515     int current_row = 0;
516 
517     sql = "CREATE TABLE TEMP.check_unique_pk (pkey ANYVALUE)";
518     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
519     if (ret != SQLITE_OK)
520 	return 0;
521 
522     sql = "INSERT INTO TEMP.check_unique_pk (pkey) VALUES (?)";
523     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
524     if (ret != SQLITE_OK)
525 	goto error;
526 
527     sqlite3_exec (sqlite, "BEGIN", NULL, NULL, NULL);
528 
529     while (1)
530       {
531 	  /* reading rows from shapefile */
532 	  int ok_insert = 0;
533 	  ret = gaiaReadShpEntity_ex (shp, current_row, srid, text_dates);
534 	  if (ret < 0)
535 	    {
536 		/* found a DBF deleted record */
537 		current_row++;
538 		continue;
539 	    }
540 	  if (!ret)
541 	      break;
542 	  current_row++;
543 	  /* binding query params */
544 	  sqlite3_reset (stmt);
545 	  sqlite3_clear_bindings (stmt);
546 	  dbf_field = shp->Dbf->First;
547 	  while (dbf_field)
548 	    {
549 		/* Primary Key value */
550 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
551 		  {
552 		      if (pk_type == SQLITE_TEXT)
553 			{
554 			    ok_insert = 1;
555 			    sqlite3_bind_text (stmt, 1,
556 					       dbf_field->Value->TxtValue,
557 					       strlen (dbf_field->
558 						       Value->TxtValue),
559 					       SQLITE_STATIC);
560 			}
561 		      else if (pk_type == SQLITE_FLOAT)
562 			{
563 			    ok_insert = 1;
564 			    sqlite3_bind_double (stmt, 1,
565 						 dbf_field->Value->DblValue);
566 			}
567 		      else
568 			{
569 			    ok_insert = 1;
570 			    sqlite3_bind_int64 (stmt, 1,
571 						dbf_field->Value->IntValue);
572 			}
573 		  }
574 		dbf_field = dbf_field->Next;
575 	    }
576 	  if (ok_insert)
577 	    {
578 		ret = sqlite3_step (stmt);
579 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
580 		    ;
581 		else
582 		    goto error;
583 	    }
584       }
585     sqlite3_finalize (stmt);
586     stmt = NULL;
587     sqlite3_exec (sqlite, "COMMIT", NULL, NULL, NULL);
588 
589     sql = "SELECT Count(*) FROM TEMP.check_unique_pk GROUP BY pkey";
590     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
591     if (ret != SQLITE_OK)
592 	goto error;
593 
594     while (1)
595       {
596 	  /* scrolling the result set rows */
597 	  ret = sqlite3_step (stmt);
598 	  if (ret == SQLITE_DONE)
599 	      break;		/* end of result set */
600 	  if (ret == SQLITE_ROW)
601 	    {
602 		if (sqlite3_column_int (stmt, 0) > 1)
603 		    duplicates = 1;
604 	    }
605       }
606     sqlite3_finalize (stmt);
607 
608     sqlite3_exec (sqlite, "DROP TABLE TEMP.check_unique_pk", NULL, NULL, NULL);
609     if (duplicates)
610 	return 0;
611     else
612 	return 1;
613 
614   error:
615     if (stmt != NULL)
616 	sqlite3_finalize (stmt);
617     sqlite3_exec (sqlite, "COMMIT", NULL, NULL, NULL);
618     sqlite3_exec (sqlite, "DROP TABLE TEMP.check_unique_pk", NULL, NULL, NULL);
619     return 0;
620 }
621 
622 static char *
convert_dbf_colname_case(const char * buf,int colname_case)623 convert_dbf_colname_case (const char *buf, int colname_case)
624 {
625 /* converts a DBF column-name to Lower- or Upper-case */
626     int len = strlen (buf);
627     char *clean = malloc (len + 1);
628     char *p = clean;
629     strcpy (clean, buf);
630     while (*p != '\0')
631       {
632 	  if (colname_case == GAIA_DBF_COLNAME_LOWERCASE)
633 	    {
634 		if (*p >= 'A' && *p <= 'Z')
635 		    *p = *p - 'A' + 'a';
636 	    }
637 	  if (colname_case == GAIA_DBF_COLNAME_UPPERCASE)
638 	    {
639 		if (*p >= 'a' && *p <= 'z')
640 		    *p = *p - 'a' + 'A';
641 	    }
642 	  p++;
643       }
644     return clean;
645 }
646 
647 SPATIALITE_DECLARE int
load_shapefile(sqlite3 * sqlite,char * shp_path,char * table,char * charset,int srid,char * column,int coerce2d,int compressed,int verbose,int spatial_index,int * rows,char * err_msg)648 load_shapefile (sqlite3 * sqlite, char *shp_path, char *table, char *charset,
649 		int srid, char *column, int coerce2d, int compressed,
650 		int verbose, int spatial_index, int *rows, char *err_msg)
651 {
652     return load_shapefile_ex (sqlite, shp_path, table, charset, srid, column,
653 			      NULL, NULL, coerce2d, compressed, verbose,
654 			      spatial_index, rows, err_msg);
655 }
656 
657 SPATIALITE_DECLARE int
load_shapefile_ex(sqlite3 * sqlite,char * shp_path,char * table,char * charset,int srid,char * g_column,char * gtype,char * pk_column,int coerce2d,int compressed,int verbose,int spatial_index,int * rows,char * err_msg)658 load_shapefile_ex (sqlite3 * sqlite, char *shp_path, char *table,
659 		   char *charset, int srid, char *g_column, char *gtype,
660 		   char *pk_column, int coerce2d, int compressed, int verbose,
661 		   int spatial_index, int *rows, char *err_msg)
662 {
663     return load_shapefile_ex2 (sqlite, shp_path, table, charset, srid, g_column,
664 			       gtype, pk_column, coerce2d, compressed, verbose,
665 			       spatial_index, 0, rows, err_msg);
666 }
667 
668 SPATIALITE_DECLARE int
load_shapefile_ex2(sqlite3 * sqlite,char * shp_path,char * table,char * charset,int srid,char * g_column,char * gtype,char * pk_column,int coerce2d,int compressed,int verbose,int spatial_index,int text_dates,int * rows,char * err_msg)669 load_shapefile_ex2 (sqlite3 * sqlite, char *shp_path, char *table,
670 		    char *charset, int srid, char *g_column, char *gtype,
671 		    char *pk_column, int coerce2d, int compressed,
672 		    int verbose, int spatial_index, int text_dates, int *rows,
673 		    char *err_msg)
674 {
675     return load_shapefile_ex3 (sqlite, shp_path, table, charset, srid, g_column,
676 			       gtype, pk_column, coerce2d, compressed, verbose,
677 			       spatial_index, text_dates, rows,
678 			       GAIA_DBF_COLNAME_LOWERCASE, err_msg);
679 }
680 
681 static int
load_shapefile_common(struct zip_mem_shapefile * mem_shape,sqlite3 * sqlite,const char * shp_path,const char * table,const char * charset,int srid,const char * g_column,const char * gtype,const char * pk_column,int coerce2d,int compressed,int verbose,int spatial_index,int text_dates,int * rows,int colname_case,char * err_msg)682 load_shapefile_common (struct zip_mem_shapefile *mem_shape, sqlite3 * sqlite,
683 		       const char *shp_path, const char *table,
684 		       const char *charset, int srid, const char *g_column,
685 		       const char *gtype, const char *pk_column, int coerce2d,
686 		       int compressed, int verbose, int spatial_index,
687 		       int text_dates, int *rows, int colname_case,
688 		       char *err_msg)
689 {
690     sqlite3_stmt *stmt = NULL;
691     int ret;
692     char *errMsg = NULL;
693     char *sql;
694     char *dummy;
695     int already_exists = 0;
696     int metadata = 0;
697     int sqlError = 0;
698     gaiaShapefilePtr shp = NULL;
699     gaiaDbfFieldPtr dbf_field;
700     int cnt;
701     int col_cnt = 0;
702     int seed;
703     int len;
704     int dup;
705     int idup;
706     int current_row = 0;
707     int deleted = 0;
708     char **col_name = NULL;
709     unsigned char *blob;
710     int blob_size;
711     char *geom_type = NULL;
712     char *txt_dims;
713     const char *geo_column = g_column;
714     const char *xgtype = gtype;
715     char *qtable = NULL;
716     char *qpk_name = NULL;
717     const char *pk_name = NULL;
718     char *casename;
719     int pk_autoincr = 1;
720     char *xname;
721     int pk_type = SQLITE_INTEGER;
722     int pk_set;
723     const char *alt_pk[10] =
724 	{ "PK_ALT0", "PK_ALT1", "PK_ALT2", "PK_ALT3", "PK_ALT4", "PK_ALT5",
725 	"PK_ALT6", "PK_ALT7", "PK_ALT8", "PK_ALT9"
726     };
727     gaiaOutBuffer sql_statement;
728     if (!geo_column)
729 	geo_column = "Geometry";
730     if (rows)
731 	*rows = -1;
732     if (!xgtype)
733 	;
734     else
735       {
736 	  if (strcasecmp (xgtype, "LINESTRING") == 0)
737 	      xgtype = "LINESTRING";
738 	  else if (strcasecmp (xgtype, "LINESTRINGZ") == 0)
739 	      xgtype = "LINESTRINGZ";
740 	  else if (strcasecmp (xgtype, "LINESTRINGM") == 0)
741 	      xgtype = "LINESTRINGM";
742 	  else if (strcasecmp (xgtype, "LINESTRINGZM") == 0)
743 	      xgtype = "LINESTRINGZM";
744 	  else if (strcasecmp (xgtype, "MULTILINESTRING") == 0)
745 	      xgtype = "MULTILINESTRING";
746 	  else if (strcasecmp (xgtype, "MULTILINESTRINGZ") == 0)
747 	      xgtype = "MULTILINESTRINGZ";
748 	  else if (strcasecmp (xgtype, "MULTILINESTRINGM") == 0)
749 	      xgtype = "MULTILINESTRINGM";
750 	  else if (strcasecmp (xgtype, "MULTILINESTRINGZM") == 0)
751 	      xgtype = "MULTILINESTRINGZM";
752 	  else if (strcasecmp (xgtype, "POLYGON") == 0)
753 	      xgtype = "POLYGON";
754 	  else if (strcasecmp (xgtype, "POLYGONZ") == 0)
755 	      xgtype = "POLYGONZ";
756 	  else if (strcasecmp (xgtype, "POLYGONM") == 0)
757 	      xgtype = "POLYGONM";
758 	  else if (strcasecmp (xgtype, "POLYGONZM") == 0)
759 	      xgtype = "POLYGONZM";
760 	  else if (strcasecmp (xgtype, "MULTIPOLYGON") == 0)
761 	      xgtype = "MULTIPOLYGON";
762 	  else if (strcasecmp (xgtype, "MULTIPOLYGONZ") == 0)
763 	      xgtype = "MULTIPOLYGONZ";
764 	  else if (strcasecmp (xgtype, "MULTIPOLYGONM") == 0)
765 	      xgtype = "MULTIPOLYGONM";
766 	  else if (strcasecmp (xgtype, "MULTIPOLYGONZM") == 0)
767 	      xgtype = "MULTIPOLYGONZM";
768 	  else
769 	      xgtype = NULL;
770       }
771     qtable = gaiaDoubleQuotedSql (table);
772 /* checking if TABLE already exists */
773     sql =
774 	sqlite3_mprintf ("SELECT name FROM sqlite_master WHERE type = 'table' "
775 			 "AND Lower(name) = Lower(%Q)", table);
776     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
777     sqlite3_free (sql);
778     if (ret != SQLITE_OK)
779       {
780 	  if (!err_msg)
781 	      spatialite_e ("load shapefile error: <%s>\n",
782 			    sqlite3_errmsg (sqlite));
783 	  else
784 	      sprintf (err_msg, "load shapefile error: <%s>\n",
785 		       sqlite3_errmsg (sqlite));
786 	  goto clean_up;
787       }
788     while (1)
789       {
790 	  /* scrolling the result set */
791 	  ret = sqlite3_step (stmt);
792 	  if (ret == SQLITE_DONE)
793 	      break;		/* end of result set */
794 	  if (ret == SQLITE_ROW)
795 	      already_exists = 1;
796 	  else
797 	    {
798 		spatialite_e ("load shapefile error: <%s>\n",
799 			      sqlite3_errmsg (sqlite));
800 		break;
801 	    }
802       }
803     sqlite3_finalize (stmt);
804     if (already_exists)
805       {
806 	  if (!err_msg)
807 	      spatialite_e ("load shapefile error: table '%s' already exists\n",
808 			    table);
809 	  else
810 	      sprintf (err_msg,
811 		       "load shapefile error: table '%s' already exists\n",
812 		       table);
813 	  if (qtable)
814 	      free (qtable);
815 	  if (qpk_name)
816 	      free (qpk_name);
817 	  return 0;
818       }
819 /* checking if MetaData GEOMETRY_COLUMNS exists */
820     sql =
821 	"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'geometry_columns'";
822     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
823     if (ret != SQLITE_OK)
824       {
825 	  if (!err_msg)
826 	      spatialite_e ("load shapefile error: <%s>\n",
827 			    sqlite3_errmsg (sqlite));
828 	  else
829 	      sprintf (err_msg, "load shapefile error: <%s>\n",
830 		       sqlite3_errmsg (sqlite));
831 	  if (qtable)
832 	      free (qtable);
833 	  if (qpk_name)
834 	      free (qpk_name);
835 	  return 0;
836       }
837     while (1)
838       {
839 	  /* scrolling the result set */
840 	  ret = sqlite3_step (stmt);
841 	  if (ret == SQLITE_DONE)
842 	      break;		/* end of result set */
843 	  if (ret == SQLITE_ROW)
844 	      metadata = 1;
845 	  else
846 	    {
847 		spatialite_e ("load shapefile error: <%s>\n",
848 			      sqlite3_errmsg (sqlite));
849 		break;
850 	    }
851       }
852     sqlite3_finalize (stmt);
853     shp = gaiaAllocShapefile ();
854     if (mem_shape != NULL)
855       {
856 	  /* initializing Memory based files */
857 	  shp->memShx = &(mem_shape->shx);
858 	  shp->memShp = &(mem_shape->shp);
859 	  shp->memDbf = &(mem_shape->dbf);
860       }
861     gaiaOpenShpRead (shp, shp_path, charset, "UTF-8");
862     if (!(shp->Valid))
863       {
864 	  if (!err_msg)
865 	    {
866 		spatialite_e
867 		    ("load shapefile error: cannot open shapefile '%s'\n",
868 		     shp_path);
869 		if (shp->LastError)
870 		    spatialite_e ("\tcause: %s\n", shp->LastError);
871 	    }
872 	  else
873 	    {
874 		char extra[512];
875 		*extra = '\0';
876 		if (shp->LastError)
877 		    sprintf (extra, "\n\tcause: %s\n", shp->LastError);
878 		sprintf (err_msg,
879 			 "load shapefile error: cannot open shapefile '%s'%s",
880 			 shp_path, extra);
881 	    }
882 	  gaiaFreeShapefile (shp);
883 	  if (qtable)
884 	      free (qtable);
885 	  if (qpk_name)
886 	      free (qpk_name);
887 	  return 0;
888       }
889 /* checking for duplicate / illegal column names and antialising them */
890     col_cnt = 0;
891     dbf_field = shp->Dbf->First;
892     while (dbf_field)
893       {
894 	  /* counting DBF fields */
895 	  col_cnt++;
896 	  dbf_field = dbf_field->Next;
897       }
898     col_name = malloc (sizeof (char *) * col_cnt);
899     cnt = 0;
900     seed = 0;
901     if (pk_column != NULL)
902       {
903 	  /* validating the Primary Key column */
904 	  dbf_field = shp->Dbf->First;
905 	  while (dbf_field)
906 	    {
907 		if (strcasecmp (pk_column, dbf_field->Name) == 0)
908 		  {
909 		      /* ok, using this field as Primary Key */
910 		      pk_name = pk_column;
911 		      pk_autoincr = 0;
912 		      switch (dbf_field->Type)
913 			{
914 			case 'C':
915 			    pk_type = SQLITE_TEXT;
916 			    break;
917 			case 'N':
918 			    if (dbf_field->Decimals)
919 				pk_type = SQLITE_FLOAT;
920 			    else
921 			      {
922 				  if (dbf_field->Length <= 18)
923 				      pk_type = SQLITE_INTEGER;
924 				  else
925 				      pk_type = SQLITE_FLOAT;
926 			      }
927 			    break;
928 			case 'D':
929 			    if (text_dates)
930 				pk_type = SQLITE_TEXT;
931 			    else
932 				pk_type = SQLITE_FLOAT;
933 			    break;
934 			case 'F':
935 			    pk_type = SQLITE_FLOAT;
936 			    break;
937 			case 'L':
938 			    pk_type = SQLITE_INTEGER;
939 			    break;
940 			};
941 		  }
942 		dbf_field = dbf_field->Next;
943 	    }
944       }
945     if (pk_name == NULL)
946       {
947 	  if (pk_column != NULL)
948 	      pk_name = pk_column;
949 	  else
950 	      pk_name = "PK_UID";
951       }
952     if (!do_check_shp_unique_pk_values
953 	(sqlite, shp, srid, text_dates, pk_name, pk_type))
954       {
955 	  const char *old_pk = pk_name;
956 	  int antialias;
957 	  for (antialias = 0; antialias < 10; antialias++)
958 	    {
959 		/* searching an alternative Primary Key column name */
960 		int found = 0;
961 		pk_name = alt_pk[antialias];
962 		dbf_field = shp->Dbf->First;
963 		while (dbf_field)
964 		  {
965 		      if (strcasecmp (pk_name, dbf_field->Name) == 0)
966 			  found = 1;
967 		      dbf_field = dbf_field->Next;
968 		  }
969 		if (!found)
970 		  {
971 		      pk_autoincr = 1;
972 		      goto ok_pk;
973 		  }
974 	    }
975 	  pk_name = old_pk;
976       }
977   ok_pk:
978     casename = convert_dbf_colname_case (pk_name, colname_case);
979     qpk_name = gaiaDoubleQuotedSql (casename);
980     free (casename);
981     dbf_field = shp->Dbf->First;
982     while (dbf_field)
983       {
984 	  /* preparing column names */
985 	  char *xdummy = NULL;
986 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
987 	    {
988 		/* skipping the Primary Key field */
989 		dummy = dbf_field->Name;
990 		len = strlen (dummy);
991 		*(col_name + cnt) = malloc (len + 1);
992 		strcpy (*(col_name + cnt), dummy);
993 		cnt++;
994 		dbf_field = dbf_field->Next;
995 		continue;
996 	    }
997 	  dummy = dbf_field->Name;
998 	  dup = 0;
999 	  for (idup = 0; idup < cnt; idup++)
1000 	    {
1001 		if (strcasecmp (dummy, *(col_name + idup)) == 0)
1002 		    dup = 1;
1003 	    }
1004 	  if (strcasecmp (dummy, pk_name) == 0)
1005 	      dup = 1;
1006 	  if (strcasecmp (dummy, geo_column) == 0)
1007 	      dup = 1;
1008 	  if (dup)
1009 	    {
1010 		xdummy = sqlite3_mprintf ("COL_%d", seed++);
1011 		spatialite_e
1012 		    ("Warning: duplicated fieldName \"%s\" in shapefile \"%s\": "
1013 		     "renaming the second occurrence in table \"%s\" as \"%s\".\n",
1014 		     dummy, shp_path, table, xdummy);
1015 		dummy = xdummy;
1016 	    }
1017 	  len = strlen (dummy);
1018 	  *(col_name + cnt) = malloc (len + 1);
1019 	  strcpy (*(col_name + cnt), dummy);
1020 	  if (xdummy)
1021 	      sqlite3_free (xdummy);
1022 	  cnt++;
1023 	  dbf_field = dbf_field->Next;
1024       }
1025     if (verbose)
1026 	spatialite_e
1027 	    ("========\nLoading shapefile at '%s' into SQLite table '%s'\n",
1028 	     shp_path, table);
1029 /* starting a transaction */
1030     if (verbose)
1031 	spatialite_e ("\nBEGIN;\n");
1032     ret = sqlite3_exec (sqlite, "BEGIN", NULL, 0, &errMsg);
1033     if (ret != SQLITE_OK)
1034       {
1035 	  if (!err_msg)
1036 	      spatialite_e ("load shapefile error: <%s>\n", errMsg);
1037 	  else
1038 	      sprintf (err_msg, "load shapefile error: <%s>\n", errMsg);
1039 	  sqlite3_free (errMsg);
1040 	  sqlError = 1;
1041 	  goto clean_up;
1042       }
1043 /* creating the Table */
1044     gaiaOutBufferInitialize (&sql_statement);
1045     if (pk_type == SQLITE_TEXT)
1046       {
1047 	  sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
1048 				 "TEXT PRIMARY KEY NOT NULL", qtable, qpk_name);
1049       }
1050     else if (pk_type == SQLITE_FLOAT)
1051       {
1052 	  sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
1053 				 "DOUBLE PRIMARY KEY NOT NULL", qtable,
1054 				 qpk_name);
1055       }
1056     else
1057       {
1058 	  if (pk_autoincr)
1059 	      sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
1060 				     "INTEGER PRIMARY KEY AUTOINCREMENT",
1061 				     qtable, qpk_name);
1062 	  else
1063 	      sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
1064 				     "INTEGER NOT NULL PRIMARY KEY", qtable,
1065 				     qpk_name);
1066       }
1067     gaiaAppendToOutBuffer (&sql_statement, sql);
1068     sqlite3_free (sql);
1069     cnt = 0;
1070     dbf_field = shp->Dbf->First;
1071     while (dbf_field)
1072       {
1073 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
1074 	    {
1075 		/* skipping the Primary Key field */
1076 		dbf_field = dbf_field->Next;
1077 		cnt++;
1078 		continue;
1079 	    }
1080 	  casename = convert_dbf_colname_case (*(col_name + cnt), colname_case);
1081 	  xname = gaiaDoubleQuotedSql (casename);
1082 	  free (casename);
1083 	  sql = sqlite3_mprintf (",\n\"%s\"", xname);
1084 	  free (xname);
1085 	  gaiaAppendToOutBuffer (&sql_statement, sql);
1086 	  sqlite3_free (sql);
1087 	  cnt++;
1088 	  switch (dbf_field->Type)
1089 	    {
1090 	    case 'C':
1091 		gaiaAppendToOutBuffer (&sql_statement, " TEXT");
1092 		break;
1093 	    case 'N':
1094 		if (dbf_field->Decimals)
1095 		    gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
1096 		else
1097 		  {
1098 		      if (dbf_field->Length <= 18)
1099 			  gaiaAppendToOutBuffer (&sql_statement, " INTEGER");
1100 		      else
1101 			  gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
1102 		  }
1103 		break;
1104 	    case 'D':
1105 		if (text_dates)
1106 		    gaiaAppendToOutBuffer (&sql_statement, "TEXT");
1107 		else
1108 		    gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
1109 		break;
1110 	    case 'F':
1111 		gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
1112 		break;
1113 	    case 'L':
1114 		gaiaAppendToOutBuffer (&sql_statement, " INTEGER");
1115 		break;
1116 	    };
1117 	  dbf_field = dbf_field->Next;
1118       }
1119     if (metadata)
1120 	gaiaAppendToOutBuffer (&sql_statement, ")");
1121     else
1122       {
1123 	  casename = convert_dbf_colname_case (geo_column, colname_case);
1124 	  xname = gaiaDoubleQuotedSql (casename);
1125 	  free (casename);
1126 	  sql = sqlite3_mprintf (",\n\"%s\" BLOB)", xname);
1127 	  free (xname);
1128 	  gaiaAppendToOutBuffer (&sql_statement, sql);
1129 	  sqlite3_free (sql);
1130       }
1131     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
1132       {
1133 	  if (verbose)
1134 	      spatialite_e ("%s;\n", sql_statement.Buffer);
1135 	  ret = sqlite3_exec (sqlite, sql_statement.Buffer, NULL, 0, &errMsg);
1136       }
1137     else
1138 	ret = SQLITE_ERROR;
1139     gaiaOutBufferReset (&sql_statement);
1140     if (ret != SQLITE_OK)
1141       {
1142 	  if (!err_msg)
1143 	      spatialite_e ("load shapefile error: <%s>\n", errMsg);
1144 	  else
1145 	      sprintf (err_msg, "load shapefile error: <%s>\n", errMsg);
1146 	  sqlite3_free (errMsg);
1147 	  sqlError = 1;
1148 	  goto clean_up;
1149       }
1150     if (metadata)
1151       {
1152 	  /* creating Geometry column */
1153 	  switch (shp->Shape)
1154 	    {
1155 	    case GAIA_SHP_POINT:
1156 	    case GAIA_SHP_POINTM:
1157 	    case GAIA_SHP_POINTZ:
1158 		geom_type = "POINT";
1159 		break;
1160 	    case GAIA_SHP_MULTIPOINT:
1161 	    case GAIA_SHP_MULTIPOINTM:
1162 	    case GAIA_SHP_MULTIPOINTZ:
1163 		geom_type = "MULTIPOINT";
1164 		break;
1165 	    case GAIA_SHP_POLYLINE:
1166 	    case GAIA_SHP_POLYLINEM:
1167 	    case GAIA_SHP_POLYLINEZ:
1168 		if (xgtype == NULL)
1169 		  {
1170 		      /* auto-decting if MULTILINESTRING is required */
1171 		      gaiaShpAnalyze (shp);
1172 		      if (shp->EffectiveType == GAIA_LINESTRING)
1173 			  geom_type = "LINESTRING";
1174 		      else
1175 			  geom_type = "MULTILINESTRING";
1176 		  }
1177 		else
1178 		  {
1179 		      /* user-defined geometry type */
1180 		      if (strcmp (xgtype, "LINESTRING") == 0)
1181 			{
1182 			    geom_type = "LINESTRING";
1183 			    shp->EffectiveType = GAIA_LINESTRING;
1184 			    shp->EffectiveDims = GAIA_XY;
1185 			}
1186 		      if (strcmp (xgtype, "LINESTRINGZ") == 0)
1187 			{
1188 			    geom_type = "LINESTRING";
1189 			    shp->EffectiveType = GAIA_LINESTRING;
1190 			    shp->EffectiveDims = GAIA_XY_Z;
1191 			}
1192 		      if (strcmp (xgtype, "LINESTRINGM") == 0)
1193 			{
1194 			    geom_type = "LINESTRING";
1195 			    shp->EffectiveType = GAIA_LINESTRING;
1196 			    shp->EffectiveDims = GAIA_XY_M;
1197 			}
1198 		      if (strcmp (xgtype, "LINESTRINGZM") == 0)
1199 			{
1200 			    geom_type = "LINESTRING";
1201 			    shp->EffectiveType = GAIA_LINESTRING;
1202 			    shp->EffectiveDims = GAIA_XY_Z_M;
1203 			}
1204 		      if (strcmp (xgtype, "MULTILINESTRING") == 0)
1205 			{
1206 			    geom_type = "MULTILINESTRING";
1207 			    shp->EffectiveType = GAIA_MULTILINESTRING;
1208 			    shp->EffectiveDims = GAIA_XY;
1209 			}
1210 		      if (strcmp (xgtype, "MULTILINESTRINGZ") == 0)
1211 			{
1212 			    geom_type = "MULTILINESTRING";
1213 			    shp->EffectiveType = GAIA_MULTILINESTRING;
1214 			    shp->EffectiveDims = GAIA_XY_Z;
1215 			}
1216 		      if (strcmp (xgtype, "MULTILINESTRINGM") == 0)
1217 			{
1218 			    geom_type = "MULTILINESTRING";
1219 			    shp->EffectiveType = GAIA_MULTILINESTRING;
1220 			    shp->EffectiveDims = GAIA_XY_M;
1221 			}
1222 		      if (strcmp (xgtype, "MULTILINESTRINGZM") == 0)
1223 			{
1224 			    geom_type = "MULTILINESTRING";
1225 			    shp->EffectiveType = GAIA_MULTILINESTRING;
1226 			    shp->EffectiveDims = GAIA_XY_Z_M;
1227 			}
1228 		  }
1229 		break;
1230 	    case GAIA_SHP_POLYGON:
1231 	    case GAIA_SHP_POLYGONM:
1232 	    case GAIA_SHP_POLYGONZ:
1233 		if (xgtype == NULL)
1234 		  {
1235 		      /* auto-decting if MULTIPOLYGON is required */
1236 		      gaiaShpAnalyze (shp);
1237 		      if (shp->EffectiveType == GAIA_POLYGON)
1238 			  geom_type = "POLYGON";
1239 		      else
1240 			  geom_type = "MULTIPOLYGON";
1241 		  }
1242 		else
1243 		  {
1244 		      /* user-defined geometry type */
1245 		      if (strcmp (xgtype, "POLYGON") == 0)
1246 			{
1247 			    geom_type = "POLYGON";
1248 			    shp->EffectiveType = GAIA_POLYGON;
1249 			    shp->EffectiveDims = GAIA_XY;
1250 			}
1251 		      if (strcmp (xgtype, "POLYGONZ") == 0)
1252 			{
1253 			    geom_type = "POLYGON";
1254 			    shp->EffectiveType = GAIA_POLYGON;
1255 			    shp->EffectiveDims = GAIA_XY_Z;
1256 			}
1257 		      if (strcmp (xgtype, "POLYGONM") == 0)
1258 			{
1259 			    geom_type = "POLYGON";
1260 			    shp->EffectiveType = GAIA_POLYGON;
1261 			    shp->EffectiveDims = GAIA_XY_M;
1262 			}
1263 		      if (strcmp (xgtype, "POLYGONZM") == 0)
1264 			{
1265 			    geom_type = "POLYGON";
1266 			    shp->EffectiveType = GAIA_POLYGON;
1267 			    shp->EffectiveDims = GAIA_XY_Z_M;
1268 			}
1269 		      if (strcmp (xgtype, "MULTIPOLYGON") == 0)
1270 			{
1271 			    geom_type = "MULTIPOLYGON";
1272 			    shp->EffectiveType = GAIA_MULTIPOLYGON;
1273 			    shp->EffectiveDims = GAIA_XY;
1274 			}
1275 		      if (strcmp (xgtype, "MULTIPOLYGONZ") == 0)
1276 			{
1277 			    geom_type = "MULTIPOLYGON";
1278 			    shp->EffectiveType = GAIA_MULTIPOLYGON;
1279 			    shp->EffectiveDims = GAIA_XY_Z;
1280 			}
1281 		      if (strcmp (xgtype, "MULTIPOLYGONM") == 0)
1282 			{
1283 			    geom_type = "MULTIPOLYGON";
1284 			    shp->EffectiveType = GAIA_MULTIPOLYGON;
1285 			    shp->EffectiveDims = GAIA_XY_M;
1286 			}
1287 		      if (strcmp (xgtype, "MULTIPOLYGONZM") == 0)
1288 			{
1289 			    geom_type = "MULTIPOLYGON";
1290 			    shp->EffectiveType = GAIA_MULTIPOLYGON;
1291 			    shp->EffectiveDims = GAIA_XY_Z_M;
1292 			}
1293 		  }
1294 		break;
1295 	    };
1296 	  if (coerce2d)
1297 	      shp->EffectiveDims = GAIA_XY;
1298 	  switch (shp->EffectiveDims)
1299 	    {
1300 	    case GAIA_XY_Z:
1301 		txt_dims = "XYZ";
1302 		break;
1303 	    case GAIA_XY_M:
1304 		txt_dims = "XYM";
1305 		break;
1306 	    case GAIA_XY_Z_M:
1307 		txt_dims = "XYZM";
1308 		break;
1309 	    default:
1310 		txt_dims = "XY";
1311 		break;
1312 	    };
1313 	  if (geom_type == NULL)
1314 	    {
1315 		/* undefined Geometry Type */
1316 		const char *gt = "UNKNOWN";
1317 		switch (shp->Shape)
1318 		  {
1319 		  case GAIA_SHP_POINT:
1320 		  case GAIA_SHP_POINTM:
1321 		  case GAIA_SHP_POINTZ:
1322 		      gt = "POINT";
1323 		      break;
1324 		  case GAIA_SHP_MULTIPOINT:
1325 		  case GAIA_SHP_MULTIPOINTM:
1326 		  case GAIA_SHP_MULTIPOINTZ:
1327 		      gt = "MULTIPOINT";
1328 		      break;
1329 		  case GAIA_SHP_POLYLINE:
1330 		  case GAIA_SHP_POLYLINEM:
1331 		  case GAIA_SHP_POLYLINEZ:
1332 		      if (shp->EffectiveType == GAIA_LINESTRING)
1333 			  gt = "LINESTRING";
1334 		      else
1335 			  gt = "MULTILINESTRING";
1336 		      break;
1337 		  case GAIA_SHP_POLYGON:
1338 		  case GAIA_SHP_POLYGONM:
1339 		  case GAIA_SHP_POLYGONZ:
1340 		      if (shp->EffectiveType == GAIA_POLYGON)
1341 			  gt = "POLYGON";
1342 		      else
1343 			  gt = "MULTIPOLYGON";
1344 		      break;
1345 		  };
1346 		if (!err_msg)
1347 		    spatialite_e
1348 			("Error: mismatching type: requested %s but Shape is %s %s\n",
1349 			 xgtype, gt, txt_dims);
1350 		else
1351 		    sprintf (err_msg,
1352 			     "Error: mismatching type: requested %s but Shape is %s %s\n",
1353 			     xgtype, gt, txt_dims);
1354 		sqlError = 1;
1355 		goto clean_up;
1356 	    }
1357 	  casename = convert_dbf_colname_case (geo_column, colname_case);
1358 	  sql = sqlite3_mprintf ("SELECT AddGeometryColumn(%Q, %Q, %d, %Q, %Q)",
1359 				 table, casename, srid, geom_type, txt_dims);
1360 	  free (casename);
1361 	  if (verbose)
1362 	      spatialite_e ("%s;\n", sql);
1363 	  ret = sqlite3_exec (sqlite, sql, NULL, 0, &errMsg);
1364 	  sqlite3_free (sql);
1365 	  if (ret != SQLITE_OK)
1366 	    {
1367 		if (!err_msg)
1368 		    spatialite_e ("load shapefile error: <%s>\n", errMsg);
1369 		else
1370 		    sprintf (err_msg, "load shapefile error: <%s>\n", errMsg);
1371 		sqlite3_free (errMsg);
1372 		sqlError = 1;
1373 		goto clean_up;
1374 	    }
1375 	  if (spatial_index)
1376 	    {
1377 		/* creating the Spatial Index */
1378 		sql = sqlite3_mprintf ("SELECT CreateSpatialIndex(%Q, %Q)",
1379 				       table, geo_column);
1380 		ret = sqlite3_exec (sqlite, sql, NULL, 0, &errMsg);
1381 		sqlite3_free (sql);
1382 		if (ret != SQLITE_OK)
1383 		  {
1384 		      if (!err_msg)
1385 			  spatialite_e ("load shapefile error: <%s>\n", errMsg);
1386 		      else
1387 			  sprintf (err_msg, "load shapefile error: <%s>\n",
1388 				   errMsg);
1389 		      sqlite3_free (errMsg);
1390 		      sqlError = 1;
1391 		      goto clean_up;
1392 		  }
1393 	    }
1394       }
1395     else
1396       {
1397 	  /* no Metadata */
1398 	  if (shp->Shape == GAIA_SHP_POLYLINE
1399 	      || shp->Shape == GAIA_SHP_POLYLINEM
1400 	      || shp->Shape == GAIA_SHP_POLYLINEZ
1401 	      || shp->Shape == GAIA_SHP_POLYGON
1402 	      || shp->Shape == GAIA_SHP_POLYGONM
1403 	      || shp->Shape == GAIA_SHP_POLYGONZ)
1404 	    {
1405 		/*
1406 		   / fixing anyway the Geometry type for
1407 		   / LINESTRING/MULTILINESTRING or
1408 		   / POLYGON/MULTIPOLYGON
1409 		 */
1410 		gaiaShpAnalyze (shp);
1411 	    }
1412       }
1413     /* preparing the INSERT INTO parametrerized statement */
1414     gaiaOutBufferInitialize (&sql_statement);
1415     sql = sqlite3_mprintf ("INSERT INTO \"%s\" (\"%s\",", qtable, qpk_name);
1416     gaiaAppendToOutBuffer (&sql_statement, sql);
1417     sqlite3_free (sql);
1418     cnt = 0;
1419     dbf_field = shp->Dbf->First;
1420     while (dbf_field)
1421       {
1422 	  /* columns corresponding to some DBF attribute */
1423 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
1424 	    {
1425 		/* skipping the Primary Key field */
1426 		dbf_field = dbf_field->Next;
1427 		cnt++;
1428 		continue;
1429 	    }
1430 	  xname = gaiaDoubleQuotedSql (*(col_name + cnt++));
1431 	  sql = sqlite3_mprintf ("\"%s\" ,", xname);
1432 	  free (xname);
1433 	  gaiaAppendToOutBuffer (&sql_statement, sql);
1434 	  sqlite3_free (sql);
1435 	  dbf_field = dbf_field->Next;
1436       }
1437     xname = gaiaDoubleQuotedSql (geo_column);	/* the GEOMETRY column */
1438     sql = sqlite3_mprintf ("\"%s\")\n VALUES (?", xname);
1439     free (xname);
1440     gaiaAppendToOutBuffer (&sql_statement, sql);
1441     sqlite3_free (sql);
1442     dbf_field = shp->Dbf->First;
1443     while (dbf_field)
1444       {
1445 	  /* column values */
1446 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
1447 	    {
1448 		/* skipping the Primary Key field */
1449 		dbf_field = dbf_field->Next;
1450 		continue;
1451 	    }
1452 	  gaiaAppendToOutBuffer (&sql_statement, ", ?");
1453 	  dbf_field = dbf_field->Next;
1454       }
1455     gaiaAppendToOutBuffer (&sql_statement, ", ?)");	/* the GEOMETRY column */
1456     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
1457 	ret =
1458 	    sqlite3_prepare_v2 (sqlite, sql_statement.Buffer,
1459 				strlen (sql_statement.Buffer), &stmt, NULL);
1460     else
1461 	ret = SQLITE_ERROR;
1462     gaiaOutBufferReset (&sql_statement);
1463     if (ret != SQLITE_OK)
1464       {
1465 	  if (!err_msg)
1466 	      spatialite_e ("load shapefile error: <%s>\n",
1467 			    sqlite3_errmsg (sqlite));
1468 	  else
1469 	      sprintf (err_msg, "load shapefile error: <%s>\n",
1470 		       sqlite3_errmsg (sqlite));
1471 	  sqlError = 1;
1472 	  goto clean_up;
1473       }
1474     current_row = 0;
1475     while (1)
1476       {
1477 	  /* inserting rows from shapefile */
1478 	  ret = gaiaReadShpEntity_ex (shp, current_row, srid, text_dates);
1479 	  if (ret < 0)
1480 	    {
1481 		/* found a DBF deleted record */
1482 		current_row++;
1483 		deleted++;
1484 		continue;
1485 	    }
1486 	  if (!ret)
1487 	    {
1488 		if (!(shp->LastError))	/* normal SHP EOF */
1489 		    break;
1490 		if (!err_msg)
1491 		    spatialite_e ("%s\n", shp->LastError);
1492 		else
1493 		    sprintf (err_msg, "%s\n", shp->LastError);
1494 		sqlError = 1;
1495 		sqlite3_finalize (stmt);
1496 		goto clean_up;
1497 	    }
1498 	  current_row++;
1499 	  /* binding query params */
1500 	  sqlite3_reset (stmt);
1501 	  sqlite3_clear_bindings (stmt);
1502 	  pk_set = 0;
1503 	  cnt = 0;
1504 	  dbf_field = shp->Dbf->First;
1505 	  while (dbf_field)
1506 	    {
1507 		/* Primary Key value */
1508 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
1509 		  {
1510 		      if (pk_type == SQLITE_TEXT)
1511 			  sqlite3_bind_text (stmt, 1,
1512 					     dbf_field->Value->TxtValue,
1513 					     strlen (dbf_field->
1514 						     Value->TxtValue),
1515 					     SQLITE_STATIC);
1516 		      else if (pk_type == SQLITE_FLOAT)
1517 			  sqlite3_bind_double (stmt, 1,
1518 					       dbf_field->Value->DblValue);
1519 		      else
1520 			  sqlite3_bind_int64 (stmt, 1,
1521 					      dbf_field->Value->IntValue);
1522 		      pk_set = 1;
1523 		  }
1524 		dbf_field = dbf_field->Next;
1525 	    }
1526 	  if (!pk_set)
1527 	      sqlite3_bind_int (stmt, 1, current_row);
1528 	  cnt = 0;
1529 	  dbf_field = shp->Dbf->First;
1530 	  while (dbf_field)
1531 	    {
1532 		/* column values */
1533 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
1534 		  {
1535 		      /* skipping the Primary Key field */
1536 		      dbf_field = dbf_field->Next;
1537 		      continue;
1538 		  }
1539 		if (!(dbf_field->Value))
1540 		    sqlite3_bind_null (stmt, cnt + 2);
1541 		else
1542 		  {
1543 		      switch (dbf_field->Value->Type)
1544 			{
1545 			case GAIA_INT_VALUE:
1546 			    sqlite3_bind_int64 (stmt, cnt + 2,
1547 						dbf_field->Value->IntValue);
1548 			    break;
1549 			case GAIA_DOUBLE_VALUE:
1550 			    sqlite3_bind_double (stmt, cnt + 2,
1551 						 dbf_field->Value->DblValue);
1552 			    break;
1553 			case GAIA_TEXT_VALUE:
1554 			    sqlite3_bind_text (stmt, cnt + 2,
1555 					       dbf_field->Value->TxtValue,
1556 					       strlen (dbf_field->
1557 						       Value->TxtValue),
1558 					       SQLITE_STATIC);
1559 			    break;
1560 			default:
1561 			    sqlite3_bind_null (stmt, cnt + 2);
1562 			    break;
1563 			}
1564 		  }
1565 		cnt++;
1566 		dbf_field = dbf_field->Next;
1567 	    }
1568 	  if (shp->Dbf->Geometry)
1569 	    {
1570 		if (compressed)
1571 		    gaiaToCompressedBlobWkb (shp->Dbf->Geometry, &blob,
1572 					     &blob_size);
1573 		else
1574 		    gaiaToSpatiaLiteBlobWkb (shp->Dbf->Geometry, &blob,
1575 					     &blob_size);
1576 		sqlite3_bind_blob (stmt, cnt + 2, blob, blob_size, free);
1577 	    }
1578 	  else
1579 	    {
1580 		/* handling a NULL-Geometry */
1581 		sqlite3_bind_null (stmt, cnt + 2);
1582 	    }
1583 	  ret = sqlite3_step (stmt);
1584 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1585 	      ;
1586 	  else
1587 	    {
1588 		if (!err_msg)
1589 		    spatialite_e ("load shapefile error: <%s>\n",
1590 				  sqlite3_errmsg (sqlite));
1591 		else
1592 		    sprintf (err_msg, "load shapefile error: <%s>\n",
1593 			     sqlite3_errmsg (sqlite));
1594 		sqlite3_finalize (stmt);
1595 		sqlError = 1;
1596 		goto clean_up;
1597 	    }
1598       }
1599     sqlite3_finalize (stmt);
1600   clean_up:
1601     if (qtable)
1602 	free (qtable);
1603     if (qpk_name)
1604 	free (qpk_name);
1605     gaiaFreeShapefile (shp);
1606     if (col_name)
1607       {
1608 	  /* releasing memory allocation for column names */
1609 	  for (cnt = 0; cnt < col_cnt; cnt++)
1610 	      free (*(col_name + cnt));
1611 	  free (col_name);
1612       }
1613     if (sqlError)
1614       {
1615 	  /* some error occurred - ROLLBACK */
1616 	  if (verbose)
1617 	      spatialite_e ("ROLLBACK;\n");
1618 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, 0, &errMsg);
1619 	  if (ret != SQLITE_OK)
1620 	    {
1621 		spatialite_e ("load shapefile error: <%s>\n", errMsg);
1622 		sqlite3_free (errMsg);
1623 	    }
1624 	  return 0;
1625       }
1626     else
1627       {
1628 	  /* ok - confirming pending transaction - COMMIT */
1629 	  if (verbose)
1630 	      spatialite_e ("COMMIT;\n");
1631 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, 0, &errMsg);
1632 	  if (ret != SQLITE_OK)
1633 	    {
1634 		if (!err_msg)
1635 		    spatialite_e ("load shapefile error: <%s>\n", errMsg);
1636 		else
1637 		    sprintf (err_msg, "load shapefile error: <%s>\n", errMsg);
1638 		sqlite3_free (errMsg);
1639 		return 0;
1640 	    }
1641 	  if (rows)
1642 	      *rows = current_row - deleted;
1643 	  if (verbose)
1644 	      spatialite_e
1645 		  ("\nInserted %d rows into '%s' from SHAPEFILE\n========\n",
1646 		   current_row - deleted, table);
1647 	  if (err_msg)
1648 	      sprintf (err_msg, "Inserted %d rows into '%s' from SHAPEFILE",
1649 		       current_row - deleted, table);
1650 	  return 1;
1651       }
1652 }
1653 
1654 SPATIALITE_DECLARE int
load_shapefile_ex3(sqlite3 * sqlite,const char * shp_path,const char * table,const char * charset,int srid,const char * g_column,const char * gtype,const char * pk_column,int coerce2d,int compressed,int verbose,int spatial_index,int text_dates,int * rows,int colname_case,char * err_msg)1655 load_shapefile_ex3 (sqlite3 * sqlite, const char *shp_path, const char *table,
1656 		    const char *charset, int srid, const char *g_column,
1657 		    const char *gtype, const char *pk_column, int coerce2d,
1658 		    int compressed, int verbose, int spatial_index,
1659 		    int text_dates, int *rows, int colname_case, char *err_msg)
1660 {
1661     return load_shapefile_common (NULL, sqlite, shp_path, table, charset, srid,
1662 				  g_column, gtype, pk_column, coerce2d,
1663 				  compressed, verbose, spatial_index,
1664 				  text_dates, rows, colname_case, err_msg);
1665 }
1666 
1667 static int
do_check_dbf_unique_pk_values(sqlite3 * sqlite,gaiaDbfPtr dbf,int text_dates,const char * pk_name,int pk_type)1668 do_check_dbf_unique_pk_values (sqlite3 * sqlite, gaiaDbfPtr dbf, int text_dates,
1669 			       const char *pk_name, int pk_type)
1670 {
1671 /* checking for duplicate PK values */
1672     char *sql;
1673     sqlite3_stmt *stmt = NULL;
1674     gaiaDbfFieldPtr dbf_field;
1675     int ret;
1676     int deleted;
1677     int duplicates = 0;
1678     int current_row = 0;
1679 
1680     sql = "CREATE TABLE TEMP.check_unique_pk (pkey ANYVALUE)";
1681     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
1682     if (ret != SQLITE_OK)
1683 	return 0;
1684 
1685     sql = "INSERT INTO TEMP.check_unique_pk (pkey) VALUES (?)";
1686     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
1687     if (ret != SQLITE_OK)
1688 	goto error;
1689 
1690     sqlite3_exec (sqlite, "BEGIN", NULL, NULL, NULL);
1691 
1692     while (1)
1693       {
1694 	  /* reading rows from shapefile */
1695 	  int ok_insert = 0;
1696 	  ret = gaiaReadDbfEntity_ex (dbf, current_row, &deleted, text_dates);
1697 	  if (!ret)
1698 	      break;
1699 	  current_row++;
1700 	  if (deleted)
1701 	    {
1702 		/* skipping DBF deleted row */
1703 		continue;
1704 	    }
1705 	  /* binding query params */
1706 	  sqlite3_reset (stmt);
1707 	  sqlite3_clear_bindings (stmt);
1708 	  dbf_field = dbf->Dbf->First;
1709 	  while (dbf_field)
1710 	    {
1711 		/* Primary Key value */
1712 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
1713 		  {
1714 		      if (pk_type == SQLITE_TEXT)
1715 			{
1716 			    ok_insert = 1;
1717 			    sqlite3_bind_text (stmt, 1,
1718 					       dbf_field->Value->TxtValue,
1719 					       strlen (dbf_field->
1720 						       Value->TxtValue),
1721 					       SQLITE_STATIC);
1722 			}
1723 		      else if (pk_type == SQLITE_FLOAT)
1724 			{
1725 			    ok_insert = 1;
1726 			    sqlite3_bind_double (stmt, 1,
1727 						 dbf_field->Value->DblValue);
1728 			}
1729 		      else
1730 			{
1731 			    ok_insert = 1;
1732 			    sqlite3_bind_int64 (stmt, 1,
1733 						dbf_field->Value->IntValue);
1734 			}
1735 		  }
1736 		dbf_field = dbf_field->Next;
1737 	    }
1738 	  if (ok_insert)
1739 	    {
1740 		ret = sqlite3_step (stmt);
1741 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1742 		    ;
1743 		else
1744 		    goto error;
1745 	    }
1746       }
1747     sqlite3_finalize (stmt);
1748     stmt = NULL;
1749     sqlite3_exec (sqlite, "COMMIT", NULL, NULL, NULL);
1750 
1751     sql = "SELECT Count(*) FROM TEMP.check_unique_pk GROUP BY pkey";
1752     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
1753     if (ret != SQLITE_OK)
1754 	goto error;
1755 
1756     while (1)
1757       {
1758 	  /* scrolling the result set rows */
1759 	  ret = sqlite3_step (stmt);
1760 	  if (ret == SQLITE_DONE)
1761 	      break;		/* end of result set */
1762 	  if (ret == SQLITE_ROW)
1763 	    {
1764 		if (sqlite3_column_int (stmt, 0) > 1)
1765 		    duplicates = 1;
1766 	    }
1767       }
1768     sqlite3_finalize (stmt);
1769 
1770     sqlite3_exec (sqlite, "DROP TABLE TEMP.check_unique_pk", NULL, NULL, NULL);
1771     if (duplicates)
1772 	return 0;
1773     else
1774 	return 1;
1775 
1776   error:
1777     if (stmt != NULL)
1778 	sqlite3_finalize (stmt);
1779     sqlite3_exec (sqlite, "COMMIT", NULL, NULL, NULL);
1780     sqlite3_exec (sqlite, "DROP TABLE TEMP.check_unique_pk", NULL, NULL, NULL);
1781     return 0;
1782 }
1783 
1784 SPATIALITE_DECLARE int
load_dbf_common(struct zip_mem_shapefile * mem_shape,sqlite3 * sqlite,const char * dbf_path,const char * table,const char * pk_column,const char * charset,int verbose,int text_dates,int * rows,int colname_case,char * err_msg)1785 load_dbf_common (struct zip_mem_shapefile *mem_shape, sqlite3 * sqlite,
1786 		 const char *dbf_path, const char *table, const char *pk_column,
1787 		 const char *charset, int verbose, int text_dates, int *rows,
1788 		 int colname_case, char *err_msg)
1789 {
1790     sqlite3_stmt *stmt;
1791     int ret;
1792     char *errMsg = NULL;
1793     char *sql;
1794     char *dummy;
1795     char *xname;
1796     int already_exists = 0;
1797     int sqlError = 0;
1798     gaiaDbfPtr dbf = NULL;
1799     gaiaDbfFieldPtr dbf_field;
1800     int cnt;
1801     int col_cnt;
1802     int seed;
1803     int len;
1804     int dup;
1805     int idup;
1806     int current_row = 0;
1807     char **col_name = NULL;
1808     int deleted;
1809     char *qtable = NULL;
1810     char *qpk_name = NULL;
1811     const char *pk_name = NULL;
1812     char *casename;
1813     int pk_autoincr = 1;
1814     gaiaOutBuffer sql_statement;
1815     int pk_type = SQLITE_INTEGER;
1816     int pk_set;
1817     const char *alt_pk[10] =
1818 	{ "PK_ALT0", "PK_ALT1", "PK_ALT2", "PK_ALT3", "PK_ALT4", "PK_ALT5",
1819 	"PK_ALT6", "PK_ALT7", "PK_ALT8", "PK_ALT9"
1820     };
1821     qtable = gaiaDoubleQuotedSql (table);
1822     if (rows)
1823 	*rows = -1;
1824 /* checking if TABLE already exists */
1825     sql = sqlite3_mprintf ("SELECT name FROM sqlite_master WHERE "
1826 			   "type = 'table' AND Lower(name) = Lower(%Q)", table);
1827     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
1828     sqlite3_free (sql);
1829     if (ret != SQLITE_OK)
1830       {
1831 	  if (!err_msg)
1832 	      spatialite_e ("load DBF error: <%s>\n", sqlite3_errmsg (sqlite));
1833 	  else
1834 	      sprintf (err_msg, "load DBF error: <%s>\n",
1835 		       sqlite3_errmsg (sqlite));
1836 	  if (qtable)
1837 	      free (qtable);
1838 	  if (qpk_name)
1839 	      free (qpk_name);
1840 	  return 0;
1841       }
1842     while (1)
1843       {
1844 	  /* scrolling the result set */
1845 	  ret = sqlite3_step (stmt);
1846 	  if (ret == SQLITE_DONE)
1847 	      break;		/* end of result set */
1848 	  if (ret == SQLITE_ROW)
1849 	      already_exists = 1;
1850 	  else
1851 	    {
1852 		spatialite_e ("load DBF error: <%s>\n",
1853 			      sqlite3_errmsg (sqlite));
1854 		break;
1855 	    }
1856       }
1857     sqlite3_finalize (stmt);
1858     if (already_exists)
1859       {
1860 	  if (!err_msg)
1861 	      spatialite_e ("load DBF error: table '%s' already exists\n",
1862 			    table);
1863 	  else
1864 	      sprintf (err_msg, "load DBF error: table '%s' already exists\n",
1865 		       table);
1866 	  if (qtable)
1867 	      free (qtable);
1868 	  if (qpk_name)
1869 	      free (qpk_name);
1870 	  return 0;
1871       }
1872     dbf = gaiaAllocDbf ();
1873     if (mem_shape != NULL)
1874       {
1875 	  /* initializing Memory based files */
1876 	  dbf->memDbf = &(mem_shape->dbf);
1877       }
1878     gaiaOpenDbfRead (dbf, dbf_path, charset, "UTF-8");
1879     if (!(dbf->Valid))
1880       {
1881 	  if (!err_msg)
1882 	    {
1883 		spatialite_e ("load DBF error: cannot open '%s'\n", dbf_path);
1884 		if (dbf->LastError)
1885 		    spatialite_e ("\tcause: %s\n", dbf->LastError);
1886 	    }
1887 	  else
1888 	    {
1889 		char extra[512];
1890 		*extra = '\0';
1891 		if (dbf->LastError)
1892 		    sprintf (extra, "\n\tcause: %s", dbf->LastError);
1893 		sprintf (err_msg, "load DBF error: cannot open '%s'%s",
1894 			 dbf_path, extra);
1895 	    }
1896 	  gaiaFreeDbf (dbf);
1897 	  if (qtable)
1898 	      free (qtable);
1899 	  if (qpk_name)
1900 	      free (qpk_name);
1901 	  return 0;
1902       }
1903 /* checking for duplicate / illegal column names and antialising them */
1904     col_cnt = 0;
1905     dbf_field = dbf->Dbf->First;
1906     while (dbf_field)
1907       {
1908 	  /* counting DBF fields */
1909 	  col_cnt++;
1910 	  dbf_field = dbf_field->Next;
1911       }
1912     col_name = malloc (sizeof (char *) * col_cnt);
1913     cnt = 0;
1914     seed = 0;
1915     if (pk_column != NULL)
1916       {
1917 	  /* validating the Primary Key column */
1918 	  dbf_field = dbf->Dbf->First;
1919 	  while (dbf_field)
1920 	    {
1921 		if (strcasecmp (pk_column, dbf_field->Name) == 0)
1922 		  {
1923 		      /* ok, using this field as Primary Key */
1924 		      pk_name = pk_column;
1925 		      pk_autoincr = 0;
1926 		      switch (dbf_field->Type)
1927 			{
1928 			case 'C':
1929 			    pk_type = SQLITE_TEXT;
1930 			    break;
1931 			case 'N':
1932 			    if (dbf_field->Decimals)
1933 				pk_type = SQLITE_FLOAT;
1934 			    else
1935 			      {
1936 				  if (dbf_field->Length <= 18)
1937 				      pk_type = SQLITE_INTEGER;
1938 				  else
1939 				      pk_type = SQLITE_FLOAT;
1940 			      }
1941 			    break;
1942 			case 'D':
1943 			    if (text_dates)
1944 				pk_type = SQLITE_TEXT;
1945 			    else
1946 				pk_type = SQLITE_FLOAT;
1947 			    break;
1948 			case 'F':
1949 			    pk_type = SQLITE_FLOAT;
1950 			    break;
1951 			case 'L':
1952 			    pk_type = SQLITE_INTEGER;
1953 			    break;
1954 			};
1955 		  }
1956 		dbf_field = dbf_field->Next;
1957 	    }
1958       }
1959     if (pk_name == NULL)
1960       {
1961 	  if (pk_column != NULL)
1962 	      pk_name = pk_column;
1963 	  else
1964 	      pk_name = "PK_UID";
1965       }
1966     if (!do_check_dbf_unique_pk_values
1967 	(sqlite, dbf, text_dates, pk_name, pk_type))
1968       {
1969 	  const char *old_pk = pk_name;
1970 	  int antialias;
1971 	  for (antialias = 0; antialias < 10; antialias++)
1972 	    {
1973 		/* searching an alternative Primary Key column name */
1974 		int found = 0;
1975 		pk_name = alt_pk[antialias];
1976 		dbf_field = dbf->Dbf->First;
1977 		while (dbf_field)
1978 		  {
1979 		      if (strcasecmp (pk_name, dbf_field->Name) == 0)
1980 			  found = 1;
1981 		      dbf_field = dbf_field->Next;
1982 		  }
1983 		if (!found)
1984 		  {
1985 		      pk_autoincr = 1;
1986 		      goto ok_pk;
1987 		  }
1988 	    }
1989 	  pk_name = old_pk;
1990       }
1991   ok_pk:
1992     casename = convert_dbf_colname_case (pk_name, colname_case);
1993     qpk_name = gaiaDoubleQuotedSql (casename);
1994     free (casename);
1995     dbf_field = dbf->Dbf->First;
1996     while (dbf_field)
1997       {
1998 	  /* preparing column names */
1999 	  char *xdummy = NULL;
2000 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
2001 	    {
2002 		/* skipping the Primary Key field */
2003 		dummy = dbf_field->Name;
2004 		len = strlen (dummy);
2005 		*(col_name + cnt) = malloc (len + 1);
2006 		strcpy (*(col_name + cnt), dummy);
2007 		cnt++;
2008 		dbf_field = dbf_field->Next;
2009 		continue;
2010 	    }
2011 	  dummy = dbf_field->Name;
2012 	  dup = 0;
2013 	  for (idup = 0; idup < cnt; idup++)
2014 	    {
2015 		if (strcasecmp (dummy, *(col_name + idup)) == 0)
2016 		    dup = 1;
2017 	    }
2018 	  if (dup)
2019 	    {
2020 		xdummy = sqlite3_mprintf ("COL_%d", seed++);
2021 		dummy = xdummy;
2022 	    }
2023 	  len = strlen (dummy);
2024 	  *(col_name + cnt) = malloc (len + 1);
2025 	  strcpy (*(col_name + cnt), dummy);
2026 	  if (xdummy)
2027 	      sqlite3_free (xdummy);
2028 	  cnt++;
2029 	  dbf_field = dbf_field->Next;
2030       }
2031     if (verbose)
2032 	spatialite_e ("========\nLoading DBF at '%s' into SQLite table '%s'\n",
2033 		      dbf_path, table);
2034 /* starting a transaction */
2035     if (verbose)
2036 	spatialite_e ("\nBEGIN;\n");
2037     ret = sqlite3_exec (sqlite, "BEGIN", NULL, 0, &errMsg);
2038     if (ret != SQLITE_OK)
2039       {
2040 	  if (!err_msg)
2041 	      spatialite_e ("load DBF error: <%s>\n", errMsg);
2042 	  else
2043 	      sprintf (err_msg, "load DBF error: <%s>\n", errMsg);
2044 	  sqlite3_free (errMsg);
2045 	  sqlError = 1;
2046 	  goto clean_up;
2047       }
2048 /* creating the Table */
2049     gaiaOutBufferInitialize (&sql_statement);
2050     if (pk_type == SQLITE_TEXT)
2051       {
2052 	  sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
2053 				 "TEXT PRIMARY KEY NOT NULL", qtable, qpk_name);
2054       }
2055     else if (pk_type == SQLITE_FLOAT)
2056       {
2057 	  sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
2058 				 "DOUBLE PRIMARY KEY NOT NULL", qtable,
2059 				 qpk_name);
2060       }
2061     else
2062       {
2063 	  if (pk_autoincr)
2064 	      sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
2065 				     "INTEGER PRIMARY KEY AUTOINCREMENT",
2066 				     qtable, qpk_name);
2067 	  else
2068 	      sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n\"%s\" "
2069 				     "INTEGER NOT NULL PRIMARY KEY", qtable,
2070 				     qpk_name);
2071       }
2072     gaiaAppendToOutBuffer (&sql_statement, sql);
2073     sqlite3_free (sql);
2074     cnt = 0;
2075     dbf_field = dbf->Dbf->First;
2076     while (dbf_field)
2077       {
2078 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
2079 	    {
2080 		/* skipping the Primary Key field */
2081 		dbf_field = dbf_field->Next;
2082 		cnt++;
2083 		continue;
2084 	    }
2085 	  casename = convert_dbf_colname_case (*(col_name + cnt), colname_case);
2086 	  xname = gaiaDoubleQuotedSql (casename);
2087 	  free (casename);
2088 	  sql = sqlite3_mprintf (",\n\"%s\"", xname);
2089 	  free (xname);
2090 	  gaiaAppendToOutBuffer (&sql_statement, sql);
2091 	  sqlite3_free (sql);
2092 	  cnt++;
2093 	  switch (dbf_field->Type)
2094 	    {
2095 	    case 'C':
2096 		gaiaAppendToOutBuffer (&sql_statement, " TEXT");
2097 		break;
2098 	    case 'N':
2099 		if (dbf_field->Decimals)
2100 		    gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
2101 		else
2102 		  {
2103 		      if (dbf_field->Length <= 18)
2104 			  gaiaAppendToOutBuffer (&sql_statement, " INTEGER");
2105 		      else
2106 			  gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
2107 		  }
2108 		break;
2109 	    case 'D':
2110 		if (text_dates)
2111 		    gaiaAppendToOutBuffer (&sql_statement, " TEXT");
2112 		else
2113 		    gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
2114 		break;
2115 	    case 'F':
2116 		gaiaAppendToOutBuffer (&sql_statement, " DOUBLE");
2117 		break;
2118 	    case 'L':
2119 		gaiaAppendToOutBuffer (&sql_statement, " INTEGER");
2120 		break;
2121 	    };
2122 	  dbf_field = dbf_field->Next;
2123       }
2124     gaiaAppendToOutBuffer (&sql_statement, ")");
2125     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
2126       {
2127 	  if (verbose)
2128 	      spatialite_e ("%s;\n", sql_statement.Buffer);
2129 	  ret = sqlite3_exec (sqlite, sql_statement.Buffer, NULL, 0, &errMsg);
2130       }
2131     else
2132 	ret = SQLITE_ERROR;
2133     gaiaOutBufferReset (&sql_statement);
2134     if (ret != SQLITE_OK)
2135       {
2136 	  if (!err_msg)
2137 	      spatialite_e ("load DBF error: <%s>\n", errMsg);
2138 	  else
2139 	      sprintf (err_msg, "load DBF error: <%s>\n", errMsg);
2140 	  sqlite3_free (errMsg);
2141 	  sqlError = 1;
2142 	  goto clean_up;
2143       }
2144     /* preparing the INSERT INTO parametrerized statement */
2145     sql = sqlite3_mprintf ("INSERT INTO \"%s\" (\"%s\"", qtable, qpk_name);
2146     gaiaAppendToOutBuffer (&sql_statement, sql);
2147     sqlite3_free (sql);
2148     cnt = 0;
2149     dbf_field = dbf->Dbf->First;
2150     while (dbf_field)
2151       {
2152 	  /* columns corresponding to some DBF attribute */
2153 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
2154 	    {
2155 		/* skipping the Primary Key field */
2156 		dbf_field = dbf_field->Next;
2157 		cnt++;
2158 		continue;
2159 	    }
2160 	  xname = gaiaDoubleQuotedSql (*(col_name + cnt++));
2161 	  sql = sqlite3_mprintf (",\"%s\"", xname);
2162 	  free (xname);
2163 	  gaiaAppendToOutBuffer (&sql_statement, sql);
2164 	  sqlite3_free (sql);
2165 	  dbf_field = dbf_field->Next;
2166       }
2167     gaiaAppendToOutBuffer (&sql_statement, ")\nVALUES (?");
2168     dbf_field = dbf->Dbf->First;
2169     while (dbf_field)
2170       {
2171 	  /* column values */
2172 	  if (strcasecmp (pk_name, dbf_field->Name) == 0)
2173 	    {
2174 		/* skipping the Primary Key field */
2175 		dbf_field = dbf_field->Next;
2176 		continue;
2177 	    }
2178 	  gaiaAppendToOutBuffer (&sql_statement, ", ?");
2179 	  dbf_field = dbf_field->Next;
2180       }
2181     gaiaAppendToOutBuffer (&sql_statement, ")");
2182     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
2183 	ret =
2184 	    sqlite3_prepare_v2 (sqlite, sql_statement.Buffer,
2185 				strlen (sql_statement.Buffer), &stmt, NULL);
2186     else
2187 	ret = SQLITE_ERROR;
2188     gaiaOutBufferReset (&sql_statement);
2189     if (ret != SQLITE_OK)
2190       {
2191 	  if (!err_msg)
2192 	      spatialite_e ("load DBF error: <%s>\n", sqlite3_errmsg (sqlite));
2193 	  else
2194 	      sprintf (err_msg, "load DBF error: <%s>\n",
2195 		       sqlite3_errmsg (sqlite));
2196 	  sqlError = 1;
2197 	  goto clean_up;
2198       }
2199     current_row = 0;
2200     while (1)
2201       {
2202 	  /* inserting rows from DBF */
2203 	  ret = gaiaReadDbfEntity_ex (dbf, current_row, &deleted, text_dates);
2204 	  if (!ret)
2205 	    {
2206 		if (!(dbf->LastError))	/* normal DBF EOF */
2207 		    break;
2208 		if (!err_msg)
2209 		    spatialite_e ("%s\n", dbf->LastError);
2210 		else
2211 		    sprintf (err_msg, "%s\n", dbf->LastError);
2212 		sqlError = 1;
2213 		goto clean_up;
2214 	    }
2215 	  current_row++;
2216 	  if (deleted)
2217 	    {
2218 		/* skipping DBF deleted row */
2219 		continue;
2220 	    }
2221 	  /* binding query params */
2222 	  sqlite3_reset (stmt);
2223 	  sqlite3_clear_bindings (stmt);
2224 	  pk_set = 0;
2225 	  cnt = 0;
2226 	  dbf_field = dbf->Dbf->First;
2227 	  while (dbf_field)
2228 	    {
2229 		/* Primary Key value */
2230 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
2231 		  {
2232 		      if (pk_type == SQLITE_TEXT)
2233 			  sqlite3_bind_text (stmt, 1,
2234 					     dbf_field->Value->TxtValue,
2235 					     strlen (dbf_field->
2236 						     Value->TxtValue),
2237 					     SQLITE_STATIC);
2238 		      else if (pk_type == SQLITE_FLOAT)
2239 			  sqlite3_bind_double (stmt, 1,
2240 					       dbf_field->Value->DblValue);
2241 		      else
2242 			  sqlite3_bind_int64 (stmt, 1,
2243 					      dbf_field->Value->IntValue);
2244 		      pk_set = 1;
2245 		  }
2246 		dbf_field = dbf_field->Next;
2247 	    }
2248 	  if (!pk_set)
2249 	      sqlite3_bind_int (stmt, 1, current_row);
2250 	  cnt = 0;
2251 	  dbf_field = dbf->Dbf->First;
2252 	  while (dbf_field)
2253 	    {
2254 		/* column values */
2255 		if (strcasecmp (pk_name, dbf_field->Name) == 0)
2256 		  {
2257 		      /* skipping the Primary Key field */
2258 		      dbf_field = dbf_field->Next;
2259 		      continue;
2260 		  }
2261 		if (!(dbf_field->Value))
2262 		    sqlite3_bind_null (stmt, cnt + 2);
2263 		else
2264 		  {
2265 		      switch (dbf_field->Value->Type)
2266 			{
2267 			case GAIA_INT_VALUE:
2268 			    sqlite3_bind_int64 (stmt, cnt + 2,
2269 						dbf_field->Value->IntValue);
2270 			    break;
2271 			case GAIA_DOUBLE_VALUE:
2272 			    sqlite3_bind_double (stmt, cnt + 2,
2273 						 dbf_field->Value->DblValue);
2274 			    break;
2275 			case GAIA_TEXT_VALUE:
2276 			    sqlite3_bind_text (stmt, cnt + 2,
2277 					       dbf_field->Value->TxtValue,
2278 					       strlen (dbf_field->
2279 						       Value->TxtValue),
2280 					       SQLITE_STATIC);
2281 			    break;
2282 			default:
2283 			    sqlite3_bind_null (stmt, cnt + 2);
2284 			    break;
2285 			}
2286 		  }
2287 		cnt++;
2288 		dbf_field = dbf_field->Next;
2289 	    }
2290 	  ret = sqlite3_step (stmt);
2291 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
2292 	      ;
2293 	  else
2294 	    {
2295 		if (!err_msg)
2296 		    spatialite_e ("load DBF error: <%s>\n",
2297 				  sqlite3_errmsg (sqlite));
2298 		else
2299 		    sprintf (err_msg, "load DBF error: <%s>\n",
2300 			     sqlite3_errmsg (sqlite));
2301 		sqlite3_finalize (stmt);
2302 		sqlError = 1;
2303 		goto clean_up;
2304 	    }
2305       }
2306     sqlite3_finalize (stmt);
2307   clean_up:
2308     if (qtable)
2309 	free (qtable);
2310     qtable = NULL;
2311     if (qpk_name)
2312 	free (qpk_name);
2313     qpk_name = NULL;
2314     gaiaFreeDbf (dbf);
2315     if (col_name)
2316       {
2317 	  /* releasing memory allocation for column names */
2318 	  for (cnt = 0; cnt < col_cnt; cnt++)
2319 	      free (*(col_name + cnt));
2320 	  free (col_name);
2321       }
2322     if (sqlError)
2323       {
2324 	  /* some error occurred - ROLLBACK */
2325 	  if (verbose)
2326 	      spatialite_e ("ROLLBACK;\n");
2327 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, 0, &errMsg);
2328 	  if (ret != SQLITE_OK)
2329 	    {
2330 		spatialite_e ("load DBF error: <%s>\n", errMsg);
2331 		sqlite3_free (errMsg);
2332 	    };
2333 	  if (qtable)
2334 	      free (qtable);
2335 	  if (qpk_name)
2336 	      free (qpk_name);
2337 	  return 0;
2338       }
2339     else
2340       {
2341 	  /* ok - confirming pending transaction - COMMIT */
2342 	  if (verbose)
2343 	      spatialite_e ("COMMIT;\n");
2344 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, 0, &errMsg);
2345 	  if (ret != SQLITE_OK)
2346 	    {
2347 		spatialite_e ("load DBF error: <%s>\n", errMsg);
2348 		sqlite3_free (errMsg);
2349 		return 0;
2350 	    }
2351 	  if (rows)
2352 	      *rows = current_row;
2353 	  if (verbose)
2354 	      spatialite_e ("\nInserted %d rows into '%s' from DBF\n========\n",
2355 			    current_row, table);
2356 	  if (err_msg)
2357 	      sprintf (err_msg, "Inserted %d rows into '%s' from DBF",
2358 		       current_row, table);
2359 	  return 1;
2360       }
2361 }
2362 
2363 #ifdef ENABLE_MINIZIP		/* MINIZIP is enabled */
2364 
2365 static struct zip_mem_shp_item *
alloc_zip_mem_shp_item(const char * basename,int wich,int dbf_only)2366 alloc_zip_mem_shp_item (const char *basename, int wich, int dbf_only)
2367 {
2368 /* creating a Shapefile within a Zipfile */
2369     struct zip_mem_shp_item *item = malloc (sizeof (struct zip_mem_shp_item));
2370     if (basename == NULL)
2371 	item->basename = NULL;
2372     else
2373       {
2374 	  int len = strlen (basename);
2375 	  item->basename = malloc (len + 1);
2376 	  strcpy (item->basename, basename);
2377 	  if (!dbf_only)
2378 	    {
2379 		if (*(item->basename + len - 4) == '.')
2380 		    *(item->basename + len - 4) = '\0';
2381 	    }
2382       }
2383     item->shp = 0;
2384     item->shx = 0;
2385     item->dbf = 0;
2386     item->prj = 0;
2387     switch (wich)
2388       {
2389       case GAIA_ZIPFILE_SHP:
2390 	  item->shp = 1;
2391 	  break;
2392       case GAIA_ZIPFILE_SHX:
2393 	  item->shx = 1;
2394 	  break;
2395       case GAIA_ZIPFILE_DBF:
2396 	  item->dbf = 1;
2397 	  break;
2398       case GAIA_ZIPFILE_PRJ:
2399 	  item->prj = 1;
2400 	  break;
2401       };
2402     item->next = NULL;
2403     return item;
2404 }
2405 
2406 static void
add_item_into_zip_mem_shp_list(struct zip_mem_shp_list * list,const char * filename,int wich,int dbf_only)2407 add_item_into_zip_mem_shp_list (struct zip_mem_shp_list *list,
2408 				const char *filename, int wich, int dbf_only)
2409 {
2410 /* populating the list of Zipfile Shapefiles */
2411     struct zip_mem_shp_item *item;
2412 
2413     if (list == NULL)
2414 	return;
2415 
2416     item = list->first;
2417     while (item != NULL)
2418       {
2419 	  /* verifying an already existing basename */
2420 	  char *name = NULL;
2421 	  switch (wich)
2422 	    {
2423 	    case GAIA_ZIPFILE_SHP:
2424 		name = sqlite3_mprintf ("%s.shp", item->basename);
2425 		break;
2426 	    case GAIA_ZIPFILE_SHX:
2427 		name = sqlite3_mprintf ("%s.shx", item->basename);
2428 		break;
2429 	    case GAIA_ZIPFILE_DBF:
2430 		name = sqlite3_mprintf ("%s.dbf", item->basename);
2431 		break;
2432 	    case GAIA_ZIPFILE_PRJ:
2433 		name = sqlite3_mprintf ("%s.prj", item->basename);
2434 		break;
2435 	    };
2436 	  if (name != NULL)
2437 	    {
2438 		if (strcasecmp (name, filename) == 0)
2439 		  {
2440 		      /* found a mathcing basename */
2441 		      sqlite3_free (name);
2442 		      switch (wich)
2443 			{
2444 			case GAIA_ZIPFILE_SHP:
2445 			    item->shp = 1;
2446 			    break;
2447 			case GAIA_ZIPFILE_SHX:
2448 			    item->shx = 1;
2449 			    break;
2450 			case GAIA_ZIPFILE_DBF:
2451 			    item->dbf = 1;
2452 			    break;
2453 			case GAIA_ZIPFILE_PRJ:
2454 			    item->prj = 1;
2455 			    break;
2456 			};
2457 		      return;
2458 		  }
2459 		sqlite3_free (name);
2460 	    }
2461 	  item = item->next;
2462       }
2463 
2464 /* inserting a new basename into the list */
2465     item = alloc_zip_mem_shp_item (filename, wich, dbf_only);
2466     if (list->first == NULL)
2467 	list->first = item;
2468     if (list->last != NULL)
2469 	list->last->next = item;
2470     list->last = item;
2471 }
2472 
2473 static struct zip_mem_shapefile *
alloc_zip_mem_shapefile()2474 alloc_zip_mem_shapefile ()
2475 {
2476 /* allocating a Memory Zip Shapefile */
2477     struct zip_mem_shapefile *mem_shp =
2478 	malloc (sizeof (struct zip_mem_shapefile));
2479     mem_shp->shp.path = NULL;
2480     mem_shp->shp.buf = NULL;
2481     mem_shp->shp.size = 0;
2482     mem_shp->shp.offset = 0;
2483     mem_shp->shx.path = NULL;
2484     mem_shp->shx.buf = NULL;
2485     mem_shp->shx.size = 0;
2486     mem_shp->shx.offset = 0;
2487     mem_shp->dbf.path = NULL;
2488     mem_shp->dbf.buf = NULL;
2489     mem_shp->dbf.size = 0;
2490     mem_shp->dbf.offset = 0;
2491     mem_shp->prj.path = NULL;
2492     mem_shp->prj.buf = NULL;
2493     mem_shp->prj.size = 0;
2494     mem_shp->prj.offset = 0;
2495     return mem_shp;
2496 }
2497 
2498 static void
destroy_zip_mem_file(gaiaMemFilePtr mem)2499 destroy_zip_mem_file (gaiaMemFilePtr mem)
2500 {
2501 /* memory cleanup: destroying a Memoroy Zip File */
2502     if (mem == NULL)
2503 	return;
2504     if (mem->path != NULL)
2505 	free (mem->path);
2506     if (mem->buf != NULL)
2507 	free (mem->buf);
2508 }
2509 
2510 static void
destroy_zip_mem_shapefile(struct zip_mem_shapefile * mem_shp)2511 destroy_zip_mem_shapefile (struct zip_mem_shapefile *mem_shp)
2512 {
2513 /* memory cleanup: destroying a Memory Zip Shapefile */
2514     if (mem_shp == NULL)
2515 	return;
2516     destroy_zip_mem_file (&(mem_shp->shp));
2517     destroy_zip_mem_file (&(mem_shp->shx));
2518     destroy_zip_mem_file (&(mem_shp->dbf));
2519     destroy_zip_mem_file (&(mem_shp->prj));
2520     free (mem_shp);
2521 }
2522 
2523 static void
destroy_zip_mem_shp_item(struct zip_mem_shp_item * item)2524 destroy_zip_mem_shp_item (struct zip_mem_shp_item *item)
2525 {
2526 /* destroying a Shapefile item */
2527     if (item == NULL)
2528 	return;
2529     if (item->basename != NULL)
2530 	free (item->basename);
2531     free (item);
2532 }
2533 
2534 static struct zip_mem_shp_list *
alloc_zip_mem_shp_list()2535 alloc_zip_mem_shp_list ()
2536 {
2537 /* creating a list of Shapefiles within a Shapefile */
2538     struct zip_mem_shp_list *list = malloc (sizeof (struct zip_mem_shp_list));
2539     list->first = NULL;
2540     list->last = NULL;
2541     return list;
2542 }
2543 
2544 static void
destroy_zip_mem_shp_list(struct zip_mem_shp_list * list)2545 destroy_zip_mem_shp_list (struct zip_mem_shp_list *list)
2546 {
2547 /* memory cleanup: destroying a list of Shapefiles within a Shapefile */
2548     struct zip_mem_shp_item *item;
2549     struct zip_mem_shp_item *item_n;
2550 
2551     if (list == NULL)
2552 	return;
2553     item = list->first;
2554     while (item != NULL)
2555       {
2556 	  item_n = item->next;
2557 	  destroy_zip_mem_shp_item (item);
2558 	  item = item_n;
2559       }
2560     free (list);
2561 }
2562 
2563 static int
do_sniff_zipfile_dir(unzFile uf,struct zip_mem_shp_list * list,int dbf_only)2564 do_sniff_zipfile_dir (unzFile uf, struct zip_mem_shp_list *list, int dbf_only)
2565 {
2566 /* sniffing a Zipfile directory */
2567     int retval = 1;
2568     unz_global_info64 gi;
2569     int ret;
2570     unsigned int i;
2571 
2572     ret = unzGetGlobalInfo64 (uf, &gi);
2573     if (ret != UNZ_OK)
2574       {
2575 	  spatialite_e ("Error %d within zipfile in unzGetGlobalInfo\n", ret);
2576 	  return 0;
2577       }
2578 
2579     for (i = 0; i < gi.number_entry; i++)
2580       {
2581 	  unsigned int len;
2582 	  char suffix[6];
2583 	  char filename[256];
2584 	  unz_file_info64 file_info;
2585 
2586 	  ret =
2587 	      unzGetCurrentFileInfo64 (uf, &file_info, filename, 256, NULL, 0,
2588 				       NULL, 0);
2589 	  if (ret != UNZ_OK)
2590 	    {
2591 		spatialite_e
2592 		    ("Error %d with zipfile in unzGetCurrentFileInfo\n", ret);
2593 		retval = 0;
2594 		goto stop;
2595 	    }
2596 
2597 	  suffix[0] = '\0';
2598 	  len = strlen (filename);
2599 	  if (len >= 5)
2600 	    {
2601 		suffix[0] = *(filename + len - 4);
2602 		suffix[1] = *(filename + len - 3);
2603 		suffix[2] = *(filename + len - 2);
2604 		suffix[3] = *(filename + len - 1);
2605 		suffix[4] = '\0';
2606 	    }
2607 	  if (strcasecmp (suffix, ".shp") == 0)
2608 	      add_item_into_zip_mem_shp_list (list, filename, GAIA_ZIPFILE_SHP,
2609 					      0);
2610 	  if (strcasecmp (suffix, ".shx") == 0)
2611 	      add_item_into_zip_mem_shp_list (list, filename, GAIA_ZIPFILE_SHX,
2612 					      0);
2613 	  if (strcasecmp (suffix, ".dbf") == 0)
2614 	      add_item_into_zip_mem_shp_list (list, filename, GAIA_ZIPFILE_DBF,
2615 					      dbf_only);
2616 	  if (strcasecmp (suffix, ".prj") == 0)
2617 	      add_item_into_zip_mem_shp_list (list, filename, GAIA_ZIPFILE_PRJ,
2618 					      0);
2619 
2620 	  if (i + 1 == gi.number_entry)
2621 	      break;
2622 	  ret = unzGoToNextFile (uf);
2623 	  if (ret != UNZ_OK)
2624 	    {
2625 		spatialite_e ("Error %d with zipfile in unzGoToNextFile\n",
2626 			      ret);
2627 		retval = 0;
2628 		goto stop;
2629 	    }
2630       }
2631   stop:
2632     return retval;
2633 }
2634 
2635 static struct zip_mem_shapefile *
do_list_zipfile_dir(unzFile uf,const char * shp_path,int dbf_mode)2636 do_list_zipfile_dir (unzFile uf, const char *shp_path, int dbf_mode)
2637 {
2638 /* parsing a Zipfile directory */
2639     unz_global_info64 gi;
2640     int ret;
2641     unsigned int i;
2642     int len;
2643     int shp = 0;
2644     int dbf = 0;
2645     int shx = 0;
2646     int prj = 0;
2647     struct zip_mem_shapefile *mem_shp = NULL;
2648 
2649     ret = unzGetGlobalInfo64 (uf, &gi);
2650     if (ret != UNZ_OK)
2651       {
2652 	  spatialite_e ("Error %d within zipfile in unzGetGlobalInfo\n", ret);
2653 	  return 0;
2654       }
2655 
2656     mem_shp = alloc_zip_mem_shapefile ();
2657     for (i = 0; i < gi.number_entry; i++)
2658       {
2659 	  char *path;
2660 	  char filename[256];
2661 	  unz_file_info64 file_info;
2662 
2663 	  ret =
2664 	      unzGetCurrentFileInfo64 (uf, &file_info, filename, 256, NULL, 0,
2665 				       NULL, 0);
2666 	  if (ret != UNZ_OK)
2667 	    {
2668 		spatialite_e
2669 		    ("Error %d with zipfile in unzGetCurrentFileInfo\n", ret);
2670 		goto error;
2671 	    }
2672 	  if (dbf_mode)
2673 	    {
2674 		/* searching for just a bare DBF */
2675 		if (!dbf)
2676 		  {
2677 		      if (strcasecmp (shp_path, filename) == 0)
2678 			{
2679 			    dbf = 1;
2680 			    len = strlen (filename);
2681 			    mem_shp->dbf.path = malloc (len + 1);
2682 			    strcpy (mem_shp->dbf.path, filename);
2683 			}
2684 		  }
2685 	    }
2686 	  else
2687 	    {
2688 		/* searching for a Shapefile */
2689 		if (!shp)
2690 		  {
2691 		      path = sqlite3_mprintf ("%s.shp", shp_path);
2692 		      if (strcasecmp (path, filename) == 0)
2693 			{
2694 			    shp = 1;
2695 			    len = strlen (filename);
2696 			    mem_shp->shp.path = malloc (len + 1);
2697 			    strcpy (mem_shp->shp.path, filename);
2698 			}
2699 		      sqlite3_free (path);
2700 		  }
2701 		if (!shx)
2702 		  {
2703 		      path = sqlite3_mprintf ("%s.shx", shp_path);
2704 		      if (strcasecmp (path, filename) == 0)
2705 			{
2706 			    shx = 1;
2707 			    len = strlen (filename);
2708 			    mem_shp->shx.path = malloc (len + 1);
2709 			    strcpy (mem_shp->shx.path, filename);
2710 			}
2711 		      sqlite3_free (path);
2712 		  }
2713 		if (!dbf)
2714 		  {
2715 		      path = sqlite3_mprintf ("%s.dbf", shp_path);
2716 		      if (strcasecmp (path, filename) == 0)
2717 			{
2718 			    dbf = 1;
2719 			    len = strlen (filename);
2720 			    mem_shp->dbf.path = malloc (len + 1);
2721 			    strcpy (mem_shp->dbf.path, filename);
2722 			}
2723 		      sqlite3_free (path);
2724 		  }
2725 		if (!prj)
2726 		  {
2727 		      path = sqlite3_mprintf ("%s.prj", shp_path);
2728 		      if (strcasecmp (path, filename) == 0)
2729 			{
2730 			    prj = 1;
2731 			    len = strlen (filename);
2732 			    mem_shp->prj.path = malloc (len + 1);
2733 			    strcpy (mem_shp->prj.path, filename);
2734 			}
2735 		      sqlite3_free (path);
2736 		  }
2737 	    }
2738 
2739 	  if (i + 1 == gi.number_entry)
2740 	      break;
2741 	  ret = unzGoToNextFile (uf);
2742 	  if (ret != UNZ_OK)
2743 	    {
2744 		spatialite_e ("Error %d with zipfile in unzGoToNextFile\n",
2745 			      ret);
2746 		goto error;
2747 	    }
2748       }
2749     if (dbf_mode && dbf)
2750 	return mem_shp;
2751     if (shp && shx && dbf)
2752 	return mem_shp;
2753 
2754   error:
2755     destroy_zip_mem_shapefile (mem_shp);
2756     return NULL;
2757 }
2758 
2759 static int
do_read_zipfile_file(unzFile uf,struct zip_mem_shapefile * mem_shape,int wich)2760 do_read_zipfile_file (unzFile uf, struct zip_mem_shapefile *mem_shape, int wich)
2761 {
2762 //
2763 // impo
2764     int is_open = 0;
2765     int retval = 1;
2766     uint64_t size_buf;
2767     uint64_t rd_cnt;
2768     uint64_t unrd_cnt;
2769     unsigned char *buf = NULL;
2770     char filename[256];
2771     gaiaMemFilePtr mem_file;
2772     unz_file_info64 file_info;
2773     int err;
2774 
2775     switch (wich)
2776       {
2777       case GAIA_ZIPFILE_SHP:
2778 	  mem_file = &(mem_shape->shp);
2779 	  break;
2780       case GAIA_ZIPFILE_SHX:
2781 	  mem_file = &(mem_shape->shx);
2782 	  break;
2783       case GAIA_ZIPFILE_DBF:
2784 	  mem_file = &(mem_shape->dbf);
2785 	  break;
2786       case GAIA_ZIPFILE_PRJ:
2787 	  mem_file = &(mem_shape->prj);
2788 	  break;
2789       default:
2790 	  mem_file = NULL;
2791       };
2792     if (mem_file == NULL)
2793 	return 0;
2794     if (mem_file->path == NULL)
2795 	return 0;
2796 
2797     err = unzLocateFile (uf, mem_file->path, 0);
2798     if (err != UNZ_OK)
2799       {
2800 	  spatialite_e ("File %s not found within zipfile\n", mem_file->path);
2801 	  retval = 0;
2802 	  goto skip;
2803       }
2804     err =
2805 	unzGetCurrentFileInfo64 (uf, &file_info, filename, 256, NULL, 0, NULL,
2806 				 0);
2807     if (err != UNZ_OK)
2808       {
2809 	  spatialite_e ("Error %d with zipfile in unzGetCurrentFileInfo\n",
2810 			err);
2811 	  retval = 0;
2812 	  goto skip;
2813       }
2814     size_buf = file_info.uncompressed_size;
2815     buf = malloc (size_buf);
2816     err = unzOpenCurrentFile (uf);
2817     if (err != UNZ_OK)
2818       {
2819 	  spatialite_e ("Error %d with zipfile in unzGetCurrentFileInfo\n",
2820 			err);
2821 	  retval = 0;
2822 	  goto skip;
2823       }
2824     is_open = 1;
2825     rd_cnt = 0;
2826     while (rd_cnt < size_buf)
2827       {
2828 	  /* reading big chunks so to avoid large file issues */
2829 	  uint32_t max = 1000000000;	/* max chunk size */
2830 	  uint32_t len;
2831 	  unrd_cnt = size_buf - rd_cnt;
2832 	  if (unrd_cnt < max)
2833 	      len = unrd_cnt;
2834 	  else
2835 	      len = max;
2836 	  err = unzReadCurrentFile (uf, buf + rd_cnt, len);
2837 	  if (err < 0)
2838 	    {
2839 		spatialite_e ("Error %d with zipfile in unzReadCurrentFile\n",
2840 			      err);
2841 		retval = 0;
2842 		goto skip;
2843 	    }
2844 	  rd_cnt += len;
2845       }
2846     mem_file->buf = buf;
2847     mem_file->size = size_buf;
2848 
2849   skip:
2850     if (buf != NULL && !retval)
2851 	free (buf);
2852     if (is_open)
2853 	unzCloseCurrentFile (uf);
2854     return retval;
2855 }
2856 
2857 SPATIALITE_DECLARE int
load_zip_shapefile(sqlite3 * sqlite,const char * zip_path,const char * shp_path,const char * table,const char * charset,int srid,const char * g_column,const char * gtype,const char * pk_column,int coerce2d,int compressed,int verbose,int spatial_index,int text_dates,int * rows,int colname_case,char * err_msg)2858 load_zip_shapefile (sqlite3 * sqlite, const char *zip_path,
2859 		    const char *shp_path, const char *table,
2860 		    const char *charset, int srid, const char *g_column,
2861 		    const char *gtype, const char *pk_column, int coerce2d,
2862 		    int compressed, int verbose, int spatial_index,
2863 		    int text_dates, int *rows, int colname_case, char *err_msg)
2864 {
2865 /* loading a Shapefile from within a Zipfile */
2866     unzFile uf = NULL;
2867     int retval = 0;
2868     struct zip_mem_shapefile *mem_shape = NULL;
2869 
2870     if (zip_path == NULL)
2871       {
2872 	  spatialite_e ("load zip shapefile error: <%s>\n",
2873 			"NULL zipfile path");
2874 	  return 0;
2875       }
2876 /* opening the Zipfile expected to contain the Shapefile */
2877     uf = unzOpen64 (zip_path);
2878     if (uf == NULL)
2879       {
2880 	  spatialite_e ("Unable to Open %s\n", zip_path);
2881 	  return 0;
2882       }
2883 /* parsing the Zipfile directory */
2884     mem_shape = do_list_zipfile_dir (uf, shp_path, 0);
2885     if (mem_shape == NULL)
2886       {
2887 	  spatialite_e ("No SHP %s with Zipfile\n", shp_path);
2888 	  goto stop;
2889       }
2890 /* unzipping the SHP member */
2891     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_SHP))
2892 	goto stop;
2893 /* unzipping the SHX member */
2894     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_SHX))
2895 	goto stop;
2896 /* unzipping the DBF member */
2897     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_DBF))
2898 	goto stop;
2899 /* unzipping the PRJ member */
2900     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_PRJ))
2901 	goto stop;
2902 
2903 /* doing the hard work */
2904     if (load_shapefile_common
2905 	(mem_shape, sqlite, shp_path, table, charset, srid, g_column, gtype,
2906 	 pk_column, coerce2d, compressed, verbose, spatial_index, text_dates,
2907 	 rows, colname_case, err_msg))
2908 	retval = 1;
2909 
2910   stop:
2911     unzClose (uf);
2912     if (mem_shape != NULL)
2913 	destroy_zip_mem_shapefile (mem_shape);
2914     return retval;
2915 }
2916 
2917 GAIAGEO_DECLARE gaiaDbfPtr
gaiaOpenZipDbf(const char * zip_path,const char * filename,const char * charFrom,const char * charTo)2918 gaiaOpenZipDbf (const char *zip_path, const char *filename,
2919 		const char *charFrom, const char *charTo)
2920 {
2921 /* creating a DBF object (just for checking its fields) */
2922     unzFile uf = NULL;
2923     struct zip_mem_shapefile *mem_shape = NULL;
2924     gaiaDbfPtr dbf = NULL;
2925 
2926     if (zip_path == NULL)
2927       {
2928 	  spatialite_e ("open zip dbf error: <%s>\n", "NULL zipfile path");
2929 	  return 0;
2930       }
2931 /* opening the Zipfile expected to contain the Shapefile */
2932     uf = unzOpen64 (zip_path);
2933     if (uf == NULL)
2934       {
2935 	  spatialite_e ("Unable to Open %s\n", zip_path);
2936 	  return 0;
2937       }
2938 /* parsing the Zipfile directory */
2939     mem_shape = do_list_zipfile_dir (uf, filename, 1);
2940     if (mem_shape == NULL)
2941       {
2942 	  spatialite_e ("No DBF %s with Zipfile\n", filename);
2943 	  goto stop;
2944       }
2945 /* unzipping the DBF member */
2946     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_DBF))
2947 	goto stop;
2948 /* attempting to create and initialize the DBF object */
2949     dbf = gaiaAllocDbf ();
2950     dbf->memDbf = &(mem_shape->dbf);
2951     gaiaOpenDbfRead (dbf, filename, charFrom, charTo);
2952 
2953   stop:
2954     unzClose (uf);
2955     destroy_zip_mem_shapefile (mem_shape);
2956     return dbf;
2957 }
2958 
2959 SPATIALITE_DECLARE int
load_zip_dbf(sqlite3 * sqlite,const char * zip_path,const char * dbf_path,const char * table,const char * pk_column,const char * charset,int verbose,int text_dates,int * rows,int colname_case,char * err_msg)2960 load_zip_dbf (sqlite3 * sqlite, const char *zip_path, const char *dbf_path,
2961 	      const char *table, const char *pk_column, const char *charset,
2962 	      int verbose, int text_dates, int *rows,
2963 	      int colname_case, char *err_msg)
2964 {
2965 /* loading a DBF file from within a Zipfile */
2966     unzFile uf = NULL;
2967     int retval = 0;
2968     struct zip_mem_shapefile *mem_shape = NULL;
2969 
2970     if (zip_path == NULL)
2971       {
2972 	  spatialite_e ("load zip shapefile error: <%s>\n",
2973 			"NULL zipfile path");
2974 	  return 0;
2975       }
2976 /* opening the Zipfile expected to contain the Shapefile */
2977     uf = unzOpen64 (zip_path);
2978     if (uf == NULL)
2979       {
2980 	  spatialite_e ("Unable to Open %s\n", zip_path);
2981 	  return 0;
2982       }
2983 /* parsing the Zipfile directory */
2984     mem_shape = do_list_zipfile_dir (uf, dbf_path, 1);
2985     if (mem_shape == NULL)
2986       {
2987 	  spatialite_e ("No DBF %s with Zipfile\n", dbf_path);
2988 	  goto stop;
2989       }
2990 /* unzipping the DBF member */
2991     if (!do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_DBF))
2992 	goto stop;
2993 
2994 /* doing the hard work */
2995     if (load_dbf_common
2996 	(mem_shape, sqlite, dbf_path, table, pk_column, charset, verbose,
2997 	 text_dates, rows, colname_case, err_msg))
2998 	retval = 1;
2999 
3000   stop:
3001     unzClose (uf);
3002     if (mem_shape != NULL)
3003 	destroy_zip_mem_shapefile (mem_shape);
3004     return retval;
3005 }
3006 
3007 #endif /* end MINIZIP */
3008 
3009 #ifndef OMIT_PROJ		/* including PROJ */
3010 #ifdef PROJ_NEW			/* only if new PROJ.6 is supported */
3011 static int
output_prj_file_proj_new(int srid,const char * path,void * proj_ctx)3012 output_prj_file_proj_new (int srid, const char *path, void *proj_ctx)
3013 {
3014 /* attempting to export a genuine ESRI WKT */
3015     PJ_CONTEXT *ctx = (PJ_CONTEXT *) proj_ctx;
3016     PJ *crs_def;
3017     FILE *out;
3018     const char *projPath;
3019     const char *auth_name = "EPSG";
3020     char dummy[64];
3021     const char *wkt;
3022     char *prj_path;
3023     char *options[4];
3024     options[0] = "MULTILINE=NO";
3025     options[1] = "INDENTATION_WIDTH=4";
3026     options[2] = "OUTPUT_AXIS=AUTO";
3027     options[3] = NULL;
3028 
3029     if (ctx == NULL)
3030 	goto error;
3031     projPath = proj_context_get_database_path (ctx);
3032     if (projPath == NULL)
3033 	goto error;		/* PROJ's own SQLite DB is undefined */
3034 
3035 /* attemping to get an ESRI WKT from PROJ.6 */
3036     sprintf (dummy, "%d", srid);
3037     crs_def =
3038 	proj_create_from_database (ctx, auth_name, dummy, PJ_CATEGORY_CRS, 0,
3039 				   NULL);
3040     if (crs_def != NULL)
3041       {
3042 	  wkt =
3043 	      proj_as_wkt (ctx, crs_def, PJ_WKT1_ESRI,
3044 			   (const char *const *) options);
3045 	  if (wkt != NULL)
3046 	    {
3047 		/* generating the .PRJ file */
3048 		prj_path = sqlite3_mprintf ("%s.prj", path);
3049 #ifdef _WIN32
3050 		out = gaia_win_fopen (prj_path, "wb");
3051 #else
3052 		out = fopen (prj_path, "wb");
3053 #endif
3054 		sqlite3_free (prj_path);
3055 		if (out)
3056 		  {
3057 		      fprintf (out, "%s\r\n", wkt);
3058 		      fclose (out);
3059 		  }
3060 	    }
3061 	  proj_destroy (crs_def);
3062       }
3063     return 1;
3064 
3065   error:
3066     return 0;
3067 }
3068 #endif
3069 #endif
3070 
3071 static void
output_prj_file(sqlite3 * sqlite,char * path,char * table,char * column,void * proj_ctx)3072 output_prj_file (sqlite3 * sqlite, char *path, char *table, char *column,
3073 		 void *proj_ctx)
3074 {
3075 /* exporting [if possible] a .PRJ file */
3076     char **results;
3077     int rows;
3078     int columns;
3079     int i;
3080     char *errMsg = NULL;
3081     int srid = -1;
3082     char *sql;
3083     int ret;
3084     int rs_srid = 0;
3085     int rs_srs_wkt = 0;
3086     int rs_srtext = 0;
3087     int has_srtext = 0;
3088     const char *name;
3089     char *srsWkt = NULL;
3090     FILE *out;
3091 
3092 /* step I: retrieving the SRID */
3093     sql = sqlite3_mprintf ("SELECT srid FROM geometry_columns WHERE "
3094 			   "Lower(f_table_name) = Lower(%Q) AND "
3095 			   "Lower(f_geometry_column) = Lower(%Q)",
3096 			   table, column);
3097     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
3098     sqlite3_free (sql);
3099     if (ret != SQLITE_OK)
3100       {
3101 	  spatialite_e ("dump shapefile MetaData error: <%s>\n", errMsg);
3102 	  sqlite3_free (errMsg);
3103 	  return;
3104       }
3105     for (i = 1; i <= rows; i++)
3106       {
3107 	  srid = atoi (results[(i * columns) + 0]);
3108       }
3109     sqlite3_free_table (results);
3110     if (srid <= 0)
3111       {
3112 	  /* srid still undefined, so we'll read VIEWS_GEOMETRY_COLUMNS */
3113 	  sql = sqlite3_mprintf ("SELECT srid FROM views_geometry_columns "
3114 				 "JOIN geometry_columns USING (f_table_name, f_geometry_column) "
3115 				 "WHERE Lower(view_name) = Lower(%Q) AND "
3116 				 "Lower(view_geometry) = Lower(%Q)",
3117 				 table, column);
3118 	  ret =
3119 	      sqlite3_get_table (sqlite, sql, &results, &rows, &columns,
3120 				 &errMsg);
3121 	  sqlite3_free (sql);
3122 	  if (ret != SQLITE_OK)
3123 	    {
3124 		spatialite_e ("dump shapefile MetaData error: <%s>\n", errMsg);
3125 		sqlite3_free (errMsg);
3126 		return;
3127 	    }
3128 	  for (i = 1; i <= rows; i++)
3129 	    {
3130 		srid = atoi (results[(i * columns) + 0]);
3131 	    }
3132 	  sqlite3_free_table (results);
3133       }
3134     if (srid <= 0)
3135 	return;
3136 
3137 #ifndef OMIT_PROJ		/* including PROJ */
3138 #ifdef PROJ_NEW
3139 /* if new PROJ.6 is available we'll attempt first to export a genuine ESRI WKT */
3140     if (proj_ctx != NULL)
3141       {
3142 	  if (output_prj_file_proj_new (srid, path, proj_ctx))
3143 	      return;
3144       }
3145 #else
3146 /* suppressing stupid compiler warnings about unused args */
3147     if (proj_ctx == NULL)
3148 	proj_ctx = NULL;
3149 #endif
3150 #endif
3151 
3152 /* step II: checking if the SRS_WKT or SRTEXT column actually exists */
3153     ret =
3154 	sqlite3_get_table (sqlite, "PRAGMA table_info(spatial_ref_sys)",
3155 			   &results, &rows, &columns, &errMsg);
3156     if (ret != SQLITE_OK)
3157       {
3158 	  spatialite_e ("dump shapefile MetaData error: <%s>\n", errMsg);
3159 	  sqlite3_free (errMsg);
3160 	  return;
3161       }
3162     if (rows < 1)
3163 	;
3164     else
3165       {
3166 	  for (i = 1; i <= rows; i++)
3167 	    {
3168 		name = results[(i * columns) + 1];
3169 		if (strcasecmp (name, "srid") == 0)
3170 		    rs_srid = 1;
3171 		if (strcasecmp (name, "srs_wkt") == 0)
3172 		    rs_srs_wkt = 1;
3173 		if (strcasecmp (name, "srtext") == 0)
3174 		    rs_srtext = 1;
3175 	    }
3176       }
3177     sqlite3_free_table (results);
3178     if (rs_srs_wkt == 1 || rs_srtext == 1)
3179 	has_srtext = 1;
3180     if (rs_srid == 0 || has_srtext == 0)
3181 	return;
3182 
3183 /* step III: fetching WKT SRS */
3184     if (rs_srtext)
3185       {
3186 	  sql = sqlite3_mprintf ("SELECT srtext FROM spatial_ref_sys "
3187 				 "WHERE srid = %d AND srtext IS NOT NULL",
3188 				 srid);
3189       }
3190     else
3191       {
3192 	  sql = sqlite3_mprintf ("SELECT srs_wkt FROM spatial_ref_sys "
3193 				 "WHERE srid = %d AND srs_wkt IS NOT NULL",
3194 				 srid);
3195       }
3196     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
3197     sqlite3_free (sql);
3198     if (ret != SQLITE_OK)
3199       {
3200 	  spatialite_e ("dump shapefile MetaData error: <%s>\n", errMsg);
3201 	  sqlite3_free (errMsg);
3202 	  goto end;
3203       }
3204     if (rows < 1)
3205 	;
3206     else
3207       {
3208 	  for (i = 1; i <= rows; i++)
3209 	    {
3210 		char *srs = results[(i * columns) + 0];
3211 		int len = strlen (srs);
3212 		if (srsWkt)
3213 		    free (srsWkt);
3214 		srsWkt = malloc (len + 1);
3215 		strcpy (srsWkt, srs);
3216 	    }
3217       }
3218     sqlite3_free_table (results);
3219     if (srsWkt == NULL)
3220 	goto end;
3221 
3222 /* step IV: generating the .PRJ file */
3223     sql = sqlite3_mprintf ("%s.prj", path);
3224 #ifdef _WIN32
3225     out = gaia_win_fopen (sql, "wb");
3226 #else
3227     out = fopen (sql, "wb");
3228 #endif
3229     sqlite3_free (sql);
3230     if (!out)
3231 	goto end;
3232     fprintf (out, "%s\r\n", srsWkt);
3233     fclose (out);
3234   end:
3235     if (srsWkt)
3236 	free (srsWkt);
3237     return;
3238 }
3239 
3240 static int
get_default_dbf_fields(sqlite3 * sqlite,const char * xtable,const char * db_prefix,const char * table_name,gaiaDbfListPtr * dbf_export_list)3241 get_default_dbf_fields (sqlite3 * sqlite, const char *xtable,
3242 			const char *db_prefix, const char *table_name,
3243 			gaiaDbfListPtr * dbf_export_list)
3244 {
3245 /* creating DBF field definitions for an empty DBF */
3246     int row = 0;
3247     char *sql;
3248     sqlite3_stmt *stmt;
3249     int ret;
3250     int offset = 0;
3251     gaiaDbfListPtr list = NULL;
3252 
3253     if (db_prefix != NULL && table_name != NULL)
3254       {
3255 	  char *xprefix = gaiaDoubleQuotedSql (db_prefix);
3256 	  char *xxtable = gaiaDoubleQuotedSql (table_name);
3257 	  sql =
3258 	      sqlite3_mprintf ("PRAGMA \"%s\".table_info(\"%s\")", xprefix,
3259 			       xxtable);
3260 	  free (xprefix);
3261 	  free (xxtable);
3262       }
3263     else
3264 	sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xtable);
3265 /*
3266 / compiling SQL prepared statement
3267 */
3268 
3269     list = gaiaAllocDbfList ();
3270     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
3271     sqlite3_free (sql);
3272     if (ret != SQLITE_OK)
3273 	goto sql_error;
3274     while (1)
3275       {
3276 	  ret = sqlite3_step (stmt);
3277 	  if (ret == SQLITE_DONE)
3278 	      break;		/* end of result set */
3279 	  if (ret == SQLITE_ROW)
3280 	    {
3281 		/* processing a result set row */
3282 		int xtype = SQLITE_TEXT;
3283 		int length = 60;
3284 		char *name = (char *) sqlite3_column_text (stmt, 1);
3285 		const char *type = (const char *) sqlite3_column_text (stmt, 2);
3286 
3287 		if (strcasecmp (type, "INT") == 0
3288 		    || strcasecmp (type, "INTEGER") == 0
3289 		    || strcasecmp (type, "SMALLINT") == 0
3290 		    || strcasecmp (type, "BIGINT") == 0
3291 		    || strcasecmp (type, "TINYINT") == 0)
3292 		    xtype = SQLITE_INTEGER;
3293 		if (strcasecmp (type, "DOUBLE") == 0
3294 		    || strcasecmp (type, "REAL") == 0
3295 		    || strcasecmp (type, "DOUBLE PRECISION") == 0
3296 		    || strcasecmp (type, "NUMERIC") == 0
3297 		    || strcasecmp (type, "FLOAT") == 0)
3298 		    xtype = SQLITE_FLOAT;
3299 		if (strncasecmp (type, "VARCHAR(", 8) == 0)
3300 		    length = atoi (type + 8);
3301 		if (strncasecmp (type, "CHAR(", 5) == 0)
3302 		    length = atoi (type + 5);
3303 
3304 		if (xtype == SQLITE_FLOAT)
3305 		  {
3306 		      gaiaAddDbfField (list, name, 'N', offset, 19, 6);
3307 		      offset += 19;
3308 		  }
3309 		else if (xtype == SQLITE_INTEGER)
3310 		  {
3311 		      gaiaAddDbfField (list, name, 'N', offset, 18, 0);
3312 		      offset += 18;
3313 		  }
3314 		else
3315 		  {
3316 		      gaiaAddDbfField (list, name, 'C', offset, (char) length,
3317 				       0);
3318 		      offset += length;
3319 		  }
3320 		row++;
3321 	    }
3322 	  else
3323 	      goto sql_error;
3324       }
3325     sqlite3_finalize (stmt);
3326     if (row == 0)
3327 	goto sql_error;
3328     *dbf_export_list = list;
3329     return 1;
3330   sql_error:
3331     gaiaFreeDbfList (list);
3332     *dbf_export_list = NULL;
3333     return 0;
3334 }
3335 
3336 static gaiaVectorLayersListPtr
recover_unregistered_geometry(sqlite3 * handle,const char * table,const char * geometry)3337 recover_unregistered_geometry (sqlite3 * handle, const char *table,
3338 			       const char *geometry)
3339 {
3340 /* attempting to recover an unregistered Geometry */
3341     int len;
3342     int error = 0;
3343     gaiaVectorLayersListPtr list;
3344     gaiaVectorLayerPtr lyr;
3345 
3346 /* allocating a VectorLayersList */
3347     list = malloc (sizeof (gaiaVectorLayersList));
3348     list->First = NULL;
3349     list->Last = NULL;
3350     list->Current = NULL;
3351 
3352     lyr = malloc (sizeof (gaiaVectorLayer));
3353     lyr->LayerType = GAIA_VECTOR_UNKNOWN;
3354     len = strlen (table);
3355     lyr->TableName = malloc (len + 1);
3356     strcpy (lyr->TableName, table);
3357     len = strlen (geometry);
3358     lyr->GeometryName = malloc (len + 1);
3359     strcpy (lyr->GeometryName, geometry);
3360     lyr->Srid = 0;
3361     lyr->GeometryType = GAIA_VECTOR_UNKNOWN;
3362     lyr->Dimensions = GAIA_VECTOR_UNKNOWN;
3363     lyr->SpatialIndex = GAIA_SPATIAL_INDEX_NONE;
3364     lyr->ExtentInfos = NULL;
3365     lyr->AuthInfos = NULL;
3366     lyr->First = NULL;
3367     lyr->Last = NULL;
3368     lyr->Next = NULL;
3369     list->Current = NULL;
3370     if (list->First == NULL)
3371 	list->First = lyr;
3372     if (list->Last != NULL)
3373 	list->Last->Next = lyr;
3374     list->Last = lyr;
3375 
3376     if (!doComputeFieldInfos
3377 	(handle, lyr->TableName, lyr->GeometryName,
3378 	 SPATIALITE_STATISTICS_LEGACY, lyr))
3379 	error = 1;
3380 
3381     if (list->First == NULL || error)
3382       {
3383 	  gaiaFreeVectorLayersList (list);
3384 	  return NULL;
3385       }
3386     return list;
3387 }
3388 
3389 static int
compute_max_int_length(sqlite3_int64 min,sqlite3_int64 max)3390 compute_max_int_length (sqlite3_int64 min, sqlite3_int64 max)
3391 {
3392 /* determining the buffer size for some INT */
3393     int pos_len = 0;
3394     int neg_len = 1;
3395     sqlite3_int64 value = max;
3396     if (value == 0)
3397 	pos_len = 1;
3398     else
3399       {
3400 	  while (value != 0)
3401 	    {
3402 		pos_len++;
3403 		value /= 10;
3404 	    }
3405       }
3406     if (min >= 0)
3407 	return pos_len;
3408     value = min;
3409     while (value != 0)
3410       {
3411 	  neg_len++;
3412 	  value /= 10;
3413       }
3414     if (neg_len > pos_len)
3415 	return neg_len;
3416     return pos_len;
3417 }
3418 
3419 static int
compute_max_dbl_length(double min,double max)3420 compute_max_dbl_length (double min, double max)
3421 {
3422 /* determining the buffer size for some DOUBLE */
3423     int pos_len = 0;
3424     int neg_len = 1;
3425     sqlite3_int64 value;
3426     if (max >= 0.0)
3427 	value = (sqlite3_int64) floor (max);
3428     else
3429 	value = (sqlite3_int64) ceil (max);
3430     while (value != 0)
3431       {
3432 	  pos_len++;
3433 	  value /= 10;
3434       }
3435     if (min >= 0.0)
3436 	return pos_len + 7;
3437     value = (sqlite3_int64) ceil (min);
3438     while (value != 0)
3439       {
3440 	  neg_len++;
3441 	  value /= 10;
3442       }
3443     if (neg_len > pos_len)
3444 	return neg_len + 7;
3445     return pos_len + 7;
3446 }
3447 
3448 static void
shp_parse_table_name(const char * tn,char ** db_prefix,char ** table_name)3449 shp_parse_table_name (const char *tn, char **db_prefix, char **table_name)
3450 {
3451 /* attempting to extract an eventual DB prefix */
3452     int i;
3453     int len = strlen (tn);
3454     int i_dot = -1;
3455     int l_db;
3456     int l_tbl;
3457     for (i = 0; i < len; i++)
3458       {
3459 	  if (tn[i] == '.')
3460 	    {
3461 		i_dot = i;
3462 		break;
3463 	    }
3464       }
3465     if (i_dot >= 1)
3466       {
3467 	  l_db = i_dot;
3468 	  l_tbl = len - (i_dot + 1);
3469 	  *db_prefix = malloc (l_db + 1);
3470 	  memset (*db_prefix, '\0', l_db + 1);
3471 	  memcpy (*db_prefix, tn, l_db);
3472 	  *table_name = malloc (l_tbl + 1);
3473 	  strcpy (*table_name, tn + i_dot + 1);
3474 	  return;
3475       }
3476     *table_name = malloc (len + 1);
3477     strcpy (*table_name, tn);
3478 }
3479 
3480 static int
get_attached_layer_v4(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry,gaiaVectorLayersListPtr list)3481 get_attached_layer_v4 (sqlite3 * handle, const char *db_prefix,
3482 		       const char *table, const char *geometry,
3483 		       gaiaVectorLayersListPtr list)
3484 {
3485 /* creating a VectorLayersList object - v.4.0.0 DB layout */
3486     char *sql;
3487     int ret;
3488     sqlite3_stmt *stmt;
3489     int error = 0;
3490     char *xdb;
3491 
3492 /* querying the vector_layers view */
3493     xdb = gaiaDoubleQuotedSql (db_prefix);
3494     sql =
3495 	sqlite3_mprintf
3496 	("SELECT layer_type, table_name, geometry_column, geometry_type, "
3497 	 "srid, spatial_index_enabled FROM \"%s\".vector_layers "
3498 	 "WHERE Lower(table_name) = Lower(%Q) AND "
3499 	 "Lower(geometry_column) = Lower(%Q)", xdb, table, geometry);
3500     free (xdb);
3501 /* compiling SQL prepared statement */
3502     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
3503     sqlite3_free (sql);
3504     if (ret != SQLITE_OK)
3505       {
3506 	  error = 1;
3507 	  goto stop;
3508       }
3509     while (1)
3510       {
3511 	  /* scrolling the result set rows */
3512 	  ret = sqlite3_step (stmt);
3513 	  if (ret == SQLITE_DONE)
3514 	      break;		/* end of result set */
3515 	  if (ret == SQLITE_ROW)
3516 	    {
3517 		/* processing a VectorLayer row */
3518 		const char *layer_type =
3519 		    (const char *) sqlite3_column_text (stmt, 0);
3520 		const char *table_name =
3521 		    (const char *) sqlite3_column_text (stmt, 1);
3522 		const char *geometry_column =
3523 		    (const char *) sqlite3_column_text (stmt, 2);
3524 		int geometry_type = sqlite3_column_int (stmt, 3);
3525 		int srid = sqlite3_column_int (stmt, 4);
3526 		int spatial_index = sqlite3_column_int (stmt, 5);
3527 		addVectorLayer (list, layer_type, table_name, geometry_column,
3528 				geometry_type, srid, spatial_index);
3529 	    }
3530 	  else
3531 	      error = 1;
3532       }
3533     ret = sqlite3_finalize (stmt);
3534 
3535   stop:
3536     if (error)
3537 	return 0;
3538 
3539 /* querying the vector_layers_statistics view */
3540     xdb = gaiaDoubleQuotedSql (db_prefix);
3541     sql =
3542 	sqlite3_mprintf
3543 	("SELECT table_name, geometry_column, row_count, extent_min_x, "
3544 	 "extent_min_y, extent_max_x, extent_max_y FROM \"%s\".vector_layers_statistics "
3545 	 "WHERE Lower(table_name) = Lower(%Q) AND "
3546 	 "Lower(geometry_column) = Lower(%Q)", xdb, table, geometry);
3547     free (xdb);
3548 /* compiling SQL prepared statement */
3549     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
3550     sqlite3_free (sql);
3551     if (ret != SQLITE_OK)
3552       {
3553 	  error = 1;
3554 	  goto stop2;
3555       }
3556     while (1)
3557       {
3558 	  /* scrolling the result set rows */
3559 	  ret = sqlite3_step (stmt);
3560 	  if (ret == SQLITE_DONE)
3561 	      break;		/* end of result set */
3562 	  if (ret == SQLITE_ROW)
3563 	    {
3564 		/* processing a VectorLayer row */
3565 		int is_null = 0;
3566 		const char *table_name =
3567 		    (const char *) sqlite3_column_text (stmt, 0);
3568 		const char *geometry_column =
3569 		    (const char *) sqlite3_column_text (stmt, 1);
3570 		int count = 0;
3571 		double min_x = 0.0;
3572 		double min_y = 0.0;
3573 		double max_x = 0.0;
3574 		double max_y = 0.0;
3575 		if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
3576 		    is_null = 1;
3577 		else
3578 		    count = sqlite3_column_int (stmt, 2);
3579 		if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
3580 		    is_null = 1;
3581 		else
3582 		    min_x = sqlite3_column_double (stmt, 3);
3583 		if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
3584 		    is_null = 1;
3585 		else
3586 		    min_y = sqlite3_column_double (stmt, 4);
3587 		if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
3588 		    is_null = 1;
3589 		else
3590 		    max_x = sqlite3_column_double (stmt, 5);
3591 		if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
3592 		    is_null = 1;
3593 		else
3594 		    max_y = sqlite3_column_double (stmt, 6);
3595 		if (!is_null)
3596 		    addVectorLayerExtent (list, table_name, geometry_column,
3597 					  count, min_x, min_y, max_x, max_y);
3598 	    }
3599       }
3600     ret = sqlite3_finalize (stmt);
3601 
3602   stop2:
3603 /* querying the vector_layers_field_infos view */
3604     xdb = gaiaDoubleQuotedSql (db_prefix);
3605     sql =
3606 	sqlite3_mprintf
3607 	("SELECT table_name, geometry_column, ordinal, column_name, "
3608 	 "null_values, integer_values, double_values, text_values, blob_values,"
3609 	 "max_size, integer_min, integer_max, double_min, double_max "
3610 	 "FROM \"%s\".vector_layers_field_infos "
3611 	 "WHERE Lower(table_name) = Lower(%Q) AND "
3612 	 "Lower(geometry_column) = Lower(%Q)", xdb, table, geometry);
3613     free (xdb);
3614 /* compiling SQL prepared statement */
3615     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
3616     sqlite3_free (sql);
3617     if (ret != SQLITE_OK)
3618       {
3619 	  error = 1;
3620 	  goto stop4;
3621       }
3622     while (1)
3623       {
3624 	  /* scrolling the result set rows */
3625 	  ret = sqlite3_step (stmt);
3626 	  if (ret == SQLITE_DONE)
3627 	      break;		/* end of result set */
3628 	  if (ret == SQLITE_ROW)
3629 	    {
3630 		/* processing a VectorLayer row */
3631 		int null_max_size = 0;
3632 		int null_int_range = 0;
3633 		int null_double_range = 0;
3634 		int max_size = 0;
3635 		sqlite3_int64 integer_min;
3636 		sqlite3_int64 integer_max;
3637 		double double_min = DBL_MAX;
3638 		double double_max = 0.0 - DBL_MAX;
3639 		const char *table_name =
3640 		    (const char *) sqlite3_column_text (stmt, 0);
3641 		const char *geometry_column =
3642 		    (const char *) sqlite3_column_text (stmt, 1);
3643 		int ordinal = sqlite3_column_int (stmt, 2);
3644 		const char *column_name =
3645 		    (const char *) sqlite3_column_text (stmt, 3);
3646 		int null_values = sqlite3_column_int (stmt, 4);
3647 		int integer_values = sqlite3_column_int (stmt, 5);
3648 		int double_values = sqlite3_column_int (stmt, 6);
3649 		int text_values = sqlite3_column_int (stmt, 7);
3650 		int blob_values = sqlite3_column_int (stmt, 8);
3651 		if (sqlite3_column_type (stmt, 9) == SQLITE_NULL)
3652 		    null_max_size = 1;
3653 		else
3654 		    max_size = sqlite3_column_int (stmt, 9);
3655 		if (sqlite3_column_type (stmt, 10) == SQLITE_NULL
3656 		    || sqlite3_column_type (stmt, 11) == SQLITE_NULL)
3657 		    null_int_range = 1;
3658 		else
3659 		  {
3660 		      integer_min = sqlite3_column_int64 (stmt, 10);
3661 		      integer_max = sqlite3_column_int64 (stmt, 11);
3662 		  }
3663 		if (sqlite3_column_type (stmt, 12) == SQLITE_NULL
3664 		    || sqlite3_column_type (stmt, 13) == SQLITE_NULL)
3665 		    null_double_range = 1;
3666 		else
3667 		  {
3668 		      double_min = sqlite3_column_double (stmt, 12);
3669 		      double_max = sqlite3_column_double (stmt, 13);
3670 		  }
3671 		addLayerAttributeField (list, table_name, geometry_column,
3672 					ordinal, column_name, null_values,
3673 					integer_values, double_values,
3674 					text_values, blob_values, null_max_size,
3675 					max_size, null_int_range, &integer_min,
3676 					&integer_max, null_double_range,
3677 					double_min, double_max);
3678 	    }
3679       }
3680     ret = sqlite3_finalize (stmt);
3681 
3682   stop4:
3683     if (error)
3684 	return 0;
3685     return 1;
3686 }
3687 
3688 static int
check_spatial_metadata(const void * handle,const char * db_prefix)3689 check_spatial_metadata (const void *handle, const char *db_prefix)
3690 {
3691 /* internal utility function:
3692 /
3693 / 0 - if no valid SpatialMetaData were found
3694 / 1 - if SpatiaLite-like (legacy) SpatialMetadata were found
3695 / 2 - if FDO-OGR-like SpatialMetadata were found
3696 / 3 - if SpatiaLite-like (current) SpatialMetadata were found
3697 /
3698 */
3699     sqlite3 *sqlite = (sqlite3 *) handle;
3700     int spatialite_legacy_rs = 0;
3701     int spatialite_rs = 0;
3702     int fdo_rs = 0;
3703     int spatialite_legacy_gc = 0;
3704     int spatialite_gc = 0;
3705     int fdo_gc = 0;
3706     int rs_srid = 0;
3707     int auth_name = 0;
3708     int auth_srid = 0;
3709     int srtext = 0;
3710     int ref_sys_name = 0;
3711     int proj4text = 0;
3712     int f_table_name = 0;
3713     int f_geometry_column = 0;
3714     int geometry_type = 0;
3715     int coord_dimension = 0;
3716     int gc_srid = 0;
3717     int geometry_format = 0;
3718     int type = 0;
3719     int spatial_index_enabled = 0;
3720     char *sql;
3721     int ret;
3722     const char *name;
3723     int i;
3724     char **results;
3725     int rows;
3726     int columns;
3727     char *xdb;
3728 /* checking the GEOMETRY_COLUMNS table */
3729     xdb = gaiaDoubleQuotedSql (db_prefix);
3730     sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(geometry_columns)", xdb);
3731     free (xdb);
3732     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
3733     sqlite3_free (sql);
3734     if (ret != SQLITE_OK)
3735 	goto unknown;
3736     if (rows < 1)
3737 	;
3738     else
3739       {
3740 	  for (i = 1; i <= rows; i++)
3741 	    {
3742 		name = results[(i * columns) + 1];
3743 		if (strcasecmp (name, "f_table_name") == 0)
3744 		    f_table_name = 1;
3745 		if (strcasecmp (name, "f_geometry_column") == 0)
3746 		    f_geometry_column = 1;
3747 		if (strcasecmp (name, "geometry_type") == 0)
3748 		    geometry_type = 1;
3749 		if (strcasecmp (name, "coord_dimension") == 0)
3750 		    coord_dimension = 1;
3751 		if (strcasecmp (name, "srid") == 0)
3752 		    gc_srid = 1;
3753 		if (strcasecmp (name, "geometry_format") == 0)
3754 		    geometry_format = 1;
3755 		if (strcasecmp (name, "type") == 0)
3756 		    type = 1;
3757 		if (strcasecmp (name, "spatial_index_enabled") == 0)
3758 		    spatial_index_enabled = 1;
3759 	    }
3760       }
3761     sqlite3_free_table (results);
3762     if (f_table_name && f_geometry_column && type && coord_dimension
3763 	&& gc_srid && spatial_index_enabled)
3764 	spatialite_legacy_gc = 1;
3765     if (f_table_name && f_geometry_column && geometry_type && coord_dimension
3766 	&& gc_srid && spatial_index_enabled)
3767 	spatialite_gc = 1;
3768     if (f_table_name && f_geometry_column && geometry_type && coord_dimension
3769 	&& gc_srid && geometry_format)
3770 	fdo_gc = 1;
3771 /* checking the SPATIAL_REF_SYS table */
3772     xdb = gaiaDoubleQuotedSql (db_prefix);
3773     sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(spatial_ref_sys)", xdb);
3774     free (xdb);
3775     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
3776     sqlite3_free (sql);
3777     if (ret != SQLITE_OK)
3778 	goto unknown;
3779     if (rows < 1)
3780 	;
3781     else
3782       {
3783 	  for (i = 1; i <= rows; i++)
3784 	    {
3785 		name = results[(i * columns) + 1];
3786 		if (strcasecmp (name, "srid") == 0)
3787 		    rs_srid = 1;
3788 		if (strcasecmp (name, "auth_name") == 0)
3789 		    auth_name = 1;
3790 		if (strcasecmp (name, "auth_srid") == 0)
3791 		    auth_srid = 1;
3792 		if (strcasecmp (name, "srtext") == 0)
3793 		    srtext = 1;
3794 		if (strcasecmp (name, "ref_sys_name") == 0)
3795 		    ref_sys_name = 1;
3796 		if (strcasecmp (name, "proj4text") == 0)
3797 		    proj4text = 1;
3798 		if (strcasecmp (name, "srtext") == 0)
3799 		    srtext = 1;
3800 	    }
3801       }
3802     sqlite3_free_table (results);
3803     if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text
3804 	&& srtext)
3805 	spatialite_rs = 1;
3806     if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text)
3807 	spatialite_legacy_rs = 1;
3808     if (rs_srid && auth_name && auth_srid && srtext)
3809 	fdo_rs = 1;
3810 /* verifying the MetaData format */
3811     if (spatialite_legacy_gc && spatialite_legacy_rs)
3812 	return 1;
3813     if (fdo_gc && fdo_rs)
3814 	return 2;
3815     if (spatialite_gc && spatialite_rs)
3816 	return 3;
3817   unknown:
3818     return 0;
3819 }
3820 
3821 static int
get_attached_table_layer_legacy(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry,gaiaVectorLayersListPtr list)3822 get_attached_table_layer_legacy (sqlite3 * handle, const char *db_prefix,
3823 				 const char *table, const char *geometry,
3824 				 gaiaVectorLayersListPtr list)
3825 {
3826 /* fetching Table-based geometries */
3827     int ret;
3828     char *sql;
3829     const char *name;
3830     int i;
3831     char **results;
3832     int rows;
3833     int columns;
3834     int f_table = 0;
3835     int f_geometry = 0;
3836     int type = 0;
3837     int dims = 0;
3838     int srid = 0;
3839     int spatial_index = 0;
3840     sqlite3_stmt *stmt;
3841     int error = 0;
3842     char *xdb;
3843 
3844 /* checking the GEOMETRY_COLUMN table */
3845     xdb = gaiaDoubleQuotedSql (db_prefix);
3846     sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(geometry_columns)", xdb);
3847     free (xdb);
3848     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
3849     sqlite3_free (sql);
3850     if (ret != SQLITE_OK)
3851 	return 0;
3852     if (rows < 1)
3853 	;
3854     else
3855       {
3856 	  for (i = 1; i <= rows; i++)
3857 	    {
3858 		name = results[(i * columns) + 1];
3859 		if (strcasecmp (name, "f_table_name") == 0)
3860 		    f_table = 1;
3861 		if (strcasecmp (name, "f_geometry_column") == 0)
3862 		    f_geometry = 1;
3863 		if (strcasecmp (name, "type") == 0)
3864 		    type = 1;
3865 		if (strcasecmp (name, "coord_dimension") == 0)
3866 		    dims = 1;
3867 		if (strcasecmp (name, "srid") == 0)
3868 		    srid = 1;
3869 		if (strcasecmp (name, "spatial_index_enabled") == 0)
3870 		    spatial_index = 1;
3871 	    }
3872       }
3873     sqlite3_free_table (results);
3874     if (f_table && f_geometry && type && dims && srid && spatial_index)
3875 	;
3876     else
3877 	return 1;
3878 
3879 
3880     xdb = gaiaDoubleQuotedSql (db_prefix);
3881     sql =
3882 	sqlite3_mprintf
3883 	("SELECT f_table_name, f_geometry_column, type, coord_dimension, "
3884 	 "srid, spatial_index_enabled FROM \"%s\".geometry_columns "
3885 	 "WHERE Lower(f_table_name) = Lower(%Q) AND "
3886 	 "Lower(f_geometry_column) = Lower(%Q)", xdb, table, geometry);
3887     free (xdb);
3888 /* compiling SQL prepared statement */
3889     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
3890     sqlite3_free (sql);
3891     if (ret != SQLITE_OK)
3892       {
3893 	  error = 1;
3894 	  goto stop;
3895       }
3896     while (1)
3897       {
3898 	  /* scrolling the result set rows */
3899 	  ret = sqlite3_step (stmt);
3900 	  if (ret == SQLITE_DONE)
3901 	      break;		/* end of result set */
3902 	  if (ret == SQLITE_ROW)
3903 	    {
3904 		/* processing a VectorLayer row */
3905 		const char *table_name =
3906 		    (const char *) sqlite3_column_text (stmt, 0);
3907 		const char *geometry_column =
3908 		    (const char *) sqlite3_column_text (stmt, 1);
3909 		const char *type = (const char *) sqlite3_column_text (stmt, 2);
3910 		const char *dims = (const char *) sqlite3_column_text (stmt, 3);
3911 		int srid = sqlite3_column_int (stmt, 4);
3912 		int spatial_index = sqlite3_column_int (stmt, 5);
3913 		int geometry_type = -1;
3914 		if (strcasecmp (type, "POINT") == 0)
3915 		    geometry_type = 1;
3916 		if (strcasecmp (type, "LINESTRING") == 0)
3917 		    geometry_type = 2;
3918 		if (strcasecmp (type, "POLYGON") == 0)
3919 		    geometry_type = 3;
3920 		if (strcasecmp (type, "MULTIPOINT") == 0)
3921 		    geometry_type = 4;
3922 		if (strcasecmp (type, "MULTILINESTRING") == 0)
3923 		    geometry_type = 5;
3924 		if (strcasecmp (type, "MULTIPOLYGON") == 0)
3925 		    geometry_type = 6;
3926 		if (strcasecmp (type, "GEOMETRYCOLLECTION") == 0)
3927 		    geometry_type = 7;
3928 		if (strcasecmp (type, "GEOMETRY") == 0)
3929 		    geometry_type = 0;
3930 		if (strcasecmp (dims, "XYZ") == 0
3931 		    || strcasecmp (dims, "3") == 0)
3932 		    geometry_type += 1000;
3933 		if (strcasecmp (dims, "XYM") == 0)
3934 		    geometry_type += 2000;
3935 		if (strcasecmp (dims, "XYZM") == 0
3936 		    || strcasecmp (dims, "4") == 0)
3937 		    geometry_type += 3000;
3938 		addVectorLayer (list, "SpatialTable", table_name,
3939 				geometry_column, geometry_type, srid,
3940 				spatial_index);
3941 	    }
3942 	  else
3943 	      error = 1;
3944       }
3945     ret = sqlite3_finalize (stmt);
3946 
3947   stop:
3948     if (error)
3949 	return 0;
3950     return 1;
3951 }
3952 
3953 static int
get_attached_view_layer_legacy(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry,gaiaVectorLayersListPtr list)3954 get_attached_view_layer_legacy (sqlite3 * handle, const char *db_prefix,
3955 				const char *table, const char *geometry,
3956 				gaiaVectorLayersListPtr list)
3957 {
3958 /* fetching View-based geometries */
3959     int ret;
3960     char *sql;
3961     const char *name;
3962     int i;
3963     char **results;
3964     int rows;
3965     int columns;
3966     int f_table = 0;
3967     int f_geometry = 0;
3968     int type = 0;
3969     int dims = 0;
3970     int srid = 0;
3971     int spatial_index = 0;
3972     int view_name = 0;
3973     int view_geometry = 0;
3974     int fvw_table = 0;
3975     int fvw_geometry = 0;
3976     sqlite3_stmt *stmt;
3977     int error = 0;
3978     char *xdb;
3979 
3980 /* checking the GEOMETRY_COLUMN table */
3981     xdb = gaiaDoubleQuotedSql (db_prefix);
3982     sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(geometry_columns)", xdb);
3983     free (xdb);
3984     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
3985     sqlite3_free (sql);
3986     if (ret != SQLITE_OK)
3987 	return 0;
3988     if (rows < 1)
3989 	;
3990     else
3991       {
3992 	  for (i = 1; i <= rows; i++)
3993 	    {
3994 		name = results[(i * columns) + 1];
3995 		if (strcasecmp (name, "f_table_name") == 0)
3996 		    f_table = 1;
3997 		if (strcasecmp (name, "f_geometry_column") == 0)
3998 		    f_geometry = 1;
3999 		if (strcasecmp (name, "type") == 0)
4000 		    type = 1;
4001 		if (strcasecmp (name, "coord_dimension") == 0)
4002 		    dims = 1;
4003 		if (strcasecmp (name, "srid") == 0)
4004 		    srid = 1;
4005 		if (strcasecmp (name, "spatial_index_enabled") == 0)
4006 		    spatial_index = 1;
4007 	    }
4008       }
4009     sqlite3_free_table (results);
4010     if (f_table && f_geometry && type && dims && srid && spatial_index)
4011 	;
4012     else
4013 	return 1;
4014 
4015 /* checking the VIEWS_GEOMETRY_COLUMN table */
4016     xdb = gaiaDoubleQuotedSql (db_prefix);
4017     sql =
4018 	sqlite3_mprintf ("PRAGMA \"%s\".table_info(views_geometry_columns)",
4019 			 xdb);
4020     free (xdb);
4021     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
4022     sqlite3_free (sql);
4023     if (ret != SQLITE_OK)
4024 	return 0;
4025     if (rows < 1)
4026 	;
4027     else
4028       {
4029 	  for (i = 1; i <= rows; i++)
4030 	    {
4031 		name = results[(i * columns) + 1];
4032 		if (strcasecmp (name, "view_name") == 0)
4033 		    view_name = 1;
4034 		if (strcasecmp (name, "view_geometry") == 0)
4035 		    view_geometry = 1;
4036 		if (strcasecmp (name, "f_table_name") == 0)
4037 		    fvw_table = 1;
4038 		if (strcasecmp (name, "f_geometry_column") == 0)
4039 		    fvw_geometry = 1;
4040 	    }
4041       }
4042     sqlite3_free_table (results);
4043     if (view_name && view_geometry && fvw_table && fvw_geometry)
4044 	;
4045     else
4046 	return 1;
4047 
4048     xdb = gaiaDoubleQuotedSql (db_prefix);
4049     sql =
4050 	sqlite3_mprintf
4051 	("SELECT a.view_name, a.view_geometry, b.type, b.coord_dimension, "
4052 	 "b.srid, b.spatial_index_enabled FROM \"%s\".views_geometry_columns AS a "
4053 	 "JOIN \"%s\".geometry_columns AS b ON (Lower(a.f_table_name) = Lower(b.f_table_name) "
4054 	 "AND Lower(a.f_geometry_column) = Lower(b.f_geometry_column)) "
4055 	 "WHERE Lower(a.view_name) = Lower(%Q) AND "
4056 	 "Lower(a.view_geometry) = Lower(%Q)", xdb, xdb, table, geometry);
4057     free (xdb);
4058 /* compiling SQL prepared statement */
4059     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4060     sqlite3_free (sql);
4061     if (ret != SQLITE_OK)
4062       {
4063 	  error = 1;
4064 	  goto stop;
4065       }
4066     while (1)
4067       {
4068 	  /* scrolling the result set rows */
4069 	  ret = sqlite3_step (stmt);
4070 	  if (ret == SQLITE_DONE)
4071 	      break;		/* end of result set */
4072 	  if (ret == SQLITE_ROW)
4073 	    {
4074 		/* processing a VectorLayer row */
4075 		const char *table_name =
4076 		    (const char *) sqlite3_column_text (stmt, 0);
4077 		const char *geometry_column =
4078 		    (const char *) sqlite3_column_text (stmt, 1);
4079 		const char *type = (const char *) sqlite3_column_text (stmt, 2);
4080 		const char *dims = (const char *) sqlite3_column_text (stmt, 3);
4081 		int srid = sqlite3_column_int (stmt, 4);
4082 		int spatial_index = sqlite3_column_int (stmt, 5);
4083 		int geometry_type = -1;
4084 		if (strcasecmp (type, "POINT") == 0)
4085 		    geometry_type = 1;
4086 		if (strcasecmp (type, "LINESTRING") == 0)
4087 		    geometry_type = 2;
4088 		if (strcasecmp (type, "POLYGON") == 0)
4089 		    geometry_type = 3;
4090 		if (strcasecmp (type, "MULTIPOINT") == 0)
4091 		    geometry_type = 4;
4092 		if (strcasecmp (type, "MULTILINESTRING") == 0)
4093 		    geometry_type = 5;
4094 		if (strcasecmp (type, "MULTIPOLYGON") == 0)
4095 		    geometry_type = 6;
4096 		if (strcasecmp (type, "GEOMETRYCOLLECTION") == 0)
4097 		    geometry_type = 7;
4098 		if (strcasecmp (type, "GEOMETRY") == 0)
4099 		    geometry_type = 0;
4100 		if (strcasecmp (dims, "XYZ") == 0
4101 		    || strcasecmp (dims, "3") == 0)
4102 		    geometry_type += 1000;
4103 		if (strcasecmp (dims, "XYM") == 0)
4104 		    geometry_type += 2000;
4105 		if (strcasecmp (dims, "XYZM") == 0
4106 		    || strcasecmp (dims, "4") == 0)
4107 		    geometry_type += 3000;
4108 		addVectorLayer (list, "SpatialView", table_name,
4109 				geometry_column, geometry_type, srid,
4110 				spatial_index);
4111 	    }
4112 	  else
4113 	      error = 1;
4114       }
4115     ret = sqlite3_finalize (stmt);
4116 
4117   stop:
4118     if (error)
4119 	return 0;
4120     return 1;
4121 }
4122 
4123 static int
get_attached_table_extent_legacy(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry,gaiaVectorLayersListPtr list)4124 get_attached_table_extent_legacy (sqlite3 * handle, const char *db_prefix,
4125 				  const char *table, const char *geometry,
4126 				  gaiaVectorLayersListPtr list)
4127 {
4128 /* fetching Table-based extents */
4129     int ret;
4130     char *sql;
4131     const char *name;
4132     int i;
4133     char **results;
4134     int rows;
4135     int columns;
4136     int f_table = 0;
4137     int f_geometry = 0;
4138     int count = 0;
4139     int minx = 0;
4140     int miny = 0;
4141     int maxx = 0;
4142     int maxy = 0;
4143     sqlite3_stmt *stmt;
4144     char *xdb;
4145 
4146 /* checking the LAYER_STATISTICS table */
4147     xdb = gaiaDoubleQuotedSql (db_prefix);
4148     sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(layer_statistics)", xdb);
4149     free (xdb);
4150     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
4151     sqlite3_free (sql);
4152     if (ret != SQLITE_OK)
4153 	return 0;
4154     if (rows < 1)
4155 	;
4156     else
4157       {
4158 	  for (i = 1; i <= rows; i++)
4159 	    {
4160 		name = results[(i * columns) + 1];
4161 		if (strcasecmp (name, "table_name") == 0)
4162 		    f_table = 1;
4163 		if (strcasecmp (name, "geometry_column") == 0)
4164 		    f_geometry = 1;
4165 		if (strcasecmp (name, "row_count") == 0)
4166 		    count = 1;
4167 		if (strcasecmp (name, "extent_min_x") == 0)
4168 		    minx = 1;
4169 		if (strcasecmp (name, "extent_min_y") == 0)
4170 		    miny = 1;
4171 		if (strcasecmp (name, "extent_max_x") == 0)
4172 		    maxx = 1;
4173 		if (strcasecmp (name, "extent_max_y") == 0)
4174 		    maxy = 1;
4175 	    }
4176       }
4177     sqlite3_free_table (results);
4178     if (f_table && f_geometry && count && minx && miny && maxx && maxy)
4179 	;
4180     else
4181 	return 1;
4182 
4183 /* querying the layer_statistics table */
4184     xdb = gaiaDoubleQuotedSql (db_prefix);
4185     sql =
4186 	sqlite3_mprintf
4187 	("SELECT table_name, geometry_column, row_count, extent_min_x, "
4188 	 "extent_min_y, extent_max_x, extent_max_y FROM \"%s\".layer_statistics "
4189 	 "WHERE Lower(table_name) = Lower(%Q) AND "
4190 	 "Lower(geometry_column) = Lower(%Q)", xdb, table, geometry);
4191     free (xdb);
4192 /* compiling SQL prepared statement */
4193     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4194     sqlite3_free (sql);
4195     if (ret != SQLITE_OK)
4196 	goto stop;
4197     while (1)
4198       {
4199 	  /* scrolling the result set rows */
4200 	  ret = sqlite3_step (stmt);
4201 	  if (ret == SQLITE_DONE)
4202 	      break;		/* end of result set */
4203 	  if (ret == SQLITE_ROW)
4204 	    {
4205 		/* processing a VectorLayer row */
4206 		int is_null = 0;
4207 		const char *table_name =
4208 		    (const char *) sqlite3_column_text (stmt, 0);
4209 		const char *geometry_column =
4210 		    (const char *) sqlite3_column_text (stmt, 1);
4211 		int count = 0;
4212 		double min_x = 0.0;
4213 		double min_y = 0.0;
4214 		double max_x = 0.0;
4215 		double max_y = 0.0;
4216 		if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
4217 		    is_null = 1;
4218 		else
4219 		    count = sqlite3_column_int (stmt, 2);
4220 		if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
4221 		    is_null = 1;
4222 		else
4223 		    min_x = sqlite3_column_double (stmt, 3);
4224 		if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
4225 		    is_null = 1;
4226 		else
4227 		    min_y = sqlite3_column_double (stmt, 4);
4228 		if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
4229 		    is_null = 1;
4230 		else
4231 		    max_x = sqlite3_column_double (stmt, 5);
4232 		if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
4233 		    is_null = 1;
4234 		else
4235 		    max_y = sqlite3_column_double (stmt, 6);
4236 		if (!is_null)
4237 		    addVectorLayerExtent (list, table_name, geometry_column,
4238 					  count, min_x, min_y, max_x, max_y);
4239 	    }
4240       }
4241     ret = sqlite3_finalize (stmt);
4242   stop:
4243     return 1;
4244 }
4245 
4246 static int
get_attached_view_extent_legacy(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry,gaiaVectorLayersListPtr list)4247 get_attached_view_extent_legacy (sqlite3 * handle, const char *db_prefix,
4248 				 const char *table, const char *geometry,
4249 				 gaiaVectorLayersListPtr list)
4250 {
4251 /* fetching View-based extents */
4252     int ret;
4253     char *sql;
4254     const char *name;
4255     int i;
4256     char **results;
4257     int rows;
4258     int columns;
4259     int f_table = 0;
4260     int f_geometry = 0;
4261     int count = 0;
4262     int minx = 0;
4263     int miny = 0;
4264     int maxx = 0;
4265     int maxy = 0;
4266     sqlite3_stmt *stmt;
4267     char *xdb;
4268 
4269 /* checking the VIEWS_LAYER_STATISTICS table */
4270     xdb = gaiaDoubleQuotedSql (db_prefix);
4271     sql =
4272 	sqlite3_mprintf ("PRAGMA \"%s\".table_info(views_layer_statistics)",
4273 			 xdb);
4274     free (xdb);
4275     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
4276     sqlite3_free (sql);
4277     if (ret != SQLITE_OK)
4278 	return 0;
4279     if (rows < 1)
4280 	;
4281     else
4282       {
4283 	  for (i = 1; i <= rows; i++)
4284 	    {
4285 		name = results[(i * columns) + 1];
4286 		if (strcasecmp (name, "view_name") == 0)
4287 		    f_table = 1;
4288 		if (strcasecmp (name, "view_geometry") == 0)
4289 		    f_geometry = 1;
4290 		if (strcasecmp (name, "row_count") == 0)
4291 		    count = 1;
4292 		if (strcasecmp (name, "extent_min_x") == 0)
4293 		    minx = 1;
4294 		if (strcasecmp (name, "extent_min_y") == 0)
4295 		    miny = 1;
4296 		if (strcasecmp (name, "extent_max_x") == 0)
4297 		    maxx = 1;
4298 		if (strcasecmp (name, "extent_max_y") == 0)
4299 		    maxy = 1;
4300 	    }
4301       }
4302     sqlite3_free_table (results);
4303     if (f_table && f_geometry && count && minx && miny && maxx && maxy)
4304 	;
4305     else
4306 	return 1;
4307 
4308 /* querying the views_layer_statistics table */
4309 
4310     xdb = gaiaDoubleQuotedSql (db_prefix);
4311     sql =
4312 	sqlite3_mprintf
4313 	("SELECT view_name, view_geometry, row_count, extent_min_x, "
4314 	 "extent_min_y, extent_max_x, extent_max_y FROM \"%s\".views_layer_statistics "
4315 	 "WHERE Lower(view_name) = Lower(%Q) AND "
4316 	 "Lower(view_geometry) = Lower(%Q)", xdb, table, geometry);
4317     free (xdb);
4318 /* compiling SQL prepared statement */
4319     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4320     sqlite3_free (sql);
4321     if (ret != SQLITE_OK)
4322 	goto stop;
4323     while (1)
4324       {
4325 	  /* scrolling the result set rows */
4326 	  ret = sqlite3_step (stmt);
4327 	  if (ret == SQLITE_DONE)
4328 	      break;		/* end of result set */
4329 	  if (ret == SQLITE_ROW)
4330 	    {
4331 		/* processing a VectorLayer row */
4332 		int is_null = 0;
4333 		const char *table_name =
4334 		    (const char *) sqlite3_column_text (stmt, 0);
4335 		const char *geometry_column =
4336 		    (const char *) sqlite3_column_text (stmt, 1);
4337 		int count = 0;
4338 		double min_x = DBL_MAX;
4339 		double min_y = DBL_MAX;
4340 		double max_x = 0.0 - DBL_MAX;
4341 		double max_y = 0.0 - DBL_MAX;
4342 		if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
4343 		    is_null = 1;
4344 		else
4345 		    count = sqlite3_column_int (stmt, 2);
4346 		if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
4347 		    is_null = 1;
4348 		else
4349 		    min_x = sqlite3_column_double (stmt, 3);
4350 		if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
4351 		    is_null = 1;
4352 		else
4353 		    min_y = sqlite3_column_double (stmt, 4);
4354 		if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
4355 		    is_null = 1;
4356 		else
4357 		    max_x = sqlite3_column_double (stmt, 5);
4358 		if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
4359 		    is_null = 1;
4360 		else
4361 		    max_y = sqlite3_column_double (stmt, 6);
4362 		if (!is_null)
4363 		    addVectorLayerExtent (list, table_name, geometry_column,
4364 					  count, min_x, min_y, max_x, max_y);
4365 	    }
4366       }
4367     ret = sqlite3_finalize (stmt);
4368   stop:
4369     return 1;
4370 }
4371 
4372 static gaiaVectorLayersListPtr
attached_layer(sqlite3 * handle,const char * db_prefix,const char * table,const char * geometry)4373 attached_layer (sqlite3 * handle, const char *db_prefix, const char *table,
4374 		const char *geometry)
4375 {
4376 /* attempting to support a "layer" from within an attached DB */
4377     gaiaVectorLayersListPtr list;
4378     int metadata_version;
4379     list = malloc (sizeof (gaiaVectorLayersList));
4380     list->First = NULL;
4381     list->Last = NULL;
4382     list->Current = NULL;
4383 
4384     metadata_version = check_spatial_metadata (handle, db_prefix);
4385     if (metadata_version == 3)
4386       {
4387 	  /* current metadata style >= v.4.0.0 */
4388 	  if (!get_attached_layer_v4 (handle, db_prefix, table, geometry, list))
4389 	    {
4390 		gaiaFreeVectorLayersList (list);
4391 		return NULL;
4392 	    }
4393 	  if (list->First == NULL)
4394 	    {
4395 		gaiaFreeVectorLayersList (list);
4396 		return NULL;
4397 	    }
4398 	  return list;
4399       }
4400 
4401 /* legacy metadata style <= v.3.x.x */
4402     if (!get_attached_table_layer_legacy
4403 	(handle, db_prefix, table, geometry, list))
4404 	goto error;
4405     if (!get_attached_view_layer_legacy
4406 	(handle, db_prefix, table, geometry, list))
4407 	goto error;
4408     if (!get_attached_table_extent_legacy
4409 	(handle, db_prefix, table, geometry, list))
4410 	goto error;
4411     if (!get_attached_view_extent_legacy
4412 	(handle, db_prefix, table, geometry, list))
4413 	goto error;
4414 
4415     if (list->First == NULL)
4416       {
4417 	  gaiaFreeVectorLayersList (list);
4418 	  return NULL;
4419       }
4420     return list;
4421 
4422   error:
4423     gaiaFreeVectorLayersList (list);
4424     return NULL;
4425 }
4426 
4427 static int
compute_text_length(const char * string,const char * charset)4428 compute_text_length (const char *string, const char *charset)
4429 {
4430 /* computing the actual length of TEXT fields */
4431     int len = 0;
4432     char *converted = sqlite3_malloc (strlen (string) + 1);
4433     strcpy (converted, string);
4434     if (gaiaConvertCharset (&converted, "UTF-8", charset))
4435 	len = strlen (converted);
4436     sqlite3_free (converted);
4437     return len;
4438 }
4439 
4440 static void
compute_exact_text_max_length(sqlite3 * sqlite,gaiaDbfListPtr dbf_list,const char * table,const char * charset)4441 compute_exact_text_max_length (sqlite3 * sqlite, gaiaDbfListPtr dbf_list,
4442 			       const char *table, const char *charset)
4443 {
4444 /* computing the exact max length of TEXT fields */
4445     char *sql;
4446     char *prevsql;
4447     char *xtable;
4448     gaiaDbfFieldPtr fld;
4449     int first = 1;
4450     int ok = 0;
4451     int ret;
4452     sqlite3_stmt *stmt = NULL;
4453     int offset = 0;
4454 
4455 /* preparing the SQL query */
4456     sql = sqlite3_mprintf ("SELECT");
4457     prevsql = sql;
4458     fld = dbf_list->First;
4459     while (fld)
4460       {
4461 	  char *xcolumn;
4462 	  if (fld->Type != 'C')
4463 	      goto skip_field;
4464 	  ok = 1;
4465 	  xcolumn = gaiaDoubleQuotedSql (fld->Name);
4466 	  if (first)
4467 	    {
4468 		sql = sqlite3_mprintf ("%s \"%s\"", prevsql, xcolumn);
4469 		first = 0;
4470 	    }
4471 	  else
4472 	      sql = sqlite3_mprintf ("%s, \"%s\"", prevsql, xcolumn);
4473 	  free (xcolumn);
4474 	  sqlite3_free (prevsql);
4475 	  prevsql = sql;
4476 
4477 	skip_field:
4478 	  fld = fld->Next;
4479       }
4480     if (!ok)
4481       {
4482 	  sqlite3_free (sql);
4483 	  return;
4484       }
4485 
4486     xtable = gaiaDoubleQuotedSql (table);
4487     sql = sqlite3_mprintf ("%s FROM \"%s\"", prevsql, xtable);
4488     sqlite3_free (prevsql);
4489     free (xtable);
4490     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4491     sqlite3_free (sql);
4492     if (ret != SQLITE_OK)
4493 	return;
4494     while (1)
4495       {
4496 	  /* scrolling the result set rows */
4497 	  ret = sqlite3_step (stmt);
4498 	  if (ret == SQLITE_DONE)
4499 	      break;		/* end of result set */
4500 	  if (ret == SQLITE_ROW)
4501 	    {
4502 		int col = 0;
4503 		fld = dbf_list->First;
4504 		while (fld)
4505 		  {
4506 		      if (fld->Type != 'C')
4507 			  goto skip_field2;
4508 		      if (sqlite3_column_type (stmt, col) == SQLITE_TEXT)
4509 			{
4510 			    const char *string = (const char *)
4511 				sqlite3_column_text (stmt, col);
4512 			    char *converted =
4513 				sqlite3_malloc (strlen (string) + 1);
4514 			    strcpy (converted, string);
4515 			    if (gaiaConvertCharset
4516 				(&converted, "UTF-8", charset))
4517 			      {
4518 				  /* we need to determine the field length _AFTER_ converting to the output charset */
4519 				  int len = strlen (converted);
4520 				  if (len > fld->Length)
4521 				      fld->Length = len;
4522 				  sqlite3_free (converted);
4523 			      }
4524 			    col++;
4525 			}
4526 		    skip_field2:
4527 		      fld = fld->Next;
4528 		  }
4529 	    }
4530       }
4531     sqlite3_finalize (stmt);
4532 
4533     fld = dbf_list->First;
4534     while (fld)
4535       {
4536 	  /* readjusting all offsets */
4537 	  fld->Offset = offset;
4538 	  offset += fld->Length;
4539 	  fld = fld->Next;
4540       }
4541 }
4542 
4543 SPATIALITE_DECLARE int
dump_shapefile(sqlite3 * sqlite,char * table,char * column,char * shp_path,char * charset,char * geom_type,int verbose,int * xrows,char * err_msg)4544 dump_shapefile (sqlite3 * sqlite, char *table, char *column, char *shp_path,
4545 		char *charset, char *geom_type, int verbose, int *xrows,
4546 		char *err_msg)
4547 {
4548     return dump_shapefile_ex (sqlite, table, column, shp_path, charset,
4549 			      geom_type, verbose, xrows,
4550 			      GAIA_DBF_COLNAME_CASE_IGNORE, err_msg);
4551 }
4552 
4553 SPATIALITE_DECLARE int
dump_shapefile_ex(sqlite3 * sqlite,char * table,char * column,char * shp_path,char * charset,char * geom_type,int verbose,int * xrows,int colname_case,char * err_msg)4554 dump_shapefile_ex (sqlite3 * sqlite, char *table, char *column, char *shp_path,
4555 		   char *charset, char *geom_type, int verbose, int *xrows,
4556 		   int colname_case, char *err_msg)
4557 {
4558     return dump_shapefile_ex2 (sqlite, NULL, table, column, shp_path, charset,
4559 			       geom_type, verbose, xrows,
4560 			       colname_case, err_msg);
4561 }
4562 
4563 SPATIALITE_DECLARE int
dump_shapefile_ex2(sqlite3 * sqlite,void * proj_ctx,char * table,char * column,char * shp_path,char * charset,char * geom_type,int verbose,int * xrows,int colname_case,char * err_msg)4564 dump_shapefile_ex2 (sqlite3 * sqlite, void *proj_ctx, char *table, char *column,
4565 		    char *shp_path, char *charset, char *geom_type, int verbose,
4566 		    int *xrows, int colname_case, char *err_msg)
4567 {
4568 /* SHAPEFILE dump */
4569     char *sql;
4570     char *dummy;
4571     int shape = -1;
4572     int len;
4573     int ret;
4574     sqlite3_stmt *stmt;
4575     int n_cols = 0;
4576     int offset = 0;
4577     int i;
4578     int rows = 0;
4579     char buf[256];
4580     char *xtable;
4581     char *xcolumn;
4582     const void *blob_value;
4583     gaiaShapefilePtr shp = NULL;
4584     gaiaDbfListPtr dbf_list = NULL;
4585     gaiaDbfListPtr dbf_write;
4586     gaiaDbfFieldPtr dbf_field;
4587     gaiaVectorLayerPtr lyr = NULL;
4588     gaiaLayerAttributeFieldPtr fld;
4589     gaiaVectorLayersListPtr list;
4590     char *db_prefix = NULL;
4591     char *table_name = NULL;
4592     char *xprefix;
4593     char *xxtable;
4594     struct auxdbf_list *auxdbf = NULL;
4595 
4596     if (xrows)
4597 	*xrows = -1;
4598     if (geom_type)
4599       {
4600 	  /* normalizing required geometry type */
4601 	  if (strcasecmp ((char *) geom_type, "POINT") == 0)
4602 	      shape = GAIA_POINT;
4603 	  if (strcasecmp ((char *) geom_type, "LINESTRING") == 0)
4604 	      shape = GAIA_LINESTRING;
4605 	  if (strcasecmp ((char *) geom_type, "POLYGON") == 0)
4606 	      shape = GAIA_POLYGON;
4607 	  if (strcasecmp ((char *) geom_type, "MULTIPOINT") == 0)
4608 	      shape = GAIA_MULTIPOINT;
4609       }
4610 /* is the datasource a genuine registered Geometry ?? */
4611     list = gaiaGetVectorLayersList (sqlite, table, column,
4612 				    GAIA_VECTORS_LIST_PESSIMISTIC);
4613     if (list == NULL)
4614       {
4615 	  /* attempting to recover an unregistered Geometry */
4616 	  list = recover_unregistered_geometry (sqlite, table, column);
4617       }
4618 
4619     if (list == NULL)
4620       {
4621 	  /* attempting to enucleate an eventual DB-prefix */
4622 	  shp_parse_table_name (table, &db_prefix, &table_name);
4623 	  if (db_prefix != NULL && table_name != NULL)
4624 	      list = attached_layer (sqlite, db_prefix, table_name, column);
4625       }
4626 
4627     if (list != NULL)
4628 	lyr = list->First;
4629     if (lyr == NULL)
4630       {
4631 	  gaiaFreeVectorLayersList (list);
4632 	  if (!err_msg)
4633 	      spatialite_e
4634 		  ("Unable to detect GeometryType for \"%s\".\"%s\" ... sorry\n",
4635 		   table, column);
4636 	  else
4637 	      sprintf (err_msg,
4638 		       "Unable to detect GeometryType for \"%s\".\"%s\" ... sorry\n",
4639 		       table, column);
4640 	  return 0;
4641       }
4642 
4643     switch (lyr->GeometryType)
4644       {
4645       case GAIA_VECTOR_POINT:
4646 	  switch (lyr->Dimensions)
4647 	    {
4648 	    case GAIA_XY:
4649 		shape = GAIA_POINT;
4650 		break;
4651 	    case GAIA_XY_Z:
4652 		shape = GAIA_POINTZ;
4653 		break;
4654 	    case GAIA_XY_M:
4655 		shape = GAIA_POINTM;
4656 		break;
4657 	    case GAIA_XY_Z_M:
4658 		shape = GAIA_POINTZM;
4659 		break;
4660 	    };
4661 	  break;
4662       case GAIA_VECTOR_LINESTRING:
4663 	  switch (lyr->Dimensions)
4664 	    {
4665 	    case GAIA_XY:
4666 		shape = GAIA_LINESTRING;
4667 		break;
4668 	    case GAIA_XY_Z:
4669 		shape = GAIA_LINESTRINGZ;
4670 		break;
4671 	    case GAIA_XY_M:
4672 		shape = GAIA_LINESTRINGM;
4673 		break;
4674 	    case GAIA_XY_Z_M:
4675 		shape = GAIA_LINESTRINGZM;
4676 		break;
4677 	    };
4678 	  break;
4679       case GAIA_VECTOR_POLYGON:
4680 	  switch (lyr->Dimensions)
4681 	    {
4682 	    case GAIA_XY:
4683 		shape = GAIA_POLYGON;
4684 		break;
4685 	    case GAIA_XY_Z:
4686 		shape = GAIA_POLYGONZ;
4687 		break;
4688 	    case GAIA_XY_M:
4689 		shape = GAIA_POLYGONM;
4690 		break;
4691 	    case GAIA_XY_Z_M:
4692 		shape = GAIA_POLYGONZM;
4693 		break;
4694 	    };
4695 	  break;
4696       case GAIA_VECTOR_MULTIPOINT:
4697 	  switch (lyr->Dimensions)
4698 	    {
4699 	    case GAIA_XY:
4700 		shape = GAIA_MULTIPOINT;
4701 		break;
4702 	    case GAIA_XY_Z:
4703 		shape = GAIA_MULTIPOINTZ;
4704 		break;
4705 	    case GAIA_XY_M:
4706 		shape = GAIA_MULTIPOINTM;
4707 		break;
4708 	    case GAIA_XY_Z_M:
4709 		shape = GAIA_MULTIPOINTZM;
4710 		break;
4711 	    };
4712 	  break;
4713       case GAIA_VECTOR_MULTILINESTRING:
4714 	  switch (lyr->Dimensions)
4715 	    {
4716 	    case GAIA_XY:
4717 		shape = GAIA_MULTILINESTRING;
4718 		break;
4719 	    case GAIA_XY_Z:
4720 		shape = GAIA_MULTILINESTRINGZ;
4721 		break;
4722 	    case GAIA_XY_M:
4723 		shape = GAIA_MULTILINESTRINGM;
4724 		break;
4725 	    case GAIA_XY_Z_M:
4726 		shape = GAIA_MULTILINESTRINGZM;
4727 		break;
4728 	    };
4729 	  break;
4730       case GAIA_VECTOR_MULTIPOLYGON:
4731 	  switch (lyr->Dimensions)
4732 	    {
4733 	    case GAIA_XY:
4734 		shape = GAIA_MULTIPOLYGON;
4735 		break;
4736 	    case GAIA_XY_Z:
4737 		shape = GAIA_MULTIPOLYGONZ;
4738 		break;
4739 	    case GAIA_XY_M:
4740 		shape = GAIA_MULTIPOLYGONM;
4741 		break;
4742 	    case GAIA_XY_Z_M:
4743 		shape = GAIA_MULTIPOLYGONZM;
4744 		break;
4745 	    };
4746 	  break;
4747       };
4748 
4749     if (shape < 0)
4750       {
4751 	  if (!err_msg)
4752 	      spatialite_e
4753 		  ("Unable to detect GeometryType for \"%s\".\"%s\" ... sorry\n",
4754 		   table, column);
4755 	  else
4756 	      sprintf (err_msg,
4757 		       "Unable to detect GeometryType for \"%s\".\"%s\" ... sorry\n",
4758 		       table, column);
4759 	  return 0;
4760       }
4761     if (verbose)
4762 	spatialite_e
4763 	    ("========\nDumping SQLite table '%s' into shapefile at '%s'\n",
4764 	     table, shp_path);
4765     /* preparing SQL statement */
4766     xtable = gaiaDoubleQuotedSql (table);
4767     xcolumn = gaiaDoubleQuotedSql (column);
4768     if (shape == GAIA_LINESTRING || shape == GAIA_LINESTRINGZ
4769 	|| shape == GAIA_LINESTRINGM || shape == GAIA_LINESTRINGZM ||
4770 	shape == GAIA_MULTILINESTRING || shape == GAIA_MULTILINESTRINGZ
4771 	|| shape == GAIA_MULTILINESTRINGM || shape == GAIA_MULTILINESTRINGZM)
4772       {
4773 	  if (db_prefix != NULL && table_name != NULL)
4774 	    {
4775 		xprefix = gaiaDoubleQuotedSql (db_prefix);
4776 		xxtable = gaiaDoubleQuotedSql (table_name);
4777 		sql =
4778 		    sqlite3_mprintf
4779 		    ("SELECT * FROM \"%s\".\"%s\" WHERE GeometryAliasType(\"%w\") = "
4780 		     "'LINESTRING' OR GeometryAliasType(\"%w\") = 'MULTILINESTRING' "
4781 		     "OR \"%s\" IS NULL", xprefix, xxtable, column, column,
4782 		     xcolumn);
4783 		free (xprefix);
4784 		free (xxtable);
4785 	    }
4786 	  else
4787 	      sql =
4788 		  sqlite3_mprintf
4789 		  ("SELECT * FROM \"%s\" WHERE GeometryAliasType(\"%w\") = "
4790 		   "'LINESTRING' OR GeometryAliasType(\"%w\") = 'MULTILINESTRING' "
4791 		   "OR \"%s\" IS NULL", xtable, column, column, xcolumn);
4792       }
4793     else if (shape == GAIA_POLYGON || shape == GAIA_POLYGONZ
4794 	     || shape == GAIA_POLYGONM || shape == GAIA_POLYGONZM ||
4795 	     shape == GAIA_MULTIPOLYGON || shape == GAIA_MULTIPOLYGONZ
4796 	     || shape == GAIA_MULTIPOLYGONM || shape == GAIA_MULTIPOLYGONZM)
4797       {
4798 	  if (db_prefix != NULL && table_name != NULL)
4799 	    {
4800 		xprefix = gaiaDoubleQuotedSql (db_prefix);
4801 		xxtable = gaiaDoubleQuotedSql (table_name);
4802 		sql =
4803 		    sqlite3_mprintf
4804 		    ("SELECT * FROM \"%s\".\"%s\" WHERE GeometryAliasType(\"%w\") = "
4805 		     "'POLYGON' OR GeometryAliasType(\"%w\") = 'MULTIPOLYGON'"
4806 		     "OR \"%s\" IS NULL", xprefix, xxtable, column, column,
4807 		     xcolumn);
4808 		free (xprefix);
4809 		free (xxtable);
4810 	    }
4811 	  else
4812 	      sql =
4813 		  sqlite3_mprintf
4814 		  ("SELECT * FROM \"%s\" WHERE GeometryAliasType(\"%w\") = "
4815 		   "'POLYGON' OR GeometryAliasType(\"%w\") = 'MULTIPOLYGON'"
4816 		   "OR \"%s\" IS NULL", xtable, column, column, xcolumn);
4817       }
4818     else if (shape == GAIA_MULTIPOINT || shape == GAIA_MULTIPOINTZ
4819 	     || shape == GAIA_MULTIPOINTM || shape == GAIA_MULTIPOINTZM)
4820       {
4821 	  if (db_prefix != NULL && table_name != NULL)
4822 	    {
4823 		xprefix = gaiaDoubleQuotedSql (db_prefix);
4824 		xxtable = gaiaDoubleQuotedSql (table_name);
4825 		sql =
4826 		    sqlite3_mprintf
4827 		    ("SELECT * FROM \"%s\".\"%s\" WHERE GeometryAliasType(\"%w\") = "
4828 		     "'POINT' OR GeometryAliasType(\"%w\") = 'MULTIPOINT'"
4829 		     "OR \"%s\" IS NULL", xprefix, xxtable, column, column,
4830 		     xcolumn);
4831 		free (xprefix);
4832 		free (xxtable);
4833 	    }
4834 	  else
4835 	      sql =
4836 		  sqlite3_mprintf
4837 		  ("SELECT * FROM \"%s\" WHERE GeometryAliasType(\"%w\") = "
4838 		   "'POINT' OR GeometryAliasType(\"%w\") = 'MULTIPOINT'"
4839 		   "OR \"%s\" IS NULL", xtable, column, column, xcolumn);
4840       }
4841     else
4842       {
4843 	  if (db_prefix != NULL && table_name != NULL)
4844 	    {
4845 		xprefix = gaiaDoubleQuotedSql (db_prefix);
4846 		xxtable = gaiaDoubleQuotedSql (table_name);
4847 		sql =
4848 		    sqlite3_mprintf
4849 		    ("SELECT * FROM \"%s\".\"%s\" WHERE GeometryAliasType(\"%w\") = "
4850 		     "'POINT' OR \"%s\" IS NULL", xprefix, xxtable, column,
4851 		     xcolumn);
4852 		free (xprefix);
4853 		free (xxtable);
4854 	    }
4855 	  else
4856 	      sql =
4857 		  sqlite3_mprintf
4858 		  ("SELECT * FROM \"%s\" WHERE GeometryAliasType(\"%w\") = "
4859 		   "'POINT' OR \"%s\" IS NULL", xtable, column, xcolumn);
4860       }
4861 /* compiling SQL prepared statement */
4862     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4863     sqlite3_free (sql);
4864     if (ret != SQLITE_OK)
4865 	goto sql_error;
4866 
4867     if (lyr->First == NULL)
4868       {
4869 	  /* the datasource is probably empty - zero rows */
4870 	  if (get_default_dbf_fields
4871 	      (sqlite, xtable, db_prefix, table_name, &dbf_list))
4872 	      goto continue_exporting;
4873       }
4874 
4875 /* preparing the DBF fields list */
4876     dbf_list = gaiaAllocDbfList ();
4877     offset = 0;
4878     fld = lyr->First;
4879     while (fld)
4880       {
4881 	  int sql_type = SQLITE_NULL;
4882 	  int max_len = 0;
4883 	  if (strcasecmp (fld->AttributeFieldName, column) == 0)
4884 	    {
4885 		/* ignoring the Geometry itself */
4886 		fld = fld->Next;
4887 		continue;
4888 	    }
4889 	  if (fld->IntegerValuesCount > 0 && fld->DoubleValuesCount == 0
4890 	      && fld->TextValuesCount == 0)
4891 	    {
4892 		sql_type = SQLITE_INTEGER;
4893 		max_len = 18;
4894 		if (fld->IntRange)
4895 		    max_len =
4896 			compute_max_int_length (fld->IntRange->MinValue,
4897 						fld->IntRange->MaxValue);
4898 	    }
4899 	  if (fld->DoubleValuesCount > 0 && fld->TextValuesCount == 0)
4900 	    {
4901 		sql_type = SQLITE_FLOAT;
4902 		max_len = 19;
4903 		if (fld->DoubleRange)
4904 		    max_len =
4905 			compute_max_dbl_length (fld->DoubleRange->MinValue,
4906 						fld->DoubleRange->MaxValue);
4907 	    }
4908 	  if (fld->TextValuesCount > 0)
4909 	    {
4910 		sql_type = SQLITE_TEXT;
4911 		max_len = 254;
4912 		if (fld->MaxSize)
4913 		    max_len = fld->MaxSize->MaxSize;
4914 	    }
4915 	  if (sql_type == SQLITE_NULL)
4916 	    {
4917 		/* considering as TEXT(1) */
4918 		sql_type = SQLITE_TEXT;
4919 		max_len = 1;
4920 	    }
4921 	  /* adding a DBF field */
4922 	  if (sql_type == SQLITE_TEXT)
4923 	    {
4924 		if (max_len == 0)	/* avoiding ZERO-length fields */
4925 		    max_len = 1;
4926 		if (max_len > 254)
4927 		  {
4928 		      /* DBF C: max allowed lenght */
4929 		      max_len = 254;
4930 		  }
4931 		gaiaAddDbfField (dbf_list, fld->AttributeFieldName, 'C', offset,
4932 				 (unsigned char) max_len, 0);
4933 		offset += max_len;
4934 	    }
4935 	  if (sql_type == SQLITE_FLOAT)
4936 	    {
4937 		if (max_len > 19)
4938 		    max_len = 19;
4939 		if (max_len < 8)
4940 		    max_len = 8;
4941 		gaiaAddDbfField (dbf_list, fld->AttributeFieldName, 'N', offset,
4942 				 (unsigned char) max_len, 6);
4943 		offset += max_len;
4944 	    }
4945 	  if (sql_type == SQLITE_INTEGER)
4946 	    {
4947 		if (max_len > 18)
4948 		    max_len = 18;
4949 		gaiaAddDbfField (dbf_list, fld->AttributeFieldName, 'N', offset,
4950 				 (unsigned char) max_len, 0);
4951 		offset += max_len;
4952 	    }
4953 	  fld = fld->Next;
4954       }
4955 
4956 /* exact computation of TEXT fields max length */
4957     compute_exact_text_max_length (sqlite, dbf_list, table, charset);
4958 
4959 /* resetting SQLite query */
4960   continue_exporting:
4961     ret = sqlite3_reset (stmt);
4962     if (ret != SQLITE_OK)
4963 	goto sql_error;
4964 /* trying to open shapefile files */
4965     shp = gaiaAllocShapefile ();
4966     gaiaOpenShpWriteEx (shp, shp_path, shape, dbf_list, "UTF-8", charset,
4967 			colname_case);
4968     if (!(shp->Valid))
4969 	goto no_file;
4970 /* trying to export the .PRJ file */
4971     output_prj_file (sqlite, shp_path, table, column, proj_ctx);
4972     while (1)
4973       {
4974 	  /* scrolling the result set to dump data into shapefile */
4975 	  ret = sqlite3_step (stmt);
4976 	  if (ret == SQLITE_DONE)
4977 	      break;		/* end of result set */
4978 	  if (ret == SQLITE_ROW)
4979 	    {
4980 		if (n_cols == 0)
4981 		    n_cols = sqlite3_column_count (stmt);
4982 		rows++;
4983 		dbf_write = gaiaCloneDbfEntity (dbf_list);
4984 		auxdbf = alloc_auxdbf (dbf_write);
4985 		for (i = 0; i < n_cols; i++)
4986 		  {
4987 		      if (strcasecmp
4988 			  ((char *) column,
4989 			   (char *) sqlite3_column_name (stmt, i)) == 0)
4990 			{
4991 			    /* this one is the internal BLOB encoded GEOMETRY to be exported */
4992 			    if (sqlite3_column_type (stmt, i) != SQLITE_BLOB)
4993 			      {
4994 				  /* this one is a NULL Geometry */
4995 				  dbf_write->Geometry = NULL;
4996 			      }
4997 			    else
4998 			      {
4999 				  blob_value = sqlite3_column_blob (stmt, i);
5000 				  len = sqlite3_column_bytes (stmt, i);
5001 				  dbf_write->Geometry =
5002 				      gaiaFromSpatiaLiteBlobWkb (blob_value,
5003 								 len);
5004 			      }
5005 			}
5006 		      dummy = (char *) sqlite3_column_name (stmt, i);
5007 		      dbf_field = getDbfField (auxdbf, dummy);
5008 		      if (!dbf_field)
5009 			  continue;
5010 		      if (sqlite3_column_type (stmt, i) == SQLITE_NULL)
5011 			{
5012 			    /* handling NULL values */
5013 			    gaiaSetNullValue (dbf_field);
5014 			}
5015 		      else
5016 			{
5017 			    switch (dbf_field->Type)
5018 			      {
5019 			      case 'N':
5020 				  if (sqlite3_column_type (stmt, i) ==
5021 				      SQLITE_INTEGER)
5022 				      gaiaSetIntValue (dbf_field,
5023 						       sqlite3_column_int64
5024 						       (stmt, i));
5025 				  else if (sqlite3_column_type (stmt, i) ==
5026 					   SQLITE_FLOAT)
5027 				      gaiaSetDoubleValue (dbf_field,
5028 							  sqlite3_column_double
5029 							  (stmt, i));
5030 				  else
5031 				      gaiaSetNullValue (dbf_field);
5032 				  break;
5033 			      case 'C':
5034 				  if (sqlite3_column_type (stmt, i) ==
5035 				      SQLITE_TEXT)
5036 				    {
5037 					dummy =
5038 					    (char *) sqlite3_column_text (stmt,
5039 									  i);
5040 					gaiaSetStrValue (dbf_field, dummy);
5041 				    }
5042 				  else if (sqlite3_column_type (stmt, i) ==
5043 					   SQLITE_INTEGER)
5044 				    {
5045 					sprintf (buf, FRMT64,
5046 						 sqlite3_column_int64 (stmt,
5047 								       i));
5048 					gaiaSetStrValue (dbf_field, buf);
5049 				    }
5050 				  else if (sqlite3_column_type (stmt, i) ==
5051 					   SQLITE_FLOAT)
5052 				    {
5053 					sql = sqlite3_mprintf ("%1.6f",
5054 							       sqlite3_column_double
5055 							       (stmt, i));
5056 					gaiaSetStrValue (dbf_field, sql);
5057 					sqlite3_free (sql);
5058 				    }
5059 				  else
5060 				      gaiaSetNullValue (dbf_field);
5061 				  break;
5062 			      };
5063 			}
5064 		  }
5065 		free_auxdbf (auxdbf);
5066 		auxdbf = NULL;
5067 		if (!gaiaWriteShpEntity (shp, dbf_write))
5068 		    spatialite_e ("shapefile write error\n");
5069 		gaiaFreeDbfList (dbf_write);
5070 	    }
5071 	  else
5072 	      goto sql_error;
5073       }
5074     if (auxdbf != NULL)
5075 	free_auxdbf (auxdbf);
5076     sqlite3_finalize (stmt);
5077     gaiaFlushShpHeaders (shp);
5078     gaiaFreeShapefile (shp);
5079     free (xtable);
5080     free (xcolumn);
5081     gaiaFreeVectorLayersList (list);
5082     if (verbose)
5083 	spatialite_e ("\nExported %d rows into SHAPEFILE\n========\n", rows);
5084     if (xrows)
5085 	*xrows = rows;
5086     if (err_msg)
5087 	sprintf (err_msg, "Exported %d rows into SHAPEFILE", rows);
5088     if (db_prefix != NULL)
5089 	free (db_prefix);
5090     if (table_name != NULL)
5091 	free (table_name);
5092     return 1;
5093   sql_error:
5094 /* some SQL error occurred */
5095     if (auxdbf != NULL)
5096 	free_auxdbf (auxdbf);
5097     sqlite3_finalize (stmt);
5098     free (xtable);
5099     free (xcolumn);
5100     gaiaFreeVectorLayersList (list);
5101     if (dbf_list)
5102 	gaiaFreeDbfList (dbf_list);
5103     if (shp)
5104 	gaiaFreeShapefile (shp);
5105     if (!err_msg)
5106 	spatialite_e ("SELECT failed: %s", sqlite3_errmsg (sqlite));
5107     else
5108 	sprintf (err_msg, "SELECT failed: %s", sqlite3_errmsg (sqlite));
5109     if (db_prefix != NULL)
5110 	free (db_prefix);
5111     if (table_name != NULL)
5112 	free (table_name);
5113     return 0;
5114   no_file:
5115 /* shapefile can't be created/opened */
5116     if (auxdbf != NULL)
5117 	free_auxdbf (auxdbf);
5118     free (xtable);
5119     free (xcolumn);
5120     gaiaFreeVectorLayersList (list);
5121     if (dbf_list)
5122 	gaiaFreeDbfList (dbf_list);
5123     if (shp)
5124 	gaiaFreeShapefile (shp);
5125     if (!err_msg)
5126 	spatialite_e ("ERROR: unable to open '%s' for writing", shp_path);
5127     else
5128 	sprintf (err_msg, "ERROR: unable to open '%s' for writing", shp_path);
5129     if (db_prefix != NULL)
5130 	free (db_prefix);
5131     if (table_name != NULL)
5132 	free (table_name);
5133     return 0;
5134 }
5135 
5136 SPATIALITE_DECLARE int
load_dbf(sqlite3 * sqlite,char * dbf_path,char * table,char * charset,int verbose,int * rows,char * err_msg)5137 load_dbf (sqlite3 * sqlite, char *dbf_path, char *table, char *charset,
5138 	  int verbose, int *rows, char *err_msg)
5139 {
5140     return load_dbf_ex (sqlite, dbf_path, table, NULL, charset, verbose, rows,
5141 			err_msg);
5142 }
5143 
5144 SPATIALITE_DECLARE int
load_dbf_ex(sqlite3 * sqlite,char * dbf_path,char * table,char * pk_column,char * charset,int verbose,int * rows,char * err_msg)5145 load_dbf_ex (sqlite3 * sqlite, char *dbf_path, char *table, char *pk_column,
5146 	     char *charset, int verbose, int *rows, char *err_msg)
5147 {
5148     return load_dbf_ex2 (sqlite, dbf_path, table, pk_column, charset, verbose,
5149 			 0, rows, err_msg);
5150 }
5151 
5152 SPATIALITE_DECLARE int
load_dbf_ex2(sqlite3 * sqlite,char * dbf_path,char * table,char * pk_column,char * charset,int verbose,int text_dates,int * rows,char * err_msg)5153 load_dbf_ex2 (sqlite3 * sqlite, char *dbf_path, char *table, char *pk_column,
5154 	      char *charset, int verbose, int text_dates, int *rows,
5155 	      char *err_msg)
5156 {
5157     return load_dbf_ex3 (sqlite, dbf_path, table, pk_column, charset, verbose,
5158 			 text_dates, rows, GAIA_DBF_COLNAME_LOWERCASE, err_msg);
5159 }
5160 
5161 SPATIALITE_DECLARE int
load_dbf_ex3(sqlite3 * sqlite,const char * dbf_path,const char * table,const char * pk_column,const char * charset,int verbose,int text_dates,int * rows,int colname_case,char * err_msg)5162 load_dbf_ex3 (sqlite3 * sqlite, const char *dbf_path, const char *table,
5163 	      const char *pk_column, const char *charset, int verbose,
5164 	      int text_dates, int *rows, int colname_case, char *err_msg)
5165 {
5166     return load_dbf_common (NULL, sqlite, dbf_path, table, pk_column, charset,
5167 			    verbose, text_dates, rows, colname_case, err_msg);
5168 }
5169 
5170 SPATIALITE_DECLARE int
dump_dbf(sqlite3 * sqlite,char * table,char * dbf_path,char * charset,char * err_msg)5171 dump_dbf (sqlite3 * sqlite, char *table, char *dbf_path, char *charset,
5172 	  char *err_msg)
5173 {
5174     int rows;
5175     return dump_dbf_ex (sqlite, table, dbf_path, charset, &rows, err_msg);
5176 }
5177 
5178 SPATIALITE_DECLARE int
dump_dbf_ex(sqlite3 * sqlite,char * table,char * dbf_path,char * charset,int * xrows,char * err_msg)5179 dump_dbf_ex (sqlite3 * sqlite, char *table, char *dbf_path, char *charset,
5180 	     int *xrows, char *err_msg)
5181 {
5182     return dump_dbf_ex2 (sqlite, table, dbf_path, charset, xrows,
5183 			 GAIA_DBF_COLNAME_CASE_IGNORE, err_msg);
5184 }
5185 
5186 SPATIALITE_DECLARE int
dump_dbf_ex2(sqlite3 * sqlite,char * table,char * dbf_path,char * charset,int * xrows,int colname_case,char * err_msg)5187 dump_dbf_ex2 (sqlite3 * sqlite, char *table, char *dbf_path, char *charset,
5188 	      int *xrows, int colname_case, char *err_msg)
5189 {
5190 /* DBF dump */
5191     int rows;
5192     int i;
5193     char *sql;
5194     char *xtable = NULL;
5195     sqlite3_stmt *stmt;
5196     int row1 = 0;
5197     int n_cols = 0;
5198     int offset = 0;
5199     int type;
5200     gaiaDbfPtr dbf = NULL;
5201     gaiaDbfListPtr dbf_export_list = NULL;
5202     gaiaDbfListPtr dbf_list = NULL;
5203     gaiaDbfListPtr dbf_write;
5204     gaiaDbfFieldPtr dbf_field;
5205     int *max_length = NULL;
5206     int *sql_type = NULL;
5207     char *dummy;
5208     char buf[256];
5209     int len;
5210     int ret;
5211     char *db_prefix = NULL;
5212     char *table_name = NULL;
5213     struct auxdbf_list *auxdbf = NULL;
5214 
5215     *xrows = -1;
5216     shp_parse_table_name (table, &db_prefix, &table_name);
5217 /*
5218 / preparing SQL statement
5219 */
5220     if (db_prefix != NULL && table_name != NULL)
5221       {
5222 	  char *xdb = gaiaDoubleQuotedSql (db_prefix);
5223 	  char *xxtable = gaiaDoubleQuotedSql (table_name);
5224 	  sql = sqlite3_mprintf ("SELECT * FROM \"%s\".\"%s\"", xdb, xxtable);
5225 	  free (xdb);
5226 	  free (xxtable);
5227       }
5228     else
5229       {
5230 	  xtable = gaiaDoubleQuotedSql (table);
5231 	  sql = sqlite3_mprintf ("SELECT * FROM \"%s\"", xtable);
5232       }
5233 /*
5234 / compiling SQL prepared statement
5235 */
5236     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
5237     sqlite3_free (sql);
5238     if (ret != SQLITE_OK)
5239 	goto sql_error;
5240     rows = 0;
5241     while (1)
5242       {
5243 	  /*
5244 	     / Pass I - scrolling the result set to compute real DBF attributes' sizes and types
5245 	   */
5246 	  ret = sqlite3_step (stmt);
5247 	  if (ret == SQLITE_DONE)
5248 	      break;		/* end of result set */
5249 	  if (ret == SQLITE_ROW)
5250 	    {
5251 		/* processing a result set row */
5252 		row1++;
5253 		if (n_cols == 0)
5254 		  {
5255 		      /* this one is the first row, so we are going to prepare the DBF Fields list */
5256 		      n_cols = sqlite3_column_count (stmt);
5257 		      dbf_export_list = gaiaAllocDbfList ();
5258 		      max_length = (int *) malloc (sizeof (int) * n_cols);
5259 		      sql_type = (int *) malloc (sizeof (int) * n_cols);
5260 		      for (i = 0; i < n_cols; i++)
5261 			{
5262 			    /* initializes the DBF export fields */
5263 			    dummy = (char *) sqlite3_column_name (stmt, i);
5264 			    gaiaAddDbfField (dbf_export_list, dummy, '\0', 0, 0,
5265 					     0);
5266 			    max_length[i] = 0;
5267 			    sql_type[i] = SQLITE_NULL;
5268 			}
5269 		  }
5270 		for (i = 0; i < n_cols; i++)
5271 		  {
5272 		      /* update the DBF export fields analyzing fetched data */
5273 		      type = sqlite3_column_type (stmt, i);
5274 		      if (type == SQLITE_NULL || type == SQLITE_BLOB)
5275 			  continue;
5276 		      if (type == SQLITE_TEXT)
5277 			{
5278 			    const char *string =
5279 				(const char *) sqlite3_column_text (stmt, i);
5280 			    len = compute_text_length (string, charset);
5281 			    if (len > 254)
5282 			      {
5283 				  /* DBF C type: max allowed length */
5284 				  len = 254;
5285 			      }
5286 			    sql_type[i] = SQLITE_TEXT;
5287 			    if (len > max_length[i])
5288 				max_length[i] = len;
5289 			}
5290 		      else if (type == SQLITE_FLOAT
5291 			       && sql_type[i] != SQLITE_TEXT)
5292 			  sql_type[i] = SQLITE_FLOAT;	/* promoting a numeric column to be DOUBLE */
5293 		      else if (type == SQLITE_INTEGER
5294 			       && (sql_type[i] == SQLITE_NULL
5295 				   || sql_type[i] == SQLITE_INTEGER))
5296 			  sql_type[i] = SQLITE_INTEGER;	/* promoting a null column to be INTEGER */
5297 		      if (type == SQLITE_INTEGER && max_length[i] < 18)
5298 			  max_length[i] = 18;
5299 		      if (type == SQLITE_FLOAT && max_length[i] < 24)
5300 			  max_length[i] = 24;
5301 		  }
5302 	    }
5303 	  else
5304 	      goto sql_error;
5305       }
5306     if (!row1)
5307 	goto empty_result_set;
5308     i = 0;
5309     offset = 0;
5310     dbf_list = gaiaAllocDbfList ();
5311     dbf_field = dbf_export_list->First;
5312     while (dbf_field)
5313       {
5314 	  /* preparing the final DBF attribute list */
5315 	  if (sql_type[i] == SQLITE_NULL || sql_type[i] == SQLITE_BLOB)
5316 	    {
5317 		i++;
5318 		dbf_field = dbf_field->Next;
5319 		continue;
5320 	    }
5321 	  if (sql_type[i] == SQLITE_TEXT)
5322 	    {
5323 		gaiaAddDbfField (dbf_list, dbf_field->Name, 'C', offset,
5324 				 (unsigned char) (max_length[i]), 0);
5325 		offset += max_length[i];
5326 	    }
5327 	  if (sql_type[i] == SQLITE_FLOAT)
5328 	    {
5329 		gaiaAddDbfField (dbf_list, dbf_field->Name, 'N', offset, 19, 6);
5330 		offset += 19;
5331 	    }
5332 	  if (sql_type[i] == SQLITE_INTEGER)
5333 	    {
5334 		gaiaAddDbfField (dbf_list, dbf_field->Name, 'N', offset, 18, 0);
5335 		offset += 18;
5336 	    }
5337 	  i++;
5338 	  dbf_field = dbf_field->Next;
5339       }
5340     free (max_length);
5341     free (sql_type);
5342     gaiaFreeDbfList (dbf_export_list);
5343     dbf_export_list = NULL;
5344 
5345   continue_exporting:
5346 /* resetting SQLite query */
5347     ret = sqlite3_reset (stmt);
5348     if (ret != SQLITE_OK)
5349 	goto sql_error;
5350 /* trying to open the DBF file */
5351     dbf = gaiaAllocDbf ();
5352 /* xfering export-list ownership */
5353     dbf->Dbf = dbf_list;
5354     dbf_list = NULL;
5355     gaiaOpenDbfWriteEx (dbf, dbf_path, "UTF-8", charset, colname_case);
5356     if (!(dbf->Valid))
5357 	goto no_file;
5358     while (1)
5359       {
5360 	  /* Pass II - scrolling the result set to dump data into DBF */
5361 	  ret = sqlite3_step (stmt);
5362 	  if (ret == SQLITE_DONE)
5363 	      break;		/* end of result set */
5364 	  if (ret == SQLITE_ROW)
5365 	    {
5366 		rows++;
5367 		dbf_write = gaiaCloneDbfEntity (dbf->Dbf);
5368 		auxdbf = alloc_auxdbf (dbf_write);
5369 		for (i = 0; i < n_cols; i++)
5370 		  {
5371 		      dummy = (char *) sqlite3_column_name (stmt, i);
5372 		      dbf_field = getDbfField (auxdbf, dummy);
5373 		      if (!dbf_field)
5374 			  continue;
5375 		      if (sqlite3_column_type (stmt, i) == SQLITE_NULL
5376 			  || sqlite3_column_type (stmt, i) == SQLITE_BLOB)
5377 			{
5378 			    /* handling NULL values */
5379 			    gaiaSetNullValue (dbf_field);
5380 			}
5381 		      else
5382 			{
5383 			    switch (dbf_field->Type)
5384 			      {
5385 			      case 'N':
5386 				  if (sqlite3_column_type (stmt, i) ==
5387 				      SQLITE_INTEGER)
5388 				      gaiaSetIntValue (dbf_field,
5389 						       sqlite3_column_int64
5390 						       (stmt, i));
5391 				  else if (sqlite3_column_type (stmt, i) ==
5392 					   SQLITE_FLOAT)
5393 				      gaiaSetDoubleValue (dbf_field,
5394 							  sqlite3_column_double
5395 							  (stmt, i));
5396 				  else
5397 				      gaiaSetNullValue (dbf_field);
5398 				  break;
5399 			      case 'C':
5400 				  if (sqlite3_column_type (stmt, i) ==
5401 				      SQLITE_TEXT)
5402 				    {
5403 					dummy =
5404 					    (char *) sqlite3_column_text (stmt,
5405 									  i);
5406 					gaiaSetStrValue (dbf_field, dummy);
5407 				    }
5408 				  else if (sqlite3_column_type (stmt, i) ==
5409 					   SQLITE_INTEGER)
5410 				    {
5411 					sprintf (buf, FRMT64,
5412 						 sqlite3_column_int64 (stmt,
5413 								       i));
5414 					gaiaSetStrValue (dbf_field, buf);
5415 				    }
5416 				  else if (sqlite3_column_type (stmt, i) ==
5417 					   SQLITE_FLOAT)
5418 				    {
5419 					sql = sqlite3_mprintf ("%1.6f",
5420 							       sqlite3_column_double
5421 							       (stmt, i));
5422 					gaiaSetStrValue (dbf_field, sql);
5423 					sqlite3_free (sql);
5424 				    }
5425 				  else
5426 				      gaiaSetNullValue (dbf_field);
5427 				  break;
5428 			      };
5429 			}
5430 		  }
5431 		free_auxdbf (auxdbf);
5432 		auxdbf = NULL;
5433 		if (!gaiaWriteDbfEntity (dbf, dbf_write))
5434 		    spatialite_e ("DBF write error\n");
5435 		gaiaFreeDbfList (dbf_write);
5436 	    }
5437 	  else
5438 	      goto sql_error;
5439       }
5440     if (auxdbf != NULL)
5441 	free_auxdbf (auxdbf);
5442     sqlite3_finalize (stmt);
5443     gaiaFlushDbfHeader (dbf);
5444     gaiaFreeDbf (dbf);
5445     free (xtable);
5446     if (!err_msg)
5447 	spatialite_e ("Exported %d rows into the DBF file\n", rows);
5448     else
5449 	sprintf (err_msg, "Exported %d rows into the DBF file\n", rows);
5450     if (db_prefix != NULL)
5451 	free (db_prefix);
5452     if (table_name != NULL)
5453 	free (table_name);
5454     *xrows = rows;
5455     return 1;
5456   sql_error:
5457 /* some SQL error occurred */
5458     if (auxdbf != NULL)
5459 	free_auxdbf (auxdbf);
5460     free (xtable);
5461     sqlite3_finalize (stmt);
5462     if (dbf_export_list)
5463 	gaiaFreeDbfList (dbf_export_list);
5464     if (dbf_list)
5465 	gaiaFreeDbfList (dbf_list);
5466     if (dbf)
5467 	gaiaFreeDbf (dbf);
5468     if (!err_msg)
5469 	spatialite_e ("dump DBF file error: %s\n", sqlite3_errmsg (sqlite));
5470     else
5471 	sprintf (err_msg, "dump DBF file error: %s\n", sqlite3_errmsg (sqlite));
5472     if (db_prefix != NULL)
5473 	free (db_prefix);
5474     if (table_name != NULL)
5475 	free (table_name);
5476     return 0;
5477   no_file:
5478 /* DBF can't be created/opened */
5479     if (auxdbf != NULL)
5480 	free_auxdbf (auxdbf);
5481     free (xtable);
5482     if (dbf_export_list)
5483 	gaiaFreeDbfList (dbf_export_list);
5484     if (dbf_list)
5485 	gaiaFreeDbfList (dbf_list);
5486     if (dbf)
5487 	gaiaFreeDbf (dbf);
5488     if (!err_msg)
5489 	spatialite_e ("ERROR: unable to open '%s' for writing\n", dbf_path);
5490     else
5491 	sprintf (err_msg, "ERROR: unable to open '%s' for writing\n", dbf_path);
5492     if (db_prefix != NULL)
5493 	free (db_prefix);
5494     if (table_name != NULL)
5495 	free (table_name);
5496     return 0;
5497   empty_result_set:
5498 /* the result set is empty - nothing to do */
5499     if (auxdbf != NULL)
5500 	free_auxdbf (auxdbf);
5501     if (get_default_dbf_fields
5502 	(sqlite, xtable, db_prefix, table_name, &dbf_list))
5503 	goto continue_exporting;
5504     free (xtable);
5505     sqlite3_finalize (stmt);
5506     if (dbf_export_list)
5507 	gaiaFreeDbfList (dbf_export_list);
5508     if (dbf_list)
5509 	gaiaFreeDbfList (dbf_list);
5510     if (dbf)
5511 	gaiaFreeDbf (dbf);
5512     if (!err_msg)
5513 	spatialite_e
5514 	    ("The SQL SELECT returned an empty result set ... there is nothing to export ...\n");
5515     else
5516 	sprintf (err_msg,
5517 		 "The SQL SELECT returned an empty result set ... there is nothing to export ...\n");
5518     if (db_prefix != NULL)
5519 	free (db_prefix);
5520     if (table_name != NULL)
5521 	free (table_name);
5522     return 0;
5523 }
5524 
5525 SPATIALITE_DECLARE int
is_kml_constant(sqlite3 * sqlite,char * table,char * column)5526 is_kml_constant (sqlite3 * sqlite, char *table, char *column)
5527 {
5528 /* checking a possible column name for KML dump */
5529     char *sql;
5530     char *xname;
5531     int ret;
5532     int k = 1;
5533     const char *name;
5534     char **results;
5535     int rows;
5536     int columns;
5537     int i;
5538     char *errMsg = NULL;
5539 
5540     xname = gaiaDoubleQuotedSql (table);
5541     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xname);
5542     free (xname);
5543     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
5544     sqlite3_free (sql);
5545     if (ret != SQLITE_OK)
5546 	return 1;
5547     if (rows < 1)
5548 	;
5549     else
5550       {
5551 	  for (i = 1; i <= rows; i++)
5552 	    {
5553 		name = results[(i * columns) + 1];
5554 		if (strcasecmp (name, column) == 0)
5555 		    k = 0;
5556 	    }
5557       }
5558     sqlite3_free_table (results);
5559     return k;
5560 }
5561 
5562 SPATIALITE_DECLARE int
dump_kml(sqlite3 * sqlite,char * table,char * geom_col,char * kml_path,char * name_col,char * desc_col,int precision)5563 dump_kml (sqlite3 * sqlite, char *table, char *geom_col, char *kml_path,
5564 	  char *name_col, char *desc_col, int precision)
5565 {
5566     int rows;
5567     return dump_kml_ex (sqlite, table, geom_col, kml_path, name_col, desc_col,
5568 			precision, &rows);
5569 }
5570 
5571 SPATIALITE_DECLARE int
dump_kml_ex(sqlite3 * sqlite,char * table,char * geom_col,char * kml_path,char * name_col,char * desc_col,int precision,int * xrows)5572 dump_kml_ex (sqlite3 * sqlite, char *table, char *geom_col, char *kml_path,
5573 	     char *name_col, char *desc_col, int precision, int *xrows)
5574 {
5575 /* dumping a  geometry table as KML */
5576     char *sql;
5577     char *xname;
5578     char *xdesc;
5579     char *xgeom_col;
5580     char *xtable;
5581     sqlite3_stmt *stmt = NULL;
5582     FILE *out = NULL;
5583     int ret;
5584     int rows = 0;
5585     int is_const = 1;
5586 
5587     *xrows = -1;
5588 /* opening/creating the KML file */
5589 #ifdef _WIN32
5590     out = gaia_win_fopen (kml_path, "wb");
5591 #else
5592     out = fopen (kml_path, "wb");
5593 #endif
5594     if (!out)
5595 	goto no_file;
5596 
5597 /* preparing SQL statement */
5598     if (name_col == NULL)
5599 	xname = sqlite3_mprintf ("%Q", "name");
5600     else
5601       {
5602 	  is_const = is_kml_constant (sqlite, table, name_col);
5603 	  if (is_const)
5604 	      xname = sqlite3_mprintf ("%Q", name_col);
5605 	  else
5606 	    {
5607 		xname = gaiaDoubleQuotedSql (name_col);
5608 		sql = sqlite3_mprintf ("\"%s\"", xname);
5609 		free (xname);
5610 		xname = sql;
5611 	    }
5612       }
5613     if (desc_col == NULL)
5614 	xdesc = sqlite3_mprintf ("%Q", "description");
5615     else
5616       {
5617 	  is_const = is_kml_constant (sqlite, table, desc_col);
5618 	  if (is_const)
5619 	      xdesc = sqlite3_mprintf ("%Q", desc_col);
5620 	  else
5621 	    {
5622 		xdesc = gaiaDoubleQuotedSql (desc_col);
5623 		sql = sqlite3_mprintf ("\"%s\"", xdesc);
5624 		free (xdesc);
5625 		xdesc = sql;
5626 	    }
5627       }
5628     xgeom_col = gaiaDoubleQuotedSql (geom_col);
5629     xtable = gaiaDoubleQuotedSql (table);
5630     sql = sqlite3_mprintf ("SELECT AsKML(%s, %s, %s, %d) FROM \"%s\" "
5631 			   "WHERE \"%s\" IS NOT NULL", xname, xdesc,
5632 			   xgeom_col, precision, xtable, xgeom_col);
5633     sqlite3_free (xname);
5634     sqlite3_free (xdesc);
5635     free (xgeom_col);
5636     free (xtable);
5637 /* compiling SQL prepared statement */
5638     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
5639     sqlite3_free (sql);
5640     if (ret != SQLITE_OK)
5641 	goto sql_error;
5642 
5643     while (1)
5644       {
5645 	  /* scrolling the result set */
5646 	  ret = sqlite3_step (stmt);
5647 	  if (ret == SQLITE_DONE)
5648 	      break;		/* end of result set */
5649 	  if (ret == SQLITE_ROW)
5650 	    {
5651 		/* processing a result set row */
5652 		if (rows == 0)
5653 		  {
5654 		      fprintf (out,
5655 			       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
5656 		      fprintf (out,
5657 			       "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\r\n");
5658 		      fprintf (out, "<Document>\r\n");
5659 		  }
5660 		rows++;
5661 		fprintf (out, "\t%s\r\n", sqlite3_column_text (stmt, 0));
5662 	    }
5663 	  else
5664 	      goto sql_error;
5665       }
5666     if (!rows)
5667 	goto empty_result_set;
5668 
5669 
5670     fprintf (out, "</Document>\r\n");
5671     fprintf (out, "</kml>\r\n");
5672     sqlite3_finalize (stmt);
5673     fclose (out);
5674     *xrows = rows;
5675     return 1;
5676 
5677   sql_error:
5678 /* some SQL error occurred */
5679     if (stmt)
5680 	sqlite3_finalize (stmt);
5681     if (out)
5682 	fclose (out);
5683     spatialite_e ("Dump KML error: %s\n", sqlite3_errmsg (sqlite));
5684     return 0;
5685   no_file:
5686 /* KML file can't be created/opened */
5687     if (stmt)
5688 	sqlite3_finalize (stmt);
5689     if (out)
5690 	fclose (out);
5691     spatialite_e ("ERROR: unable to open '%s' for writing\n", kml_path);
5692     return 0;
5693   empty_result_set:
5694 /* the result set is empty - nothing to do */
5695     if (stmt)
5696 	sqlite3_finalize (stmt);
5697     if (out)
5698 	fclose (out);
5699     spatialite_e
5700 	("The SQL SELECT returned an empty result set\n... there is nothing to export ...\n");
5701     return 0;
5702 }
5703 
5704 SPATIALITE_DECLARE int
dump_geojson(sqlite3 * sqlite,char * table,char * geom_col,char * outfile_path,int precision,int option)5705 dump_geojson (sqlite3 * sqlite, char *table, char *geom_col,
5706 	      char *outfile_path, int precision, int option)
5707 {
5708     int rows;
5709     return dump_geojson_ex (sqlite, table, geom_col, outfile_path, precision,
5710 			    option, &rows);
5711 }
5712 
5713 SPATIALITE_DECLARE int
dump_geojson_ex(sqlite3 * sqlite,char * table,char * geom_col,char * outfile_path,int precision,int option,int * xrows)5714 dump_geojson_ex (sqlite3 * sqlite, char *table, char *geom_col,
5715 		 char *outfile_path, int precision, int option, int *xrows)
5716 {
5717 /* dumping a  geometry table as GeoJSON - Brad Hards 2011-11-09 */
5718 /* sandro furieri 2014-08-30: adding the "int *xrows" argument */
5719     char *sql;
5720     char *xgeom_col;
5721     char *xtable;
5722     sqlite3_stmt *stmt = NULL;
5723     FILE *out = NULL;
5724     int ret;
5725     int rows = 0;
5726 
5727     *xrows = -1;
5728 /* opening/creating the GeoJSON output file */
5729 #ifdef _WIN32
5730     out = gaia_win_fopen (outfile_path, "wb");
5731 #else
5732     out = fopen (outfile_path, "wb");
5733 #endif
5734     if (!out)
5735 	goto no_file;
5736 
5737 /* preparing SQL statement */
5738     xtable = gaiaDoubleQuotedSql (table);
5739     xgeom_col = gaiaDoubleQuotedSql (geom_col);
5740     sql =
5741 	sqlite3_mprintf
5742 	("SELECT AsGeoJSON(\"%s\", %d, %d) FROM \"%s\" WHERE \"%s\" IS NOT NULL",
5743 	 xgeom_col, precision, option, xtable, xgeom_col);
5744     free (xtable);
5745     free (xgeom_col);
5746     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
5747     sqlite3_free (sql);
5748     if (ret != SQLITE_OK)
5749 	goto sql_error;
5750 
5751     while (1)
5752       {
5753 	  /* scrolling the result set */
5754 	  ret = sqlite3_step (stmt);
5755 	  if (ret == SQLITE_DONE)
5756 	    {
5757 		break;		/* end of result set */
5758 	    }
5759 	  if (ret == SQLITE_ROW)
5760 	    {
5761 		rows++;
5762 		fprintf (out, "%s\r\n", sqlite3_column_text (stmt, 0));
5763 	    }
5764 	  else
5765 	    {
5766 		goto sql_error;
5767 	    }
5768       }
5769     if (rows == 0)
5770       {
5771 	  goto empty_result_set;
5772       }
5773 
5774     sqlite3_finalize (stmt);
5775     fclose (out);
5776     *xrows = rows;
5777     return 1;
5778 
5779   sql_error:
5780 /* an SQL error occurred */
5781     if (stmt)
5782       {
5783 	  sqlite3_finalize (stmt);
5784       }
5785     if (out)
5786       {
5787 	  fclose (out);
5788       }
5789     spatialite_e ("Dump GeoJSON error: %s\n", sqlite3_errmsg (sqlite));
5790     return 0;
5791 
5792   no_file:
5793 /* Output file could not be created / opened */
5794     if (stmt)
5795       {
5796 	  sqlite3_finalize (stmt);
5797       }
5798     if (out)
5799       {
5800 	  fclose (out);
5801       }
5802     spatialite_e ("ERROR: unable to open '%s' for writing\n", outfile_path);
5803     return 0;
5804 
5805   empty_result_set:
5806 /* the result set is empty - nothing to do */
5807     if (stmt)
5808       {
5809 	  sqlite3_finalize (stmt);
5810       }
5811     if (out)
5812       {
5813 	  fclose (out);
5814       }
5815     spatialite_e ("The SQL SELECT returned no data to export...\n");
5816     return 0;
5817 }
5818 
5819 static int
do_check_geometry(sqlite3 * sqlite,const char * table,const char * geom_col,char ** geoname,int * srid,int * dims)5820 do_check_geometry (sqlite3 * sqlite, const char *table, const char *geom_col,
5821 		   char **geoname, int *srid, int *dims)
5822 {
5823 /* checking Geometry Column, SRID and Dimensions */
5824     char *sql;
5825     int ret;
5826     char **results;
5827     int rows;
5828     int columns;
5829     int i;
5830     char *errMsg = NULL;
5831 
5832     if (geom_col == NULL)
5833 	sql = sqlite3_mprintf ("SELECT f_geometry_column, srid, geometry_type "
5834 			       "FROM geometry_columns WHERE Lower(f_table_name) = Lower(%Q)",
5835 			       table);
5836     else
5837 	sql = sqlite3_mprintf ("SELECT f_geometry_column, srid, geometry_type "
5838 			       "FROM geometry_columns WHERE Lower(f_table_name) = Lower(%Q) AND "
5839 			       "Lower(f_geometry_column) = Lower(%Q)",
5840 			       table, geom_col);
5841     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
5842     sqlite3_free (sql);
5843     if (ret != SQLITE_OK)
5844       {
5845 	  spatialite_e ("dump GeoJSON2 MetaData error: <%s>\n", errMsg);
5846 	  sqlite3_free (errMsg);
5847 	  return 0;
5848       }
5849     if (rows == 1)
5850 	goto ok;
5851 
5852 /* it could be a possible Spatial View */
5853     if (geom_col == NULL)
5854 	sql =
5855 	    sqlite3_mprintf
5856 	    ("SELECT g.f_geometry_column, g.srid, g.geometry_type "
5857 	     "FROM views_geometry_columns AS v "
5858 	     "JOIN geometry_columns AS g ON (v.f_table_name = g.f_table_name) "
5859 	     "WHERE Lower(v.view_name) = Lower(%Q)", table);
5860     else
5861 	sql =
5862 	    sqlite3_mprintf
5863 	    ("SELECT g.f_geometry_column, g.srid, g.geometry_type "
5864 	     "FROM views_geometry_columns AS v "
5865 	     "JOIN geometry_columns AS g ON (v.f_table_name = g.f_table_name) "
5866 	     "WHERE Lower(v.view_name) = Lower(%Q) AND "
5867 	     "Lower(v.view_geometry) = Lower(%Q)", table, geom_col);
5868     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
5869     sqlite3_free (sql);
5870     if (ret != SQLITE_OK)
5871       {
5872 	  spatialite_e ("dump GeoJSON2 MetaData error: <%s>\n", errMsg);
5873 	  sqlite3_free (errMsg);
5874 	  return 0;
5875       }
5876     if (rows == 1)
5877 	goto ok;
5878 
5879 /* it could be a possible Spatial Virtual Table */
5880     if (geom_col == NULL)
5881 	sql = sqlite3_mprintf ("SELECT virt_geometry, srid, geometry_type "
5882 			       "FROM virts_geometry_columns "
5883 			       "WHERE Lower(virt_name) = Lower(%Q)", table);
5884     else
5885 	sql = sqlite3_mprintf ("SELECT virt_geometry, srid, geometry_type "
5886 			       "FROM virts_geometry_columns "
5887 			       "WHERE Lower(virt_name) = Lower(%Q) AND "
5888 			       "Lower(virt_geometry) = Lower(%Q)",
5889 			       table, geom_col);
5890     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
5891     sqlite3_free (sql);
5892     if (ret != SQLITE_OK)
5893       {
5894 	  spatialite_e ("dump GeoJSON2 MetaData error: <%s>\n", errMsg);
5895 	  sqlite3_free (errMsg);
5896 	  return 0;
5897       }
5898     if (rows != 1)
5899 	goto error;
5900 
5901   ok:
5902     for (i = 1; i <= rows; i++)
5903       {
5904 	  int gtype;
5905 	  const char *x = results[(i * columns) + 0];
5906 	  int len = strlen (x);
5907 	  *geoname = malloc (len + 1);
5908 	  strcpy (*geoname, x);
5909 	  *srid = atoi (results[(i * columns) + 1]);
5910 	  gtype = atoi (results[(i * columns) + 2]);
5911 	  switch (gtype)
5912 	    {
5913 	    case GAIA_POINT:
5914 	    case GAIA_LINESTRING:
5915 	    case GAIA_POLYGON:
5916 	    case GAIA_MULTIPOINT:
5917 	    case GAIA_MULTILINESTRING:
5918 	    case GAIA_MULTIPOLYGON:
5919 	    case GAIA_GEOMETRYCOLLECTION:
5920 		*dims = GAIA_XY;
5921 		break;
5922 	    case GAIA_POINTZ:
5923 	    case GAIA_LINESTRINGZ:
5924 	    case GAIA_POLYGONZ:
5925 	    case GAIA_MULTIPOINTZ:
5926 	    case GAIA_MULTILINESTRINGZ:
5927 	    case GAIA_MULTIPOLYGONZ:
5928 	    case GAIA_GEOMETRYCOLLECTIONZ:
5929 		*dims = GAIA_XY_Z;
5930 		break;
5931 	    case GAIA_POINTM:
5932 	    case GAIA_LINESTRINGM:
5933 	    case GAIA_POLYGONM:
5934 	    case GAIA_MULTIPOINTM:
5935 	    case GAIA_MULTILINESTRINGM:
5936 	    case GAIA_MULTIPOLYGONM:
5937 	    case GAIA_GEOMETRYCOLLECTIONM:
5938 		*dims = GAIA_XY_M;
5939 		break;
5940 	    case GAIA_POINTZM:
5941 	    case GAIA_LINESTRINGZM:
5942 	    case GAIA_POLYGONZM:
5943 	    case GAIA_MULTIPOINTZM:
5944 	    case GAIA_MULTILINESTRINGZM:
5945 	    case GAIA_MULTIPOLYGONZM:
5946 	    case GAIA_GEOMETRYCOLLECTIONZM:
5947 		*dims = GAIA_XY_Z_M;
5948 		break;
5949 	    default:
5950 		goto error;
5951 	    };
5952       }
5953     sqlite3_free_table (results);
5954     return 1;
5955 
5956   error:
5957     sqlite3_free_table (results);
5958     return 0;
5959 }
5960 
5961 static char *
do_prepare_sql(sqlite3 * sqlite,const char * table,const char * geom_col,int srid,int dims,int precision,int lon_lat,int m_coords)5962 do_prepare_sql (sqlite3 * sqlite, const char *table, const char *geom_col,
5963 		int srid, int dims, int precision, int lon_lat, int m_coords)
5964 {
5965 /* preparing the SQL statement */
5966     char *sql;
5967     char *prev;
5968     char *xtable;
5969     char *x_col;
5970     int ret;
5971     char **results;
5972     int rows;
5973     int columns;
5974     int i;
5975     char *errMsg = NULL;
5976 
5977     xtable = gaiaDoubleQuotedSql (table);
5978     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
5979     free (xtable);
5980     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
5981     sqlite3_free (sql);
5982     if (ret != SQLITE_OK)
5983       {
5984 	  spatialite_e ("dump GeoJSON2 PRAGMA error: <%s>\n", errMsg);
5985 	  sqlite3_free (errMsg);
5986 	  return 0;
5987       }
5988 
5989 /* defining the Geometry first */
5990     x_col = gaiaDoubleQuotedSql (geom_col);
5991     if (lon_lat)
5992       {
5993 	  /* exporting Geographic coordinates (lon-lat) */
5994 	  if (srid == 0 || srid == 4326)
5995 	    {
5996 		/* already lon-lan, no transformation is required */
5997 		if (m_coords)
5998 		  {
5999 		      /* exporting eventual M-Values */
6000 		      sql =
6001 			  sqlite3_mprintf
6002 			  ("SELECT AsGeoJSON(ST_ForcePolygonCCW(\"%s\"), %d)",
6003 			   x_col, precision);
6004 		  }
6005 		else
6006 		  {
6007 		      if (dims == GAIA_XY_M)
6008 			{
6009 			    /* exporting XYM as XY */
6010 			    sql =
6011 				sqlite3_mprintf
6012 				("SELECT AsGeoJSON(CastToXY(ST_ForcePolygonCCW(\"%s\")), %d)",
6013 				 x_col, precision);
6014 			}
6015 		      else if (dims == GAIA_XY_Z_M)
6016 			{
6017 			    /* exporting XYZM as XYZ */
6018 			    sql =
6019 				sqlite3_mprintf
6020 				("SELECT AsGeoJSON(CastToXYZ(ST_ForcePolygonCCW(\"%s\")), %d)",
6021 				 x_col, precision);
6022 			}
6023 		      else
6024 			{
6025 			    /* unchanged dimensions */
6026 			    sql =
6027 				sqlite3_mprintf
6028 				("SELECT AsGeoJSON(ST_ForcePolygonCCW(\"%s\"), %d)",
6029 				 x_col, precision);
6030 			}
6031 		  }
6032 	    }
6033 	  else
6034 	    {
6035 		/* converting to lon-lat WGS84 */
6036 		if (m_coords)
6037 		  {
6038 		      /* exporting eventual M-Values */
6039 		      sql =
6040 			  sqlite3_mprintf
6041 			  ("SELECT AsGeoJSON(ST_Transform(ST_ForcePolygonCCW(\"%s\"), 4326), %d)",
6042 			   x_col, precision);
6043 		  }
6044 		else
6045 		  {
6046 		      if (dims == GAIA_XY_M)
6047 			{
6048 			    /* exporting XYM as XY */
6049 			    sql =
6050 				sqlite3_mprintf
6051 				("SELECT AsGeoJSON(ST_Transform(CastToXY(ST_ForcePolygonCCW(\"%s\")), 4326), %d)",
6052 				 x_col, precision);
6053 			}
6054 		      else if (dims == GAIA_XY_Z_M)
6055 			{
6056 			    /* exporting XYZM as XYZ */
6057 			    sql =
6058 				sqlite3_mprintf
6059 				("SELECT AsGeoJSON(ST_TransformCastToXYZ(ST_ForcePolygonCCW(\"%s\")), 4326), %d)",
6060 				 x_col, precision);
6061 			}
6062 		      else
6063 			{
6064 			    /* unchanged dimensions */
6065 			    sql =
6066 				sqlite3_mprintf
6067 				("SELECT AsGeoJSON(ST_Transform(ST_ForcePolygonCCW(\"%s\"), 4326), %d)",
6068 				 x_col, precision);
6069 			}
6070 		  }
6071 	    }
6072       }
6073     else
6074       {
6075 	  /* exporting coordinates as they are without any transformation */
6076 	  if (m_coords)
6077 	    {
6078 		/* exporting eventual M-Values */
6079 		sql =
6080 		    sqlite3_mprintf
6081 		    ("SELECT AsGeoJSON(ST_ForcePolygonCCW(\"%s\"), %d)", x_col,
6082 		     precision);
6083 	    }
6084 	  else
6085 	    {
6086 		if (dims == GAIA_XY_M)
6087 		  {
6088 		      /* exporting XYM as XY */
6089 		      sql =
6090 			  sqlite3_mprintf
6091 			  ("SELECT AsGeoJSON(CastToXY(ST_ForcePolygonCCW(\"%s\")), %d)",
6092 			   x_col, precision);
6093 		  }
6094 		else if (dims == GAIA_XY_Z_M)
6095 		  {
6096 		      /* exporting XYZM as XYZ */
6097 		      sql =
6098 			  sqlite3_mprintf
6099 			  ("SELECT AsGeoJSON(CastToXYZ(ST_ForcePolygonCCW(\"%s\")), %d)",
6100 			   x_col, precision);
6101 		  }
6102 		else
6103 		  {
6104 		      /* unchanged dimensions */
6105 		      sql =
6106 			  sqlite3_mprintf
6107 			  ("SELECT AsGeoJSON(ST_ForcePolygonCCW(\"%s\"), %d)",
6108 			   x_col, precision);
6109 		  }
6110 	    }
6111       }
6112     free (x_col);
6113 
6114     for (i = 1; i <= rows; i++)
6115       {
6116 	  /* then adding all Properties */
6117 	  const char *col = results[(i * columns) + 1];
6118 	  if (strcasecmp (col, geom_col) == 0)
6119 	      continue;		/* skipping the Geometry itself */
6120 	  x_col = gaiaDoubleQuotedSql (col);
6121 	  prev = sql;
6122 	  sql = sqlite3_mprintf ("%s, \"%s\"", prev, x_col);
6123 	  free (x_col);
6124 	  sqlite3_free (prev);
6125       }
6126     sqlite3_free_table (results);
6127     prev = sql;
6128     xtable = gaiaDoubleQuotedSql (table);
6129     sql = sqlite3_mprintf ("%s FROM \"%s\"", prev, xtable);
6130     free (xtable);
6131     sqlite3_free (prev);
6132     return sql;
6133 }
6134 
6135 static char *
do_normalize_case(const char * name,int colname_case)6136 do_normalize_case (const char *name, int colname_case)
6137 {
6138 /* transforming a name in full lower- or upper-case */
6139     int len = strlen (name);
6140     char *clean = malloc (len + 1);
6141     char *p = clean;
6142     strcpy (clean, name);
6143     while (*p != '\0')
6144       {
6145 	  if (colname_case == GAIA_DBF_COLNAME_LOWERCASE)
6146 	    {
6147 		if (*p >= 'A' && *p <= 'Z')
6148 		    *p = *p - 'A' + 'a';
6149 	    }
6150 	  if (colname_case == GAIA_DBF_COLNAME_UPPERCASE)
6151 	    {
6152 		if (*p >= 'a' && *p <= 'z')
6153 		    *p = *p - 'a' + 'A';
6154 	    }
6155 	  p++;
6156       }
6157     return clean;
6158 }
6159 
6160 SPATIALITE_DECLARE int
dump_geojson2(sqlite3 * sqlite,char * table,char * geom_col,char * outfile_path,int precision,int lon_lat,int m_coords,int indented,int colname_case,int * xrows,char ** error_message)6161 dump_geojson2 (sqlite3 * sqlite, char *table, char *geom_col,
6162 	       char *outfile_path, int precision, int lon_lat,
6163 	       int m_coords, int indented, int colname_case, int *xrows,
6164 	       char **error_message)
6165 {
6166 /* dumping a  geometry table as GeoJSON FeatureCollection (RFC 7946) */
6167 /* sandro furieri 2018-11-25 */
6168     char *sql;
6169     sqlite3_stmt *stmt = NULL;
6170     FILE *out = NULL;
6171     int ret;
6172     int rows = 0;
6173     char *geoname = NULL;
6174     int srid;
6175     int dims;
6176     int first_feature = 1;
6177     sqlite3_int64 ival;
6178     double dval;
6179     const char *tval;
6180     char *xtval;
6181     *error_message = NULL;
6182 
6183 /* checking Geometry Column, SRID and Dimensions */
6184     if (!do_check_geometry (sqlite, table, geom_col, &geoname, &srid, &dims))
6185 	goto no_geom;
6186 
6187     *xrows = -1;
6188 /* opening/creating the GeoJSON output file */
6189 #ifdef _WIN32
6190     out = gaia_win_fopen (outfile_path, "wb");
6191 #else
6192     out = fopen (outfile_path, "wb");
6193 #endif
6194     if (!out)
6195 	goto no_file;
6196 
6197 /* preparing SQL statement */
6198     sql =
6199 	do_prepare_sql (sqlite, table, geoname, srid, dims, precision, lon_lat,
6200 			m_coords);
6201     if (sql == NULL)
6202 	goto no_sql;
6203     free (geoname);
6204 
6205     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
6206     sqlite3_free (sql);
6207     if (ret != SQLITE_OK)
6208 	goto sql_error;
6209 
6210     while (1)
6211       {
6212 	  /* scrolling the result set */
6213 	  ret = sqlite3_step (stmt);
6214 	  if (ret == SQLITE_DONE)
6215 	    {
6216 		break;		/* end of result set */
6217 	    }
6218 	  if (ret == SQLITE_ROW)
6219 	    {
6220 		int c;
6221 		int cols = sqlite3_column_count (stmt);
6222 		if (first_feature)
6223 		  {
6224 		      /* FeatureCollection */
6225 		      if (indented)
6226 			  fprintf (out,
6227 				   "{\r\n\t\"type\" : \"FeatureCollection\",\r\n\t\"features\" : [{\r\n");
6228 		      else
6229 			  fprintf (out,
6230 				   "{\"type\":\"FeatureCollection\",\"features\":[{");
6231 		      first_feature = 0;
6232 		  }
6233 		/* Feature */
6234 		if (rows == 0)
6235 		  {
6236 		      /* first Feature */
6237 		      if (indented)
6238 			  fprintf (out,
6239 				   "\t\t\"type\" : \"Feature\",\r\n\t\t\"properties\" : ");
6240 		      else
6241 			  fprintf (out, "\"type\":\"Feature\",\"properties\":");
6242 		  }
6243 		else
6244 		  {
6245 		      /* any other Feature except the first one */
6246 		      if (indented)
6247 			  fprintf (out,
6248 				   ", {\r\n\t\t\"type\" : \"Feature\",\r\n\t\t\"properties\" : ");
6249 		      else
6250 			  fprintf (out,
6251 				   ",{\"type\":\"Feature\",\"properties\":");
6252 		  }
6253 		for (c = 1; c < cols; c++)
6254 		  {
6255 		      /* Properties */
6256 		      const char *col_name = sqlite3_column_name (stmt, c);
6257 		      char *norm_name =
6258 			  do_normalize_case (col_name, colname_case);
6259 		      char *xcol_name = gaiaDoubleQuotedSql (norm_name);
6260 		      free (norm_name);
6261 		      if (c == 1)
6262 			{
6263 			    if (indented)
6264 				fprintf (out, "{\r\n\t\t\t\"%s\" : ",
6265 					 xcol_name);
6266 			    else
6267 				fprintf (out, "{\"%s\":", xcol_name);
6268 			}
6269 		      else
6270 			{
6271 			    if (indented)
6272 				fprintf (out, ",\r\n\t\t\t\"%s\" : ",
6273 					 xcol_name);
6274 			    else
6275 				fprintf (out, ",\"%s\":", xcol_name);
6276 			}
6277 		      free (xcol_name);
6278 		      switch (sqlite3_column_type (stmt, c))
6279 			{
6280 			case SQLITE_INTEGER:
6281 			    ival = sqlite3_column_int64 (stmt, c);
6282 			    fprintf (out, "%lld", ival);
6283 			    break;
6284 			case SQLITE_FLOAT:
6285 			    dval = sqlite3_column_double (stmt, c);
6286 			    fprintf (out, "%f", dval);
6287 			    break;
6288 			case SQLITE_TEXT:
6289 			    tval = (const char *) sqlite3_column_text (stmt, c);
6290 			    xtval = gaiaDoubleQuotedSql (tval);
6291 			    fprintf (out, "\"%s\"", xtval);
6292 			    free (xtval);
6293 			    break;
6294 			case SQLITE_BLOB:
6295 			    fprintf (out, "\"BLOB value\"");
6296 			    break;
6297 			case SQLITE_NULL:
6298 			default:
6299 			    fprintf (out, "null");
6300 			    break;
6301 			};
6302 		  }
6303 		/* geometry */
6304 		if (indented)
6305 		    fprintf (out, "\r\n\t\t},\r\n\t\t\"geometry\" : ");
6306 		else
6307 		    fprintf (out, "},\"geomety\":");
6308 		switch (sqlite3_column_type (stmt, 0))
6309 		  {
6310 		  case SQLITE_NULL:
6311 		      fprintf (out, "null");
6312 		      break;
6313 		  default:
6314 		      tval = (const char *) sqlite3_column_text (stmt, 0);
6315 		      fprintf (out, "%s", tval);
6316 		      break;
6317 		  };
6318 		/* end Feature */
6319 		if (indented)
6320 		    fprintf (out, "\r\n\t}");
6321 		else
6322 		    fprintf (out, "}");
6323 		rows++;
6324 	    }
6325 	  else
6326 	    {
6327 		goto sql_error;
6328 	    }
6329       }
6330     if (rows == 0)
6331       {
6332 	  goto empty_result_set;
6333       }
6334     if (indented)
6335 	fprintf (out, "]\r\n}\r\n");
6336     else
6337 	fprintf (out, "]}");
6338 
6339     sqlite3_finalize (stmt);
6340     fclose (out);
6341     *xrows = rows;
6342     return 1;
6343 
6344   sql_error:
6345 /* an SQL error occurred */
6346     if (stmt)
6347       {
6348 	  sqlite3_finalize (stmt);
6349       }
6350     if (out)
6351       {
6352 	  fclose (out);
6353       }
6354     *error_message =
6355 	sqlite3_mprintf ("Dump GeoJSON2 error: %s\n", sqlite3_errmsg (sqlite));
6356     return 0;
6357 
6358   no_file:
6359 /* Output file could not be created / opened */
6360     if (stmt)
6361       {
6362 	  sqlite3_finalize (stmt);
6363       }
6364     if (out)
6365       {
6366 	  fclose (out);
6367       }
6368     if (geoname != NULL)
6369 	free (geoname);
6370     *error_message =
6371 	sqlite3_mprintf ("ERROR: unable to open '%s' for writing\n",
6372 			 outfile_path);
6373     return 0;
6374 
6375   empty_result_set:
6376 /* the result set is empty - nothing to do */
6377     if (stmt)
6378       {
6379 	  sqlite3_finalize (stmt);
6380       }
6381     if (out)
6382       {
6383 	  fclose (out);
6384       }
6385     *error_message =
6386 	sqlite3_mprintf ("The SQL SELECT returned no data to export...\n");
6387     return 0;
6388 
6389   no_geom:
6390 /* not a valid Geometry Column */
6391     if (out)
6392       {
6393 	  fclose (out);
6394       }
6395     *error_message = sqlite3_mprintf ("Not a valid Geometry Column.\n");
6396     return 0;
6397 
6398   no_sql:
6399 /* unable to create a valid SQL query */
6400     if (out)
6401       {
6402 	  fclose (out);
6403       }
6404     *error_message = sqlite3_mprintf ("Unable to create a valid SQL query.\n");
6405     return 0;
6406 }
6407 
6408 SPATIALITE_DECLARE int
load_geojson(sqlite3 * sqlite,char * path,char * table,char * geom_col,int spatial_index,int srid,int colname_case,int * rows,char ** error_message)6409 load_geojson (sqlite3 * sqlite, char *path, char *table, char *geom_col,
6410 	      int spatial_index, int srid, int colname_case, int *rows,
6411 	      char **error_message)
6412 {
6413 /* Loads an external GeoJSON file into a newly created table */
6414     FILE *in = NULL;
6415     sqlite3_stmt *stmt = NULL;
6416     geojson_parser_ptr parser = NULL;
6417     geojson_feature_ptr ft;
6418     int i;
6419     int ret;
6420     int pending = 0;
6421     char *sql;
6422     int ins_rows = 0;
6423     *error_message = NULL;
6424 
6425 /* attempting to open the GeoJSON file for reading */
6426 #ifdef _WIN32
6427     in = gaia_win_fopen (path, "rb");
6428 #else
6429     in = fopen (path, "rb");
6430 #endif
6431     if (in == NULL)
6432       {
6433 	  *error_message =
6434 	      sqlite3_mprintf
6435 	      ("GeoJSON parser: unable to open %s for reading\n", path);
6436 	  return 0;
6437       }
6438 
6439 /* creating the GeoJSON parser */
6440     parser = geojson_create_parser (in);
6441     if (!geojson_parser_init (parser, error_message))
6442 	goto err;
6443     if (!geojson_create_features_index (parser, error_message))
6444 	goto err;
6445     if (!geojson_check_features (parser, error_message))
6446 	goto err;
6447 
6448 /* creating the output table */
6449     sql = geojson_sql_create_table (parser, table, colname_case);
6450     if (sql == NULL)
6451 	goto err;
6452     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
6453     sqlite3_free (sql);
6454     if (ret != SQLITE_OK)
6455       {
6456 	  *error_message =
6457 	      sqlite3_mprintf
6458 	      ("GeoJSON import: unable to create the output table (%s)\n",
6459 	       sqlite3_errmsg (sqlite));
6460 	  goto err;
6461       }
6462 
6463 /* adding the Geometry Column */
6464     sql =
6465 	geojson_sql_add_geometry (parser, table, geom_col, colname_case, srid);
6466     if (sql == NULL)
6467 	goto err;
6468     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
6469     sqlite3_free (sql);
6470     if (ret != SQLITE_OK)
6471       {
6472 	  *error_message =
6473 	      sqlite3_mprintf
6474 	      ("GeoJSON import: unable to create the Geometry column (%s)\n",
6475 	       sqlite3_errmsg (sqlite));
6476 	  goto err;
6477       }
6478 
6479     if (spatial_index)
6480       {
6481 	  /* creating the Spatial Index */
6482 	  sql = geojson_sql_create_rtree (table, geom_col, colname_case);
6483 	  if (sql == NULL)
6484 	      goto err;
6485 	  ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
6486 	  sqlite3_free (sql);
6487 	  if (ret != SQLITE_OK)
6488 	    {
6489 		*error_message =
6490 		    sqlite3_mprintf
6491 		    ("GeoJSON import: unable to create the SpatialIndex (%s)\n",
6492 		     sqlite3_errmsg (sqlite));
6493 		goto err;
6494 	    }
6495       }
6496 
6497 /* the whole import will be enclosed in a single Transaction */
6498     ret = sqlite3_exec (sqlite, "SAVEPOINT import_geo_json", NULL, NULL, NULL);
6499     if (ret != SQLITE_OK)
6500       {
6501 	  *error_message =
6502 	      sqlite3_mprintf ("GeoJSON import: SAVEPOINT error (%s)\n",
6503 			       sqlite3_errmsg (sqlite));
6504 	  goto err;
6505       }
6506     pending = 1;
6507 
6508     sql = geojson_sql_insert_into (parser, table);
6509     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
6510     sqlite3_free (sql);
6511     if (ret != SQLITE_OK)
6512       {
6513 	  *error_message =
6514 	      sqlite3_mprintf ("GeoJSON import: INSERT INTO error (%s)\n",
6515 			       sqlite3_errmsg (sqlite));
6516 	  goto err;
6517       }
6518 
6519     for (i = 0; i < parser->count; i++)
6520       {
6521 	  /* inserting all features into the output table */
6522 	  ft = parser->features + i;
6523 	  if (geojson_init_feature (parser, ft, error_message))
6524 	    {
6525 		/* inserting a single Feature */
6526 		geojson_column_ptr col;
6527 		int cnt = 1;
6528 		sqlite3_reset (stmt);
6529 		sqlite3_clear_bindings (stmt);
6530 		col = parser->first_col;
6531 		while (col != NULL)
6532 		  {
6533 		      /* binding column values */
6534 		      geojson_property_ptr prop =
6535 			  geojson_get_property_by_name (ft, col->name);
6536 		      if (prop == NULL)
6537 			  sqlite3_bind_null (stmt, cnt++);
6538 		      else
6539 			{
6540 			    switch (prop->type)
6541 			      {
6542 			      case GEOJSON_TEXT:
6543 				  sqlite3_bind_text (stmt, cnt++,
6544 						     prop->txt_value,
6545 						     strlen (prop->txt_value),
6546 						     SQLITE_STATIC);
6547 				  break;
6548 			      case GEOJSON_INTEGER:
6549 				  sqlite3_bind_int64 (stmt, cnt++,
6550 						      prop->int_value);
6551 				  break;
6552 			      case GEOJSON_DOUBLE:
6553 				  sqlite3_bind_double (stmt, cnt++,
6554 						       prop->dbl_value);
6555 				  break;
6556 			      case GEOJSON_FALSE:
6557 				  sqlite3_bind_int (stmt, cnt++, 0);
6558 				  break;
6559 			      case GEOJSON_TRUE:
6560 				  sqlite3_bind_int (stmt, cnt++, 0);
6561 				  break;
6562 			      case GEOJSON_NULL:
6563 			      default:
6564 				  sqlite3_bind_null (stmt, cnt++);
6565 				  break;
6566 			      };
6567 			}
6568 		      col = col->next;
6569 		  }
6570 		if (ft->geometry == NULL)
6571 		    sqlite3_bind_null (stmt, cnt++);
6572 		else
6573 		  {
6574 		      gaiaGeomCollPtr geo =
6575 			  gaiaParseGeoJSON ((const unsigned char
6576 					     *) (ft->geometry));
6577 		      if (geo != NULL)
6578 			{
6579 			    /* binding the Geometry BLOB */
6580 			    unsigned char *blob;
6581 			    int blob_size;
6582 			    geo->Srid = srid;
6583 			    gaiaToSpatiaLiteBlobWkb (geo, &blob, &blob_size);
6584 			    sqlite3_bind_blob (stmt, cnt, blob, blob_size,
6585 					       free);
6586 			    gaiaFreeGeomColl (geo);
6587 			}
6588 		      else
6589 			{
6590 			    *error_message =
6591 				sqlite3_mprintf
6592 				("GeoJSON import: invalid Geometry (fid=%d)\n",
6593 				 ft->fid);
6594 			    goto err;
6595 			}
6596 		  }
6597 		/* inserting the Feature into the DB Table */
6598 		ret = sqlite3_step (stmt);
6599 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6600 		    ins_rows++;
6601 		else
6602 		  {
6603 		      *error_message =
6604 			  sqlite3_mprintf
6605 			  ("GeoJSON import: INSERT INTO failure (fid=%d) %s\n",
6606 			   ft->fid, sqlite3_errmsg (sqlite));
6607 		      goto err;
6608 		  }
6609 		geojson_reset_feature (ft);
6610 	    }
6611 	  else
6612 	      goto err;
6613       }
6614     sqlite3_finalize (stmt);
6615     stmt = NULL;
6616 
6617 /* Committing the still pending Transaction */
6618     ret =
6619 	sqlite3_exec (sqlite, "RELEASE SAVEPOINT import_geo_json", NULL, NULL,
6620 		      NULL);
6621     if (ret != SQLITE_OK)
6622       {
6623 	  *error_message =
6624 	      sqlite3_mprintf ("GeoJSON import: RELEASE SAVEPOINT error (%s)\n",
6625 			       sqlite3_errmsg (sqlite));
6626 	  goto err;
6627       }
6628 
6629     geojson_destroy_parser (parser);
6630     *rows = ins_rows;
6631     return 1;
6632 
6633   err:
6634     if (stmt != NULL)
6635 	sqlite3_finalize (stmt);
6636     if (pending)
6637       {
6638 	  /* Rolling back the Transaction */
6639 	  sqlite3_exec (sqlite, "ROLLBAKC TO SAVEPOINT import_geo_json", NULL,
6640 			NULL, NULL);
6641 	  sqlite3_exec (sqlite, "RELEASE SAVEPOINT import_geo_json", NULL, NULL,
6642 			NULL);
6643       }
6644     geojson_destroy_parser (parser);
6645     *rows = 0;
6646     return 0;
6647 }
6648 
6649 #ifdef ENABLE_MINIZIP		/* MINIZIP is enabled */
6650 
6651 GAIAGEO_DECLARE char *
gaiaReadWktFromZipShp(const char * zip_path,const char * basename)6652 gaiaReadWktFromZipShp (const char *zip_path, const char *basename)
6653 {
6654 /* attempting to read the .PRJ member of some zipped Shapefile */
6655     char *wkt = NULL;
6656     unzFile uf = NULL;
6657     struct zip_mem_shapefile *mem_shape = NULL;
6658 
6659     if (zip_path == NULL)
6660       {
6661 	  spatialite_e ("read_wkt_from_zipshp error: <%s>\n",
6662 			"NULL zipfile path");
6663 	  return NULL;
6664       }
6665 /* opening the Zipfile expected to contain the Shapefile */
6666     uf = unzOpen64 (zip_path);
6667     if (uf == NULL)
6668       {
6669 	  spatialite_e ("Unable to Open %s\n", zip_path);
6670 	  return NULL;
6671       }
6672 /* parsing the Zipfile directory */
6673     mem_shape = do_list_zipfile_dir (uf, basename, 0);
6674     if (mem_shape == NULL)
6675       {
6676 	  spatialite_e ("No SHP %s with Zipfile\n", basename);
6677 	  goto stop;
6678       }
6679 /* unzipping the PRJ member (if any) */
6680     do_read_zipfile_file (uf, mem_shape, GAIA_ZIPFILE_PRJ);
6681     if (mem_shape->prj.buf != NULL)
6682       {
6683 	  wkt = malloc (mem_shape->prj.size + 1);
6684 	  memcpy (wkt, mem_shape->prj.buf, mem_shape->prj.size);
6685 	  *(wkt + mem_shape->prj.size) = '\0';
6686       }
6687 
6688   stop:
6689     unzClose (uf);
6690     if (mem_shape != NULL)
6691 	destroy_zip_mem_shapefile (mem_shape);
6692     return wkt;
6693 }
6694 
6695 GAIAGEO_DECLARE int
gaiaZipfileNumSHP(const char * zip_path,int * count)6696 gaiaZipfileNumSHP (const char *zip_path, int *count)
6697 {
6698 /* attempting to count how many Shapefiles are within a given Zipfile */
6699     int ret;
6700     int retval = 1;
6701     struct zip_mem_shp_item *item;
6702     struct zip_mem_shp_list *list = alloc_zip_mem_shp_list ();
6703     unzFile uf = NULL;
6704 
6705     *count = 0;
6706     if (zip_path == NULL)
6707       {
6708 	  spatialite_e ("zipfile NumSHP error: <%s>\n", "NULL zipfile path");
6709 	  retval = 0;
6710 	  goto stop;
6711       }
6712 /* opening the Zipfile expected to contain the Shapefile */
6713     uf = unzOpen64 (zip_path);
6714     if (uf == NULL)
6715       {
6716 	  spatialite_e ("Unable to Open %s\n", zip_path);
6717 	  retval = 0;
6718 	  goto stop;
6719       }
6720 /* sniffing the Zipfile */
6721     ret = do_sniff_zipfile_dir (uf, list, 0);
6722     if (!ret)
6723       {
6724 	  retval = 0;
6725 	  goto stop;
6726       }
6727     item = list->first;
6728     while (item != NULL)
6729       {
6730 	  /* counting how many Shapefiles are there */
6731 	  if (item->shp && item->shx && item->dbf)
6732 	      *count += 1;
6733 	  item = item->next;
6734       }
6735   stop:
6736     unzClose (uf);
6737     destroy_zip_mem_shp_list (list);
6738     return retval;
6739 }
6740 
6741 GAIAGEO_DECLARE char *
gaiaZipfileShpN(const char * zip_path,int idx)6742 gaiaZipfileShpN (const char *zip_path, int idx)
6743 {
6744 /* attempting to return the Nth Shapefile's basename fromt within a given Zipfile */
6745     int ret;
6746     int count = 0;
6747     char *basename = NULL;
6748     struct zip_mem_shp_item *item;
6749     struct zip_mem_shp_list *list = alloc_zip_mem_shp_list ();
6750     unzFile uf = NULL;
6751 
6752     count = 0;
6753     if (zip_path == NULL)
6754       {
6755 	  spatialite_e ("zipfile NumSHP error: <%s>\n", "NULL zipfile path");
6756 	  goto stop;
6757       }
6758 /* opening the Zipfile expected to contain the Shapefile */
6759     uf = unzOpen64 (zip_path);
6760     if (uf == NULL)
6761       {
6762 	  spatialite_e ("Unable to Open %s\n", zip_path);
6763 	  goto stop;
6764       }
6765 /* sniffing the Zipfile */
6766     ret = do_sniff_zipfile_dir (uf, list, 0);
6767     if (!ret)
6768 	goto stop;
6769     item = list->first;
6770     while (item != NULL)
6771       {
6772 	  /* counting how many Shapefiles are there */
6773 	  if (item->shp && item->shx && item->dbf)
6774 	      count++;
6775 	  if (count == idx)
6776 	    {
6777 		int len = strlen (item->basename);
6778 		basename = malloc (len + 1);
6779 		strcpy (basename, item->basename);
6780 		break;
6781 	    }
6782 	  item = item->next;
6783       }
6784   stop:
6785     unzClose (uf);
6786     destroy_zip_mem_shp_list (list);
6787     return basename;
6788 }
6789 
6790 GAIAGEO_DECLARE int
gaiaZipfileNumDBF(const char * zip_path,int * count)6791 gaiaZipfileNumDBF (const char *zip_path, int *count)
6792 {
6793 /* attempting to count how many DBF files are within a given Zipfile */
6794     int ret;
6795     int retval = 1;
6796     struct zip_mem_shp_item *item;
6797     struct zip_mem_shp_list *list = alloc_zip_mem_shp_list ();
6798     unzFile uf = NULL;
6799 
6800     *count = 0;
6801     if (zip_path == NULL)
6802       {
6803 	  spatialite_e ("zipfile NumDBF error: <%s>\n", "NULL zipfile path");
6804 	  retval = 0;
6805 	  goto stop;
6806       }
6807 /* opening the Zipfile expected to contain the DBF file */
6808     uf = unzOpen64 (zip_path);
6809     if (uf == NULL)
6810       {
6811 	  spatialite_e ("Unable to Open %s\n", zip_path);
6812 	  retval = 0;
6813 	  goto stop;
6814       }
6815 /* sniffing the Zipfile */
6816     ret = do_sniff_zipfile_dir (uf, list, 1);
6817     if (!ret)
6818       {
6819 	  retval = 0;
6820 	  goto stop;
6821       }
6822     item = list->first;
6823     while (item != NULL)
6824       {
6825 	  /* counting how many DBF files are there */
6826 	  if (item->dbf)
6827 	      *count += 1;
6828 	  item = item->next;
6829       }
6830   stop:
6831     unzClose (uf);
6832     destroy_zip_mem_shp_list (list);
6833     return retval;
6834 }
6835 
6836 GAIAGEO_DECLARE char *
gaiaZipfileDbfN(const char * zip_path,int idx)6837 gaiaZipfileDbfN (const char *zip_path, int idx)
6838 {
6839 /* attempting to return the Nth DBF filename fromt within a given Zipfile */
6840     int ret;
6841     int count = 0;
6842     char *filename = NULL;
6843     struct zip_mem_shp_item *item;
6844     struct zip_mem_shp_list *list = alloc_zip_mem_shp_list ();
6845     unzFile uf = NULL;
6846 
6847     count = 0;
6848     if (zip_path == NULL)
6849       {
6850 	  spatialite_e ("zipfile NumDBF error: <%s>\n", "NULL zipfile path");
6851 	  goto stop;
6852       }
6853 /* opening the Zipfile expected to contain the DBF file */
6854     uf = unzOpen64 (zip_path);
6855     if (uf == NULL)
6856       {
6857 	  spatialite_e ("Unable to Open %s\n", zip_path);
6858 	  goto stop;
6859       }
6860 /* sniffing the Zipfile */
6861     ret = do_sniff_zipfile_dir (uf, list, 1);
6862     if (!ret)
6863 	goto stop;
6864     item = list->first;
6865     while (item != NULL)
6866       {
6867 	  /* counting how many DBF files are there */
6868 	  if (item->dbf)
6869 	      count++;
6870 	  if (count == idx)
6871 	    {
6872 		int len = strlen (item->basename);
6873 		filename = malloc (len + 1);
6874 		strcpy (filename, item->basename);
6875 		break;
6876 	    }
6877 	  item = item->next;
6878       }
6879   stop:
6880     unzClose (uf);
6881     destroy_zip_mem_shp_list (list);
6882     return filename;
6883 }
6884 
6885 #endif /* end MINIZIP */
6886 
6887 #endif /* end ICONV (SHP) */
6888 
6889 static int
is_table(sqlite3 * sqlite,const char * table)6890 is_table (sqlite3 * sqlite, const char *table)
6891 {
6892 /* check if this one really is a TABLE */
6893     char *sql;
6894     int ret;
6895     char **results;
6896     int rows;
6897     int columns;
6898     char *errMsg = NULL;
6899     int ok = 0;
6900 
6901     sql = sqlite3_mprintf ("SELECT tbl_name FROM sqlite_master "
6902 			   "WHERE type = 'table' AND Lower(tbl_name) = Lower(%Q)",
6903 			   table);
6904     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
6905     sqlite3_free (sql);
6906     if (ret != SQLITE_OK)
6907       {
6908 	  spatialite_e ("SQLite SQL error: %s\n", errMsg);
6909 	  sqlite3_free (errMsg);
6910 	  return ok;
6911       }
6912     if (rows < 1)
6913 	;
6914     else
6915 	ok = 1;
6916     sqlite3_free_table (results);
6917     return ok;
6918 }
6919 
6920 SPATIALITE_DECLARE void
check_duplicated_rows(sqlite3 * sqlite,char * table,int * dupl_count)6921 check_duplicated_rows (sqlite3 * sqlite, char *table, int *dupl_count)
6922 {
6923 /* Checking a Table for Duplicate rows */
6924     char *sql;
6925     int first = 1;
6926     char *xname;
6927     int pk;
6928     int ret;
6929     char **results;
6930     int rows;
6931     int columns;
6932     int i;
6933     char *errMsg = NULL;
6934     sqlite3_stmt *stmt = NULL;
6935     gaiaOutBuffer sql_statement;
6936     gaiaOutBuffer col_list;
6937 
6938     *dupl_count = 0;
6939 
6940     if (is_table (sqlite, table) == 0)
6941       {
6942 	  spatialite_e (".chkdupl %s: no such table\n", table);
6943 	  *dupl_count = -1;
6944 	  return;
6945       }
6946 /* extracting the column names (excluding any Primary Key) */
6947     gaiaOutBufferInitialize (&col_list);
6948     xname = gaiaDoubleQuotedSql (table);
6949     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xname);
6950     free (xname);
6951     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
6952     sqlite3_free (sql);
6953     if (ret != SQLITE_OK)
6954       {
6955 	  spatialite_e ("SQLite SQL error: %s\n", errMsg);
6956 	  sqlite3_free (errMsg);
6957 	  return;
6958       }
6959     if (rows < 1)
6960 	;
6961     else
6962       {
6963 	  for (i = 1; i <= rows; i++)
6964 	    {
6965 		sql = results[(i * columns) + 1];
6966 		pk = atoi (results[(i * columns) + 5]);
6967 		if (!pk)
6968 		  {
6969 		      xname = gaiaDoubleQuotedSql (sql);
6970 		      if (first)
6971 			{
6972 			    sql = sqlite3_mprintf ("\"%s\"", xname);
6973 			    first = 0;
6974 			}
6975 		      else
6976 			  sql = sqlite3_mprintf (", \"%s\"", xname);
6977 		      free (xname);
6978 		      gaiaAppendToOutBuffer (&col_list, sql);
6979 		      sqlite3_free (sql);
6980 		  }
6981 	    }
6982       }
6983     sqlite3_free_table (results);
6984     /* preparing the SQL statement */
6985     gaiaOutBufferInitialize (&sql_statement);
6986     gaiaAppendToOutBuffer (&sql_statement,
6987 			   "SELECT Count(*) AS \"[dupl-count]\", ");
6988     if (col_list.Error == 0 && col_list.Buffer != NULL)
6989 	gaiaAppendToOutBuffer (&sql_statement, col_list.Buffer);
6990     xname = gaiaDoubleQuotedSql (table);
6991     sql = sqlite3_mprintf ("\nFROM \"%s\"\nGROUP BY ", xname);
6992     free (xname);
6993     gaiaAppendToOutBuffer (&sql_statement, sql);
6994     sqlite3_free (sql);
6995     if (col_list.Error == 0 && col_list.Buffer != NULL)
6996 	gaiaAppendToOutBuffer (&sql_statement, col_list.Buffer);
6997     gaiaOutBufferReset (&col_list);
6998     gaiaAppendToOutBuffer (&sql_statement, "\nHAVING \"[dupl-count]\" > 1");
6999     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
7000       {
7001 	  ret =
7002 	      sqlite3_prepare_v2 (sqlite, sql_statement.Buffer,
7003 				  strlen (sql_statement.Buffer), &stmt, NULL);
7004 	  gaiaOutBufferReset (&sql_statement);
7005 	  if (ret != SQLITE_OK)
7006 	    {
7007 		spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
7008 		return;
7009 	    }
7010       }
7011     while (1)
7012       {
7013 	  /* fetching the result set rows */
7014 	  ret = sqlite3_step (stmt);
7015 	  if (ret == SQLITE_DONE)
7016 	      break;		/* end of result set */
7017 	  if (ret == SQLITE_ROW)
7018 	    {
7019 		/* fetching a row */
7020 		*dupl_count += sqlite3_column_int (stmt, 0) - 1;
7021 	    }
7022 	  else
7023 	    {
7024 		spatialite_e ("SQL error: %s", sqlite3_errmsg (sqlite));
7025 		sqlite3_finalize (stmt);
7026 		return;
7027 	    }
7028       }
7029     sqlite3_finalize (stmt);
7030     if (*dupl_count)
7031 	spatialite_e ("%d duplicated rows found !!!\n", *dupl_count);
7032     else
7033 	spatialite_e ("No duplicated rows have been identified\n");
7034 }
7035 
7036 static int
do_delete_duplicates2(sqlite3 * sqlite,sqlite3_int64 rowid,sqlite3_stmt * stmt1)7037 do_delete_duplicates2 (sqlite3 * sqlite, sqlite3_int64 rowid,
7038 		       sqlite3_stmt * stmt1)
7039 {
7040 /* deleting duplicate rows [actual delete] */
7041     int ret;
7042 
7043     sqlite3_reset (stmt1);
7044     sqlite3_clear_bindings (stmt1);
7045     sqlite3_bind_int64 (stmt1, 1, rowid);
7046     ret = sqlite3_step (stmt1);
7047     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
7048 	;
7049     else
7050       {
7051 	  spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
7052 	  return 0;
7053       }
7054     return 1;
7055 }
7056 
7057 static int
do_delete_duplicates(sqlite3 * sqlite,const char * sql1,const char * sql2,int * count,int transaction)7058 do_delete_duplicates (sqlite3 * sqlite, const char *sql1, const char *sql2,
7059 		      int *count, int transaction)
7060 {
7061 /* deleting duplicate rows */
7062     struct resultset_comparator *rs_obj = NULL;
7063     sqlite3_stmt *stmt1 = NULL;
7064     sqlite3_stmt *stmt2 = NULL;
7065     int ret;
7066     int cnt = 0;
7067     char *sql_err = NULL;
7068 
7069     *count = 0;
7070 
7071     if (transaction)
7072       {
7073 	  /* the complete operation is handled as an unique SQL Transaction */
7074 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &sql_err);
7075 	  if (ret != SQLITE_OK)
7076 	    {
7077 		spatialite_e ("BEGIN TRANSACTION error: %s\n", sql_err);
7078 		sqlite3_free (sql_err);
7079 		return 0;
7080 	    }
7081       }
7082 
7083 /* preparing the main SELECT statement */
7084     ret = sqlite3_prepare_v2 (sqlite, sql1, strlen (sql1), &stmt1, NULL);
7085     if (ret != SQLITE_OK)
7086       {
7087 	  spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
7088 	  return 0;
7089       }
7090 /* preparing the DELETE statement */
7091     ret = sqlite3_prepare_v2 (sqlite, sql2, strlen (sql2), &stmt2, NULL);
7092     if (ret != SQLITE_OK)
7093       {
7094 	  spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
7095 	  goto error;
7096       }
7097 
7098     rs_obj = create_resultset_comparator (sqlite3_column_count (stmt1) - 1);
7099     while (1)
7100       {
7101 	  /* fetching the result set rows */
7102 	  ret = sqlite3_step (stmt1);
7103 	  if (ret == SQLITE_DONE)
7104 	      break;		/* end of result set */
7105 	  if (ret == SQLITE_ROW)
7106 	    {
7107 		/* fetching a row */
7108 		save_row_from_resultset (rs_obj, stmt1);
7109 		if (resultset_rows_equals (rs_obj))
7110 		  {
7111 		      if (do_delete_duplicates2
7112 			  (sqlite, get_current_resultset_rowid (rs_obj), stmt2))
7113 			{
7114 			    cnt += 1;
7115 			    reset_resultset_current_row (rs_obj);
7116 			    continue;
7117 			}
7118 		      else
7119 			  goto error;
7120 		  }
7121 	    }
7122 	  else
7123 	    {
7124 		spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
7125 		goto error;
7126 	    }
7127 	  swap_resultset_rows (rs_obj);
7128       }
7129 
7130     sqlite3_finalize (stmt1);
7131     sqlite3_finalize (stmt2);
7132     destroy_resultset_comparator (rs_obj);
7133 
7134     if (transaction)
7135       {
7136 	  /* confirm the still pending Transaction */
7137 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &sql_err);
7138 	  if (ret != SQLITE_OK)
7139 	    {
7140 		spatialite_e ("COMMIT TRANSACTION error: %s\n", sql_err);
7141 		sqlite3_free (sql_err);
7142 		return 0;
7143 	    }
7144       }
7145 
7146     *count = cnt;
7147     return 1;
7148 
7149   error:
7150     *count = 0;
7151     if (stmt1)
7152 	sqlite3_finalize (stmt1);
7153     if (stmt2)
7154 	sqlite3_finalize (stmt2);
7155 
7156     if (transaction)
7157       {
7158 	  /* performing a ROLLBACK anyway */
7159 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &sql_err);
7160 	  if (ret != SQLITE_OK)
7161 	    {
7162 		spatialite_e ("ROLLBACK TRANSACTION error: %s\n", sql_err);
7163 		sqlite3_free (sql_err);
7164 		return 0;
7165 	    }
7166       }
7167 
7168     return 0;
7169 }
7170 
7171 SPATIALITE_DECLARE void
remove_duplicated_rows_ex2(sqlite3 * sqlite,char * table,int * removed,int transaction)7172 remove_duplicated_rows_ex2 (sqlite3 * sqlite, char *table, int *removed,
7173 			    int transaction)
7174 {
7175 /* attempting to delete Duplicate rows from a table */
7176     char *sql;
7177     char *sql2;
7178     int first = 1;
7179     char *xname;
7180     int pk;
7181     int ret;
7182     char **results;
7183     int rows;
7184     int columns;
7185     int i;
7186     char *errMsg = NULL;
7187     int count;
7188     gaiaOutBuffer sql_statement;
7189     gaiaOutBuffer col_list;
7190 
7191     if (removed != NULL)
7192 	*removed = 0;
7193 
7194     if (is_table (sqlite, table) == 0)
7195       {
7196 	  spatialite_e (".remdupl %s: no such table\n", table);
7197 	  if (removed != NULL)
7198 	      *removed = -1;
7199 	  return;
7200       }
7201 /* extracting the column names (excluding any Primary Key) */
7202     gaiaOutBufferInitialize (&col_list);
7203     xname = gaiaDoubleQuotedSql (table);
7204     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xname);
7205     free (xname);
7206     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7207     sqlite3_free (sql);
7208     if (ret != SQLITE_OK)
7209       {
7210 	  spatialite_e ("SQLite SQL error: %s\n", errMsg);
7211 	  sqlite3_free (errMsg);
7212 	  return;
7213       }
7214     if (rows < 1)
7215 	;
7216     else
7217       {
7218 	  for (i = 1; i <= rows; i++)
7219 	    {
7220 		sql = results[(i * columns) + 1];
7221 		pk = atoi (results[(i * columns) + 5]);
7222 		if (!pk)
7223 		  {
7224 		      if (first)
7225 			  first = 0;
7226 		      else
7227 			  gaiaAppendToOutBuffer (&col_list, ", ");
7228 		      xname = gaiaDoubleQuotedSql (sql);
7229 		      sql = sqlite3_mprintf ("\"%s\"", xname);
7230 		      free (xname);
7231 		      gaiaAppendToOutBuffer (&col_list, sql);
7232 		      sqlite3_free (sql);
7233 		  }
7234 	    }
7235       }
7236     sqlite3_free_table (results);
7237 /* preparing the SQL statement (identifying duplicated rows) */
7238     gaiaOutBufferInitialize (&sql_statement);
7239     gaiaAppendToOutBuffer (&sql_statement, "SELECT ROWID, ");
7240     if (col_list.Error == 0 && col_list.Buffer != NULL)
7241 	gaiaAppendToOutBuffer (&sql_statement, col_list.Buffer);
7242     xname = gaiaDoubleQuotedSql (table);
7243     sql = sqlite3_mprintf ("\nFROM \"%s\"\nORDER BY ", xname);
7244     free (xname);
7245     gaiaAppendToOutBuffer (&sql_statement, sql);
7246     sqlite3_free (sql);
7247     if (col_list.Error == 0 && col_list.Buffer != NULL)
7248 	gaiaAppendToOutBuffer (&sql_statement, col_list.Buffer);
7249     gaiaOutBufferReset (&col_list);
7250     gaiaAppendToOutBuffer (&sql_statement, ", ROWID");
7251 /* preparing the SQL statement [delete] */
7252     xname = gaiaDoubleQuotedSql (table);
7253     sql2 = sqlite3_mprintf ("DELETE FROM \"%s\" WHERE ROWID = ?", xname);
7254     free (xname);
7255 
7256     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
7257 	sql = sql_statement.Buffer;
7258     else
7259 	sql = "NULL-SELECT";
7260     if (do_delete_duplicates (sqlite, sql, sql2, &count, transaction))
7261       {
7262 	  if (removed == NULL)
7263 	    {
7264 		if (!count)
7265 		    spatialite_e ("No duplicated rows have been identified\n");
7266 		else
7267 		    spatialite_e ("%d duplicated rows deleted from: %s\n",
7268 				  count, table);
7269 	    }
7270 	  else
7271 	      *removed = count;
7272       }
7273     gaiaOutBufferReset (&sql_statement);
7274     sqlite3_free (sql2);
7275 }
7276 
7277 SPATIALITE_DECLARE void
remove_duplicated_rows_ex(sqlite3 * sqlite,char * table,int * removed)7278 remove_duplicated_rows_ex (sqlite3 * sqlite, char *table, int *removed)
7279 {
7280 /* attempting to delete Duplicate rows from a table */
7281     remove_duplicated_rows_ex2 (sqlite, table, removed, 1);
7282 }
7283 
7284 SPATIALITE_DECLARE void
remove_duplicated_rows(sqlite3 * sqlite,char * table)7285 remove_duplicated_rows (sqlite3 * sqlite, char *table)
7286 {
7287 /* attempting to delete Duplicate rows from a table */
7288     remove_duplicated_rows_ex (sqlite, table, NULL);
7289 }
7290 
7291 static int
check_elementary(sqlite3 * sqlite,const char * inTable,const char * geom,const char * outTable,const char * pKey,const char * multiID,char * type,int * srid,char * coordDims)7292 check_elementary (sqlite3 * sqlite, const char *inTable, const char *geom,
7293 		  const char *outTable, const char *pKey, const char *multiID,
7294 		  char *type, int *srid, char *coordDims)
7295 {
7296 /* preliminary check for ELEMENTARY GEOMETRIES */
7297     char *sql;
7298     char *xtable;
7299     int ret;
7300     char **results;
7301     int rows;
7302     int columns;
7303     char *errMsg = NULL;
7304     int ok = 0;
7305     int i;
7306     char *gtp;
7307     char *dims;
7308     int metadata_version = checkSpatialMetaData (sqlite);
7309 
7310 /* fetching metadata */
7311     if (metadata_version == 3)
7312       {
7313 	  /* current metadata style >= v.4.0.0 */
7314 	  sql = sqlite3_mprintf ("SELECT geometry_type, srid "
7315 				 "FROM geometry_columns WHERE Lower(f_table_name) = Lower(%Q) "
7316 				 "AND Lower(f_geometry_column) = Lower(%Q)",
7317 				 inTable, geom);
7318       }
7319     else
7320       {
7321 	  /* legacy metadata style <= v.3.1.0 */
7322 	  sql = sqlite3_mprintf ("SELECT type, coord_dimension, srid "
7323 				 "FROM geometry_columns WHERE Lower(f_table_name) = Lower(%Q) "
7324 				 "AND Lower(f_geometry_column) = Lower(%Q)",
7325 				 inTable, geom);
7326       }
7327     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7328     sqlite3_free (sql);
7329     if (ret != SQLITE_OK)
7330       {
7331 	  spatialite_e ("SQL error: %s\n", errMsg);
7332 	  sqlite3_free (errMsg);
7333 	  return 0;
7334       }
7335     if (rows < 1)
7336 	;
7337     else
7338       {
7339 	  for (i = 1; i <= rows; i++)
7340 	    {
7341 		if (metadata_version == 3)
7342 		  {
7343 		      /* current metadata style >= v.4.0.0 */
7344 		      gtp = "UNKNOWN";
7345 		      dims = "UNKNOWN";
7346 		      switch (atoi (results[(i * columns) + 0]))
7347 			{
7348 			case 0:
7349 			    gtp = "GEOMETRY";
7350 			    dims = "XY";
7351 			    break;
7352 			case 1:
7353 			    gtp = "POINT";
7354 			    dims = "XY";
7355 			    break;
7356 			case 2:
7357 			    gtp = "LINESTRING";
7358 			    dims = "XY";
7359 			    break;
7360 			case 3:
7361 			    gtp = "POLYGON";
7362 			    dims = "XY";
7363 			    break;
7364 			case 4:
7365 			    gtp = "MULTIPOINT";
7366 			    dims = "XY";
7367 			    break;
7368 			case 5:
7369 			    gtp = "MULTILINESTRING";
7370 			    dims = "XY";
7371 			    break;
7372 			case 6:
7373 			    gtp = "MULTIPOLYGON";
7374 			    dims = "XY";
7375 			    break;
7376 			case 7:
7377 			    gtp = "GEOMETRYCOLLECTION";
7378 			    dims = "XY";
7379 			    break;
7380 			case 1000:
7381 			    gtp = "GEOMETRY";
7382 			    dims = "XYZ";
7383 			    break;
7384 			case 1001:
7385 			    gtp = "POINT";
7386 			    dims = "XYZ";
7387 			    break;
7388 			case 1002:
7389 			    gtp = "LINESTRING";
7390 			    dims = "XYZ";
7391 			    break;
7392 			case 1003:
7393 			    gtp = "POLYGON";
7394 			    dims = "XYZ";
7395 			    break;
7396 			case 1004:
7397 			    gtp = "MULTIPOINT";
7398 			    dims = "XYZ";
7399 			    break;
7400 			case 1005:
7401 			    gtp = "MULTILINESTRING";
7402 			    dims = "XYZ";
7403 			    break;
7404 			case 1006:
7405 			    gtp = "MULTIPOLYGON";
7406 			    dims = "XYZ";
7407 			    break;
7408 			case 1007:
7409 			    gtp = "GEOMETRYCOLLECTION";
7410 			    dims = "XYZ";
7411 			    break;
7412 			case 2000:
7413 			    gtp = "GEOMETRY";
7414 			    dims = "XYM";
7415 			    break;
7416 			case 2001:
7417 			    gtp = "POINT";
7418 			    dims = "XYM";
7419 			    break;
7420 			case 2002:
7421 			    gtp = "LINESTRING";
7422 			    dims = "XYM";
7423 			    break;
7424 			case 2003:
7425 			    gtp = "POLYGON";
7426 			    dims = "XYM";
7427 			    break;
7428 			case 2004:
7429 			    gtp = "MULTIPOINT";
7430 			    dims = "XYM";
7431 			    break;
7432 			case 2005:
7433 			    gtp = "MULTILINESTRING";
7434 			    dims = "XYM";
7435 			    break;
7436 			case 2006:
7437 			    gtp = "MULTIPOLYGON";
7438 			    dims = "XYM";
7439 			    break;
7440 			case 2007:
7441 			    gtp = "GEOMETRYCOLLECTION";
7442 			    dims = "XYM";
7443 			    break;
7444 			case 3000:
7445 			    gtp = "GEOMETRY";
7446 			    dims = "XYZM";
7447 			    break;
7448 			case 3001:
7449 			    gtp = "POINT";
7450 			    dims = "XYZM";
7451 			    break;
7452 			case 3002:
7453 			    gtp = "LINESTRING";
7454 			    dims = "XYZM";
7455 			    break;
7456 			case 3003:
7457 			    gtp = "POLYGON";
7458 			    dims = "XYZM";
7459 			    break;
7460 			case 3004:
7461 			    gtp = "MULTIPOINT";
7462 			    dims = "XYZM";
7463 			    break;
7464 			case 3005:
7465 			    gtp = "MULTILINESTRING";
7466 			    dims = "XYZM";
7467 			    break;
7468 			case 3006:
7469 			    gtp = "MULTIPOLYGON";
7470 			    dims = "XYZM";
7471 			    break;
7472 			case 3007:
7473 			    gtp = "GEOMETRYCOLLECTION";
7474 			    dims = "XYZM";
7475 			    break;
7476 			};
7477 		      *srid = atoi (results[(i * columns) + 1]);
7478 		  }
7479 		else
7480 		  {
7481 		      /* legacy metadata style <= v.3.1.0 */
7482 		      gtp = results[(i * columns) + 0];
7483 		      dims = results[(i * columns) + 1];
7484 		      *srid = atoi (results[(i * columns) + 2]);
7485 		  }
7486 		if (strcasecmp (gtp, "POINT") == 0
7487 		    || strcasecmp (gtp, "MULTIPOINT") == 0)
7488 		    strcpy (type, "POINT");
7489 		else if (strcasecmp (gtp, "LINESTRING") == 0
7490 			 || strcasecmp (gtp, "MULTILINESTRING") == 0)
7491 		    strcpy (type, "LINESTRING");
7492 		else if (strcasecmp (gtp, "POLYGON") == 0
7493 			 || strcasecmp (gtp, "MULTIPOLYGON") == 0)
7494 		    strcpy (type, "POLYGON");
7495 		else
7496 		    strcpy (type, "GEOMETRY");
7497 		strcpy (coordDims, dims);
7498 		ok = 1;
7499 	    }
7500       }
7501     sqlite3_free_table (results);
7502     if (!ok)
7503 	return 0;
7504 
7505 /* checking if PrimaryKey already exists */
7506     xtable = gaiaDoubleQuotedSql (inTable);
7507     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xtable);
7508     free (xtable);
7509     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7510     sqlite3_free (sql);
7511     if (ret != SQLITE_OK)
7512       {
7513 	  spatialite_e ("SQL error: %s\n", errMsg);
7514 	  sqlite3_free (errMsg);
7515 	  return 0;
7516       }
7517     if (rows < 1)
7518 	;
7519     else
7520       {
7521 	  for (i = 1; i <= rows; i++)
7522 	    {
7523 		if (strcasecmp (pKey, results[(i * columns) + 1]) == 0)
7524 		    ok = 0;
7525 	    }
7526       }
7527     sqlite3_free_table (results);
7528     if (!ok)
7529 	return 0;
7530 
7531 /* checking if MultiID already exists */
7532     xtable = gaiaDoubleQuotedSql (inTable);
7533     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xtable);
7534     free (xtable);
7535     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7536     sqlite3_free (sql);
7537     if (ret != SQLITE_OK)
7538       {
7539 	  spatialite_e ("SQL error: %s\n", errMsg);
7540 	  sqlite3_free (errMsg);
7541 	  return 0;
7542       }
7543     if (rows < 1)
7544 	;
7545     else
7546       {
7547 	  for (i = 1; i <= rows; i++)
7548 	    {
7549 		if (strcasecmp (multiID, results[(i * columns) + 1]) == 0)
7550 		    ok = 0;
7551 	    }
7552       }
7553     sqlite3_free_table (results);
7554     if (!ok)
7555 	return 0;
7556 
7557 /* cheching if Output Table already exists */
7558     sql = sqlite3_mprintf ("SELECT Count(*) FROM sqlite_master "
7559 			   "WHERE type = 'table' AND Lower(tbl_name) = Lower(%Q)",
7560 			   outTable);
7561     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7562     sqlite3_free (sql);
7563     if (ret != SQLITE_OK)
7564       {
7565 	  spatialite_e ("SQL error: %s\n", errMsg);
7566 	  sqlite3_free (errMsg);
7567 	  return 0;
7568       }
7569     if (rows < 1)
7570 	;
7571     else
7572       {
7573 	  for (i = 1; i <= rows; i++)
7574 	    {
7575 		if (atoi (results[(i * columns) + 0]) != 0)
7576 		    ok = 0;
7577 	    }
7578       }
7579     sqlite3_free_table (results);
7580 
7581     return ok;
7582 }
7583 
7584 static gaiaGeomCollPtr
elemGeomFromPoint(gaiaPointPtr pt,int srid)7585 elemGeomFromPoint (gaiaPointPtr pt, int srid)
7586 {
7587 /* creating a Geometry containing a single Point */
7588     gaiaGeomCollPtr g = NULL;
7589     switch (pt->DimensionModel)
7590       {
7591       case GAIA_XY_Z_M:
7592 	  g = gaiaAllocGeomCollXYZM ();
7593 	  break;
7594       case GAIA_XY_Z:
7595 	  g = gaiaAllocGeomCollXYZ ();
7596 	  break;
7597       case GAIA_XY_M:
7598 	  g = gaiaAllocGeomCollXYM ();
7599 	  break;
7600       default:
7601 	  g = gaiaAllocGeomColl ();
7602 	  break;
7603       };
7604     if (!g)
7605 	return NULL;
7606     g->Srid = srid;
7607     g->DeclaredType = GAIA_POINT;
7608     switch (pt->DimensionModel)
7609       {
7610       case GAIA_XY_Z_M:
7611 	  gaiaAddPointToGeomCollXYZM (g, pt->X, pt->Y, pt->Z, pt->M);
7612 	  break;
7613       case GAIA_XY_Z:
7614 	  gaiaAddPointToGeomCollXYZ (g, pt->X, pt->Y, pt->Z);
7615 	  break;
7616       case GAIA_XY_M:
7617 	  gaiaAddPointToGeomCollXYM (g, pt->X, pt->Y, pt->M);
7618 	  break;
7619       default:
7620 	  gaiaAddPointToGeomColl (g, pt->X, pt->Y);
7621 	  break;
7622       };
7623     return g;
7624 }
7625 
7626 static gaiaGeomCollPtr
elemGeomFromLinestring(gaiaLinestringPtr ln,int srid)7627 elemGeomFromLinestring (gaiaLinestringPtr ln, int srid)
7628 {
7629 /* creating a Geometry containing a single Linestring */
7630     gaiaGeomCollPtr g = NULL;
7631     gaiaLinestringPtr ln2;
7632     int iv;
7633     double x;
7634     double y;
7635     double z;
7636     double m;
7637     switch (ln->DimensionModel)
7638       {
7639       case GAIA_XY_Z_M:
7640 	  g = gaiaAllocGeomCollXYZM ();
7641 	  break;
7642       case GAIA_XY_Z:
7643 	  g = gaiaAllocGeomCollXYZ ();
7644 	  break;
7645       case GAIA_XY_M:
7646 	  g = gaiaAllocGeomCollXYM ();
7647 	  break;
7648       default:
7649 	  g = gaiaAllocGeomColl ();
7650 	  break;
7651       };
7652     if (!g)
7653 	return NULL;
7654     g->Srid = srid;
7655     g->DeclaredType = GAIA_LINESTRING;
7656     ln2 = gaiaAddLinestringToGeomColl (g, ln->Points);
7657     switch (ln->DimensionModel)
7658       {
7659       case GAIA_XY_Z_M:
7660 	  for (iv = 0; iv < ln->Points; iv++)
7661 	    {
7662 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
7663 		gaiaSetPointXYZM (ln2->Coords, iv, x, y, z, m);
7664 	    }
7665 	  break;
7666       case GAIA_XY_Z:
7667 	  for (iv = 0; iv < ln->Points; iv++)
7668 	    {
7669 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
7670 		gaiaSetPointXYZ (ln2->Coords, iv, x, y, z);
7671 	    }
7672 	  break;
7673       case GAIA_XY_M:
7674 	  for (iv = 0; iv < ln->Points; iv++)
7675 	    {
7676 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
7677 		gaiaSetPointXYM (ln2->Coords, iv, x, y, m);
7678 	    }
7679 	  break;
7680       default:
7681 	  for (iv = 0; iv < ln->Points; iv++)
7682 	    {
7683 		gaiaGetPoint (ln->Coords, iv, &x, &y);
7684 		gaiaSetPoint (ln2->Coords, iv, x, y);
7685 	    }
7686 	  break;
7687       };
7688     return g;
7689 }
7690 
7691 static gaiaGeomCollPtr
elemGeomFromPolygon(gaiaPolygonPtr pg,int srid)7692 elemGeomFromPolygon (gaiaPolygonPtr pg, int srid)
7693 {
7694 /* creating a Geometry containing a single Polygon */
7695     gaiaGeomCollPtr g = NULL;
7696     gaiaPolygonPtr pg2;
7697     gaiaRingPtr rng;
7698     gaiaRingPtr rng2;
7699     int ib;
7700     int iv;
7701     double x;
7702     double y;
7703     double z;
7704     double m;
7705     switch (pg->DimensionModel)
7706       {
7707       case GAIA_XY_Z_M:
7708 	  g = gaiaAllocGeomCollXYZM ();
7709 	  break;
7710       case GAIA_XY_Z:
7711 	  g = gaiaAllocGeomCollXYZ ();
7712 	  break;
7713       case GAIA_XY_M:
7714 	  g = gaiaAllocGeomCollXYM ();
7715 	  break;
7716       default:
7717 	  g = gaiaAllocGeomColl ();
7718 	  break;
7719       };
7720     if (!g)
7721 	return NULL;
7722     g->Srid = srid;
7723     g->DeclaredType = GAIA_POLYGON;
7724     rng = pg->Exterior;
7725     pg2 = gaiaAddPolygonToGeomColl (g, rng->Points, pg->NumInteriors);
7726     rng2 = pg2->Exterior;
7727     switch (pg->DimensionModel)
7728       {
7729       case GAIA_XY_Z_M:
7730 	  for (iv = 0; iv < rng->Points; iv++)
7731 	    {
7732 		gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
7733 		gaiaSetPointXYZM (rng2->Coords, iv, x, y, z, m);
7734 	    }
7735 	  for (ib = 0; ib < pg->NumInteriors; ib++)
7736 	    {
7737 		rng = pg->Interiors + ib;
7738 		rng2 = gaiaAddInteriorRing (pg2, ib, rng->Points);
7739 		for (iv = 0; iv < rng->Points; iv++)
7740 		  {
7741 		      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
7742 		      gaiaSetPointXYZM (rng2->Coords, iv, x, y, z, m);
7743 		  }
7744 	    }
7745 	  break;
7746       case GAIA_XY_Z:
7747 	  for (iv = 0; iv < rng->Points; iv++)
7748 	    {
7749 		gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
7750 		gaiaSetPointXYZ (rng2->Coords, iv, x, y, z);
7751 	    }
7752 	  for (ib = 0; ib < pg->NumInteriors; ib++)
7753 	    {
7754 		rng = pg->Interiors + ib;
7755 		rng2 = gaiaAddInteriorRing (pg2, ib, rng->Points);
7756 		for (iv = 0; iv < rng->Points; iv++)
7757 		  {
7758 		      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
7759 		      gaiaSetPointXYZ (rng2->Coords, iv, x, y, z);
7760 		  }
7761 	    }
7762 	  break;
7763       case GAIA_XY_M:
7764 	  for (iv = 0; iv < rng->Points; iv++)
7765 	    {
7766 		gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
7767 		gaiaSetPointXYM (rng2->Coords, iv, x, y, m);
7768 	    }
7769 	  for (ib = 0; ib < pg->NumInteriors; ib++)
7770 	    {
7771 		rng = pg->Interiors + ib;
7772 		rng2 = gaiaAddInteriorRing (pg2, ib, rng->Points);
7773 		for (iv = 0; iv < rng->Points; iv++)
7774 		  {
7775 		      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
7776 		      gaiaSetPointXYM (rng2->Coords, iv, x, y, m);
7777 		  }
7778 	    }
7779 	  break;
7780       default:
7781 	  for (iv = 0; iv < rng->Points; iv++)
7782 	    {
7783 		gaiaGetPoint (rng->Coords, iv, &x, &y);
7784 		gaiaSetPoint (rng2->Coords, iv, x, y);
7785 	    }
7786 	  for (ib = 0; ib < pg->NumInteriors; ib++)
7787 	    {
7788 		rng = pg->Interiors + ib;
7789 		rng2 = gaiaAddInteriorRing (pg2, ib, rng->Points);
7790 		for (iv = 0; iv < rng->Points; iv++)
7791 		  {
7792 		      gaiaGetPoint (rng->Coords, iv, &x, &y);
7793 		      gaiaSetPoint (rng2->Coords, iv, x, y);
7794 		  }
7795 	    }
7796 	  break;
7797       };
7798     return g;
7799 }
7800 
7801 SPATIALITE_DECLARE void
elementary_geometries(sqlite3 * sqlite,char * inTable,char * geometry,char * outTable,char * pKey,char * multiId)7802 elementary_geometries (sqlite3 * sqlite,
7803 		       char *inTable, char *geometry, char *outTable,
7804 		       char *pKey, char *multiId)
7805 {
7806 /* attempting to create a derived table surely containing elemetary Geoms */
7807     int rows;
7808     elementary_geometries_ex (sqlite, inTable, geometry, outTable, pKey,
7809 			      multiId, &rows);
7810 }
7811 
7812 SPATIALITE_DECLARE void
elementary_geometries_ex(sqlite3 * sqlite,char * inTable,char * geometry,char * outTable,char * pKey,char * multiId,int * xrows)7813 elementary_geometries_ex (sqlite3 * sqlite,
7814 			  char *inTable, char *geometry, char *outTable,
7815 			  char *pKey, char *multiId, int *xrows)
7816 {
7817 /* attempting to create a derived table surely containing elemetary Geoms */
7818     elementary_geometries_ex2 (sqlite, inTable, geometry, outTable, pKey,
7819 			       multiId, xrows, 1);
7820 }
7821 
7822 SPATIALITE_DECLARE void
elementary_geometries_ex2(sqlite3 * sqlite,char * inTable,char * geometry,char * outTable,char * pKey,char * multiId,int * xrows,int transaction)7823 elementary_geometries_ex2 (sqlite3 * sqlite,
7824 			   char *inTable, char *geometry, char *outTable,
7825 			   char *pKey, char *multiId, int *xrows,
7826 			   int transaction)
7827 {
7828 /* attempting to create a derived table surely containing elemetary Geoms */
7829     elementary_geometries_ex3 (sqlite, inTable, geometry, outTable, pKey,
7830 			       multiId, NULL, xrows, transaction);
7831 }
7832 
7833 static int
test_elemgeom_ignore(struct aux_elemgeom_options * options,const char * column)7834 test_elemgeom_ignore (struct aux_elemgeom_options *options, const char *column)
7835 {
7836 /* testing for a column to be ignored */
7837     struct aux_elemgeom_ignore *ign;
7838     if (options == NULL)
7839 	return 0;
7840 
7841     ign = options->first;
7842     while (ign != NULL)
7843       {
7844 	  if (strcasecmp (ign->column, column) == 0)
7845 	      return 1;
7846 	  ign = ign->next;
7847       }
7848     return 0;
7849 }
7850 
7851 SPATIALITE_DECLARE void
elementary_geometries_ex3(sqlite3 * sqlite,char * inTable,char * geometry,char * outTable,char * pKey,char * multiId,const void * opts,int * xrows,int transaction)7852 elementary_geometries_ex3 (sqlite3 * sqlite,
7853 			   char *inTable, char *geometry, char *outTable,
7854 			   char *pKey, char *multiId, const void *opts,
7855 			   int *xrows, int transaction)
7856 {
7857 /* attempting to create a derived table surely containing elemetary Geoms */
7858     char type[128];
7859     int srid;
7860     char dims[64];
7861     char *sql;
7862     char *xname;
7863     char *xpk;
7864     char *xmulti;
7865     gaiaOutBuffer sql_statement;
7866     gaiaOutBuffer sql2;
7867     gaiaOutBuffer sql3;
7868     gaiaOutBuffer sql4;
7869     char *sql_geom;
7870     int ret;
7871     int comma = 0;
7872     char *errMsg = NULL;
7873     int i;
7874     char **results;
7875     int rows;
7876     int columns;
7877     int i_col;
7878     int geom_idx = -1;
7879     sqlite3_stmt *stmt_in = NULL;
7880     sqlite3_stmt *stmt_out = NULL;
7881     int n_columns;
7882     sqlite3_int64 id = 0;
7883     int inserted = 0;
7884     struct aux_elemgeom_options *options = (struct aux_elemgeom_options *) opts;
7885 
7886     if (check_elementary
7887 	(sqlite, inTable, geometry, outTable, pKey, multiId, type, &srid,
7888 	 dims) == 0)
7889       {
7890 	  spatialite_e (".elemgeo: invalid args\n");
7891 	  *xrows = 0;
7892 	  return;
7893       }
7894 
7895     if (transaction)
7896       {
7897 	  /* starts a transaction */
7898 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
7899 	  if (ret != SQLITE_OK)
7900 	    {
7901 		spatialite_e ("SQL error: %s\n", errMsg);
7902 		sqlite3_free (errMsg);
7903 		goto abort;
7904 	    }
7905       }
7906 
7907     gaiaOutBufferInitialize (&sql_statement);
7908     gaiaOutBufferInitialize (&sql2);
7909     gaiaOutBufferInitialize (&sql3);
7910     gaiaOutBufferInitialize (&sql4);
7911 
7912     gaiaAppendToOutBuffer (&sql_statement, "SELECT ");
7913     xname = gaiaDoubleQuotedSql (outTable);
7914     xpk = gaiaDoubleQuotedSql (pKey);
7915     xmulti = gaiaDoubleQuotedSql (multiId);
7916     sql =
7917 	sqlite3_mprintf ("INSERT INTO \"%s\" (\"%s\", \"%s\", ", xname, xpk,
7918 			 xmulti);
7919     free (xname);
7920     free (xpk);
7921     free (xmulti);
7922     gaiaAppendToOutBuffer (&sql2, sql);
7923     sqlite3_free (sql);
7924     gaiaAppendToOutBuffer (&sql3, ") VALUES (NULL, ?");
7925     xname = gaiaDoubleQuotedSql (outTable);
7926     xpk = gaiaDoubleQuotedSql (pKey);
7927     xmulti = gaiaDoubleQuotedSql (multiId);
7928     sql = sqlite3_mprintf ("CREATE TABLE \"%s\" (\n"
7929 			   "\t\"%s\" INTEGER PRIMARY KEY AUTOINCREMENT"
7930 			   ",\n\t\"%s\" INTEGER NOT NULL", xname, xpk, xmulti);
7931     free (xname);
7932     free (xpk);
7933     free (xmulti);
7934     gaiaAppendToOutBuffer (&sql4, sql);
7935     sqlite3_free (sql);
7936 
7937     xname = gaiaDoubleQuotedSql (inTable);
7938     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xname);
7939     free (xname);
7940     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
7941     sqlite3_free (sql);
7942     if (ret != SQLITE_OK)
7943       {
7944 	  spatialite_e ("SQL error: %s\n", errMsg);
7945 	  sqlite3_free (errMsg);
7946 	  goto abort;
7947       }
7948     if (rows < 1)
7949 	;
7950     else
7951       {
7952 	  i_col = 0;
7953 	  for (i = 1; i <= rows; i++)
7954 	    {
7955 		if (test_elemgeom_ignore (options, results[(i * columns) + 1])
7956 		    && strcasecmp (geometry, results[(i * columns) + 1]) != 0)
7957 		  {
7958 		      /* skipping a column to be ignored */
7959 		      continue;
7960 		  }
7961 		i_col++;
7962 		xname = gaiaDoubleQuotedSql (results[(i * columns) + 1]);
7963 		if (comma)
7964 		    sql = sqlite3_mprintf (", \"%s\"", xname);
7965 		else
7966 		  {
7967 		      comma = 1;
7968 		      sql = sqlite3_mprintf ("\"%s\"", xname);
7969 		  }
7970 		free (xname);
7971 		gaiaAppendToOutBuffer (&sql_statement, sql);
7972 		gaiaAppendToOutBuffer (&sql2, sql);
7973 		if (strcasecmp (geometry, results[(i * columns) + 1]) == 0)
7974 		  {
7975 		      int cast2multi = 0;
7976 		      if (options != NULL)
7977 			  cast2multi = options->cast2multi;
7978 		      if (cast2multi)
7979 			  gaiaAppendToOutBuffer (&sql3, ", CastToMulti(?)");
7980 		      else
7981 			  gaiaAppendToOutBuffer (&sql3, ", ?");
7982 		  }
7983 		else
7984 		    gaiaAppendToOutBuffer (&sql3, ", ?");
7985 		sqlite3_free (sql);
7986 
7987 		if (strcasecmp (geometry, results[(i * columns) + 1]) == 0)
7988 		    geom_idx = i_col - 1;
7989 		else
7990 		  {
7991 		      xname = gaiaDoubleQuotedSql (results[(i * columns) + 1]);
7992 		      if (atoi (results[(i * columns) + 3]) != 0)
7993 			  sql =
7994 			      sqlite3_mprintf (",\n\t\"%s\" %s NOT NULL", xname,
7995 					       results[(i * columns) + 2]);
7996 		      else
7997 			  sql =
7998 			      sqlite3_mprintf (",\n\t\"%s\" %s", xname,
7999 					       results[(i * columns) + 2]);
8000 		      free (xname);
8001 		      gaiaAppendToOutBuffer (&sql4, sql);
8002 		      sqlite3_free (sql);
8003 		  }
8004 	    }
8005       }
8006     sqlite3_free_table (results);
8007     if (geom_idx < 0)
8008 	goto abort;
8009 
8010     xname = gaiaDoubleQuotedSql (inTable);
8011     sql = sqlite3_mprintf (" FROM \"%s\"", xname);
8012     free (xname);
8013     gaiaAppendToOutBuffer (&sql_statement, sql);
8014     sqlite3_free (sql);
8015     gaiaAppendToOutBuffer (&sql2, sql3.Buffer);
8016     gaiaAppendToOutBuffer (&sql2, ")");
8017     gaiaAppendToOutBuffer (&sql4, ")");
8018     gaiaOutBufferReset (&sql3);
8019 
8020     if (options != NULL)
8021       {
8022 	  if (options->cast2multi)
8023 	    {
8024 		char multi_type[128];
8025 		if (strcasecmp (type, "POINT") == 0)
8026 		    strcpy (multi_type, "MULTIPOINT");
8027 		else if (strcasecmp (type, "LINESTRING") == 0)
8028 		    strcpy (multi_type, "MULTILINESTRING");
8029 		else if (strcasecmp (type, "POLYGON") == 0)
8030 		    strcpy (multi_type, "MULTIPOLYGON");
8031 		else
8032 		    strcpy (multi_type, type);
8033 		sql_geom =
8034 		    sqlite3_mprintf
8035 		    ("SELECT AddGeometryColumn(%Q, %Q, %d, %Q, %Q)", outTable,
8036 		     geometry, srid, multi_type, dims);
8037 	    }
8038 	  else
8039 	    {
8040 		sql_geom =
8041 		    sqlite3_mprintf
8042 		    ("SELECT AddGeometryColumn(%Q, %Q, %d, %Q, %Q)", outTable,
8043 		     geometry, srid, type, dims);
8044 	    }
8045       }
8046     else
8047       {
8048 	  sql_geom =
8049 	      sqlite3_mprintf ("SELECT AddGeometryColumn(%Q, %Q, %d, %Q, %Q)",
8050 			       outTable, geometry, srid, type, dims);
8051       }
8052 
8053 /* creating the output table */
8054     ret = sqlite3_exec (sqlite, sql4.Buffer, NULL, NULL, &errMsg);
8055     gaiaOutBufferReset (&sql4);
8056     if (ret != SQLITE_OK)
8057       {
8058 	  spatialite_e ("SQL error: %s\n", errMsg);
8059 	  sqlite3_free (errMsg);
8060 	  goto abort;
8061       }
8062 /* creating the output Geometry */
8063     ret = sqlite3_exec (sqlite, sql_geom, NULL, NULL, &errMsg);
8064     sqlite3_free (sql_geom);
8065     if (ret != SQLITE_OK)
8066       {
8067 	  spatialite_e ("SQL error: %s\n", errMsg);
8068 	  sqlite3_free (errMsg);
8069 	  goto abort;
8070       }
8071 
8072 /* preparing the INPUT statement */
8073     ret =
8074 	sqlite3_prepare_v2 (sqlite, sql_statement.Buffer,
8075 			    strlen (sql_statement.Buffer), &stmt_in, NULL);
8076     gaiaOutBufferReset (&sql_statement);
8077     if (ret != SQLITE_OK)
8078       {
8079 	  spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
8080 	  goto abort;
8081       }
8082 
8083 /* preparing the OUTPUT statement */
8084     ret =
8085 	sqlite3_prepare_v2 (sqlite, sql2.Buffer, strlen (sql2.Buffer),
8086 			    &stmt_out, NULL);
8087     gaiaOutBufferReset (&sql2);
8088     if (ret != SQLITE_OK)
8089       {
8090 	  spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
8091 	  goto abort;
8092       }
8093 
8094 /* data transfer */
8095     n_columns = sqlite3_column_count (stmt_in);
8096     while (1)
8097       {
8098 	  ret = sqlite3_step (stmt_in);
8099 	  if (ret == SQLITE_DONE)
8100 	      break;
8101 	  if (ret == SQLITE_ROW)
8102 	    {
8103 		gaiaGeomCollPtr g =
8104 		    gaiaFromSpatiaLiteBlobWkb ((const unsigned char *)
8105 					       sqlite3_column_blob (stmt_in,
8106 								    geom_idx),
8107 					       sqlite3_column_bytes (stmt_in,
8108 								     geom_idx));
8109 		if (!g)
8110 		  {
8111 		      /* NULL input geometry */
8112 		      sqlite3_reset (stmt_out);
8113 		      sqlite3_clear_bindings (stmt_out);
8114 		      sqlite3_bind_int64 (stmt_out, 1, id);
8115 		      sqlite3_bind_null (stmt_out, geom_idx + 2);
8116 
8117 		      for (i = 0; i < n_columns; i++)
8118 			{
8119 			    int type = sqlite3_column_type (stmt_in, i);
8120 			    if (i == geom_idx)
8121 				continue;
8122 			    switch (type)
8123 			      {
8124 			      case SQLITE_INTEGER:
8125 				  sqlite3_bind_int64 (stmt_out, i + 2,
8126 						      sqlite3_column_int64
8127 						      (stmt_in, i));
8128 				  break;
8129 			      case SQLITE_FLOAT:
8130 				  sqlite3_bind_double (stmt_out, i + 2,
8131 						       sqlite3_column_double
8132 						       (stmt_in, i));
8133 				  break;
8134 			      case SQLITE_TEXT:
8135 				  sqlite3_bind_text (stmt_out, i + 2,
8136 						     (const char *)
8137 						     sqlite3_column_text
8138 						     (stmt_in, i),
8139 						     sqlite3_column_bytes
8140 						     (stmt_in, i),
8141 						     SQLITE_STATIC);
8142 				  break;
8143 			      case SQLITE_BLOB:
8144 				  sqlite3_bind_blob (stmt_out, i + 2,
8145 						     sqlite3_column_blob
8146 						     (stmt_in, i),
8147 						     sqlite3_column_bytes
8148 						     (stmt_in, i),
8149 						     SQLITE_STATIC);
8150 				  break;
8151 			      case SQLITE_NULL:
8152 			      default:
8153 				  sqlite3_bind_null (stmt_out, i + 2);
8154 				  break;
8155 			      };
8156 			}
8157 
8158 		      ret = sqlite3_step (stmt_out);
8159 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
8160 			  ;
8161 		      else
8162 			{
8163 			    spatialite_e ("[OUT]step error: %s\n",
8164 					  sqlite3_errmsg (sqlite));
8165 			    goto abort;
8166 			}
8167 		      inserted++;
8168 		  }
8169 		else
8170 		  {
8171 		      /* separating Elementary Geoms */
8172 		      gaiaPointPtr pt;
8173 		      gaiaLinestringPtr ln;
8174 		      gaiaPolygonPtr pg;
8175 		      gaiaGeomCollPtr outGeom;
8176 		      pt = g->FirstPoint;
8177 		      while (pt)
8178 			{
8179 			    /* separating Points */
8180 			    outGeom = elemGeomFromPoint (pt, g->Srid);
8181 			    sqlite3_reset (stmt_out);
8182 			    sqlite3_clear_bindings (stmt_out);
8183 			    sqlite3_bind_int64 (stmt_out, 1, id);
8184 			    if (!outGeom)
8185 				sqlite3_bind_null (stmt_out, geom_idx + 2);
8186 			    else
8187 			      {
8188 				  unsigned char *blob;
8189 				  int size;
8190 				  gaiaToSpatiaLiteBlobWkb (outGeom, &blob,
8191 							   &size);
8192 				  sqlite3_bind_blob (stmt_out, geom_idx + 2,
8193 						     blob, size, free);
8194 				  gaiaFreeGeomColl (outGeom);
8195 			      }
8196 
8197 			    for (i = 0; i < n_columns; i++)
8198 			      {
8199 				  int type = sqlite3_column_type (stmt_in, i);
8200 				  if (i == geom_idx)
8201 				      continue;
8202 				  switch (type)
8203 				    {
8204 				    case SQLITE_INTEGER:
8205 					sqlite3_bind_int64 (stmt_out, i + 2,
8206 							    sqlite3_column_int64
8207 							    (stmt_in, i));
8208 					break;
8209 				    case SQLITE_FLOAT:
8210 					sqlite3_bind_double (stmt_out, i + 2,
8211 							     sqlite3_column_double
8212 							     (stmt_in, i));
8213 					break;
8214 				    case SQLITE_TEXT:
8215 					sqlite3_bind_text (stmt_out, i + 2,
8216 							   (const char *)
8217 							   sqlite3_column_text
8218 							   (stmt_in, i),
8219 							   sqlite3_column_bytes
8220 							   (stmt_in, i),
8221 							   SQLITE_STATIC);
8222 					break;
8223 				    case SQLITE_BLOB:
8224 					sqlite3_bind_blob (stmt_out, i + 2,
8225 							   sqlite3_column_blob
8226 							   (stmt_in, i),
8227 							   sqlite3_column_bytes
8228 							   (stmt_in, i),
8229 							   SQLITE_STATIC);
8230 					break;
8231 				    case SQLITE_NULL:
8232 				    default:
8233 					sqlite3_bind_null (stmt_out, i + 2);
8234 					break;
8235 				    };
8236 			      }
8237 
8238 			    ret = sqlite3_step (stmt_out);
8239 			    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
8240 				;
8241 			    else
8242 			      {
8243 				  spatialite_e ("[OUT]step error: %s\n",
8244 						sqlite3_errmsg (sqlite));
8245 				  goto abort;
8246 			      }
8247 			    inserted++;
8248 			    pt = pt->Next;
8249 			}
8250 		      ln = g->FirstLinestring;
8251 		      while (ln)
8252 			{
8253 			    /* separating Linestrings */
8254 			    outGeom = elemGeomFromLinestring (ln, g->Srid);
8255 			    sqlite3_reset (stmt_out);
8256 			    sqlite3_clear_bindings (stmt_out);
8257 			    sqlite3_bind_int64 (stmt_out, 1, id);
8258 			    if (!outGeom)
8259 				sqlite3_bind_null (stmt_out, geom_idx + 2);
8260 			    else
8261 			      {
8262 				  unsigned char *blob;
8263 				  int size;
8264 				  gaiaToSpatiaLiteBlobWkb (outGeom, &blob,
8265 							   &size);
8266 				  sqlite3_bind_blob (stmt_out, geom_idx + 2,
8267 						     blob, size, free);
8268 				  gaiaFreeGeomColl (outGeom);
8269 			      }
8270 
8271 			    for (i = 0; i < n_columns; i++)
8272 			      {
8273 				  int type = sqlite3_column_type (stmt_in, i);
8274 				  if (i == geom_idx)
8275 				      continue;
8276 				  switch (type)
8277 				    {
8278 				    case SQLITE_INTEGER:
8279 					sqlite3_bind_int64 (stmt_out, i + 2,
8280 							    sqlite3_column_int64
8281 							    (stmt_in, i));
8282 					break;
8283 				    case SQLITE_FLOAT:
8284 					sqlite3_bind_double (stmt_out, i + 2,
8285 							     sqlite3_column_double
8286 							     (stmt_in, i));
8287 					break;
8288 				    case SQLITE_TEXT:
8289 					sqlite3_bind_text (stmt_out, i + 2,
8290 							   (const char *)
8291 							   sqlite3_column_text
8292 							   (stmt_in, i),
8293 							   sqlite3_column_bytes
8294 							   (stmt_in, i),
8295 							   SQLITE_STATIC);
8296 					break;
8297 				    case SQLITE_BLOB:
8298 					sqlite3_bind_blob (stmt_out, i + 2,
8299 							   sqlite3_column_blob
8300 							   (stmt_in, i),
8301 							   sqlite3_column_bytes
8302 							   (stmt_in, i),
8303 							   SQLITE_STATIC);
8304 					break;
8305 				    case SQLITE_NULL:
8306 				    default:
8307 					sqlite3_bind_null (stmt_out, i + 2);
8308 					break;
8309 				    };
8310 			      }
8311 
8312 			    ret = sqlite3_step (stmt_out);
8313 			    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
8314 				;
8315 			    else
8316 			      {
8317 				  spatialite_e ("[OUT]step error: %s\n",
8318 						sqlite3_errmsg (sqlite));
8319 				  goto abort;
8320 			      }
8321 			    inserted++;
8322 			    ln = ln->Next;
8323 			}
8324 		      pg = g->FirstPolygon;
8325 		      while (pg)
8326 			{
8327 			    /* separating Polygons */
8328 			    outGeom = elemGeomFromPolygon (pg, g->Srid);
8329 			    sqlite3_reset (stmt_out);
8330 			    sqlite3_clear_bindings (stmt_out);
8331 			    sqlite3_bind_int64 (stmt_out, 1, id);
8332 			    if (!outGeom)
8333 				sqlite3_bind_null (stmt_out, geom_idx + 2);
8334 			    else
8335 			      {
8336 				  unsigned char *blob;
8337 				  int size;
8338 				  gaiaToSpatiaLiteBlobWkb (outGeom, &blob,
8339 							   &size);
8340 				  sqlite3_bind_blob (stmt_out, geom_idx + 2,
8341 						     blob, size, free);
8342 				  gaiaFreeGeomColl (outGeom);
8343 			      }
8344 
8345 			    for (i = 0; i < n_columns; i++)
8346 			      {
8347 				  int type = sqlite3_column_type (stmt_in, i);
8348 				  if (i == geom_idx)
8349 				      continue;
8350 				  switch (type)
8351 				    {
8352 				    case SQLITE_INTEGER:
8353 					sqlite3_bind_int64 (stmt_out, i + 2,
8354 							    sqlite3_column_int64
8355 							    (stmt_in, i));
8356 					break;
8357 				    case SQLITE_FLOAT:
8358 					sqlite3_bind_double (stmt_out, i + 2,
8359 							     sqlite3_column_double
8360 							     (stmt_in, i));
8361 					break;
8362 				    case SQLITE_TEXT:
8363 					sqlite3_bind_text (stmt_out, i + 2,
8364 							   (const char *)
8365 							   sqlite3_column_text
8366 							   (stmt_in, i),
8367 							   sqlite3_column_bytes
8368 							   (stmt_in, i),
8369 							   SQLITE_STATIC);
8370 					break;
8371 				    case SQLITE_BLOB:
8372 					sqlite3_bind_blob (stmt_out, i + 2,
8373 							   sqlite3_column_blob
8374 							   (stmt_in, i),
8375 							   sqlite3_column_bytes
8376 							   (stmt_in, i),
8377 							   SQLITE_STATIC);
8378 					break;
8379 				    case SQLITE_NULL:
8380 				    default:
8381 					sqlite3_bind_null (stmt_out, i + 2);
8382 					break;
8383 				    };
8384 			      }
8385 
8386 			    ret = sqlite3_step (stmt_out);
8387 			    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
8388 				;
8389 			    else
8390 			      {
8391 				  spatialite_e ("[OUT]step error: %s\n",
8392 						sqlite3_errmsg (sqlite));
8393 				  goto abort;
8394 			      }
8395 			    inserted++;
8396 			    pg = pg->Next;
8397 			}
8398 		      gaiaFreeGeomColl (g);
8399 		  }
8400 		id++;
8401 	    }
8402 	  else
8403 	    {
8404 		spatialite_e ("[IN]step error: %s\n", sqlite3_errmsg (sqlite));
8405 		goto abort;
8406 	    }
8407       }
8408     sqlite3_finalize (stmt_in);
8409     sqlite3_finalize (stmt_out);
8410 
8411     if (transaction)
8412       {
8413 	  /* commits the transaction */
8414 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
8415 	  if (ret != SQLITE_OK)
8416 	    {
8417 		spatialite_e ("SQL error: %s\n", errMsg);
8418 		sqlite3_free (errMsg);
8419 		goto abort;
8420 	    }
8421       }
8422     *xrows = inserted;
8423     return;
8424 
8425   abort:
8426     if (stmt_in)
8427 	sqlite3_finalize (stmt_in);
8428     if (stmt_out)
8429 	sqlite3_finalize (stmt_out);
8430 
8431     if (transaction)
8432       {
8433 	  /* rolling bacj the transaction */
8434 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
8435 	  if (ret != SQLITE_OK)
8436 	    {
8437 		spatialite_e ("SQL error: %s\n", errMsg);
8438 		sqlite3_free (errMsg);
8439 	    }
8440       }
8441     *xrows = 0;
8442 }
8443 
8444 #ifndef OMIT_FREEXL		/* including FreeXL */
8445 
8446 SPATIALITE_DECLARE int
load_XL(sqlite3 * sqlite,const char * path,const char * table,unsigned int worksheetIndex,int first_titles,unsigned int * rows,char * err_msg)8447 load_XL (sqlite3 * sqlite, const char *path, const char *table,
8448 	 unsigned int worksheetIndex, int first_titles, unsigned int *rows,
8449 	 char *err_msg)
8450 {
8451 /* loading an XL spreadsheet as a new DB table */
8452     sqlite3_stmt *stmt;
8453     unsigned int current_row;
8454     int ret;
8455     char *errMsg = NULL;
8456     char *xname;
8457     char *dummy;
8458     char *xdummy;
8459     char *sql;
8460     int sqlError = 0;
8461     const void *xl_handle;
8462     unsigned int info;
8463     unsigned short columns;
8464     unsigned short col;
8465     gaiaOutBuffer sql_statement;
8466     FreeXL_CellValue cell;
8467     int already_exists = 0;
8468 
8469     *rows = 0;
8470 /* checking if TABLE already exists */
8471     sql =
8472 	sqlite3_mprintf ("SELECT name FROM sqlite_master WHERE type = 'table' "
8473 			 "AND Lower(name) = Lower(%Q)", table);
8474     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
8475     sqlite3_free (sql);
8476     if (ret != SQLITE_OK)
8477       {
8478 	  if (!err_msg)
8479 	      spatialite_e ("load XL error: <%s>\n", sqlite3_errmsg (sqlite));
8480 	  else
8481 	      sprintf (err_msg, "load XL error: <%s>\n",
8482 		       sqlite3_errmsg (sqlite));
8483 	  return 0;
8484       }
8485     while (1)
8486       {
8487 	  /* scrolling the result set */
8488 	  ret = sqlite3_step (stmt);
8489 	  if (ret == SQLITE_DONE)
8490 	      break;		/* end of result set */
8491 	  if (ret == SQLITE_ROW)
8492 	      already_exists = 1;
8493 	  else
8494 	    {
8495 		spatialite_e ("load XL error: <%s>\n", sqlite3_errmsg (sqlite));
8496 		break;
8497 	    }
8498       }
8499     sqlite3_finalize (stmt);
8500     if (already_exists)
8501       {
8502 	  if (!err_msg)
8503 	      spatialite_e ("load XL error: table '%s' already exists\n",
8504 			    table);
8505 	  else
8506 	      sprintf (err_msg, "load XL error: table '%s' already exists\n",
8507 		       table);
8508 	  return 0;
8509       }
8510 /* opening the .XLS file [Workbook] */
8511     ret = freexl_open (path, &xl_handle);
8512     if (ret != FREEXL_OK)
8513 	goto error;
8514 /* checking if Password protected */
8515     ret = freexl_get_info (xl_handle, FREEXL_BIFF_PASSWORD, &info);
8516     if (ret != FREEXL_OK)
8517 	goto error;
8518     if (info != FREEXL_BIFF_PLAIN)
8519 	goto error;
8520 /* Worksheet entries */
8521     ret = freexl_get_info (xl_handle, FREEXL_BIFF_SHEET_COUNT, &info);
8522     if (ret != FREEXL_OK)
8523 	goto error;
8524     if (info == 0)
8525 	goto error;
8526     if (worksheetIndex < info)
8527 	;
8528     else
8529 	goto error;
8530     ret =
8531 	freexl_select_active_worksheet (xl_handle,
8532 					(unsigned short) worksheetIndex);
8533     if (ret != FREEXL_OK)
8534 	goto error;
8535     ret = freexl_worksheet_dimensions (xl_handle, rows, &columns);
8536     if (ret != FREEXL_OK)
8537 	goto error;
8538 /* starting a transaction */
8539     ret = sqlite3_exec (sqlite, "BEGIN", NULL, 0, &errMsg);
8540     if (ret != SQLITE_OK)
8541       {
8542 	  spatialite_e ("load XL error: %s\n", errMsg);
8543 	  sqlite3_free (errMsg);
8544 	  sqlError = 1;
8545 	  goto clean_up;
8546       }
8547 /* creating the Table */
8548     gaiaOutBufferInitialize (&sql_statement);
8549     xname = gaiaDoubleQuotedSql (table);
8550     sql = sqlite3_mprintf ("CREATE TABLE \"%s\"", xname);
8551     free (xname);
8552     gaiaAppendToOutBuffer (&sql_statement, sql);
8553     sqlite3_free (sql);
8554     gaiaAppendToOutBuffer (&sql_statement,
8555 			   " (\nPK_UID INTEGER PRIMARY KEY AUTOINCREMENT");
8556     for (col = 0; col < columns; col++)
8557       {
8558 	  if (first_titles)
8559 	    {
8560 		/* fetching column names */
8561 		for (col = 0; col < columns; col++)
8562 		  {
8563 		      ret = freexl_get_cell_value (xl_handle, 0, col, &cell);
8564 		      if (ret != FREEXL_OK)
8565 			  dummy = sqlite3_mprintf ("col_%d", col);
8566 		      else
8567 			{
8568 			    if (cell.type == FREEXL_CELL_INT)
8569 				dummy =
8570 				    sqlite3_mprintf ("%d",
8571 						     cell.value.int_value);
8572 			    else if (cell.type == FREEXL_CELL_DOUBLE)
8573 				dummy = sqlite3_mprintf ("%1.2f ",
8574 							 cell.
8575 							 value.double_value);
8576 			    else if (cell.type == FREEXL_CELL_TEXT
8577 				     || cell.type == FREEXL_CELL_SST_TEXT
8578 				     || cell.type == FREEXL_CELL_DATE
8579 				     || cell.type == FREEXL_CELL_DATETIME
8580 				     || cell.type == FREEXL_CELL_TIME)
8581 			      {
8582 				  int len = strlen (cell.value.text_value);
8583 				  if (len < 256)
8584 				      dummy =
8585 					  sqlite3_mprintf ("%s",
8586 							   cell.
8587 							   value.text_value);
8588 				  else
8589 				      dummy = sqlite3_mprintf ("col_%d", col);
8590 			      }
8591 			    else
8592 				dummy = sqlite3_mprintf ("col_%d", col);
8593 			}
8594 		      xdummy = gaiaDoubleQuotedSql (dummy);
8595 		      sqlite3_free (dummy);
8596 		      sql = sqlite3_mprintf (", \"%s\"", xdummy);
8597 		      free (xdummy);
8598 		      gaiaAppendToOutBuffer (&sql_statement, sql);
8599 		      sqlite3_free (sql);
8600 		  }
8601 	    }
8602 	  else
8603 	    {
8604 		/* setting default column names */
8605 		for (col = 0; col < columns; col++)
8606 		  {
8607 		      dummy = sqlite3_mprintf ("col_%d", col);
8608 		      xdummy = gaiaDoubleQuotedSql (dummy);
8609 		      sqlite3_free (dummy);
8610 		      sql = sqlite3_mprintf (", \"%s\"", xdummy);
8611 		      free (xdummy);
8612 		      gaiaAppendToOutBuffer (&sql_statement, sql);
8613 		      sqlite3_free (sql);
8614 		  }
8615 	    }
8616       }
8617     gaiaAppendToOutBuffer (&sql_statement, ")");
8618     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
8619       {
8620 	  ret = sqlite3_exec (sqlite, sql_statement.Buffer, NULL, 0, &errMsg);
8621 	  gaiaOutBufferReset (&sql_statement);
8622 	  if (ret != SQLITE_OK)
8623 	    {
8624 		spatialite_e ("load XL error: %s\n", errMsg);
8625 		sqlite3_free (errMsg);
8626 		sqlError = 1;
8627 		goto clean_up;
8628 	    }
8629       }
8630 /* preparing the INSERT INTO parameterized statement */
8631     gaiaOutBufferReset (&sql_statement);
8632     xname = gaiaDoubleQuotedSql (table);
8633     sql = sqlite3_mprintf ("INSERT INTO \"%s\" (PK_UID", xname);
8634     free (xname);
8635     gaiaAppendToOutBuffer (&sql_statement, sql);
8636     sqlite3_free (sql);
8637     for (col = 0; col < columns; col++)
8638       {
8639 	  if (first_titles)
8640 	    {
8641 		ret = freexl_get_cell_value (xl_handle, 0, col, &cell);
8642 		if (ret != FREEXL_OK)
8643 		    dummy = sqlite3_mprintf ("col_%d", col);
8644 		else
8645 		  {
8646 		      if (cell.type == FREEXL_CELL_INT)
8647 			  dummy = sqlite3_mprintf ("%d", cell.value.int_value);
8648 		      else if (cell.type == FREEXL_CELL_DOUBLE)
8649 			  dummy =
8650 			      sqlite3_mprintf ("%1.2f",
8651 					       cell.value.double_value);
8652 		      else if (cell.type == FREEXL_CELL_TEXT
8653 			       || cell.type == FREEXL_CELL_SST_TEXT
8654 			       || cell.type == FREEXL_CELL_DATE
8655 			       || cell.type == FREEXL_CELL_DATETIME
8656 			       || cell.type == FREEXL_CELL_TIME)
8657 			{
8658 			    int len = strlen (cell.value.text_value);
8659 			    if (len < 256)
8660 				dummy =
8661 				    sqlite3_mprintf ("%s",
8662 						     cell.value.text_value);
8663 			    else
8664 				dummy = sqlite3_mprintf ("col_%d", col);
8665 			}
8666 		      else
8667 			  dummy = sqlite3_mprintf ("col_%d", col);
8668 		  }
8669 		xdummy = gaiaDoubleQuotedSql (dummy);
8670 		sqlite3_free (dummy);
8671 		sql = sqlite3_mprintf (", \"%s\"", xdummy);
8672 		free (xdummy);
8673 		gaiaAppendToOutBuffer (&sql_statement, sql);
8674 		sqlite3_free (sql);
8675 	    }
8676 	  else
8677 	    {
8678 		/* setting default column names  */
8679 		dummy = sqlite3_mprintf ("col_%d", col);
8680 		xdummy = gaiaDoubleQuotedSql (dummy);
8681 		sqlite3_free (dummy);
8682 		sql = sqlite3_mprintf (", \"%s\"", xdummy);
8683 		free (xdummy);
8684 		gaiaAppendToOutBuffer (&sql_statement, sql);
8685 		sqlite3_free (sql);
8686 	    }
8687       }
8688     gaiaAppendToOutBuffer (&sql_statement, ")\nVALUES (NULL");
8689     for (col = 0; col < columns; col++)
8690       {
8691 	  /* column values */
8692 	  gaiaAppendToOutBuffer (&sql_statement, ", ?");
8693       }
8694     gaiaAppendToOutBuffer (&sql_statement, ")");
8695     if (sql_statement.Error == 0 && sql_statement.Buffer != NULL)
8696       {
8697 	  ret =
8698 	      sqlite3_prepare_v2 (sqlite, sql_statement.Buffer,
8699 				  strlen (sql_statement.Buffer), &stmt, NULL);
8700 	  gaiaOutBufferReset (&sql_statement);
8701 	  if (ret != SQLITE_OK)
8702 	    {
8703 		spatialite_e ("load XL error: %s\n", sqlite3_errmsg (sqlite));
8704 		sqlError = 1;
8705 		goto clean_up;
8706 	    }
8707       }
8708     if (first_titles)
8709 	current_row = 1;
8710     else
8711 	current_row = 0;
8712     while (current_row < *rows)
8713       {
8714 	  /* binding query params */
8715 	  sqlite3_reset (stmt);
8716 	  sqlite3_clear_bindings (stmt);
8717 	  for (col = 0; col < columns; col++)
8718 	    {
8719 		/* column values */
8720 		ret =
8721 		    freexl_get_cell_value (xl_handle, current_row, col, &cell);
8722 		if (ret != FREEXL_OK)
8723 		    sqlite3_bind_null (stmt, col + 1);
8724 		else
8725 		  {
8726 		      switch (cell.type)
8727 			{
8728 			case FREEXL_CELL_INT:
8729 			    sqlite3_bind_int (stmt, col + 1,
8730 					      cell.value.int_value);
8731 			    break;
8732 			case FREEXL_CELL_DOUBLE:
8733 			    sqlite3_bind_double (stmt, col + 1,
8734 						 cell.value.double_value);
8735 			    break;
8736 			case FREEXL_CELL_TEXT:
8737 			case FREEXL_CELL_SST_TEXT:
8738 			case FREEXL_CELL_DATE:
8739 			case FREEXL_CELL_DATETIME:
8740 			case FREEXL_CELL_TIME:
8741 			    sqlite3_bind_text (stmt, col + 1,
8742 					       cell.value.text_value,
8743 					       strlen (cell.value.text_value),
8744 					       SQLITE_STATIC);
8745 			    break;
8746 			default:
8747 			    sqlite3_bind_null (stmt, col + 1);
8748 			    break;
8749 			};
8750 		  }
8751 	    }
8752 	  ret = sqlite3_step (stmt);
8753 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
8754 	      ;
8755 	  else
8756 	    {
8757 		spatialite_e ("load XL error: %s\n", sqlite3_errmsg (sqlite));
8758 		sqlite3_finalize (stmt);
8759 		sqlError = 1;
8760 		goto clean_up;
8761 	    }
8762 	  current_row++;
8763       }
8764     sqlite3_finalize (stmt);
8765   clean_up:
8766     if (sqlError)
8767       {
8768 	  /* some error occurred - ROLLBACK */
8769 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, 0, &errMsg);
8770 	  if (ret != SQLITE_OK)
8771 	    {
8772 		spatialite_e ("load XL error: %s\n", errMsg);
8773 		sqlite3_free (errMsg);
8774 	    }
8775 	  spatialite_e
8776 	      ("XL not loaded\n\n\na ROLLBACK was automatically performed\n");
8777       }
8778     else
8779       {
8780 	  /* ok - confirming pending transaction - COMMIT */
8781 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, 0, &errMsg);
8782 	  if (ret != SQLITE_OK)
8783 	    {
8784 		if (!err_msg)
8785 		    spatialite_e ("load XL error: %s\n", errMsg);
8786 		else
8787 		    sprintf (err_msg, "load XL error: %s\n", errMsg);
8788 		sqlite3_free (errMsg);
8789 		return 0;
8790 	    }
8791 	  if (first_titles)
8792 	      *rows = *rows - 1;	/* allow for header row */
8793 	  spatialite_e ("XL loaded\n\n%d inserted rows\n", *rows);
8794       }
8795     freexl_close (xl_handle);
8796     return 1;
8797 
8798   error:
8799     freexl_close (xl_handle);
8800     if (!err_msg)
8801 	spatialite_e ("XL datasource '%s' is not valid\n", path);
8802     else
8803 	sprintf (err_msg, "XL datasource '%s' is not valid\n", path);
8804     *rows = 0;
8805     return 0;
8806 }
8807 
8808 #endif /* FreeXL enabled/disabled */
8809