~ubuntu-branches/ubuntu/wily/spatialite/wily-proposed

« back to all changes in this revision

Viewing changes to src/spatialite/table_cloner.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-07-14 11:57:46 UTC
  • mfrom: (16.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20150714115746-e2iljfmb5sq7o5hh
Tags: 4.3.0-1
Move from experimental to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 table_cloner.c -- Cloning a Table
 
4
 
 
5
 version 4.3, 2015 June 29
 
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-2015
 
28
the Initial Developer. All Rights Reserved.
 
29
 
 
30
Contributor(s):
 
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
#include <stdlib.h>
 
47
#include <stdio.h>
 
48
#include <string.h>
 
49
 
 
50
#if defined(_WIN32) && !defined(__MINGW32__)
 
51
#include "config-msvc.h"
 
52
#else
 
53
#include "config.h"
 
54
#endif
 
55
 
 
56
#include <spatialite/sqlite.h>
 
57
#include <spatialite/debug.h>
 
58
 
 
59
#include <spatialite.h>
 
60
#include <spatialite_private.h>
 
61
#include <spatialite/gaiaaux.h>
 
62
 
 
63
#ifdef _WIN32
 
64
#define strcasecmp      _stricmp
 
65
#define strncasecmp     _strnicmp
 
66
#endif /* not WIN32 */
 
67
 
 
68
struct aux_geometry
 
69
{
 
70
/* a Geometry column object */
 
71
    int type;
 
72
    int dims;
 
73
    int srid;
 
74
    int spatial_index;
 
75
    int cast2multi;
 
76
    int already_existing;
 
77
};
 
78
 
 
79
struct aux_trigger
 
80
{
 
81
/* a Trigger object */
 
82
    char *name;
 
83
    char *sql;
 
84
    int already_existing;
 
85
    struct aux_trigger *next;
 
86
};
 
87
 
 
88
struct aux_fk_columns
 
89
{
 
90
/* a Foreign Key Columns object */
 
91
    char *from;
 
92
    char *to;
 
93
    struct aux_fk_columns *next;
 
94
};
 
95
 
 
96
struct aux_foreign_key
 
97
{
 
98
/* a Foreign Key object */
 
99
    int id;
 
100
    char *name;
 
101
    char *references;
 
102
    char *on_update;
 
103
    char *on_delete;
 
104
    char *match;
 
105
    struct aux_fk_columns *first;
 
106
    struct aux_fk_columns *last;
 
107
    struct aux_foreign_key *next;
 
108
};
 
109
 
 
110
struct aux_index_column
 
111
{
 
112
/* an Index Column object */
 
113
    char *name;
 
114
    struct aux_index_column *next;
 
115
};
 
116
 
 
117
struct aux_index
 
118
{
 
119
/* a Table Index object */
 
120
    char *name;
 
121
    int unique;
 
122
    struct aux_index_column *first;
 
123
    struct aux_index_column *last;
 
124
    struct aux_index *next;
 
125
};
 
126
 
 
127
struct aux_column
 
128
{
 
129
/* a Table Column object */
 
130
    char *name;
 
131
    char *type;
 
132
    int notnull;
 
133
    char *deflt;
 
134
    int pk;
 
135
    int fk;
 
136
    int idx;
 
137
    struct aux_geometry *geometry;
 
138
    int ignore;
 
139
    int already_existing;
 
140
    int mismatching;
 
141
    struct aux_column *next;
 
142
};
 
143
 
 
144
struct aux_pk_column
 
145
{
 
146
/* Primary Key Columns */
 
147
    struct aux_column *column;
 
148
    struct aux_pk_column *next;
 
149
};
 
150
 
 
151
struct aux_cloner
 
152
{
 
153
/* the main Cloner object */
 
154
    sqlite3 *sqlite;
 
155
    char *db_prefix;
 
156
    char *in_table;
 
157
    char *out_table;
 
158
    struct aux_column *first_col;
 
159
    struct aux_column *last_col;
 
160
    struct aux_pk_column *first_pk;
 
161
    struct aux_pk_column *last_pk;
 
162
    struct aux_index *first_idx;
 
163
    struct aux_index *last_idx;
 
164
    struct aux_foreign_key *first_fk;
 
165
    struct aux_foreign_key *last_fk;
 
166
    struct aux_trigger *first_trigger;
 
167
    struct aux_trigger *last_trigger;
 
168
    struct aux_pk_column **sorted_pks;
 
169
    int pk_count;
 
170
    int autoincrement;
 
171
    int resequence;
 
172
    int with_fks;
 
173
    int with_triggers;
 
174
    int append;
 
175
    int already_existing;
 
176
};
 
177
 
 
178
static int
 
179
create_column (sqlite3 * sqlite, const char *table, struct aux_column *column)
 
180
{
 
181
/* creating a further ordinary Column */
 
182
    char *sql;
 
183
    char *err_msg = NULL;
 
184
    int ret;
 
185
    char *xtable;
 
186
    char *xcolumn;
 
187
 
 
188
    xtable = gaiaDoubleQuotedSql (table);
 
189
    xcolumn = gaiaDoubleQuotedSql (column->name);
 
190
    if (column->notnull)
 
191
      {
 
192
          if (column->deflt != NULL)
 
193
              sql = sqlite3_mprintf ("ALTER TABLE main.\"%s\" "
 
194
                                     "ADD COLUMN \"%s\" %s NOT NULL DEFAULT %s",
 
195
                                     xtable, xcolumn, column->type,
 
196
                                     column->deflt);
 
197
          else
 
198
              sql = sqlite3_mprintf ("ALTER TABLE main.\"%s\" "
 
199
                                     "ADD COLUMN \"%s\" %s NOT NULL", xtable,
 
200
                                     xcolumn, column->type);
 
201
      }
 
202
    else
 
203
      {
 
204
          if (column->deflt != NULL)
 
205
              sql = sqlite3_mprintf ("ALTER TABLE main.\"%s\" "
 
206
                                     "ADD COLUMN \"%s\" %s DEFAULT %s", xtable,
 
207
                                     xcolumn, column->type, column->deflt);
 
208
          else
 
209
              sql = sqlite3_mprintf ("ALTER TABLE main.\"%s\" "
 
210
                                     "ADD COLUMN \"%s\" %s", xtable, xcolumn,
 
211
                                     column->type);
 
212
      }
 
213
    free (xtable);
 
214
    free (xcolumn);
 
215
    ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
 
216
    if (ret != SQLITE_OK)
 
217
      {
 
218
          spatialite_e ("ALTER TABLE ADD COLUMN error: %s\n", err_msg);
 
219
          sqlite3_free (err_msg);
 
220
          return 0;
 
221
      }
 
222
    return 1;
 
223
}
 
224
 
 
225
static int
 
226
create_geometry (sqlite3 * sqlite, const char *table, struct aux_column *column)
 
227
{
 
228
/* creating a further Geometry Column */
 
229
    char *sql;
 
230
    char *err_msg = NULL;
 
231
    int ret;
 
232
    char *xtable;
 
233
    char *xcolumn;
 
234
    const char *type = "GEOMETRY";
 
235
    const char *dims = "XY";
 
236
    int gtype = column->geometry->type;
 
237
 
 
238
    if (column->geometry->cast2multi)
 
239
      {
 
240
          /* promoting to the corresponding MultiType */
 
241
          switch (column->geometry->type)
 
242
            {
 
243
            case 1:
 
244
                gtype = 4;
 
245
                break;
 
246
            case 1001:
 
247
                gtype = 1004;
 
248
                break;
 
249
            case 2001:
 
250
                gtype = 2004;
 
251
                break;
 
252
            case 3001:
 
253
                gtype = 3004;
 
254
                break;
 
255
            case 2:
 
256
                gtype = 5;
 
257
                break;
 
258
            case 1002:
 
259
                gtype = 1005;
 
260
                break;
 
261
            case 2002:
 
262
                gtype = 2005;
 
263
                break;
 
264
            case 3002:
 
265
                gtype = 3005;
 
266
                break;
 
267
            case 3:
 
268
                gtype = 6;
 
269
                break;
 
270
            case 1003:
 
271
                gtype = 1006;
 
272
                break;
 
273
            case 2003:
 
274
                gtype = 2006;
 
275
                break;
 
276
            case 3003:
 
277
                gtype = 3006;
 
278
                break;
 
279
            };
 
280
      }
 
281
 
 
282
    switch (gtype)
 
283
      {
 
284
      case 1:
 
285
          type = "POINT";
 
286
          dims = "XY";
 
287
          break;
 
288
      case 1001:
 
289
          type = "POINT";
 
290
          dims = "XYZ";
 
291
          break;
 
292
      case 2001:
 
293
          type = "POINT";
 
294
          dims = "XYM";
 
295
          break;
 
296
      case 3001:
 
297
          type = "POINT";
 
298
          dims = "XYZM";
 
299
          break;
 
300
      case 2:
 
301
          type = "LINESTRING";
 
302
          dims = "XY";
 
303
          break;
 
304
      case 1002:
 
305
          type = "LINESTRING";
 
306
          dims = "XYZ";
 
307
          break;
 
308
      case 2002:
 
309
          type = "LINESTRING";
 
310
          dims = "XYM";
 
311
          break;
 
312
      case 3002:
 
313
          type = "LINESTRING";
 
314
          dims = "XYZM";
 
315
          break;
 
316
      case 3:
 
317
          type = "POLYGON";
 
318
          dims = "XY";
 
319
          break;
 
320
      case 1003:
 
321
          type = "POLYGON";
 
322
          dims = "XYZ";
 
323
          break;
 
324
      case 2003:
 
325
          type = "POLYGON";
 
326
          dims = "XYM";
 
327
          break;
 
328
      case 3003:
 
329
          type = "POLYGON";
 
330
          dims = "XYZM";
 
331
          break;
 
332
      case 4:
 
333
          type = "MULTIPOINT";
 
334
          dims = "XY";
 
335
          break;
 
336
      case 1004:
 
337
          type = "MULTIPOINT";
 
338
          dims = "XYZ";
 
339
          break;
 
340
      case 2004:
 
341
          type = "MULTIPOINT";
 
342
          dims = "XYM";
 
343
          break;
 
344
      case 3004:
 
345
          type = "MULTIPOINT";
 
346
          dims = "XYZM";
 
347
          break;
 
348
      case 5:
 
349
          type = "MULTILINESTRING";
 
350
          dims = "XY";
 
351
          break;
 
352
      case 1005:
 
353
          type = "MULTILINESTRING";
 
354
          dims = "XYZ";
 
355
          break;
 
356
      case 2005:
 
357
          type = "MULTILINESTRING";
 
358
          dims = "XYM";
 
359
          break;
 
360
      case 3005:
 
361
          type = "MULTILINESTRING";
 
362
          dims = "XYZM";
 
363
          break;
 
364
      case 6:
 
365
          type = "MULTIPOLYGON";
 
366
          dims = "XY";
 
367
          break;
 
368
      case 1006:
 
369
          type = "MULTIPOLYGON";
 
370
          dims = "XYZ";
 
371
          break;
 
372
      case 2006:
 
373
          type = "MULTIPOLYGON";
 
374
          dims = "XYM";
 
375
          break;
 
376
      case 3006:
 
377
          type = "MULTIPOLYGON";
 
378
          dims = "XYZM";
 
379
          break;
 
380
      case 7:
 
381
          type = "GEOMETRYCOLLECTION";
 
382
          dims = "XY";
 
383
          break;
 
384
      case 1007:
 
385
          type = "GEOMETRYCOLLECTION";
 
386
          dims = "XYZ";
 
387
          break;
 
388
      case 2007:
 
389
          type = "GEOMETRYCOLLECTION";
 
390
          dims = "XYM";
 
391
          break;
 
392
      case 3007:
 
393
          type = "GEOMETRYCOLLECTION";
 
394
          dims = "XYZM";
 
395
          break;
 
396
      case 0:
 
397
          type = "GEOMETRY";
 
398
          dims = "XY";
 
399
          break;
 
400
      case 1000:
 
401
          type = "GEOMETRY";
 
402
          dims = "XYZ";
 
403
          break;
 
404
      case 2000:
 
405
          type = "GEOMETRY";
 
406
          dims = "XYM";
 
407
          break;
 
408
      case 3000:
 
409
          type = "GEOMETRY";
 
410
          dims = "XYZM";
 
411
          break;
 
412
      };
 
413
 
 
414
    xtable = gaiaDoubleQuotedSql (table);
 
415
    xcolumn = gaiaDoubleQuotedSql (column->name);
 
416
    if (column->notnull)
 
417
      {
 
418
          sql = sqlite3_mprintf ("SELECT AddGeometryColumn(Lower(%Q), "
 
419
                                 "Lower(%Q), %d, %Q, %Q, 1)", xtable, xcolumn,
 
420
                                 column->geometry->srid, type, dims);
 
421
      }
 
422
    else
 
423
      {
 
424
          sql = sqlite3_mprintf ("SELECT AddGeometryColumn(Lower(%Q), "
 
425
                                 "Lower(%Q), %d, %Q, %Q)", xtable, xcolumn,
 
426
                                 column->geometry->srid, type, dims);
 
427
      }
 
428
    free (xtable);
 
429
    free (xcolumn);
 
430
    ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
 
431
    if (ret != SQLITE_OK)
 
432
      {
 
433
          spatialite_e ("ADD GEOMETRY COLUMN error: %s\n", err_msg);
 
434
          sqlite3_free (err_msg);
 
435
          return 0;
 
436
      }
 
437
 
 
438
    if (column->geometry->spatial_index)
 
439
      {
 
440
          /* creating the corresponding Spatial Index */
 
441
          xtable = gaiaDoubleQuotedSql (table);
 
442
          xcolumn = gaiaDoubleQuotedSql (column->name);
 
443
          sql = sqlite3_mprintf ("SELECT CreateSpatialIndex("
 
444
                                 "Lower(%Q), Lower(%Q))", xtable, xcolumn);
 
445
          free (xtable);
 
446
          free (xcolumn);
 
447
          ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
 
448
          if (ret != SQLITE_OK)
 
449
            {
 
450
                spatialite_e ("CREATE SPATIAL INDEX error: %s\n", err_msg);
 
451
                sqlite3_free (err_msg);
 
452
                return 0;
 
453
            }
 
454
      }
 
455
    return 1;
 
456
}
 
457
 
 
458
static int
 
459
upgrade_output_table (struct aux_cloner *cloner)
 
460
{
 
461
/* creating any new Column required by APPEND */
 
462
    struct aux_column *column = cloner->first_col;
 
463
    while (column != NULL)
 
464
      {
 
465
          if (column->ignore)
 
466
            {
 
467
                /* skipping columns marked to be ignored */
 
468
                column = column->next;
 
469
                continue;
 
470
            }
 
471
          if (column->already_existing == 0)
 
472
            {
 
473
                if (column->geometry != NULL)
 
474
                  {
 
475
                      /* creating a Geometry */
 
476
                      if (!create_geometry
 
477
                          (cloner->sqlite, cloner->out_table, column))
 
478
                        {
 
479
                            spatialite_e
 
480
                                ("CloneTable: unable to ADD Geometry COLUMN \"%s\" on Table \"%s\"\n",
 
481
                                 column->name, cloner->out_table);
 
482
                            return 0;
 
483
                        }
 
484
                  }
 
485
                else
 
486
                  {
 
487
                      /* creating an ordinary Column */
 
488
                      if (!create_column
 
489
                          (cloner->sqlite, cloner->out_table, column))
 
490
                        {
 
491
                            spatialite_e
 
492
                                ("CloneTable: unable to ADD COLUMN \"%s\" on Table \"%s\"\n",
 
493
                                 column->name, cloner->out_table);
 
494
                            return 0;
 
495
                        }
 
496
                  }
 
497
            }
 
498
          column = column->next;
 
499
      }
 
500
    return 1;
 
501
}
 
502
 
 
503
static void
 
504
sort_pk_columns (struct aux_cloner *cloner)
 
505
{
 
506
/* sorting the PK columns (if required) */
 
507
    struct aux_pk_column *ppk;
 
508
    int cnt;
 
509
    int ok;
 
510
    if (cloner->pk_count <= 1)
 
511
        return;
 
512
    cloner->sorted_pks =
 
513
        malloc (sizeof (struct aux_pk_column *) * cloner->pk_count);
 
514
    cnt = 0;
 
515
    ppk = cloner->first_pk;
 
516
    while (ppk != NULL)
 
517
      {
 
518
          /* copying pointers to PK cols */
 
519
          *(cloner->sorted_pks + cnt++) = ppk;
 
520
          ppk = ppk->next;
 
521
      }
 
522
    ok = 1;
 
523
    while (ok)
 
524
      {
 
525
          /* bubble sorting */
 
526
          ok = 0;
 
527
          for (cnt = 1; cnt < cloner->pk_count; cnt++)
 
528
            {
 
529
                struct aux_pk_column *ppk1 = *(cloner->sorted_pks + cnt - 1);
 
530
                ppk = *(cloner->sorted_pks + cnt);
 
531
                if (ppk1->column->pk > ppk->column->pk)
 
532
                  {
 
533
                      /* swapping */
 
534
                      *(cloner->sorted_pks + cnt - 1) = ppk;
 
535
                      *(cloner->sorted_pks + cnt) = ppk1;
 
536
                      ok = 1;
 
537
                  }
 
538
            }
 
539
      }
 
540
}
 
541
 
 
542
static void
 
543
adjust_ignore (struct aux_cloner *cloner)
 
544
{
 
545
/* adjusting Ignore columns */
 
546
    struct aux_column *column = cloner->first_col;
 
547
    while (column != NULL)
 
548
      {
 
549
          if (column->ignore)
 
550
            {
 
551
                if (column->pk)
 
552
                    column->ignore = 0;
 
553
                if (column->fk && cloner->with_fks)
 
554
                    column->ignore = 0;
 
555
                if (column->idx)
 
556
                    column->ignore = 0;
 
557
            }
 
558
          column = column->next;
 
559
      }
 
560
}
 
561
 
 
562
static const char *
 
563
get_pk_column (struct aux_cloner *cloner, int index)
 
564
{
 
565
/* returning a PK column name (by sorted index) */
 
566
    struct aux_pk_column *ppk;
 
567
    if (cloner->sorted_pks == NULL)
 
568
        return NULL;
 
569
    if (index < 0 || index >= cloner->pk_count)
 
570
        return NULL;
 
571
    ppk = *(cloner->sorted_pks + index);
 
572
    return ppk->column->name;
 
573
}
 
574
 
 
575
static void
 
576
mark_existing_trigger (struct aux_cloner *cloner, const char *name)
 
577
{
 
578
/* marking an existing Trigger */
 
579
    struct aux_trigger *trigger = cloner->first_trigger;
 
580
    while (trigger != NULL)
 
581
      {
 
582
          if (strcasecmp (trigger->name, name) == 0)
 
583
            {
 
584
                trigger->already_existing = 1;
 
585
                return;
 
586
            }
 
587
          trigger = trigger->next;
 
588
      }
 
589
}
 
590
 
 
591
static void
 
592
check_existing_triggers (struct aux_cloner *cloner)
 
593
{
 
594
/* exploring the output table - already existing Triggers */
 
595
    char *sql;
 
596
    int ret;
 
597
    int i;
 
598
    char **results;
 
599
    int rows;
 
600
    int columns;
 
601
    const char *name;
 
602
 
 
603
    sql = sqlite3_mprintf ("SELECT name FROM main.sqlite_master "
 
604
                           "WHERE type = 'trigger' AND Lower(tbl_name) = Lower(%Q)",
 
605
                           cloner->in_table);
 
606
    ret =
 
607
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
608
                           NULL);
 
609
    sqlite3_free (sql);
 
610
    if (ret != SQLITE_OK)
 
611
        return;
 
612
    if (rows < 1)
 
613
        ;
 
614
    else
 
615
      {
 
616
          for (i = 1; i <= rows; i++)
 
617
            {
 
618
                name = results[(i * columns) + 0];
 
619
                mark_existing_trigger (cloner, name);
 
620
            }
 
621
      }
 
622
    sqlite3_free_table (results);
 
623
}
 
