1 /*
2
3 metatables.c -- creating the metadata tables and related triggers
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):
31 Pepijn Van Eeckhoudt <pepijnvaneeckhoudt@luciad.com>
32 (implementing Android support)
33
34 Mark Johnson <mj10777@googlemail.com>
35 (checking triggers supporting a supposed Writable Spatial View)
36
37 Alternatively, the contents of this file may be used under the terms of
38 either the GNU General Public License Version 2 or later (the "GPL"), or
39 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
40 in which case the provisions of the GPL or the LGPL are applicable instead
41 of those above. If you wish to allow use of your version of this file only
42 under the terms of either the GPL or the LGPL, and not to allow others to
43 use your version of this file under the terms of the MPL, indicate your
44 decision by deleting the provisions above and replace them with the notice
45 and other provisions required by the GPL or the LGPL. If you do not delete
46 the provisions above, a recipient may use your version of this file under
47 the terms of any one of the MPL, the GPL or the LGPL.
48
49 */
50
51 #include <sys/types.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.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.h>
67 #include <spatialite/spatialite_ext.h>
68 #include <spatialite_private.h>
69 #include <spatialite/gaiaaux.h>
70 #include <spatialite/gaiageo.h>
71
72 #ifdef _WIN32
73 #define strcasecmp _stricmp
74 #endif /* not WIN32 */
75
76 struct rtree_envelope
77 {
78 int valid;
79 double minx;
80 double maxx;
81 double miny;
82 double maxy;
83 };
84
85 struct spatial_index_str
86 {
87 /* a struct to implement a linked list of spatial-indexes */
88 char ValidRtree;
89 char ValidCache;
90 char *TableName;
91 char *ColumnName;
92 struct spatial_index_str *Next;
93 };
94
95 static int
testSpatiaLiteHistory(sqlite3 * sqlite)96 testSpatiaLiteHistory (sqlite3 * sqlite)
97 {
98 /* internal utility function:
99 /
100 / checks if the SPATIALITE_HISTORY table already exists
101 /
102 */
103 int event_id = 0;
104 int table_name = 0;
105 int geometry_column = 0;
106 int event = 0;
107 int timestamp = 0;
108 int ver_sqlite = 0;
109 int ver_splite = 0;
110 char sql[1024];
111 int ret;
112 const char *name;
113 int i;
114 char **results;
115 int rows;
116 int columns;
117 /* checking the SPATIALITE_HISTORY table */
118 strcpy (sql, "PRAGMA table_info(spatialite_history)");
119 ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
120 if (ret != SQLITE_OK)
121 return 0;
122 if (rows < 1)
123 ;
124 else
125 {
126 for (i = 1; i <= rows; i++)
127 {
128 name = results[(i * columns) + 1];
129 if (strcasecmp (name, "event_id") == 0)
130 event_id = 1;
131 if (strcasecmp (name, "table_name") == 0)
132 table_name = 1;
133 if (strcasecmp (name, "geometry_column") == 0)
134 geometry_column = 1;
135 if (strcasecmp (name, "event") == 0)
136 event = 1;
137 if (strcasecmp (name, "timestamp") == 0)
138 timestamp = 1;
139 if (strcasecmp (name, "ver_sqlite") == 0)
140 ver_sqlite = 1;
141 if (strcasecmp (name, "ver_splite") == 0)
142 ver_splite = 1;
143 }
144 }
145 sqlite3_free_table (results);
146 if (event_id && table_name && geometry_column && event && timestamp
147 && ver_sqlite && ver_splite)
148 return 1;
149 return 0;
150 }
151
152 static int
checkSpatiaLiteHistory(sqlite3 * sqlite)153 checkSpatiaLiteHistory (sqlite3 * sqlite)
154 {
155 /* internal utility function:
156 /
157 / checks if the SPATIALITE_HISTORY table already exists
158 / if not, such table will then be created
159 /
160 */
161 char sql[1024];
162 char *errMsg = NULL;
163 int ret;
164
165 if (testSpatiaLiteHistory (sqlite))
166 return 1;
167
168 /* creating the SPATIALITE_HISTORY table */
169 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
170 strcat (sql, "spatialite_history (\n");
171 strcat (sql, "event_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n");
172 strcat (sql, "table_name TEXT NOT NULL,\n");
173 strcat (sql, "geometry_column TEXT,\n");
174 strcat (sql, "event TEXT NOT NULL,\n");
175 strcat (sql, "timestamp TEXT NOT NULL,\n");
176 strcat (sql, "ver_sqlite TEXT NOT NULL,\n");
177 strcat (sql, "ver_splite TEXT NOT NULL)");
178 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
179 if (ret != SQLITE_OK)
180 return 0;
181
182 if (testSpatiaLiteHistory (sqlite))
183 return 1;
184 return 0;
185 }
186
187 SPATIALITE_PRIVATE void
updateSpatiaLiteHistory(void * p_sqlite,const char * table,const char * geom,const char * operation)188 updateSpatiaLiteHistory (void *p_sqlite, const char *table,
189 const char *geom, const char *operation)
190 {
191 /* inserting a row in SPATIALITE_HISTORY */
192 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
193 char sql[2048];
194 sqlite3_stmt *stmt = NULL;
195 int ret;
196
197 if (checkSpatiaLiteHistory (sqlite) == 0)
198 return;
199
200 strcpy (sql, "INSERT INTO spatialite_history ");
201 strcat (sql, "(event_id, table_name, geometry_column, event, timestamp, ");
202 strcat (sql, "ver_sqlite, ver_splite) VALUES (NULL, ?, ?, ?, ");
203 strcat (sql, "strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), ");
204 strcat (sql, "sqlite_version(), spatialite_version())");
205 ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
206 if (ret != SQLITE_OK)
207 {
208 spatialite_e ("SQL error: %s: %s\n", sql, sqlite3_errmsg (sqlite));
209 goto stop;
210 }
211 sqlite3_reset (stmt);
212 sqlite3_clear_bindings (stmt);
213 sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
214 if (!geom)
215 sqlite3_bind_null (stmt, 2);
216 else
217 sqlite3_bind_text (stmt, 2, geom, strlen (geom), SQLITE_STATIC);
218 sqlite3_bind_text (stmt, 3, operation, strlen (operation), SQLITE_STATIC);
219 ret = sqlite3_step (stmt);
220 if (ret == SQLITE_DONE || ret == SQLITE_ROW)
221 goto stop;
222 spatialite_e ("SQL error: %s\n", sqlite3_errmsg (sqlite));
223
224 stop:
225 if (stmt)
226 sqlite3_finalize (stmt);
227 }
228
229 static int
create_views_geometry_columns(sqlite3 * sqlite)230 create_views_geometry_columns (sqlite3 * sqlite)
231 {
232 char sql[4186];
233 char *errMsg = NULL;
234 int ret;
235
236 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
237 {
238 /* ignoring a read-only database */
239 return 1;
240 }
241
242 /* creating the VIEWS_GEOMETRY_COLUMNS table */
243 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
244 strcat (sql, "views_geometry_columns (\n");
245 strcat (sql, "view_name TEXT NOT NULL,\n");
246 strcat (sql, "view_geometry TEXT NOT NULL,\n");
247 strcat (sql, "view_rowid TEXT NOT NULL,\n");
248 strcat (sql, "f_table_name TEXT NOT NULL,\n");
249 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
250 strcat (sql, "read_only INTEGER NOT NULL,\n");
251 strcat (sql, "CONSTRAINT pk_geom_cols_views PRIMARY KEY ");
252 strcat (sql, "(view_name, view_geometry),\n");
253 strcat (sql, "CONSTRAINT fk_views_geom_cols FOREIGN KEY ");
254 strcat (sql, "(f_table_name, f_geometry_column) ");
255 strcat (sql, "REFERENCES geometry_columns ");
256 strcat (sql, "(f_table_name, f_geometry_column) ");
257 strcat (sql, "ON DELETE CASCADE,\n");
258 strcat (sql, "CONSTRAINT ck_vw_rdonly CHECK (read_only IN ");
259 strcat (sql, "(0,1)))");
260 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
261 if (ret != SQLITE_OK)
262 {
263 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
264 sqlite3_free (errMsg);
265 return 0;
266 }
267 /* creating an INDEX supporting the GEOMETRY_COLUMNS FK */
268 strcpy (sql, "CREATE INDEX IF NOT EXISTS ");
269 strcat (sql, "idx_viewsjoin ON views_geometry_columns\n");
270 strcat (sql, "(f_table_name, f_geometry_column)");
271 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
272 if (ret != SQLITE_OK)
273 {
274 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
275 sqlite3_free (errMsg);
276 return 0;
277 }
278 /* creating the VIEWS_GEOMETRY_COLUMNS triggers */
279 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_name_insert\n");
280 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns'\n");
281 strcat (sql, "FOR EACH ROW BEGIN\n");
282 strcat (sql,
283 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
284 strcat (sql, "view_name value must not contain a single quote')\n");
285 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
286 strcat (sql,
287 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
288 strcat (sql, "view_name value must not contain a double quote')\n");
289 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
290 strcat (sql,
291 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n");
292 strcat (sql, "view_name value must be lower case')\n");
293 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
294 strcat (sql, "END");
295 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
296 if (ret != SQLITE_OK)
297 {
298 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
299 sqlite3_free (errMsg);
300 return 0;
301 }
302 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_name_update\n");
303 strcat (sql, "BEFORE UPDATE OF 'view_name' ON 'views_geometry_columns'\n");
304 strcat (sql, "FOR EACH ROW BEGIN\n");
305 strcat (sql,
306 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
307 strcat (sql, "view_name value must not contain a single quote')\n");
308 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
309 strcat (sql,
310 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
311 strcat (sql, "view_name value must not contain a double quote')\n");
312 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
313 strcat (sql,
314 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
315 strcat (sql, "view_name value must be lower case')\n");
316 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
317 strcat (sql, "END");
318 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
319 if (ret != SQLITE_OK)
320 {
321 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
322 sqlite3_free (errMsg);
323 return 0;
324 }
325 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_geometry_insert\n");
326 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns'\n");
327 strcat (sql, "FOR EACH ROW BEGIN\n");
328 strcat (sql,
329 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
330 strcat (sql, "view_geometry value must not contain a single quote')\n");
331 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
332 strcat (sql,
333 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n");
334 strcat (sql, "view_geometry value must not contain a double quote')\n");
335 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
336 strcat (sql,
337 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
338 strcat (sql, "view_geometry value must be lower case')\n");
339 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
340 strcat (sql, "END");
341 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
342 if (ret != SQLITE_OK)
343 {
344 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
345 sqlite3_free (errMsg);
346 return 0;
347 }
348 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_geometry_update\n");
349 strcat (sql,
350 "BEFORE UPDATE OF 'view_geometry' ON 'views_geometry_columns'\n");
351 strcat (sql, "FOR EACH ROW BEGIN\n");
352 strcat (sql,
353 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
354 strcat (sql, "view_geometry value must not contain a single quote')\n");
355 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
356 strcat (sql,
357 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: \n");
358 strcat (sql, "view_geometry value must not contain a double quote')\n");
359 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
360 strcat (sql,
361 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
362 strcat (sql, "view_geometry value must be lower case')\n");
363 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
364 strcat (sql, "END");
365 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
366 if (ret != SQLITE_OK)
367 {
368 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
369 sqlite3_free (errMsg);
370 return 0;
371 }
372 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_rowid_update\n");
373 strcat (sql, "BEFORE UPDATE OF 'view_rowid' ON 'views_geometry_columns'\n");
374 strcat (sql, "FOR EACH ROW BEGIN\n");
375 strcat (sql,
376 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
377 strcat (sql, "view_rowid value must not contain a single quote')\n");
378 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
379 strcat (sql,
380 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
381 strcat (sql, "view_rowid value must not contain a double quote')\n");
382 strcat (sql, "WHERE NEW.view_rowid LIKE ('%\"%');\n");
383 strcat (sql,
384 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
385 strcat (sql, "view_rowid value must be lower case')\n");
386 strcat (sql, "WHERE NEW.view_rowid <> lower(NEW.view_rowid);\n");
387 strcat (sql, "END");
388 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
389 if (ret != SQLITE_OK)
390 {
391 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
392 sqlite3_free (errMsg);
393 return 0;
394 }
395 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_view_rowid_insert\n");
396 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns'\n");
397 strcat (sql, "FOR EACH ROW BEGIN\n");
398 strcat (sql,
399 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
400 strcat (sql, "view_rowid value must not contain a single quote')\n");
401 strcat (sql, "WHERE NEW.view_rowid LIKE ('%''%');\n");
402 strcat (sql,
403 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n");
404 strcat (sql, "view_rowid value must not contain a double quote')\n");
405 strcat (sql, "WHERE NEW.view_rowid LIKE ('%\"%');\n");
406 strcat (sql,
407 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
408 strcat (sql, "view_rowid value must be lower case')\n");
409 strcat (sql, "WHERE NEW.view_rowid <> lower(NEW.view_rowid);\n");
410 strcat (sql, "END");
411 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
412 if (ret != SQLITE_OK)
413 {
414 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
415 sqlite3_free (errMsg);
416 return 0;
417 }
418 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_f_table_name_insert\n");
419 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns'\n");
420 strcat (sql, "FOR EACH ROW BEGIN\n");
421 strcat (sql,
422 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
423 strcat (sql, "f_table_name value must not contain a single quote')\n");
424 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
425 strcat (sql,
426 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
427 strcat (sql, "f_table_name value must not contain a double quote')\n");
428 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
429 strcat (sql,
430 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n");
431 strcat (sql, "f_table_name value must be lower case')\n");
432 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
433 strcat (sql, "END");
434 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
435 if (ret != SQLITE_OK)
436 {
437 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
438 sqlite3_free (errMsg);
439 return 0;
440 }
441 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgc_f_table_name_update\n");
442 strcat (sql,
443 "BEFORE UPDATE OF 'f_table_name' ON 'views_geometry_columns'\n");
444 strcat (sql, "FOR EACH ROW BEGIN\n");
445 strcat (sql,
446 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
447 strcat (sql, "f_table_name value must not contain a single quote')\n");
448 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
449 strcat (sql,
450 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
451 strcat (sql, "f_table_name value must not contain a double quote')\n");
452 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
453 strcat (sql,
454 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
455 strcat (sql, "f_table_name value must be lower case')\n");
456 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
457 strcat (sql, "END");
458 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
459 if (ret != SQLITE_OK)
460 {
461 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
462 sqlite3_free (errMsg);
463 return 0;
464 }
465 strcpy (sql,
466 "CREATE TRIGGER IF NOT EXISTS vwgc_f_geometry_column_insert\n");
467 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns'\n");
468 strcat (sql, "FOR EACH ROW BEGIN\n");
469 strcat (sql,
470 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
471 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
472 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
473 strcat (sql,
474 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n");
475 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
476 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
477 strcat (sql,
478 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: ");
479 strcat (sql, "f_geometry_column value must be lower case')\n");
480 strcat (sql,
481 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
482 strcat (sql, "END");
483 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
484 if (ret != SQLITE_OK)
485 {
486 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
487 sqlite3_free (errMsg);
488 return 0;
489 }
490 strcpy (sql,
491 "CREATE TRIGGER IF NOT EXISTS vwgc_f_geometry_column_update\n");
492 strcat (sql,
493 "BEFORE UPDATE OF 'f_geometry_column' ON 'views_geometry_columns'\n");
494 strcat (sql, "FOR EACH ROW BEGIN\n");
495 strcat (sql,
496 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
497 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
498 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
499 strcat (sql,
500 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
501 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
502 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
503 strcat (sql,
504 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: ");
505 strcat (sql, "f_geometry_column value must be lower case')\n");
506 strcat (sql,
507 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
508 strcat (sql, "END");
509 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
510 if (ret != SQLITE_OK)
511 {
512 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
513 sqlite3_free (errMsg);
514 return 0;
515 }
516 return 1;
517 }
518
519 static int
create_virts_geometry_columns(sqlite3 * sqlite)520 create_virts_geometry_columns (sqlite3 * sqlite)
521 {
522 char sql[4186];
523 char *errMsg = NULL;
524 int ret;
525
526 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
527 {
528 /* ignoring a read-only database */
529 return 1;
530 }
531
532 /* creating the VIRTS_GEOMETRY_COLUMNS table */
533 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
534 strcat (sql, "virts_geometry_columns (\n");
535 strcat (sql, "virt_name TEXT NOT NULL,\n");
536 strcat (sql, "virt_geometry TEXT NOT NULL,\n");
537 strcat (sql, "geometry_type INTEGER NOT NULL,\n");
538 strcat (sql, "coord_dimension INTEGER NOT NULL,\n");
539 strcat (sql, "srid INTEGER NOT NULL,\n");
540 strcat (sql, "CONSTRAINT pk_geom_cols_virts PRIMARY KEY ");
541 strcat (sql, "(virt_name, virt_geometry),\n");
542 strcat (sql, "CONSTRAINT fk_vgc_srid FOREIGN KEY ");
543 strcat (sql, "(srid) REFERENCES spatial_ref_sys (srid))");
544 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
545 if (ret != SQLITE_OK)
546 {
547 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
548 sqlite3_free (errMsg);
549 return 0;
550 }
551 /* creating an INDEX supporting the SPATIAL_REF_SYS FK */
552 strcpy (sql, "CREATE INDEX IF NOT EXISTS ");
553 strcat (sql, "idx_virtssrid ON virts_geometry_columns\n");
554 strcat (sql, "(srid)");
555 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
556 if (ret != SQLITE_OK)
557 {
558 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
559 sqlite3_free (errMsg);
560 return 0;
561 }
562 /* creating the VIRTS_GEOMETRY_COLUMNS triggers */
563 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_virt_name_insert\n");
564 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns'\n");
565 strcat (sql, "FOR EACH ROW BEGIN\n");
566 strcat (sql,
567 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: ");
568 strcat (sql, "virt_name value must not contain a single quote')\n");
569 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
570 strcat (sql,
571 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: ");
572 strcat (sql, "virt_name value must not contain a double quote')\n");
573 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
574 strcat (sql,
575 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: \n");
576 strcat (sql, "virt_name value must be lower case')\n");
577 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
578 strcat (sql, "END");
579 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
580 if (ret != SQLITE_OK)
581 {
582 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
583 sqlite3_free (errMsg);
584 return 0;
585 }
586 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_virt_name_update\n");
587 strcat (sql, "BEFORE UPDATE OF 'virt_name' ON 'virts_geometry_columns'\n");
588 strcat (sql, "FOR EACH ROW BEGIN\n");
589 strcat (sql,
590 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: ");
591 strcat (sql, "virt_name value must not contain a single quote')\n");
592 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
593 strcat (sql,
594 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: ");
595 strcat (sql, "virt_name value must not contain a double quote')\n");
596 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
597 strcat (sql,
598 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: ");
599 strcat (sql, "virt_name value must be lower case')\n");
600 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
601 strcat (sql, "END");
602 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
603 if (ret != SQLITE_OK)
604 {
605 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
606 sqlite3_free (errMsg);
607 return 0;
608 }
609 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_virt_geometry_insert\n");
610 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns'\n");
611 strcat (sql, "FOR EACH ROW BEGIN\n");
612 strcat (sql,
613 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: ");
614 strcat (sql, "virt_geometry value must not contain a single quote')\n");
615 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
616 strcat (sql,
617 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: \n");
618 strcat (sql, "virt_geometry value must not contain a double quote')\n");
619 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
620 strcat (sql,
621 "SELECT RAISE(ABORT,'insert on virts_geometry_columns violates constraint: ");
622 strcat (sql, "virt_geometry value must be lower case')\n");
623 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
624 strcat (sql, "END");
625 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
626 if (ret != SQLITE_OK)
627 {
628 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
629 sqlite3_free (errMsg);
630 return 0;
631 }
632 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_virt_geometry_update\n");
633 strcat (sql,
634 "BEFORE UPDATE OF 'virt_geometry' ON 'virts_geometry_columns'\n");
635 strcat (sql, "FOR EACH ROW BEGIN\n");
636 strcat (sql,
637 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: ");
638 strcat (sql, "virt_geometry value must not contain a single quote')\n");
639 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
640 strcat (sql,
641 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: \n");
642 strcat (sql, "virt_geometry value must not contain a double quote')\n");
643 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
644 strcat (sql,
645 "SELECT RAISE(ABORT,'update on virts_geometry_columns violates constraint: ");
646 strcat (sql, "virt_geometry value must be lower case')\n");
647 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
648 strcat (sql, "END");
649 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
650 if (ret != SQLITE_OK)
651 {
652 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
653 sqlite3_free (errMsg);
654 return 0;
655 }
656 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_geometry_type_insert\n");
657 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns'\n");
658 strcat (sql, "FOR EACH ROW BEGIN\n");
659 strcat (sql, "SELECT RAISE(ABORT,'geometry_type must be one of ");
660 strcat (sql, "0,1,2,3,4,5,6,7,");
661 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
662 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
663 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007')\n");
664 strcat (sql, "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,");
665 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
666 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
667 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007));\n");
668 strcat (sql, "END");
669 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
670 if (ret != SQLITE_OK)
671 {
672 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
673 sqlite3_free (errMsg);
674 return 0;
675 }
676 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_geometry_type_update\n");
677 strcat (sql,
678 "BEFORE UPDATE OF 'geometry_type' ON 'virts_geometry_columns'\n");
679 strcat (sql, "FOR EACH ROW BEGIN\n");
680 strcat (sql, "SELECT RAISE(ABORT,'geometry_type must be one of ");
681 strcat (sql, "0,1,2,3,4,5,6,7,");
682 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
683 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
684 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007')\n");
685 strcat (sql, "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,");
686 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
687 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
688 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007));\n");
689 strcat (sql, "END");
690 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
691 if (ret != SQLITE_OK)
692 {
693 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
694 sqlite3_free (errMsg);
695 return 0;
696 }
697 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_coord_dimension_insert\n");
698 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns'\n");
699 strcat (sql, "FOR EACH ROW BEGIN\n");
700 strcat (sql,
701 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n");
702 strcat (sql, "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n");
703 strcat (sql, "END");
704 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
705 if (ret != SQLITE_OK)
706 {
707 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
708 sqlite3_free (errMsg);
709 return 0;
710 }
711 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgc_coord_dimension_update\n");
712 strcat (sql,
713 "BEFORE UPDATE OF 'coord_dimension' ON 'virts_geometry_columns'\n");
714 strcat (sql, "FOR EACH ROW BEGIN\n");
715 strcat (sql,
716 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n");
717 strcat (sql, "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n");
718 strcat (sql, "END");
719 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
720 if (ret != SQLITE_OK)
721 {
722 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
723 sqlite3_free (errMsg);
724 return 0;
725 }
726 return 1;
727 }
728
729 static int
create_geometry_columns_statistics(sqlite3 * sqlite)730 create_geometry_columns_statistics (sqlite3 * sqlite)
731 {
732 char sql[4186];
733 char *errMsg = NULL;
734 int ret;
735
736 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
737 {
738 /* ignoring a read-only database */
739 return 1;
740 }
741
742 /* creating the GEOMETRY_COLUMNS_STATISTICS table */
743 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
744 strcat (sql, "geometry_columns_statistics (\n");
745 strcat (sql, "f_table_name TEXT NOT NULL,\n");
746 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
747 strcat (sql, "last_verified TIMESTAMP,\n");
748 strcat (sql, "row_count INTEGER,\n");
749 strcat (sql, "extent_min_x DOUBLE,\n");
750 strcat (sql, "extent_min_y DOUBLE,\n");
751 strcat (sql, "extent_max_x DOUBLE,\n");
752 strcat (sql, "extent_max_y DOUBLE,\n");
753 strcat (sql, "CONSTRAINT pk_gc_statistics PRIMARY KEY ");
754 strcat (sql, "(f_table_name, f_geometry_column),\n");
755 strcat (sql, "CONSTRAINT fk_gc_statistics FOREIGN KEY ");
756 strcat (sql, "(f_table_name, f_geometry_column) REFERENCES ");
757 strcat (sql, "geometry_columns (f_table_name, f_geometry_column) ");
758 strcat (sql, "ON DELETE CASCADE)");
759 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
760 if (ret != SQLITE_OK)
761 {
762 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
763 sqlite3_free (errMsg);
764 return 0;
765 }
766 /* creating the GEOMETRY_COLUMNS_STATISTICS triggers */
767 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcs_f_table_name_insert\n");
768 strcat (sql, "BEFORE INSERT ON 'geometry_columns_statistics'\n");
769 strcat (sql, "FOR EACH ROW BEGIN\n");
770 strcat (sql,
771 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: ");
772 strcat (sql, "f_table_name value must not contain a single quote')\n");
773 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
774 strcat (sql,
775 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: ");
776 strcat (sql, "f_table_name value must not contain a double quote')\n");
777 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
778 strcat (sql,
779 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: \n");
780 strcat (sql, "f_table_name value must be lower case')\n");
781 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
782 strcat (sql, "END");
783 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
784 if (ret != SQLITE_OK)
785 {
786 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
787 sqlite3_free (errMsg);
788 return 0;
789 }
790 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcs_f_table_name_update\n");
791 strcat (sql,
792 "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns_statistics'\n");
793 strcat (sql, "FOR EACH ROW BEGIN\n");
794 strcat (sql,
795 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
796 strcat (sql, "f_table_name value must not contain a single quote')\n");
797 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
798 strcat (sql,
799 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
800 strcat (sql, "f_table_name value must not contain a double quote')\n");
801 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
802 strcat (sql,
803 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
804 strcat (sql, "f_table_name value must be lower case')\n");
805 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
806 strcat (sql, "END");
807 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
808 if (ret != SQLITE_OK)
809 {
810 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
811 sqlite3_free (errMsg);
812 return 0;
813 }
814 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcs_f_geometry_column_insert\n");
815 strcat (sql, "BEFORE INSERT ON 'geometry_columns_statistics'\n");
816 strcat (sql, "FOR EACH ROW BEGIN\n");
817 strcat (sql,
818 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: ");
819 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
820 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
821 strcat (sql,
822 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: \n");
823 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
824 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
825 strcat (sql,
826 "SELECT RAISE(ABORT,'insert on geometry_columns_statistics violates constraint: ");
827 strcat (sql, "f_geometry_column value must be lower case')\n");
828 strcat (sql,
829 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
830 strcat (sql, "END");
831 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
832 if (ret != SQLITE_OK)
833 {
834 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
835 sqlite3_free (errMsg);
836 return 0;
837 }
838 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcs_f_geometry_column_update\n");
839 strcat (sql,
840 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns_statistics'\n");
841 strcat (sql, "FOR EACH ROW BEGIN\n");
842 strcat (sql,
843 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
844 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
845 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
846 strcat (sql,
847 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
848 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
849 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
850 strcat (sql,
851 "SELECT RAISE(ABORT,'update on geometry_columns_statistics violates constraint: ");
852 strcat (sql, "f_geometry_column value must be lower case')\n");
853 strcat (sql,
854 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
855 strcat (sql, "END");
856 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
857 if (ret != SQLITE_OK)
858 {
859 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
860 sqlite3_free (errMsg);
861 return 0;
862 }
863 return 1;
864 }
865
866 static int
create_views_geometry_columns_statistics(sqlite3 * sqlite)867 create_views_geometry_columns_statistics (sqlite3 * sqlite)
868 {
869 char sql[4186];
870 char *errMsg = NULL;
871 int ret;
872
873 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
874 {
875 /* ignoring a read-only database */
876 return 1;
877 }
878
879 /* creating the VIEWS_GEOMETRY_COLUMNS_STATISTICS table */
880 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
881 strcat (sql, "views_geometry_columns_statistics (\n");
882 strcat (sql, "view_name TEXT NOT NULL,\n");
883 strcat (sql, "view_geometry TEXT NOT NULL,\n");
884 strcat (sql, "last_verified TIMESTAMP,\n");
885 strcat (sql, "row_count INTEGER,\n");
886 strcat (sql, "extent_min_x DOUBLE,\n");
887 strcat (sql, "extent_min_y DOUBLE,\n");
888 strcat (sql, "extent_max_x DOUBLE,\n");
889 strcat (sql, "extent_max_y DOUBLE,\n");
890 strcat (sql, "CONSTRAINT pk_vwgc_statistics PRIMARY KEY ");
891 strcat (sql, "(view_name, view_geometry),\n");
892 strcat (sql, "CONSTRAINT fk_vwgc_statistics FOREIGN KEY ");
893 strcat (sql, "(view_name, view_geometry) REFERENCES ");
894 strcat (sql, "views_geometry_columns (view_name, view_geometry) ");
895 strcat (sql, "ON DELETE CASCADE)");
896 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
897 if (ret != SQLITE_OK)
898 {
899 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
900 sqlite3_free (errMsg);
901 return 0;
902 }
903 /* creating the VIEWS_GEOMETRY_COLUMNS_STATISTICS triggers */
904 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcs_view_name_insert\n");
905 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_statistics'\n");
906 strcat (sql, "FOR EACH ROW BEGIN\n");
907 strcat (sql,
908 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: ");
909 strcat (sql, "view_name value must not contain a single quote')\n");
910 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
911 strcat (sql,
912 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: ");
913 strcat (sql, "view_name value must not contain a double quote')\n");
914 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
915 strcat (sql,
916 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: \n");
917 strcat (sql, "view_name value must be lower case')\n");
918 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
919 strcat (sql, "END");
920 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
921 if (ret != SQLITE_OK)
922 {
923 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
924 sqlite3_free (errMsg);
925 return 0;
926 }
927 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcs_view_name_update\n");
928 strcat (sql,
929 "BEFORE UPDATE OF 'view_name' ON 'views_geometry_columns_statistics'\n");
930 strcat (sql, "FOR EACH ROW BEGIN\n");
931 strcat (sql,
932 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: ");
933 strcat (sql, "view_name value must not contain a single quote')\n");
934 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
935 strcat (sql,
936 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: ");
937 strcat (sql, "view_name value must not contain a double quote')\n");
938 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
939 strcat (sql,
940 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: ");
941 strcat (sql, "view_name value must be lower case')\n");
942 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
943 strcat (sql, "END");
944 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
945 if (ret != SQLITE_OK)
946 {
947 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
948 sqlite3_free (errMsg);
949 return 0;
950 }
951 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcs_view_geometry_insert\n");
952 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_statistics'\n");
953 strcat (sql, "FOR EACH ROW BEGIN\n");
954 strcat (sql,
955 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: ");
956 strcat (sql, "view_geometry value must not contain a single quote')\n");
957 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
958 strcat (sql,
959 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: \n");
960 strcat (sql, "view_geometry value must not contain a double quote')\n");
961 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
962 strcat (sql,
963 "SELECT RAISE(ABORT,'insert on views_geometry_columns_statistics violates constraint: ");
964 strcat (sql, "view_geometry value must be lower case')\n");
965 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
966 strcat (sql, "END");
967 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
968 if (ret != SQLITE_OK)
969 {
970 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
971 sqlite3_free (errMsg);
972 return 0;
973 }
974 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcs_view_geometry_update\n");
975 strcat (sql,
976 "BEFORE UPDATE OF 'view_geometry' ON 'views_geometry_columns_statistics'\n");
977 strcat (sql, "FOR EACH ROW BEGIN\n");
978 strcat (sql,
979 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: ");
980 strcat (sql, "view_geometry value must not contain a single quote')\n");
981 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
982 strcat (sql,
983 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: \n");
984 strcat (sql, "view_geometry value must not contain a double quote')\n");
985 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
986 strcat (sql,
987 "SELECT RAISE(ABORT,'update on views_geometry_columns_statistics violates constraint: ");
988 strcat (sql, "view_geometry value must be lower case')\n");
989 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
990 strcat (sql, "END");
991 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
992 if (ret != SQLITE_OK)
993 {
994 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
995 sqlite3_free (errMsg);
996 return 0;
997 }
998 return 1;
999 }
1000
1001 static int
create_virts_geometry_columns_statistics(sqlite3 * sqlite)1002 create_virts_geometry_columns_statistics (sqlite3 * sqlite)
1003 {
1004 char sql[4186];
1005 char *errMsg = NULL;
1006 int ret;
1007
1008 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1009 {
1010 /* ignoring a read-only database */
1011 return 1;
1012 }
1013
1014 /* creating the VIRTS_GEOMETRY_COLUMNS_STATISTICS table */
1015 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1016 strcat (sql, "virts_geometry_columns_statistics (\n");
1017 strcat (sql, "virt_name TEXT NOT NULL,\n");
1018 strcat (sql, "virt_geometry TEXT NOT NULL,\n");
1019 strcat (sql, "last_verified TIMESTAMP,\n");
1020 strcat (sql, "row_count INTEGER,\n");
1021 strcat (sql, "extent_min_x DOUBLE,\n");
1022 strcat (sql, "extent_min_y DOUBLE,\n");
1023 strcat (sql, "extent_max_x DOUBLE,\n");
1024 strcat (sql, "extent_max_y DOUBLE,\n");
1025 strcat (sql, "CONSTRAINT pk_vrtgc_statistics PRIMARY KEY ");
1026 strcat (sql, "(virt_name, virt_geometry),\n");
1027 strcat (sql, "CONSTRAINT fk_vrtgc_statistics FOREIGN KEY ");
1028 strcat (sql, "(virt_name, virt_geometry) REFERENCES ");
1029 strcat (sql, "virts_geometry_columns (virt_name, virt_geometry) ");
1030 strcat (sql, "ON DELETE CASCADE)");
1031 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1032 if (ret != SQLITE_OK)
1033 {
1034 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1035 sqlite3_free (errMsg);
1036 return 0;
1037 }
1038 /* creating the VIRTS_GEOMETRY_COLUMNS_STATISTICS triggers */
1039 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcs_virt_name_insert\n");
1040 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_statistics'\n");
1041 strcat (sql, "FOR EACH ROW BEGIN\n");
1042 strcat (sql,
1043 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: ");
1044 strcat (sql, "virt_name value must not contain a single quote')\n");
1045 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
1046 strcat (sql,
1047 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: ");
1048 strcat (sql, "virt_name value must not contain a double quote')\n");
1049 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
1050 strcat (sql,
1051 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: \n");
1052 strcat (sql, "virt_name value must be lower case')\n");
1053 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
1054 strcat (sql, "END");
1055 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1056 if (ret != SQLITE_OK)
1057 {
1058 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1059 sqlite3_free (errMsg);
1060 return 0;
1061 }
1062 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcs_virt_name_update\n");
1063 strcat (sql,
1064 "BEFORE UPDATE OF 'virt_name' ON 'virts_geometry_columns_statistics'\n");
1065 strcat (sql, "FOR EACH ROW BEGIN\n");
1066 strcat (sql,
1067 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: ");
1068 strcat (sql, "virt_name value must not contain a single quote')\n");
1069 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
1070 strcat (sql,
1071 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: ");
1072 strcat (sql, "virt_name value must not contain a double quote')\n");
1073 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
1074 strcat (sql,
1075 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: ");
1076 strcat (sql, "virt_name value must be lower case')\n");
1077 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
1078 strcat (sql, "END");
1079 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1080 if (ret != SQLITE_OK)
1081 {
1082 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1083 sqlite3_free (errMsg);
1084 return 0;
1085 }
1086 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcs_virt_geometry_insert\n");
1087 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_statistics'\n");
1088 strcat (sql, "FOR EACH ROW BEGIN\n");
1089 strcat (sql,
1090 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: ");
1091 strcat (sql, "virt_geometry value must not contain a single quote')\n");
1092 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
1093 strcat (sql,
1094 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: \n");
1095 strcat (sql, "virt_geometry value must not contain a double quote')\n");
1096 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
1097 strcat (sql,
1098 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_statistics violates constraint: ");
1099 strcat (sql, "virt_geometry value must be lower case')\n");
1100 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
1101 strcat (sql, "END");
1102 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1103 if (ret != SQLITE_OK)
1104 {
1105 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1106 sqlite3_free (errMsg);
1107 return 0;
1108 }
1109 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcs_virt_geometry_update\n");
1110 strcat (sql,
1111 "BEFORE UPDATE OF 'virt_geometry' ON 'virts_geometry_columns_statistics'\n");
1112 strcat (sql, "FOR EACH ROW BEGIN\n");
1113 strcat (sql,
1114 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: ");
1115 strcat (sql, "virt_geometry value must not contain a single quote')\n");
1116 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
1117 strcat (sql,
1118 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: \n");
1119 strcat (sql, "virt_geometry value must not contain a double quote')\n");
1120 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
1121 strcat (sql,
1122 "SELECT RAISE(ABORT,'update on virts_geometry_columns_statistics violates constraint: ");
1123 strcat (sql, "virt_geometry value must be lower case')\n");
1124 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
1125 strcat (sql, "END");
1126 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1127 if (ret != SQLITE_OK)
1128 {
1129 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1130 sqlite3_free (errMsg);
1131 return 0;
1132 }
1133 return 1;
1134 }
1135
1136 static int
create_geometry_columns_field_infos(sqlite3 * sqlite)1137 create_geometry_columns_field_infos (sqlite3 * sqlite)
1138 {
1139 char sql[4186];
1140 char *errMsg = NULL;
1141 int ret;
1142
1143 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1144 {
1145 /* ignoring a read-only database */
1146 return 1;
1147 }
1148
1149 /* creating the GEOMETRY_COLUMNS_FIELD_INFOS table */
1150 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1151 strcat (sql, "geometry_columns_field_infos (\n");
1152 strcat (sql, "f_table_name TEXT NOT NULL,\n");
1153 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
1154 strcat (sql, "ordinal INTEGER NOT NULL,\n");
1155 strcat (sql, "column_name TEXT NOT NULL,\n");
1156 strcat (sql, "null_values INTEGER NOT NULL,\n");
1157 strcat (sql, "integer_values INTEGER NOT NULL,\n");
1158 strcat (sql, "double_values INTEGER NOT NULL,\n");
1159 strcat (sql, "text_values INTEGER NOT NULL,\n");
1160 strcat (sql, "blob_values INTEGER NOT NULL,\n");
1161 strcat (sql, "max_size INTEGER,\n");
1162 strcat (sql, "integer_min INTEGER,\n");
1163 strcat (sql, "integer_max INTEGER,\n");
1164 strcat (sql, "double_min DOUBLE,\n");
1165 strcat (sql, "double_max DOUBLE,\n");
1166 strcat (sql, "CONSTRAINT pk_gcfld_infos PRIMARY KEY ");
1167 strcat (sql, "(f_table_name, f_geometry_column, ordinal, column_name),\n");
1168 strcat (sql, "CONSTRAINT fk_gcfld_infos FOREIGN KEY ");
1169 strcat (sql, "(f_table_name, f_geometry_column) REFERENCES ");
1170 strcat (sql, "geometry_columns (f_table_name, f_geometry_column) ");
1171 strcat (sql, "ON DELETE CASCADE)");
1172 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1173 if (ret != SQLITE_OK)
1174 {
1175 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1176 sqlite3_free (errMsg);
1177 return 0;
1178 }
1179 /* creating the GEOMETRY_COLUMNS_FIELD_INFOS triggers */
1180 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcfi_f_table_name_insert\n");
1181 strcat (sql, "BEFORE INSERT ON 'geometry_columns_field_infos'\n");
1182 strcat (sql, "FOR EACH ROW BEGIN\n");
1183 strcat (sql,
1184 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: ");
1185 strcat (sql, "f_table_name value must not contain a single quote')\n");
1186 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1187 strcat (sql,
1188 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: ");
1189 strcat (sql, "f_table_name value must not contain a double quote')\n");
1190 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1191 strcat (sql,
1192 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: \n");
1193 strcat (sql, "f_table_name value must be lower case')\n");
1194 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1195 strcat (sql, "END");
1196 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1197 if (ret != SQLITE_OK)
1198 {
1199 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1200 sqlite3_free (errMsg);
1201 return 0;
1202 }
1203 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcfi_f_table_name_update\n");
1204 strcat (sql,
1205 "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns_field_infos'\n");
1206 strcat (sql, "FOR EACH ROW BEGIN\n");
1207 strcat (sql,
1208 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1209 strcat (sql, "f_table_name value must not contain a single quote')\n");
1210 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1211 strcat (sql,
1212 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1213 strcat (sql, "f_table_name value must not contain a double quote')\n");
1214 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1215 strcat (sql,
1216 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1217 strcat (sql, "f_table_name value must be lower case')\n");
1218 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1219 strcat (sql, "END");
1220 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1221 if (ret != SQLITE_OK)
1222 {
1223 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1224 sqlite3_free (errMsg);
1225 return 0;
1226 }
1227 strcpy (sql,
1228 "CREATE TRIGGER IF NOT EXISTS gcfi_f_geometry_column_insert\n");
1229 strcat (sql, "BEFORE INSERT ON 'geometry_columns_field_infos'\n");
1230 strcat (sql, "FOR EACH ROW BEGIN\n");
1231 strcat (sql,
1232 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: ");
1233 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1234 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1235 strcat (sql,
1236 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: \n");
1237 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1238 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1239 strcat (sql,
1240 "SELECT RAISE(ABORT,'insert on geometry_columns_field_infos violates constraint: ");
1241 strcat (sql, "f_geometry_column value must be lower case')\n");
1242 strcat (sql,
1243 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1244 strcat (sql, "END");
1245 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1246 if (ret != SQLITE_OK)
1247 {
1248 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1249 sqlite3_free (errMsg);
1250 return 0;
1251 }
1252 strcpy (sql,
1253 "CREATE TRIGGER IF NOT EXISTS gcfi_f_geometry_column_update\n");
1254 strcat (sql,
1255 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns_field_infos'\n");
1256 strcat (sql, "FOR EACH ROW BEGIN\n");
1257 strcat (sql,
1258 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1259 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1260 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1261 strcat (sql,
1262 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1263 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1264 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1265 strcat (sql,
1266 "SELECT RAISE(ABORT,'update on geometry_columns_field_infos violates constraint: ");
1267 strcat (sql, "f_geometry_column value must be lower case')\n");
1268 strcat (sql,
1269 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1270 strcat (sql, "END");
1271 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1272 if (ret != SQLITE_OK)
1273 {
1274 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1275 sqlite3_free (errMsg);
1276 return 0;
1277 }
1278 return 1;
1279 }
1280
1281 static int
create_views_geometry_columns_field_infos(sqlite3 * sqlite)1282 create_views_geometry_columns_field_infos (sqlite3 * sqlite)
1283 {
1284 char sql[4186];
1285 char *errMsg = NULL;
1286 int ret;
1287
1288 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1289 {
1290 /* ignoring a read-only database */
1291 return 1;
1292 }
1293
1294 /* creating the VIEWS_COLUMNS_FIELD_INFOS table */
1295 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1296 strcat (sql, "views_geometry_columns_field_infos (\n");
1297 strcat (sql, "view_name TEXT NOT NULL,\n");
1298 strcat (sql, "view_geometry TEXT NOT NULL,\n");
1299 strcat (sql, "ordinal INTEGER NOT NULL,\n");
1300 strcat (sql, "column_name TEXT NOT NULL,\n");
1301 strcat (sql, "null_values INTEGER NOT NULL,\n");
1302 strcat (sql, "integer_values INTEGER NOT NULL,\n");
1303 strcat (sql, "double_values INTEGER NOT NULL,\n");
1304 strcat (sql, "text_values INTEGER NOT NULL,\n");
1305 strcat (sql, "blob_values INTEGER NOT NULL,\n");
1306 strcat (sql, "max_size INTEGER,\n");
1307 strcat (sql, "integer_min INTEGER,\n");
1308 strcat (sql, "integer_max INTEGER,\n");
1309 strcat (sql, "double_min DOUBLE,\n");
1310 strcat (sql, "double_max DOUBLE,\n");
1311 strcat (sql, "CONSTRAINT pk_vwgcfld_infos PRIMARY KEY ");
1312 strcat (sql, "(view_name, view_geometry, ordinal, column_name),\n");
1313 strcat (sql, "CONSTRAINT fk_vwgcfld_infos FOREIGN KEY ");
1314 strcat (sql, "(view_name, view_geometry) REFERENCES ");
1315 strcat (sql, "views_geometry_columns (view_name, view_geometry) ");
1316 strcat (sql, "ON DELETE CASCADE)");
1317 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1318 if (ret != SQLITE_OK)
1319 {
1320 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1321 sqlite3_free (errMsg);
1322 return 0;
1323 }
1324 /* creating the VIEWS_COLUMNS_FIELD_INFOS triggers */
1325 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcfi_view_name_insert\n");
1326 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_field_infos'\n");
1327 strcat (sql, "FOR EACH ROW BEGIN\n");
1328 strcat (sql,
1329 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: ");
1330 strcat (sql, "view_name value must not contain a single quote')\n");
1331 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
1332 strcat (sql,
1333 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: ");
1334 strcat (sql, "view_name value must not contain a double quote')\n");
1335 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
1336 strcat (sql,
1337 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: \n");
1338 strcat (sql, "view_name value must be lower case')\n");
1339 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
1340 strcat (sql, "END");
1341 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1342 if (ret != SQLITE_OK)
1343 {
1344 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1345 sqlite3_free (errMsg);
1346 return 0;
1347 }
1348 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcfi_view_name_update\n");
1349 strcat (sql,
1350 "BEFORE UPDATE OF 'view_name' ON 'views_geometry_columns_field_infos'\n");
1351 strcat (sql, "FOR EACH ROW BEGIN\n");
1352 strcat (sql,
1353 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: ");
1354 strcat (sql, "view_name value must not contain a single quote')\n");
1355 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
1356 strcat (sql,
1357 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: ");
1358 strcat (sql, "view_name value must not contain a double quote')\n");
1359 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
1360 strcat (sql,
1361 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: ");
1362 strcat (sql, "view_name value must be lower case')\n");
1363 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
1364 strcat (sql, "END");
1365 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1366 if (ret != SQLITE_OK)
1367 {
1368 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1369 sqlite3_free (errMsg);
1370 return 0;
1371 }
1372 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcfi_view_geometry_insert\n");
1373 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_field_infos'\n");
1374 strcat (sql, "FOR EACH ROW BEGIN\n");
1375 strcat (sql,
1376 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: ");
1377 strcat (sql, "view_geometry value must not contain a single quote')\n");
1378 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
1379 strcat (sql,
1380 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: \n");
1381 strcat (sql, "view_geometry value must not contain a double quote')\n");
1382 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
1383 strcat (sql,
1384 "SELECT RAISE(ABORT,'insert on views_geometry_columns_field_infos violates constraint: ");
1385 strcat (sql, "view_geometry value must be lower case')\n");
1386 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
1387 strcat (sql, "END");
1388 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1389 if (ret != SQLITE_OK)
1390 {
1391 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1392 sqlite3_free (errMsg);
1393 return 0;
1394 }
1395 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcfi_view_geometry_update\n");
1396 strcat (sql,
1397 "BEFORE UPDATE OF 'view_geometry' ON 'views_geometry_columns_field_infos'\n");
1398 strcat (sql, "FOR EACH ROW BEGIN\n");
1399 strcat (sql,
1400 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: ");
1401 strcat (sql, "view_geometry value must not contain a single quote')\n");
1402 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
1403 strcat (sql,
1404 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: \n");
1405 strcat (sql, "view_geometry value must not contain a double quote')\n");
1406 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
1407 strcat (sql,
1408 "SELECT RAISE(ABORT,'update on views_geometry_columns_field_infos violates constraint: ");
1409 strcat (sql, "view_geometry value must be lower case')\n");
1410 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
1411 strcat (sql, "END");
1412 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1413 if (ret != SQLITE_OK)
1414 {
1415 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1416 sqlite3_free (errMsg);
1417 return 0;
1418 }
1419 return 1;
1420 }
1421
1422 static int
create_virts_geometry_columns_field_infos(sqlite3 * sqlite)1423 create_virts_geometry_columns_field_infos (sqlite3 * sqlite)
1424 {
1425 char sql[4186];
1426 char *errMsg = NULL;
1427 int ret;
1428
1429 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1430 {
1431 /* ignoring a read-only database */
1432 return 1;
1433 }
1434
1435 /* creating the VIRTS_GEOMETRY_COLUMNS_FIELD_INFOS table */
1436 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1437 strcat (sql, "virts_geometry_columns_field_infos (\n");
1438 strcat (sql, "virt_name TEXT NOT NULL,\n");
1439 strcat (sql, "virt_geometry TEXT NOT NULL,\n");
1440 strcat (sql, "ordinal INTEGER NOT NULL,\n");
1441 strcat (sql, "column_name TEXT NOT NULL,\n");
1442 strcat (sql, "null_values INTEGER NOT NULL,\n");
1443 strcat (sql, "integer_values INTEGER NOT NULL,\n");
1444 strcat (sql, "double_values INTEGER NOT NULL,\n");
1445 strcat (sql, "text_values INTEGER NOT NULL,\n");
1446 strcat (sql, "blob_values INTEGER NOT NULL,\n");
1447 strcat (sql, "max_size INTEGER,\n");
1448 strcat (sql, "integer_min INTEGER,\n");
1449 strcat (sql, "integer_max INTEGER,\n");
1450 strcat (sql, "double_min DOUBLE,\n");
1451 strcat (sql, "double_max DOUBLE,\n");
1452 strcat (sql, "CONSTRAINT pk_vrtgcfld_infos PRIMARY KEY ");
1453 strcat (sql, "(virt_name, virt_geometry, ordinal, column_name),\n");
1454 strcat (sql, "CONSTRAINT fk_vrtgcfld_infos FOREIGN KEY ");
1455 strcat (sql, "(virt_name, virt_geometry) REFERENCES ");
1456 strcat (sql, "virts_geometry_columns (virt_name, virt_geometry) ");
1457 strcat (sql, "ON DELETE CASCADE)");
1458 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1459 if (ret != SQLITE_OK)
1460 {
1461 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1462 sqlite3_free (errMsg);
1463 return 0;
1464 }
1465 /* creating the VIRTS_GEOMETRY_COLUMNS_FIELD_INFOS triggers */
1466 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcfi_virt_name_insert\n");
1467 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_field_infos'\n");
1468 strcat (sql, "FOR EACH ROW BEGIN\n");
1469 strcat (sql,
1470 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: ");
1471 strcat (sql, "virt_name value must not contain a single quote')\n");
1472 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
1473 strcat (sql,
1474 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: ");
1475 strcat (sql, "virt_name value must not contain a double quote')\n");
1476 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
1477 strcat (sql,
1478 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: \n");
1479 strcat (sql, "virt_name value must be lower case')\n");
1480 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
1481 strcat (sql, "END");
1482 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1483 if (ret != SQLITE_OK)
1484 {
1485 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1486 sqlite3_free (errMsg);
1487 return 0;
1488 }
1489 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcfi_virt_name_update\n");
1490 strcat (sql,
1491 "BEFORE UPDATE OF 'virt_name' ON 'virts_geometry_columns_field_infos'\n");
1492 strcat (sql, "FOR EACH ROW BEGIN\n");
1493 strcat (sql,
1494 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: ");
1495 strcat (sql, "virt_name value must not contain a single quote')\n");
1496 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
1497 strcat (sql,
1498 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: ");
1499 strcat (sql, "virt_name value must not contain a double quote')\n");
1500 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
1501 strcat (sql,
1502 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: ");
1503 strcat (sql, "virt_name value must be lower case')\n");
1504 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
1505 strcat (sql, "END");
1506 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1507 if (ret != SQLITE_OK)
1508 {
1509 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1510 sqlite3_free (errMsg);
1511 return 0;
1512 }
1513 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcfi_virt_geometry_insert\n");
1514 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_field_infos'\n");
1515 strcat (sql, "FOR EACH ROW BEGIN\n");
1516 strcat (sql,
1517 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: ");
1518 strcat (sql, "virt_geometry value must not contain a single quote')\n");
1519 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
1520 strcat (sql,
1521 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: \n");
1522 strcat (sql, "virt_geometry value must not contain a double quote')\n");
1523 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
1524 strcat (sql,
1525 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_field_infos violates constraint: ");
1526 strcat (sql, "virt_geometry value must be lower case')\n");
1527 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
1528 strcat (sql, "END");
1529 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1530 if (ret != SQLITE_OK)
1531 {
1532 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1533 sqlite3_free (errMsg);
1534 return 0;
1535 }
1536 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcfi_virt_geometry_update\n");
1537 strcat (sql,
1538 "BEFORE UPDATE OF 'virt_geometry' ON 'virts_geometry_columns_field_infos'\n");
1539 strcat (sql, "FOR EACH ROW BEGIN\n");
1540 strcat (sql,
1541 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: ");
1542 strcat (sql, "virt_geometry value must not contain a single quote')\n");
1543 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
1544 strcat (sql,
1545 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: \n");
1546 strcat (sql, "virt_geometry value must not contain a double quote')\n");
1547 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
1548 strcat (sql,
1549 "SELECT RAISE(ABORT,'update on virts_geometry_columns_field_infos violates constraint: ");
1550 strcat (sql, "virt_geometry value must be lower case')\n");
1551 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
1552 strcat (sql, "END");
1553 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1554 if (ret != SQLITE_OK)
1555 {
1556 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1557 sqlite3_free (errMsg);
1558 return 0;
1559 }
1560 return 1;
1561 }
1562
1563 SPATIALITE_PRIVATE int
create_geometry_columns_time(sqlite3 * sqlite)1564 create_geometry_columns_time (sqlite3 * sqlite)
1565 {
1566 char sql[4186];
1567 char *errMsg = NULL;
1568 int ret;
1569
1570 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1571 {
1572 /* ignoring a read-only database */
1573 return 1;
1574 }
1575
1576 /* creating the GEOMETRY_COLUMNS_TIME table */
1577 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1578 strcat (sql, "geometry_columns_time (\n");
1579 strcat (sql, "f_table_name TEXT NOT NULL,\n");
1580 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
1581 strcat (sql,
1582 "last_insert TIMESTAMP NOT NULL DEFAULT '0000-01-01T00:00:00.000Z',\n");
1583 strcat (sql,
1584 "last_update TIMESTAMP NOT NULL DEFAULT '0000-01-01T00:00:00.000Z',\n");
1585 strcat (sql,
1586 "last_delete TIMESTAMP NOT NULL DEFAULT '0000-01-01T00:00:00.000Z',\n");
1587 strcat (sql, "CONSTRAINT pk_gc_time PRIMARY KEY ");
1588 strcat (sql, "(f_table_name, f_geometry_column),\n");
1589 strcat (sql, "CONSTRAINT fk_gc_time FOREIGN KEY ");
1590 strcat (sql, "(f_table_name, f_geometry_column) ");
1591 strcat (sql, "REFERENCES geometry_columns ");
1592 strcat (sql, "(f_table_name, f_geometry_column) ");
1593 strcat (sql, "ON DELETE CASCADE)");
1594 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1595 if (ret != SQLITE_OK)
1596 {
1597 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1598 sqlite3_free (errMsg);
1599 return 0;
1600 }
1601 /* creating the GEOMETRY_COLUMNS_TIME triggers */
1602 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gctm_f_table_name_insert\n");
1603 strcat (sql, "BEFORE INSERT ON 'geometry_columns_time'\n");
1604 strcat (sql, "FOR EACH ROW BEGIN\n");
1605 strcat (sql,
1606 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: ");
1607 strcat (sql, "f_table_name value must not contain a single quote')\n");
1608 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1609 strcat (sql,
1610 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: ");
1611 strcat (sql, "f_table_name value must not contain a double quote')\n");
1612 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1613 strcat (sql,
1614 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: \n");
1615 strcat (sql, "f_table_name value must be lower case')\n");
1616 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1617 strcat (sql, "END");
1618 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1619 if (ret != SQLITE_OK)
1620 {
1621 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1622 sqlite3_free (errMsg);
1623 return 0;
1624 }
1625 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gctm_f_table_name_update\n");
1626 strcat (sql,
1627 "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns_time'\n");
1628 strcat (sql, "FOR EACH ROW BEGIN\n");
1629 strcat (sql,
1630 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1631 strcat (sql, "f_table_name value must not contain a single quote')\n");
1632 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1633 strcat (sql,
1634 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1635 strcat (sql, "f_table_name value must not contain a double quote')\n");
1636 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1637 strcat (sql,
1638 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1639 strcat (sql, "f_table_name value must be lower case')\n");
1640 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1641 strcat (sql, "END");
1642 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1643 if (ret != SQLITE_OK)
1644 {
1645 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1646 sqlite3_free (errMsg);
1647 return 0;
1648 }
1649 strcpy (sql,
1650 "CREATE TRIGGER IF NOT EXISTS gctm_f_geometry_column_insert\n");
1651 strcat (sql, "BEFORE INSERT ON 'geometry_columns_time'\n");
1652 strcat (sql, "FOR EACH ROW BEGIN\n");
1653 strcat (sql,
1654 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: ");
1655 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1656 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1657 strcat (sql,
1658 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: \n");
1659 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1660 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1661 strcat (sql,
1662 "SELECT RAISE(ABORT,'insert on geometry_columns_time violates constraint: ");
1663 strcat (sql, "f_geometry_column value must be lower case')\n");
1664 strcat (sql,
1665 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1666 strcat (sql, "END");
1667 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1668 if (ret != SQLITE_OK)
1669 {
1670 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1671 sqlite3_free (errMsg);
1672 return 0;
1673 }
1674 strcpy (sql,
1675 "CREATE TRIGGER IF NOT EXISTS gctm_f_geometry_column_update\n");
1676 strcat (sql,
1677 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns_time'\n");
1678 strcat (sql, "FOR EACH ROW BEGIN\n");
1679 strcat (sql,
1680 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1681 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1682 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1683 strcat (sql,
1684 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1685 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1686 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1687 strcat (sql,
1688 "SELECT RAISE(ABORT,'update on geometry_columns_time violates constraint: ");
1689 strcat (sql, "f_geometry_column value must be lower case')\n");
1690 strcat (sql,
1691 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1692 strcat (sql, "END");
1693 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1694 if (ret != SQLITE_OK)
1695 {
1696 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1697 sqlite3_free (errMsg);
1698 return 0;
1699 }
1700 return 1;
1701 }
1702
1703 static int
create_geometry_columns_auth(sqlite3 * sqlite)1704 create_geometry_columns_auth (sqlite3 * sqlite)
1705 {
1706 char sql[4186];
1707 char *errMsg = NULL;
1708 int ret;
1709
1710 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1711 {
1712 /* ignoring a read-only database */
1713 return 1;
1714 }
1715
1716 /* creating the GEOMETRY_COLUMNS_AUTH table */
1717 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1718 strcat (sql, "geometry_columns_auth (\n");
1719 strcat (sql, "f_table_name TEXT NOT NULL,\n");
1720 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
1721 strcat (sql, "read_only INTEGER NOT NULL,\n");
1722 strcat (sql, "hidden INTEGER NOT NULL,\n");
1723 strcat (sql, "CONSTRAINT pk_gc_auth PRIMARY KEY ");
1724 strcat (sql, "(f_table_name, f_geometry_column),\n");
1725 strcat (sql, "CONSTRAINT fk_gc_auth FOREIGN KEY ");
1726 strcat (sql, "(f_table_name, f_geometry_column) ");
1727 strcat (sql, "REFERENCES geometry_columns ");
1728 strcat (sql, "(f_table_name, f_geometry_column) ");
1729 strcat (sql, "ON DELETE CASCADE,\n");
1730 strcat (sql, "CONSTRAINT ck_gc_ronly CHECK (read_only IN ");
1731 strcat (sql, "(0,1)),\n");
1732 strcat (sql, "CONSTRAINT ck_gc_hidden CHECK (hidden IN ");
1733 strcat (sql, "(0,1)))");
1734 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1735 if (ret != SQLITE_OK)
1736 {
1737 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1738 sqlite3_free (errMsg);
1739 return 0;
1740 }
1741 /* creating the GEOMETRY_COLUMNS_AUTH triggers */
1742 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcau_f_table_name_insert\n");
1743 strcat (sql, "BEFORE INSERT ON 'geometry_columns_auth'\n");
1744 strcat (sql, "FOR EACH ROW BEGIN\n");
1745 strcat (sql,
1746 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: ");
1747 strcat (sql, "f_table_name value must not contain a single quote')\n");
1748 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1749 strcat (sql,
1750 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: ");
1751 strcat (sql, "f_table_name value must not contain a double quote')\n");
1752 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1753 strcat (sql,
1754 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: \n");
1755 strcat (sql, "f_table_name value must be lower case')\n");
1756 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1757 strcat (sql, "END");
1758 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1759 if (ret != SQLITE_OK)
1760 {
1761 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1762 sqlite3_free (errMsg);
1763 return 0;
1764 }
1765 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS gcau_f_table_name_update\n");
1766 strcat (sql,
1767 "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns_auth'\n");
1768 strcat (sql, "FOR EACH ROW BEGIN\n");
1769 strcat (sql,
1770 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1771 strcat (sql, "f_table_name value must not contain a single quote')\n");
1772 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
1773 strcat (sql,
1774 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1775 strcat (sql, "f_table_name value must not contain a double quote')\n");
1776 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
1777 strcat (sql,
1778 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1779 strcat (sql, "f_table_name value must be lower case')\n");
1780 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
1781 strcat (sql, "END");
1782 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1783 if (ret != SQLITE_OK)
1784 {
1785 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1786 sqlite3_free (errMsg);
1787 return 0;
1788 }
1789 strcpy (sql,
1790 "CREATE TRIGGER IF NOT EXISTS gcau_f_geometry_column_insert\n");
1791 strcat (sql, "BEFORE INSERT ON 'geometry_columns_auth'\n");
1792 strcat (sql, "FOR EACH ROW BEGIN\n");
1793 strcat (sql,
1794 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: ");
1795 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1796 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1797 strcat (sql,
1798 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: \n");
1799 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1800 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1801 strcat (sql,
1802 "SELECT RAISE(ABORT,'insert on geometry_columns_auth violates constraint: ");
1803 strcat (sql, "f_geometry_column value must be lower case')\n");
1804 strcat (sql,
1805 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1806 strcat (sql, "END");
1807 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1808 if (ret != SQLITE_OK)
1809 {
1810 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1811 sqlite3_free (errMsg);
1812 return 0;
1813 }
1814 strcpy (sql,
1815 "CREATE TRIGGER IF NOT EXISTS gcau_f_geometry_column_update\n");
1816 strcat (sql,
1817 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns_auth'\n");
1818 strcat (sql, "FOR EACH ROW BEGIN\n");
1819 strcat (sql,
1820 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1821 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
1822 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
1823 strcat (sql,
1824 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1825 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
1826 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
1827 strcat (sql,
1828 "SELECT RAISE(ABORT,'update on geometry_columns_auth violates constraint: ");
1829 strcat (sql, "f_geometry_column value must be lower case')\n");
1830 strcat (sql,
1831 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
1832 strcat (sql, "END");
1833 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1834 if (ret != SQLITE_OK)
1835 {
1836 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1837 sqlite3_free (errMsg);
1838 return 0;
1839 }
1840 return 1;
1841 }
1842
1843 static int
create_views_geometry_columns_auth(sqlite3 * sqlite)1844 create_views_geometry_columns_auth (sqlite3 * sqlite)
1845 {
1846 char sql[4186];
1847 char *errMsg = NULL;
1848 int ret;
1849
1850 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1851 {
1852 /* ignoring a read-only database */
1853 return 1;
1854 }
1855
1856 /* creating the VIEWS_GEOMETRY_COLUMNS_AUTH table */
1857 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1858 strcat (sql, "views_geometry_columns_auth (\n");
1859 strcat (sql, "view_name TEXT NOT NULL,\n");
1860 strcat (sql, "view_geometry TEXT NOT NULL,\n");
1861 strcat (sql, "hidden INTEGER NOT NULL,\n");
1862 strcat (sql, "CONSTRAINT pk_vwgc_auth PRIMARY KEY ");
1863 strcat (sql, "(view_name, view_geometry),\n");
1864 strcat (sql, "CONSTRAINT fk_vwgc_auth FOREIGN KEY ");
1865 strcat (sql, "(view_name, view_geometry) ");
1866 strcat (sql, "REFERENCES views_geometry_columns ");
1867 strcat (sql, "(view_name, view_geometry) ");
1868 strcat (sql, "ON DELETE CASCADE,\n");
1869 strcat (sql, "CONSTRAINT ck_vwgc_hidden CHECK (hidden IN ");
1870 strcat (sql, "(0,1)))");
1871 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1872 if (ret != SQLITE_OK)
1873 {
1874 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1875 sqlite3_free (errMsg);
1876 return 0;
1877 }
1878 /* creating the VIEWS_GEOMETRY_COLUMNS_AUTH triggers */
1879 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcau_view_name_insert\n");
1880 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_auth'\n");
1881 strcat (sql, "FOR EACH ROW BEGIN\n");
1882 strcat (sql,
1883 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: ");
1884 strcat (sql, "view_name value must not contain a single quote')\n");
1885 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
1886 strcat (sql,
1887 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: ");
1888 strcat (sql, "view_name value must not contain a double quote')\n");
1889 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
1890 strcat (sql,
1891 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: \n");
1892 strcat (sql, "view_name value must be lower case')\n");
1893 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
1894 strcat (sql, "END");
1895 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1896 if (ret != SQLITE_OK)
1897 {
1898 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1899 sqlite3_free (errMsg);
1900 return 0;
1901 }
1902 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcau_view_name_update\n");
1903 strcat (sql,
1904 "BEFORE UPDATE OF 'view_name' ON 'views_geometry_columns_auth'\n");
1905 strcat (sql, "FOR EACH ROW BEGIN\n");
1906 strcat (sql,
1907 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: ");
1908 strcat (sql, "view_name value must not contain a single quote')\n");
1909 strcat (sql, "WHERE NEW.view_name LIKE ('%''%');\n");
1910 strcat (sql,
1911 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: ");
1912 strcat (sql, "view_name value must not contain a double quote')\n");
1913 strcat (sql, "WHERE NEW.view_name LIKE ('%\"%');\n");
1914 strcat (sql,
1915 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: ");
1916 strcat (sql, "view_name value must be lower case')\n");
1917 strcat (sql, "WHERE NEW.view_name <> lower(NEW.view_name);\n");
1918 strcat (sql, "END");
1919 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1920 if (ret != SQLITE_OK)
1921 {
1922 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1923 sqlite3_free (errMsg);
1924 return 0;
1925 }
1926 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcau_view_geometry_insert\n");
1927 strcat (sql, "BEFORE INSERT ON 'views_geometry_columns_auth'\n");
1928 strcat (sql, "FOR EACH ROW BEGIN\n");
1929 strcat (sql,
1930 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: ");
1931 strcat (sql, "view_geometry value must not contain a single quote')\n");
1932 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
1933 strcat (sql,
1934 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: \n");
1935 strcat (sql, "view_geometry value must not contain a double quote')\n");
1936 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
1937 strcat (sql,
1938 "SELECT RAISE(ABORT,'insert on views_geometry_columns_auth violates constraint: ");
1939 strcat (sql, "view_geometry value must be lower case')\n");
1940 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
1941 strcat (sql, "END");
1942 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1943 if (ret != SQLITE_OK)
1944 {
1945 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1946 sqlite3_free (errMsg);
1947 return 0;
1948 }
1949 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vwgcau_view_geometry_update\n");
1950 strcat (sql,
1951 "BEFORE UPDATE OF 'view_geometry' ON 'views_geometry_columns_auth'\n");
1952 strcat (sql, "FOR EACH ROW BEGIN\n");
1953 strcat (sql,
1954 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: ");
1955 strcat (sql, "view_geometry value must not contain a single quote')\n");
1956 strcat (sql, "WHERE NEW.view_geometry LIKE ('%''%');\n");
1957 strcat (sql,
1958 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: \n");
1959 strcat (sql, "view_geometry value must not contain a double quote')\n");
1960 strcat (sql, "WHERE NEW.view_geometry LIKE ('%\"%');\n");
1961 strcat (sql,
1962 "SELECT RAISE(ABORT,'update on views_geometry_columns_auth violates constraint: ");
1963 strcat (sql, "view_geometry value must be lower case')\n");
1964 strcat (sql, "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n");
1965 strcat (sql, "END");
1966 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
1967 if (ret != SQLITE_OK)
1968 {
1969 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
1970 sqlite3_free (errMsg);
1971 return 0;
1972 }
1973 return 1;
1974 }
1975
1976 static int
create_virts_geometry_columns_auth(sqlite3 * sqlite)1977 create_virts_geometry_columns_auth (sqlite3 * sqlite)
1978 {
1979 char sql[4186];
1980 char *errMsg = NULL;
1981 int ret;
1982
1983 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
1984 {
1985 /* ignoring a read-only database */
1986 return 1;
1987 }
1988
1989 /* creating the VIRTS_GEOMETRY_COLUMNS_AUTH table */
1990 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
1991 strcat (sql, "virts_geometry_columns_auth (\n");
1992 strcat (sql, "virt_name TEXT NOT NULL,\n");
1993 strcat (sql, "virt_geometry TEXT NOT NULL,\n");
1994 strcat (sql, "hidden INTEGER NOT NULL,\n");
1995 strcat (sql, "CONSTRAINT pk_vrtgc_auth PRIMARY KEY ");
1996 strcat (sql, "(virt_name, virt_geometry),\n");
1997 strcat (sql, "CONSTRAINT fk_vrtgc_auth FOREIGN KEY ");
1998 strcat (sql, "(virt_name, virt_geometry) ");
1999 strcat (sql, "REFERENCES virts_geometry_columns ");
2000 strcat (sql, "(virt_name, virt_geometry) ");
2001 strcat (sql, "ON DELETE CASCADE,\n");
2002 strcat (sql, "CONSTRAINT ck_vrtgc_hidden CHECK (hidden IN ");
2003 strcat (sql, "(0,1)))");
2004 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2005 if (ret != SQLITE_OK)
2006 {
2007 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2008 sqlite3_free (errMsg);
2009 return 0;
2010 }
2011 /* creating the VIRTS_GEOMETRY_COLUMNS_AUTH triggers */
2012 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcau_virt_name_insert\n");
2013 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_auth'\n");
2014 strcat (sql, "FOR EACH ROW BEGIN\n");
2015 strcat (sql,
2016 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: ");
2017 strcat (sql, "virt_name value must not contain a single quote')\n");
2018 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
2019 strcat (sql,
2020 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: ");
2021 strcat (sql, "virt_name value must not contain a double quote')\n");
2022 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
2023 strcat (sql,
2024 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: \n");
2025 strcat (sql, "virt_name value must be lower case')\n");
2026 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
2027 strcat (sql, "END");
2028 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2029 if (ret != SQLITE_OK)
2030 {
2031 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2032 sqlite3_free (errMsg);
2033 return 0;
2034 }
2035 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcau_virt_name_update\n");
2036 strcat (sql,
2037 "BEFORE UPDATE OF 'virt_name' ON 'virts_geometry_columns_auth'\n");
2038 strcat (sql, "FOR EACH ROW BEGIN\n");
2039 strcat (sql,
2040 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: ");
2041 strcat (sql, "virt_name value must not contain a single quote')\n");
2042 strcat (sql, "WHERE NEW.virt_name LIKE ('%''%');\n");
2043 strcat (sql,
2044 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: ");
2045 strcat (sql, "virt_name value must not contain a double quote')\n");
2046 strcat (sql, "WHERE NEW.virt_name LIKE ('%\"%');\n");
2047 strcat (sql,
2048 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: ");
2049 strcat (sql, "virt_name value must be lower case')\n");
2050 strcat (sql, "WHERE NEW.virt_name <> lower(NEW.virt_name);\n");
2051 strcat (sql, "END");
2052 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2053 if (ret != SQLITE_OK)
2054 {
2055 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2056 sqlite3_free (errMsg);
2057 return 0;
2058 }
2059 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcau_virt_geometry_insert\n");
2060 strcat (sql, "BEFORE INSERT ON 'virts_geometry_columns_auth'\n");
2061 strcat (sql, "FOR EACH ROW BEGIN\n");
2062 strcat (sql,
2063 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: ");
2064 strcat (sql, "virt_geometry value must not contain a single quote')\n");
2065 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
2066 strcat (sql,
2067 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: \n");
2068 strcat (sql, "virt_geometry value must not contain a double quote')\n");
2069 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
2070 strcat (sql,
2071 "SELECT RAISE(ABORT,'insert on virts_geometry_columns_auth violates constraint: ");
2072 strcat (sql, "virt_geometry value must be lower case')\n");
2073 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
2074 strcat (sql, "END");
2075 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2076 if (ret != SQLITE_OK)
2077 {
2078 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2079 sqlite3_free (errMsg);
2080 return 0;
2081 }
2082 strcpy (sql, "CREATE TRIGGER IF NOT EXISTS vtgcau_virt_geometry_update\n");
2083 strcat (sql,
2084 "BEFORE UPDATE OF 'virt_geometry' ON 'virts_geometry_columns_auth'\n");
2085 strcat (sql, "FOR EACH ROW BEGIN\n");
2086 strcat (sql,
2087 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: ");
2088 strcat (sql, "virt_geometry value must not contain a single quote')\n");
2089 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%''%');\n");
2090 strcat (sql,
2091 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: \n");
2092 strcat (sql, "virt_geometry value must not contain a double quote')\n");
2093 strcat (sql, "WHERE NEW.virt_geometry LIKE ('%\"%');\n");
2094 strcat (sql,
2095 "SELECT RAISE(ABORT,'update on virts_geometry_columns_auth violates constraint: ");
2096 strcat (sql, "virt_geometry value must be lower case')\n");
2097 strcat (sql, "WHERE NEW.virt_geometry <> lower(NEW.virt_geometry);\n");
2098 strcat (sql, "END");
2099 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2100 if (ret != SQLITE_OK)
2101 {
2102 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2103 sqlite3_free (errMsg);
2104 return 0;
2105 }
2106 return 1;
2107 }
2108
2109 static int
create_geometry_columns_views(sqlite3 * sqlite)2110 create_geometry_columns_views (sqlite3 * sqlite)
2111 {
2112 char sql[4186];
2113 char *errMsg = NULL;
2114 int ret;
2115
2116 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
2117 {
2118 /* ignoring a read-only database */
2119 return 1;
2120 }
2121
2122 /* creating the VECTOR_LAYERS view */
2123 strcpy (sql, "CREATE VIEW IF NOT EXISTS ");
2124 strcat (sql, "vector_layers AS\n");
2125 strcat (sql, "SELECT 'SpatialTable' AS layer_type, ");
2126 strcat (sql, "f_table_name AS table_name, ");
2127 strcat (sql, "f_geometry_column AS geometry_column, ");
2128 strcat (sql, "geometry_type AS geometry_type, ");
2129 strcat (sql, "coord_dimension AS coord_dimension, ");
2130 strcat (sql, "srid AS srid, ");
2131 strcat (sql, "spatial_index_enabled AS spatial_index_enabled\n");
2132 strcat (sql, "FROM geometry_columns\n");
2133 strcat (sql, "UNION\n");
2134 strcat (sql, "SELECT 'SpatialView' AS layer_type, ");
2135 strcat (sql, "a.view_name AS table_name, ");
2136 strcat (sql, "a.view_geometry AS geometry_column, ");
2137 strcat (sql, "b.geometry_type AS geometry_type, ");
2138 strcat (sql, "b.coord_dimension AS coord_dimension, ");
2139 strcat (sql, "b.srid AS srid, ");
2140 strcat (sql, "b.spatial_index_enabled AS spatial_index_enabled\n");
2141 strcat (sql, "FROM views_geometry_columns AS a\n");
2142 strcat (sql, "LEFT JOIN geometry_columns AS b ON (");
2143 strcat (sql, "Upper(a.f_table_name) = Upper(b.f_table_name) AND ");
2144 strcat (sql, "Upper(a.f_geometry_column) = Upper(b.f_geometry_column))\n");
2145 strcat (sql, "UNION\n");
2146 strcat (sql, "SELECT 'VirtualShape' AS layer_type, ");
2147 strcat (sql, "virt_name AS table_name, ");
2148 strcat (sql, "virt_geometry AS geometry_column, ");
2149 strcat (sql, "geometry_type AS geometry_type, ");
2150 strcat (sql, "coord_dimension AS coord_dimension, ");
2151 strcat (sql, "srid AS srid, ");
2152 strcat (sql, "0 AS spatial_index_enabled\n");
2153 strcat (sql, "FROM virts_geometry_columns");
2154 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2155 if (ret != SQLITE_OK)
2156 {
2157 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2158 sqlite3_free (errMsg);
2159 return 0;
2160 }
2161 /* creating the VECTOR_LAYERS_AUTH view */
2162 strcpy (sql, "CREATE VIEW IF NOT EXISTS ");
2163 strcat (sql, "vector_layers_auth AS\n");
2164 strcat (sql, "SELECT 'SpatialTable' AS layer_type, ");
2165 strcat (sql, "f_table_name AS table_name, ");
2166 strcat (sql, "f_geometry_column AS geometry_column, ");
2167 strcat (sql, "read_only AS read_only, ");
2168 strcat (sql, "hidden AS hidden\n");
2169 strcat (sql, "FROM geometry_columns_auth\n");
2170 strcat (sql, "UNION\n");
2171 strcat (sql, "SELECT 'SpatialView' AS layer_type, ");
2172 strcat (sql, "a.view_name AS table_name, ");
2173 strcat (sql, "a.view_geometry AS geometry_column, ");
2174 strcat (sql, "b.read_only AS read_only, ");
2175 strcat (sql, "a.hidden AS hidden\n");
2176 strcat (sql, "FROM views_geometry_columns_auth AS a\n");
2177 strcat (sql, "JOIN views_geometry_columns AS b ON (");
2178 strcat (sql, "Upper(a.view_name) = Upper(b.view_name) AND ");
2179 strcat (sql, "Upper(a.view_geometry) = Upper(b.view_geometry))\n");
2180 strcat (sql, "UNION\n");
2181 strcat (sql, "SELECT 'VirtualShape' AS layer_type, ");
2182 strcat (sql, "virt_name AS table_name, ");
2183 strcat (sql, "virt_geometry AS geometry_column, ");
2184 strcat (sql, "1 AS read_only, ");
2185 strcat (sql, "hidden AS hidden\n");
2186 strcat (sql, "FROM virts_geometry_columns_auth");
2187 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2188 if (ret != SQLITE_OK)
2189 {
2190 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2191 sqlite3_free (errMsg);
2192 return 0;
2193 }
2194 /* creating the VECTOR_LAYERS_STATISTICS view */
2195 strcpy (sql, "CREATE VIEW IF NOT EXISTS ");
2196 strcat (sql, "vector_layers_statistics AS\n");
2197 strcat (sql, "SELECT 'SpatialTable' AS layer_type, ");
2198 strcat (sql, "f_table_name AS table_name, ");
2199 strcat (sql, "f_geometry_column AS geometry_column, ");
2200 strcat (sql, "last_verified AS last_verified, ");
2201 strcat (sql, "row_count AS row_count, ");
2202 strcat (sql, "extent_min_x AS extent_min_x, ");
2203 strcat (sql, "extent_min_y AS extent_min_y, ");
2204 strcat (sql, "extent_max_x AS extent_max_x, ");
2205 strcat (sql, "extent_max_y AS extent_max_y\n");
2206 strcat (sql, "FROM geometry_columns_statistics\n");
2207 strcat (sql, "UNION\n");
2208 strcat (sql, "SELECT 'SpatialView' AS layer_type, ");
2209 strcat (sql, "view_name AS table_name, ");
2210 strcat (sql, "view_geometry AS geometry_column, ");
2211 strcat (sql, "last_verified AS last_verified, ");
2212 strcat (sql, "row_count AS row_count, ");
2213 strcat (sql, "extent_min_x AS extent_min_x, ");
2214 strcat (sql, "extent_min_y AS extent_min_y, ");
2215 strcat (sql, "extent_max_x AS extent_max_x, ");
2216 strcat (sql, "extent_max_y AS extent_max_y\n");
2217 strcat (sql, "FROM views_geometry_columns_statistics\n");
2218 strcat (sql, "UNION\n");
2219 strcat (sql, "SELECT 'VirtualShape' AS layer_type, ");
2220 strcat (sql, "virt_name AS table_name, ");
2221 strcat (sql, "virt_geometry AS geometry_column, ");
2222 strcat (sql, "last_verified AS last_verified, ");
2223 strcat (sql, "row_count AS row_count, ");
2224 strcat (sql, "extent_min_x AS extent_min_x, ");
2225 strcat (sql, "extent_min_y AS extent_min_y, ");
2226 strcat (sql, "extent_max_x AS extent_max_x, ");
2227 strcat (sql, "extent_max_y AS extent_max_y\n");
2228 strcat (sql, "FROM virts_geometry_columns_statistics");
2229 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2230 if (ret != SQLITE_OK)
2231 {
2232 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2233 sqlite3_free (errMsg);
2234 return 0;
2235 }
2236 /* creating the VECTOR_LAYERS_FIELD_INFOS view */
2237 strcpy (sql, "CREATE VIEW IF NOT EXISTS ");
2238 strcat (sql, "vector_layers_field_infos AS\n");
2239 strcat (sql, "SELECT 'SpatialTable' AS layer_type, ");
2240 strcat (sql, "f_table_name AS table_name, ");
2241 strcat (sql, "f_geometry_column AS geometry_column, ");
2242 strcat (sql, "ordinal AS ordinal, ");
2243 strcat (sql, "column_name AS column_name, ");
2244 strcat (sql, "null_values AS null_values, ");
2245 strcat (sql, "integer_values AS integer_values, ");
2246 strcat (sql, "double_values AS double_values, ");
2247 strcat (sql, "text_values AS text_values, ");
2248 strcat (sql, "blob_values AS blob_values, ");
2249 strcat (sql, "max_size AS max_size, ");
2250 strcat (sql, "integer_min AS integer_min, ");
2251 strcat (sql, "integer_max AS integer_max, ");
2252 strcat (sql, "double_min AS double_min, ");
2253 strcat (sql, "double_max double_max\n");
2254 strcat (sql, "FROM geometry_columns_field_infos\n");
2255 strcat (sql, "UNION\n");
2256 strcat (sql, "SELECT 'SpatialView' AS layer_type, ");
2257 strcat (sql, "view_name AS table_name, ");
2258 strcat (sql, "view_geometry AS geometry_column, ");
2259 strcat (sql, "ordinal AS ordinal, ");
2260 strcat (sql, "column_name AS column_name, ");
2261 strcat (sql, "null_values AS null_values, ");
2262 strcat (sql, "integer_values AS integer_values, ");
2263 strcat (sql, "double_values AS double_values, ");
2264 strcat (sql, "text_values AS text_values, ");
2265 strcat (sql, "blob_values AS blob_values, ");
2266 strcat (sql, "max_size AS max_size, ");
2267 strcat (sql, "integer_min AS integer_min, ");
2268 strcat (sql, "integer_max AS integer_max, ");
2269 strcat (sql, "double_min AS double_min, ");
2270 strcat (sql, "double_max double_max\n");
2271 strcat (sql, "FROM views_geometry_columns_field_infos\n");
2272 strcat (sql, "UNION\n");
2273 strcat (sql, "SELECT 'VirtualShape' AS layer_type, ");
2274 strcat (sql, "virt_name AS table_name, ");
2275 strcat (sql, "virt_geometry AS geometry_column, ");
2276 strcat (sql, "ordinal AS ordinal, ");
2277 strcat (sql, "column_name AS column_name, ");
2278 strcat (sql, "null_values AS null_values, ");
2279 strcat (sql, "integer_values AS integer_values, ");
2280 strcat (sql, "double_values AS double_values, ");
2281 strcat (sql, "text_values AS text_values, ");
2282 strcat (sql, "blob_values AS blob_values, ");
2283 strcat (sql, "max_size AS max_size, ");
2284 strcat (sql, "integer_min AS integer_min, ");
2285 strcat (sql, "integer_max AS integer_max, ");
2286 strcat (sql, "double_min AS double_min, ");
2287 strcat (sql, "double_max double_max\n");
2288 strcat (sql, "FROM virts_geometry_columns_field_infos");
2289 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2290 if (ret != SQLITE_OK)
2291 {
2292 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2293 sqlite3_free (errMsg);
2294 return 0;
2295 }
2296 return 1;
2297 }
2298
2299 SPATIALITE_PRIVATE int
create_data_licenses(sqlite3 * sqlite)2300 create_data_licenses (sqlite3 * sqlite)
2301 {
2302 char sql[4186];
2303 char *errMsg = NULL;
2304 int ret;
2305
2306 if (sqlite3_db_readonly (sqlite, "MAIN") == 1)
2307 {
2308 /* ignoring a read-only database */
2309 return 1;
2310 }
2311
2312 /* creating the DATA_LICENSES table */
2313 strcpy (sql, "CREATE TABLE IF NOT EXISTS data_licenses (\n");
2314 strcat (sql, "\tid INTEGER PRIMARY KEY AUTOINCREMENT,\n");
2315 strcat (sql, "\tname TEXT NOT NULL UNIQUE,\n");
2316 strcat (sql, "\turl TEXT)");
2317 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2318 if (ret != SQLITE_OK)
2319 {
2320 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2321 sqlite3_free (errMsg);
2322 return 0;
2323 }
2324 /* inserting the UNDEFINED license */
2325 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2326 strcat (sql, "VALUES (0, 'Undefined', NULL)");
2327 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2328 if (ret != SQLITE_OK)
2329 {
2330 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2331 sqlite3_free (errMsg);
2332 return 0;
2333 }
2334 /* inserting the PROPRIETARY license */
2335 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2336 strcat (sql, "VALUES (1, 'Proprietary - Non Free', NULL)");
2337 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2338 if (ret != SQLITE_OK)
2339 {
2340 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2341 sqlite3_free (errMsg);
2342 return 0;
2343 }
2344 /* inserting the PUBLIC DOMAIN license */
2345 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2346 strcat (sql, "VALUES (2, 'PD - Public Domain', NULL)");
2347 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2348 if (ret != SQLITE_OK)
2349 {
2350 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2351 sqlite3_free (errMsg);
2352 return 0;
2353 }
2354 /* inserting the CC0 1.0 license */
2355 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2356 strcat (sql,
2357 "VALUES (3, 'CC0 1.0', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt')");
2358 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2359 if (ret != SQLITE_OK)
2360 {
2361 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2362 sqlite3_free (errMsg);
2363 return 0;
2364 }
2365 /* inserting the CC BY 3.0 license */
2366 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2367 strcat (sql,
2368 "VALUES (4, 'CC BY 3.0', 'https://creativecommons.org/licenses/by/3.0/legalcode.txt')");
2369 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2370 if (ret != SQLITE_OK)
2371 {
2372 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2373 sqlite3_free (errMsg);
2374 return 0;
2375 }
2376 /* inserting the CC BY 4.0 license */
2377 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2378 strcat (sql,
2379 "VALUES (5, 'CC BY 4.0', 'https://creativecommons.org/licenses/by/4.0/legalcode.txt')");
2380 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2381 if (ret != SQLITE_OK)
2382 {
2383 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2384 sqlite3_free (errMsg);
2385 return 0;
2386 }
2387 /* inserting the CC BY-SA 3.0 license */
2388 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2389 strcat (sql,
2390 "VALUES (6, 'CC BY-SA 3.0', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode.txt')");
2391 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2392 if (ret != SQLITE_OK)
2393 {
2394 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2395 sqlite3_free (errMsg);
2396 return 0;
2397 }
2398 /* inserting the CC BY-SA 4.0 license */
2399 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2400 strcat (sql,
2401 "VALUES (7, 'CC BY-SA 4.0', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt')");
2402 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2403 if (ret != SQLITE_OK)
2404 {
2405 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2406 sqlite3_free (errMsg);
2407 return 0;
2408 }
2409 /* inserting the CC BY-SA-NC 3.0 license */
2410 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2411 strcat (sql,
2412 "VALUES (8, 'CC BY-SA-NC 3.0', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode.txt')");
2413 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2414 if (ret != SQLITE_OK)
2415 {
2416 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2417 sqlite3_free (errMsg);
2418 return 0;
2419 }
2420 /* inserting the CC BY-SA-NC 4.0 license */
2421 strcpy (sql, "INSERT OR IGNORE INTO data_licenses (id, name, url) ");
2422 strcat (sql,
2423 "VALUES (9, 'CC BY-SA-NC 4.0', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt')");
2424 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2425 if (ret != SQLITE_OK)
2426 {
2427 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2428 sqlite3_free (errMsg);
2429 return 0;
2430 }
2431 return 1;
2432 }
2433
2434 SPATIALITE_PRIVATE int
check_layer_statistics(void * p_sqlite)2435 check_layer_statistics (void *p_sqlite)
2436 {
2437 /*
2438 / checks the LAYER_STATISTICS table for validity;
2439 / if the table doesn't exist, attempts to create
2440 */
2441 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
2442 char sql[8192];
2443 char **results;
2444 int rows;
2445 int columns;
2446 int ret;
2447 int raster_layer = 0;
2448 int table_name = 0;
2449 int geometry_column = 0;
2450 int row_count = 0;
2451 int extent_min_x = 0;
2452 int extent_min_y = 0;
2453 int extent_max_x = 0;
2454 int extent_max_y = 0;
2455 int i;
2456 const char *name;
2457 int has_pk = 0;
2458
2459 /* checking the LAYER_STATISTICS table */
2460 ret =
2461 sqlite3_get_table (sqlite, "PRAGMA table_info(layer_statistics)",
2462 &results, &rows, &columns, NULL);
2463 if (ret != SQLITE_OK)
2464 return 0;
2465 if (rows < 1)
2466 ;
2467 else
2468 {
2469 for (i = 1; i <= rows; i++)
2470 {
2471 name = results[(i * columns) + 1];
2472 if (strcasecmp (name, "raster_layer") == 0)
2473 raster_layer = 1;
2474 if (strcasecmp (name, "table_name") == 0)
2475 table_name = 1;
2476 if (strcasecmp (name, "geometry_column") == 0)
2477 geometry_column = 1;
2478 if (strcasecmp (name, "row_count") == 0)
2479 row_count = 1;
2480 if (strcasecmp (name, "extent_min_x") == 0)
2481 extent_min_x = 1;
2482 if (strcasecmp (name, "extent_min_y") == 0)
2483 extent_min_y = 1;
2484 if (strcasecmp (name, "extent_max_x") == 0)
2485 extent_max_x = 1;
2486 if (strcasecmp (name, "extent_max_y") == 0)
2487 extent_max_y = 1;
2488 }
2489 }
2490 sqlite3_free_table (results);
2491
2492 /* LAYER_STATISTICS already exists and has a valid layout */
2493 if (raster_layer && table_name && geometry_column && row_count
2494 && extent_min_x && extent_max_x && extent_min_y && extent_max_y)
2495 return 1;
2496 /* LAYER_STATISTICS already exists, but has an invalid layout */
2497 if (raster_layer || table_name || geometry_column || row_count
2498 || extent_min_x || extent_max_x || extent_min_y || extent_max_y)
2499 return 0;
2500
2501 /* checking if GEOMETRY_COLUMNS has a Primary Key */
2502 ret =
2503 sqlite3_get_table (sqlite, "PRAGMA table_info(geometry_columns)",
2504 &results, &rows, &columns, NULL);
2505 if (ret != SQLITE_OK)
2506 return 0;
2507 if (rows < 1)
2508 ;
2509 else
2510 {
2511 for (i = 1; i <= rows; i++)
2512 {
2513 name = results[(i * columns) + 5];
2514 if (atoi (name) != 0)
2515 has_pk = 1;
2516 }
2517 }
2518 sqlite3_free_table (results);
2519
2520 /* attempting to create LAYER_STATISTICS */
2521 if (has_pk)
2522 {
2523 /* GEOMETRY_COLUMNS has a Primary Key */
2524 strcpy (sql, "CREATE TABLE layer_statistics (\n");
2525 strcat (sql, "raster_layer INTEGER NOT NULL,\n");
2526 strcat (sql, "table_name TEXT NOT NULL,\n");
2527 strcat (sql, "geometry_column TEXT NOT NULL,\n");
2528 strcat (sql, "row_count INTEGER,\n");
2529 strcat (sql, "extent_min_x DOUBLE,\n");
2530 strcat (sql, "extent_min_y DOUBLE,\n");
2531 strcat (sql, "extent_max_x DOUBLE,\n");
2532 strcat (sql, "extent_max_y DOUBLE,\n");
2533 strcat (sql, "CONSTRAINT pk_layer_statistics PRIMARY KEY ");
2534 strcat (sql, "(raster_layer, table_name, geometry_column),\n");
2535 strcat (sql, "CONSTRAINT fk_layer_statistics FOREIGN KEY ");
2536 strcat (sql, "(table_name, geometry_column) REFERENCES ");
2537 strcat (sql, "geometry_columns (f_table_name, f_geometry_column) ");
2538 strcat (sql, "ON DELETE CASCADE)");
2539 }
2540 else
2541 {
2542 /* there is no Primary Key on GEOMETRY_COLUMNS */
2543 strcpy (sql, "CREATE TABLE layer_statistics (\n");
2544 strcat (sql, "raster_layer INTEGER NOT NULL,\n");
2545 strcat (sql, "table_name TEXT NOT NULL,\n");
2546 strcat (sql, "geometry_column TEXT NOT NULL,\n");
2547 strcat (sql, "row_count INTEGER,\n");
2548 strcat (sql, "extent_min_x DOUBLE,\n");
2549 strcat (sql, "extent_min_y DOUBLE,\n");
2550 strcat (sql, "extent_max_x DOUBLE,\n");
2551 strcat (sql, "extent_max_y DOUBLE,\n");
2552 strcat (sql, "CONSTRAINT pk_layer_statistics PRIMARY KEY ");
2553 strcat (sql, "(raster_layer, table_name, geometry_column))");
2554 }
2555 ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
2556 if (ret != SQLITE_OK)
2557 return 0;
2558 return 1;
2559 }
2560
2561 SPATIALITE_PRIVATE int
check_views_layer_statistics(void * p_sqlite)2562 check_views_layer_statistics (void *p_sqlite)
2563 {
2564 /*
2565 / checks the VIEWS_LAYER_STATISTICS table for validity;
2566 / if the table doesn't exist, attempts to create
2567 */
2568 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
2569 char sql[8192];
2570 char **results;
2571 int rows;
2572 int columns;
2573 int ret;
2574 int view_name = 0;
2575 int view_geometry = 0;
2576 int row_count = 0;
2577 int extent_min_x = 0;
2578 int extent_min_y = 0;
2579 int extent_max_x = 0;
2580 int extent_max_y = 0;
2581 int i;
2582 const char *name;
2583
2584 /* checking the VIEWS_LAYER_STATISTICS table */
2585 ret =
2586 sqlite3_get_table (sqlite, "PRAGMA table_info(views_layer_statistics)",
2587 &results, &rows, &columns, NULL);
2588 if (ret != SQLITE_OK)
2589 return 0;
2590 if (rows < 1)
2591 ;
2592 else
2593 {
2594 for (i = 1; i <= rows; i++)
2595 {
2596 name = results[(i * columns) + 1];
2597 if (strcasecmp (name, "view_name") == 0)
2598 view_name = 1;
2599 if (strcasecmp (name, "view_geometry") == 0)
2600 view_geometry = 1;
2601 if (strcasecmp (name, "row_count") == 0)
2602 row_count = 1;
2603 if (strcasecmp (name, "extent_min_x") == 0)
2604 extent_min_x = 1;
2605 if (strcasecmp (name, "extent_min_y") == 0)
2606 extent_min_y = 1;
2607 if (strcasecmp (name, "extent_max_x") == 0)
2608 extent_max_x = 1;
2609 if (strcasecmp (name, "extent_max_y") == 0)
2610 extent_max_y = 1;
2611 }
2612 }
2613 sqlite3_free_table (results);
2614
2615 /* VIEWS_LAYER_STATISTICS already exists and has a valid layout */
2616 if (view_name && view_geometry && row_count && extent_min_x && extent_max_x
2617 && extent_min_y && extent_max_y)
2618 return 1;
2619 /* VIEWS_LAYER_STATISTICS already exists, but has an invalid layout */
2620 if (view_name || view_geometry || row_count || extent_min_x || extent_max_x
2621 || extent_min_y || extent_max_y)
2622 return 0;
2623
2624 /* attempting to create VIEWS_LAYER_STATISTICS */
2625 strcpy (sql, "CREATE TABLE views_layer_statistics (\n");
2626 strcat (sql, "view_name TEXT NOT NULL,\n");
2627 strcat (sql, "view_geometry TEXT NOT NULL,\n");
2628 strcat (sql, "row_count INTEGER,\n");
2629 strcat (sql, "extent_min_x DOUBLE,\n");
2630 strcat (sql, "extent_min_y DOUBLE,\n");
2631 strcat (sql, "extent_max_x DOUBLE,\n");
2632 strcat (sql, "extent_max_y DOUBLE,\n");
2633 strcat (sql, "CONSTRAINT pk_views_layer_statistics PRIMARY KEY ");
2634 strcat (sql, "(view_name, view_geometry),\n");
2635 strcat (sql, "CONSTRAINT fk_views_layer_statistics FOREIGN KEY ");
2636 strcat (sql, "(view_name, view_geometry) REFERENCES ");
2637 strcat (sql, "views_geometry_columns (view_name, view_geometry) ");
2638 strcat (sql, "ON DELETE CASCADE)");
2639 ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
2640 if (ret != SQLITE_OK)
2641 return 0;
2642 return 1;
2643 }
2644
2645 SPATIALITE_PRIVATE int
check_virts_layer_statistics(void * p_sqlite)2646 check_virts_layer_statistics (void *p_sqlite)
2647 {
2648 /*
2649 / checks the VIRTS_LAYER_STATISTICS table for validity;
2650 / if the table doesn't exist, attempts to create
2651 */
2652 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
2653 char sql[8192];
2654 char **results;
2655 int rows;
2656 int columns;
2657 int ret;
2658 int virt_name = 0;
2659 int virt_geometry = 0;
2660 int row_count = 0;
2661 int extent_min_x = 0;
2662 int extent_min_y = 0;
2663 int extent_max_x = 0;
2664 int extent_max_y = 0;
2665 int i;
2666 const char *name;
2667
2668 /* checking the VIRTS_LAYER_STATISTICS table */
2669 ret =
2670 sqlite3_get_table (sqlite, "PRAGMA table_info(virts_layer_statistics)",
2671 &results, &rows, &columns, NULL);
2672 if (ret != SQLITE_OK)
2673 return 0;
2674 if (rows < 1)
2675 ;
2676 else
2677 {
2678 for (i = 1; i <= rows; i++)
2679 {
2680 name = results[(i * columns) + 1];
2681 if (strcasecmp (name, "virt_name") == 0)
2682 virt_name = 1;
2683 if (strcasecmp (name, "virt_geometry") == 0)
2684 virt_geometry = 1;
2685 if (strcasecmp (name, "row_count") == 0)
2686 row_count = 1;
2687 if (strcasecmp (name, "extent_min_x") == 0)
2688 extent_min_x = 1;
2689 if (strcasecmp (name, "extent_min_y") == 0)
2690 extent_min_y = 1;
2691 if (strcasecmp (name, "extent_max_x") == 0)
2692 extent_max_x = 1;
2693 if (strcasecmp (name, "extent_max_y") == 0)
2694 extent_max_y = 1;
2695 }
2696 }
2697 sqlite3_free_table (results);
2698
2699 /* VIRTS_LAYER_STATISTICS already exists and has a valid layout */
2700 if (virt_name && virt_geometry && row_count && extent_min_x && extent_max_x
2701 && extent_min_y && extent_max_y)
2702 return 1;
2703 /* VIRTS_LAYER_STATISTICS already exists, but has an invalid layout */
2704 if (virt_name || virt_geometry || row_count || extent_min_x || extent_max_x
2705 || extent_min_y || extent_max_y)
2706 return 0;
2707
2708 /* attempting to create VIRTS_LAYER_STATISTICS */
2709 strcpy (sql, "CREATE TABLE virts_layer_statistics (\n");
2710 strcat (sql, "virt_name TEXT NOT NULL,\n");
2711 strcat (sql, "virt_geometry TEXT NOT NULL,\n");
2712 strcat (sql, "row_count INTEGER,\n");
2713 strcat (sql, "extent_min_x DOUBLE,\n");
2714 strcat (sql, "extent_min_y DOUBLE,\n");
2715 strcat (sql, "extent_max_x DOUBLE,\n");
2716 strcat (sql, "extent_max_y DOUBLE,\n");
2717 strcat (sql, "CONSTRAINT pk_virts_layer_statistics PRIMARY KEY ");
2718 strcat (sql, "(virt_name, virt_geometry),\n");
2719 strcat (sql, "CONSTRAINT fk_virts_layer_statistics FOREIGN KEY ");
2720 strcat (sql, "(virt_name, virt_geometry) REFERENCES ");
2721 strcat (sql, "virts_geometry_columns (virt_name, virt_geometry) ");
2722 strcat (sql, "ON DELETE CASCADE)");
2723 ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
2724 if (ret != SQLITE_OK)
2725 return 0;
2726 return 1;
2727 }
2728
2729 static int
create_sql_statements_log(sqlite3 * sqlite)2730 create_sql_statements_log (sqlite3 * sqlite)
2731 {
2732 char sql[4186];
2733 char *errMsg = NULL;
2734 int ret;
2735 /* creating the SQL_STATEMENTS_LOG table */
2736 strcpy (sql, "CREATE TABLE IF NOT EXISTS ");
2737 strcat (sql, "sql_statements_log (\n");
2738 strcat (sql, "id INTEGER PRIMARY KEY AUTOINCREMENT,\n");
2739 strcat (sql,
2740 "time_start TIMESTAMP NOT NULL DEFAULT '0000-01-01T00:00:00.000Z',\n");
2741 strcat (sql,
2742 "time_end TIMESTAMP NOT NULL DEFAULT '0000-01-01T00:00:00.000Z',\n");
2743 strcat (sql, "user_agent TEXT NOT NULL,\n");
2744 strcat (sql, "sql_statement TEXT NOT NULL,\n");
2745 strcat (sql, "success INTEGER NOT NULL DEFAULT 0,\n");
2746 strcat (sql, "error_cause TEXT NOT NULL DEFAULT 'ABORTED',\n");
2747 strcat (sql, "CONSTRAINT sqllog_success CHECK ");
2748 strcat (sql, "(success IN (0,1)))");
2749 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2750 if (ret != SQLITE_OK)
2751 {
2752 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2753 sqlite3_free (errMsg);
2754 return 0;
2755 }
2756 return 1;
2757 }
2758
2759 SPATIALITE_PRIVATE int
createAdvancedMetaData(void * p_sqlite)2760 createAdvancedMetaData (void *p_sqlite)
2761 {
2762 /* creating the advanced MetaData tables */
2763 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
2764 if (!create_views_geometry_columns (sqlite))
2765 return 0;
2766 if (!create_virts_geometry_columns (sqlite))
2767 return 0;
2768 if (!create_geometry_columns_statistics (sqlite))
2769 return 0;
2770 if (!create_views_geometry_columns_statistics (sqlite))
2771 return 0;
2772 if (!create_virts_geometry_columns_statistics (sqlite))
2773 return 0;
2774 if (!create_geometry_columns_field_infos (sqlite))
2775 return 0;
2776 if (!create_views_geometry_columns_field_infos (sqlite))
2777 return 0;
2778 if (!create_virts_geometry_columns_field_infos (sqlite))
2779 return 0;
2780 if (!create_geometry_columns_time (sqlite))
2781 return 0;
2782 if (!create_geometry_columns_auth (sqlite))
2783 return 0;
2784 if (!create_views_geometry_columns_auth (sqlite))
2785 return 0;
2786 if (!create_virts_geometry_columns_auth (sqlite))
2787 return 0;
2788 if (!create_geometry_columns_views (sqlite))
2789 return 0;
2790 if (!create_data_licenses (sqlite))
2791 return 0;
2792 if (!create_sql_statements_log (sqlite))
2793 return 0;
2794
2795 return 1;
2796 }
2797
2798 SPATIALITE_PRIVATE int
createGeometryColumns(void * p_sqlite)2799 createGeometryColumns (void *p_sqlite)
2800 {
2801 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
2802 char sql[4186];
2803 char *errMsg = NULL;
2804 int ret;
2805 /* creating the GEOMETRY_COLUMNS table */
2806 strcpy (sql, "CREATE TABLE geometry_columns (\n");
2807 strcat (sql, "f_table_name TEXT NOT NULL,\n");
2808 strcat (sql, "f_geometry_column TEXT NOT NULL,\n");
2809 strcat (sql, "geometry_type INTEGER NOT NULL,\n");
2810 strcat (sql, "coord_dimension INTEGER NOT NULL,\n");
2811 strcat (sql, "srid INTEGER NOT NULL,\n");
2812 strcat (sql, "spatial_index_enabled INTEGER NOT NULL,\n");
2813 strcat (sql, "CONSTRAINT pk_geom_cols PRIMARY KEY ");
2814 strcat (sql, "(f_table_name, f_geometry_column),\n");
2815 strcat (sql, "CONSTRAINT fk_gc_srs FOREIGN KEY ");
2816 strcat (sql, "(srid) REFERENCES spatial_ref_sys (srid),\n");
2817 strcat (sql, "CONSTRAINT ck_gc_rtree CHECK ");
2818 strcat (sql, "(spatial_index_enabled IN (0,1,2)))");
2819 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2820 if (ret != SQLITE_OK)
2821 {
2822 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2823 sqlite3_free (errMsg);
2824 return 0;
2825 }
2826 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2827 "table successfully created");
2828 /* creating an INDEX corresponding to the SRID FK */
2829 strcpy (sql, "CREATE INDEX idx_srid_geocols ON geometry_columns\n");
2830 strcat (sql, "(srid) ");
2831 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2832 if (ret != SQLITE_OK)
2833 {
2834 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2835 sqlite3_free (errMsg);
2836 return 0;
2837 }
2838 /* creating the GEOMETRY_COLUMNS triggers */
2839 strcpy (sql, "CREATE TRIGGER geometry_columns_f_table_name_insert\n");
2840 strcat (sql, "BEFORE INSERT ON 'geometry_columns'\n");
2841 strcat (sql, "FOR EACH ROW BEGIN\n");
2842 strcat (sql,
2843 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: ");
2844 strcat (sql, "f_table_name value must not contain a single quote')\n");
2845 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
2846 strcat (sql,
2847 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: ");
2848 strcat (sql, "f_table_name value must not contain a double quote')\n");
2849 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
2850 strcat (sql,
2851 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: \n");
2852 strcat (sql, "f_table_name value must be lower case')\n");
2853 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
2854 strcat (sql, "END");
2855 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2856 if (ret != SQLITE_OK)
2857 {
2858 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2859 sqlite3_free (errMsg);
2860 return 0;
2861 }
2862 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2863 "trigger 'geometry_columns_f_table_name_insert' successfully created");
2864 strcpy (sql, "CREATE TRIGGER geometry_columns_f_table_name_update\n");
2865 strcat (sql, "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns'\n");
2866 strcat (sql, "FOR EACH ROW BEGIN\n");
2867 strcat (sql,
2868 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2869 strcat (sql, "f_table_name value must not contain a single quote')\n");
2870 strcat (sql, "WHERE NEW.f_table_name LIKE ('%''%');\n");
2871 strcat (sql,
2872 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2873 strcat (sql, "f_table_name value must not contain a double quote')\n");
2874 strcat (sql, "WHERE NEW.f_table_name LIKE ('%\"%');\n");
2875 strcat (sql,
2876 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2877 strcat (sql, "f_table_name value must be lower case')\n");
2878 strcat (sql, "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n");
2879 strcat (sql, "END");
2880 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2881 if (ret != SQLITE_OK)
2882 {
2883 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2884 sqlite3_free (errMsg);
2885 return 0;
2886 }
2887 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2888 "trigger 'geometry_columns_f_table_name_update' successfully created");
2889 strcpy (sql, "CREATE TRIGGER geometry_columns_f_geometry_column_insert\n");
2890 strcat (sql, "BEFORE INSERT ON 'geometry_columns'\n");
2891 strcat (sql, "FOR EACH ROW BEGIN\n");
2892 strcat (sql,
2893 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: ");
2894 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
2895 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
2896 strcat (sql,
2897 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: \n");
2898 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
2899 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
2900 strcat (sql,
2901 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: ");
2902 strcat (sql, "f_geometry_column value must be lower case')\n");
2903 strcat (sql,
2904 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
2905 strcat (sql, "END");
2906 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2907 if (ret != SQLITE_OK)
2908 {
2909 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2910 sqlite3_free (errMsg);
2911 return 0;
2912 }
2913 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2914 "trigger 'geometry_columns_f_geometry_column_insert' successfully created");
2915 strcpy (sql, "CREATE TRIGGER geometry_columns_f_geometry_column_update\n");
2916 strcat (sql,
2917 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns'\n");
2918 strcat (sql, "FOR EACH ROW BEGIN\n");
2919 strcat (sql,
2920 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2921 strcat (sql, "f_geometry_column value must not contain a single quote')\n");
2922 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%''%');\n");
2923 strcat (sql,
2924 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2925 strcat (sql, "f_geometry_column value must not contain a double quote')\n");
2926 strcat (sql, "WHERE NEW.f_geometry_column LIKE ('%\"%');\n");
2927 strcat (sql,
2928 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: ");
2929 strcat (sql, "f_geometry_column value must be lower case')\n");
2930 strcat (sql,
2931 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n");
2932 strcat (sql, "END");
2933 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2934 if (ret != SQLITE_OK)
2935 {
2936 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2937 sqlite3_free (errMsg);
2938 return 0;
2939 }
2940 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2941 "trigger 'geometry_columns_f_geometry_column_update' successfully created");
2942 strcpy (sql, "CREATE TRIGGER geometry_columns_geometry_type_insert\n");
2943 strcat (sql, "BEFORE INSERT ON 'geometry_columns'\n");
2944 strcat (sql, "FOR EACH ROW BEGIN\n");
2945 strcat (sql, "SELECT RAISE(ABORT,'geometry_type must be one of ");
2946 strcat (sql, "0,1,2,3,4,5,6,7,");
2947 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
2948 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
2949 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007')\n");
2950 strcat (sql, "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,");
2951 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
2952 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
2953 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007));\n");
2954 strcat (sql, "END");
2955 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2956 if (ret != SQLITE_OK)
2957 {
2958 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2959 sqlite3_free (errMsg);
2960 return 0;
2961 }
2962 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2963 "trigger 'geometry_columns_geometry_type_insert' successfully created");
2964 strcpy (sql, "CREATE TRIGGER geometry_columns_geometry_type_update\n");
2965 strcat (sql, "BEFORE UPDATE OF 'geometry_type' ON 'geometry_columns'\n");
2966 strcat (sql, "FOR EACH ROW BEGIN\n");
2967 strcat (sql, "SELECT RAISE(ABORT,'geometry_type must be one of ");
2968 strcat (sql, "0,1,2,3,4,5,6,7,");
2969 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
2970 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
2971 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007')\n");
2972 strcat (sql, "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,");
2973 strcat (sql, "1000,1001,1002,1003,1004,1005,1006,1007,");
2974 strcat (sql, "2000,2001,2002,2003,2004,2005,2006,2007,");
2975 strcat (sql, "3000,3001,3002,3003,3004,3005,3006,3007));\n");
2976 strcat (sql, "END");
2977 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2978 if (ret != SQLITE_OK)
2979 {
2980 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2981 sqlite3_free (errMsg);
2982 return 0;
2983 }
2984 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
2985 "trigger 'geometry_columns_geometry_type_update' successfully created");
2986 strcpy (sql, "CREATE TRIGGER geometry_columns_coord_dimension_insert\n");
2987 strcat (sql, "BEFORE INSERT ON 'geometry_columns'\n");
2988 strcat (sql, "FOR EACH ROW BEGIN\n");
2989 strcat (sql,
2990 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n");
2991 strcat (sql, "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n");
2992 strcat (sql, "END");
2993 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2994 if (ret != SQLITE_OK)
2995 {
2996 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
2997 sqlite3_free (errMsg);
2998 return 0;
2999 }
3000 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
3001 "trigger 'geometry_columns_coord_dimension_insert' successfully created");
3002 strcpy (sql, "CREATE TRIGGER geometry_columns_coord_dimension_update\n");
3003 strcat (sql, "BEFORE UPDATE OF 'coord_dimension' ON 'geometry_columns'\n");
3004 strcat (sql, "FOR EACH ROW BEGIN\n");
3005 strcat (sql,
3006 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n");
3007 strcat (sql, "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n");
3008 strcat (sql, "END");
3009 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3010 if (ret != SQLITE_OK)
3011 {
3012 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3013 sqlite3_free (errMsg);
3014 return 0;
3015 }
3016 updateSpatiaLiteHistory (sqlite, "geometry_columns", NULL,
3017 "trigger 'geometry_columns_coord_dimension_update' successfully created");
3018 return 1;
3019 }
3020
3021 SPATIALITE_PRIVATE int
createTemporarySpatialRefSys(void * p_sqlite,const char * db_prefix)3022 createTemporarySpatialRefSys (void *p_sqlite, const char *db_prefix)
3023 {
3024 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
3025 char *sql_statement;
3026 sqlite3_stmt *stmt;
3027 int ret;
3028 char *prefix;
3029 int already_defined = 0;
3030 char *errMsg = NULL;
3031
3032 /* checking if already defined */
3033 prefix = gaiaDoubleQuotedSql (db_prefix);
3034 sql_statement = sqlite3_mprintf ("SELECT name "
3035 "FROM \"%s\".sqlite_master WHERE type = 'table' "
3036 "AND Lower(name) = 'spatial_ref_sys'",
3037 prefix);
3038 free (prefix);
3039 /* compiling SQL prepared statement */
3040 ret =
3041 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
3042 &stmt, NULL);
3043 sqlite3_free (sql_statement);
3044 if (ret != SQLITE_OK)
3045 {
3046 spatialite_e ("createTemporarySpatialRefSys: error %d \"%s\"\n",
3047 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
3048 return 0;
3049 }
3050 sqlite3_reset (stmt);
3051 sqlite3_clear_bindings (stmt);
3052 while (1)
3053 {
3054 /* scrolling the result set rows */
3055 ret = sqlite3_step (stmt);
3056 if (ret == SQLITE_DONE)
3057 break; /* end of result set */
3058 if (ret == SQLITE_ROW)
3059 already_defined = 1;
3060 }
3061 sqlite3_finalize (stmt);
3062
3063 if (already_defined)
3064 return 1;
3065
3066 /* creating the SPATIAL_REF_SYS table */
3067 prefix = gaiaDoubleQuotedSql (db_prefix);
3068 sql_statement = sqlite3_mprintf ("CREATE TABLE \"%s\".spatial_ref_sys (\n"
3069 "srid INTEGER NOT NULL PRIMARY KEY,\n"
3070 "auth_name TEXT NOT NULL,\n"
3071 "auth_srid INTEGER NOT NULL,\n"
3072 "ref_sys_name TEXT NOT NULL DEFAULT 'Unknown',\n"
3073 "proj4text TEXT NOT NULL,\n"
3074 "srtext TEXT NOT NULL DEFAULT 'Undefined')",
3075 prefix);
3076 free (prefix);
3077 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3078 sqlite3_free (sql_statement);
3079 if (ret != SQLITE_OK)
3080 goto error;
3081 prefix = gaiaDoubleQuotedSql (db_prefix);
3082 sql_statement =
3083 sqlite3_mprintf ("CREATE UNIQUE INDEX \"%s\".idx_spatial_ref_sys \n"
3084 "ON spatial_ref_sys (auth_srid, auth_name)", prefix);
3085 free (prefix);
3086 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3087 sqlite3_free (sql_statement);
3088 if (ret != SQLITE_OK)
3089 goto error;
3090
3091 sql_statement = sqlite3_mprintf ("SAVEPOINT tmp_spatial_ref_sys");
3092 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3093 sqlite3_free (sql_statement);
3094 if (ret != SQLITE_OK)
3095 goto error;
3096 prefix = gaiaDoubleQuotedSql (db_prefix);
3097 sql_statement = sqlite3_mprintf ("INSERT INTO \"%s\".spatial_ref_sys "
3098 "(srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext) "
3099 "SELECT srid, auth_name, auth_srid, ref_sys_name, proj4text, srtext "
3100 "FROM main.spatial_ref_sys", prefix);
3101 free (prefix);
3102 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3103 sqlite3_free (sql_statement);
3104 if (ret != SQLITE_OK)
3105 goto error;
3106 sql_statement = sqlite3_mprintf ("RELEASE SAVEPOINT tmp_spatial_ref_sys");
3107 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3108 sqlite3_free (sql_statement);
3109 if (ret != SQLITE_OK)
3110 goto error;
3111
3112 return 1;
3113
3114 error:
3115 return 0;
3116 }
3117
3118 static int
createTemporaryViewsGeometryColumns(sqlite3 * sqlite,const char * db_prefix)3119 createTemporaryViewsGeometryColumns (sqlite3 * sqlite, const char *db_prefix)
3120 {
3121 /* creating the VIEWS_GEOMETRY_COLUMNS table */
3122 char *sql;
3123 char *errMsg = NULL;
3124 int ret;
3125 char *prefix;
3126
3127 /* creating the VIEWS_GEOMETRY_COLUMNS table */
3128 prefix = gaiaDoubleQuotedSql (db_prefix);
3129 sql =
3130 sqlite3_mprintf
3131 ("CREATE TABLE IF NOT EXISTS \"%s\".views_geometry_columns (\n"
3132 "view_name TEXT NOT NULL,\n" "view_geometry TEXT NOT NULL,\n"
3133 "view_rowid TEXT NOT NULL,\n" "f_table_name TEXT NOT NULL,\n"
3134 "f_geometry_column TEXT NOT NULL,\n" "read_only INTEGER NOT NULL,\n"
3135 "CONSTRAINT pk_geom_cols_views PRIMARY KEY "
3136 "(view_name, view_geometry),\n"
3137 "CONSTRAINT fk_views_geom_cols FOREIGN KEY "
3138 "(f_table_name, f_geometry_column) " "REFERENCES geometry_columns "
3139 "(f_table_name, f_geometry_column) " "ON DELETE CASCADE,\n"
3140 "CONSTRAINT ck_vw_rdonly CHECK (read_only IN (0,1)))", prefix);
3141 free (prefix);
3142 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3143 sqlite3_free (sql);
3144 if (ret != SQLITE_OK)
3145 {
3146 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3147 sqlite3_free (errMsg);
3148 return 0;
3149 }
3150 /* creating an INDEX supporting the GEOMETRY_COLUMNS FK */
3151 prefix = gaiaDoubleQuotedSql (db_prefix);
3152 sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS \"%s\".idx_viewsjoin "
3153 "ON views_geometry_columns\n"
3154 "(f_table_name, f_geometry_column)", prefix);
3155 free (prefix);
3156 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3157 if (ret != SQLITE_OK)
3158 {
3159 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3160 sqlite3_free (errMsg);
3161 sqlite3_free (sql);
3162 return 0;
3163 }
3164 sqlite3_free (sql);
3165 /* creating the VIEWS_GEOMETRY_COLUMNS triggers */
3166 prefix = gaiaDoubleQuotedSql (db_prefix);
3167 sql =
3168 sqlite3_mprintf
3169 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_name_insert\n"
3170 "BEFORE INSERT ON 'views_geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3171 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3172 "view_name value must not contain a single quote')\n"
3173 "WHERE NEW.view_name LIKE ('%%''%%');\n"
3174 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3175 "view_name value must not contain a double quote')\n"
3176 "WHERE NEW.view_name LIKE ('%%\"%%');\n"
3177 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n"
3178 "view_name value must be lower case')\n"
3179 "WHERE NEW.view_name <> lower(NEW.view_name);\n" "END", prefix);
3180 free (prefix);
3181 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3182 if (ret != SQLITE_OK)
3183 {
3184 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3185 sqlite3_free (errMsg);
3186 sqlite3_free (sql);
3187 return 0;
3188 }
3189 sqlite3_free (sql);
3190 prefix = gaiaDoubleQuotedSql (db_prefix);
3191 sql =
3192 sqlite3_mprintf
3193 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_name_update\n"
3194 "BEFORE UPDATE OF 'view_name' ON 'views_geometry_columns'\n"
3195 "FOR EACH ROW BEGIN\n"
3196 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3197 "view_name value must not contain a single quote')\n"
3198 "WHERE NEW.view_name LIKE ('%%''%%');\n"
3199 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3200 "view_name value must not contain a double quote')\n"
3201 "WHERE NEW.view_name LIKE ('%%\"%%');\n"
3202 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3203 "view_name value must be lower case')\n"
3204 "WHERE NEW.view_name <> lower(NEW.view_name);\n" "END", prefix);
3205 free (prefix);
3206 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3207 if (ret != SQLITE_OK)
3208 {
3209 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3210 sqlite3_free (errMsg);
3211 sqlite3_free (sql);
3212 return 0;
3213 }
3214 sqlite3_free (sql);
3215 prefix = gaiaDoubleQuotedSql (db_prefix);
3216 sql =
3217 sqlite3_mprintf
3218 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_geometry_insert\n"
3219 "BEFORE INSERT ON 'views_geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3220 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3221 "view_geometry value must not contain a single quote')\n"
3222 "WHERE NEW.view_geometry LIKE ('%%''%%');\n"
3223 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n"
3224 "view_geometry value must not contain a double quote')\n"
3225 "WHERE NEW.view_geometry LIKE ('%%\"%%');\n"
3226 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3227 "view_geometry value must be lower case')\n"
3228 "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n" "END",
3229 prefix);
3230 free (prefix);
3231 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3232 if (ret != SQLITE_OK)
3233 {
3234 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3235 sqlite3_free (errMsg);
3236 sqlite3_free (sql);
3237 return 0;
3238 }
3239 sqlite3_free (sql);
3240 prefix = gaiaDoubleQuotedSql (db_prefix);
3241 sql =
3242 sqlite3_mprintf
3243 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_geometry_update\n"
3244 "BEFORE UPDATE OF 'view_geometry' ON 'views_geometry_columns'\n"
3245 "FOR EACH ROW BEGIN\n"
3246 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3247 "view_geometry value must not contain a single quote')\n"
3248 "WHERE NEW.view_geometry LIKE ('%%''%%');\n"
3249 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: \n"
3250 "view_geometry value must not contain a double quote')\n"
3251 "WHERE NEW.view_geometry LIKE ('%%\"%%');\n"
3252 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3253 "view_geometry value must be lower case')\n"
3254 "WHERE NEW.view_geometry <> lower(NEW.view_geometry);\n" "END",
3255 prefix);
3256 free (prefix);
3257 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3258 if (ret != SQLITE_OK)
3259 {
3260 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3261 sqlite3_free (errMsg);
3262 sqlite3_free (sql);
3263 return 0;
3264 }
3265 sqlite3_free (sql);
3266 prefix = gaiaDoubleQuotedSql (db_prefix);
3267 sql =
3268 sqlite3_mprintf
3269 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_rowid_update\n"
3270 "BEFORE UPDATE OF 'view_rowid' ON 'views_geometry_columns'\n"
3271 "FOR EACH ROW BEGIN\n"
3272 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3273 "view_rowid value must not contain a single quote')\n"
3274 "WHERE NEW.f_geometry_column LIKE ('%%''%%');\n"
3275 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3276 "view_rowid value must not contain a double quote')\n"
3277 "WHERE NEW.view_rowid LIKE ('%%\"%%');\n"
3278 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3279 "view_rowid value must be lower case')\n"
3280 "WHERE NEW.view_rowid <> lower(NEW.view_rowid);\n" "END", prefix);
3281 free (prefix);
3282 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3283 if (ret != SQLITE_OK)
3284 {
3285 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3286 sqlite3_free (errMsg);
3287 sqlite3_free (sql);
3288 return 0;
3289 }
3290 sqlite3_free (sql);
3291 prefix = gaiaDoubleQuotedSql (db_prefix);
3292 sql =
3293 sqlite3_mprintf
3294 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_view_rowid_insert\n"
3295 "BEFORE INSERT ON 'views_geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3296 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3297 "view_rowid value must not contain a single quote')\n"
3298 "WHERE NEW.view_rowid LIKE ('%%''%%');\n"
3299 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n"
3300 "view_rowid value must not contain a double quote')\n"
3301 "WHERE NEW.view_rowid LIKE ('%%\"%%');\n"
3302 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3303 "view_rowid value must be lower case')\n"
3304 "WHERE NEW.view_rowid <> lower(NEW.view_rowid);\n" "END", prefix);
3305 free (prefix);
3306 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3307 if (ret != SQLITE_OK)
3308 {
3309 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3310 sqlite3_free (errMsg);
3311 sqlite3_free (sql);
3312 return 0;
3313 }
3314 sqlite3_free (sql);
3315 prefix = gaiaDoubleQuotedSql (db_prefix);
3316 sql =
3317 sqlite3_mprintf
3318 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_f_table_name_insert\n"
3319 "BEFORE INSERT ON 'views_geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3320 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3321 "f_table_name value must not contain a single quote')\n"
3322 "WHERE NEW.f_table_name LIKE ('%%''%%');\n"
3323 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3324 "f_table_name value must not contain a double quote')\n"
3325 "WHERE NEW.f_table_name LIKE ('%%\"%%');\n"
3326 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n"
3327 "f_table_name value must be lower case')\n"
3328 "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n" "END", prefix);
3329 free (prefix);
3330 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3331 if (ret != SQLITE_OK)
3332 {
3333 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3334 sqlite3_free (errMsg);
3335 sqlite3_free (sql);
3336 return 0;
3337 }
3338 sqlite3_free (sql);
3339 prefix = gaiaDoubleQuotedSql (db_prefix);
3340 sql =
3341 sqlite3_mprintf
3342 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_f_table_name_update\n"
3343 "BEFORE UPDATE OF 'f_table_name' ON 'views_geometry_columns'\n"
3344 "FOR EACH ROW BEGIN\n"
3345 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3346 "f_table_name value must not contain a single quote')\n"
3347 "WHERE NEW.f_table_name LIKE ('%%''%%');\n"
3348 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3349 "f_table_name value must not contain a double quote')\n"
3350 "WHERE NEW.f_table_name LIKE ('%%\"%%');\n"
3351 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3352 "f_table_name value must be lower case')\n"
3353 "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n" "END", prefix);
3354 free (prefix);
3355 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3356 if (ret != SQLITE_OK)
3357 {
3358 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3359 sqlite3_free (errMsg);
3360 sqlite3_free (sql);
3361 return 0;
3362 }
3363 sqlite3_free (sql);
3364 prefix = gaiaDoubleQuotedSql (db_prefix);
3365 sql =
3366 sqlite3_mprintf
3367 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_f_geometry_column_insert\n"
3368 "BEFORE INSERT ON 'views_geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3369 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3370 "f_geometry_column value must not contain a single quote')\n"
3371 "WHERE NEW.f_geometry_column LIKE ('%%''%%');\n"
3372 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: \n"
3373 "f_geometry_column value must not contain a double quote')\n"
3374 "WHERE NEW.f_geometry_column LIKE ('%%\"%%');\n"
3375 "SELECT RAISE(ABORT,'insert on views_geometry_columns violates constraint: "
3376 "f_geometry_column value must be lower case')\n"
3377 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n" "END",
3378 prefix);
3379 free (prefix);
3380 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3381 if (ret != SQLITE_OK)
3382 {
3383 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3384 sqlite3_free (errMsg);
3385 sqlite3_free (sql);
3386 return 0;
3387 }
3388 sqlite3_free (sql);
3389 prefix = gaiaDoubleQuotedSql (db_prefix);
3390 sql =
3391 sqlite3_mprintf
3392 ("CREATE TRIGGER IF NOT EXISTS \"%s\".vwgc_f_geometry_column_update\n"
3393 "BEFORE UPDATE OF 'f_geometry_column' ON 'views_geometry_columns'\n"
3394 "FOR EACH ROW BEGIN\n"
3395 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3396 "f_geometry_column value must not contain a single quote')\n"
3397 "WHERE NEW.f_geometry_column LIKE ('%%''%%');\n"
3398 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3399 "f_geometry_column value must not contain a double quote')\n"
3400 "WHERE NEW.f_geometry_column LIKE ('%%\"%%');\n"
3401 "SELECT RAISE(ABORT,'update on views_geometry_columns violates constraint: "
3402 "f_geometry_column value must be lower case')\n"
3403 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n" "END",
3404 prefix);
3405 free (prefix);
3406 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3407 if (ret != SQLITE_OK)
3408 {
3409 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3410 sqlite3_free (errMsg);
3411 sqlite3_free (sql);
3412 return 0;
3413 }
3414 sqlite3_free (sql);
3415 return 1;
3416 }
3417
3418 SPATIALITE_PRIVATE int
createTemporaryGeometryColumns(void * p_sqlite,const char * db_prefix)3419 createTemporaryGeometryColumns (void *p_sqlite, const char *db_prefix)
3420 {
3421 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
3422 char *sql;
3423 char *errMsg = NULL;
3424 int ret;
3425 char *prefix;
3426 /* creating the GEOMETRY_COLUMNS table */
3427 prefix = gaiaDoubleQuotedSql (db_prefix);
3428 sql =
3429 sqlite3_mprintf
3430 ("CREATE TABLE IF NOT EXISTS \"%s\".geometry_columns (\n"
3431 "f_table_name TEXT NOT NULL,\n" "f_geometry_column TEXT NOT NULL,\n"
3432 "geometry_type INTEGER NOT NULL,\n"
3433 "coord_dimension INTEGER NOT NULL,\n" "srid INTEGER NOT NULL,\n"
3434 "spatial_index_enabled INTEGER NOT NULL,\n"
3435 "CONSTRAINT pk_geom_cols PRIMARY KEY "
3436 "(f_table_name, f_geometry_column),\n"
3437 "CONSTRAINT fk_gc_srs FOREIGN KEY "
3438 "(srid) REFERENCES spatial_ref_sys (srid),\n"
3439 "CONSTRAINT ck_gc_rtree CHECK " "(spatial_index_enabled IN (0,1)))",
3440 prefix);
3441 free (prefix);
3442 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3443 if (ret != SQLITE_OK)
3444 {
3445 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3446 sqlite3_free (errMsg);
3447 sqlite3_free (sql);
3448 return 0;
3449 }
3450 sqlite3_free (sql);
3451 /* creating an INDEX corresponding to the SRID FK */
3452 prefix = gaiaDoubleQuotedSql (db_prefix);
3453 sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS \"%s\".idx_srid_geocols "
3454 "ON geometry_columns (srid)", prefix);
3455 free (prefix);
3456 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3457 if (ret != SQLITE_OK)
3458 {
3459 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3460 sqlite3_free (sql);
3461 sqlite3_free (errMsg);
3462 return 0;
3463 }
3464 sqlite3_free (sql);
3465 /* creating the GEOMETRY_COLUMNS triggers */
3466 prefix = gaiaDoubleQuotedSql (db_prefix);
3467 sql =
3468 sqlite3_mprintf
3469 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_f_table_name_insert\n"
3470 "BEFORE INSERT ON 'geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3471 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: "
3472 "f_table_name value must not contain a single quote')\n"
3473 "WHERE NEW.f_table_name LIKE ('%%''%%');\n"
3474 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: "
3475 "f_table_name value must not contain a double quote')\n"
3476 "WHERE NEW.f_table_name LIKE ('%%\"%%');\n"
3477 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: \n"
3478 "f_table_name value must be lower case')\n"
3479 "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n" "END", prefix);
3480 free (prefix);
3481 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3482 if (ret != SQLITE_OK)
3483 {
3484 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3485 sqlite3_free (errMsg);
3486 sqlite3_free (sql);
3487 return 0;
3488 }
3489 sqlite3_free (sql);
3490 prefix = gaiaDoubleQuotedSql (db_prefix);
3491 sql =
3492 sqlite3_mprintf
3493 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_f_table_name_update\n"
3494 "BEFORE UPDATE OF 'f_table_name' ON 'geometry_columns'\n"
3495 "FOR EACH ROW BEGIN\n"
3496 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3497 "f_table_name value must not contain a single quote')\n"
3498 "WHERE NEW.f_table_name LIKE ('%%''%%');\n"
3499 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3500 "f_table_name value must not contain a double quote')\n"
3501 "WHERE NEW.f_table_name LIKE ('%%\"%%');\n"
3502 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3503 "f_table_name value must be lower case')\n"
3504 "WHERE NEW.f_table_name <> lower(NEW.f_table_name);\n" "END", prefix);
3505 free (prefix);
3506 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3507 if (ret != SQLITE_OK)
3508 {
3509 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3510 sqlite3_free (errMsg);
3511 sqlite3_free (sql);
3512 return 0;
3513 }
3514 sqlite3_free (sql);
3515 prefix = gaiaDoubleQuotedSql (db_prefix);
3516 sql =
3517 sqlite3_mprintf
3518 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_f_geometry_column_insert\n"
3519 "BEFORE INSERT ON 'geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3520 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: "
3521 "f_geometry_column value must not contain a single quote')\n"
3522 "WHERE NEW.f_geometry_column LIKE ('%%''%%');\n"
3523 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: \n"
3524 "f_geometry_column value must not contain a double quote')\n"
3525 "WHERE NEW.f_geometry_column LIKE ('%%\"%%');\n"
3526 "SELECT RAISE(ABORT,'insert on geometry_columns violates constraint: "
3527 "f_geometry_column value must be lower case')\n"
3528 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n" "END",
3529 prefix);
3530 free (prefix);
3531 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3532 if (ret != SQLITE_OK)
3533 {
3534 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3535 sqlite3_free (errMsg);
3536 sqlite3_free (sql);
3537 return 0;
3538 }
3539 sqlite3_free (sql);
3540 prefix = gaiaDoubleQuotedSql (db_prefix);
3541 sql =
3542 sqlite3_mprintf
3543 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_f_geometry_column_update\n"
3544 "BEFORE UPDATE OF 'f_geometry_column' ON 'geometry_columns'\n"
3545 "FOR EACH ROW BEGIN\n"
3546 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3547 "f_geometry_column value must not contain a single quote')\n"
3548 "WHERE NEW.f_geometry_column LIKE ('%%''%%');\n"
3549 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3550 "f_geometry_column value must not contain a double quote')\n"
3551 "WHERE NEW.f_geometry_column LIKE ('%%\"%%');\n"
3552 "SELECT RAISE(ABORT,'update on geometry_columns violates constraint: "
3553 "f_geometry_column value must be lower case')\n"
3554 "WHERE NEW.f_geometry_column <> lower(NEW.f_geometry_column);\n" "END",
3555 prefix);
3556 free (prefix);
3557 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3558 if (ret != SQLITE_OK)
3559 {
3560 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3561 sqlite3_free (errMsg);
3562 sqlite3_free (sql);
3563 return 0;
3564 }
3565 sqlite3_free (sql);
3566 prefix = gaiaDoubleQuotedSql (db_prefix);
3567 sql =
3568 sqlite3_mprintf
3569 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_geometry_type_insert\n"
3570 "BEFORE INSERT ON 'geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3571 "SELECT RAISE(ABORT,'geometry_type must be one of " "0,1,2,3,4,5,6,7,"
3572 "1000,1001,1002,1003,1004,1005,1006,1007,"
3573 "2000,2001,2002,2003,2004,2005,2006,2007,"
3574 "3000,3001,3002,3003,3004,3005,3006,3007')\n"
3575 "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,"
3576 "1000,1001,1002,1003,1004,1005,1006,1007,"
3577 "2000,2001,2002,2003,2004,2005,2006,2007,"
3578 "3000,3001,3002,3003,3004,3005,3006,3007));\n" "END", prefix);
3579 free (prefix);
3580 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3581 if (ret != SQLITE_OK)
3582 {
3583 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3584 sqlite3_free (errMsg);
3585 sqlite3_free (sql);
3586 return 0;
3587 }
3588 sqlite3_free (sql);
3589 prefix = gaiaDoubleQuotedSql (db_prefix);
3590 sql =
3591 sqlite3_mprintf
3592 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_geometry_type_update\n"
3593 "BEFORE UPDATE OF 'geometry_type' ON 'geometry_columns'\n"
3594 "FOR EACH ROW BEGIN\n"
3595 "SELECT RAISE(ABORT,'geometry_type must be one of " "0,1,2,3,4,5,6,7,"
3596 "1000,1001,1002,1003,1004,1005,1006,1007,"
3597 "2000,2001,2002,2003,2004,2005,2006,2007,"
3598 "3000,3001,3002,3003,3004,3005,3006,3007')\n"
3599 "WHERE NOT(NEW.geometry_type IN (0,1,2,3,4,5,6,7,"
3600 "1000,1001,1002,1003,1004,1005,1006,1007,"
3601 "2000,2001,2002,2003,2004,2005,2006,2007,"
3602 "3000,3001,3002,3003,3004,3005,3006,3007));\n" "END", prefix);
3603 free (prefix);
3604 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3605 if (ret != SQLITE_OK)
3606 {
3607 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3608 sqlite3_free (errMsg);
3609 sqlite3_free (sql);
3610 return 0;
3611 }
3612 sqlite3_free (sql);
3613 prefix = gaiaDoubleQuotedSql (db_prefix);
3614 sql =
3615 sqlite3_mprintf
3616 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_coord_dimension_insert\n"
3617 "BEFORE INSERT ON 'geometry_columns'\n" "FOR EACH ROW BEGIN\n"
3618 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n"
3619 "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n" "END", prefix);
3620 free (prefix);
3621 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3622 if (ret != SQLITE_OK)
3623 {
3624 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3625 sqlite3_free (errMsg);
3626 sqlite3_free (sql);
3627 return 0;
3628 }
3629 sqlite3_free (sql);
3630 prefix = gaiaDoubleQuotedSql (db_prefix);
3631 sql =
3632 sqlite3_mprintf
3633 ("CREATE TRIGGER IF NOT EXISTS \"%s\".geometry_columns_coord_dimension_update\n"
3634 "BEFORE UPDATE OF 'coord_dimension' ON 'geometry_columns'\n"
3635 "FOR EACH ROW BEGIN\n"
3636 "SELECT RAISE(ABORT,'coord_dimension must be one of 2,3,4')\n"
3637 "WHERE NOT(NEW.coord_dimension IN (2,3,4));\n" "END", prefix);
3638 free (prefix);
3639 ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
3640 if (ret != SQLITE_OK)
3641 {
3642 spatialite_e ("SQL error: %s: %s\n", sql, errMsg);
3643 sqlite3_free (errMsg);
3644 sqlite3_free (sql);
3645 return 0;
3646 }
3647 sqlite3_free (sql);
3648
3649 /* attempting to create views_geometry_columns on the same TMP-DB */
3650 if (!createTemporaryViewsGeometryColumns (sqlite, db_prefix))
3651 return 0;
3652 return 1;
3653 }
3654
3655 SPATIALITE_PRIVATE int
upgradeGeometryTriggers(void * p_sqlite)3656 upgradeGeometryTriggers (void *p_sqlite)
3657 {
3658 /* upgrading all triggers for any Spatial Column */
3659 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
3660 int ret;
3661 sqlite3_stmt *stmt = NULL;
3662 char *sql_statement;
3663 int retcode = 0;
3664 int metadata_version = checkSpatialMetaData (sqlite);
3665 if (metadata_version < 3)
3666 return 0;
3667
3668 sql_statement =
3669 sqlite3_mprintf ("SELECT f_table_name, f_geometry_column "
3670 "FROM geometry_columns");
3671 /* compiling SQL prepared statement */
3672 ret =
3673 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
3674 &stmt, NULL);
3675 sqlite3_free (sql_statement);
3676 if (ret != SQLITE_OK)
3677 {
3678 spatialite_e ("upgradeGeometryTriggers: error %d \"%s\"\n",
3679 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
3680 return 0;
3681 }
3682 while (1)
3683 {
3684 /* scrolling the result set rows */
3685 ret = sqlite3_step (stmt);
3686 if (ret == SQLITE_DONE)
3687 break; /* end of result set */
3688 if (ret == SQLITE_ROW)
3689 {
3690 const char *table =
3691 (const char *) sqlite3_column_text (stmt, 0);
3692 const char *column =
3693 (const char *) sqlite3_column_text (stmt, 1);
3694 updateGeometryTriggers (sqlite, table, column);
3695 retcode = 1;
3696 }
3697 else
3698 {
3699 retcode = 0;
3700 break;
3701 }
3702 }
3703 ret = sqlite3_finalize (stmt);
3704 return retcode;
3705 }
3706
3707 SPATIALITE_PRIVATE void
updateGeometryTriggers(void * p_sqlite,const char * table,const char * column)3708 updateGeometryTriggers (void *p_sqlite, const char *table, const char *column)
3709 {
3710 /* updates triggers for some Spatial Column */
3711 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
3712 int ret;
3713 int col_index;
3714 const char *col_dims;
3715 int index;
3716 int cached;
3717 int dims;
3718 char *txt_dims = NULL;
3719 int len;
3720 char *errMsg = NULL;
3721 char *sql_statement;
3722 char *raw;
3723 char *quoted_trigger;
3724 char *quoted_rtree;
3725 char *quoted_table;
3726 char *quoted_column;
3727 char *p_table = NULL;
3728 char *p_column = NULL;
3729 sqlite3_stmt *stmt;
3730 struct spatial_index_str *first_idx = NULL;
3731 struct spatial_index_str *last_idx = NULL;
3732 struct spatial_index_str *curr_idx;
3733 struct spatial_index_str *next_idx;
3734 int metadata_version = checkSpatialMetaData (sqlite);
3735
3736 if (!getRealSQLnames (sqlite, table, column, &p_table, &p_column))
3737 {
3738 spatialite_e
3739 ("updateTableTriggers() error: not existing Table or Column\n");
3740 return;
3741 }
3742 if (metadata_version == 3)
3743 {
3744 /* current metadata style >= v.4.0.0 */
3745 sql_statement = sqlite3_mprintf ("SELECT spatial_index_enabled "
3746 "FROM geometry_columns WHERE Lower(f_table_name) = Lower(?) "
3747 "AND Lower(f_geometry_column) = Lower(?)");
3748 }
3749 else
3750 {
3751 /* legacy metadata style <= v.3.1.0 */
3752 sql_statement =
3753 sqlite3_mprintf ("SELECT spatial_index_enabled, coord_dimension "
3754 "FROM geometry_columns WHERE Lower(f_table_name) = Lower(?) "
3755 "AND Lower(f_geometry_column) = Lower(?)");
3756 }
3757 /* compiling SQL prepared statement */
3758 ret =
3759 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
3760 &stmt, NULL);
3761 sqlite3_free (sql_statement);
3762 if (ret != SQLITE_OK)
3763 {
3764 spatialite_e ("updateTableTriggers: error %d \"%s\"\n",
3765 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
3766 return;
3767 }
3768 sqlite3_reset (stmt);
3769 sqlite3_clear_bindings (stmt);
3770 sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
3771 sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
3772 while (1)
3773 {
3774 /* scrolling the result set rows */
3775 ret = sqlite3_step (stmt);
3776 if (ret == SQLITE_DONE)
3777 break; /* end of result set */
3778 if (ret == SQLITE_ROW)
3779 {
3780 col_index = sqlite3_column_int (stmt, 0);
3781 if (metadata_version == 1)
3782 {
3783 /* legacy metadata style <= v.3.1.0 */
3784 col_dims = (const char *) sqlite3_column_text (stmt, 1);
3785 dims = GAIA_XY;
3786 if (strcasecmp (col_dims, "XYZ") == 0)
3787 dims = GAIA_XY_Z;
3788 if (strcasecmp (col_dims, "XYM") == 0)
3789 dims = GAIA_XY_M;
3790 if (strcasecmp (col_dims, "XYZM") == 0)
3791 dims = GAIA_XY_Z_M;
3792 switch (dims)
3793 {
3794 case GAIA_XY_Z:
3795 txt_dims = "XYZ";
3796 break;
3797 case GAIA_XY_M:
3798 txt_dims = "XYM";
3799 break;
3800 case GAIA_XY_Z_M:
3801 txt_dims = "XYZM";
3802 break;
3803 default:
3804 txt_dims = "XY";
3805 break;
3806 };
3807 }
3808 index = 0;
3809 cached = 0;
3810 if (col_index == 1)
3811 index = 1;
3812 if (col_index == 2)
3813 cached = 1;
3814
3815 /* trying to delete old versions [v2.0, v2.2] triggers[if any] */
3816 raw = sqlite3_mprintf ("gti_%s_%s", p_table, p_column);
3817 quoted_trigger = gaiaDoubleQuotedSql (raw);
3818 sqlite3_free (raw);
3819 sql_statement =
3820 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3821 quoted_trigger);
3822 free (quoted_trigger);
3823 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3824 sqlite3_free (sql_statement);
3825 if (ret != SQLITE_OK)
3826 goto error;
3827 raw = sqlite3_mprintf ("gtu_%s_%s", p_table, p_column);
3828 quoted_trigger = gaiaDoubleQuotedSql (raw);
3829 sqlite3_free (raw);
3830 sql_statement =
3831 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3832 quoted_trigger);
3833 free (quoted_trigger);
3834 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3835 sqlite3_free (sql_statement);
3836 if (ret != SQLITE_OK)
3837 goto error;
3838 raw = sqlite3_mprintf ("gsi_%s_%s", p_table, p_column);
3839 quoted_trigger = gaiaDoubleQuotedSql (raw);
3840 sqlite3_free (raw);
3841 sql_statement =
3842 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3843 quoted_trigger);
3844 free (quoted_trigger);
3845 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3846 sqlite3_free (sql_statement);
3847 if (ret != SQLITE_OK)
3848 goto error;
3849 raw = sqlite3_mprintf ("gsu_%s_%s", p_table, p_column);
3850 quoted_trigger = gaiaDoubleQuotedSql (raw);
3851 sqlite3_free (raw);
3852 sql_statement =
3853 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3854 quoted_trigger);
3855 free (quoted_trigger);
3856 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3857 sqlite3_free (sql_statement);
3858 if (ret != SQLITE_OK)
3859 goto error;
3860 /* end deletion old versions [v2.0, v2.2] triggers[if any] */
3861
3862 /* deleting the old INSERT trigger TYPE [if any] */
3863 raw = sqlite3_mprintf ("ggi_%s_%s", p_table, p_column);
3864 quoted_trigger = gaiaDoubleQuotedSql (raw);
3865 sqlite3_free (raw);
3866 sql_statement =
3867 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3868 quoted_trigger);
3869 free (quoted_trigger);
3870 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3871 sqlite3_free (sql_statement);
3872 if (ret != SQLITE_OK)
3873 goto error;
3874
3875 /* inserting the new INSERT trigger TYPE */
3876 raw = sqlite3_mprintf ("ggi_%s_%s", p_table, p_column);
3877 quoted_trigger = gaiaDoubleQuotedSql (raw);
3878 sqlite3_free (raw);
3879 quoted_table = gaiaDoubleQuotedSql (p_table);
3880 quoted_column = gaiaDoubleQuotedSql (p_column);
3881 if (metadata_version == 3)
3882 {
3883 /* current metadata style >= v.4.0.0 */
3884 sql_statement =
3885 sqlite3_mprintf
3886 ("CREATE TRIGGER \"%s\" BEFORE INSERT ON \"%s\"\n"
3887 "FOR EACH ROW BEGIN\n"
3888 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
3889 "WHERE (SELECT geometry_type FROM geometry_columns\n"
3890 "WHERE Lower(f_table_name) = Lower(%Q) AND "
3891 "Lower(f_geometry_column) = Lower(%Q)\n"
3892 "AND GeometryConstraints(NEW.\"%s\", geometry_type, srid) = 1) IS NULL;\nEND",
3893 quoted_trigger, quoted_table, p_table, p_column,
3894 p_table, p_column, quoted_column);
3895 free (quoted_trigger);
3896 free (quoted_table);
3897 free (quoted_column);
3898 }
3899 else
3900 {
3901 /* legacy metadata style <= v.3.1.0 */
3902 sql_statement =
3903 sqlite3_mprintf
3904 ("CREATE TRIGGER \"%s\" BEFORE INSERT ON \"%s\"\n"
3905 "FOR EACH ROW BEGIN\n"
3906 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
3907 "WHERE (SELECT type FROM geometry_columns\n"
3908 "WHERE f_table_name = %Q AND f_geometry_column = %Q\n"
3909 "AND GeometryConstraints(NEW.\"%s\", type, srid, %Q) = 1) IS NULL;\nEND",
3910 quoted_trigger, quoted_table, p_table, p_column,
3911 p_table, p_column, quoted_column, txt_dims);
3912 free (quoted_trigger);
3913 free (quoted_table);
3914 free (quoted_column);
3915 }
3916 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3917 sqlite3_free (sql_statement);
3918 if (ret != SQLITE_OK)
3919 goto error;
3920 /* deleting the old UPDATE trigger TYPE [if any] */
3921 raw = sqlite3_mprintf ("ggu_%s_%s", p_table, p_column);
3922 quoted_trigger = gaiaDoubleQuotedSql (raw);
3923 sqlite3_free (raw);
3924 sql_statement =
3925 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
3926 quoted_trigger);
3927 free (quoted_trigger);
3928 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3929 sqlite3_free (sql_statement);
3930 if (ret != SQLITE_OK)
3931 goto error;
3932
3933 /* inserting the new UPDATE trigger TYPE */
3934 raw = sqlite3_mprintf ("ggu_%s_%s", p_table, p_column);
3935 quoted_trigger = gaiaDoubleQuotedSql (raw);
3936 sqlite3_free (raw);
3937 quoted_table = gaiaDoubleQuotedSql (p_table);
3938 quoted_column = gaiaDoubleQuotedSql (p_column);
3939 if (metadata_version == 3)
3940 {
3941 /* current metadata style >= v.4.0.0 */
3942 sql_statement =
3943 sqlite3_mprintf
3944 ("CREATE TRIGGER \"%s\" BEFORE UPDATE OF \"%s\" ON \"%s\"\n"
3945 "FOR EACH ROW BEGIN\n"
3946 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
3947 "WHERE (SELECT geometry_type FROM geometry_columns\n"
3948 "WHERE Lower(f_table_name) = Lower(%Q) AND "
3949 "Lower(f_geometry_column) = Lower(%Q)\n"
3950 "AND GeometryConstraints(NEW.\"%s\", geometry_type, srid) = 1) IS NULL;\nEND",
3951 quoted_trigger, quoted_column, quoted_table, p_table,
3952 p_column, p_table, p_column, quoted_column);
3953 free (quoted_trigger);
3954 free (quoted_table);
3955 free (quoted_column);
3956 }
3957 else
3958 {
3959 /* legacy metadata style <= v.3.1.0 */
3960 sql_statement =
3961 sqlite3_mprintf
3962 ("CREATE TRIGGER \"%s\" BEFORE UPDATE ON \"%s\"\n"
3963 "FOR EACH ROW BEGIN\n"
3964 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
3965 "WHERE (SELECT type FROM geometry_columns\n"
3966 "WHERE f_table_name = %Q AND f_geometry_column = %Q\n"
3967 "AND GeometryConstraints(NEW.\"%s\", type, srid, %Q) = 1) IS NULL;\nEND",
3968 quoted_trigger, quoted_table, p_table, p_column,
3969 p_table, p_column, quoted_column, txt_dims);
3970 free (quoted_trigger);
3971 free (quoted_table);
3972 free (quoted_column);
3973 }
3974 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
3975 sqlite3_free (sql_statement);
3976 if (ret != SQLITE_OK)
3977 goto error;
3978
3979 /* inserting SpatialIndex information into the linked list */
3980 curr_idx = malloc (sizeof (struct spatial_index_str));
3981 len = strlen (p_table);
3982 curr_idx->TableName = malloc (len + 1);
3983 strcpy (curr_idx->TableName, p_table);
3984 len = strlen (p_column);
3985 curr_idx->ColumnName = malloc (len + 1);
3986 strcpy (curr_idx->ColumnName, p_column);
3987 curr_idx->ValidRtree = (char) index;
3988 curr_idx->ValidCache = (char) cached;
3989 curr_idx->Next = NULL;
3990 if (!first_idx)
3991 first_idx = curr_idx;
3992 if (last_idx)
3993 last_idx->Next = curr_idx;
3994 last_idx = curr_idx;
3995
3996 /* deleting the old INSERT trigger SPATIAL_INDEX [if any] */
3997 raw = sqlite3_mprintf ("gii_%s_%s", p_table, p_column);
3998 quoted_trigger = gaiaDoubleQuotedSql (raw);
3999 sqlite3_free (raw);
4000 sql_statement =
4001 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4002 quoted_trigger);
4003 free (quoted_trigger);
4004 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4005 sqlite3_free (sql_statement);
4006 if (ret != SQLITE_OK)
4007 goto error;
4008
4009 if (metadata_version == 3)
4010 {
4011 /* deleting the old UPDATE (timestamp) trigger [if any] */
4012 raw = sqlite3_mprintf ("tmu_%s_%s", p_table, p_column);
4013 quoted_trigger = gaiaDoubleQuotedSql (raw);
4014 sqlite3_free (raw);
4015 sql_statement =
4016 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4017 quoted_trigger);
4018 free (quoted_trigger);
4019 ret =
4020 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4021 &errMsg);
4022 sqlite3_free (sql_statement);
4023 if (ret != SQLITE_OK)
4024 goto error;
4025 /* deleting the old INSERT (timestamp) trigger [if any] */
4026 raw = sqlite3_mprintf ("tmi_%s_%s", p_table, p_column);
4027 quoted_trigger = gaiaDoubleQuotedSql (raw);
4028 sqlite3_free (raw);
4029 sql_statement =
4030 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4031 quoted_trigger);
4032 free (quoted_trigger);
4033 ret =
4034 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4035 &errMsg);
4036 sqlite3_free (sql_statement);
4037 if (ret != SQLITE_OK)
4038 goto error;
4039 /* deleting the old DELETE (timestamp) trigger [if any] */
4040 raw = sqlite3_mprintf ("tmd_%s_%s", p_table, p_column);
4041 quoted_trigger = gaiaDoubleQuotedSql (raw);
4042 sqlite3_free (raw);
4043 sql_statement =
4044 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4045 quoted_trigger);
4046 free (quoted_trigger);
4047 ret =
4048 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4049 &errMsg);
4050 sqlite3_free (sql_statement);
4051 if (ret != SQLITE_OK)
4052 goto error;
4053 }
4054
4055 if (metadata_version == 3)
4056 {
4057 /* current metadata style >= v.4.0.0 */
4058
4059 /* inserting the new UPDATE (timestamp) trigger */
4060 raw = sqlite3_mprintf ("tmu_%s_%s", p_table, p_column);
4061 quoted_trigger = gaiaDoubleQuotedSql (raw);
4062 sqlite3_free (raw);
4063 quoted_table = gaiaDoubleQuotedSql (p_table);
4064 sql_statement =
4065 sqlite3_mprintf
4066 ("CREATE TRIGGER \"%s\" AFTER UPDATE ON \"%s\"\n"
4067 "FOR EACH ROW BEGIN\n"
4068 "UPDATE geometry_columns_time SET last_update = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now')\n"
4069 "WHERE Lower(f_table_name) = Lower(%Q) AND "
4070 "Lower(f_geometry_column) = Lower(%Q);\nEND",
4071 quoted_trigger, quoted_table, p_table, p_column);
4072 free (quoted_trigger);
4073 free (quoted_table);
4074 ret =
4075 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4076 &errMsg);
4077 sqlite3_free (sql_statement);
4078 if (ret != SQLITE_OK)
4079 goto error;
4080
4081 /* inserting the new INSERT (timestamp) trigger */
4082 raw = sqlite3_mprintf ("tmi_%s_%s", p_table, p_column);
4083 quoted_trigger = gaiaDoubleQuotedSql (raw);
4084 sqlite3_free (raw);
4085 quoted_table = gaiaDoubleQuotedSql (p_table);
4086 sql_statement =
4087 sqlite3_mprintf
4088 ("CREATE TRIGGER \"%s\" AFTER INSERT ON \"%s\"\n"
4089 "FOR EACH ROW BEGIN\n"
4090 "UPDATE geometry_columns_time SET last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now')\n"
4091 "WHERE Lower(f_table_name) = Lower(%Q) AND "
4092 "Lower(f_geometry_column) = Lower(%Q);\nEND",
4093 quoted_trigger, quoted_table, p_table, p_column);
4094 free (quoted_trigger);
4095 free (quoted_table);
4096 ret =
4097 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4098 &errMsg);
4099 sqlite3_free (sql_statement);
4100 if (ret != SQLITE_OK)
4101 goto error;
4102
4103 /* inserting the new DELETE (timestamp) trigger */
4104 raw = sqlite3_mprintf ("tmd_%s_%s", p_table, p_column);
4105 quoted_trigger = gaiaDoubleQuotedSql (raw);
4106 sqlite3_free (raw);
4107 quoted_table = gaiaDoubleQuotedSql (p_table);
4108 sql_statement =
4109 sqlite3_mprintf
4110 ("CREATE TRIGGER \"%s\" AFTER DELETE ON \"%s\"\n"
4111 "FOR EACH ROW BEGIN\n"
4112 "UPDATE geometry_columns_time SET last_delete = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now')\n"
4113 "WHERE Lower(f_table_name) = Lower(%Q) AND "
4114 "Lower(f_geometry_column) = Lower(%Q);\nEND",
4115 quoted_trigger, quoted_table, p_table, p_column);
4116 free (quoted_trigger);
4117 free (quoted_table);
4118 ret =
4119 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4120 &errMsg);
4121 sqlite3_free (sql_statement);
4122 if (ret != SQLITE_OK)
4123 goto error;
4124 }
4125
4126 /* deleting the old INSERT trigger SPATIAL_INDEX [if any] */
4127 raw = sqlite3_mprintf ("gii_%s_%s", p_table, p_column);
4128 quoted_trigger = gaiaDoubleQuotedSql (raw);
4129 sqlite3_free (raw);
4130 sql_statement =
4131 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4132 quoted_trigger);
4133 free (quoted_trigger);
4134 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4135 sqlite3_free (sql_statement);
4136 if (ret != SQLITE_OK)
4137 goto error;
4138
4139 /* deleting the old UPDATE trigger SPATIAL_INDEX [if any] */
4140 raw = sqlite3_mprintf ("giu_%s_%s", p_table, p_column);
4141 quoted_trigger = gaiaDoubleQuotedSql (raw);
4142 sqlite3_free (raw);
4143 sql_statement =
4144 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4145 quoted_trigger);
4146 free (quoted_trigger);
4147 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4148 sqlite3_free (sql_statement);
4149 if (ret != SQLITE_OK)
4150 goto error;
4151
4152 /* deleting the old DELETE trigger SPATIAL_INDEX [if any] */
4153 raw = sqlite3_mprintf ("gid_%s_%s", p_table, p_column);
4154 quoted_trigger = gaiaDoubleQuotedSql (raw);
4155 sqlite3_free (raw);
4156 sql_statement =
4157 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4158 quoted_trigger);
4159 free (quoted_trigger);
4160 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4161 sqlite3_free (sql_statement);
4162 if (ret != SQLITE_OK)
4163 goto error;
4164
4165 /* deleting the old INSERT trigger MBR_CACHE [if any] */
4166 raw = sqlite3_mprintf ("gci_%s_%s", p_table, p_column);
4167 quoted_trigger = gaiaDoubleQuotedSql (raw);
4168 sqlite3_free (raw);
4169 sql_statement =
4170 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4171 quoted_trigger);
4172 free (quoted_trigger);
4173 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4174 sqlite3_free (sql_statement);
4175 if (ret != SQLITE_OK)
4176 goto error;
4177
4178 /* deleting the old UPDATE trigger MBR_CACHE [if any] */
4179 raw = sqlite3_mprintf ("gcu_%s_%s", p_table, p_column);
4180 quoted_trigger = gaiaDoubleQuotedSql (raw);
4181 sqlite3_free (raw);
4182 sql_statement =
4183 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4184 quoted_trigger);
4185 free (quoted_trigger);
4186 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4187 sqlite3_free (sql_statement);
4188 if (ret != SQLITE_OK)
4189 goto error;
4190
4191 /* deleting the old UPDATE trigger MBR_CACHE [if any] */
4192 raw = sqlite3_mprintf ("gcd_%s_%s", p_table, p_column);
4193 quoted_trigger = gaiaDoubleQuotedSql (raw);
4194 sqlite3_free (raw);
4195 sql_statement =
4196 sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"",
4197 quoted_trigger);
4198 free (quoted_trigger);
4199 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4200 sqlite3_free (sql_statement);
4201 if (ret != SQLITE_OK)
4202 goto error;
4203
4204 if (index)
4205 {
4206 /* inserting the new INSERT trigger RTree */
4207 if (metadata_version == 3)
4208 {
4209 /* current metadata style >= v.4.0.0 */
4210 raw =
4211 sqlite3_mprintf ("gii_%s_%s", p_table,
4212 p_column);
4213 quoted_trigger = gaiaDoubleQuotedSql (raw);
4214 sqlite3_free (raw);
4215 raw =
4216 sqlite3_mprintf ("idx_%s_%s", p_table,
4217 p_column);
4218 quoted_rtree = gaiaDoubleQuotedSql (raw);
4219 quoted_table = gaiaDoubleQuotedSql (p_table);
4220 quoted_column = gaiaDoubleQuotedSql (p_column);
4221 sql_statement =
4222 sqlite3_mprintf
4223 ("CREATE TRIGGER \"%s\" AFTER INSERT ON \"%s\"\n"
4224 "FOR EACH ROW BEGIN\n"
4225 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4226 "SELECT RTreeAlign(%Q, NEW.ROWID, NEW.\"%s\");\nEND",
4227 quoted_trigger, quoted_table, quoted_rtree,
4228 raw, quoted_column);
4229 sqlite3_free (raw);
4230 free (quoted_trigger);
4231 free (quoted_rtree);
4232 free (quoted_table);
4233 free (quoted_column);
4234 }
4235 else
4236 {
4237 /* legacy metadata style <= v.3.1.0 */
4238 raw =
4239 sqlite3_mprintf ("gii_%s_%s", p_table,
4240 p_column);
4241 quoted_trigger = gaiaDoubleQuotedSql (raw);
4242 sqlite3_free (raw);
4243 raw =
4244 sqlite3_mprintf ("idx_%s_%s", p_table,
4245 p_column);
4246 quoted_rtree = gaiaDoubleQuotedSql (raw);
4247 quoted_table = gaiaDoubleQuotedSql (p_table);
4248 quoted_column = gaiaDoubleQuotedSql (p_column);
4249 sql_statement =
4250 sqlite3_mprintf
4251 ("CREATE TRIGGER \"%s\" AFTER INSERT ON \"%s\"\n"
4252 "FOR EACH ROW BEGIN\n"
4253 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4254 "SELECT RTreeAlign(%Q, NEW.ROWID, NEW.\"%s\");\nEND",
4255 quoted_trigger, quoted_table, quoted_rtree,
4256 raw, quoted_column);
4257 sqlite3_free (raw);
4258 free (quoted_trigger);
4259 free (quoted_rtree);
4260 free (quoted_table);
4261 free (quoted_column);
4262 }
4263 ret =
4264 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4265 &errMsg);
4266 sqlite3_free (sql_statement);
4267 if (ret != SQLITE_OK)
4268 goto error;
4269
4270 /* inserting the new UPDATE trigger RTree */
4271 if (metadata_version == 3)
4272 {
4273 /* current metadata style >= v.4.0.0 */
4274 raw =
4275 sqlite3_mprintf ("giu_%s_%s", p_table,
4276 p_column);
4277 quoted_trigger = gaiaDoubleQuotedSql (raw);
4278 sqlite3_free (raw);
4279 raw =
4280 sqlite3_mprintf ("idx_%s_%s", p_table,
4281 p_column);
4282 quoted_rtree = gaiaDoubleQuotedSql (raw);
4283 quoted_table = gaiaDoubleQuotedSql (p_table);
4284 quoted_column = gaiaDoubleQuotedSql (p_column);
4285 sql_statement =
4286 sqlite3_mprintf
4287 ("CREATE TRIGGER \"%s\" AFTER UPDATE OF \"%s\" ON \"%s\"\n"
4288 "FOR EACH ROW BEGIN\n"
4289 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4290 "SELECT RTreeAlign(%Q, NEW.ROWID, NEW.\"%s\");\nEND",
4291 quoted_trigger, quoted_column, quoted_table,
4292 quoted_rtree, raw, quoted_column);
4293 sqlite3_free (raw);
4294 free (quoted_trigger);
4295 free (quoted_rtree);
4296 free (quoted_table);
4297 free (quoted_column);
4298 }
4299 else
4300 {
4301 /* legacy metadata style <= v.3.1.0 */
4302 raw =
4303 sqlite3_mprintf ("giu_%s_%s", p_table,
4304 p_column);
4305 quoted_trigger = gaiaDoubleQuotedSql (raw);
4306 sqlite3_free (raw);
4307 raw =
4308 sqlite3_mprintf ("idx_%s_%s", p_table,
4309 p_column);
4310 quoted_rtree = gaiaDoubleQuotedSql (raw);
4311 quoted_table = gaiaDoubleQuotedSql (p_table);
4312 quoted_column = gaiaDoubleQuotedSql (p_column);
4313 sql_statement =
4314 sqlite3_mprintf
4315 ("CREATE TRIGGER \"%s\" AFTER UPDATE ON \"%s\"\n"
4316 "FOR EACH ROW BEGIN\n"
4317 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4318 "SELECT RTreeAlign(%Q, NEW.ROWID, NEW.\"%s\");\nEND",
4319 quoted_trigger, quoted_table, quoted_rtree,
4320 raw, quoted_column);
4321 sqlite3_free (raw);
4322 free (quoted_trigger);
4323 free (quoted_rtree);
4324 free (quoted_table);
4325 free (quoted_column);
4326 }
4327 ret =
4328 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4329 &errMsg);
4330 sqlite3_free (sql_statement);
4331 if (ret != SQLITE_OK)
4332 goto error;
4333
4334 /* inserting the new DELETE trigger RTree */
4335 if (metadata_version == 3)
4336 {
4337 /* current metadata style >= v.4.0.0 */
4338 raw =
4339 sqlite3_mprintf ("gid_%s_%s", p_table,
4340 p_column);
4341 quoted_trigger = gaiaDoubleQuotedSql (raw);
4342 sqlite3_free (raw);
4343 raw =
4344 sqlite3_mprintf ("idx_%s_%s", p_table,
4345 p_column);
4346 quoted_rtree = gaiaDoubleQuotedSql (raw);
4347 sqlite3_free (raw);
4348 quoted_table = gaiaDoubleQuotedSql (p_table);
4349 quoted_column = gaiaDoubleQuotedSql (p_column);
4350 sql_statement =
4351 sqlite3_mprintf
4352 ("CREATE TRIGGER \"%s\" AFTER DELETE ON \"%s\"\n"
4353 "FOR EACH ROW BEGIN\n"
4354 "DELETE FROM \"%s\" WHERE pkid=OLD.ROWID;\nEND",
4355 quoted_trigger, quoted_table, quoted_rtree);
4356 free (quoted_trigger);
4357 free (quoted_rtree);
4358 free (quoted_table);
4359 free (quoted_column);
4360 }
4361 else
4362 {
4363 /* legacy metadata style <= v.3.1.0 */
4364 raw =
4365 sqlite3_mprintf ("gid_%s_%s", p_table,
4366 p_column);
4367 quoted_trigger = gaiaDoubleQuotedSql (raw);
4368 sqlite3_free (raw);
4369 raw =
4370 sqlite3_mprintf ("idx_%s_%s", p_table,
4371 p_column);
4372 quoted_rtree = gaiaDoubleQuotedSql (raw);
4373 sqlite3_free (raw);
4374 quoted_table = gaiaDoubleQuotedSql (p_table);
4375 quoted_column = gaiaDoubleQuotedSql (p_column);
4376 sql_statement =
4377 sqlite3_mprintf
4378 ("CREATE TRIGGER \"%s\" AFTER DELETE ON \"%s\"\n"
4379 "FOR EACH ROW BEGIN\n"
4380 "DELETE FROM \"%s\" WHERE pkid=OLD.ROWID;\nEND",
4381 quoted_trigger, quoted_table, quoted_rtree);
4382 free (quoted_trigger);
4383 free (quoted_rtree);
4384 free (quoted_table);
4385 free (quoted_column);
4386 }
4387 ret =
4388 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4389 &errMsg);
4390 sqlite3_free (sql_statement);
4391 if (ret != SQLITE_OK)
4392 goto error;
4393 }
4394
4395 if (cached)
4396 {
4397 /* inserting the new INSERT trigger MBRcache */
4398 if (metadata_version == 3)
4399 {
4400 /* current metadata style >= v.4.0.0 */
4401 raw =
4402 sqlite3_mprintf ("gci_%s_%s", p_table,
4403 p_column);
4404 quoted_trigger = gaiaDoubleQuotedSql (raw);
4405 sqlite3_free (raw);
4406 raw =
4407 sqlite3_mprintf ("cache_%s_%s", p_table,
4408 p_column);
4409 quoted_rtree = gaiaDoubleQuotedSql (raw);
4410 sqlite3_free (raw);
4411 quoted_table = gaiaDoubleQuotedSql (p_table);
4412 quoted_column = gaiaDoubleQuotedSql (p_column);
4413 sql_statement =
4414 sqlite3_mprintf
4415 ("CREATE TRIGGER \"%s\" AFTER INSERT ON \"%s\"\n"
4416 "FOR EACH ROW BEGIN\n"
4417 "INSERT INTO \"%s\" (rowid, mbr) VALUES (NEW.ROWID,\nBuildMbrFilter("
4418 "MbrMinX(NEW.\"%s\"), MbrMinY(NEW.\"%s\"), MbrMaxX(NEW.\"%s\"), MbrMaxY(NEW.\"%s\")));\nEND",
4419 quoted_trigger, quoted_table, quoted_rtree,
4420 quoted_column, quoted_column, quoted_column,
4421 quoted_column);
4422 free (quoted_trigger);
4423 free (quoted_rtree);
4424 free (quoted_table);
4425 free (quoted_column);
4426 }
4427 else
4428 {
4429 /* legacy metadata style <= v.3.1.0 */
4430 raw =
4431 sqlite3_mprintf ("gci_%s_%s", p_table,
4432 p_column);
4433 quoted_trigger = gaiaDoubleQuotedSql (raw);
4434 sqlite3_free (raw);
4435 raw =
4436 sqlite3_mprintf ("cache_%s_%s", p_table,
4437 p_column);
4438 quoted_rtree = gaiaDoubleQuotedSql (raw);
4439 sqlite3_free (raw);
4440 quoted_table = gaiaDoubleQuotedSql (p_table);
4441 quoted_column = gaiaDoubleQuotedSql (p_column);
4442 sql_statement =
4443 sqlite3_mprintf
4444 ("CREATE TRIGGER \"%s\" AFTER INSERT ON \"%s\"\n"
4445 "FOR EACH ROW BEGIN\n"
4446 "INSERT INTO \"%s\" (rowid, mbr) VALUES (NEW.ROWID,\nBuildMbrFilter("
4447 "MbrMinX(NEW.\"%s\"), MbrMinY(NEW.\"%s\"), MbrMaxX(NEW.\"%s\"), MbrMaxY(NEW.\"%s\")));\nEND",
4448 quoted_trigger, quoted_table, quoted_rtree,
4449 quoted_column, quoted_column, quoted_column,
4450 quoted_column);
4451 free (quoted_trigger);
4452 free (quoted_rtree);
4453 free (quoted_table);
4454 free (quoted_column);
4455 }
4456 ret =
4457 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4458 &errMsg);
4459 sqlite3_free (sql_statement);
4460 if (ret != SQLITE_OK)
4461 goto error;
4462
4463 /* inserting the new UPDATE trigger MBRcache */
4464 if (metadata_version == 3)
4465 {
4466 /* current metadata style >= v.4.0.0 */
4467 raw =
4468 sqlite3_mprintf ("gcu_%s_%s", p_table,
4469 p_column);
4470 quoted_trigger = gaiaDoubleQuotedSql (raw);
4471 sqlite3_free (raw);
4472 raw =
4473 sqlite3_mprintf ("cache_%s_%s", p_table,
4474 p_column);
4475 quoted_rtree = gaiaDoubleQuotedSql (raw);
4476 sqlite3_free (raw);
4477 quoted_table = gaiaDoubleQuotedSql (p_table);
4478 quoted_column = gaiaDoubleQuotedSql (p_column);
4479 sql_statement =
4480 sqlite3_mprintf
4481 ("CREATE TRIGGER \"%s\" AFTER UPDATE OF \"%s\" ON \"%s\"\n"
4482 "FOR EACH ROW BEGIN\n"
4483 "UPDATE \"%s\" SET mbr = BuildMbrFilter("
4484 "MbrMinX(NEW.\"%s\"), MbrMinY(NEW.\"%s\"), MbrMaxX(NEW.\"%s\"), MbrMaxY(NEW.\"%s\"))\n"
4485 "WHERE rowid = NEW.ROWID;\nEND",
4486 quoted_trigger, quoted_column, quoted_table,
4487 quoted_rtree, quoted_column, quoted_column,
4488 quoted_column, quoted_column);
4489 free (quoted_trigger);
4490 free (quoted_rtree);
4491 free (quoted_table);
4492 free (quoted_column);
4493 }
4494 else
4495 {
4496 /* legacy metadata style <= v.3.1.0 */
4497 raw =
4498 sqlite3_mprintf ("gcu_%s_%s", p_table,
4499 p_column);
4500 quoted_trigger = gaiaDoubleQuotedSql (raw);
4501 sqlite3_free (raw);
4502 raw =
4503 sqlite3_mprintf ("cache_%s_%s", p_table,
4504 p_column);
4505 quoted_rtree = gaiaDoubleQuotedSql (raw);
4506 sqlite3_free (raw);
4507 quoted_table = gaiaDoubleQuotedSql (p_table);
4508 quoted_column = gaiaDoubleQuotedSql (p_column);
4509 sql_statement =
4510 sqlite3_mprintf
4511 ("CREATE TRIGGER \"%s\" AFTER UPDATE ON \"%s\"\n"
4512 "FOR EACH ROW BEGIN\n"
4513 "UPDATE \"%s\" SET mbr = BuildMbrFilter("
4514 "MbrMinX(NEW.\"%s\"), MbrMinY(NEW.\"%s\"), MbrMaxX(NEW.\"%s\"), MbrMaxY(NEW.\"%s\"))\n"
4515 "WHERE rowid = NEW.ROWID;\nEND",
4516 quoted_trigger, quoted_table, quoted_rtree,
4517 quoted_column, quoted_column, quoted_column,
4518 quoted_column);
4519 free (quoted_trigger);
4520 free (quoted_rtree);
4521 free (quoted_table);
4522 free (quoted_column);
4523 }
4524 ret =
4525 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4526 &errMsg);
4527 sqlite3_free (sql_statement);
4528 if (ret != SQLITE_OK)
4529 goto error;
4530
4531 /* inserting the new DELETE trigger MBRcache */
4532 if (metadata_version == 3)
4533 {
4534 /* current metadata style >= v.4.0.0 */
4535 raw =
4536 sqlite3_mprintf ("gcd_%s_%s", p_table,
4537 p_column);
4538 quoted_trigger = gaiaDoubleQuotedSql (raw);
4539 sqlite3_free (raw);
4540 raw =
4541 sqlite3_mprintf ("cache_%s_%s", p_table,
4542 p_column);
4543 quoted_rtree = gaiaDoubleQuotedSql (raw);
4544 sqlite3_free (raw);
4545 quoted_table = gaiaDoubleQuotedSql (p_table);
4546 sql_statement =
4547 sqlite3_mprintf
4548 ("CREATE TRIGGER \"%s\" AFTER DELETE ON \"%s\"\n"
4549 "FOR EACH ROW BEGIN\n"
4550 "DELETE FROM \"%s\" WHERE rowid = OLD.ROWID;\nEND",
4551 quoted_trigger, quoted_table, quoted_rtree);
4552 free (quoted_trigger);
4553 free (quoted_rtree);
4554 free (quoted_table);
4555 }
4556 else
4557 {
4558 /* legacy metadata style <= v.3.1.0 */
4559 raw =
4560 sqlite3_mprintf ("gcd_%s_%s", p_table,
4561 p_column);
4562 quoted_trigger = gaiaDoubleQuotedSql (raw);
4563 sqlite3_free (raw);
4564 raw =
4565 sqlite3_mprintf ("cache_%s_%s", p_table,
4566 p_column);
4567 quoted_rtree = gaiaDoubleQuotedSql (raw);
4568 sqlite3_free (raw);
4569 quoted_table = gaiaDoubleQuotedSql (p_table);
4570 quoted_column = gaiaDoubleQuotedSql (p_column);
4571 sql_statement =
4572 sqlite3_mprintf
4573 ("CREATE TRIGGER \"%s\" AFTER DELETE ON \"%s\"\n"
4574 "FOR EACH ROW BEGIN\n"
4575 "DELETE FROM \"%s\" WHERE rowid = OLD.ROWID;\nEND",
4576 quoted_trigger, quoted_table, quoted_rtree);
4577 free (quoted_trigger);
4578 free (quoted_rtree);
4579 free (quoted_table);
4580 }
4581 ret =
4582 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4583 &errMsg);
4584 sqlite3_free (sql_statement);
4585 if (ret != SQLITE_OK)
4586 goto error;
4587 }
4588
4589 }
4590 }
4591 ret = sqlite3_finalize (stmt);
4592 /* now we'll adjust any related SpatialIndex as required */
4593 curr_idx = first_idx;
4594 while (curr_idx)
4595 {
4596 if (curr_idx->ValidRtree)
4597 {
4598 /* building RTree SpatialIndex */
4599 int status;
4600 raw = sqlite3_mprintf ("idx_%s_%s", curr_idx->TableName,
4601 curr_idx->ColumnName);
4602 quoted_rtree = gaiaDoubleQuotedSql (raw);
4603 sqlite3_free (raw);
4604 sql_statement = sqlite3_mprintf ("CREATE VIRTUAL TABLE \"%s\" "
4605 "USING rtree(pkid, xmin, xmax, ymin, ymax)",
4606 quoted_rtree);
4607 free (quoted_rtree);
4608 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4609 sqlite3_free (sql_statement);
4610 if (ret != SQLITE_OK)
4611 goto error;
4612 status = buildSpatialIndexEx (sqlite,
4613 (unsigned char
4614 *) (curr_idx->TableName),
4615 curr_idx->ColumnName);
4616 if (status == 0)
4617 ;
4618 else
4619 {
4620 if (status == -2)
4621 errMsg =
4622 sqlite3_mprintf
4623 ("SpatialIndex error: a physical column named ROWID shadows the real ROWID");
4624 else
4625 errMsg =
4626 sqlite3_mprintf
4627 ("SpatialIndex error: unable to rebuild the T*Tree");
4628 goto error;
4629 }
4630 }
4631 if (curr_idx->ValidCache)
4632 {
4633 /* building MbrCache SpatialIndex */
4634 raw = sqlite3_mprintf ("cache_%s_%s", curr_idx->TableName,
4635 curr_idx->ColumnName);
4636 quoted_rtree = gaiaDoubleQuotedSql (raw);
4637 sqlite3_free (raw);
4638 quoted_table = gaiaDoubleQuotedSql (curr_idx->TableName);
4639 quoted_column = gaiaDoubleQuotedSql (curr_idx->ColumnName);
4640 sql_statement = sqlite3_mprintf ("CREATE VIRTUAL TABLE \"%s\" "
4641 "USING MbrCache(\"%s\", \"%s\")",
4642 quoted_rtree, quoted_table,
4643 quoted_column);
4644 free (quoted_rtree);
4645 free (quoted_table);
4646 free (quoted_column);
4647 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4648 sqlite3_free (sql_statement);
4649 if (ret != SQLITE_OK)
4650 goto error;
4651 }
4652 curr_idx = curr_idx->Next;
4653 }
4654 goto index_cleanup;
4655 error:
4656 spatialite_e ("updateTableTriggers: \"%s\"\n", errMsg);
4657 sqlite3_free (errMsg);
4658 index_cleanup:
4659 curr_idx = first_idx;
4660 while (curr_idx)
4661 {
4662 next_idx = curr_idx->Next;
4663 if (curr_idx->TableName)
4664 free (curr_idx->TableName);
4665 if (curr_idx->ColumnName)
4666 free (curr_idx->ColumnName);
4667 free (curr_idx);
4668 curr_idx = next_idx;
4669 }
4670 if (p_table)
4671 free (p_table);
4672 if (p_column)
4673 free (p_column);
4674 }
4675
4676 SPATIALITE_PRIVATE void
updateTemporaryGeometryTriggers(void * p_sqlite,const char * db_prefix,const char * table,const char * column)4677 updateTemporaryGeometryTriggers (void *p_sqlite, const char *db_prefix,
4678 const char *table, const char *column)
4679 {
4680 /* updates triggers for some Spatial Column - only on Attached DB based on :memory: */
4681 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
4682 int ret;
4683 int col_index;
4684 int index;
4685 int len;
4686 char *errMsg = NULL;
4687 char *sql_statement;
4688 char *raw;
4689 char *quoted_trigger;
4690 char *quoted_rtree;
4691 char *quoted_prefix;
4692 char *quoted_table;
4693 char *quoted_column;
4694 char *p_table = NULL;
4695 char *p_column = NULL;
4696 sqlite3_stmt *stmt;
4697 struct spatial_index_str *first_idx = NULL;
4698 struct spatial_index_str *last_idx = NULL;
4699 struct spatial_index_str *curr_idx;
4700 struct spatial_index_str *next_idx;
4701
4702 if (!getRealSQLnamesTemporary
4703 (sqlite, db_prefix, table, column, &p_table, &p_column))
4704 {
4705 spatialite_e
4706 ("updateTemporaryTableTriggers() error: not existing Table or Column\n");
4707 return;
4708 }
4709 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4710 sql_statement = sqlite3_mprintf ("SELECT spatial_index_enabled "
4711 "FROM \"%s\".geometry_columns WHERE Lower(f_table_name) = Lower(?) "
4712 "AND Lower(f_geometry_column) = Lower(?)",
4713 quoted_prefix);
4714 free (quoted_prefix);
4715 /* compiling SQL prepared statement */
4716 ret =
4717 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
4718 &stmt, NULL);
4719 sqlite3_free (sql_statement);
4720 if (ret != SQLITE_OK)
4721 {
4722 spatialite_e ("updateTemporaryTableTriggers: error %d \"%s\"\n",
4723 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
4724 return;
4725 }
4726 sqlite3_reset (stmt);
4727 sqlite3_clear_bindings (stmt);
4728 sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4729 sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4730 while (1)
4731 {
4732 /* scrolling the result set rows */
4733 ret = sqlite3_step (stmt);
4734 if (ret == SQLITE_DONE)
4735 break; /* end of result set */
4736 if (ret == SQLITE_ROW)
4737 {
4738 col_index = sqlite3_column_int (stmt, 0);
4739 index = 0;
4740 if (col_index == 1)
4741 index = 1;
4742
4743 /* deleting the old INSERT trigger TYPE [if any] */
4744 raw = sqlite3_mprintf ("ggi_%s_%s", p_table, p_column);
4745 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4746 quoted_trigger = gaiaDoubleQuotedSql (raw);
4747 sqlite3_free (raw);
4748 sql_statement =
4749 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4750 quoted_prefix, quoted_trigger);
4751 free (quoted_prefix);
4752 free (quoted_trigger);
4753 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4754 sqlite3_free (sql_statement);
4755 if (ret != SQLITE_OK)
4756 goto error;
4757
4758 /* inserting the INSERT trigger TYPE */
4759 raw = sqlite3_mprintf ("ggi_%s_%s", p_table, p_column);
4760 quoted_trigger = gaiaDoubleQuotedSql (raw);
4761 sqlite3_free (raw);
4762 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4763 quoted_table = gaiaDoubleQuotedSql (p_table);
4764 quoted_column = gaiaDoubleQuotedSql (p_column);
4765 sql_statement =
4766 sqlite3_mprintf
4767 ("CREATE TRIGGER \"%s\".\"%s\" BEFORE INSERT ON \"%s\"\n"
4768 "FOR EACH ROW BEGIN\n"
4769 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
4770 "WHERE (SELECT geometry_type FROM \"%s\".geometry_columns\n"
4771 "WHERE Lower(f_table_name) = Lower(%Q) AND "
4772 "Lower(f_geometry_column) = Lower(%Q)\n"
4773 "AND GeometryConstraints(NEW.\"%s\", geometry_type, srid) = 1) IS NULL;\nEND",
4774 quoted_prefix, quoted_trigger, quoted_table, p_table,
4775 p_column, db_prefix, p_table, p_column, quoted_column);
4776 free (quoted_prefix);
4777 free (quoted_trigger);
4778 free (quoted_table);
4779 free (quoted_column);
4780 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4781 sqlite3_free (sql_statement);
4782 if (ret != SQLITE_OK)
4783 goto error;
4784
4785 /* deleting the old UPDATE trigger TYPE [if any] */
4786 raw = sqlite3_mprintf ("ggu_%s_%s", p_table, p_column);
4787 quoted_trigger = gaiaDoubleQuotedSql (raw);
4788 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4789 sqlite3_free (raw);
4790 sql_statement =
4791 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4792 quoted_prefix, quoted_trigger);
4793 free (quoted_prefix);
4794 free (quoted_trigger);
4795 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4796 sqlite3_free (sql_statement);
4797 if (ret != SQLITE_OK)
4798 goto error;
4799
4800 /* inserting the new UPDATE trigger TYPE */
4801 raw = sqlite3_mprintf ("ggu_%s_%s", p_table, p_column);
4802 quoted_trigger = gaiaDoubleQuotedSql (raw);
4803 sqlite3_free (raw);
4804 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4805 quoted_table = gaiaDoubleQuotedSql (p_table);
4806 quoted_column = gaiaDoubleQuotedSql (p_column);
4807 sql_statement =
4808 sqlite3_mprintf
4809 ("CREATE TRIGGER \"%s\".\"%s\" BEFORE UPDATE OF \"%s\" ON \"%s\"\n"
4810 "FOR EACH ROW BEGIN\n"
4811 "SELECT RAISE(ROLLBACK, '%q.%q violates Geometry constraint [geom-type or SRID not allowed]')\n"
4812 "WHERE (SELECT geometry_type FROM \"%s\".geometry_columns\n"
4813 "WHERE Lower(f_table_name) = Lower(%Q) AND "
4814 "Lower(f_geometry_column) = Lower(%Q)\n"
4815 "AND GeometryConstraints(NEW.\"%s\", geometry_type, srid) = 1) IS NULL;\nEND",
4816 quoted_prefix, quoted_trigger, quoted_column, quoted_table,
4817 p_table, p_column, db_prefix, p_table, p_column,
4818 quoted_column);
4819 free (quoted_prefix);
4820 free (quoted_trigger);
4821 free (quoted_table);
4822 free (quoted_column);
4823 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4824 sqlite3_free (sql_statement);
4825 if (ret != SQLITE_OK)
4826 goto error;
4827
4828 /* inserting SpatialIndex information into the linked list */
4829 curr_idx = malloc (sizeof (struct spatial_index_str));
4830 len = strlen (p_table);
4831 curr_idx->TableName = malloc (len + 1);
4832 strcpy (curr_idx->TableName, p_table);
4833 len = strlen (p_column);
4834 curr_idx->ColumnName = malloc (len + 1);
4835 strcpy (curr_idx->ColumnName, p_column);
4836 curr_idx->ValidRtree = (char) index;
4837 curr_idx->ValidCache = '\0';
4838 curr_idx->Next = NULL;
4839 if (!first_idx)
4840 first_idx = curr_idx;
4841 if (last_idx)
4842 last_idx->Next = curr_idx;
4843 last_idx = curr_idx;
4844
4845 /* deleting the old INSERT trigger SPATIAL_INDEX [if any] */
4846 raw = sqlite3_mprintf ("gii_%s_%s", p_table, p_column);
4847 quoted_trigger = gaiaDoubleQuotedSql (raw);
4848 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4849 sqlite3_free (raw);
4850 sql_statement =
4851 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4852 quoted_prefix, quoted_trigger);
4853 free (quoted_prefix);
4854 free (quoted_trigger);
4855 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4856 sqlite3_free (sql_statement);
4857 if (ret != SQLITE_OK)
4858 goto error;
4859
4860
4861 /* deleting the old UPDATE trigger SPATIAL_INDEX [if any] */
4862 raw = sqlite3_mprintf ("giu_%s_%s", p_table, p_column);
4863 quoted_trigger = gaiaDoubleQuotedSql (raw);
4864 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4865 sqlite3_free (raw);
4866 sql_statement =
4867 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4868 quoted_prefix, quoted_trigger);
4869 free (quoted_prefix);
4870 free (quoted_trigger);
4871 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4872 sqlite3_free (sql_statement);
4873 if (ret != SQLITE_OK)
4874 goto error;
4875
4876 /* deleting the old DELETE trigger SPATIAL_INDEX [if any] */
4877 raw = sqlite3_mprintf ("gid_%s_%s", p_table, p_column);
4878 quoted_trigger = gaiaDoubleQuotedSql (raw);
4879 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4880 sqlite3_free (raw);
4881 sql_statement =
4882 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4883 quoted_prefix, quoted_trigger);
4884 free (quoted_prefix);
4885 free (quoted_trigger);
4886 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4887 sqlite3_free (sql_statement);
4888 if (ret != SQLITE_OK)
4889 goto error;
4890
4891 /* deleting the old INSERT trigger MBR_CACHE [if any] */
4892 raw = sqlite3_mprintf ("gci_%s_%s", p_table, p_column);
4893 quoted_trigger = gaiaDoubleQuotedSql (raw);
4894 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4895 sqlite3_free (raw);
4896 sql_statement =
4897 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4898 quoted_prefix, quoted_trigger);
4899 free (quoted_prefix);
4900 free (quoted_trigger);
4901 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4902 sqlite3_free (sql_statement);
4903 if (ret != SQLITE_OK)
4904 goto error;
4905
4906 /* deleting the old UPDATE trigger MBR_CACHE [if any] */
4907 raw = sqlite3_mprintf ("gcu_%s_%s", p_table, p_column);
4908 quoted_trigger = gaiaDoubleQuotedSql (raw);
4909 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4910 sqlite3_free (raw);
4911 sql_statement =
4912 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4913 quoted_prefix, quoted_trigger);
4914 free (quoted_prefix);
4915 free (quoted_trigger);
4916 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4917 sqlite3_free (sql_statement);
4918 if (ret != SQLITE_OK)
4919 goto error;
4920
4921 /* deleting the old UPDATE trigger MBR_CACHE [if any] */
4922 raw = sqlite3_mprintf ("gcd_%s_%s", p_table, p_column);
4923 quoted_trigger = gaiaDoubleQuotedSql (raw);
4924 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4925 sqlite3_free (raw);
4926 sql_statement =
4927 sqlite3_mprintf ("DROP TRIGGER IF EXISTS \"%s\".\"%s\"",
4928 quoted_prefix, quoted_trigger);
4929 free (quoted_prefix);
4930 free (quoted_trigger);
4931 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
4932 sqlite3_free (sql_statement);
4933 if (ret != SQLITE_OK)
4934 goto error;
4935
4936 if (index)
4937 {
4938 /* inserting the new INSERT trigger RTree */
4939 raw = sqlite3_mprintf ("gii_%s_%s", p_table, p_column);
4940 quoted_trigger = gaiaDoubleQuotedSql (raw);
4941 sqlite3_free (raw);
4942 raw = sqlite3_mprintf ("idx_%s_%s", p_table, p_column);
4943 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4944 quoted_rtree = gaiaDoubleQuotedSql (raw);
4945 quoted_table = gaiaDoubleQuotedSql (p_table);
4946 quoted_column = gaiaDoubleQuotedSql (p_column);
4947 sql_statement =
4948 sqlite3_mprintf
4949 ("CREATE TRIGGER \"%s\".\"%s\" AFTER INSERT ON \"%s\"\n"
4950 "FOR EACH ROW BEGIN\n"
4951 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4952 "SELECT TemporaryRTreeAlign(%Q, %Q, NEW.ROWID, NEW.\"%s\");\nEND",
4953 quoted_prefix, quoted_trigger, quoted_table,
4954 quoted_rtree, db_prefix, raw, quoted_column);
4955 sqlite3_free (raw);
4956 free (quoted_prefix);
4957 free (quoted_trigger);
4958 free (quoted_rtree);
4959 free (quoted_table);
4960 free (quoted_column);
4961 ret =
4962 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4963 &errMsg);
4964 sqlite3_free (sql_statement);
4965 if (ret != SQLITE_OK)
4966 goto error;
4967
4968 /* inserting the new UPDATE trigger RTree */
4969 raw = sqlite3_mprintf ("giu_%s_%s", p_table, p_column);
4970 quoted_trigger = gaiaDoubleQuotedSql (raw);
4971 sqlite3_free (raw);
4972 raw = sqlite3_mprintf ("idx_%s_%s", p_table, p_column);
4973 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
4974 quoted_rtree = gaiaDoubleQuotedSql (raw);
4975 quoted_table = gaiaDoubleQuotedSql (p_table);
4976 quoted_column = gaiaDoubleQuotedSql (p_column);
4977 sql_statement =
4978 sqlite3_mprintf
4979 ("CREATE TRIGGER \"%s\".\"%s\" AFTER UPDATE OF \"%s\" ON \"%s\"\n"
4980 "FOR EACH ROW BEGIN\n"
4981 "DELETE FROM \"%s\" WHERE pkid=NEW.ROWID;\n"
4982 "SELECT TemporaryRTreeAlign(%Q, %Q, NEW.ROWID, NEW.\"%s\");\nEND",
4983 quoted_prefix, quoted_trigger, quoted_column,
4984 quoted_table, quoted_rtree, db_prefix, raw,
4985 quoted_column);
4986 sqlite3_free (raw);
4987 free (quoted_prefix);
4988 free (quoted_trigger);
4989 free (quoted_rtree);
4990 free (quoted_table);
4991 free (quoted_column);
4992 ret =
4993 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
4994 &errMsg);
4995 sqlite3_free (sql_statement);
4996 if (ret != SQLITE_OK)
4997 goto error;
4998
4999 /* inserting the new DELETE trigger RTree */
5000 raw = sqlite3_mprintf ("gid_%s_%s", p_table, p_column);
5001 quoted_trigger = gaiaDoubleQuotedSql (raw);
5002 sqlite3_free (raw);
5003 raw = sqlite3_mprintf ("idx_%s_%s", p_table, p_column);
5004 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5005 quoted_rtree = gaiaDoubleQuotedSql (raw);
5006 sqlite3_free (raw);
5007 quoted_table = gaiaDoubleQuotedSql (p_table);
5008 quoted_column = gaiaDoubleQuotedSql (p_column);
5009 sql_statement =
5010 sqlite3_mprintf
5011 ("CREATE TRIGGER \"%s\".\"%s\" AFTER DELETE ON \"%s\"\n"
5012 "FOR EACH ROW BEGIN\n"
5013 "DELETE FROM \"%s\" WHERE pkid=OLD.ROWID;\nEND",
5014 quoted_prefix, quoted_trigger, quoted_table,
5015 quoted_rtree);
5016 free (quoted_prefix);
5017 free (quoted_trigger);
5018 free (quoted_rtree);
5019 free (quoted_table);
5020 free (quoted_column);
5021 ret =
5022 sqlite3_exec (sqlite, sql_statement, NULL, NULL,
5023 &errMsg);
5024 sqlite3_free (sql_statement);
5025 if (ret != SQLITE_OK)
5026 goto error;
5027 }
5028 }
5029 }
5030 ret = sqlite3_finalize (stmt);
5031 /* now we'll adjust any related SpatialIndex as required */
5032 curr_idx = first_idx;
5033 while (curr_idx)
5034 {
5035 if (curr_idx->ValidRtree)
5036 {
5037 /* building RTree SpatialIndex */
5038 int status;
5039 raw = sqlite3_mprintf ("idx_%s_%s", curr_idx->TableName,
5040 curr_idx->ColumnName);
5041 quoted_rtree = gaiaDoubleQuotedSql (raw);
5042 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5043 sqlite3_free (raw);
5044 sql_statement =
5045 sqlite3_mprintf ("CREATE VIRTUAL TABLE \"%s\".\"%s\" "
5046 "USING rtree(pkid, xmin, xmax, ymin, ymax)",
5047 quoted_prefix, quoted_rtree);
5048 free (quoted_prefix);
5049 free (quoted_rtree);
5050 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
5051 sqlite3_free (sql_statement);
5052 if (ret != SQLITE_OK)
5053 goto error;
5054 status = buildTemporarySpatialIndex (sqlite, db_prefix,
5055 (unsigned char
5056 *) (curr_idx->TableName),
5057 curr_idx->ColumnName);
5058 if (status == 0)
5059 ;
5060 else
5061 {
5062 if (status == -2)
5063 errMsg =
5064 sqlite3_mprintf
5065 ("TemporarySpatialIndex error: a physical column named ROWID shadows the real ROWID");
5066 else
5067 errMsg =
5068 sqlite3_mprintf
5069 ("TemporarySpatialIndex error: unable to rebuild the T*Tree");
5070 goto error;
5071 }
5072 }
5073 if (curr_idx->ValidCache)
5074 {
5075 /* building MbrCache SpatialIndex */
5076 raw = sqlite3_mprintf ("cache_%s_%s", curr_idx->TableName,
5077 curr_idx->ColumnName);
5078 quoted_rtree = gaiaDoubleQuotedSql (raw);
5079 sqlite3_free (raw);
5080 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5081 quoted_table = gaiaDoubleQuotedSql (curr_idx->TableName);
5082 quoted_column = gaiaDoubleQuotedSql (curr_idx->ColumnName);
5083 sql_statement =
5084 sqlite3_mprintf ("CREATE VIRTUAL TABLE \"%s\".\"%s\" "
5085 "USING MbrCache(\"%s\", \"%s\")",
5086 quoted_prefix, quoted_rtree, quoted_table,
5087 quoted_column);
5088 free (quoted_prefix);
5089 free (quoted_rtree);
5090 free (quoted_table);
5091 free (quoted_column);
5092 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
5093 sqlite3_free (sql_statement);
5094 if (ret != SQLITE_OK)
5095 goto error;
5096 }
5097 curr_idx = curr_idx->Next;
5098 }
5099 goto index_cleanup;
5100 error:
5101 spatialite_e ("updateTemporaryTableTriggers: \"%s\"\n", errMsg);
5102 sqlite3_free (errMsg);
5103 index_cleanup:
5104 curr_idx = first_idx;
5105 while (curr_idx)
5106 {
5107 next_idx = curr_idx->Next;
5108 if (curr_idx->TableName)
5109 free (curr_idx->TableName);
5110 if (curr_idx->ColumnName)
5111 free (curr_idx->ColumnName);
5112 free (curr_idx);
5113 curr_idx = next_idx;
5114 }
5115 if (p_table)
5116 free (p_table);
5117 if (p_column)
5118 free (p_column);
5119 }
5120
5121 SPATIALITE_PRIVATE void
buildSpatialIndex(void * p_sqlite,const unsigned char * table,const char * column)5122 buildSpatialIndex (void *p_sqlite, const unsigned char *table,
5123 const char *column)
5124 {
5125 /* DEPRECATED - always use buildSpatialIndexEx as a safer replacement */
5126 buildSpatialIndexEx (p_sqlite, table, column);
5127 }
5128
5129 SPATIALITE_PRIVATE int
validateRowid(void * p_sqlite,const char * table)5130 validateRowid (void *p_sqlite, const char *table)
5131 {
5132 /* check for tables containing a physical column named ROWID */
5133 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5134 int rowid = 0;
5135 char *sql;
5136 int ret;
5137 const char *name;
5138 const char *type;
5139 const char *pk;
5140 int rowid_pk = 0;
5141 int int_pk = 0;
5142 int pk_cols = 0;
5143 int i;
5144 char **results;
5145 int rows;
5146 int columns;
5147 char *quoted_table = gaiaDoubleQuotedSql (table);
5148 sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", quoted_table);
5149 ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
5150 sqlite3_free (sql);
5151 free (quoted_table);
5152 if (ret != SQLITE_OK)
5153 return 0;
5154 if (rows < 1)
5155 ;
5156 else
5157 {
5158 for (i = 1; i <= rows; i++)
5159 {
5160 name = results[(i * columns) + 1];
5161 if (strcasecmp (name, "rowid") == 0)
5162 rowid = 1;
5163 type = results[(i * columns) + 2];
5164 if (strcasecmp (type, "INTEGER") == 0)
5165 int_pk = 1;
5166 pk = results[(i * columns) + 5];
5167 if (atoi (pk) != 0)
5168 pk_cols++;
5169 if (strcasecmp (name, "rowid") == 0 && atoi (pk) != 0)
5170 rowid_pk = 1;
5171 }
5172 }
5173 sqlite3_free_table (results);
5174 if (rowid == 0)
5175 return 1;
5176 if (rowid_pk == 1 && pk_cols == 1 && int_pk == 1)
5177 {
5178 /* OK, found: ROWID INTEGER PRIMARY KEY */
5179 return 1;
5180 }
5181 return 0;
5182 }
5183
5184 SPATIALITE_PRIVATE int
validateTemporaryRowid(void * p_sqlite,const char * db_prefix,const char * table)5185 validateTemporaryRowid (void *p_sqlite, const char *db_prefix,
5186 const char *table)
5187 {
5188 /* check for tables containing a physical column named ROWID */
5189 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5190 int rowid = 0;
5191 char *sql;
5192 int ret;
5193 const char *name;
5194 const char *type;
5195 const char *pk;
5196 int rowid_pk = 0;
5197 int int_pk = 0;
5198 int pk_cols = 0;
5199 int i;
5200 char **results;
5201 int rows;
5202 int columns;
5203 char *quoted_prefix;
5204 char *quoted_table;
5205
5206 if (db_prefix == NULL)
5207 return 0;
5208
5209 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5210 quoted_table = gaiaDoubleQuotedSql (table);
5211 sql =
5212 sqlite3_mprintf ("PRAGMA \"%s\".table_info(\"%s\")", quoted_prefix,
5213 quoted_table);
5214 ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
5215 sqlite3_free (sql);
5216 free (quoted_prefix);
5217 free (quoted_table);
5218 if (ret != SQLITE_OK)
5219 return 0;
5220 if (rows < 1)
5221 ;
5222 else
5223 {
5224 for (i = 1; i <= rows; i++)
5225 {
5226 name = results[(i * columns) + 1];
5227 if (strcasecmp (name, "rowid") == 0)
5228 rowid = 1;
5229 type = results[(i * columns) + 2];
5230 if (strcasecmp (type, "INTEGER") == 0)
5231 int_pk = 1;
5232 pk = results[(i * columns) + 5];
5233 if (atoi (pk) != 0)
5234 pk_cols++;
5235 if (strcasecmp (name, "rowid") == 0 && atoi (pk) != 0)
5236 rowid_pk = 1;
5237 }
5238 }
5239 sqlite3_free_table (results);
5240 if (rowid == 0)
5241 return 1;
5242 if (rowid_pk == 1 && pk_cols == 1 && int_pk == 1)
5243 {
5244 /* OK, found: ROWID INTEGER PRIMARY KEY */
5245 return 1;
5246 }
5247 return 0;
5248 }
5249
5250 SPATIALITE_PRIVATE int
buildSpatialIndexEx(void * p_sqlite,const unsigned char * table,const char * column)5251 buildSpatialIndexEx (void *p_sqlite, const unsigned char *table,
5252 const char *column)
5253 {
5254 /* loading a SpatialIndex [RTree] */
5255 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5256 char *raw;
5257 char *quoted_rtree;
5258 char *quoted_table;
5259 char *quoted_column;
5260 char *sql_statement;
5261 char *errMsg = NULL;
5262 int ret;
5263
5264 if (!validateRowid (sqlite, (const char *) table))
5265 {
5266 /* a physical column named "rowid" shadows the real ROWID */
5267 spatialite_e
5268 ("buildSpatialIndex error: a physical column named ROWID shadows the real ROWID\n");
5269 return -2;
5270 }
5271
5272 raw = sqlite3_mprintf ("idx_%s_%s", table, column);
5273 quoted_rtree = gaiaDoubleQuotedSql (raw);
5274 sqlite3_free (raw);
5275 quoted_table = gaiaDoubleQuotedSql ((const char *) table);
5276 quoted_column = gaiaDoubleQuotedSql (column);
5277 sql_statement = sqlite3_mprintf ("INSERT INTO \"%s\" "
5278 "(pkid, xmin, xmax, ymin, ymax) "
5279 "SELECT ROWID, MbrMinX(\"%s\"), MbrMaxX(\"%s\"), MbrMinY(\"%s\"), MbrMaxY(\"%s\") "
5280 "FROM \"%s\" WHERE MbrMinX(\"%s\") IS NOT NULL",
5281 quoted_rtree, quoted_column, quoted_column,
5282 quoted_column, quoted_column, quoted_table,
5283 quoted_column);
5284 free (quoted_rtree);
5285 free (quoted_table);
5286 free (quoted_column);
5287 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
5288 sqlite3_free (sql_statement);
5289 if (ret != SQLITE_OK)
5290 {
5291 spatialite_e ("buildSpatialIndex error: \"%s\"\n", errMsg);
5292 sqlite3_free (errMsg);
5293 return -1;
5294 }
5295 return 0;
5296 }
5297
5298 SPATIALITE_PRIVATE int
buildTemporarySpatialIndex(void * p_sqlite,const char * db_prefix,const unsigned char * table,const char * column)5299 buildTemporarySpatialIndex (void *p_sqlite, const char *db_prefix,
5300 const unsigned char *table, const char *column)
5301 {
5302 /* loading a SpatialIndex [RTree] */
5303 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5304 char *raw;
5305 char *quoted_prefix;
5306 char *quoted_rtree;
5307 char *quoted_table;
5308 char *quoted_column;
5309 char *sql_statement;
5310 char *errMsg = NULL;
5311 int ret;
5312
5313 if (!validateTemporaryRowid (sqlite, db_prefix, (const char *) table))
5314 {
5315 /* a physical column named "rowid" shadows the real ROWID */
5316 spatialite_e
5317 ("buildTemporarySpatialIndex error: a physical column named ROWID shadows the real ROWID\n");
5318 return -2;
5319 }
5320
5321 raw = sqlite3_mprintf ("idx_%s_%s", table, column);
5322 quoted_rtree = gaiaDoubleQuotedSql (raw);
5323 sqlite3_free (raw);
5324 quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5325 quoted_table = gaiaDoubleQuotedSql ((const char *) table);
5326 quoted_column = gaiaDoubleQuotedSql (column);
5327 sql_statement = sqlite3_mprintf ("INSERT INTO \"%s\".\"%s\" "
5328 "(pkid, xmin, xmax, ymin, ymax) "
5329 "SELECT ROWID, MbrMinX(\"%s\"), MbrMaxX(\"%s\"), MbrMinY(\"%s\"), MbrMaxY(\"%s\") "
5330 "FROM \"%s\".\"%s\" WHERE MbrMinX(\"%s\") IS NOT NULL",
5331 quoted_prefix, quoted_rtree, quoted_column,
5332 quoted_column, quoted_column,
5333 quoted_column, quoted_prefix, quoted_table,
5334 quoted_column);
5335 free (quoted_prefix);
5336 free (quoted_rtree);
5337 free (quoted_table);
5338 free (quoted_column);
5339 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
5340 sqlite3_free (sql_statement);
5341 if (ret != SQLITE_OK)
5342 {
5343 spatialite_e ("buildTemporarySpatialIndex error: \"%s\"\n", errMsg);
5344 sqlite3_free (errMsg);
5345 return -1;
5346 }
5347 return 0;
5348 }
5349
5350 SPATIALITE_PRIVATE int
getRealSQLnames(void * p_sqlite,const char * table,const char * column,char ** real_table,char ** real_column)5351 getRealSQLnames (void *p_sqlite, const char *table, const char *column,
5352 char **real_table, char **real_column)
5353 {
5354 /* attempting to retrieve the "real" table and column names (upper/lowercase) */
5355 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5356 char *p_table = NULL;
5357 char *p_column = NULL;
5358 char *sql_statement;
5359 char *quoted;
5360 const char *name;
5361 int len;
5362 sqlite3_stmt *stmt;
5363 int ret;
5364
5365 sql_statement = sqlite3_mprintf ("SELECT name "
5366 "FROM sqlite_master WHERE type = 'table' "
5367 "AND Lower(name) = Lower(?)");
5368 /* compiling SQL prepared statement */
5369 ret =
5370 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
5371 &stmt, NULL);
5372 sqlite3_free (sql_statement);
5373 if (ret != SQLITE_OK)
5374 {
5375 spatialite_e ("real_names: error %d \"%s\"\n",
5376 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
5377 return 0;
5378 }
5379 sqlite3_reset (stmt);
5380 sqlite3_clear_bindings (stmt);
5381 sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
5382 while (1)
5383 {
5384 /* scrolling the result set rows */
5385 ret = sqlite3_step (stmt);
5386 if (ret == SQLITE_DONE)
5387 break; /* end of result set */
5388 if (ret == SQLITE_ROW)
5389 {
5390 name = (const char *) sqlite3_column_text (stmt, 0);
5391 len = sqlite3_column_bytes (stmt, 0);
5392 if (p_table)
5393 free (p_table);
5394 p_table = malloc (len + 1);
5395 strcpy (p_table, name);
5396 }
5397 }
5398 sqlite3_finalize (stmt);
5399
5400 if (p_table == NULL)
5401 return 0;
5402
5403 quoted = gaiaDoubleQuotedSql (p_table);
5404 sql_statement = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", quoted);
5405 free (quoted);
5406 /* compiling SQL prepared statement */
5407 ret =
5408 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
5409 &stmt, NULL);
5410 sqlite3_free (sql_statement);
5411 if (ret != SQLITE_OK)
5412 {
5413 spatialite_e ("real_names: error %d \"%s\"\n",
5414 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
5415 free (p_table);
5416 return 0;
5417 }
5418 while (1)
5419 {
5420 /* scrolling the result set rows */
5421 ret = sqlite3_step (stmt);
5422 if (ret == SQLITE_DONE)
5423 break; /* end of result set */
5424 if (ret == SQLITE_ROW)
5425 {
5426 name = (const char *) sqlite3_column_text (stmt, 1);
5427 len = sqlite3_column_bytes (stmt, 1);
5428 if (strcasecmp (name, column) == 0)
5429 {
5430 if (p_column)
5431 free (p_column);
5432 p_column = malloc (len + 1);
5433 strcpy (p_column, name);
5434 }
5435 }
5436 }
5437 sqlite3_finalize (stmt);
5438
5439 if (p_column == NULL)
5440 {
5441 free (p_table);
5442 return 0;
5443 }
5444
5445 *real_table = p_table;
5446 *real_column = p_column;
5447 return 1;
5448 }
5449
5450 SPATIALITE_PRIVATE int
getRealSQLnamesTemporary(void * p_sqlite,const char * db_prefix,const char * table,const char * column,char ** real_table,char ** real_column)5451 getRealSQLnamesTemporary (void *p_sqlite, const char *db_prefix,
5452 const char *table, const char *column,
5453 char **real_table, char **real_column)
5454 {
5455 /* attempting to retrieve the "real" table and column names (upper/lowercase) */
5456 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
5457 char *p_table = NULL;
5458 char *p_column = NULL;
5459 char *sql_statement;
5460 char *prefix;
5461 char *quoted;
5462 const char *name;
5463 int len;
5464 sqlite3_stmt *stmt;
5465 int ret;
5466
5467 if (db_prefix == NULL)
5468 return 0;
5469
5470 prefix = gaiaDoubleQuotedSql (db_prefix);
5471 sql_statement = sqlite3_mprintf ("SELECT name "
5472 "FROM \"%s\".sqlite_master WHERE type = 'table' "
5473 "AND Lower(name) = Lower(?)", prefix);
5474 free (prefix);
5475 /* compiling SQL prepared statement */
5476 ret =
5477 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
5478 &stmt, NULL);
5479 sqlite3_free (sql_statement);
5480 if (ret != SQLITE_OK)
5481 {
5482 spatialite_e ("real_names temporary: error %d \"%s\"\n",
5483 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
5484 return 0;
5485 }
5486 sqlite3_reset (stmt);
5487 sqlite3_clear_bindings (stmt);
5488 sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
5489 while (1)
5490 {
5491 /* scrolling the result set rows */
5492 ret = sqlite3_step (stmt);
5493 if (ret == SQLITE_DONE)
5494 break; /* end of result set */
5495 if (ret == SQLITE_ROW)
5496 {
5497 name = (const char *) sqlite3_column_text (stmt, 0);
5498 len = sqlite3_column_bytes (stmt, 0);
5499 if (p_table)
5500 free (p_table);
5501 p_table = malloc (len + 1);
5502 strcpy (p_table, name);
5503 }
5504 }
5505 sqlite3_finalize (stmt);
5506
5507 if (p_table == NULL)
5508 return 0;
5509
5510 prefix = gaiaDoubleQuotedSql (db_prefix);
5511 quoted = gaiaDoubleQuotedSql (p_table);
5512 sql_statement =
5513 sqlite3_mprintf ("PRAGMA \"%s\".table_info(\"%s\")", prefix, quoted);
5514 free (prefix);
5515 free (quoted);
5516 /* compiling SQL prepared statement */
5517 ret =
5518 sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
5519 &stmt, NULL);
5520 sqlite3_free (sql_statement);
5521 if (ret != SQLITE_OK)
5522 {
5523 spatialite_e ("real_names temporary: error %d \"%s\"\n",
5524 sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
5525 free (p_table);
5526 return 0;
5527 }
5528 while (1)
5529 {
5530 /* scrolling the result set rows */
5531 ret = sqlite3_step (stmt);
5532 if (ret == SQLITE_DONE)
5533 break; /* end of result set */
5534 if (ret == SQLITE_ROW)
5535 {
5536 name = (const char *) sqlite3_column_text (stmt, 1);
5537 len = sqlite3_column_bytes (stmt, 1);
5538 if (strcasecmp (name, column) == 0)
5539 {
5540 if (p_column)
5541 free (p_column);
5542 p_column = malloc (len + 1);
5543 strcpy (p_column, name);
5544 }
5545 }
5546 }
5547 sqlite3_finalize (stmt);
5548
5549 if (p_column == NULL)
5550 {
5551 free (p_table);
5552 return 0;
5553 }
5554
5555 *real_table = p_table;
5556 *real_column = p_column;
5557 return 1;
5558 }
5559
5560 SPATIALITE_PRIVATE void
addLayerAttributeField(void * x_list,const char * table_name,const char * geometry_column,int ordinal,const char * column_name,int null_values,int integer_values,int double_values,int text_values,int blob_values,int null_max_size,int max_size,int null_int_range,void * x_integer_min,void * x_integer_max,int null_double_range,double double_min,double double_max)5561 addLayerAttributeField (void *x_list, const char *table_name,
5562 const char *geometry_column, int ordinal,
5563 const char *column_name, int null_values,
5564 int integer_values, int double_values, int text_values,
5565 int blob_values, int null_max_size, int max_size,
5566 int null_int_range, void *x_integer_min,
5567 void *x_integer_max, int null_double_range,
5568 double double_min, double double_max)
5569 {
5570 /* adding some AttributeFiled to a VectorLayer */
5571 gaiaVectorLayersListPtr list = (gaiaVectorLayersListPtr) x_list;
5572 sqlite3_int64 integer_min = *((sqlite3_int64 *) x_integer_min);
5573 sqlite3_int64 integer_max = *((sqlite3_int64 *) x_integer_max);
5574 gaiaLayerAttributeFieldPtr fld;
5575 int len;
5576 gaiaVectorLayerPtr lyr = list->Current;
5577 if (lyr)
5578 {
5579 if (strcasecmp (lyr->TableName, table_name) == 0
5580 && strcasecmp (lyr->GeometryName, geometry_column) == 0)
5581 goto valid_pointer;
5582 }
5583 list->Current = NULL;
5584 lyr = list->First;
5585 while (lyr)
5586 {
5587 if (strcasecmp (lyr->TableName, table_name) == 0
5588 && strcasecmp (lyr->GeometryName, geometry_column) == 0)
5589 {
5590 list->Current = lyr;
5591 goto valid_pointer;
5592 }
5593 lyr = lyr->Next;
5594 }
5595 valid_pointer:
5596 lyr = list->Current;
5597 if (lyr == NULL)
5598 return;
5599 fld = malloc (sizeof (gaiaLayerAttributeField));
5600 fld->Ordinal = ordinal;
5601 len = strlen (column_name);
5602 fld->AttributeFieldName = malloc (len + 1);
5603 strcpy (fld->AttributeFieldName, column_name);
5604 fld->NullValuesCount = null_values;
5605 fld->IntegerValuesCount = integer_values;
5606 fld->DoubleValuesCount = double_values;
5607 fld->TextValuesCount = text_values;
5608 fld->BlobValuesCount = blob_values;
5609 fld->MaxSize = NULL;
5610 fld->IntRange = NULL;
5611 fld->DoubleRange = NULL;
5612 if (!null_max_size)
5613 {
5614 fld->MaxSize = malloc (sizeof (gaiaAttributeFieldMaxSize));
5615 fld->MaxSize->MaxSize = max_size;
5616 }
5617 if (!null_int_range)
5618 {
5619 fld->IntRange = malloc (sizeof (gaiaAttributeFieldIntRange));
5620 fld->IntRange->MinValue = integer_min;
5621 fld->IntRange->MaxValue = integer_max;
5622 }
5623 if (!null_double_range)
5624 {
5625 fld->DoubleRange = malloc (sizeof (gaiaAttributeFieldDoubleRange));
5626 fld->DoubleRange->MinValue = double_min;
5627 fld->DoubleRange->MaxValue = double_max;
5628 }
5629 fld->Next = NULL;
5630 if (lyr->First == NULL)
5631 lyr->First = fld;
5632 if (lyr->Last != NULL)
5633 lyr->Last->Next = fld;
5634 lyr->Last = fld;
5635 }
5636
5637 SPATIALITE_PRIVATE void
addVectorLayer(void * x_list,const char * layer_type,const char * table_name,const char * geometry_column,int geometry_type,int srid,int spatial_index)5638 addVectorLayer (void *x_list, const char *layer_type,
5639 const char *table_name, const char *geometry_column,
5640 int geometry_type, int srid, int spatial_index)
5641 {
5642 /* adding a Layer to a VectorLayersList */
5643 gaiaVectorLayersListPtr list = (gaiaVectorLayersListPtr) x_list;
5644 int len;
5645 gaiaVectorLayerPtr lyr = malloc (sizeof (gaiaVectorLayer));
5646 lyr->LayerType = GAIA_VECTOR_UNKNOWN;
5647 if (strcasecmp (layer_type, "SpatialTable") == 0)
5648 lyr->LayerType = GAIA_VECTOR_TABLE;
5649 if (strcasecmp (layer_type, "SpatialView") == 0)
5650 lyr->LayerType = GAIA_VECTOR_VIEW;
5651 if (strcasecmp (layer_type, "VirtualShape") == 0)
5652 lyr->LayerType = GAIA_VECTOR_VIRTUAL;
5653 len = strlen (table_name);
5654 lyr->TableName = malloc (len + 1);
5655 strcpy (lyr->TableName, table_name);
5656 len = strlen (geometry_column);
5657 lyr->GeometryName = malloc (len + 1);
5658 strcpy (lyr->GeometryName, geometry_column);
5659 lyr->Srid = srid;
5660 switch (geometry_type)
5661 {
5662 case 0:
5663 lyr->GeometryType = GAIA_VECTOR_GEOMETRY;
5664 lyr->Dimensions = GAIA_XY;
5665 break;
5666 case 1000:
5667 lyr->GeometryType = GAIA_VECTOR_GEOMETRY;
5668 lyr->Dimensions = GAIA_XY_Z;
5669 break;
5670 case 2000:
5671 lyr->GeometryType = GAIA_VECTOR_GEOMETRY;
5672 lyr->Dimensions = GAIA_XY_M;
5673 break;
5674 case 3000:
5675 lyr->GeometryType = GAIA_VECTOR_GEOMETRY;
5676 lyr->Dimensions = GAIA_XY_Z_M;
5677 break;
5678 case 1:
5679 lyr->GeometryType = GAIA_VECTOR_POINT;
5680 lyr->Dimensions = GAIA_XY;
5681 break;
5682 case 1001:
5683 lyr->GeometryType = GAIA_VECTOR_POINT;
5684 lyr->Dimensions = GAIA_XY_Z;
5685 break;
5686 case 2001:
5687 lyr->GeometryType = GAIA_VECTOR_POINT;
5688 lyr->Dimensions = GAIA_XY_M;
5689 break;
5690 case 3001:
5691 lyr->GeometryType = GAIA_VECTOR_POINT;
5692 lyr->Dimensions = GAIA_XY_Z_M;
5693 break;
5694 case 2:
5695 lyr->GeometryType = GAIA_VECTOR_LINESTRING;
5696 lyr->Dimensions = GAIA_XY;
5697 break;
5698 case 1002:
5699 lyr->GeometryType = GAIA_VECTOR_LINESTRING;
5700 lyr->Dimensions = GAIA_XY_Z;
5701 break;
5702 case 2002:
5703 lyr->GeometryType = GAIA_VECTOR_LINESTRING;
5704 lyr->Dimensions = GAIA_XY_M;
5705 break;
5706 case 3002:
5707 lyr->GeometryType = GAIA_VECTOR_LINESTRING;
5708 lyr->Dimensions = GAIA_XY_Z_M;
5709 break;
5710 case 3:
5711 lyr->GeometryType = GAIA_VECTOR_POLYGON;
5712 lyr->Dimensions = GAIA_XY;
5713 break;
5714 case 1003:
5715 lyr->GeometryType = GAIA_VECTOR_POLYGON;
5716 lyr->Dimensions = GAIA_XY_Z;
5717 break;
5718 case 2003:
5719 lyr->GeometryType = GAIA_VECTOR_POLYGON;
5720 lyr->Dimensions = GAIA_XY_M;
5721 break;
5722 case 3003:
5723 lyr->GeometryType = GAIA_VECTOR_POLYGON;
5724 lyr->Dimensions = GAIA_XY_Z_M;
5725 break;
5726 case 4:
5727 lyr->GeometryType = GAIA_VECTOR_MULTIPOINT;
5728 lyr->Dimensions = GAIA_XY;
5729 break;
5730 case 1004:
5731 lyr->GeometryType = GAIA_VECTOR_MULTIPOINT;
5732 lyr->Dimensions = GAIA_XY_Z;
5733 break;
5734 case 2004:
5735 lyr->GeometryType = GAIA_VECTOR_MULTIPOINT;
5736 lyr->Dimensions = GAIA_XY_M;
5737 break;
5738 case 3004:
5739 lyr->GeometryType = GAIA_VECTOR_MULTIPOINT;
5740 lyr->Dimensions = GAIA_XY_Z_M;
5741 break;
5742 case 5:
5743 lyr->GeometryType = GAIA_VECTOR_MULTILINESTRING;
5744 lyr->Dimensions = GAIA_XY;
5745 break;
5746 case 1005:
5747 lyr->GeometryType = GAIA_VECTOR_MULTILINESTRING;
5748 lyr->Dimensions = GAIA_XY_Z;
5749 break;
5750 case 2005:
5751 lyr->GeometryType = GAIA_VECTOR_MULTILINESTRING;
5752 lyr->Dimensions = GAIA_XY_M;
5753 break;
5754 case 3005:
5755 lyr->GeometryType = GAIA_VECTOR_MULTILINESTRING;
5756 lyr->Dimensions = GAIA_XY_Z_M;
5757 break;
5758 case 6:
5759 lyr->GeometryType = GAIA_VECTOR_MULTIPOLYGON;
5760 lyr->Dimensions = GAIA_XY;
5761 break;
5762 case 1006:
5763 lyr->GeometryType = GAIA_VECTOR_MULTIPOLYGON;
5764 lyr->Dimensions = GAIA_XY_Z;
5765 break;
5766 case 2006:
5767 lyr->GeometryType = GAIA_VECTOR_MULTIPOLYGON;
5768 lyr->Dimensions = GAIA_XY_M;
5769 break;
5770 case 3006:
5771 lyr->GeometryType = GAIA_VECTOR_MULTIPOLYGON;
5772 lyr->Dimensions = GAIA_XY_Z_M;
5773 break;
5774 case 7:
5775 lyr->GeometryType = GAIA_VECTOR_GEOMETRYCOLLECTION;
5776 lyr->Dimensions = GAIA_XY;
5777 break;
5778 case 1007:
5779 lyr->GeometryType = GAIA_VECTOR_GEOMETRYCOLLECTION;
5780 lyr->Dimensions = GAIA_XY_Z;
5781 break;
5782 case 2007:
5783 lyr->GeometryType = GAIA_VECTOR_GEOMETRYCOLLECTION;
5784 lyr->Dimensions = GAIA_XY_M;
5785 break;
5786 case 3007:
5787 lyr->GeometryType = GAIA_VECTOR_GEOMETRYCOLLECTION;
5788 lyr->Dimensions = GAIA_XY_Z_M;
5789 break;
5790 default:
5791 lyr->GeometryType = GAIA_VECTOR_UNKNOWN;
5792 lyr->Dimensions = GAIA_VECTOR_UNKNOWN;
5793 break;
5794 };
5795 switch (spatial_index)
5796 {
5797 case 0:
5798 lyr->SpatialIndex = GAIA_SPATIAL_INDEX_NONE;
5799 break;
5800 case 1:
5801 lyr->SpatialIndex = GAIA_SPATIAL_INDEX_RTREE;
5802 break;
5803 case 2:
5804 lyr->SpatialIndex = GAIA_SPATIAL_INDEX_MBRCACHE;
5805 break;
5806 default:
5807 lyr->SpatialIndex = GAIA_VECTOR_UNKNOWN;
5808 break;
5809 };
5810 lyr->ExtentInfos = NULL;
5811 lyr->AuthInfos = NULL;
5812 lyr->First = NULL;
5813 lyr->Last = NULL;
5814 lyr->Next = NULL;
5815 list->Current = NULL;
5816 if (list->First == NULL)
5817 list->First = lyr;
5818 if (list->Last != NULL)
5819 list->Last->Next = lyr;
5820 list->Last = lyr;
5821 }
5822
5823 SPATIALITE_PRIVATE void
addVectorLayerExtent(void * x_list,const char * table_name,const char * geometry_column,int count,double min_x,double min_y,double max_x,double max_y)5824 addVectorLayerExtent (void *x_list, const char *table_name,
5825 const char *geometry_column, int count, double min_x,
5826 double min_y, double max_x, double max_y)
5827 {
5828 /* appending a LayerExtent object to the corresponding VectorLayer */
5829 gaiaVectorLayersListPtr list = (gaiaVectorLayersListPtr) x_list;
5830 gaiaVectorLayerPtr lyr = list->First;
5831 while (lyr)
5832 {
5833 if (strcasecmp (lyr->TableName, table_name) == 0
5834 && strcasecmp (lyr->GeometryName, geometry_column) == 0)
5835 {
5836 lyr->ExtentInfos = malloc (sizeof (gaiaLayerExtent));
5837 lyr->ExtentInfos->Count = count;
5838 lyr->ExtentInfos->MinX = min_x;
5839 lyr->ExtentInfos->MinY = min_y;
5840 lyr->ExtentInfos->MaxX = max_x;
5841 lyr->ExtentInfos->MaxY = max_y;
5842 return;
5843 }
5844 lyr = lyr->Next;
5845 }
5846 }
5847
5848 static void
doCheckWritableSpatialView(sqlite3 * handle,const char * view_name,int * has_trigger_insert,int * has_trigger_update,int * has_trigger_delete,int * is_read_only)5849 doCheckWritableSpatialView (sqlite3 * handle, const char *view_name,
5850 int *has_trigger_insert, int *has_trigger_update,
5851 int *has_trigger_delete, int *is_read_only)
5852 {
5853 /*
5854 * checking if a supposed Writable Spatial View do
5855 * effectively declares all expected Triggers
5856 *
5857 * patch kindly submitted by Mark Johnson <mj10777@googlemail.com>
5858 * see ticket: https://www.gaia-gis.it/fossil/libspatialite/tktview/597fce55f2884668a24b591840162ffebda390e1
5859 */
5860 int ret;
5861 char *sql;
5862 sqlite3_stmt *stmt;
5863
5864 /* Claims to be a Writable SpatialView, we shall see ... */
5865 *has_trigger_insert = 0;
5866 *has_trigger_update = 0;
5867 *has_trigger_delete = 0;
5868 *is_read_only = 1;
5869
5870 sql =
5871 sqlite3_mprintf ("SELECT "
5872 "(SELECT Exists(SELECT rootpage FROM sqlite_master "
5873 "WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND "
5874 "(instr(upper(sql),'INSTEAD OF INSERT') > 0)))), "
5875 "(SELECT Exists(SELECT rootpage FROM sqlite_master "
5876 "WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND "
5877 "(instr(upper(sql),'INSTEAD OF UPDATE') > 0)))), "
5878 "(SELECT Exists(SELECT rootpage FROM sqlite_master "
5879 "WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND "
5880 "(instr(upper(sql),'INSTEAD OF DELETE') > 0))))",
5881 view_name, view_name, view_name);
5882 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
5883 sqlite3_free (sql);
5884 if (ret == SQLITE_OK)
5885 {
5886 while (sqlite3_step (stmt) == SQLITE_ROW)
5887 {
5888 if (sqlite3_column_type (stmt, 0) != SQLITE_NULL)
5889 {
5890 if (sqlite3_column_int (stmt, 0) == 1)
5891 *has_trigger_insert = 1;
5892 }
5893 if (sqlite3_column_type (stmt, 1) != SQLITE_NULL)
5894 {
5895 if (sqlite3_column_int (stmt, 1) == 1)
5896 *has_trigger_update = 1;
5897 }
5898 if (sqlite3_column_type (stmt, 2) != SQLITE_NULL)
5899 {
5900 if (sqlite3_column_int (stmt, 2) == 1)
5901 *has_trigger_delete = 1;
5902 }
5903 }
5904 ret = sqlite3_finalize (stmt);
5905 }
5906 if (*has_trigger_insert || *has_trigger_update || *has_trigger_delete)
5907 *is_read_only = 0; /* Yes, this could be a functional Writable SpatialView */
5908 }
5909
5910 static void
addVectorLayerAuth(sqlite3 * handle,gaiaVectorLayersListPtr list,const char * table_name,const char * geometry_column,int read_only,int hidden)5911 addVectorLayerAuth (sqlite3 * handle, gaiaVectorLayersListPtr list,
5912 const char *table_name, const char *geometry_column,
5913 int read_only, int hidden)
5914 {
5915 /* appending a LayerAuth object to the corresponding VectorLayer */
5916 gaiaVectorLayerPtr lyr = list->First;
5917 while (lyr)
5918 {
5919 if (strcasecmp (lyr->TableName, table_name) == 0
5920 && strcasecmp (lyr->GeometryName, geometry_column) == 0)
5921 {
5922 gaiaLayerAuthPtr auth = malloc (sizeof (gaiaLayerAuth));
5923 lyr->AuthInfos = auth;
5924 auth->IsReadOnly = read_only;
5925 auth->IsHidden = hidden;
5926 auth->HasTriggerInsert = 0;
5927 auth->HasTriggerUpdate = 0;
5928 auth->HasTriggerDelete = 0;
5929 if ((lyr->LayerType == GAIA_VECTOR_VIEW) && (!auth->IsReadOnly))
5930 {
5931 int has_trigger_insert = 0;
5932 int has_trigger_update = 0;
5933 int has_trigger_delete = 0;
5934 int is_read_only = 1;
5935 doCheckWritableSpatialView (handle, table_name,
5936 &has_trigger_insert,
5937 &has_trigger_update,
5938 &has_trigger_delete,
5939 &is_read_only);
5940 auth->HasTriggerInsert = has_trigger_insert;
5941 auth->HasTriggerUpdate = has_trigger_update;
5942 auth->HasTriggerDelete = has_trigger_delete;
5943 auth->IsReadOnly = is_read_only;
5944 }
5945 return;
5946 }
5947 lyr = lyr->Next;
5948 }
5949 }
5950
5951 static void
freeLayerAttributeField(gaiaLayerAttributeFieldPtr fld)5952 freeLayerAttributeField (gaiaLayerAttributeFieldPtr fld)
5953 {
5954 /* destroying an AttributeField */
5955 if (fld->AttributeFieldName)
5956 free (fld->AttributeFieldName);
5957 if (fld->MaxSize)
5958 free (fld->MaxSize);
5959 if (fld->IntRange)
5960 free (fld->IntRange);
5961 if (fld->DoubleRange)
5962 free (fld->DoubleRange);
5963 free (fld);
5964 }
5965
5966 static void
freeVectorLayer(gaiaVectorLayerPtr lyr)5967 freeVectorLayer (gaiaVectorLayerPtr lyr)
5968 {
5969 /* destroying a VectorLayer object */
5970 gaiaLayerAttributeFieldPtr fld;
5971 gaiaLayerAttributeFieldPtr fldn;
5972 if (!lyr)
5973 return;
5974 if (lyr->TableName)
5975 free (lyr->TableName);
5976 if (lyr->GeometryName)
5977 free (lyr->GeometryName);
5978 if (lyr->ExtentInfos)
5979 free (lyr->ExtentInfos);
5980 if (lyr->AuthInfos)
5981 free (lyr->AuthInfos);
5982 fld = lyr->First;
5983 while (fld)
5984 {
5985 fldn = fld->Next;
5986 freeLayerAttributeField (fld);
5987 fld = fldn;
5988 }
5989 free (lyr);
5990 }
5991
5992 SPATIALITE_DECLARE void
gaiaFreeVectorLayersList(gaiaVectorLayersListPtr list)5993 gaiaFreeVectorLayersList (gaiaVectorLayersListPtr list)
5994 {
5995 /* destroying a VectorLayersList object */
5996 gaiaVectorLayerPtr lyr;
5997 gaiaVectorLayerPtr lyr_n;
5998 if (!list)
5999 return;
6000 lyr = list->First;
6001 while (lyr)
6002 {
6003 /* destroying each layer */
6004 lyr_n = lyr->Next;
6005 freeVectorLayer (lyr);
6006 lyr = lyr_n;
6007 }
6008 free (list);
6009 }
6010
6011 static int
gaiaGetVectorLayersList_v4(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6012 gaiaGetVectorLayersList_v4 (sqlite3 * handle, const char *table,
6013 const char *geometry, gaiaVectorLayersListPtr list)
6014 {
6015 /* creating a VectorLayersList object - v.4.0.0 DB layout */
6016 char *sql;
6017 int ret;
6018 sqlite3_stmt *stmt;
6019 int error = 0;
6020
6021 /*
6022 * attempting first to recover all SpatialViews registered into
6023 * views_geometry_columns but not into views_geometry_columns_auth
6024 */
6025 sql = "INSERT OR IGNORE INTO views_geometry_columns_auth "
6026 "(view_name, view_geometry, hidden) "
6027 "SELECT view_name, view_geometry, 0 FROM views_geometry_columns";
6028 sqlite3_exec (handle, sql, NULL, NULL, NULL);
6029
6030 /* querying the vector_layers view */
6031 if (table == NULL)
6032 sql =
6033 sqlite3_mprintf
6034 ("SELECT layer_type, table_name, geometry_column, geometry_type, "
6035 "srid, spatial_index_enabled FROM vector_layers");
6036 else
6037 {
6038 if (geometry == NULL)
6039 sql =
6040 sqlite3_mprintf
6041 ("SELECT layer_type, table_name, geometry_column, geometry_type, "
6042 "srid, spatial_index_enabled FROM vector_layers "
6043 "WHERE Lower(table_name) = Lower(%Q)", table);
6044 else
6045 sql =
6046 sqlite3_mprintf
6047 ("SELECT layer_type, table_name, geometry_column, geometry_type, "
6048 "srid, spatial_index_enabled FROM vector_layers "
6049 "WHERE Lower(table_name) = Lower(%Q) AND "
6050 "Lower(geometry_column) = Lower(%Q)", table, geometry);
6051 }
6052 /* compiling SQL prepared statement */
6053 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6054 sqlite3_free (sql);
6055 if (ret != SQLITE_OK)
6056 {
6057 error = 1;
6058 goto stop;
6059 }
6060 while (1)
6061 {
6062 /* scrolling the result set rows */
6063 ret = sqlite3_step (stmt);
6064 if (ret == SQLITE_DONE)
6065 break; /* end of result set */
6066 if (ret == SQLITE_ROW)
6067 {
6068 /* processing a VectorLayer row */
6069 const char *layer_type =
6070 (const char *) sqlite3_column_text (stmt, 0);
6071 const char *table_name =
6072 (const char *) sqlite3_column_text (stmt, 1);
6073 const char *geometry_column =
6074 (const char *) sqlite3_column_text (stmt, 2);
6075 int geometry_type = sqlite3_column_int (stmt, 3);
6076 int srid = sqlite3_column_int (stmt, 4);
6077 int spatial_index = sqlite3_column_int (stmt, 5);
6078 addVectorLayer (list, layer_type, table_name, geometry_column,
6079 geometry_type, srid, spatial_index);
6080 }
6081 else
6082 error = 1;
6083 }
6084 ret = sqlite3_finalize (stmt);
6085
6086 stop:
6087 if (error)
6088 return 0;
6089
6090 /* querying the vector_layers_statistics view */
6091 if (table == NULL)
6092 sql =
6093 sqlite3_mprintf
6094 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6095 "extent_min_y, extent_max_x, extent_max_y FROM vector_layers_statistics");
6096 else
6097 {
6098 if (geometry == NULL)
6099 sql =
6100 sqlite3_mprintf
6101 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6102 "extent_min_y, extent_max_x, extent_max_y FROM vector_layers_statistics "
6103 "WHERE Lower(table_name) = Lower(%Q)", table);
6104 else
6105 sql =
6106 sqlite3_mprintf
6107 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6108 "extent_min_y, extent_max_x, extent_max_y FROM vector_layers_statistics "
6109 "WHERE Lower(table_name) = Lower(%Q) AND "
6110 "Lower(geometry_column) = Lower(%Q)", table, geometry);
6111 }
6112 /* compiling SQL prepared statement */
6113 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6114 sqlite3_free (sql);
6115 if (ret != SQLITE_OK)
6116 {
6117 error = 1;
6118 goto stop2;
6119 }
6120 while (1)
6121 {
6122 /* scrolling the result set rows */
6123 ret = sqlite3_step (stmt);
6124 if (ret == SQLITE_DONE)
6125 break; /* end of result set */
6126 if (ret == SQLITE_ROW)
6127 {
6128 /* processing a VectorLayer row */
6129 int is_null = 0;
6130 const char *table_name =
6131 (const char *) sqlite3_column_text (stmt, 0);
6132 const char *geometry_column =
6133 (const char *) sqlite3_column_text (stmt, 1);
6134 int count = 0;
6135 double min_x = DBL_MAX;
6136 double min_y = DBL_MAX;
6137 double max_x = 0.0 - DBL_MAX;
6138 double max_y = 0.0 - DBL_MAX;
6139 if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
6140 is_null = 1;
6141 else
6142 count = sqlite3_column_int (stmt, 2);
6143 if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
6144 is_null = 1;
6145 else
6146 min_x = sqlite3_column_double (stmt, 3);
6147 if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
6148 is_null = 1;
6149 else
6150 min_y = sqlite3_column_double (stmt, 4);
6151 if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
6152 is_null = 1;
6153 else
6154 max_x = sqlite3_column_double (stmt, 5);
6155 if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
6156 is_null = 1;
6157 else
6158 max_y = sqlite3_column_double (stmt, 6);
6159 if (!is_null)
6160 addVectorLayerExtent (list, table_name, geometry_column,
6161 count, min_x, min_y, max_x, max_y);
6162 }
6163 }
6164 ret = sqlite3_finalize (stmt);
6165
6166 stop2:
6167 /* querying the vector_layers_auth view */
6168 if (table == NULL)
6169 sql =
6170 sqlite3_mprintf
6171 ("SELECT table_name, geometry_column, read_only, hidden "
6172 "FROM vector_layers_auth");
6173 else
6174 {
6175 if (geometry == NULL)
6176 sql =
6177 sqlite3_mprintf
6178 ("SELECT table_name, geometry_column, read_only, hidden "
6179 "FROM vector_layers_auth WHERE Lower(table_name) = Lower(%Q)",
6180 table, geometry);
6181 else
6182 sql =
6183 sqlite3_mprintf
6184 ("SELECT table_name, geometry_column, read_only, hidden "
6185 "FROM vector_layers_auth "
6186 "WHERE Lower(table_name) = Lower(%Q) AND "
6187 "Lower(geometry_column) = Lower(%Q)", table, geometry);
6188 }
6189 /* compiling SQL prepared statement */
6190 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6191 sqlite3_free (sql);
6192 if (ret != SQLITE_OK)
6193 {
6194 error = 1;
6195 goto stop3;
6196 }
6197 while (1)
6198 {
6199 /* scrolling the result set rows */
6200 ret = sqlite3_step (stmt);
6201 if (ret == SQLITE_DONE)
6202 break; /* end of result set */
6203 if (ret == SQLITE_ROW)
6204 {
6205 /* processing a VectorLayer row */
6206 int is_null = 0;
6207 const char *table_name =
6208 (const char *) sqlite3_column_text (stmt, 0);
6209 const char *geometry_column =
6210 (const char *) sqlite3_column_text (stmt, 1);
6211 int read_only = 0;
6212 int hidden = 0;
6213 if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
6214 is_null = 1;
6215 else
6216 read_only = sqlite3_column_int (stmt, 2);
6217 if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
6218 is_null = 1;
6219 else
6220 hidden = sqlite3_column_int (stmt, 3);
6221 if (!is_null)
6222 addVectorLayerAuth (handle, list, table_name,
6223 geometry_column, read_only, hidden);
6224 }
6225 }
6226 ret = sqlite3_finalize (stmt);
6227
6228 stop3:
6229 /* querying the vector_layers_field_infos view */
6230 if (table == NULL)
6231 {
6232 /* if no "table" is set, we'll never return AttributeField Infos */
6233 goto stop4;
6234 }
6235 else
6236 {
6237 if (geometry == NULL)
6238 sql =
6239 sqlite3_mprintf
6240 ("SELECT table_name, geometry_column, ordinal, column_name, "
6241 "null_values, integer_values, double_values, text_values, blob_values,"
6242 "max_size, integer_min, integer_max, double_min, double_max "
6243 "FROM vector_layers_field_infos WHERE Lower(table_name) = Lower(%Q)",
6244 table, geometry);
6245 else
6246 sql =
6247 sqlite3_mprintf
6248 ("SELECT table_name, geometry_column, ordinal, column_name, "
6249 "null_values, integer_values, double_values, text_values, blob_values,"
6250 "max_size, integer_min, integer_max, double_min, double_max "
6251 "FROM vector_layers_field_infos "
6252 "WHERE Lower(table_name) = Lower(%Q) AND "
6253 "Lower(geometry_column) = Lower(%Q)", table, geometry);
6254 }
6255 /* compiling SQL prepared statement */
6256 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6257 sqlite3_free (sql);
6258 if (ret != SQLITE_OK)
6259 {
6260 error = 1;
6261 goto stop4;
6262 }
6263 while (1)
6264 {
6265 /* scrolling the result set rows */
6266 ret = sqlite3_step (stmt);
6267 if (ret == SQLITE_DONE)
6268 break; /* end of result set */
6269 if (ret == SQLITE_ROW)
6270 {
6271 /* processing a VectorLayer row */
6272 int null_max_size = 0;
6273 int null_int_range = 0;
6274 int null_double_range = 0;
6275 int max_size = 0;
6276 sqlite3_int64 integer_min;
6277 sqlite3_int64 integer_max;
6278 double double_min = DBL_MAX;
6279 double double_max = 0.0 - DBL_MAX;
6280 const char *table_name =
6281 (const char *) sqlite3_column_text (stmt, 0);
6282 const char *geometry_column =
6283 (const char *) sqlite3_column_text (stmt, 1);
6284 int ordinal = sqlite3_column_int (stmt, 2);
6285 const char *column_name =
6286 (const char *) sqlite3_column_text (stmt, 3);
6287 int null_values = sqlite3_column_int (stmt, 4);
6288 int integer_values = sqlite3_column_int (stmt, 5);
6289 int double_values = sqlite3_column_int (stmt, 6);
6290 int text_values = sqlite3_column_int (stmt, 7);
6291 int blob_values = sqlite3_column_int (stmt, 8);
6292 if (sqlite3_column_type (stmt, 9) == SQLITE_NULL)
6293 null_max_size = 1;
6294 else
6295 max_size = sqlite3_column_int (stmt, 9);
6296 if (sqlite3_column_type (stmt, 10) == SQLITE_NULL
6297 || sqlite3_column_type (stmt, 11) == SQLITE_NULL)
6298 null_int_range = 1;
6299 else
6300 {
6301 integer_min = sqlite3_column_int64 (stmt, 10);
6302 integer_max = sqlite3_column_int64 (stmt, 11);
6303 }
6304 if (sqlite3_column_type (stmt, 12) == SQLITE_NULL
6305 || sqlite3_column_type (stmt, 13) == SQLITE_NULL)
6306 null_double_range = 1;
6307 else
6308 {
6309 double_min = sqlite3_column_double (stmt, 12);
6310 double_max = sqlite3_column_double (stmt, 13);
6311 }
6312 addLayerAttributeField (list, table_name, geometry_column,
6313 ordinal, column_name, null_values,
6314 integer_values, double_values,
6315 text_values, blob_values, null_max_size,
6316 max_size, null_int_range, &integer_min,
6317 &integer_max, null_double_range,
6318 double_min, double_max);
6319 }
6320 }
6321 ret = sqlite3_finalize (stmt);
6322
6323 stop4:
6324 if (error)
6325 return 0;
6326 return 1;
6327 }
6328
6329 static int
get_table_layers_legacy(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6330 get_table_layers_legacy (sqlite3 * handle, const char *table,
6331 const char *geometry, gaiaVectorLayersListPtr list)
6332 {
6333 /* fetching Table-based geometries */
6334 int ret;
6335 char *sql;
6336 const char *name;
6337 int i;
6338 char **results;
6339 int rows;
6340 int columns;
6341 int f_table = 0;
6342 int f_geometry = 0;
6343 int type = 0;
6344 int dims = 0;
6345 int srid = 0;
6346 int spatial_index = 0;
6347 sqlite3_stmt *stmt;
6348 int error = 0;
6349
6350 /* checking the GEOMETRY_COLUMN table */
6351 sql = "PRAGMA table_info(geometry_columns)";
6352 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6353 if (ret != SQLITE_OK)
6354 return 0;
6355 if (rows < 1)
6356 ;
6357 else
6358 {
6359 for (i = 1; i <= rows; i++)
6360 {
6361 name = results[(i * columns) + 1];
6362 if (strcasecmp (name, "f_table_name") == 0)
6363 f_table = 1;
6364 if (strcasecmp (name, "f_geometry_column") == 0)
6365 f_geometry = 1;
6366 if (strcasecmp (name, "type") == 0)
6367 type = 1;
6368 if (strcasecmp (name, "coord_dimension") == 0)
6369 dims = 1;
6370 if (strcasecmp (name, "srid") == 0)
6371 srid = 1;
6372 if (strcasecmp (name, "spatial_index_enabled") == 0)
6373 spatial_index = 1;
6374 }
6375 }
6376 sqlite3_free_table (results);
6377 if (f_table && f_geometry && type && dims && srid && spatial_index)
6378 ;
6379 else
6380 return 1;
6381
6382 if (table == NULL)
6383 sql =
6384 sqlite3_mprintf
6385 ("SELECT f_table_name, f_geometry_column, type, coord_dimension, "
6386 "srid, spatial_index_enabled FROM geometry_columns");
6387 else
6388 {
6389 if (geometry == NULL)
6390 sql =
6391 sqlite3_mprintf
6392 ("SELECT f_table_name, f_geometry_column, type, coord_dimension, "
6393 "srid, spatial_index_enabled FROM geometry_columns "
6394 "WHERE Lower(f_table_name) = Lower(%Q)", table);
6395 else
6396 sql =
6397 sqlite3_mprintf
6398 ("SELECT f_table_name, f_geometry_column, type, coord_dimension, "
6399 "srid, spatial_index_enabled FROM geometry_columns "
6400 "WHERE Lower(f_table_name) = Lower(%Q) AND "
6401 "Lower(f_geometry_column) = Lower(%Q)", table, geometry);
6402 }
6403 /* compiling SQL prepared statement */
6404 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6405 sqlite3_free (sql);
6406 if (ret != SQLITE_OK)
6407 {
6408 error = 1;
6409 goto stop;
6410 }
6411 while (1)
6412 {
6413 /* scrolling the result set rows */
6414 ret = sqlite3_step (stmt);
6415 if (ret == SQLITE_DONE)
6416 break; /* end of result set */
6417 if (ret == SQLITE_ROW)
6418 {
6419 /* processing a VectorLayer row */
6420 const char *table_name =
6421 (const char *) sqlite3_column_text (stmt, 0);
6422 const char *geometry_column =
6423 (const char *) sqlite3_column_text (stmt, 1);
6424 const char *type = (const char *) sqlite3_column_text (stmt, 2);
6425 const char *dims = (const char *) sqlite3_column_text (stmt, 3);
6426 int srid = sqlite3_column_int (stmt, 4);
6427 int spatial_index = sqlite3_column_int (stmt, 5);
6428 int geometry_type = -1;
6429 if (strcasecmp (type, "POINT") == 0)
6430 geometry_type = 1;
6431 if (strcasecmp (type, "LINESTRING") == 0)
6432 geometry_type = 2;
6433 if (strcasecmp (type, "POLYGON") == 0)
6434 geometry_type = 3;
6435 if (strcasecmp (type, "MULTIPOINT") == 0)
6436 geometry_type = 4;
6437 if (strcasecmp (type, "MULTILINESTRING") == 0)
6438 geometry_type = 5;
6439 if (strcasecmp (type, "MULTIPOLYGON") == 0)
6440 geometry_type = 6;
6441 if (strcasecmp (type, "GEOMETRYCOLLECTION") == 0)
6442 geometry_type = 7;
6443 if (strcasecmp (type, "GEOMETRY") == 0)
6444 geometry_type = 0;
6445 if (strcasecmp (dims, "XYZ") == 0
6446 || strcasecmp (dims, "3") == 0)
6447 geometry_type += 1000;
6448 if (strcasecmp (dims, "XYM") == 0)
6449 geometry_type += 2000;
6450 if (strcasecmp (dims, "XYZM") == 0
6451 || strcasecmp (dims, "4") == 0)
6452 geometry_type += 3000;
6453 addVectorLayer (list, "SpatialTable", table_name,
6454 geometry_column, geometry_type, srid,
6455 spatial_index);
6456 addVectorLayerAuth (handle, list, table_name, geometry_column,
6457 1, 0);
6458 }
6459 else
6460 error = 1;
6461 }
6462 ret = sqlite3_finalize (stmt);
6463
6464 stop:
6465 if (error)
6466 return 0;
6467 return 1;
6468 }
6469
6470 static int
get_view_layers_legacy(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6471 get_view_layers_legacy (sqlite3 * handle, const char *table,
6472 const char *geometry, gaiaVectorLayersListPtr list)
6473 {
6474 /* fetching View-based geometries */
6475 int ret;
6476 char *sql;
6477 const char *name;
6478 int i;
6479 char **results;
6480 int rows;
6481 int columns;
6482 int f_table = 0;
6483 int f_geometry = 0;
6484 int type = 0;
6485 int dims = 0;
6486 int srid = 0;
6487 int spatial_index = 0;
6488 int view_name = 0;
6489 int view_geometry = 0;
6490 int fvw_table = 0;
6491 int fvw_geometry = 0;
6492 sqlite3_stmt *stmt;
6493 int error = 0;
6494
6495 /* checking the GEOMETRY_COLUMN table */
6496 sql = "PRAGMA table_info(geometry_columns)";
6497 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6498 if (ret != SQLITE_OK)
6499 return 0;
6500 if (rows < 1)
6501 ;
6502 else
6503 {
6504 for (i = 1; i <= rows; i++)
6505 {
6506 name = results[(i * columns) + 1];
6507 if (strcasecmp (name, "f_table_name") == 0)
6508 f_table = 1;
6509 if (strcasecmp (name, "f_geometry_column") == 0)
6510 f_geometry = 1;
6511 if (strcasecmp (name, "type") == 0)
6512 type = 1;
6513 if (strcasecmp (name, "coord_dimension") == 0)
6514 dims = 1;
6515 if (strcasecmp (name, "srid") == 0)
6516 srid = 1;
6517 if (strcasecmp (name, "spatial_index_enabled") == 0)
6518 spatial_index = 1;
6519 }
6520 }
6521 sqlite3_free_table (results);
6522 if (f_table && f_geometry && type && dims && srid && spatial_index)
6523 ;
6524 else
6525 return 1;
6526
6527 /* checking the VIEWS_GEOMETRY_COLUMN table */
6528 sql = "PRAGMA table_info(views_geometry_columns)";
6529 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6530 if (ret != SQLITE_OK)
6531 return 0;
6532 if (rows < 1)
6533 ;
6534 else
6535 {
6536 for (i = 1; i <= rows; i++)
6537 {
6538 name = results[(i * columns) + 1];
6539 if (strcasecmp (name, "view_name") == 0)
6540 view_name = 1;
6541 if (strcasecmp (name, "view_geometry") == 0)
6542 view_geometry = 1;
6543 if (strcasecmp (name, "f_table_name") == 0)
6544 fvw_table = 1;
6545 if (strcasecmp (name, "f_geometry_column") == 0)
6546 fvw_geometry = 1;
6547 }
6548 }
6549 sqlite3_free_table (results);
6550 if (view_name && view_geometry && fvw_table && fvw_geometry)
6551 ;
6552 else
6553 return 1;
6554
6555 if (table == NULL)
6556 sql =
6557 sqlite3_mprintf
6558 ("SELECT a.view_name, a.view_geometry, b.type, b.coord_dimension, "
6559 "b.srid, b.spatial_index_enabled FROM views_geometry_columns AS a "
6560 "JOIN geometry_columns AS b ON (Lower(a.f_table_name) = Lower(b.f_table_name) "
6561 "AND Lower(a.f_geometry_column) = Lower(b.f_geometry_column))");
6562 else
6563 {
6564 if (geometry == NULL)
6565 sql =
6566 sqlite3_mprintf
6567 ("SELECT a.view_name, a.view_geometry, b.type, b.coord_dimension, "
6568 "b.srid, b.spatial_index_enabled FROM views_geometry_columns AS a "
6569 "JOIN geometry_columns AS b ON (Lower(a.f_table_name) = Lower(b.f_table_name) "
6570 "AND Lower(a.f_geometry_column) = Lower(b.f_geometry_column)) "
6571 "WHERE Lower(a.view_name) = Lower(%Q)", table);
6572 else
6573 sql =
6574 sqlite3_mprintf
6575 ("SELECT a.view_name, a.view_geometry, b.type, b.coord_dimension, "
6576 "b.srid, b.spatial_index_enabled FROM views_geometry_columns AS a "
6577 "JOIN geometry_columns AS b ON (Lower(a.f_table_name) = Lower(b.f_table_name) "
6578 "AND Lower(a.f_geometry_column) = Lower(b.f_geometry_column)) "
6579 "WHERE Lower(a.view_name) = Lower(%Q) AND "
6580 "Lower(a.view_geometry) = Lower(%Q)", table, geometry);
6581 }
6582 /* compiling SQL prepared statement */
6583 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6584 sqlite3_free (sql);
6585 if (ret != SQLITE_OK)
6586 {
6587 error = 1;
6588 goto stop;
6589 }
6590 while (1)
6591 {
6592 /* scrolling the result set rows */
6593 ret = sqlite3_step (stmt);
6594 if (ret == SQLITE_DONE)
6595 break; /* end of result set */
6596 if (ret == SQLITE_ROW)
6597 {
6598 /* processing a VectorLayer row */
6599 const char *table_name =
6600 (const char *) sqlite3_column_text (stmt, 0);
6601 const char *geometry_column =
6602 (const char *) sqlite3_column_text (stmt, 1);
6603 const char *type = (const char *) sqlite3_column_text (stmt, 2);
6604 const char *dims = (const char *) sqlite3_column_text (stmt, 3);
6605 int srid = sqlite3_column_int (stmt, 4);
6606 int spatial_index = sqlite3_column_int (stmt, 5);
6607 int geometry_type = -1;
6608 if (strcasecmp (type, "POINT") == 0)
6609 geometry_type = 1;
6610 if (strcasecmp (type, "LINESTRING") == 0)
6611 geometry_type = 2;
6612 if (strcasecmp (type, "POLYGON") == 0)
6613 geometry_type = 3;
6614 if (strcasecmp (type, "MULTIPOINT") == 0)
6615 geometry_type = 4;
6616 if (strcasecmp (type, "MULTILINESTRING") == 0)
6617 geometry_type = 5;
6618 if (strcasecmp (type, "MULTIPOLYGON") == 0)
6619 geometry_type = 6;
6620 if (strcasecmp (type, "GEOMETRYCOLLECTION") == 0)
6621 geometry_type = 7;
6622 if (strcasecmp (type, "GEOMETRY") == 0)
6623 geometry_type = 0;
6624 if (strcasecmp (dims, "XYZ") == 0
6625 || strcasecmp (dims, "3") == 0)
6626 geometry_type += 1000;
6627 if (strcasecmp (dims, "XYM") == 0)
6628 geometry_type += 2000;
6629 if (strcasecmp (dims, "XYZM") == 0
6630 || strcasecmp (dims, "4") == 0)
6631 geometry_type += 3000;
6632 addVectorLayer (list, "SpatialView", table_name,
6633 geometry_column, geometry_type, srid,
6634 spatial_index);
6635 }
6636 else
6637 error = 1;
6638 }
6639 ret = sqlite3_finalize (stmt);
6640
6641 stop:
6642 if (error)
6643 return 0;
6644 return 1;
6645 }
6646
6647 static int
get_table_extent_legacy(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6648 get_table_extent_legacy (sqlite3 * handle, const char *table,
6649 const char *geometry, gaiaVectorLayersListPtr list)
6650 {
6651 /* fetching Table-based extents */
6652 int ret;
6653 char *sql;
6654 const char *name;
6655 int i;
6656 char **results;
6657 int rows;
6658 int columns;
6659 int f_table = 0;
6660 int f_geometry = 0;
6661 int count = 0;
6662 int minx = 0;
6663 int miny = 0;
6664 int maxx = 0;
6665 int maxy = 0;
6666 sqlite3_stmt *stmt;
6667
6668 /* checking the LAYER_STATISTICS table */
6669 sql = "PRAGMA table_info(layer_statistics)";
6670 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6671 if (ret != SQLITE_OK)
6672 return 0;
6673 if (rows < 1)
6674 ;
6675 else
6676 {
6677 for (i = 1; i <= rows; i++)
6678 {
6679 name = results[(i * columns) + 1];
6680 if (strcasecmp (name, "table_name") == 0)
6681 f_table = 1;
6682 if (strcasecmp (name, "geometry_column") == 0)
6683 f_geometry = 1;
6684 if (strcasecmp (name, "row_count") == 0)
6685 count = 1;
6686 if (strcasecmp (name, "extent_min_x") == 0)
6687 minx = 1;
6688 if (strcasecmp (name, "extent_min_y") == 0)
6689 miny = 1;
6690 if (strcasecmp (name, "extent_max_x") == 0)
6691 maxx = 1;
6692 if (strcasecmp (name, "extent_max_y") == 0)
6693 maxy = 1;
6694 }
6695 }
6696 sqlite3_free_table (results);
6697 if (f_table && f_geometry && count && minx && miny && maxx && maxy)
6698 ;
6699 else
6700 return 1;
6701
6702 /* querying the layer_statistics table */
6703 if (table == NULL)
6704 sql =
6705 sqlite3_mprintf
6706 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6707 "extent_min_y, extent_max_x, extent_max_y FROM layer_statistics");
6708 else
6709 {
6710 if (geometry == NULL)
6711 sql =
6712 sqlite3_mprintf
6713 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6714 "extent_min_y, extent_max_x, extent_max_y FROM layer_statistics "
6715 "WHERE Lower(table_name) = Lower(%Q)", table);
6716 else
6717 sql =
6718 sqlite3_mprintf
6719 ("SELECT table_name, geometry_column, row_count, extent_min_x, "
6720 "extent_min_y, extent_max_x, extent_max_y FROM layer_statistics "
6721 "WHERE Lower(table_name) = Lower(%Q) AND "
6722 "Lower(geometry_column) = Lower(%Q)", table, geometry);
6723 }
6724 /* compiling SQL prepared statement */
6725 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6726 sqlite3_free (sql);
6727 if (ret != SQLITE_OK)
6728 goto stop;
6729 while (1)
6730 {
6731 /* scrolling the result set rows */
6732 ret = sqlite3_step (stmt);
6733 if (ret == SQLITE_DONE)
6734 break; /* end of result set */
6735 if (ret == SQLITE_ROW)
6736 {
6737 /* processing a VectorLayer row */
6738 int is_null = 0;
6739 const char *table_name =
6740 (const char *) sqlite3_column_text (stmt, 0);
6741 const char *geometry_column =
6742 (const char *) sqlite3_column_text (stmt, 1);
6743 int count = 0;
6744 double min_x = DBL_MAX;
6745 double min_y = DBL_MAX;
6746 double max_x = 0.0 - DBL_MAX;
6747 double max_y = 0.0 - DBL_MAX;
6748 if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
6749 is_null = 1;
6750 else
6751 count = sqlite3_column_int (stmt, 2);
6752 if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
6753 is_null = 1;
6754 else
6755 min_x = sqlite3_column_double (stmt, 3);
6756 if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
6757 is_null = 1;
6758 else
6759 min_y = sqlite3_column_double (stmt, 4);
6760 if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
6761 is_null = 1;
6762 else
6763 max_x = sqlite3_column_double (stmt, 5);
6764 if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
6765 is_null = 1;
6766 else
6767 max_y = sqlite3_column_double (stmt, 6);
6768 if (!is_null)
6769 addVectorLayerExtent (list, table_name, geometry_column,
6770 count, min_x, min_y, max_x, max_y);
6771 }
6772 }
6773 ret = sqlite3_finalize (stmt);
6774 stop:
6775 return 1;
6776 }
6777
6778 static int
get_view_extent_legacy(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6779 get_view_extent_legacy (sqlite3 * handle, const char *table,
6780 const char *geometry, gaiaVectorLayersListPtr list)
6781 {
6782 /* fetching View-based extents */
6783 int ret;
6784 char *sql;
6785 const char *name;
6786 int i;
6787 char **results;
6788 int rows;
6789 int columns;
6790 int f_table = 0;
6791 int f_geometry = 0;
6792 int count = 0;
6793 int minx = 0;
6794 int miny = 0;
6795 int maxx = 0;
6796 int maxy = 0;
6797 sqlite3_stmt *stmt;
6798
6799 /* checking the VIEWS_LAYER_STATISTICS table */
6800 sql = "PRAGMA table_info(views_layer_statistics)";
6801 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6802 if (ret != SQLITE_OK)
6803 return 0;
6804 if (rows < 1)
6805 ;
6806 else
6807 {
6808 for (i = 1; i <= rows; i++)
6809 {
6810 name = results[(i * columns) + 1];
6811 if (strcasecmp (name, "view_name") == 0)
6812 f_table = 1;
6813 if (strcasecmp (name, "view_geometry") == 0)
6814 f_geometry = 1;
6815 if (strcasecmp (name, "row_count") == 0)
6816 count = 1;
6817 if (strcasecmp (name, "extent_min_x") == 0)
6818 minx = 1;
6819 if (strcasecmp (name, "extent_min_y") == 0)
6820 miny = 1;
6821 if (strcasecmp (name, "extent_max_x") == 0)
6822 maxx = 1;
6823 if (strcasecmp (name, "extent_max_y") == 0)
6824 maxy = 1;
6825 }
6826 }
6827 sqlite3_free_table (results);
6828 if (f_table && f_geometry && count && minx && miny && maxx && maxy)
6829 ;
6830 else
6831 return 1;
6832
6833 /* querying the views_layer_statistics table */
6834 if (table == NULL)
6835 sql =
6836 sqlite3_mprintf
6837 ("SELECT view_name, view_geometry, row_count, extent_min_x, "
6838 "extent_min_y, extent_max_x, extent_max_y FROM views_layer_statistics");
6839 else
6840 {
6841 if (geometry == NULL)
6842 sql =
6843 sqlite3_mprintf
6844 ("SELECT view_name, view_geometry, row_count, extent_min_x, "
6845 "extent_min_y, extent_max_x, extent_max_y FROM views_layer_statistics "
6846 "WHERE Lower(view_name) = Lower(%Q)", table);
6847 else
6848 sql =
6849 sqlite3_mprintf
6850 ("SELECT view_name, view_geometry, row_count, extent_min_x, "
6851 "extent_min_y, extent_max_x, extent_max_y FROM views_layer_statistics "
6852 "WHERE Lower(view_name) = Lower(%Q) AND "
6853 "Lower(view_geometry) = Lower(%Q)", table, geometry);
6854 }
6855 /* compiling SQL prepared statement */
6856 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6857 sqlite3_free (sql);
6858 if (ret != SQLITE_OK)
6859 goto stop;
6860 while (1)
6861 {
6862 /* scrolling the result set rows */
6863 ret = sqlite3_step (stmt);
6864 if (ret == SQLITE_DONE)
6865 break; /* end of result set */
6866 if (ret == SQLITE_ROW)
6867 {
6868 /* processing a VectorLayer row */
6869 int is_null = 0;
6870 const char *table_name =
6871 (const char *) sqlite3_column_text (stmt, 0);
6872 const char *geometry_column =
6873 (const char *) sqlite3_column_text (stmt, 1);
6874 int count = 0;
6875 double min_x = DBL_MAX;
6876 double min_y = DBL_MAX;
6877 double max_x = 0.0 - DBL_MAX;
6878 double max_y = 0.0 - DBL_MAX;
6879 if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
6880 is_null = 1;
6881 else
6882 count = sqlite3_column_int (stmt, 2);
6883 if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
6884 is_null = 1;
6885 else
6886 min_x = sqlite3_column_double (stmt, 3);
6887 if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
6888 is_null = 1;
6889 else
6890 min_y = sqlite3_column_double (stmt, 4);
6891 if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
6892 is_null = 1;
6893 else
6894 max_x = sqlite3_column_double (stmt, 5);
6895 if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
6896 is_null = 1;
6897 else
6898 max_y = sqlite3_column_double (stmt, 6);
6899 if (!is_null)
6900 addVectorLayerExtent (list, table_name, geometry_column,
6901 count, min_x, min_y, max_x, max_y);
6902 }
6903 }
6904 ret = sqlite3_finalize (stmt);
6905 stop:
6906 return 1;
6907 }
6908
6909 static int
get_table_auth_legacy(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)6910 get_table_auth_legacy (sqlite3 * handle, const char *table,
6911 const char *geometry, gaiaVectorLayersListPtr list)
6912 {
6913 /* fetching Table-based Auth */
6914 int ret;
6915 char *sql;
6916 const char *name;
6917 int i;
6918 char **results;
6919 int rows;
6920 int columns;
6921 int f_table = 0;
6922 int f_geometry = 0;
6923 int read_only = 0;
6924 int hidden = 0;
6925 sqlite3_stmt *stmt;
6926
6927 /* checking the GEOMETRY_COLUMNS_AUTH table */
6928 sql = "PRAGMA table_info(geometry_columns_auth)";
6929 ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
6930 if (ret != SQLITE_OK)
6931 return 0;
6932 if (rows < 1)
6933 ;
6934 else
6935 {
6936 for (i = 1; i <= rows; i++)
6937 {
6938 name = results[(i * columns) + 1];
6939 if (strcasecmp (name, "f_table_name") == 0)
6940 f_table = 1;
6941 if (strcasecmp (name, "f_geometry_column") == 0)
6942 f_geometry = 1;
6943 if (strcasecmp (name, "read_only") == 0)
6944 read_only = 1;
6945 if (strcasecmp (name, "hidden") == 0)
6946 hidden = 1;
6947 }
6948 }
6949 sqlite3_free_table (results);
6950 if (f_table && f_geometry && read_only && hidden)
6951 ;
6952 else
6953 return 1;
6954
6955 /* querying the geometry_columns_auth table */
6956 if (table == NULL)
6957 sql =
6958 sqlite3_mprintf
6959 ("SELECT f_table_name, f_geometry_column, read_only, hidden "
6960 "FROM geometry_columns_auth");
6961 else
6962 {
6963 if (geometry == NULL)
6964 sql =
6965 sqlite3_mprintf
6966 ("SELECT f_table_name, f_geometry_column, read_only, hidden "
6967 "FROM geometry_columns_auth "
6968 "WHERE Lower(f_table_name) = Lower(%Q)", table);
6969 else
6970 sql =
6971 sqlite3_mprintf
6972 ("SELECT f_table_name, f_geometry_column, read_only, hidden "
6973 "FROM geometry_columns_auth "
6974 "WHERE Lower(f_table_name) = Lower(%Q) AND "
6975 "Lower(f_geometry_column) = Lower(%Q)", table, geometry);
6976 }
6977 /* compiling SQL prepared statement */
6978 ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
6979 sqlite3_free (sql);
6980 if (ret != SQLITE_OK)
6981 goto stop;
6982 while (1)
6983 {
6984 /* scrolling the result set rows */
6985 ret = sqlite3_step (stmt);
6986 if (ret == SQLITE_DONE)
6987 break; /* end of result set */
6988 if (ret == SQLITE_ROW)
6989 {
6990 /* processing a VectorLayer row */
6991 int is_null = 0;
6992 const char *table_name =
6993 (const char *) sqlite3_column_text (stmt, 0);
6994 const char *geometry_column =
6995 (const char *) sqlite3_column_text (stmt, 1);
6996 int read_only = 0;
6997 int hidden = 0;
6998 if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
6999 is_null = 1;
7000 else
7001 read_only = sqlite3_column_int (stmt, 2);
7002 if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
7003 is_null = 1;
7004 else
7005 hidden = sqlite3_column_int (stmt, 3);
7006 if (!is_null)
7007 addVectorLayerAuth (handle, list, table_name,
7008 geometry_column, read_only, hidden);
7009 }
7010 }
7011 ret = sqlite3_finalize (stmt);
7012 stop:
7013 return 1;
7014 }
7015
7016 static int
compute_table_fields_statistics(sqlite3 * handle,const char * table,const char * geometry,gaiaVectorLayersListPtr list)7017 compute_table_fields_statistics (sqlite3 * handle, const char *table,
7018 const char *geometry,
7019 gaiaVectorLayersListPtr list)
7020 {
7021 /* computing field statistics - legacy */
7022 gaiaVectorLayerPtr lyr;
7023 lyr = list->First;
7024 while (lyr)
7025 {
7026 /* testing if the Table/Geometry is already defined */
7027 if (geometry == NULL)
7028 {
7029 if (strcasecmp (lyr->TableName, table) == 0)
7030 {
7031 if (!doComputeFieldInfos
7032 (handle, lyr->TableName, lyr->GeometryName,
7033 SPATIALITE_STATISTICS_LEGACY, lyr))
7034 return 0;
7035 }
7036 }
7037 else
7038 {
7039 if (strcasecmp (lyr->TableName, table) == 0
7040 && strcasecmp (lyr->GeometryName, geometry) == 0)
7041 {
7042 if (!doComputeFieldInfos
7043 (handle, lyr->TableName, lyr->GeometryName,
7044 SPATIALITE_STATISTICS_LEGACY, lyr))
7045 return 0;
7046 }
7047 }
7048 lyr = lyr->Next;
7049 }
7050 return 1;
7051 }
7052
7053 static int
check_v4_statistics(sqlite3 * handle)7054 check_v4_statistics (sqlite3 * handle)
7055 {
7056 /* checking if v.4.0.0 statistics tables are supported */
7057 char *sql_statement;
7058 int ret;
7059 char **results;
7060 int rows;
7061 int columns;
7062
7063 /* testing the SQL Query */
7064 sql_statement =
7065 sqlite3_mprintf ("SELECT g.table_name, g.geometry_column, "
7066 "s.row_count, s.extent_min_x, s.extent_min_y, "
7067 "s.extent_max_x, s.extent_max_y "
7068 "FROM vector_layers AS g "
7069 "LEFT JOIN vector_layers_statistics AS s ON "
7070 "(g.table_name = s.table_name AND "
7071 "g.geometry_column = s.geometry_column) LIMIT 1");
7072 ret =
7073 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7074 NULL);
7075 sqlite3_free (sql_statement);
7076 if (ret != SQLITE_OK)
7077 return 0;
7078 sqlite3_free_table (results);
7079
7080 return 1;
7081 }
7082
7083 static int
check_v3_statistics(sqlite3 * handle)7084 check_v3_statistics (sqlite3 * handle)
7085 {
7086 /* checking if v.3.0.0 statistics tables are supported */
7087 char *sql_statement;
7088 int ret;
7089 char **results;
7090 int rows;
7091 int columns;
7092
7093 if (!check_layer_statistics (handle))
7094 return 0;
7095 /* testing the SQL Query - Table-based Geometries */
7096 sql_statement =
7097 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column, "
7098 "s.row_count, s.extent_min_x, s.extent_min_y, "
7099 "s.extent_max_x, s.extent_max_y "
7100 "FROM geometry_columns AS g "
7101 "LEFT JOIN layer_statistics AS s ON "
7102 "(g.f_table_name = s.table_name AND "
7103 "g.f_geometry_column = s.geometry_column) LIMIT 1");
7104 ret =
7105 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7106 NULL);
7107 sqlite3_free (sql_statement);
7108 if (ret != SQLITE_OK)
7109 return 0;
7110 sqlite3_free_table (results);
7111
7112 if (!check_views_layer_statistics (handle))
7113 return 0;
7114 /* testing the SQL Query - View-based Geometries */
7115 sql_statement =
7116 sqlite3_mprintf ("SELECT g.view_name, g.view_geometry, "
7117 "s.row_count, s.extent_min_x, s.extent_min_y, "
7118 "s.extent_max_x, s.extent_max_y "
7119 "FROM views_geometry_columns AS g "
7120 "LEFT JOIN views_layer_statistics AS s ON "
7121 "(g.view_name = s.view_name AND "
7122 "g.view_geometry = s.view_geometry) LIMIT 1");
7123 ret =
7124 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7125 NULL);
7126 sqlite3_free (sql_statement);
7127 if (ret != SQLITE_OK)
7128 return 0;
7129 sqlite3_free_table (results);
7130
7131 if (!check_virts_layer_statistics (handle))
7132 return 0;
7133 /* testing the SQL Query - VirtualShape-based Geometries */
7134 sql_statement =
7135 sqlite3_mprintf ("SELECT g.virt_name, g.virt_geometry, "
7136 "s.row_count, s.extent_min_x, s.extent_min_y, "
7137 "s.extent_max_x, s.extent_max_y "
7138 "FROM virts_geometry_columns AS g "
7139 "LEFT JOIN virts_layer_statistics AS s ON "
7140 "(g.virt_name = s.virt_name AND "
7141 "g.virt_geometry = s.virt_geometry) LIMIT 1");
7142 ret =
7143 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7144 NULL);
7145 sqlite3_free (sql_statement);
7146 if (ret != SQLITE_OK)
7147 return 0;
7148 sqlite3_free_table (results);
7149
7150 return 1;
7151 }
7152
7153 static int
check_v2_statistics(sqlite3 * handle)7154 check_v2_statistics (sqlite3 * handle)
7155 {
7156 /* checking if v.2.0.0 statistics tables are supported */
7157 char *sql_statement;
7158 int ret;
7159 char **results;
7160 int rows;
7161 int columns;
7162
7163 if (!check_layer_statistics (handle))
7164 return 0;
7165 /* testing the SQL Query - Table-based Geometries */
7166 sql_statement =
7167 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column, "
7168 "s.row_count, s.extent_min_x, s.extent_min_y, "
7169 "s.extent_max_x, s.extent_max_y "
7170 "FROM geometry_columns AS g "
7171 "LEFT JOIN layer_statistics AS s ON "
7172 "(g.f_table_name = s.table_name AND "
7173 "g.f_geometry_column = s.geometry_column) LIMIT 1");
7174 ret =
7175 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7176 NULL);
7177 sqlite3_free (sql_statement);
7178 if (ret != SQLITE_OK)
7179 return 0;
7180 sqlite3_free_table (results);
7181
7182 return 1;
7183 }
7184
7185 static int
optimistic_layer_statistics_v4(sqlite3 * handle,const char * table,const char * geometry)7186 optimistic_layer_statistics_v4 (sqlite3 * handle, const char *table,
7187 const char *geometry)
7188 {
7189 /* selective statistics update - v.4.0.0 layout */
7190 char *sql_statement;
7191 int ret;
7192 const char *f_table_name;
7193 const char *f_geometry_column;
7194 int i;
7195 char **results;
7196 int rows;
7197 int columns;
7198 int error = 0;
7199
7200 if (table == NULL && geometry == NULL)
7201 {
7202 /* processing any table/geometry found in GEOMETRY_COLUMNS */
7203 sql_statement =
7204 sqlite3_mprintf ("SELECT g.table_name, g.geometry_column "
7205 "FROM vector_layers AS g "
7206 "LEFT JOIN vector_layers_statistics AS s ON "
7207 "(g.table_name = s.table_name AND "
7208 "g.geometry_column = s.geometry_column) "
7209 "WHERE s.row_count IS NULL OR s.extent_min_x IS NULL "
7210 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7211 "OR s.extent_max_y IS NULL");
7212 }
7213 else if (geometry == NULL)
7214 {
7215 /* processing any geometry belonging to this table */
7216 sql_statement =
7217 sqlite3_mprintf ("SELECT g.table_name, g.geometry_column "
7218 "FROM vector_layers AS g "
7219 "LEFT JOIN vector_layers_statistics AS s ON "
7220 "(g.table_name = s.table_name AND "
7221 "g.geometry_column = s.geometry_column) "
7222 "WHERE Lower(g.table_name) = Lower(%Q) AND "
7223 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7224 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7225 "OR s.extent_max_y IS NULL)", table);
7226 }
7227 else
7228 {
7229 /* processing a single table/geometry entry */
7230 sql_statement =
7231 sqlite3_mprintf ("SELECT g.table_name, g.geometry_column "
7232 "FROM vector_layers AS g "
7233 "LEFT JOIN vector_layers_statistics AS s ON "
7234 "(g.table_name = s.table_name AND "
7235 "g.geometry_column = s.geometry_column) "
7236 "WHERE Lower(g.table_name) = Lower(%Q) AND "
7237 "Lower(g.geometry_column) = Lower(%Q) AND "
7238 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7239 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7240 "OR s.extent_max_y IS NULL)", table, geometry);
7241 }
7242 ret =
7243 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7244 NULL);
7245 sqlite3_free (sql_statement);
7246 if (ret != SQLITE_OK)
7247 return 0;
7248
7249 if (rows < 1)
7250 ;
7251 else
7252 {
7253 for (i = 1; i <= rows; i++)
7254 {
7255 f_table_name = results[(i * columns) + 0];
7256 f_geometry_column = results[(i * columns) + 1];
7257 if (!update_layer_statistics
7258 (handle, f_table_name, f_geometry_column))
7259 {
7260 error = 1;
7261 break;
7262 }
7263 }
7264 }
7265 sqlite3_free_table (results);
7266 if (error)
7267 return 0;
7268 return 1;
7269 }
7270
7271 static int
optimistic_layer_statistics_v3(sqlite3 * handle,const char * table,const char * geometry)7272 optimistic_layer_statistics_v3 (sqlite3 * handle, const char *table,
7273 const char *geometry)
7274 {
7275 /* selective statistics update - v.3.0.0 layout */
7276 char *sql_statement;
7277 int ret;
7278 const char *f_table_name;
7279 const char *f_geometry_column;
7280 int i;
7281 char **results;
7282 int rows;
7283 int columns;
7284 int error = 0;
7285
7286 /* genuine Table-based Geometries */
7287 if (table == NULL && geometry == NULL)
7288 {
7289 /* processing any table/geometry found in GEOMETRY_COLUMNS */
7290 sql_statement =
7291 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7292 "FROM geometry_columns AS g "
7293 "LEFT JOIN layer_statistics AS s ON "
7294 "(g.f_table_name = s.table_name AND "
7295 "g.f_geometry_column = s.geometry_column) "
7296 "WHERE s.row_count IS NULL OR s.extent_min_x IS NULL "
7297 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7298 "OR s.extent_max_y IS NULL");
7299 }
7300 else if (geometry == NULL)
7301 {
7302 /* processing any geometry belonging to this table */
7303 sql_statement =
7304 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7305 "FROM geometry_columns AS g "
7306 "LEFT JOIN layer_statistics AS s ON "
7307 "(g.f_table_name = s.table_name AND "
7308 "g.f_geometry_column = s.geometry_column) "
7309 "WHERE Lower(g.f_table_name) = Lower(%Q) AND "
7310 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7311 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7312 "OR s.extent_max_y IS NULL)", table);
7313 }
7314 else
7315 {
7316 /* processing a single table/geometry entry */
7317 sql_statement =
7318 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7319 "FROM geometry_columns AS g "
7320 "LEFT JOIN layer_statistics AS s ON "
7321 "(g.f_table_name = s.table_name AND "
7322 "g.f_geometry_column = s.geometry_column) "
7323 "WHERE Lower(g.f_table_name) = Lower(%Q) AND "
7324 "Lower(g.f_geometry_column) = Lower(%Q) AND "
7325 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7326 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7327 "OR s.extent_max_y IS NULL)", table, geometry);
7328 }
7329 ret =
7330 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7331 NULL);
7332 sqlite3_free (sql_statement);
7333 if (ret != SQLITE_OK)
7334 return 0;
7335
7336 if (rows < 1)
7337 ;
7338 else
7339 {
7340 for (i = 1; i <= rows; i++)
7341 {
7342 f_table_name = results[(i * columns) + 0];
7343 f_geometry_column = results[(i * columns) + 1];
7344 if (!update_layer_statistics
7345 (handle, f_table_name, f_geometry_column))
7346 {
7347 error = 1;
7348 break;
7349 }
7350 }
7351 }
7352 sqlite3_free_table (results);
7353 if (error)
7354 return 0;
7355
7356 /* View Based Geometries */
7357 if (table == NULL && geometry == NULL)
7358 {
7359 /* processing any table/geometry found in GEOMETRY_COLUMNS */
7360 sql_statement =
7361 sqlite3_mprintf ("SELECT g.view_name, g.view_geometry "
7362 "FROM views_geometry_columns AS g "
7363 "LEFT JOIN views_layer_statistics AS s ON "
7364 "(g.view_name = s.view_name AND "
7365 "g.view_geometry = s.view_geometry) "
7366 "WHERE s.row_count IS NULL OR s.extent_min_x IS NULL "
7367 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7368 "OR s.extent_max_y IS NULL");
7369 }
7370 else if (geometry == NULL)
7371 {
7372 /* processing any geometry belonging to this table */
7373 sql_statement =
7374 sqlite3_mprintf ("SELECT g.view_name, g.view_geometry "
7375 "FROM views_geometry_columns AS g "
7376 "LEFT JOIN views_layer_statistics AS s ON "
7377 "(g.view_name = s.view_name AND "
7378 "g.view_geometry = s.view_geometry) "
7379 "WHERE Lower(g.view_name) = Lower(%Q) AND "
7380 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7381 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7382 "OR s.extent_max_y IS NULL)", table);
7383 }
7384 else
7385 {
7386 /* processing a single table/geometry entry */
7387 sql_statement =
7388 sqlite3_mprintf ("SELECT g.view_name, g.view_geometry "
7389 "FROM views_geometry_columns AS g "
7390 "LEFT JOIN views_layer_statistics AS s ON "
7391 "(g.view_name = s.view_name AND "
7392 "g.view_geometry = s.view_geometry) "
7393 "WHERE Lower(g.view_name) = Lower(%Q) AND "
7394 "Lower(g.view_geometry) = Lower(%Q) AND "
7395 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7396 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7397 "OR s.extent_max_y IS NULL)", table, geometry);
7398 }
7399 ret =
7400 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7401 NULL);
7402 sqlite3_free (sql_statement);
7403 if (ret != SQLITE_OK)
7404 return 0;
7405
7406 if (rows < 1)
7407 ;
7408 else
7409 {
7410 for (i = 1; i <= rows; i++)
7411 {
7412 f_table_name = results[(i * columns) + 0];
7413 f_geometry_column = results[(i * columns) + 1];
7414 if (!update_layer_statistics
7415 (handle, f_table_name, f_geometry_column))
7416 {
7417 error = 1;
7418 break;
7419 }
7420 }
7421 }
7422 sqlite3_free_table (results);
7423 if (error)
7424 return 0;
7425
7426 /* VirtualShape Based Geometries */
7427 if (table == NULL && geometry == NULL)
7428 {
7429 /* processing any table/geometry found in GEOMETRY_COLUMNS */
7430 sql_statement =
7431 sqlite3_mprintf ("SELECT g.virt_name, g.virt_geometry "
7432 "FROM virts_geometry_columns AS g "
7433 "LEFT JOIN virts_layer_statistics AS s ON "
7434 "(g.virt_name = s.virt_name AND "
7435 "g.virt_geometry = s.virt_geometry) "
7436 "WHERE s.row_count IS NULL OR s.extent_min_x IS NULL "
7437 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7438 "OR s.extent_max_y IS NULL");
7439 }
7440 else if (geometry == NULL)
7441 {
7442 /* processing any geometry belonging to this table */
7443 sql_statement =
7444 sqlite3_mprintf ("SELECT g.virt_name, g.virt_geometry "
7445 "FROM virts_geometry_columns AS g "
7446 "LEFT JOIN virts_layer_statistics AS s ON "
7447 "(g.virt_name = s.virt_name AND "
7448 "g.virt_geometry = s.virt_geometry) "
7449 "WHERE Lower(g.virt_name) = Lower(%Q) AND "
7450 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7451 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7452 "OR s.extent_max_y IS NULL)", table);
7453 }
7454 else
7455 {
7456 /* processing a single table/geometry entry */
7457 sql_statement =
7458 sqlite3_mprintf ("SELECT g.virt_name, g.virt_geometry "
7459 "FROM virts_geometry_columns AS g "
7460 "LEFT JOIN virts_layer_statistics AS s ON "
7461 "(g.virt_name = s.virt_name AND "
7462 "g.virt_geometry = s.virt_geometry) "
7463 "WHERE Lower(g.virt_name) = Lower(%Q) AND "
7464 "Lower(g.virt_geometry) = Lower(%Q) AND "
7465 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7466 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7467 "OR s.extent_max_y IS NULL)", table, geometry);
7468 }
7469 ret =
7470 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7471 NULL);
7472 sqlite3_free (sql_statement);
7473 if (ret != SQLITE_OK)
7474 return 0;
7475
7476 if (rows < 1)
7477 ;
7478 else
7479 {
7480 for (i = 1; i <= rows; i++)
7481 {
7482 f_table_name = results[(i * columns) + 0];
7483 f_geometry_column = results[(i * columns) + 1];
7484 if (!update_layer_statistics
7485 (handle, f_table_name, f_geometry_column))
7486 {
7487 error = 1;
7488 break;
7489 }
7490 }
7491 }
7492 sqlite3_free_table (results);
7493 if (error)
7494 return 0;
7495 return 1;
7496 }
7497
7498 static int
optimistic_layer_statistics_v2(sqlite3 * handle,const char * table,const char * geometry)7499 optimistic_layer_statistics_v2 (sqlite3 * handle, const char *table,
7500 const char *geometry)
7501 {
7502 /* selective statistics update - v.2.0.0 layout */
7503 char *sql_statement;
7504 int ret;
7505 const char *f_table_name;
7506 const char *f_geometry_column;
7507 int i;
7508 char **results;
7509 int rows;
7510 int columns;
7511 int error = 0;
7512
7513 /* genuine Table-based Geometries */
7514 if (table == NULL && geometry == NULL)
7515 {
7516 /* processing any table/geometry found in GEOMETRY_COLUMNS */
7517 sql_statement =
7518 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7519 "FROM geometry_columns AS g "
7520 "LEFT JOIN layer_statistics AS s ON "
7521 "(g.f_table_name = s.table_name AND "
7522 "g.f_geometry_column = s.geometry_column) "
7523 "WHERE s.row_count IS NULL OR s.extent_min_x IS NULL "
7524 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7525 "OR s.extent_max_y IS NULL");
7526 }
7527 else if (geometry == NULL)
7528 {
7529 /* processing any geometry belonging to this table */
7530 sql_statement =
7531 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7532 "FROM geometry_columns AS g "
7533 "LEFT JOIN layer_statistics AS s ON "
7534 "(g.f_table_name = s.table_name AND "
7535 "g.f_geometry_column = s.geometry_column) "
7536 "WHERE Lower(g.f_table_name) = Lower(%Q) AND "
7537 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7538 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7539 "OR s.extent_max_y IS NULL)", table);
7540 }
7541 else
7542 {
7543 /* processing a single table/geometry entry */
7544 sql_statement =
7545 sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column "
7546 "FROM geometry_columns AS g "
7547 "LEFT JOIN layer_statistics AS s ON "
7548 "(g.f_table_name = s.table_name AND "
7549 "g.f_geometry_column = s.geometry_column) "
7550 "WHERE Lower(g.f_table_name) = Lower(%Q) AND "
7551 "Lower(g.f_geometry_column) = Lower(%Q) AND "
7552 "(s.row_count IS NULL OR s.extent_min_x IS NULL "
7553 "OR s.extent_min_y IS NULL OR s.extent_max_y IS NULL "
7554 "OR s.extent_max_y IS NULL)", table, geometry);
7555 }
7556 ret =
7557 sqlite3_get_table (handle, sql_statement, &results, &rows, &columns,
7558 NULL);
7559 sqlite3_free (sql_statement);
7560 if (ret != SQLITE_OK)
7561 return 0;
7562
7563 if (rows < 1)
7564 ;
7565 else
7566 {
7567 for (i = 1; i <= rows; i++)
7568 {
7569 f_table_name = results[(i * columns) + 0];
7570 f_geometry_column = results[(i * columns) + 1];
7571 if (!update_layer_statistics
7572 (handle, f_table_name, f_geometry_column))
7573 {
7574 error = 1;
7575 break;
7576 }
7577 }
7578 }
7579 sqlite3_free_table (results);
7580 if (error)
7581 return 0;
7582 return 1;
7583 }
7584
7585 static int
optimistic_layer_statistics(sqlite3 * handle,const char * table,const char * geometry)7586 optimistic_layer_statistics (sqlite3 * handle, const char *table,
7587 const char *geometry)
7588 {
7589 /* selective statistics update */
7590 if (check_v4_statistics (handle))
7591 return optimistic_layer_statistics_v4 (handle, table, geometry);
7592 else if (check_v3_statistics (handle))
7593 return optimistic_layer_statistics_v3 (handle, table, geometry);
7594 else if (check_v2_statistics (handle))
7595 return optimistic_layer_statistics_v2 (handle, table, geometry);
7596 else
7597 return 0;
7598 }
7599
7600 SPATIALITE_DECLARE gaiaVectorLayersListPtr
gaiaGetVectorLayersList(sqlite3 * handle,const char * table,const char * geometry,int mode)7601 gaiaGetVectorLayersList (sqlite3 * handle, const char *table,
7602 const char *geometry, int mode)
7603 {
7604 /* creating a VectorLayersList object */
7605 gaiaVectorLayersListPtr list;
7606 int metadata_version;
7607
7608 if (mode == GAIA_VECTORS_LIST_PESSIMISTIC)
7609 {
7610 /* updating anyway the statistics before querying */
7611 if (!update_layer_statistics (handle, table, geometry))
7612 return NULL;
7613 }
7614 if (mode == GAIA_VECTORS_LIST_OPTIMISTIC)
7615 {
7616 /* selectively updating the statistics before querying */
7617 if (!optimistic_layer_statistics (handle, table, geometry))
7618 {
7619 /* failure: defaulting to Pessimistic */
7620 if (!update_layer_statistics (handle, table, geometry))
7621 return NULL;
7622 }
7623 }
7624
7625 /* allocating an empty VectorLayersList */
7626 list = malloc (sizeof (gaiaVectorLayersList));
7627 list->First = NULL;
7628 list->Last = NULL;
7629 list->Current = NULL;
7630
7631 metadata_version = checkSpatialMetaData (handle);
7632 if (metadata_version == 3)
7633 {
7634 /* current metadata style >= v.4.0.0 */
7635 if (!gaiaGetVectorLayersList_v4 (handle, table, geometry, list))
7636 {
7637 gaiaFreeVectorLayersList (list);
7638 return NULL;
7639 }
7640 if (list->First == NULL)
7641 {
7642 gaiaFreeVectorLayersList (list);
7643 return NULL;
7644 }
7645 return list;
7646 }
7647
7648 /* legacy metadata style <= v.3.x.x */
7649 if (!get_table_layers_legacy (handle, table, geometry, list))
7650 goto error;
7651 if (!get_view_layers_legacy (handle, table, geometry, list))
7652 goto error;
7653 if (!get_table_extent_legacy (handle, table, geometry, list))
7654 goto error;
7655 if (!get_view_extent_legacy (handle, table, geometry, list))
7656 goto error;
7657 if (!get_table_auth_legacy (handle, table, geometry, list))
7658 goto error;
7659 if (table != NULL && mode == GAIA_VECTORS_LIST_PESSIMISTIC)
7660 {
7661 if (!compute_table_fields_statistics (handle, table, geometry, list))
7662 goto error;
7663 }
7664
7665 if (list->First == NULL)
7666 {
7667 gaiaFreeVectorLayersList (list);
7668 return NULL;
7669 }
7670 return list;
7671
7672 error:
7673 gaiaFreeVectorLayersList (list);
7674 return NULL;
7675 }
7676
7677 SPATIALITE_DECLARE gaiaGeomCollPtr
gaiaGetLayerExtent(sqlite3 * handle,const char * table,const char * geometry,int mode)7678 gaiaGetLayerExtent (sqlite3 * handle, const char *table,
7679 const char *geometry, int mode)
7680 {
7681 /* attempting to get a Layer Full Extent (Envelope) */
7682 gaiaVectorLayersListPtr list;
7683 gaiaVectorLayerPtr lyr;
7684 double minx = -DBL_MAX;
7685 double miny = -DBL_MAX;
7686 double maxx = DBL_MAX;
7687 double maxy = DBL_MAX;
7688 int srid = 0;
7689 gaiaGeomCollPtr bbox;
7690 gaiaPolygonPtr polyg;
7691 gaiaRingPtr rect;
7692 int md = GAIA_VECTORS_LIST_OPTIMISTIC;
7693
7694 if (table == NULL)
7695 return NULL;
7696 if (mode)
7697 md = GAIA_VECTORS_LIST_PESSIMISTIC;
7698
7699 list = gaiaGetVectorLayersList (handle, table, geometry, md);
7700 if (list == NULL)
7701 return NULL;
7702 lyr = list->First;
7703 if (lyr == list->Last && lyr != NULL)
7704 {
7705 srid = lyr->Srid;
7706 if (lyr->ExtentInfos)
7707 {
7708 minx = lyr->ExtentInfos->MinX;
7709 miny = lyr->ExtentInfos->MinY;
7710 maxx = lyr->ExtentInfos->MaxX;
7711 maxy = lyr->ExtentInfos->MaxY;
7712 }
7713 }
7714 gaiaFreeVectorLayersList (list);
7715
7716 if (minx == -DBL_MIN || miny == -DBL_MAX || maxx == DBL_MAX
7717 || maxy == DBL_MAX)
7718 return NULL;
7719
7720 /* building the Envelope */
7721 bbox = gaiaAllocGeomColl ();
7722 bbox->Srid = srid;
7723 polyg = gaiaAddPolygonToGeomColl (bbox, 5, 0);
7724 rect = polyg->Exterior;
7725 gaiaSetPoint (rect->Coords, 0, minx, miny); /* vertex # 1 */
7726 gaiaSetPoint (rect->Coords, 1, maxx, miny); /* vertex # 2 */
7727 gaiaSetPoint (rect->Coords, 2, maxx, maxy); /* vertex # 3 */
7728 gaiaSetPoint (rect->Coords, 3, minx, maxy); /* vertex # 4 */
7729 gaiaSetPoint (rect->Coords, 4, minx, miny); /* vertex # 5 [same as vertex # 1 to close the polygon] */
7730 return bbox;
7731 }
7732
7733 SPATIALITE_DECLARE int
gaiaStatisticsInvalidate(sqlite3 * sqlite,const char * table,const char * geometry)7734 gaiaStatisticsInvalidate (sqlite3 * sqlite, const char *table,
7735 const char *geometry)
7736 {
7737 /* attempting to immediately and unconditionally invalidate Statistics */
7738 int metadata_version = checkSpatialMetaData (sqlite);
7739
7740 if (metadata_version == 3)
7741 {
7742 /* current metadata style >= v.4.0.0 */
7743 int ret;
7744 char *errMsg = NULL;
7745 char *sql_statement;
7746 if (table != NULL && geometry != NULL)
7747 sql_statement =
7748 sqlite3_mprintf ("UPDATE geometry_columns_time SET "
7749 "last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7750 "last_update = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7751 "last_delete = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now') "
7752 "WHERE Lower(f_table_name) = Lower(%Q) AND "
7753 "Lower(f_geometry_column) = Lower(%Q)",
7754 table, geometry);
7755 else if (table != NULL)
7756 sql_statement =
7757 sqlite3_mprintf ("UPDATE geometry_columns_time SET "
7758 "last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7759 "last_update = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7760 "last_delete = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now') "
7761 "WHERE Lower(f_table_name) = Lower(%Q)",
7762 table);
7763 else
7764 sql_statement =
7765 sqlite3_mprintf ("UPDATE geometry_columns_time SET "
7766 "last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7767 "last_update = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now'), "
7768 "last_delete = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now')");
7769 ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7770 sqlite3_free (sql_statement);
7771 if (ret != SQLITE_OK)
7772 {
7773 spatialite_e ("SQL error: %s: %s\n", sql_statement, errMsg);
7774 sqlite3_free (errMsg);
7775 return 0;
7776 }
7777 return 1;
7778 }
7779 else
7780 return 0;
7781 }
7782
7783 static int
rtree_bbox_callback(sqlite3_rtree_query_info * info)7784 rtree_bbox_callback (sqlite3_rtree_query_info * info)
7785 {
7786 /*
7787
7788 R*Tree Query Callback function
7789
7790 ----------------------------------------------------------
7791
7792 this function will evaluate all first-level R*Tree Nodes
7793 (direct children of the Root Node) so to get the Full
7794 Extent of the R*Tree as a whole.
7795
7796 further descending in the Tree's hierarchy will be
7797 carefully avoided, so to ensure that also in the case
7798 of an R*Tree containing many million entries just few
7799 dozens of top level Nodes will require to be evaluated.
7800
7801 */
7802 double minx;
7803 double maxx;
7804 double miny;
7805 double maxy;
7806 struct rtree_envelope *data = (struct rtree_envelope *) (info->pContext);
7807 if (info->nCoord != 4)
7808 {
7809 /* invalid RTree; not 2D */
7810 goto end;
7811 }
7812
7813 /* fetching the Node's BBOX */
7814 minx = info->aCoord[0];
7815 maxx = info->aCoord[1];
7816 miny = info->aCoord[2];
7817 maxy = info->aCoord[3];
7818
7819 /* updating the Full Extent BBOX */
7820 if (data->valid == 0)
7821 {
7822 /* first Node retrieved */
7823 data->valid = 1;
7824 data->minx = minx;
7825 data->maxx = maxx;
7826 data->miny = miny;
7827 data->maxy = maxy;
7828 }
7829 else
7830 {
7831 /* any other further Node */
7832 if (minx < data->minx)
7833 data->minx = minx;
7834 if (maxx > data->maxx)
7835 data->maxx = maxx;
7836 if (miny < data->miny)
7837 data->miny = miny;
7838 if (maxy > data->maxy)
7839 data->maxy = maxy;
7840 }
7841
7842 end:
7843 /* setting NOT_WITHIN so to stop further descending into the tree */
7844 info->eWithin = NOT_WITHIN;
7845 return SQLITE_OK;
7846 }
7847
7848 SPATIALITE_DECLARE gaiaGeomCollPtr
gaiaGetRTreeFullExtent(sqlite3 * db_handle,const char * db_prefix,const char * name,int srid)7849 gaiaGetRTreeFullExtent (sqlite3 * db_handle, const char *db_prefix,
7850 const char *name, int srid)
7851 {
7852 /* Will attempt to retrieve the Full Extent from an R*Tree - SpatiaLite */
7853 char *sql;
7854 int ret;
7855 char *xprefix;
7856 char *xname;
7857 gaiaGeomCollPtr envelope;
7858 gaiaPolygonPtr polyg;
7859 gaiaRingPtr rect;
7860 struct rtree_envelope data;
7861
7862 data.valid = 0;
7863
7864 /* registering the Geometry Query Callback SQL function */
7865 sqlite3_rtree_query_callback (db_handle, "rtree_bbox",
7866 rtree_bbox_callback, &data, NULL);
7867
7868 /* executing the SQL Query statement */
7869 xprefix = gaiaDoubleQuotedSql (db_prefix);
7870 xname = gaiaDoubleQuotedSql (name);
7871 sql =
7872 sqlite3_mprintf
7873 ("SELECT pkid FROM \"%s\".\"%s\" WHERE pkid MATCH rtree_bbox(1)",
7874 xprefix, xname);
7875 free (xprefix);
7876 free (xname);
7877 ret = sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
7878 sqlite3_free (sql);
7879 if (ret != SQLITE_OK)
7880 return NULL;
7881 if (data.valid == 0)
7882 return NULL;
7883
7884 /* building the Envelope of the R*Tree */
7885 envelope = gaiaAllocGeomColl ();
7886 envelope->Srid = srid;
7887 polyg = gaiaAddPolygonToGeomColl (envelope, 5, 0);
7888 rect = polyg->Exterior;
7889 gaiaSetPoint (rect->Coords, 0, data.minx, data.miny); /* vertex # 1 */
7890 gaiaSetPoint (rect->Coords, 1, data.maxx, data.miny); /* vertex # 2 */
7891 gaiaSetPoint (rect->Coords, 2, data.maxx, data.maxy); /* vertex # 3 */
7892 gaiaSetPoint (rect->Coords, 3, data.minx, data.maxy); /* vertex # 4 */
7893 gaiaSetPoint (rect->Coords, 4, data.minx, data.miny); /* vertex # 5 [same as vertex # 1 to close the polygon] */
7894 return envelope;
7895 }
7896
7897 SPATIALITE_DECLARE gaiaGeomCollPtr
gaiaGetGpkgRTreeFullExtent(sqlite3 * db_handle,const char * db_prefix,const char * name,int srid)7898 gaiaGetGpkgRTreeFullExtent (sqlite3 * db_handle, const char *db_prefix,
7899 const char *name, int srid)
7900 {
7901 /* Will attempt to retrieve the Full Extent from an R*Tree - GeoPacage */
7902 char *sql;
7903 int ret;
7904 char *xprefix;
7905 char *xname;
7906 gaiaGeomCollPtr envelope;
7907 gaiaPolygonPtr polyg;
7908 gaiaRingPtr rect;
7909 struct rtree_envelope data;
7910
7911 data.valid = 0;
7912
7913 /* registering the Geometry Query Callback SQL function */
7914 sqlite3_rtree_query_callback (db_handle, "rtree_bbox",
7915 rtree_bbox_callback, &data, NULL);
7916
7917 /* executing the SQL Query statement */
7918 xprefix = gaiaDoubleQuotedSql (db_prefix);
7919 xname = gaiaDoubleQuotedSql (name);
7920 sql =
7921 sqlite3_mprintf
7922 ("SELECT id FROM \"%s\".\"%s\" WHERE id MATCH rtree_bbox(1)",
7923 xprefix, xname);
7924 free (xprefix);
7925 free (xname);
7926 ret = sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
7927 sqlite3_free (sql);
7928 if (ret != SQLITE_OK)
7929 return NULL;
7930 if (data.valid == 0)
7931 return NULL;
7932
7933 /* building the Envelope of the R*Tree */
7934 envelope = gaiaAllocGeomColl ();
7935 envelope->Srid = srid;
7936 polyg = gaiaAddPolygonToGeomColl (envelope, 5, 0);
7937 rect = polyg->Exterior;
7938 gaiaSetPoint (rect->Coords, 0, data.minx, data.miny); /* vertex # 1 */
7939 gaiaSetPoint (rect->Coords, 1, data.maxx, data.miny); /* vertex # 2 */
7940 gaiaSetPoint (rect->Coords, 2, data.maxx, data.maxy); /* vertex # 3 */
7941 gaiaSetPoint (rect->Coords, 3, data.minx, data.maxy); /* vertex # 4 */
7942 gaiaSetPoint (rect->Coords, 4, data.minx, data.miny); /* vertex # 5 [same as vertex # 1 to close the polygon] */
7943 return envelope;
7944 }
7945