624
 
 
625
static int
 
626
create_output_table (struct aux_cloner *cloner)
 
627
{
 
628
/* creating the output Table */
 
629
    char *err_msg = NULL;
 
630
    int ret;
 
631
    struct aux_column *column;
 
632
    struct aux_foreign_key *fk;
 
633
    struct aux_fk_columns *fk_col;
 
634
    struct aux_index *index;
 
635
    struct aux_index_column *idx_column;
 
636
    char *sql;
 
637
    char *prev_sql;
 
638
    char *xtable;
 
639
    char *xcolumn;
 
640
    char *constraint;
 
641
    char *xconstraint;
 
642
    int first = 1;
 
643
    int i;
 
644
    int fk_no;
 
645
 
 
646
    sort_pk_columns (cloner);
 
647
    adjust_ignore (cloner);
 
648
    xtable = gaiaDoubleQuotedSql (cloner->out_table);
 
649
    sql = sqlite3_mprintf ("CREATE TABLE main.\"%s\"", xtable);
 
650
    free (xtable);
 
651
    prev_sql = sql;
 
652
 
 
653
    column = cloner->first_col;
 
654
    while (column != NULL)
 
655
      {
 
656
          if (column->ignore)
 
657
            {
 
658
                /* IGNORE requested */
 
659
                column = column->next;
 
660
                continue;
 
661
            }
 
662
          if (column->geometry != NULL)
 
663
            {
 
664
                /* skipping any Geometry column */
 
665
                column = column->next;
 
666
                continue;
 
667
            }
 
668
          if (first)
 
669
            {
 
670
                sql = sqlite3_mprintf ("%s (\n", prev_sql);
 
671
                first = 0;
 
672
            }
 
673
          else
 
674
              sql = sqlite3_mprintf ("%s,\n", prev_sql);
 
675
          sqlite3_free (prev_sql);
 
676
          prev_sql = sql;
 
677
          xcolumn = gaiaDoubleQuotedSql (column->name);
 
678
          if (cloner->pk_count == 1 && column->pk)
 
679
            {
 
680
                /* immediately declaring a single column Primary Key */
 
681
                if (cloner->autoincrement)
 
682
                  {
 
683
                      if (column->notnull)
 
684
                        {
 
685
                            if (column->deflt != NULL)
 
686
                                sql =
 
687
                                    sqlite3_mprintf
 
688
                                    ("%s\t\"%s\" %s NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT %s",
 
689
                                     prev_sql, xcolumn, column->type,
 
690
                                     column->deflt);
 
691
                            else
 
692
                                sql =
 
693
                                    sqlite3_mprintf
 
694
                                    ("%s\t\"%s\" %s NOT NULL PRIMARY KEY AUTOINCREMENT",
 
695
                                     prev_sql, xcolumn, column->type);
 
696
                        }
 
697
                      else
 
698
                        {
 
699
                            if (column->deflt != NULL)
 
700
                                sql =
 
701
                                    sqlite3_mprintf
 
702
                                    ("%s\t\"%s\" %s PRIMARY KEY AUTOINCREMENT DEFAULT %s",
 
703
                                     prev_sql, xcolumn, column->type,
 
704
                                     column->deflt);
 
705
                            else
 
706
                                sql =
 
707
                                    sqlite3_mprintf
 
708
                                    ("%s\t\"%s\" %s PRIMARY KEY AUTOINCREMENT",
 
709
                                     prev_sql, xcolumn, column->type);
 
710
                        }
 
711
                  }
 
712
                else
 
713
                  {
 
714
                      if (column->notnull)
 
715
                        {
 
716
                            if (column->deflt != NULL)
 
717
                                sql =
 
718
                                    sqlite3_mprintf
 
719
                                    ("%s\t\"%s\" %s NOT NULL PRIMARY KEY DEFAULT %s",
 
720
                                     prev_sql, xcolumn, column->type,
 
721
                                     column->deflt);
 
722
                            else
 
723
                                sql =
 
724
                                    sqlite3_mprintf
 
725
                                    ("%s\t\"%s\" %s NOT NULL PRIMARY KEY",
 
726
                                     prev_sql, xcolumn, column->type);
 
727
                        }
 
728
                      else
 
729
                        {
 
730
                            if (column->deflt != NULL)
 
731
                                sql =
 
732
                                    sqlite3_mprintf
 
733
                                    ("%s\t\"%s\" %s PRIMARY KEY DEFAULT %s",
 
734
                                     prev_sql, xcolumn, column->type,
 
735
                                     column->deflt);
 
736
                            else
 
737
                                sql =
 
738
                                    sqlite3_mprintf
 
739
                                    ("%s\t\"%s\" %s PRIMARY KEY", prev_sql,
 
740
                                     xcolumn, column->type);
 
741
                        }
 
742
                  }
 
743
                free (xcolumn);
 
744
                sqlite3_free (prev_sql);
 
745
                prev_sql = sql;
 
746
                column = column->next;
 
747
                continue;
 
748
            }
 
749
          if (column->notnull)
 
750
            {
 
751
                if (column->deflt != NULL)
 
752
                    sql = sqlite3_mprintf ("%s\t\"%s\" %s NOT NULL DEFAULT %s",
 
753
                                           prev_sql, xcolumn, column->type,
 
754
                                           column->deflt);
 
755
                else
 
756
                    sql = sqlite3_mprintf ("%s\t\"%s\" %s NOT NULL",
 
757
                                           prev_sql, xcolumn, column->type);
 
758
            }
 
759
          else
 
760
            {
 
761
                if (column->deflt != NULL)
 
762
                    sql = sqlite3_mprintf ("%s\t\"%s\" %s DEFAULT %s",
 
763
                                           prev_sql, xcolumn, column->type,
 
764
                                           column->deflt);
 
765
                else
 
766
                    sql = sqlite3_mprintf ("%s\t\"%s\" %s",
 
767
                                           prev_sql, xcolumn, column->type);
 
768
            }
 
769
          free (xcolumn);
 
770
          sqlite3_free (prev_sql);
 
771
          prev_sql = sql;
 
772
          column = column->next;
 
773
      }
 
774
 
 
775
    if (cloner->pk_count > 1)
 
776
      {
 
777
          /* declaring a PRIMARY KEY CONSTRAINT */
 
778
          sql = sqlite3_mprintf ("%s,\n", prev_sql);
 
779
          sqlite3_free (prev_sql);
 
780
          prev_sql = sql;
 
781
          constraint = sqlite3_mprintf ("pk_%s", cloner->out_table);
 
782
          xconstraint = gaiaDoubleQuotedSql (constraint);
 
783
          sqlite3_free (constraint);
 
784
          sql =
 
785
              sqlite3_mprintf ("%s\tCONSTRAINT \"%s\" PRIMARY KEY (", prev_sql,
 
786
                               xconstraint);
 
787
          free (xconstraint);
 
788
          sqlite3_free (prev_sql);
 
789
          prev_sql = sql;
 
790
          for (i = 0; i < cloner->pk_count; i++)
 
791
            {
 
792
                xconstraint = gaiaDoubleQuotedSql (get_pk_column (cloner, i));
 
793
                if (i == 0)
 
794
                    sql = sqlite3_mprintf ("%s%s", prev_sql, xconstraint);
 
795
                else
 
796
                    sql = sqlite3_mprintf ("%s, %s", prev_sql, xconstraint);
 
797
                free (xconstraint);
 
798
                sqlite3_free (prev_sql);
 
799
                prev_sql = sql;
 
800
            }
 
801
          sql = sqlite3_mprintf ("%s)", prev_sql);
 
802
          sqlite3_free (prev_sql);
 
803
          prev_sql = sql;
 
804
      }
 
805
 
 
806
    if (cloner->with_fks)
 
807
      {
 
808
          /* cloning all Foreign Key definitions */
 
809
          fk = cloner->first_fk;
 
810
          fk_no = 1;
 
811
          while (fk != NULL)
 
812
            {
 
813
                /* declaring all FOREIGN KEY CONSTRAINTs */
 
814
                sql = sqlite3_mprintf ("%s,\n", prev_sql);
 
815
                sqlite3_free (prev_sql);
 
816
                prev_sql = sql;
 
817
                constraint =
 
818
                    sqlite3_mprintf ("fk_%s_%d", cloner->out_table, fk_no++);
 
819
                xconstraint = gaiaDoubleQuotedSql (constraint);
 
820
                sqlite3_free (constraint);
 
821
                sql =
 
822
                    sqlite3_mprintf ("%s\tCONSTRAINT \"%s\" FOREIGN KEY (",
 
823
                                     prev_sql, xconstraint);
 
824
                free (xconstraint);
 
825
                sqlite3_free (prev_sql);
 
826
                prev_sql = sql;
 
827
                fk_col = fk->first;
 
828
                while (fk_col != NULL)
 
829
                  {
 
830
                      xconstraint = gaiaDoubleQuotedSql (fk_col->from);
 
831
                      if (fk_col == fk->first)
 
832
                          sql = sqlite3_mprintf ("%s%s", prev_sql, xconstraint);
 
833
                      else
 
834
                          sql =
 
835
                              sqlite3_mprintf ("%s, %s", prev_sql, xconstraint);
 
836
                      free (xconstraint);
 
837
                      sqlite3_free (prev_sql);
 
838
                      prev_sql = sql;
 
839
                      fk_col = fk_col->next;
 
840
                  }
 
841
                xtable = gaiaDoubleQuotedSql (fk->references);
 
842
                sql =
 
843
                    sqlite3_mprintf ("%s) REFERENCES \"%s\" (", prev_sql,
 
844
                                     xtable);
 
845
                free (xtable);
 
846
                sqlite3_free (prev_sql);
 
847
                prev_sql = sql;
 
848
                fk_col = fk->first;
 
849
                while (fk_col != NULL)
 
850
                  {
 
851
                      xconstraint = gaiaDoubleQuotedSql (fk_col->to);
 
852
                      if (fk_col == fk->first)
 
853
                          sql = sqlite3_mprintf ("%s%s", prev_sql, xconstraint);
 
854
                      else
 
855
                          sql =
 
856
                              sqlite3_mprintf ("%s, %s", prev_sql, xconstraint);
 
857
                      free (xconstraint);
 
858
                      sqlite3_free (prev_sql);
 
859
                      prev_sql = sql;
 
860
                      fk_col = fk_col->next;
 
861
                  }
 
862
                sql = sqlite3_mprintf ("%s)", prev_sql);
 
863
                sqlite3_free (prev_sql);
 
864
                prev_sql = sql;
 
865
                fk = fk->next;
 
866
            }
 
867
      }
 
868
    sql = sqlite3_mprintf ("%s\n)", prev_sql);
 
869
    sqlite3_free (prev_sql);
 
870
 
 
871
    ret = sqlite3_exec (cloner->sqlite, sql, NULL, NULL, &err_msg);
 
872
    sqlite3_free (sql);
 
873
    if (ret != SQLITE_OK)
 
874
      {
 
875
          spatialite_e ("CREATE TABLE error: %s\n", err_msg);
 
876
          sqlite3_free (err_msg);
 
877
          return 0;
 
878
      }
 
879
 
 
880
    column = cloner->first_col;
 
881
    while (column != NULL)
 
882
      {
 
883
          if (column->geometry != NULL && !(column->ignore))
 
884
            {
 
885
                /* adding a Geometry Column */
 
886
                if (!create_geometry
 
887
                    (cloner->sqlite, cloner->out_table, column))
 
888
                    return 0;
 
889
            }
 
890
          column = column->next;
 
891
      }
 
892
 
 
893
    index = cloner->first_idx;
 
894
    fk_no = 1;
 
895
    while (index != NULL)
 
896
      {
 
897
          /* creating an Index */
 
898
          constraint =
 
899
              sqlite3_mprintf ("idx_%s_%d", cloner->out_table, fk_no++);
 
900
          xconstraint = gaiaDoubleQuotedSql (constraint);
 
901
          xtable = gaiaDoubleQuotedSql (cloner->out_table);
 
902
          if (index->unique)
 
903
              sql =
 
904
                  sqlite3_mprintf ("CREATE UNIQUE INDEX main.\"%s\" ON \"%s\"",
 
905
                                   xconstraint, xtable);
 
906
          else
 
907
              sql =
 
908
                  sqlite3_mprintf ("CREATE INDEX main.\"%s\" ON \"%s\"",
 
909
                                   xconstraint, xtable);
 
910
          free (xconstraint);
 
911
          free (xtable);
 
912
          prev_sql = sql;
 
913
 
 
914
          idx_column = index->first;
 
915
          first = 1;
 
916
          while (idx_column != NULL)
 
917
            {
 
918
                xcolumn = gaiaDoubleQuotedSql (idx_column->name);
 
919
                if (first)
 
920
                  {
 
921
                      sql = sqlite3_mprintf ("%s (\"%s\"", prev_sql, xcolumn);
 
922
                      first = 0;
 
923
                  }
 
924
                else
 
925
                    sql = sqlite3_mprintf ("%s, \"%s\"", prev_sql, xcolumn);
 
926
                free (xcolumn);
 
927
                sqlite3_free (prev_sql);
 
928
                prev_sql = sql;
 
929
                idx_column = idx_column->next;
 
930
            }
 
931
          sql = sqlite3_mprintf ("%s)\n", prev_sql);
 
932
          sqlite3_free (prev_sql);
 
933
 
 
934
          ret = sqlite3_exec (cloner->sqlite, sql, NULL, NULL, &err_msg);
 
935
          sqlite3_free (sql);
 
936
          if (ret != SQLITE_OK)
 
937
            {
 
938
                spatialite_e ("CREATE INDEX error: %s\n", err_msg);
 
939
                sqlite3_free (err_msg);
 
940
                return 0;
 
941
            }
 
942
          index = index->next;
 
943
      }
 
944
 
 
945
    if (cloner->with_triggers)
 
946
      {
 
947
          struct aux_trigger *trigger;
 
948
          check_existing_triggers (cloner);
 
949
          trigger = cloner->first_trigger;
 
950
          while (trigger != NULL)
 
951
            {
 
952
                if (trigger->already_existing)
 
953
                  {
 
954
                      /* skipping already defined triggers */
 
955
                      trigger = trigger->next;
 
956
                      continue;
 
957
                  }
 
958
                /* adding a trigger */
 
959
                ret =
 
960
                    sqlite3_exec (cloner->sqlite, trigger->sql, NULL, NULL,
 
961
                                  &err_msg);
 
962
                if (ret != SQLITE_OK)
 
963
                  {
 
964
                      spatialite_e ("CREATE TRIGGER error: %s\n", err_msg);
 
965
                      sqlite3_free (err_msg);
 
966
                      return 0;
 
967
                  }
 
968
                trigger = trigger->next;
 
969
            }
 
970
      }
 
971
    return 1;
 
972
}
 
973
 
 
974
static int
 
975
copy_rows (struct aux_cloner *cloner)
 
976
{
 
977
/* copying all rows from the origin into the destination Table */
 
978
    sqlite3_stmt *stmt_in = NULL;
 
979
    sqlite3_stmt *stmt_out = NULL;
 
980
    int ret;
 
981
    struct aux_column *column;
 
982
    char *sql;
 
983
    char *prev_sql;
 
984
    char *xcolumn;
 
985
    char *xtable;
 
986
    char *xdb_prefix;
 
987
    int first = 1;
 
988
 
 
989
/* composing the SELECT statement */
 
990
    sql = sqlite3_mprintf ("SELECT ");
 
991
    prev_sql = sql;
 
992
    column = cloner->first_col;
 
993
    while (column != NULL)
 
994
      {
 
995
          if (column->ignore)
 
996
            {
 
997
                /* skipping columns to be IGNORED */
 
998
                column = column->next;
 
999
                continue;
 
1000
            }
 
1001
          xcolumn = gaiaDoubleQuotedSql (column->name);
 
1002
          if (first)
 
1003
            {
 
1004
                sql = sqlite3_mprintf ("%s\"%s\"", prev_sql, xcolumn);
 
1005
                first = 0;
 
1006
            }
 
1007
          else
 
1008
              sql = sqlite3_mprintf ("%s, \"%s\"", prev_sql, xcolumn);
 
1009
          free (xcolumn);
 
1010
          sqlite3_free (prev_sql);
 
1011
          prev_sql = sql;
 
1012
          column = column->next;
 
1013
      }
 
1014
    xdb_prefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1015
    xtable = gaiaDoubleQuotedSql (cloner->in_table);
 
1016
    sql =
 
1017
        sqlite3_mprintf ("%s FROM \"%s\".\"%s\"", prev_sql, xdb_prefix, xtable);
 
1018
    free (xdb_prefix);
 
1019
    free (xtable);
 
1020
/* compiling the SELECT FROM statement */
 
1021
    ret =
 
1022
        sqlite3_prepare_v2 (cloner->sqlite, sql, strlen (sql), &stmt_in, NULL);
 
1023
    sqlite3_free (sql);
 
1024
    if (ret != SQLITE_OK)
 
1025
      {
 
1026
          spatialite_e ("SELECT FROM: \"%s\"\n",
 
1027
                        sqlite3_errmsg (cloner->sqlite));
 
1028
          goto error;
 
1029
      }
 
1030
 
 
1031
/* composing the INSERT INTO statement */
 
1032
    xtable = gaiaDoubleQuotedSql (cloner->out_table);
 
1033
    sql = sqlite3_mprintf ("INSERT INTO \"%s\" (", xtable);
 
1034
    free (xtable);
 
1035
    prev_sql = sql;
 
1036
    first = 1;
 
1037
    column = cloner->first_col;
 
1038
    while (column != NULL)
 
1039
      {
 
1040
          if (column->ignore)
 
1041
            {
 
1042
                /* skipping columns to be IGNORED */
 
1043
                column = column->next;
 
1044
                continue;
 
1045
            }
 
1046
          xcolumn = gaiaDoubleQuotedSql (column->name);
 
1047
          if (first)
 
1048
            {
 
1049
                sql = sqlite3_mprintf ("%s\"%s\"", prev_sql, xcolumn);
 
1050
                first = 0;
 
1051
            }
 
1052
          else
 
1053
              sql = sqlite3_mprintf ("%s, \"%s\"", prev_sql, xcolumn);
 
1054
          free (xcolumn);
 
1055
          sqlite3_free (prev_sql);
 
1056
          prev_sql = sql;
 
1057
          column = column->next;
 
1058
      }
 
1059
    sql = sqlite3_mprintf ("%s) VALUES (", prev_sql);
 
1060
    sqlite3_free (prev_sql);
 
1061
    prev_sql = sql;
 
1062
    first = 1;
 
1063
    column = cloner->first_col;
 
1064
    while (column != NULL)
 
1065
      {
 
1066
          if (column->ignore)
 
1067
            {
 
1068
                /* skipping columns to be IGNORED */
 
1069
                column = column->next;
 
1070
                continue;
 
1071
            }
 
1072
          if (column->geometry != NULL)
 
1073
            {
 
1074
                /* Geometry column */
 
1075
                if (column->geometry->cast2multi)
 
1076
                  {
 
1077
                      /* casting to MultiType */
 
1078
                      const char *expr = "CastToMulti(?)";
 
1079
                      if (first)
 
1080
                        {
 
1081
                            sql = sqlite3_mprintf ("%s%s", prev_sql, expr);
 
1082
                            first = 0;
 
1083
                        }
 
1084
                      else
 
1085
                          sql = sqlite3_mprintf ("%s, %s", prev_sql, expr);
 
1086
                      sqlite3_free (prev_sql);
 
1087
                      prev_sql = sql;
 
1088
                      column = column->next;
 
1089
                      continue;
 
1090
                  }
 
1091
            }
 
1092
          if (first)
 
1093
            {
 
1094
                sql = sqlite3_mprintf ("%s?", prev_sql);
 
1095
                first = 0;
 
1096
            }
 
1097
          else
 
1098
              sql = sqlite3_mprintf ("%s, ?", prev_sql);
 
1099
          sqlite3_free (prev_sql);
 
1100
          prev_sql = sql;
 
1101
          column = column->next;
 
1102
      }
 
1103
    sql = sqlite3_mprintf ("%s)", prev_sql);
 
1104
    sqlite3_free (prev_sql);
 
1105
/* compiling the INSERT INTO statement */
 
1106
    ret =
 
1107
        sqlite3_prepare_v2 (cloner->sqlite, sql, strlen (sql), &stmt_out, NULL);
 
1108
    sqlite3_free (sql);
 
1109
    if (ret != SQLITE_OK)
 
1110
      {
 
1111
          spatialite_e ("INSERT INTO: \"%s\"\n",
 
1112
                        sqlite3_errmsg (cloner->sqlite));
 
1113
          goto error;
 
1114
      }
 
1115
 
 
1116
    while (1)
 
1117
      {
 
1118
          /* scrolling the result set rows */
 
1119
          ret = sqlite3_step (stmt_in);
 
1120
          if (ret == SQLITE_DONE)
 
1121
              break;            /* end of result set */
 
1122
          if (ret == SQLITE_ROW)
 
1123
            {
 
1124
                /* copying values between input and output tables */
 
1125
                int pos = 0;
 
1126
                sqlite3_reset (stmt_out);
 
1127
                sqlite3_clear_bindings (stmt_out);
 
1128
                column = cloner->first_col;
 
1129
                while (column != NULL)
 
1130
                  {
 
1131
                      if (column->ignore)
 
1132
                        {
 
1133
                            /* skipping columns to be IGNORED */
 
1134
                            column = column->next;
 
1135
                            continue;
 
1136
                        }
 
1137
                      if (cloner->resequence && cloner->pk_count == 1
 
1138
                          && cloner->autoincrement && column->pk)
 
1139
                        {
 
1140
                            /* resequencing an AUTOINCREMENT PK */
 
1141
                            sqlite3_bind_null (stmt_out, pos + 1);
 
1142
                            pos++;
 
1143
                            column = column->next;
 
1144
                            continue;
 
1145
                        }
 
1146
                      if (sqlite3_column_type (stmt_in, pos) == SQLITE_INTEGER)
 
1147
                          sqlite3_bind_int64 (stmt_out, pos + 1,
 
1148
                                              sqlite3_column_int64 (stmt_in,
 
1149
                                                                    pos));
 
1150
                      else if (sqlite3_column_type (stmt_in, pos) ==
 
1151
                               SQLITE_FLOAT)
 
1152
                          sqlite3_bind_double (stmt_out, pos + 1,
 
1153
                                               sqlite3_column_double (stmt_in,
 
1154
                                                                      pos));
 
1155
                      else if (sqlite3_column_type (stmt_in, pos) ==
 
1156
                               SQLITE_TEXT)
 
1157
                          sqlite3_bind_text (stmt_out, pos + 1,
 
1158
                                             (const char *)
 
1159
                                             sqlite3_column_text (stmt_in, pos),
 
1160
                                             sqlite3_column_bytes (stmt_in,
 
1161
                                                                   pos),
 
1162
                                             SQLITE_STATIC);
 
1163
                      else if (sqlite3_column_type (stmt_in, pos) ==
 
1164
                               SQLITE_BLOB)
 
1165
                          sqlite3_bind_blob (stmt_out, pos + 1,
 
1166
                                             sqlite3_column_blob (stmt_in, pos),
 
1167
                                             sqlite3_column_bytes (stmt_in,
 
1168
                                                                   pos),
 
1169
                                             SQLITE_STATIC);
 
1170
                      else
 
1171
                          sqlite3_bind_null (stmt_out, pos + 1);
 
1172
                      pos++;
 
1173
                      column = column->next;
 
1174
                  }
 
1175
                /* inserting into the output table */
 
1176
                ret = sqlite3_step (stmt_out);
 
1177
                if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 
1178
                    ;
 
1179
                else
 
1180
                  {
 
1181
                      spatialite_e ("OUTPUT step error: <%s>\n",
 
1182
                                    sqlite3_errmsg (cloner->sqlite));
 
1183
                      goto error;
 
1184
                  }
 
1185
            }
 
1186
          else
 
1187
            {
 
1188
                spatialite_e ("INPUT step error: <%s>\n",
 
1189
                              sqlite3_errmsg (cloner->sqlite));
 
1190
                goto error;
 
1191
            }
 
1192
      }
 
1193
    sqlite3_finalize (stmt_in);
 
1194
    sqlite3_finalize (stmt_out);
 
1195
    return 1;
 
1196
 
 
1197
  error:
 
1198
    if (stmt_in != NULL)
 
1199
        sqlite3_finalize (stmt_in);
 
1200
    if (stmt_out != NULL)
 
1201
        sqlite3_finalize (stmt_out);
 
1202
    return 0;
 
1203
}
 
1204
 
 
1205
static void
 
1206
add_geometry (struct aux_cloner *cloner, const char *name, int type, int dims,
 
1207
              int srid, int spatial_index)
 
1208
{
 
1209
/* adding a Geometry Column definition */
 
1210
    struct aux_column *pc = cloner->first_col;
 
1211
    while (pc != NULL)
 
1212
      {
 
1213
          if (strcasecmp (pc->name, name) == 0)
 
1214
            {
 
1215
                struct aux_geometry *geom =
 
1216
                    malloc (sizeof (struct aux_geometry));
 
1217
                geom->type = type;
 
1218
                geom->dims = dims;
 
1219
                geom->srid = srid;
 
1220
                geom->spatial_index = spatial_index;
 
1221
                geom->cast2multi = 0;
 
1222
                geom->already_existing = 0;
 
1223
                if (pc->geometry != NULL)
 
1224
                    free (pc->geometry);
 
1225
                pc->geometry = geom;
 
1226
                return;
 
1227
            }
 
1228
          pc = pc->next;
 
1229
      }
 
1230
}
 
1231
 
 
1232
static void
 
1233
mark_existing_geometry (struct aux_cloner *cloner, const char *name, int type,
 
1234
                        int dims, int srid)
 
1235
{
 
1236
/* marking an existing Geometry Column definition */
 
1237
    struct aux_column *pc = cloner->first_col;
 
1238
    while (pc != NULL)
 
1239
      {
 
1240
          if (strcasecmp (pc->name, name) == 0)
 
1241
            {
 
1242
                if (pc->geometry == NULL)
 
1243
                  {
 
1244
                      /* gosh, it's not a Geometry */
 
1245
                      pc->mismatching = 1;
 
1246
                      return;
 
1247
                  }
 
1248
                if (pc->geometry->type == type && pc->geometry->dims == dims
 
1249
                    && pc->geometry->srid == srid)
 
1250
                  {
 
1251
                      /* matching arguments: confirmed */
 
1252
                      pc->geometry->already_existing = 1;
 
1253
                      return;
 
1254
                  }
 
1255
                /* different arguments: invalid */
 
1256
                pc->mismatching = 1;
 
1257
                return;
 
1258
            }
 
1259
          pc = pc->next;
 
1260
      }
 
1261
}
 
1262
 
 
1263
static void
 
1264
add_trigger (struct aux_cloner *cloner, const char *name, const char *sql)
 
1265
{
 
1266
/* adding a Trigger definition */
 
1267
    int len;
 
1268
    struct aux_trigger *trigger = malloc (sizeof (struct aux_trigger));
 
1269
    len = strlen (name);
 
1270
    trigger->name = malloc (len + 1);
 
1271
    strcpy (trigger->name, name);
 
1272
    len = strlen (sql);
 
1273
    trigger->sql = malloc (len + 1);
 
1274
    strcpy (trigger->sql, sql);
 
1275
    trigger->already_existing = 0;
 
1276
    trigger->next = NULL;
 
1277
/* updating the linked list */
 
1278
    if (cloner->first_trigger == NULL)
 
1279
        cloner->first_trigger = trigger;
 
1280
    if (cloner->last_trigger != NULL)
 
1281
        cloner->last_trigger->next = trigger;
 
1282
    cloner->last_trigger = trigger;
 
1283
}
 
1284
 
 
1285
static void
 
1286
add_fk_columns (struct aux_foreign_key *fk, struct aux_column *first_col,
 
1287
                const char *from, const char *to)
 
1288
{
 
1289
/* adding Columns correspondencies into a Foreign Key definition */
 
1290
    int len;
 
1291
    struct aux_column *column;
 
1292
    struct aux_fk_columns *col = malloc (sizeof (struct aux_fk_columns));
 
1293
    len = strlen (from);
 
1294
    col->from = malloc (len + 1);
 
1295
    strcpy (col->from, from);
 
1296
    len = strlen (to);
 
1297
    col->to = malloc (len + 1);
 
1298
    strcpy (col->to, to);
 
1299
    col->next = NULL;
 
1300
/* updating the linked list */
 
1301
    if (fk->first == NULL)
 
1302
        fk->first = col;
 
1303
    if (fk->last != NULL)
 
1304
        fk->last->next = col;
 
1305
    fk->last = col;
 
1306
/* marking the column as a Foreign Key */
 
1307
    column = first_col;
 
1308
    while (column != NULL)
 
1309
      {
 
1310
          if (strcasecmp (column->name, from) == 0)
 
1311
            {
 
1312
                column->fk = 1;
 
1313
                break;
 
1314
            }
 
1315
          column = column->next;
 
1316
      }
 
1317
}
 
1318
 
 
1319
static void
 
1320
add_foreign_key (struct aux_cloner *cloner, int id, const char *references,
 
1321
                 const char *from, const char *to, const char *on_update,
 
1322
                 const char *on_delete, const char *match)
 
1323
{
 
1324
/* adding a Foreign Key definition */
 
1325
    int len;
 
1326
    struct aux_foreign_key *fk;
 
1327
    if (cloner->last_fk != NULL)
 
1328
      {
 
1329
          if (cloner->last_fk->id == id)
 
1330
            {
 
1331
                /* continuing with the latest FK */
 
1332
                add_fk_columns (cloner->last_fk, cloner->first_col, from, to);
 
1333
                return;
 
1334
            }
 
1335
      }
 
1336
    fk = malloc (sizeof (struct aux_foreign_key));
 
1337
    fk->id = id;
 
1338
    fk->name = NULL;
 
1339
    len = strlen (references);
 
1340
    fk->references = malloc (len + 1);
 
1341
    strcpy (fk->references, references);
 
1342
    fk->on_update = NULL;
 
1343
    fk->on_delete = NULL;
 
1344
    fk->match = NULL;
 
1345
    if (on_update != NULL)
 
1346
      {
 
1347
          len = strlen (on_update);
 
1348
          fk->on_update = malloc (len + 1);
 
1349
          strcpy (fk->on_update, on_update);
 
1350
      }
 
1351
    if (on_delete != NULL)
 
1352
      {
 
1353
          len = strlen (on_delete);
 
1354
          fk->on_delete = malloc (len + 1);
 
1355
          strcpy (fk->on_delete, on_delete);
 
1356
      }
 
1357
    if (match != NULL)
 
1358
      {
 
1359
          len = strlen (match);
 
1360
          fk->match = malloc (len + 1);
 
1361
          strcpy (fk->match, match);
 
1362
      }
 
1363
    fk->first = NULL;
 
1364
    fk->last = NULL;
 
1365
    fk->next = NULL;
 
1366
    add_fk_columns (fk, cloner->first_col, from, to);
 
1367
/* updating the linked list */
 
1368
    if (cloner->first_fk == NULL)
 
1369
        cloner->first_fk = fk;
 
1370
    if (cloner->last_fk != NULL)
 
1371
        cloner->last_fk->next = fk;
 
1372
    cloner->last_fk = fk;
 
1373
}
 
1374
 
 
1375
static void
 
1376
add_index_column (struct aux_index *index, struct aux_column *first_col,
 
1377
                  const char *name)
 
1378
{
 
1379
/* adding a Column into an Index definition */
 
1380
    int len;
 
1381
    struct aux_column *col;
 
1382
    struct aux_index_column *column = malloc (sizeof (struct aux_index_column));
 
1383
    len = strlen (name);
 
1384
    column->name = malloc (len + 1);
 
1385
    strcpy (column->name, name);
 
1386
    column->next = NULL;
 
1387
/* updating the linked list */
 
1388
    if (index->first == NULL)
 
1389
        index->first = column;
 
1390
    if (index->last != NULL)
 
1391
        index->last->next = column;
 
1392
    index->last = column;
 
1393
/* marking the column as a Foreign Key */
 
1394
    col = first_col;
 
1395
    while (col != NULL)
 
1396
      {
 
1397
          if (strcasecmp (col->name, name) == 0)
 
1398
            {
 
1399
                col->idx = 1;
 
1400
                break;
 
1401
            }
 
1402
          col = col->next;
 
1403
      }
 
1404
}
 
1405
 
 
1406
static struct aux_index *
 
1407
add_index (struct aux_cloner *cloner, const char *name, int unique)
 
1408
{
 
1409
/* adding an Index definition */
 
1410
    int len;
 
1411
    struct aux_index *index = malloc (sizeof (struct aux_index));
 
1412
    len = strlen (name);
 
1413
    index->name = malloc (len + 1);
 
1414
    strcpy (index->name, name);
 
1415
    index->unique = unique;
 
1416
    index->first = NULL;
 
1417
    index->last = NULL;
 
1418
    index->next = NULL;
 
1419
/* updating the linked list */
 
1420
    if (cloner->first_idx == NULL)
 
1421
        cloner->first_idx = index;
 
1422
    if (cloner->last_idx != NULL)
 
1423
        cloner->last_idx->next = index;
 
1424
    cloner->last_idx = index;
 
1425
    return index;
 
1426
}
 
1427
 
 
1428
static void
 
1429
add_column (struct aux_cloner *cloner, const char *name, const char *type,
 
1430
            int notnull, const char *deflt, int pk)
 
1431
{
 
1432
/* adding a Column definition */
 
1433
    int len;
 
1434
    struct aux_column *column = malloc (sizeof (struct aux_column));
 
1435
    len = strlen (name);
 
1436
    column->name = malloc (len + 1);
 
1437
    strcpy (column->name, name);
 
1438
    len = strlen (type);
 
1439
    column->type = malloc (len + 1);
 
1440
    strcpy (column->type, type);
 
1441
    column->notnull = notnull;
 
1442
    if (deflt == NULL)
 
1443
        column->deflt = NULL;
 
1444
    else
 
1445
      {
 
1446
          len = strlen (deflt);
 
1447
          column->deflt = malloc (len + 1);
 
1448
          strcpy (column->deflt, deflt);
 
1449
      }
 
1450
    column->pk = pk;
 
1451
    column->fk = 0;
 
1452
    column->idx = 0;
 
1453
    column->geometry = NULL;
 
1454
    column->ignore = 0;
 
1455
    column->already_existing = 0;
 
1456
    column->mismatching = 0;
 
1457
    column->next = NULL;
 
1458
/* updating the linked list */
 
1459
    if (cloner->first_col == NULL)
 
1460
        cloner->first_col = column;
 
1461
    if (cloner->last_col != NULL)
 
1462
        cloner->last_col->next = column;
 
1463
    cloner->last_col = column;
 
1464
    if (pk)
 
1465
      {
 
1466
          struct aux_pk_column *ppk = malloc (sizeof (struct aux_pk_column));
 
1467
          ppk->column = column;
 
1468
          ppk->next = NULL;
 
1469
          /* updating the linked list */
 
1470
          if (cloner->first_pk == NULL)
 
1471
              cloner->first_pk = ppk;
 
1472
          if (cloner->last_pk != NULL)
 
1473
              cloner->last_pk->next = ppk;
 
1474
          cloner->last_pk = ppk;
 
1475
          cloner->pk_count += 1;
 
1476
      }
 
1477
}
 
1478
 
 
1479
static void
 
1480
mark_existing_column (struct aux_cloner *cloner, const char *name)
 
1481
{
 
1482
/* marking an existing Column */
 
1483
    struct aux_column *column = cloner->first_col;
 
1484
    while (column != NULL)
 
1485
      {
 
1486
          if (strcasecmp (column->name, name) == 0)
 
1487
            {
 
1488
                column->already_existing = 1;
 
1489
                return;
 
1490
            }
 
1491
          column = column->next;
 
1492
      }
 
1493
}
 
1494
 
 
1495
static int
 
1496
check_input_table_columns (struct aux_cloner *cloner)
 
1497
{
 
1498
/* exploring the input table - Columns */
 
1499
    char *sql;
 
1500
    int ret;
 
1501
    int i;
 
1502
    char **results;
 
1503
    int rows;
 
1504
    int columns;
 
1505
    const char *name;
 
1506
    const char *type;
 
1507
    int notnull;
 
1508
    const char *deflt;
 
1509
    int pk;
 
1510
    char *xprefix;
 
1511
    char *xtable;
 
1512
 
 
1513
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1514
    xtable = gaiaDoubleQuotedSql (cloner->in_table);
 
1515
    sql = sqlite3_mprintf ("PRAGMA \"%s\".table_info(\"%s\")", xprefix, xtable);
 
1516
    free (xprefix);
 
1517
    free (xtable);
 
1518
    ret =
 
1519
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1520
                           NULL);
 
1521
    sqlite3_free (sql);
 
1522
    if (ret != SQLITE_OK)
 
1523
        return 0;
 
1524
    if (rows < 1)
 
1525
        ;
 
1526
    else
 
1527
      {
 
1528
          for (i = 1; i <= rows; i++)
 
1529
            {
 
1530
                name = results[(i * columns) + 1];
 
1531
                type = results[(i * columns) + 2];
 
1532
                notnull = atoi (results[(i * columns) + 3]);
 
1533
                deflt = results[(i * columns) + 4];
 
1534
                pk = atoi (results[(i * columns) + 5]);
 
1535
                add_column (cloner, name, type, notnull, deflt, pk);
 
1536
            }
 
1537
      }
 
1538
    sqlite3_free_table (results);
 
1539
 
 
1540
    if (cloner->first_col == NULL)
 
1541
      {
 
1542
          spatialite_e
 
1543
              ("CloneTable: input table \"%s\".\"%s\" does not exist\n",
 
1544
               cloner->db_prefix, cloner->in_table);
 
1545
          goto error;
 
1546
      }
 
1547
    return 1;
 
1548
 
 
1549
  error:
 
1550
    return 0;
 
1551
}
 
1552
 
 
1553
static void
 
1554
check_input_table_autoincrement (struct aux_cloner *cloner)
 
1555
{
 
1556
/* exploring the input table AUTOINCREMENT property */
 
1557
    char *sql;
 
1558
    int ret;
 
1559
    int i;
 
1560
    char **results;
 
1561
    int rows;
 
1562
    int columns;
 
1563
    char *xprefix;
 
1564
 
 
1565
    if (cloner->pk_count != 1)
 
1566
        return;
 
1567
 
 
1568
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1569
    sql = sqlite3_mprintf ("SELECT Count(*) FROM \"%s\".sqlite_sequence "
 
1570
                           "WHERE Lower(name) = Lower(%Q)",
 
1571
                           xprefix, cloner->in_table);
 
1572
    free (xprefix);
 
1573
    ret =
 
1574
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1575
                           NULL);
 
1576
    sqlite3_free (sql);
 
1577
    if (ret != SQLITE_OK)
 
1578
        return;
 
1579
    if (rows < 1)
 
1580
        ;
 
1581
    else
 
1582
      {
 
1583
          for (i = 1; i <= rows; i++)
 
1584
            {
 
1585
                if (atoi (results[(i * columns) + 0]) > 0)
 
1586
                    cloner->autoincrement = 1;
 
1587
            }
 
1588
      }
 
1589
    sqlite3_free_table (results);
 
1590
}
 
1591
 
 
1592
static void
 
1593
check_output_table_columns (struct aux_cloner *cloner)
 
1594
{
 
1595
/* exploring the output table - Columns */
 
1596
    char *sql;
 
1597
    int ret;
 
1598
    int i;
 
1599
    char **results;
 
1600
    int rows;
 
1601
    int columns;
 
1602
    const char *name;
 
1603
    char *xtable;
 
1604
 
 
1605
    xtable = gaiaDoubleQuotedSql (cloner->out_table);
 
1606
    sql = sqlite3_mprintf ("PRAGMA main.table_info(\"%s\")", xtable);
 
1607
    free (xtable);
 
1608
    ret =
 
1609
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1610
                           NULL);
 
1611
    sqlite3_free (sql);
 
1612
    if (ret != SQLITE_OK)
 
1613
        return;
 
1614
    if (rows < 1)
 
1615
        ;
 
1616
    else
 
1617
      {
 
1618
          for (i = 1; i <= rows; i++)
 
1619
            {
 
1620
                name = results[(i * columns) + 1];
 
1621
                mark_existing_column (cloner, name);
 
1622
            }
 
1623
      }
 
1624
    sqlite3_free_table (results);
 
1625
}
 
1626
 
 
1627
static void
 
1628
expand_index (struct aux_cloner *cloner, struct aux_index *index)
 
1629
{
 
1630
/* expanding an Index definitions */
 
1631
    char *sql;
 
1632
    int ret;
 
1633
    int i;
 
1634
    char **results;
 
1635
    int rows;
 
1636
    int columns;
 
1637
    const char *name;
 
1638
    char *xprefix;
 
1639
    char *xindex;
 
1640
 
 
1641
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1642
    xindex = gaiaDoubleQuotedSql (index->name);
 
1643
    sql = sqlite3_mprintf ("PRAGMA \"%s\".index_info(\"%s\")", xprefix, xindex);
 
1644
    free (xprefix);
 
1645
    free (xindex);
 
1646
    ret =
 
1647
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1648
                           NULL);
 
1649
    sqlite3_free (sql);
 
1650
    if (ret != SQLITE_OK)
 
1651
        return;
 
1652
    if (rows < 1)
 
1653
        ;
 
1654
    else
 
1655
      {
 
1656
          for (i = 1; i <= rows; i++)
 
1657
            {
 
1658
                name = results[(i * columns) + 2];
 
1659
                add_index_column (index, cloner->first_col, name);
 
1660
            }
 
1661
      }
 
1662
    sqlite3_free_table (results);
 
1663
}
 
1664
 
 
1665
static void
 
1666
check_input_table_index_defs (struct aux_cloner *cloner)
 
1667
{
 
1668
/* exploring the input table - Index definitions */
 
1669
    char *sql;
 
1670
    int ret;
 
1671
    int i;
 
1672
    char **results;
 
1673
    int rows;
 
1674
    int columns;
 
1675
    const char *name;
 
1676
    int unique;
 
1677
    char *xprefix;
 
1678
    char *xtable;
 
1679
    struct aux_index *idx;
 
1680
 
 
1681
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1682
    xtable = gaiaDoubleQuotedSql (cloner->in_table);
 
1683
    sql = sqlite3_mprintf ("PRAGMA \"%s\".index_list(\"%s\")", xprefix, xtable);
 
1684
    free (xprefix);
 
1685
    free (xtable);
 
1686
    ret =
 
1687
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1688
                           NULL);
 
1689
    sqlite3_free (sql);
 
1690
    if (ret != SQLITE_OK)
 
1691
        return;
 
1692
    if (rows < 1)
 
1693
        ;
 
1694
    else
 
1695
      {
 
1696
          for (i = 1; i <= rows; i++)
 
1697
            {
 
1698
                name = results[(i * columns) + 1];
 
1699
                if (strncasecmp (name, "sqlite_autoindex_", 17) == 0)
 
1700
                  {
 
1701
                      /* ignoring any AUTOINDEX defined by SQLite */
 
1702
                      continue;
 
1703
                  }
 
1704
                unique = atoi (results[(i * columns) + 2]);
 
1705
                idx = add_index (cloner, name, unique);
 
1706
                expand_index (cloner, idx);
 
1707
            }
 
1708
      }
 
1709
    sqlite3_free_table (results);
 
1710
}
 
1711
 
 
1712
static void
 
1713
check_input_table_foreign_keys (struct aux_cloner *cloner)
 
1714
{
 
1715
/* exploring the input table - Foreign Keys */
 
1716
    char *sql;
 
1717
    int ret;
 
1718
    int i;
 
1719
    char **results;
 
1720
    int rows;
 
1721
    int columns;
 
1722
    int id;
 
1723
    const char *references;
 
1724
    const char *from;
 
1725
    const char *to;
 
1726
    const char *on_update;
 
1727
    const char *on_delete;
 
1728
    const char *match;
 
1729
    char *xprefix;
 
1730
    char *xtable;
 
1731
 
 
1732
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1733
    xtable = gaiaDoubleQuotedSql (cloner->in_table);
 
1734
    sql =
 
1735
        sqlite3_mprintf ("PRAGMA \"%s\".foreign_key_list(\"%s\")", xprefix,
 
1736
                         xtable);
 
1737
    free (xprefix);
 
1738
    free (xtable);
 
1739
    ret =
 
1740
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1741
                           NULL);
 
1742
    sqlite3_free (sql);
 
1743
    if (ret != SQLITE_OK)
 
1744
        return;
 
1745
    if (rows < 1)
 
1746
        ;
 
1747
    else
 
1748
      {
 
1749
          for (i = 1; i <= rows; i++)
 
1750
            {
 
1751
                id = atoi (results[(i * columns) + 0]);
 
1752
                references = results[(i * columns) + 2];
 
1753
                from = results[(i * columns) + 3];
 
1754
                to = results[(i * columns) + 4];
 
1755
                on_update = results[(i * columns) + 5];
 
1756
                on_delete = results[(i * columns) + 6];
 
1757
                match = results[(i * columns) + 7];
 
1758
                if (strcasecmp (on_update, "NO ACTION") == 0)
 
1759
                    on_update = NULL;
 
1760
                if (strcasecmp (on_delete, "NO ACTION") == 0)
 
1761
                    on_delete = NULL;
 
1762
                if (strcasecmp (match, "NONE") == 0)
 
1763
                    match = NULL;
 
1764
                add_foreign_key (cloner, id, references, from, to, on_update,
 
1765
                                 on_delete, match);
 
1766
            }
 
1767
      }
 
1768
    sqlite3_free_table (results);
 
1769
}
 
1770
 
 
1771
static void
 
1772
check_input_table_triggers (struct aux_cloner *cloner)
 
1773
{
 
1774
/* exploring the input table - Triggers */
 
1775
    char *sql;
 
1776
    int ret;
 
1777
    int i;
 
1778
    char **results;
 
1779
    int rows;
 
1780
    int columns;
 
1781
    const char *name;
 
1782
    const char *sqlx;
 
1783
    char *xprefix;
 
1784
 
 
1785
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1786
    sql = sqlite3_mprintf ("SELECT name, sql FROM \"%s\".sqlite_master "
 
1787
                           "WHERE type = 'trigger' AND Lower(tbl_name) = Lower(%Q)",
 
1788
                           xprefix, cloner->in_table);
 
1789
    free (xprefix);
 
1790
    ret =
 
1791
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1792
                           NULL);
 
1793
    sqlite3_free (sql);
 
1794
    if (ret != SQLITE_OK)
 
1795
        return;
 
1796
    if (rows < 1)
 
1797
        ;
 
1798
    else
 
1799
      {
 
1800
          for (i = 1; i <= rows; i++)
 
1801
            {
 
1802
                name = results[(i * columns) + 0];
 
1803
                sqlx = results[(i * columns) + 1];
 
1804
                add_trigger (cloner, name, sqlx);
 
1805
            }
 
1806
      }
 
1807
    sqlite3_free_table (results);
 
1808
}
 
1809
 
 
1810
static void
 
1811
check_input_table_geometries (struct aux_cloner *cloner)
 
1812
{
 
1813
/* exploring the input table - Geometries */
 
1814
    char *sql;
 
1815
    int ret;
 
1816
    int i;
 
1817
    char **results;
 
1818
    int rows;
 
1819
    int columns;
 
1820
    const char *name;
 
1821
    int type;
 
1822
    int dims;
 
1823
    int srid;
 
1824
    int spatial_index;
 
1825
    char *xprefix;
 
1826
 
 
1827
    xprefix = gaiaDoubleQuotedSql (cloner->db_prefix);
 
1828
    sql = sqlite3_mprintf ("SELECT f_geometry_column, geometry_type, "
 
1829
                           "coord_dimension, srid, spatial_index_enabled "
 
1830
                           "FROM \"%s\".geometry_columns "
 
1831
                           "WHERE Lower(f_table_name) = Lower(%Q)",
 
1832
                           xprefix, cloner->in_table);
 
1833
    free (xprefix);
 
1834
    ret =
 
1835
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1836
                           NULL);
 
1837
    sqlite3_free (sql);
 
1838
    if (ret != SQLITE_OK)
 
1839
        return;
 
1840
    if (rows < 1)
 
1841
        ;
 
1842
    else
 
1843
      {
 
1844
          for (i = 1; i <= rows; i++)
 
1845
            {
 
1846
                name = results[(i * columns) + 0];
 
1847
                type = atoi (results[(i * columns) + 1]);
 
1848
                dims = atoi (results[(i * columns) + 2]);
 
1849
                srid = atoi (results[(i * columns) + 3]);
 
1850
                spatial_index = atoi (results[(i * columns) + 4]);
 
1851
                add_geometry (cloner, name, type, dims, srid, spatial_index);
 
1852
            }
 
1853
      }
 
1854
    sqlite3_free_table (results);
 
1855
}
 
1856
 
 
1857
static void
 
1858
check_output_table_geometries (struct aux_cloner *cloner)
 
1859
{
 
1860
/* exploring the output table - Geometries */
 
1861
    char *sql;
 
1862
    int ret;
 
1863
    int i;
 
1864
    char **results;
 
1865
    int rows;
 
1866
    int columns;
 
1867
    const char *name;
 
1868
    int type;
 
1869
    int dims;
 
1870
    int srid;
 
1871
 
 
1872
    sql = sqlite3_mprintf ("SELECT f_geometry_column, geometry_type, "
 
1873
                           "coord_dimension, srid, spatial_index_enabled "
 
1874
                           "FROM main.geometry_columns "
 
1875
                           "WHERE Lower(f_table_name) = Lower(%Q)",
 
1876
                           cloner->out_table);
 
1877
    ret =
 
1878
        sqlite3_get_table (cloner->sqlite, sql, &results, &rows, &columns,
 
1879
                           NULL);
 
1880
    sqlite3_free (sql);
 
1881
    if (ret != SQLITE_OK)
 
1882
        return;
 
1883
    if (rows < 1)
 
1884
        ;
 
1885
    else
 
1886
      {
 
1887
          for (i = 1; i <= rows; i++)
 
1888
            {
 
1889
                name = results[(i * columns) + 0];
 
1890
                type = atoi (results[(i * columns) + 1]);
 
1891
                dims = atoi (results[(i * columns) + 2]);
 
1892
                srid = atoi (results[(i * columns) + 3]);
 
1893
                mark_existing_geometry (cloner, name, type, dims, srid);
 
1894
            }
 
1895
      }
 
1896
    sqlite3_free_table (results);
 
1897
}
 
1898
 
 
1899
static void
 
1900
free_trigger (struct aux_trigger *trigger)
 
1901
{
 
1902
/* memory cleanup - destroying a Trigger object */
 
1903
    if (trigger == NULL)
 
1904
        return;
 
1905
    if (trigger->name != NULL)
 
1906
        free (trigger->name);
 
1907
    if (trigger->sql != NULL)
 
1908
        free (trigger->sql);
 
1909
    free (trigger);
 
1910
}
 
1911
 
 
1912
static void
 
1913
free_fk_columns (struct aux_fk_columns *col)
 
1914
{
 
1915
/* memory cleanup - destroying a Foreign Key Columns object */
 
1916
    if (col == NULL)
 
1917
        return;
 
1918
    if (col->from != NULL)
 
1919
        free (col->from);
 
1920
    if (col->to != NULL)
 
1921
        free (col->to);
 
1922
    free (col);
 
1923
}
 
1924
 
 
1925
static void
 
1926
free_foreign_key (struct aux_foreign_key *fk)
 
1927
{
 
1928
/* memory cleanup - destroying a Foreign Key object */
 
1929
    struct aux_fk_columns *pc;
 
1930
    struct aux_fk_columns *pcn;
 
1931
    if (fk == NULL)
 
1932
        return;
 
1933
    if (fk->name != NULL)
 
1934
        free (fk->name);
 
1935
    if (fk->references != NULL)
 
1936
        free (fk->references);
 
1937
    if (fk->on_update != NULL)
 
1938
        free (fk->on_update);
 
1939
    if (fk->on_delete != NULL)
 
1940
        free (fk->on_delete);
 
1941
    if (fk->match != NULL)
 
1942
        free (fk->match);
 
1943
    pc = fk->first;
 
1944
    while (pc != NULL)
 
1945
      {
 
1946
          pcn = pc->next;
 
1947
          free_fk_columns (pc);
 
1948
          pc = pcn;
 
1949
      }
 
1950
    free (fk);
 
1951
}
 
1952
 
 
1953
static void
 
1954
free_index_column (struct aux_index_column *column)
 
1955
{
 
1956
/* memory cleanup - destroying an Index Column object */
 
1957
    if (column == NULL)
 
1958
        return;
 
1959
    if (column->name != NULL)
 
1960
        free (column->name);
 
1961
    free (column);
 
1962
}
 
1963
 
 
1964
static void
 
1965
free_index (struct aux_index *index)
 
1966
{
 
1967
/* memory cleanup - destroying an Index object */
 
1968
    struct aux_index_column *pc;
 
1969
    struct aux_index_column *pcn;
 
1970
    if (index == NULL)
 
1971
        return;
 
1972
    if (index->name != NULL)
 
1973
        free (index->name);
 
1974
    pc = index->first;
 
1975
    while (pc != NULL)
 
1976
      {
 
1977
          pcn = pc->next;
 
1978
          free_index_column (pc);
 
1979
          pc = pcn;
 
1980
      }
 
1981
    free (index);
 
1982
}
 
1983
 
 
1984
static void
 
1985
free_column (struct aux_column *column)
 
1986
{
 
1987
/* memory cleanup - destroying a Column object */
 
1988
    if (column == NULL)
 
1989
        return;
 
1990
    if (column->name != NULL)
 
1991
        free (column->name);
 
1992
    if (column->type != NULL)
 
1993
        free (column->type);
 
1994
    if (column->deflt != NULL)
 
1995
        free (column->deflt);
 
1996
    if (column->geometry != NULL)
 
1997
        free (column->geometry);
 
1998
    free (column);
 
1999
}
 
2000
 
 
2001
static void
 
2002
free_cloner (struct aux_cloner *cloner)
 
2003
{
 
2004
/* memory cleanup - destroying a Cloner object */
 
2005
    struct aux_column *pc;
 
2006
    struct aux_column *pcn;
 
2007
    struct aux_pk_column *ppk;
 
2008
    struct aux_pk_column *ppkn;
 
2009
    struct aux_index *pi;
 
2010
    struct aux_index *pin;
 
2011
    struct aux_foreign_key *pfk;
 
2012
    struct aux_foreign_key *pfkn;
 
2013
    struct aux_trigger *ptrg;
 
2014
    struct aux_trigger *ptrgn;
 
2015
    if (cloner == NULL)
 
2016
        return;
 
2017
    if (cloner->db_prefix != NULL)
 
2018
        free (cloner->db_prefix);
 
2019
    if (cloner->in_table != NULL)
 
2020
        free (cloner->in_table);
 
2021
    if (cloner->out_table != NULL)
 
2022
        free (cloner->out_table);
 
2023
    pc = cloner->first_col;
 
2024
    while (pc != NULL)
 
2025
      {
 
2026
          pcn = pc->next;
 
2027
          free_column (pc);
 
2028
          pc = pcn;
 
2029
      }
 
2030
    ppk = cloner->first_pk;
 
2031
    while (ppk != NULL)
 
2032
      {
 
2033
          ppkn = ppk->next;
 
2034
          free (ppk);
 
2035
          ppk = ppkn;
 
2036
      }
 
2037
    pi = cloner->first_idx;
 
2038
    while (pi != NULL)
 
2039
      {
 
2040
          pin = pi->next;
 
2041
          free_index (pi);
 
2042
          pi = pin;
 
2043
      }
 
2044
    pfk = cloner->first_fk;
 
2045
    while (pfk != NULL)
 
2046
      {
 
2047
          pfkn = pfk->next;
 
2048
          free_foreign_key (pfk);
 
2049
          pfk = pfkn;
 
2050
      }
 
2051
    ptrg = cloner->first_trigger;
 
2052
    while (ptrg != NULL)
 
2053
      {
 
2054
          ptrgn = ptrg->next;
 
2055
          free_trigger (ptrg);
 
2056
          ptrg = ptrgn;
 
2057
      }
 
2058
    if (cloner->sorted_pks != NULL)
 
2059
        free (cloner->sorted_pks);
 
2060
    free (cloner);
 
2061
}
 
2062
 
 
2063
static int
 
2064
already_existing_table (sqlite3 * sqlite, const char *table)
 
2065
{
 
2066
/* testing if the target Table is already defined */
 
2067
    char *sql;
 
2068
    int ret;
 
2069
    int i;
 
2070
    char **results;
 
2071
    int rows;
 
2072
    int columns;
 
2073
    int count = 0;
 
2074
 
 
2075
    sql = sqlite3_mprintf ("SELECT Count(*) FROM main.sqlite_master "
 
2076
                           "WHERE type = 'table' AND Lower(name) = Lower(%Q)",
 
2077
                           table);
 
2078
    ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
 
2079
    sqlite3_free (sql);
 
2080
    if (ret != SQLITE_OK)
 
2081
        goto stop;
 
2082
    if (rows < 1)
 
2083
        ;
 
2084
    else
 
2085
      {
 
2086
          for (i = 1; i <= rows; i++)
 
2087
              count = atoi (results[(i * columns) + 0]);
 
2088
      }
 
2089
    sqlite3_free_table (results);
 
2090
  stop:
 
2091
    return count;
 
2092
}
 
2093
 
 
2094
SPATIALITE_PRIVATE const void *
 
2095
gaiaAuxClonerCreate (const void *sqlite, const char *db_prefix,
 
2096
                     const char *in_table, const char *out_table)
 
2097
{
 
2098
/* creating a Cloner object */
 
2099
    int len;
 
2100
    struct aux_cloner *cloner;
 
2101
    if (checkSpatialMetaData ((sqlite3 *) sqlite) < 3)
 
2102
      {
 
2103
          spatialite_e ("CloneTable: obsolete DB-layout (< 4.0.0)\n");
 
2104
          return NULL;
 
2105
      }
 
2106
 
 
2107
    cloner = malloc (sizeof (struct aux_cloner));
 
2108
    if (cloner == NULL)
 
2109
        return NULL;
 
2110
    cloner->sqlite = (sqlite3 *) sqlite;
 
2111
    cloner->db_prefix = NULL;
 
2112
    cloner->in_table = NULL;
 
2113
    cloner->out_table = NULL;
 
2114
    len = strlen (db_prefix);
 
2115
    cloner->db_prefix = malloc (len + 1);
 
2116
    strcpy (cloner->db_prefix, db_prefix);
 
2117
    len = strlen (in_table);
 
2118
    cloner->in_table = malloc (len + 1);
 
2119
    strcpy (cloner->in_table, in_table);
 
2120
    len = strlen (out_table);
 
2121
    cloner->out_table = malloc (len + 1);
 
2122
    strcpy (cloner->out_table, out_table);
 
2123
    cloner->first_col = NULL;
 
2124
    cloner->last_col = NULL;
 
2125
    cloner->first_pk = NULL;
 
2126
    cloner->last_pk = NULL;
 
2127
    cloner->first_idx = NULL;
 
2128
    cloner->last_idx = NULL;
 
2129
    cloner->first_fk = NULL;
 
2130
    cloner->last_fk = NULL;
 
2131
    cloner->first_trigger = NULL;
 
2132
    cloner->last_trigger = NULL;
 
2133
    cloner->pk_count = 0;
 
2134
    cloner->sorted_pks = NULL;
 
2135
    cloner->autoincrement = 0;
 
2136
    cloner->resequence = 0;
 
2137
    cloner->with_fks = 0;
 
2138
    cloner->with_triggers = 0;
 
2139
    cloner->append = 0;
 
2140
    cloner->already_existing = 0;
 
2141
 
 
2142
/* exploring the input table - Columns */
 
2143
    if (!check_input_table_columns (cloner))
 
2144
        goto error;
 
2145
/* exploring PRIMARY KEY AUTOINCREMENT */
 
2146
    check_input_table_autoincrement (cloner);
 
2147
/* exploring the input table - Index definitions */
 
2148
    check_input_table_index_defs (cloner);
 
2149
/* exploring the input table - Foreign Key definitions */
 
2150
    check_input_table_foreign_keys (cloner);
 
2151
/* exploring the input table - Trigger definitions */
 
2152
    check_input_table_triggers (cloner);
 
2153
/* exploring the input table - Geometry definitions */
 
2154
    check_input_table_geometries (cloner);
 
2155
 
 
2156
    if (already_existing_table (cloner->sqlite, out_table))
 
2157
        cloner->already_existing = 1;
 
2158
    return cloner;
 
2159
  error:
 
2160
    free_cloner (cloner);
 
2161
    return NULL;
 
2162
}
 
2163
 
 
2164
SPATIALITE_PRIVATE void
 
2165
gaiaAuxClonerDestroy (const void *handle)
 
2166
{
 
2167
/* destroying a Cloner object */
 
2168
    struct aux_cloner *cloner = (struct aux_cloner *) handle;
 
2169
    if (handle == NULL)
 
2170
        return;
 
2171
    free_cloner (cloner);
 
2172
}
 
2173
 
 
2174
static void
 
2175
ignore_column (struct aux_cloner *cloner, const char *column)
 
2176
{
 
2177
/* marking a Column to be ignored */
 
2178
    struct aux_column *pc = cloner->first_col;
 
2179
    while (pc != NULL)
 
2180
      {
 
2181
          if (strcasecmp (pc->name, column) == 0)
 
2182
            {
 
2183
                pc->ignore = 1;
 
2184
                return;
 
2185
            }
 
2186
          pc = pc->next;
 
2187
      }
 
2188
}
 
2189
 
 
2190
static int
 
2191
check_append (struct aux_cloner *cloner)
 
2192
{
 
2193
/* cheching for APPEND validity */
 
2194
    int error = 0;
 
2195
    struct aux_column *column = cloner->first_col;
 
2196
    while (column != NULL)
 
2197
      {
 
2198
          if (column->mismatching)
 
2199
              error = 1;
 
2200
          column = column->next;
 
2201
      }
 
2202
    if (error)
 
2203
        return 0;
 
2204
    return 1;
 
2205
}
 
2206
 
 
2207
static void
 
2208
cast2multi_column (struct aux_cloner *cloner, const char *column)
 
2209
{
 
2210
/* marking a Geometry Column to be casted to MultiType */
 
2211
    struct aux_column *pc = cloner->first_col;
 
2212
    while (pc != NULL)
 
2213
      {
 
2214
          if (strcasecmp (pc->name, column) == 0 && pc->geometry != NULL)
 
2215
            {
 
2216
                pc->geometry->cast2multi = 1;
 
2217
                return;
 
2218
            }
 
2219
          pc = pc->next;
 
2220
      }
 
2221
}
 
2222
 
 
2223
SPATIALITE_PRIVATE void
 
2224
gaiaAuxClonerAddOption (const void *handle, const char *option)
 
2225
{
 
2226
/* parsing an Option */
 
2227
    struct aux_cloner *cloner = (struct aux_cloner *) handle;
 
2228
    if (handle == NULL)
 
2229
        return;
 
2230
    if (strncasecmp (option, "::ignore::", 10) == 0)
 
2231
        ignore_column (cloner, option + 10);
 
2232
    if (strncasecmp (option, "::cast2multi::", 14) == 0)
 
2233
        cast2multi_column (cloner, option + 14);
 
2234
    if (strncasecmp (option, "::resequence::", 14) == 0)
 
2235
        cloner->resequence = 1;
 
2236
    if (strncasecmp (option, "::with-foreign-keys::", 21) == 0)
 
2237
        cloner->with_fks = 1;
 
2238
    if (strncasecmp (option, "::with-triggers::", 17) == 0)
 
2239
        cloner->with_triggers = 1;
 
2240
    if (strncasecmp (option, "::append::", 10) == 0)
 
2241
      {
 
2242
          cloner->append = 1;
 
2243
          cloner->resequence = 1;
 
2244
      }
 
2245
    return;
 
2246
}
 
2247
 
 
2248
SPATIALITE_PRIVATE int
 
2249
gaiaAuxClonerCheckValidTarget (const void *handle)
 
2250
{
 
2251
/* checking the Target Table for validity */
 
2252
    struct aux_cloner *cloner = (struct aux_cloner *) handle;
 
2253
    if (handle == NULL)
 
2254
        return 0;
 
2255
 
 
2256
    if (cloner->already_existing)
 
2257
      {
 
2258
          if (cloner->append)
 
2259
            {
 
2260
                /* exploring the output table - Columns */
 
2261
                check_output_table_columns (cloner);
 
2262
                /* exploring the output table - Geometries */
 
2263
                check_output_table_geometries (cloner);
 
2264
                /* checking for validity */
 
2265
                if (!check_append (cloner))
 
2266
                  {
 
2267
                      spatialite_e
 
2268
                          ("CloneTable: output table \"%s\" can't support APPEND\n",
 
2269
                           cloner->out_table);
 
2270
                      return 0;
 
2271
                  }
 
2272
            }
 
2273
          else
 
2274
            {
 
2275
                spatialite_e
 
2276
                    ("CloneTable: output table \"%s\" already exists and APPEND is not enabled\n",
 
2277
                     cloner->out_table);
 
2278
                return 0;
 
2279
            }
 
2280
      }
 
2281
    return 1;
 
2282
}
 
2283
 
 
2284
SPATIALITE_PRIVATE int
 
2285
gaiaAuxClonerExecute (const void *handle)
 
2286
{
 
2287
/* executing the actual work */
 
2288
    struct aux_cloner *cloner = (struct aux_cloner *) handle;
 
2289
    if (handle == NULL)
 
2290
        return 0;
 
2291
    if (cloner->already_existing)
 
2292
      {
 
2293
          /* creating any further column if required */
 
2294
          if (!upgrade_output_table (cloner))
 
2295
            {
 
2296
                spatialite_e
 
2297
                    ("CloneTable: unable to updgrade the output table \"%s\"\n",
 
2298
                     cloner->out_table);
 
2299
                return 0;
 
2300
            }
 
2301
      }
 
2302
    else
 
2303
      {
 
2304
          /* creating the output table */
 
2305
          if (!create_output_table (cloner))
 
2306
            {
 
2307
                spatialite_e
 
2308
                    ("CloneTable: unable to create the output table \"%s\"\n",
 
2309
                     cloner->out_table);
 
2310
                return 0;
 
2311
            }
 
2312
      }
 
2313
    if (!copy_rows (cloner))
 
2314
      {
 
2315
          spatialite_e ("CloneTable: unable to copy Table rows\n");
 
2316
          return 0;
 
2317
      }
 
2318
    return 1;
 
2319
}