1 /*
2 
3  spatialite.c -- SQLite3 spatial extension
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 
36 Alternatively, the contents of this file may be used under the terms of
37 either the GNU General Public License Version 2 or later (the "GPL"), or
38 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
39 in which case the provisions of the GPL or the LGPL are applicable instead
40 of those above. If you wish to allow use of your version of this file only
41 under the terms of either the GPL or the LGPL, and not to allow others to
42 use your version of this file under the terms of the MPL, indicate your
43 decision by deleting the provisions above and replace them with the notice
44 and other provisions required by the GPL or the LGPL. If you do not delete
45 the provisions above, a recipient may use your version of this file under
46 the terms of any one of the MPL, the GPL or the LGPL.
47 
48 */
49 
50 /*
51 
52 CREDITS:
53 
54 this module has been partly funded by:
55 Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
56 (exposing liblwgeom APIs as SpatiaLite own SQL functions)
57 
58 */
59 
60 #include <sys/types.h>
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include <string.h>
64 #include <math.h>
65 #include <float.h>
66 #include <locale.h>
67 
68 #if defined(_WIN32) && !defined(__MINGW32__)
69 #include <io.h>
70 #include <direct.h>
71 #else
72 #include <dirent.h>
73 #endif
74 
75 #if defined(_WIN32) && !defined(__MINGW32__)
76 #include "config-msvc.h"
77 #else
78 #include "config.h"
79 #endif
80 
81 #if defined(_WIN32) || defined(WIN32)
82 #include <io.h>
83 #define isatty	_isatty
84 #else
85 #include <unistd.h>
86 #endif
87 
88 
89 #include <spatialite/sqlite.h>
90 #include <spatialite/debug.h>
91 
92 #include <spatialite/gaiaaux.h>
93 #include <spatialite/gaiageo.h>
94 #include <spatialite/gaiaexif.h>
95 #include <spatialite/geopackage.h>
96 #include <spatialite/spatialite_ext.h>
97 #include <spatialite/gg_advanced.h>
98 #include <spatialite/gg_dxf.h>
99 #include <spatialite/gaiamatrix.h>
100 #include <spatialite/geopackage.h>
101 #include <spatialite/control_points.h>
102 #include <spatialite/stored_procedures.h>
103 #include <spatialite.h>
104 #include <spatialite_private.h>
105 
106 #ifdef ENABLE_LIBXML2		/* LIBXML2 (and thus WFS) enabled */
107 #include <spatialite/gg_wfs.h>
108 #endif
109 
110 #ifndef OMIT_FREEXL		/* including FreeXL */
111 #include <freexl.h>
112 #endif
113 
114 #ifndef OMIT_GEOS		/* including GEOS */
115 #ifdef GEOS_REENTRANT
116 #ifdef GEOS_ONLY_REENTRANT
117 #define GEOS_USE_ONLY_R_API	/* only fully thread-safe GEOS API */
118 #endif
119 #endif
120 #include <geos_c.h>
121 #endif
122 
123 #ifndef OMIT_PROJ		/* including PROJ.4 */
124 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
125 #include <proj.h>
126 #else /* supporting old PROJ.4 */
127 #include <proj_api.h>
128 #endif
129 #endif
130 
131 #ifdef _WIN32
132 #define strcasecmp	_stricmp
133 #endif /* not WIN32 */
134 
135 /* 64 bit integer: portable format for printf() */
136 #if defined(_WIN32) && !defined(__MINGW32__)
137 #define FRMT64 "%I64d"
138 #else
139 #define FRMT64 "%lld"
140 #endif
141 
142 #define GAIA_UNUSED() if (argc || argv) argc = argc;
143 
144 #define LINESTRING_MIN_SEGMENT_LENGTH	1
145 #define LINESTRING_MAX_SEGMENT_LENGTH	2
146 #define LINESTRING_AVG_SEGMENT_LENGTH	3
147 
148 struct gaia_geom_chain_item
149 {
150 /* a struct used to store a chain item */
151     gaiaGeomCollPtr geom;
152     struct gaia_geom_chain_item *next;
153 };
154 
155 struct gaia_geom_chain
156 {
157 /* a struct used to store a dynamic chain of GeometryCollections */
158     int all_polygs;
159     struct gaia_geom_chain_item *first;
160     struct gaia_geom_chain_item *last;
161 };
162 
163 #ifndef OMIT_GEOCALLBACKS	/* supporting RTree geometry callbacks */
164 struct gaia_rtree_mbr
165 {
166 /* a struct used by R*Tree GeometryCallback functions [MBR] */
167     double minx;
168     double miny;
169     double maxx;
170     double maxy;
171 };
172 #endif /* end RTree geometry callbacks */
173 
174 struct stddev_str
175 {
176 /* a struct to implement StandardVariation and Variance aggregate functions */
177     int cleaned;
178     double mean;
179     double quot;
180     double count;
181 };
182 
183 struct string_list_str
184 {
185 /* a struct supporting MakeStringList aggregate function */
186     char *string;
187     char separator;
188 };
189 
190 struct fdo_table
191 {
192 /* a struct to implement a linked-list for FDO-ORG table names */
193     char *table;
194     struct fdo_table *next;
195 };
196 
197 struct gpkg_table
198 {
199 /* a struct to implement a linked-list for OGC GeoPackage table names */
200     char *table;
201     struct gpkg_table *next;
202 };
203 
204 
205 /*
206 ************************************************************************
207 **
208 ** the following code has been integrally copied from SQLite's own sources:
209 ** -/ext/misc/eval.c
210 */
211 
212 /*
213 ** 2014-11-10
214 **
215 ** The author disclaims copyright to this source code.  In place of
216 ** a legal notice, here is a blessing:
217 **
218 **    May you do good and not evil.
219 **    May you find forgiveness for yourself and forgive others.
220 **    May you share freely, never taking more than you give.
221 **
222 ******************************************************************************
223 **
224 ** This SQLite extension implements SQL function eval() which runs
225 ** SQL statements recursively.
226 */
227 
228 struct EvalResult
229 {
230 /*
231 ** Structure used to accumulate the output
232 */
233     char *z;			/* Accumulated output */
234     const char *zSep;		/* Separator */
235     int szSep;			/* Size of the separator string */
236     unsigned int nAlloc;	/* Number of bytes allocated for z[] */
237     int nUsed;			/* Number of bytes of z[] actually used */
238 };
239 
240 static int
eval_callback(void * pCtx,int argc,char ** argv,char ** colnames)241 eval_callback (void *pCtx, int argc, char **argv, char **colnames)
242 {
243 /*
244 ** Callback from sqlite_exec() for the eval() function.
245 */
246     struct EvalResult *p = (struct EvalResult *) pCtx;
247     int i;
248 
249     if (colnames == NULL)
250 	colnames = NULL;	/* silencing stupid compiler warnings */
251 
252     for (i = 0; i < argc; i++)
253       {
254 	  const char *z = argv[i] ? argv[i] : "";
255 	  size_t sz = strlen (z);
256 	  if (sz + p->nUsed + p->szSep + 1 > p->nAlloc)
257 	    {
258 		char *zNew;
259 		p->nAlloc = p->nAlloc * 2 + sz + p->szSep + 1;
260 		zNew = sqlite3_realloc (p->z, p->nAlloc);
261 		if (zNew == 0)
262 		  {
263 		      sqlite3_free (p->z);
264 		      memset (p, 0, sizeof (*p));
265 		      return 1;
266 		  }
267 		p->z = zNew;
268 	    }
269 	  if (p->nUsed > 0)
270 	    {
271 		memcpy (&p->z[p->nUsed], p->zSep, p->szSep);
272 		p->nUsed += p->szSep;
273 	    }
274 	  memcpy (&p->z[p->nUsed], z, sz);
275 	  p->nUsed += sz;
276       }
277     return 0;
278 }
279 
280 static void
fnct_EvalFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)281 fnct_EvalFunc (sqlite3_context * context, int argc, sqlite3_value ** argv)
282 {
283 /*
284 ** Implementation of the eval(X) and eval(X,Y) SQL functions.
285 **
286 ** Evaluate the SQL text in X.  Return the results, using string
287 ** Y as the separator.  If Y is omitted, use a single space character.
288 */
289     const char *zSql;
290     sqlite3 *db;
291     char *zErr = 0;
292     int rc;
293     struct EvalResult x;
294 
295     memset (&x, 0, sizeof (x));
296     x.zSep = " ";
297     zSql = (const char *) sqlite3_value_text (argv[0]);
298     if (zSql == 0)
299 	return;
300     if (argc > 1)
301       {
302 	  x.zSep = (const char *) sqlite3_value_text (argv[1]);
303 	  if (x.zSep == 0)
304 	      return;
305       }
306     x.szSep = (int) strlen (x.zSep);
307     db = sqlite3_context_db_handle (context);
308     rc = sqlite3_exec (db, zSql, eval_callback, &x, &zErr);
309     if (rc != SQLITE_OK)
310       {
311 	  sqlite3_result_error (context, zErr, -1);
312 	  sqlite3_free (zErr);
313       }
314     else if (x.zSep == 0)
315       {
316 	  sqlite3_result_error_nomem (context);
317 	  sqlite3_free (x.z);
318       }
319     else
320       {
321 	  sqlite3_result_text (context, x.z, x.nUsed, sqlite3_free);
322       }
323 }
324 
325 static void
fnct_createMissingSystemTables(sqlite3_context * context,int argc,sqlite3_value ** argv)326 fnct_createMissingSystemTables (sqlite3_context * context, int argc,
327 				sqlite3_value ** argv)
328 {
329 /* SQL function:
330 / CreateMissingSystemTables()
331 /  or
332 / CreateMissingSystemTables(bool relaxed)
333 /  or
334 / CreateMissingSystemTables(bool relaxed, bool transaction)
335 /
336 / creates all missing system tables required by version 5
337 / returns 1 on success
338 / RAISES AN EXCEPTION on failure or on invalid arguments
339 */
340     int relaxed = 0;
341     int transaction = 0;
342     int ret;
343     char *err_msg = NULL;
344     char *msg = NULL;
345     sqlite3 *sqlite = sqlite3_context_db_handle (context);
346     struct splite_internal_cache *cache = sqlite3_user_data (context);
347     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
348     if (argc >= 1)
349       {
350 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
351 	      goto invalid_arg1;
352 	  relaxed = sqlite3_value_int (argv[0]);
353       }
354     if (argc >= 2)
355       {
356 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
357 	      goto invalid_arg2;
358 	  transaction = sqlite3_value_int (argv[1]);
359       }
360 
361     ret =
362 	createMissingSystemTables (sqlite, cache, relaxed, transaction,
363 				   &err_msg);
364     if (ret <= 0)
365 	goto error;
366     msg =
367 	sqlite3_mprintf ("successfully executed (%d Table%s been created)", ret,
368 			 (ret == 1) ? " has" : "s have");
369     updateSpatiaLiteHistory (sqlite, "*** CreateMissingSystemTables ***", NULL,
370 			     msg);
371     sqlite3_free (msg);
372     sqlite3_result_int (context, ret);
373     return;
374 
375   invalid_arg1:
376     msg =
377 	"CreateMissingSystemTables exception - first argument (relaxed) expected to be an INTEGER.";
378     sqlite3_result_error (context, msg, -1);
379     return;
380 
381   invalid_arg2:
382     msg =
383 	"CreateMissingSystemTables exception - second argument (transaction) expected to be an INTEGER.";
384     sqlite3_result_error (context, msg, -1);
385     return;
386 
387   error:
388     if (err_msg == NULL)
389 	msg =
390 	    sqlite3_mprintf
391 	    ("CreateMissingSystemTables exception - Unknown failure reason.");
392     else
393       {
394 	  msg =
395 	      sqlite3_mprintf ("CreateMissingSystemTables exception - %s.",
396 			       err_msg);
397 	  sqlite3_free (err_msg);
398       }
399     sqlite3_result_error (context, msg, -1);
400     sqlite3_free (msg);
401     return;
402 }
403 
404 static void
fnct_spatialite_version(sqlite3_context * context,int argc,sqlite3_value ** argv)405 fnct_spatialite_version (sqlite3_context * context, int argc,
406 			 sqlite3_value ** argv)
407 {
408 /* SQL function:
409 / spatialite_version()
410 /
411 / return a text string representing the current SpatiaLite version
412 */
413     int len;
414     const char *p_result = spatialite_version ();
415     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
416     len = strlen (p_result);
417     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
418 }
419 
420 static int
do_check_dqs(sqlite3 * sqlite)421 do_check_dqs (sqlite3 * sqlite)
422 {
423 /* checking if SQLite supports the DQS misfeature */
424     char *sql;
425     int ret;
426     int ok = 1;
427     unsigned char rnd[16];
428     char random[40];
429     char *p = random;
430     int i;
431     char *table;
432 
433     sqlite3_randomness (16, rnd);
434     for (i = 0; i < 16; i++)
435       {
436 	  sprintf (p, "%02x", rnd[i]);
437 	  p += 2;
438       }
439     *p = '\0';
440     table = sqlite3_mprintf ("tmp_%s", random);
441 
442 /* NOTE: the following SQL statements are INTENTIONALLY badly quoted */
443     sql = sqlite3_mprintf ("CREATE TEMPORARY TABLE %Q ('column' TEXT)", table);
444     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
445     sqlite3_free (sql);
446     if (ret != SQLITE_OK)
447       {
448 	  ok = 0;
449 	  goto stop;
450       }
451 
452     sql = sqlite3_mprintf ("INSERT INTO %Q ('column') VALUES (\"one\")", table);
453     ret = sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
454     sqlite3_free (sql);
455     if (ret != SQLITE_OK)
456       {
457 	  ok = 0;
458 	  goto stop;
459       }
460 
461   stop:
462     sql = sqlite3_mprintf ("DROP TABLE IF EXISTS %Q", table);
463     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
464     sqlite3_free (table);
465     return ok;
466 }
467 
468 static void
fnct_check_strict_sql_quoting(sqlite3_context * context,int argc,sqlite3_value ** argv)469 fnct_check_strict_sql_quoting (sqlite3_context * context, int argc,
470 			       sqlite3_value ** argv)
471 {
472 /* SQL function:
473 / check_strict_sql_quoting()
474 /
475 / return TRUE of FALSE depending on SQLite3 supporting the DQS misfeature or not
476 */
477     int ret;
478     sqlite3 *sqlite = sqlite3_context_db_handle (context);
479     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
480     ret = do_check_dqs (sqlite);
481     if (ret == 0)
482 	sqlite3_result_int (context, 1);
483     else
484 	sqlite3_result_int (context, 0);
485 }
486 
487 static void
fnct_spatialite_target_cpu(sqlite3_context * context,int argc,sqlite3_value ** argv)488 fnct_spatialite_target_cpu (sqlite3_context * context, int argc,
489 			    sqlite3_value ** argv)
490 {
491 /* SQL function:
492 / spatialite_target_cpu()
493 /
494 / return a text string representing the current SpatiaLite Target CPU
495 */
496     int len;
497     const char *p_result = spatialite_target_cpu ();
498     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
499     len = strlen (p_result);
500     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
501 }
502 
503 static void
fnct_freexl_version(sqlite3_context * context,int argc,sqlite3_value ** argv)504 fnct_freexl_version (sqlite3_context * context, int argc, sqlite3_value ** argv)
505 {
506 /* SQL function:
507 / freexl_version()
508 /
509 / return a text string representing the current FreeXL version
510 / or NULL if FreeXL is currently unsupported
511 */
512 
513 #ifndef OMIT_FREEXL		/* FreeXL version */
514     int len;
515     const char *p_result = freexl_version ();
516     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
517     len = strlen (p_result);
518     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
519 #else
520     sqlite3_result_null (context);
521 #endif
522 }
523 
524 static void
fnct_geos_version(sqlite3_context * context,int argc,sqlite3_value ** argv)525 fnct_geos_version (sqlite3_context * context, int argc, sqlite3_value ** argv)
526 {
527 /* SQL function:
528 / geos_version()
529 /
530 / return a text string representing the current GEOS version
531 / or NULL if GEOS is currently unsupported
532 */
533 
534 #ifndef OMIT_GEOS		/* GEOS version */
535     int len;
536     const char *p_result = GEOSversion ();
537     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
538     len = strlen (p_result);
539     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
540 #else
541     sqlite3_result_null (context);
542 #endif
543 }
544 
545 static void
fnct_proj4_version(sqlite3_context * context,int argc,sqlite3_value ** argv)546 fnct_proj4_version (sqlite3_context * context, int argc, sqlite3_value ** argv)
547 {
548 /* SQL function:
549 / proj4_version()
550 / proj_version()
551 /
552 / return a text string representing the current PROJ.4 version
553 / or NULL if PROJ.4 is currently unsupported
554 */
555 
556 #ifndef OMIT_PROJ		/* PROJ.4 version */
557     int len;
558     const char *p_result;
559 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
560     PJ_INFO info = proj_info ();
561     p_result = info.release;
562 #else /* supporting old PROJ.4 */
563     p_result = pj_get_release ();
564 #endif
565     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
566     len = strlen (p_result);
567     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
568 #else
569     sqlite3_result_null (context);
570 #endif
571 }
572 
573 static void
fnct_has_proj(sqlite3_context * context,int argc,sqlite3_value ** argv)574 fnct_has_proj (sqlite3_context * context, int argc, sqlite3_value ** argv)
575 {
576 /* SQL function:
577 / HasProj()
578 /
579 / return 1 if built including Proj.4; otherwise 0
580 */
581     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
582 #ifndef OMIT_PROJ
583 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
584     sqlite3_result_int (context, 1);
585 #else /* supporting old PROJ.4 */
586 #if defined(PJ_VERSION) && PJ_VERSION >= 490
587     sqlite3_result_int (context, 1);
588 #else
589     sqlite3_result_int (context, 0);
590 #endif
591 #endif
592 #else
593     sqlite3_result_int (context, 0);
594 #endif
595 }
596 
597 static void
fnct_has_proj6(sqlite3_context * context,int argc,sqlite3_value ** argv)598 fnct_has_proj6 (sqlite3_context * context, int argc, sqlite3_value ** argv)
599 {
600 /* SQL function:
601 / HasProj6()
602 /
603 / return 1 if built including Proj.6; otherwise 0
604 */
605     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
606 #ifndef OMIT_PROJ
607 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
608     sqlite3_result_int (context, 1);
609 #endif
610 #endif
611     sqlite3_result_int (context, 0);
612 }
613 
614 static void
fnct_has_proj_geodesic(sqlite3_context * context,int argc,sqlite3_value ** argv)615 fnct_has_proj_geodesic (sqlite3_context * context, int argc,
616 			sqlite3_value ** argv)
617 {
618 /* SQL function:
619 / HasProjGeodesic()
620 /
621 / return 1 if built supporting Proj.4 Geodesic; otherwise 0
622 */
623     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
624 #ifndef OMIT_PROJ		/* PROJ.4 is supported */
625     sqlite3_result_int (context, 1);
626 #else
627     sqlite3_result_int (context, 0);
628 #endif
629 }
630 
631 static void
fnct_has_geos(sqlite3_context * context,int argc,sqlite3_value ** argv)632 fnct_has_geos (sqlite3_context * context, int argc, sqlite3_value ** argv)
633 {
634 /* SQL function:
635 / HasGeos()
636 /
637 / return 1 if built including GEOS; otherwise 0
638 */
639     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
640 #ifndef OMIT_GEOS		/* GEOS is supported */
641     sqlite3_result_int (context, 1);
642 #else
643     sqlite3_result_int (context, 0);
644 #endif
645 }
646 
647 static void
fnct_has_geos_advanced(sqlite3_context * context,int argc,sqlite3_value ** argv)648 fnct_has_geos_advanced (sqlite3_context * context, int argc,
649 			sqlite3_value ** argv)
650 {
651 /* SQL function:
652 / HasGeosAdvanced()
653 /
654 / return 1 if built including GEOS-ADVANCED; otherwise 0
655 */
656     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
657 #ifdef GEOS_ADVANCED		/* GEOS-ADVANCED is supported */
658     sqlite3_result_int (context, 1);
659 #else
660     sqlite3_result_int (context, 0);
661 #endif
662 }
663 
664 static void
fnct_has_geos_trunk(sqlite3_context * context,int argc,sqlite3_value ** argv)665 fnct_has_geos_trunk (sqlite3_context * context, int argc, sqlite3_value ** argv)
666 {
667 /* SQL function:
668 / HasGeosTrunk()
669 /
670 / return 1 if built including GEOS-TRUNK; otherwise 0
671 */
672     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
673     sqlite3_result_int (context, 0);
674 }
675 
676 static void
fnct_has_geos_reentrant(sqlite3_context * context,int argc,sqlite3_value ** argv)677 fnct_has_geos_reentrant (sqlite3_context * context, int argc,
678 			 sqlite3_value ** argv)
679 {
680 /* SQL function:
681 / HasGeosReentrant()
682 /
683 / return 1 if built including GEOS-REENTRANT; otherwise 0
684 */
685     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
686 #ifdef GEOS_REENTRANT		/* GEOS-REENTRANT is supported */
687     sqlite3_result_int (context, 1);
688 #else
689     sqlite3_result_int (context, 0);
690 #endif
691 }
692 
693 static void
fnct_has_geos_only_reentrant(sqlite3_context * context,int argc,sqlite3_value ** argv)694 fnct_has_geos_only_reentrant (sqlite3_context * context, int argc,
695 			      sqlite3_value ** argv)
696 {
697 /* SQL function:
698 / HasGeosOnlyReentrant()
699 /
700 / return 1 if built including GEOS-ONLY_REENTRANT; otherwise 0
701 */
702     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
703 #ifdef GEOS_REENTRANT		/* GEOS-REENTRANT is supported */
704 #ifdef GEOS_ONLY_REENTRANT	/* GEOS-ONLY-REENTRANT is supported */
705     sqlite3_result_int (context, 1);
706 #else
707     sqlite3_result_int (context, 0);
708 #endif
709 #else
710     sqlite3_result_int (context, 0);
711 #endif
712 }
713 
714 static void
fnct_has_minizip(sqlite3_context * context,int argc,sqlite3_value ** argv)715 fnct_has_minizip (sqlite3_context * context, int argc, sqlite3_value ** argv)
716 {
717 /* SQL function:
718 / HasMiniZip()
719 /
720 / return 1 if built including MINIZIP; otherwise 0
721 */
722     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
723 #ifdef ENABLE_MINIZIP		/* MINIZIP is supported */
724     sqlite3_result_int (context, 1);
725 #else
726     sqlite3_result_int (context, 0);
727 #endif
728 }
729 
730 static void
fnct_rttopo_version(sqlite3_context * context,int argc,sqlite3_value ** argv)731 fnct_rttopo_version (sqlite3_context * context, int argc, sqlite3_value ** argv)
732 {
733 /* SQL function:
734 / rttopo_version()
735 /
736 / return a text string representing the current RTTOPO version
737 / or NULL if RTTOPO is currently unsupported
738 */
739 
740 #ifdef ENABLE_RTTOPO		/* RTTOPO version */
741     int len;
742     const char *p_result = splite_rttopo_version ();
743     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
744     len = strlen (p_result);
745     sqlite3_result_text (context, p_result, len, SQLITE_TRANSIENT);
746 #else
747     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
748     sqlite3_result_null (context);
749 #endif
750 }
751 
752 static void
fnct_libxml2_version(sqlite3_context * context,int argc,sqlite3_value ** argv)753 fnct_libxml2_version (sqlite3_context * context, int argc,
754 		      sqlite3_value ** argv)
755 {
756 /* SQL function:
757 / libxml2_version()
758 /
759 / return a text string representing the current LIBXML2 version
760 / or NULL if LIBXML2 is currently unsupported
761 */
762 
763 #ifdef ENABLE_LIBXML2		/* LIBXML2 version */
764     int len;
765     const char *p_result = gaia_libxml2_version ();
766     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
767     len = strlen (p_result);
768     sqlite3_result_text (context, p_result, len, free);
769 #else
770     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
771     sqlite3_result_null (context);
772 #endif
773 }
774 
775 static void
fnct_has_rttopo(sqlite3_context * context,int argc,sqlite3_value ** argv)776 fnct_has_rttopo (sqlite3_context * context, int argc, sqlite3_value ** argv)
777 {
778 /* SQL function:
779 / HasRtTopo()
780 /
781 / return 1 if built including RTTOPO; otherwise 0
782 */
783     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
784 #ifdef ENABLE_RTTOPO		/* RTTOPO is supported */
785     sqlite3_result_int (context, 1);
786 #else
787     sqlite3_result_int (context, 0);
788 #endif
789 }
790 
791 static void
fnct_has_iconv(sqlite3_context * context,int argc,sqlite3_value ** argv)792 fnct_has_iconv (sqlite3_context * context, int argc, sqlite3_value ** argv)
793 {
794 /* SQL function:
795 / HasIconv()
796 /
797 / return 1 if built including ICONV; otherwise 0
798 */
799     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
800 #ifndef OMIT_ICONV		/* ICONV is supported */
801     sqlite3_result_int (context, 1);
802 #else
803     sqlite3_result_int (context, 0);
804 #endif
805 }
806 
807 static void
fnct_has_math_sql(sqlite3_context * context,int argc,sqlite3_value ** argv)808 fnct_has_math_sql (sqlite3_context * context, int argc, sqlite3_value ** argv)
809 {
810 /* SQL function:
811 / HasMathSql()
812 /
813 / return 1 if built including MATHSQL; otherwise 0
814 */
815     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
816 #ifndef OMIT_MATHSQL		/* MATHSQL is supported */
817     sqlite3_result_int (context, 1);
818 #else
819     sqlite3_result_int (context, 0);
820 #endif
821 }
822 
823 static void
fnct_has_geo_callbacks(sqlite3_context * context,int argc,sqlite3_value ** argv)824 fnct_has_geo_callbacks (sqlite3_context * context, int argc,
825 			sqlite3_value ** argv)
826 {
827 /* SQL function:
828 / HasGeoCallbacks()
829 /
830 / return 1 if built enabling GEOCALLBACKS; otherwise 0
831 */
832     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
833 #ifndef OMIT_GEOCALLBACKS	/* GEO-CALLBACKS are supported */
834     sqlite3_result_int (context, 1);
835 #else
836     sqlite3_result_int (context, 0);
837 #endif
838 }
839 
840 static void
fnct_has_freeXL(sqlite3_context * context,int argc,sqlite3_value ** argv)841 fnct_has_freeXL (sqlite3_context * context, int argc, sqlite3_value ** argv)
842 {
843 /* SQL function:
844 / HasFreeXL()
845 /
846 / return 1 if built including FreeXL; otherwise 0
847 */
848     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
849 #ifndef OMIT_FREEXL		/* FreeXL is supported */
850     sqlite3_result_int (context, 1);
851 #else
852     sqlite3_result_int (context, 0);
853 #endif
854 }
855 
856 static void
fnct_has_epsg(sqlite3_context * context,int argc,sqlite3_value ** argv)857 fnct_has_epsg (sqlite3_context * context, int argc, sqlite3_value ** argv)
858 {
859 /* SQL function:
860 / HasEpsg()
861 /
862 / return 1 if built including EPSG; otherwise 0
863 */
864     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
865 #ifndef OMIT_EPSG		/* EPSG is supported */
866     sqlite3_result_int (context, 1);
867 #else
868     sqlite3_result_int (context, 0);
869 #endif
870 }
871 
872 static void
fnct_has_libxml2(sqlite3_context * context,int argc,sqlite3_value ** argv)873 fnct_has_libxml2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
874 {
875 /* SQL function:
876 / HasLibXML2()
877 /
878 / return 1 if built including LIBXML2; otherwise 0
879 */
880     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
881 #ifdef ENABLE_LIBXML2		/* LIBXML2 is supported */
882     sqlite3_result_int (context, 1);
883 #else
884     sqlite3_result_int (context, 0);
885 #endif
886 }
887 
888 static void
fnct_has_geopackage(sqlite3_context * context,int argc,sqlite3_value ** argv)889 fnct_has_geopackage (sqlite3_context * context, int argc, sqlite3_value ** argv)
890 {
891 /* SQL function:
892 / HasGeoPackage()
893 /
894 / return 1 if built including GeoPackage support (GPKG); otherwise 0
895 */
896     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
897 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE is supported */
898     sqlite3_result_int (context, 1);
899 #else
900     sqlite3_result_int (context, 0);
901 #endif
902 }
903 
904 static void
fnct_has_gcp(sqlite3_context * context,int argc,sqlite3_value ** argv)905 fnct_has_gcp (sqlite3_context * context, int argc, sqlite3_value ** argv)
906 {
907 /* SQL function:
908 / HasGCP()
909 / HasGroundControlPoints()
910 /
911 / return 1 if built including GroundControlPoints support (GGP); otherwise 0
912 */
913     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
914 #ifdef ENABLE_GCP		/* GCP are supported */
915     sqlite3_result_int (context, 1);
916 #else
917     sqlite3_result_int (context, 0);
918 #endif
919 }
920 
921 static void
fnct_has_topology(sqlite3_context * context,int argc,sqlite3_value ** argv)922 fnct_has_topology (sqlite3_context * context, int argc, sqlite3_value ** argv)
923 {
924 /* SQL function:
925 / HasTopology()
926 /
927 / return 1 if built including GroundControlPoints support (GGP); otherwise 0
928 */
929     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
930 #ifdef ENABLE_RTTOPO		/* RTTOPO is supported */
931     sqlite3_result_int (context, 1);
932 #else
933     sqlite3_result_int (context, 0);
934 #endif
935 }
936 
937 static void
fnct_has_knn(sqlite3_context * context,int argc,sqlite3_value ** argv)938 fnct_has_knn (sqlite3_context * context, int argc, sqlite3_value ** argv)
939 {
940 /* SQL function:
941 / HasKNN()
942 /
943 / return 1 if built including KNN support; otherwise 0
944 */
945     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
946 #ifndef OMIT_GEOS		/* only if GEOS is enabled */
947 #ifndef OMIT_KNN		/* only if KNN is enabled */
948     sqlite3_result_int (context, 1);
949 #else
950     sqlite3_result_int (context, 0);
951 #endif
952 #else
953     sqlite3_result_int (context, 0);
954 #endif
955 }
956 
957 static void
fnct_has_routing(sqlite3_context * context,int argc,sqlite3_value ** argv)958 fnct_has_routing (sqlite3_context * context, int argc, sqlite3_value ** argv)
959 {
960 /* SQL function:
961 / HasRouting()
962 /
963 / return 1 if built including VirtualRouting support; otherwise 0
964 */
965     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
966 #ifndef OMIT_GEOS		/* only if GEOS is enabled */
967     sqlite3_result_int (context, 1);
968 #else
969     sqlite3_result_int (context, 0);
970 #endif
971 }
972 
973 static void
fnct_GeometryConstraints(sqlite3_context * context,int argc,sqlite3_value ** argv)974 fnct_GeometryConstraints (sqlite3_context * context, int argc,
975 			  sqlite3_value ** argv)
976 {
977 /* SQL function:
978 / GeometryConstraints(BLOBencoded geometry, geometry-type, srid)
979 / GeometryConstraints(BLOBencoded geometry, geometry-type, srid, dimensions)
980 /
981 / checks geometry constraints, returning:
982 /
983 / -1 - if some error occurred
984 / 1 - if geometry constraints validation passes
985 / 0 - if geometry constraints validation fails
986 /
987 */
988     int little_endian;
989     int endian_arch = gaiaEndianArch ();
990     unsigned char *p_blob = NULL;
991     int n_bytes = 0;
992     int srid;
993     int geom_srid = -1;
994     const char *type;
995     int xtype;
996     int geom_type = -1;
997     int geom_normalized_type;
998     const unsigned char *dimensions;
999     int dims = GAIA_XY;
1000     int ret;
1001     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1002     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB
1003 	|| sqlite3_value_type (argv[0]) == SQLITE_NULL)
1004 	;
1005     else
1006       {
1007 	  sqlite3_result_int (context, -1);
1008 	  return;
1009       }
1010     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
1011 	type = (const char *) sqlite3_value_text (argv[1]);
1012     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
1013       {
1014 	  /* current metadata style >= v.4.0.0 */
1015 	  type = "UNKNOWN";
1016 	  switch (sqlite3_value_int (argv[1]))
1017 	    {
1018 	    case 0:
1019 		type = "GEOMETRY";
1020 		dims = GAIA_XY;
1021 		break;
1022 	    case 1:
1023 		type = "POINT";
1024 		dims = GAIA_XY;
1025 		break;
1026 	    case 2:
1027 		type = "LINESTRING";
1028 		dims = GAIA_XY;
1029 		break;
1030 	    case 3:
1031 		type = "POLYGON";
1032 		dims = GAIA_XY;
1033 		break;
1034 	    case 4:
1035 		type = "MULTIPOINT";
1036 		dims = GAIA_XY;
1037 		break;
1038 	    case 5:
1039 		type = "MULTILINESTRING";
1040 		dims = GAIA_XY;
1041 		break;
1042 	    case 6:
1043 		type = "MULTIPOLYGON";
1044 		dims = GAIA_XY;
1045 		break;
1046 	    case 7:
1047 		type = "GEOMETRYCOLLECTION";
1048 		dims = GAIA_XY;
1049 		break;
1050 	    case 1000:
1051 		type = "GEOMETRY";
1052 		dims = GAIA_XY_Z;
1053 		break;
1054 	    case 1001:
1055 		type = "POINT";
1056 		dims = GAIA_XY_Z;
1057 		break;
1058 	    case 1002:
1059 		type = "LINESTRING";
1060 		dims = GAIA_XY_Z;
1061 		break;
1062 	    case 1003:
1063 		type = "POLYGON";
1064 		dims = GAIA_XY_Z;
1065 		break;
1066 	    case 1004:
1067 		type = "MULTIPOINT";
1068 		dims = GAIA_XY_Z;
1069 		break;
1070 	    case 1005:
1071 		type = "MULTILINESTRING";
1072 		dims = GAIA_XY_Z;
1073 		break;
1074 	    case 1006:
1075 		type = "MULTIPOLYGON";
1076 		dims = GAIA_XY_Z;
1077 		break;
1078 	    case 1007:
1079 		type = "GEOMETRYCOLLECTION";
1080 		dims = GAIA_XY_Z;
1081 		break;
1082 	    case 2000:
1083 		type = "GEOMETRY";
1084 		dims = GAIA_XY_M;
1085 		break;
1086 	    case 2001:
1087 		type = "POINT";
1088 		dims = GAIA_XY_M;
1089 		break;
1090 	    case 2002:
1091 		type = "LINESTRING";
1092 		dims = GAIA_XY_M;
1093 		break;
1094 	    case 2003:
1095 		type = "POLYGON";
1096 		dims = GAIA_XY_M;
1097 		break;
1098 	    case 2004:
1099 		type = "MULTIPOINT";
1100 		dims = GAIA_XY_M;
1101 		break;
1102 	    case 2005:
1103 		type = "MULTILINESTRING";
1104 		dims = GAIA_XY_M;
1105 		break;
1106 	    case 2006:
1107 		type = "MULTIPOLYGON";
1108 		dims = GAIA_XY_M;
1109 		break;
1110 	    case 2007:
1111 		type = "GEOMETRYCOLLECTION";
1112 		dims = GAIA_XY_M;
1113 		break;
1114 	    case 3000:
1115 		type = "GEOMETRY";
1116 		dims = GAIA_XY_Z_M;
1117 		break;
1118 	    case 3001:
1119 		type = "POINT";
1120 		dims = GAIA_XY_Z_M;
1121 		break;
1122 	    case 3002:
1123 		type = "LINESTRING";
1124 		dims = GAIA_XY_Z_M;
1125 		break;
1126 	    case 3003:
1127 		type = "POLYGON";
1128 		dims = GAIA_XY_Z_M;
1129 		break;
1130 	    case 3004:
1131 		type = "MULTIPOINT";
1132 		dims = GAIA_XY_Z_M;
1133 		break;
1134 	    case 3005:
1135 		type = "MULTILINESTRING";
1136 		dims = GAIA_XY_Z_M;
1137 		break;
1138 	    case 3006:
1139 		type = "MULTIPOLYGON";
1140 		dims = GAIA_XY_Z_M;
1141 		break;
1142 	    case 3007:
1143 		type = "GEOMETRYCOLLECTION";
1144 		dims = GAIA_XY_Z_M;
1145 		break;
1146 	    };
1147       }
1148     else
1149       {
1150 	  sqlite3_result_int (context, -1);
1151 	  return;
1152       }
1153     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
1154 	srid = sqlite3_value_int (argv[2]);
1155     else
1156       {
1157 	  sqlite3_result_int (context, -1);
1158 	  return;
1159       }
1160     if (argc == 4)
1161       {
1162 	  /* explicit dimensions - supporting XYZM */
1163 	  dimensions = sqlite3_value_text (argv[3]);
1164 	  if (strcasecmp ((char *) dimensions, "XYZ") == 0)
1165 	      dims = GAIA_XY_Z;
1166 	  else if (strcasecmp ((char *) dimensions, "XYM") == 0)
1167 	      dims = GAIA_XY_M;
1168 	  else if (strcasecmp ((char *) dimensions, "XYZM") == 0)
1169 	      dims = GAIA_XY_Z_M;
1170 	  else
1171 	      dims = GAIA_XY;
1172       }
1173     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
1174       {
1175 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
1176 	  n_bytes = sqlite3_value_bytes (argv[0]);
1177       }
1178     if (p_blob)
1179       {
1180 	  if (n_bytes == 24 || n_bytes == 32 || n_bytes == 40)
1181 	    {
1182 		/* testing for a possible TinyPoint BLOB */
1183 		if (*(p_blob + 0) == GAIA_MARK_START &&
1184 		    (*(p_blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
1185 		     || *(p_blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
1186 		    && *(p_blob + (n_bytes - 1)) == GAIA_MARK_END)
1187 		  {
1188 		      /* quick TinyPoint validation */
1189 		      int pointType;
1190 		      if (*(p_blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
1191 			  little_endian = 1;
1192 		      else if (*(p_blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
1193 			  little_endian = 0;
1194 		      else
1195 			  goto illegal_geometry;	/* unknown encoding; neither little-endian nor big-endian */
1196 		      geom_srid =
1197 			  gaiaImport32 (p_blob + 2, little_endian, endian_arch);
1198 		      pointType = *(p_blob + 6);
1199 		      switch (pointType)
1200 			{
1201 			case GAIA_TINYPOINT_XY:
1202 			    geom_type = GAIA_POINT;
1203 			    break;
1204 			case GAIA_TINYPOINT_XYZ:
1205 			    geom_type = GAIA_POINTZ;
1206 			    break;
1207 			case GAIA_TINYPOINT_XYM:
1208 			    geom_type = GAIA_POINTM;
1209 			    break;
1210 			case GAIA_TINYPOINT_XYZM:
1211 			    geom_type = GAIA_POINTZM;
1212 			    break;
1213 			default:
1214 			    goto illegal_geometry;
1215 			};
1216 		      goto valid_geometry;
1217 		  }
1218 	    }
1219 
1220 	  /* quick Geometry validation */
1221 	  if (n_bytes < 45)
1222 	      goto illegal_geometry;	/* cannot be an internal BLOB WKB geometry */
1223 	  if (*(p_blob + 0) != GAIA_MARK_START)
1224 	      goto illegal_geometry;	/* failed to recognize START signature */
1225 	  if (*(p_blob + (n_bytes - 1)) != GAIA_MARK_END)
1226 	      goto illegal_geometry;	/* failed to recognize END signature */
1227 	  if (*(p_blob + 38) != GAIA_MARK_MBR)
1228 	      goto illegal_geometry;	/* failed to recognize MBR signature */
1229 	  if (*(p_blob + 1) == GAIA_LITTLE_ENDIAN)
1230 	      little_endian = 1;
1231 	  else if (*(p_blob + 1) == GAIA_BIG_ENDIAN)
1232 	      little_endian = 0;
1233 	  else
1234 	      goto illegal_geometry;	/* unknown encoding; neither little-endian nor big-endian */
1235 	  geom_type = gaiaImport32 (p_blob + 39, little_endian, endian_arch);
1236 	  geom_srid = gaiaImport32 (p_blob + 2, little_endian, endian_arch);
1237 	  goto valid_geometry;
1238 	illegal_geometry:
1239 	  sqlite3_result_int (context, -1);
1240 	  return;
1241       }
1242   valid_geometry:
1243     xtype = GAIA_UNKNOWN;
1244     if (strcasecmp ((char *) type, "POINT") == 0)
1245       {
1246 	  switch (dims)
1247 	    {
1248 	    case GAIA_XY_Z:
1249 		xtype = GAIA_POINTZ;
1250 		break;
1251 	    case GAIA_XY_M:
1252 		xtype = GAIA_POINTM;
1253 		break;
1254 	    case GAIA_XY_Z_M:
1255 		xtype = GAIA_POINTZM;
1256 		break;
1257 	    default:
1258 		xtype = GAIA_POINT;
1259 		break;
1260 	    };
1261       }
1262     if (strcasecmp ((char *) type, "LINESTRING") == 0)
1263       {
1264 	  switch (dims)
1265 	    {
1266 	    case GAIA_XY_Z:
1267 		xtype = GAIA_LINESTRINGZ;
1268 		break;
1269 	    case GAIA_XY_M:
1270 		xtype = GAIA_LINESTRINGM;
1271 		break;
1272 	    case GAIA_XY_Z_M:
1273 		xtype = GAIA_LINESTRINGZM;
1274 		break;
1275 	    default:
1276 		xtype = GAIA_LINESTRING;
1277 		break;
1278 	    };
1279       }
1280     if (strcasecmp ((char *) type, "POLYGON") == 0)
1281       {
1282 	  switch (dims)
1283 	    {
1284 	    case GAIA_XY_Z:
1285 		xtype = GAIA_POLYGONZ;
1286 		break;
1287 	    case GAIA_XY_M:
1288 		xtype = GAIA_POLYGONM;
1289 		break;
1290 	    case GAIA_XY_Z_M:
1291 		xtype = GAIA_POLYGONZM;
1292 		break;
1293 	    default:
1294 		xtype = GAIA_POLYGON;
1295 		break;
1296 	    };
1297       }
1298     if (strcasecmp ((char *) type, "MULTIPOINT") == 0)
1299       {
1300 	  switch (dims)
1301 	    {
1302 	    case GAIA_XY_Z:
1303 		xtype = GAIA_MULTIPOINTZ;
1304 		break;
1305 	    case GAIA_XY_M:
1306 		xtype = GAIA_MULTIPOINTM;
1307 		break;
1308 	    case GAIA_XY_Z_M:
1309 		xtype = GAIA_MULTIPOINTZM;
1310 		break;
1311 	    default:
1312 		xtype = GAIA_MULTIPOINT;
1313 		break;
1314 	    };
1315       }
1316     if (strcasecmp ((char *) type, "MULTILINESTRING") == 0)
1317       {
1318 	  switch (dims)
1319 	    {
1320 	    case GAIA_XY_Z:
1321 		xtype = GAIA_MULTILINESTRINGZ;
1322 		break;
1323 	    case GAIA_XY_M:
1324 		xtype = GAIA_MULTILINESTRINGM;
1325 		break;
1326 	    case GAIA_XY_Z_M:
1327 		xtype = GAIA_MULTILINESTRINGZM;
1328 		break;
1329 	    default:
1330 		xtype = GAIA_MULTILINESTRING;
1331 		break;
1332 	    };
1333       }
1334     if (strcasecmp ((char *) type, "MULTIPOLYGON") == 0)
1335       {
1336 	  switch (dims)
1337 	    {
1338 	    case GAIA_XY_Z:
1339 		xtype = GAIA_MULTIPOLYGONZ;
1340 		break;
1341 	    case GAIA_XY_M:
1342 		xtype = GAIA_MULTIPOLYGONM;
1343 		break;
1344 	    case GAIA_XY_Z_M:
1345 		xtype = GAIA_MULTIPOLYGONZM;
1346 		break;
1347 	    default:
1348 		xtype = GAIA_MULTIPOLYGON;
1349 		break;
1350 	    };
1351       }
1352     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTION") == 0)
1353       {
1354 	  switch (dims)
1355 	    {
1356 	    case GAIA_XY_Z:
1357 		xtype = GAIA_GEOMETRYCOLLECTIONZ;
1358 		break;
1359 	    case GAIA_XY_M:
1360 		xtype = GAIA_GEOMETRYCOLLECTIONM;
1361 		break;
1362 	    case GAIA_XY_Z_M:
1363 		xtype = GAIA_GEOMETRYCOLLECTIONZM;
1364 		break;
1365 	    default:
1366 		xtype = GAIA_GEOMETRYCOLLECTION;
1367 		break;
1368 	    };
1369       }
1370     switch (geom_type)
1371       {
1372 	  /* adjusting COMPRESSED Geometries */
1373       case GAIA_COMPRESSED_LINESTRING:
1374 	  geom_normalized_type = GAIA_LINESTRING;
1375 	  break;
1376       case GAIA_COMPRESSED_LINESTRINGZ:
1377 	  geom_normalized_type = GAIA_LINESTRINGZ;
1378 	  break;
1379       case GAIA_COMPRESSED_LINESTRINGM:
1380 	  geom_normalized_type = GAIA_LINESTRINGM;
1381 	  break;
1382       case GAIA_COMPRESSED_LINESTRINGZM:
1383 	  geom_normalized_type = GAIA_LINESTRINGZM;
1384 	  break;
1385       case GAIA_COMPRESSED_POLYGON:
1386 	  geom_normalized_type = GAIA_POLYGON;
1387 	  break;
1388       case GAIA_COMPRESSED_POLYGONZ:
1389 	  geom_normalized_type = GAIA_POLYGONZ;
1390 	  break;
1391       case GAIA_COMPRESSED_POLYGONM:
1392 	  geom_normalized_type = GAIA_POLYGONM;
1393 	  break;
1394       case GAIA_COMPRESSED_POLYGONZM:
1395 	  geom_normalized_type = GAIA_POLYGONZM;
1396 	  break;
1397       default:
1398 	  geom_normalized_type = geom_type;
1399 	  break;
1400       };
1401     if (strcasecmp ((char *) type, "GEOMETRY") == 0)
1402 	xtype = -1;
1403     if (xtype == GAIA_UNKNOWN)
1404 	sqlite3_result_int (context, -1);
1405     else
1406       {
1407 	  ret = 1;
1408 	  if (p_blob)
1409 	    {
1410 		/* skipping NULL Geometry; this is assumed to be always good */
1411 		if (geom_srid != srid)
1412 		    ret = 0;
1413 		if (xtype == -1)
1414 		    ;
1415 		else if (xtype != geom_normalized_type)
1416 		    ret = 0;
1417 	    }
1418 	  sqlite3_result_int (context, ret);
1419       }
1420 }
1421 
1422 static void
fnct_RTreeAlign(sqlite3_context * context,int argc,sqlite3_value ** argv)1423 fnct_RTreeAlign (sqlite3_context * context, int argc, sqlite3_value ** argv)
1424 {
1425 /* SQL function:
1426 / RTreeAlign(RTree-table-name, PKID-value, BLOBencoded geometry)
1427 /
1428 / attempts to update the associated R*Tree, returning:
1429 /
1430 / -1 - if some invalid arg was passed
1431 / 1 - successful update
1432 / 0 - update failure
1433 /
1434 */
1435     unsigned char *p_blob = NULL;
1436     int n_bytes = 0;
1437     sqlite3_int64 pkid;
1438     const char *rtree_table;
1439     char *table_name;
1440     int len;
1441     char pkv[64];
1442     gaiaGeomCollPtr geom = NULL;
1443     int ret;
1444     char *sql_statement;
1445     sqlite3 *sqlite = sqlite3_context_db_handle (context);
1446     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1447     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
1448 	rtree_table = (const char *) sqlite3_value_text (argv[0]);
1449     else
1450       {
1451 	  sqlite3_result_int (context, -1);
1452 	  return;
1453       }
1454     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
1455 	pkid = sqlite3_value_int64 (argv[1]);
1456     else
1457       {
1458 	  sqlite3_result_int (context, -1);
1459 	  return;
1460       }
1461     if (sqlite3_value_type (argv[2]) == SQLITE_BLOB
1462 	|| sqlite3_value_type (argv[2]) == SQLITE_NULL)
1463 	;
1464     else
1465       {
1466 	  sqlite3_result_int (context, -1);
1467 	  return;
1468       }
1469     if (sqlite3_value_type (argv[2]) == SQLITE_BLOB)
1470       {
1471 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[2]);
1472 	  n_bytes = sqlite3_value_bytes (argv[2]);
1473 	  geom = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
1474       }
1475 
1476     if (geom == NULL)
1477       {
1478 	  /* NULL geometry: nothing to do */
1479 	  sqlite3_result_int (context, 1);
1480       }
1481     else
1482       {
1483 	  /* INSERTing into the R*Tree */
1484 	  if (*(rtree_table + 0) == '"'
1485 	      && *(rtree_table + strlen (rtree_table) - 1) == '"')
1486 	    {
1487 		/* earlier versions may pass an already quoted name */
1488 		char *dequoted_table_name;
1489 		len = strlen (rtree_table);
1490 		table_name = malloc (len + 1);
1491 		strcpy (table_name, rtree_table);
1492 		dequoted_table_name = gaiaDequotedSql (table_name);
1493 		free (table_name);
1494 		if (dequoted_table_name == NULL)
1495 		  {
1496 		      sqlite3_result_int (context, -1);
1497 		      return;
1498 		  }
1499 		table_name = gaiaDoubleQuotedSql (dequoted_table_name);
1500 		free (dequoted_table_name);
1501 	    }
1502 	  else
1503 	      table_name = gaiaDoubleQuotedSql (rtree_table);
1504 	  sprintf (pkv, FRMT64, pkid);
1505 	  sql_statement =
1506 	      sqlite3_mprintf
1507 	      ("INSERT INTO \"%s\" (pkid, xmin, ymin, xmax, ymax) "
1508 	       "VALUES (%s, %1.12f, %1.12f, %1.12f, %1.12f)", table_name,
1509 	       pkv, geom->MinX, geom->MinY, geom->MaxX, geom->MaxY);
1510 	  gaiaFreeGeomColl (geom);
1511 	  ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
1512 	  sqlite3_free (sql_statement);
1513 	  free (table_name);
1514 	  if (ret != SQLITE_OK)
1515 	      sqlite3_result_int (context, 0);
1516 	  else
1517 	      sqlite3_result_int (context, 1);
1518       }
1519 }
1520 
1521 static void
fnct_TemporaryRTreeAlign(sqlite3_context * context,int argc,sqlite3_value ** argv)1522 fnct_TemporaryRTreeAlign (sqlite3_context * context, int argc,
1523 			  sqlite3_value ** argv)
1524 {
1525 /* SQL function:
1526 / TemporaryRTreeAlign(db-prefix, RTree-table-name, PKID-value, BLOBencoded geometry)
1527 /
1528 / attempts to update the associated R*Tree, returning:
1529 /
1530 / -1 - if some invalid arg was passed
1531 / 1 - successful update
1532 / 0 - update failure
1533 /
1534 */
1535     unsigned char *p_blob = NULL;
1536     int n_bytes = 0;
1537     sqlite3_int64 pkid;
1538     const char *db_prefix;
1539     const char *rtree_table;
1540     char *prefix;
1541     char *table_name;
1542     int len;
1543     char pkv[64];
1544     gaiaGeomCollPtr geom = NULL;
1545     int ret;
1546     char *sql_statement;
1547     sqlite3 *sqlite = sqlite3_context_db_handle (context);
1548     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1549     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
1550 	db_prefix = (const char *) sqlite3_value_text (argv[0]);
1551     else
1552       {
1553 	  sqlite3_result_int (context, -1);
1554 	  return;
1555       }
1556     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
1557 	rtree_table = (const char *) sqlite3_value_text (argv[1]);
1558     else
1559       {
1560 	  sqlite3_result_int (context, -1);
1561 	  return;
1562       }
1563     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
1564 	pkid = sqlite3_value_int64 (argv[2]);
1565     else
1566       {
1567 	  sqlite3_result_int (context, -1);
1568 	  return;
1569       }
1570     if (sqlite3_value_type (argv[3]) == SQLITE_BLOB
1571 	|| sqlite3_value_type (argv[3]) == SQLITE_NULL)
1572 	;
1573     else
1574       {
1575 	  sqlite3_result_int (context, -1);
1576 	  return;
1577       }
1578     if (sqlite3_value_type (argv[3]) == SQLITE_BLOB)
1579       {
1580 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[3]);
1581 	  n_bytes = sqlite3_value_bytes (argv[3]);
1582 	  geom = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
1583       }
1584 
1585     if (geom == NULL)
1586       {
1587 	  /* NULL geometry: nothing to do */
1588 	  sqlite3_result_int (context, 1);
1589       }
1590     else
1591       {
1592 	  /* INSERTing into the R*Tree */
1593 	  if (*(rtree_table + 0) == '"'
1594 	      && *(rtree_table + strlen (rtree_table) - 1) == '"')
1595 	    {
1596 		/* earlier versions may pass an already quoted name */
1597 		char *dequoted_table_name;
1598 		len = strlen (rtree_table);
1599 		table_name = malloc (len + 1);
1600 		strcpy (table_name, rtree_table);
1601 		dequoted_table_name = gaiaDequotedSql (table_name);
1602 		free (table_name);
1603 		if (dequoted_table_name == NULL)
1604 		  {
1605 		      sqlite3_result_int (context, -1);
1606 		      return;
1607 		  }
1608 		table_name = gaiaDoubleQuotedSql (dequoted_table_name);
1609 		free (dequoted_table_name);
1610 	    }
1611 	  else
1612 	      table_name = gaiaDoubleQuotedSql (rtree_table);
1613 	  prefix = gaiaDoubleQuotedSql (db_prefix);
1614 	  sprintf (pkv, FRMT64, pkid);
1615 	  sql_statement =
1616 	      sqlite3_mprintf
1617 	      ("INSERT INTO \"%s\".\"%s\" (pkid, xmin, ymin, xmax, ymax) "
1618 	       "VALUES (%s, %1.12f, %1.12f, %1.12f, %1.12f)", prefix,
1619 	       table_name, pkv, geom->MinX, geom->MinY, geom->MaxX, geom->MaxY);
1620 	  free (prefix);
1621 	  gaiaFreeGeomColl (geom);
1622 	  ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
1623 	  sqlite3_free (sql_statement);
1624 	  free (table_name);
1625 	  if (ret != SQLITE_OK)
1626 	      sqlite3_result_int (context, 0);
1627 	  else
1628 	      sqlite3_result_int (context, 1);
1629       }
1630 }
1631 
1632 static void
fnct_IsValidFont(sqlite3_context * context,int argc,sqlite3_value ** argv)1633 fnct_IsValidFont (sqlite3_context * context, int argc, sqlite3_value ** argv)
1634 {
1635 /* SQL function:
1636 / IsValidFont(BLOBencoded font)
1637 /
1638 / basic version intended to be overloaded by RasterLite-2
1639 / always return 0 (FALSE)
1640 / or -1 (INVALID ARGS)
1641 /
1642 */
1643     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1644     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
1645       {
1646 	  sqlite3_result_int (context, -1);
1647 	  return;
1648       }
1649     sqlite3_result_int (context, 0);
1650 }
1651 
1652 static void
fnct_CheckFontFacename(sqlite3_context * context,int argc,sqlite3_value ** argv)1653 fnct_CheckFontFacename (sqlite3_context * context, int argc,
1654 			sqlite3_value ** argv)
1655 {
1656 /* SQL function:
1657 / CheckFontfaceName(TEXT facename, BLOBencoded font)
1658 /
1659 / basic version intended to be overloaded by RasterLite-2
1660 / always return NULL
1661 /
1662 */
1663     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1664     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
1665       {
1666 	  sqlite3_result_int (context, -1);
1667 	  return;
1668       }
1669     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
1670       {
1671 	  sqlite3_result_int (context, -1);
1672 	  return;
1673       }
1674     sqlite3_result_int (context, 0);
1675 }
1676 
1677 static void
fnct_GetFontFamily(sqlite3_context * context,int argc,sqlite3_value ** argv)1678 fnct_GetFontFamily (sqlite3_context * context, int argc, sqlite3_value ** argv)
1679 {
1680 /* SQL function:
1681 / GetFontFamily(BLOBencoded font)
1682 /
1683 / basic version intended to be overloaded by RasterLite-2
1684 / always return NULL
1685 /
1686 */
1687     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1688     sqlite3_result_null (context);
1689 }
1690 
1691 static void
fnct_IsFontBold(sqlite3_context * context,int argc,sqlite3_value ** argv)1692 fnct_IsFontBold (sqlite3_context * context, int argc, sqlite3_value ** argv)
1693 {
1694 /* SQL function:
1695 / IsFontBold(BLOBencoded font)
1696 /
1697 / basic version intended to be overloaded by RasterLite-2
1698 / always return -1
1699 /
1700 */
1701     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1702     sqlite3_result_int (context, -1);
1703 }
1704 
1705 static void
fnct_IsFontItalic(sqlite3_context * context,int argc,sqlite3_value ** argv)1706 fnct_IsFontItalic (sqlite3_context * context, int argc, sqlite3_value ** argv)
1707 {
1708 /* SQL function:
1709 / IsFontItalic(BLOBencoded font)
1710 /
1711 / basic version intended to be overloaded by RasterLite-2
1712 / always return -1
1713 /
1714 */
1715     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1716     sqlite3_result_int (context, -1);
1717 }
1718 
1719 static void
fnct_IsValidPixel(sqlite3_context * context,int argc,sqlite3_value ** argv)1720 fnct_IsValidPixel (sqlite3_context * context, int argc, sqlite3_value ** argv)
1721 {
1722 /* SQL function:
1723 / IsValidPixel(BLOBencoded pixel, text sample_type, int num_bands)
1724 /
1725 / basic version intended to be overloaded by RasterLite-2
1726 / always return 0 (FALSE)
1727 / or -1 (INVALID ARGS)
1728 /
1729 */
1730     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1731     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
1732       {
1733 	  sqlite3_result_int (context, -1);
1734 	  return;
1735       }
1736     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
1737       {
1738 	  sqlite3_result_int (context, -1);
1739 	  return;
1740       }
1741     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
1742       {
1743 	  sqlite3_result_int (context, -1);
1744 	  return;
1745       }
1746     sqlite3_result_int (context, 0);
1747 }
1748 
1749 static void
fnct_IsValidRasterPalette(sqlite3_context * context,int argc,sqlite3_value ** argv)1750 fnct_IsValidRasterPalette (sqlite3_context * context, int argc,
1751 			   sqlite3_value ** argv)
1752 {
1753 /* SQL function:
1754 / IsValidRasterPalette(BLOBencoded palette, text sample_type)
1755 /
1756 / basic version intended to be overloaded by RasterLite-2
1757 / always return 0 (FALSE)
1758 / or -1 (INVALID ARGS)
1759 /
1760 */
1761     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1762     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
1763       {
1764 	  sqlite3_result_int (context, -1);
1765 	  return;
1766       }
1767     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
1768       {
1769 	  sqlite3_result_int (context, -1);
1770 	  return;
1771       }
1772     sqlite3_result_int (context, 0);
1773 }
1774 
1775 static void
fnct_IsValidRasterStatistics(sqlite3_context * context,int argc,sqlite3_value ** argv)1776 fnct_IsValidRasterStatistics (sqlite3_context * context, int argc,
1777 			      sqlite3_value ** argv)
1778 {
1779 /* SQL function:
1780 / IsValidRasterStatistics(text db_prefix, text coverage,
1781 /                         BLOBencoded statistics)
1782 /   or
1783 / IsValidRasterStatistics(BLOBencoded statistics, text sample_type,
1784 /                         int num_bands)
1785 /
1786 / basic version intended to be overloaded by RasterLite-2
1787 / always return 0 (FALSE)
1788 / or -1 (INVALID ARGS)
1789 /
1790 */
1791     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1792     if ((sqlite3_value_type (argv[0]) == SQLITE_TEXT
1793 	 || sqlite3_value_type (argv[0]) == SQLITE_NULL)
1794 	&& sqlite3_value_type (argv[1]) == SQLITE_TEXT
1795 	&& sqlite3_value_type (argv[2]) == SQLITE_BLOB)
1796 	;
1797     else if (sqlite3_value_type (argv[0]) == SQLITE_BLOB
1798 	     && sqlite3_value_type (argv[1]) == SQLITE_TEXT
1799 	     && sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
1800 	;
1801     else
1802       {
1803 	  sqlite3_result_int (context, -1);
1804 	  return;
1805       }
1806     sqlite3_result_int (context, 0);
1807 }
1808 
1809 static void
fnct_IsValidRasterTile(sqlite3_context * context,int argc,sqlite3_value ** argv)1810 fnct_IsValidRasterTile (sqlite3_context * context, int argc,
1811 			sqlite3_value ** argv)
1812 {
1813 /* SQL function:
1814 / IsValidRasterTile(text db_prefix, text coverage, integer level,
1815 /                   BLOBencoded tile_odd, BLOBencoded tile_even)
1816 /
1817 / basic version intended to be overloaded by RasterLite-2
1818 / always return 0 (FALSE)
1819 / or -1 (INVALID ARGS)
1820 /
1821 */
1822     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1823     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT
1824 	|| sqlite3_value_type (argv[0]) == SQLITE_NULL)
1825 	;
1826     else
1827       {
1828 	  sqlite3_result_int (context, -1);
1829 	  return;
1830       }
1831     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
1832       {
1833 	  sqlite3_result_int (context, -1);
1834 	  return;
1835       }
1836     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
1837       {
1838 	  sqlite3_result_int (context, -1);
1839 	  return;
1840       }
1841     if (sqlite3_value_type (argv[3]) != SQLITE_BLOB)
1842       {
1843 	  sqlite3_result_int (context, -1);
1844 	  return;
1845       }
1846     if (sqlite3_value_type (argv[4]) != SQLITE_BLOB
1847 	&& sqlite3_value_type (argv[4]) != SQLITE_NULL)
1848       {
1849 	  sqlite3_result_int (context, -1);
1850 	  return;
1851       }
1852     sqlite3_result_int (context, 0);
1853 }
1854 
1855 static void
fnct_IsPopulatedCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)1856 fnct_IsPopulatedCoverage (sqlite3_context * context, int argc,
1857 			  sqlite3_value ** argv)
1858 {
1859 /* SQL function:
1860 / IsPopulatedCoverage(text db_prefix, text coverage)
1861 /
1862 / check if a RasterCoverage is already populated
1863 / returns 1 if TRUE, 0 if FALSE
1864 / -1 on invalid arguments
1865 */
1866     const char *db_prefix = NULL;
1867     const char *coverage;
1868     int ret;
1869     sqlite3 *sqlite = sqlite3_context_db_handle (context);
1870     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
1871     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT
1872 	|| sqlite3_value_type (argv[0]) == SQLITE_NULL)
1873 	;
1874     else
1875       {
1876 	  sqlite3_result_int (context, -1);
1877 	  return;
1878       }
1879     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
1880       {
1881 	  sqlite3_result_int (context, -1);
1882 	  return;
1883       }
1884     coverage = (const char *) sqlite3_value_text (argv[0]);
1885     ret = checkPopulatedCoverage (sqlite, db_prefix, coverage);
1886     sqlite3_result_int (context, ret);
1887     return;
1888 }
1889 
1890 static int
is_without_rowid_table(sqlite3 * sqlite,const char * table)1891 is_without_rowid_table (sqlite3 * sqlite, const char *table)
1892 {
1893 /* internal utility functions; checks for WITHOUT ROWID tables */
1894     char *sql;
1895     char *xtable;
1896     int ret;
1897     int i;
1898     char **results;
1899     int rows;
1900     int columns;
1901     int j;
1902     char **results2;
1903     int rows2;
1904     int columns2;
1905     char *errMsg = NULL;
1906     int without_rowid = 0;
1907 
1908     xtable = gaiaDoubleQuotedSql (table);
1909     sql = sqlite3_mprintf ("PRAGMA index_list(\"%s\")", xtable);
1910     free (xtable);
1911     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
1912     sqlite3_free (sql);
1913     if (ret != SQLITE_OK)
1914       {
1915 	  sqlite3_free (errMsg);
1916 	  return 1;
1917       }
1918     for (i = 1; i <= rows; i++)
1919       {
1920 	  const char *index = results[(i * columns) + 1];
1921 	  sql = sqlite3_mprintf ("SELECT count(*) FROM sqlite_master WHERE "
1922 				 "type = 'index' AND Lower(tbl_name) = Lower(%Q) "
1923 				 "AND Lower(name) = Lower(%Q)", table, index);
1924 	  ret =
1925 	      sqlite3_get_table (sqlite, sql, &results2, &rows2, &columns2,
1926 				 &errMsg);
1927 	  sqlite3_free (sql);
1928 	  if (ret != SQLITE_OK)
1929 	    {
1930 		sqlite3_free (errMsg);
1931 		return 1;
1932 	    }
1933 	  for (j = 1; j <= rows2; j++)
1934 	    {
1935 		if (atoi (results2[(j * columns2) + 0]) == 0)
1936 		    without_rowid = 1;
1937 	    }
1938 	  sqlite3_free_table (results2);
1939       }
1940     sqlite3_free_table (results);
1941     return without_rowid;
1942 }
1943 
1944 static int
is_without_rowid_table_attached(sqlite3 * sqlite,const char * db_prefix,const char * table)1945 is_without_rowid_table_attached (sqlite3 * sqlite, const char *db_prefix,
1946 				 const char *table)
1947 {
1948 /* internal utility functions; checks for WITHOUT ROWID tables */
1949     char *sql;
1950     char *xprefix;
1951     char *xtable;
1952     int ret;
1953     int i;
1954     char **results;
1955     int rows;
1956     int columns;
1957     int j;
1958     char **results2;
1959     int rows2;
1960     int columns2;
1961     char *errMsg = NULL;
1962     int without_rowid = 0;
1963 
1964     if (db_prefix == NULL)
1965 	return 1;
1966 
1967     xprefix = gaiaDoubleQuotedSql (db_prefix);
1968     xtable = gaiaDoubleQuotedSql (table);
1969     sql = sqlite3_mprintf ("PRAGMA \"%s\".index_list(\"%s\")", xprefix, xtable);
1970     free (xprefix);
1971     free (xtable);
1972     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
1973     sqlite3_free (sql);
1974     if (ret != SQLITE_OK)
1975       {
1976 	  sqlite3_free (errMsg);
1977 	  return 1;
1978       }
1979     xprefix = gaiaDoubleQuotedSql (db_prefix);
1980     for (i = 1; i <= rows; i++)
1981       {
1982 	  const char *index = results[(i * columns) + 1];
1983 	  sql =
1984 	      sqlite3_mprintf
1985 	      ("SELECT count(*) FROM \"%s\".sqlite_master WHERE "
1986 	       "type = 'index' AND Lower(tbl_name) = Lower(%Q) "
1987 	       "AND Lower(name) = Lower(%Q)", table, index);
1988 	  ret =
1989 	      sqlite3_get_table (sqlite, sql, &results2, &rows2, &columns2,
1990 				 &errMsg);
1991 	  sqlite3_free (sql);
1992 	  if (ret != SQLITE_OK)
1993 	    {
1994 		sqlite3_free (errMsg);
1995 		return 1;
1996 	    }
1997 	  for (j = 1; j <= rows2; j++)
1998 	    {
1999 		if (atoi (results2[(j * columns2) + 0]) == 0)
2000 		    without_rowid = 1;
2001 	    }
2002 	  sqlite3_free_table (results2);
2003       }
2004     free (xprefix);
2005     sqlite3_free_table (results);
2006     return without_rowid;
2007 }
2008 
2009 static int
is_attached_memory(sqlite3 * sqlite,const char * db_prefix)2010 is_attached_memory (sqlite3 * sqlite, const char *db_prefix)
2011 {
2012 /* internal utility functions; checks if an Attached Database is based on :memory: */
2013     const char *sql;
2014     int ret;
2015     int i;
2016     char **results;
2017     int rows;
2018     int columns;
2019     char *errMsg = NULL;
2020     int is_memory = 0;
2021 
2022     if (db_prefix == NULL)
2023 	return 0;
2024 
2025     sql = "PRAGMA database_list";
2026     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
2027     if (ret != SQLITE_OK)
2028       {
2029 	  sqlite3_free (errMsg);
2030 	  return 0;
2031       }
2032     for (i = 1; i <= rows; i++)
2033       {
2034 	  const char *name = results[(i * columns) + 1];
2035 	  const char *file = results[(i * columns) + 2];
2036 	  if (strcasecmp (name, db_prefix) == 0)
2037 	    {
2038 		if (file == NULL || strlen (file) == 0)
2039 		    is_memory = 1;
2040 	    }
2041       }
2042     sqlite3_free_table (results);
2043     return is_memory;
2044 }
2045 
2046 static int
checkDatabase(const sqlite3 * handle,const char * db_prefix)2047 checkDatabase (const sqlite3 * handle, const char *db_prefix)
2048 {
2049 /* testing if some ATTACHED-DB do really exist */
2050     sqlite3 *sqlite = (sqlite3 *) handle;
2051     char *xdb_prefix;
2052     char sql[1024];
2053     int ret;
2054     int i;
2055     char **results;
2056     int rows;
2057     int columns;
2058     int exists = 0;
2059 
2060     if (db_prefix == NULL)
2061 	db_prefix = "main";
2062     xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2063     sprintf (sql, "PRAGMA \"%s\".database_list", xdb_prefix);
2064     free (xdb_prefix);
2065     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
2066     if (ret != SQLITE_OK)
2067 	return 0;
2068     if (rows < 1)
2069 	;
2070     else
2071       {
2072 	  for (i = 1; i <= rows; i++)
2073 	    {
2074 		const char *name = results[(i * columns) + 1];
2075 		if (strcasecmp (name, db_prefix) == 0)
2076 		    exists = 1;
2077 	    }
2078       }
2079     sqlite3_free_table (results);
2080     return exists;
2081 }
2082 
2083 static int
checkGeoPackage(sqlite3 * handle,const char * db_prefix)2084 checkGeoPackage (sqlite3 * handle, const char *db_prefix)
2085 {
2086 /* testing for GeoPackage meta-tables */
2087     sqlite3 *sqlite = (sqlite3 *) handle;
2088     char *xdb_prefix;
2089     char sql[1024];
2090     int ret;
2091     const char *name;
2092     int table_name = 0;
2093     int column_name = 0;
2094     int geometry_type_name = 0;
2095     int srs_id_gc = 0;
2096     int has_z = 0;
2097     int has_m = 0;
2098     int gpkg_gc = 0;
2099     int srs_id_srs = 0;
2100     int srs_name = 0;
2101     int gpkg_srs = 0;
2102     int i;
2103     char **results;
2104     int rows;
2105     int columns;
2106 
2107     if (!checkDatabase (handle, db_prefix))
2108 	return -1;
2109 /* checking the GPKG_GEOMETRY_COLUMNS table */
2110     if (db_prefix == NULL)
2111 	db_prefix = "main";
2112     xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2113     sprintf (sql, "PRAGMA \"%s\".table_info(gpkg_geometry_columns)",
2114 	     xdb_prefix);
2115     free (xdb_prefix);
2116     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
2117     if (ret != SQLITE_OK)
2118 	goto unknown;
2119     if (rows < 1)
2120 	;
2121     else
2122       {
2123 	  for (i = 1; i <= rows; i++)
2124 	    {
2125 		name = results[(i * columns) + 1];
2126 		if (strcasecmp (name, "table_name") == 0)
2127 		    table_name = 1;
2128 		if (strcasecmp (name, "column_name") == 0)
2129 		    column_name = 1;
2130 		if (strcasecmp (name, "geometry_type_name") == 0)
2131 		    geometry_type_name = 1;
2132 		if (strcasecmp (name, "srs_id") == 0)
2133 		    srs_id_gc = 1;
2134 		if (strcasecmp (name, "z") == 0)
2135 		    has_z = 1;
2136 		if (strcasecmp (name, "m") == 0)
2137 		    has_m = 1;
2138 	    }
2139       }
2140     sqlite3_free_table (results);
2141     if (table_name && column_name && geometry_type_name && srs_id_gc && has_z
2142 	&& has_m)
2143 	gpkg_gc = 1;
2144 /* checking the GPKG_SPATIAL_REF_SYS table */
2145     strcpy (sql, "PRAGMA table_info(gpkg_spatial_ref_sys)");
2146     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
2147     if (ret != SQLITE_OK)
2148 	goto unknown;
2149     if (rows < 1)
2150 	;
2151     else
2152       {
2153 	  for (i = 1; i <= rows; i++)
2154 	    {
2155 		name = results[(i * columns) + 1];
2156 		if (strcasecmp (name, "srs_id") == 0)
2157 		    srs_id_srs = 1;
2158 		if (strcasecmp (name, "srs_name") == 0)
2159 		    srs_name = 1;
2160 	    }
2161       }
2162     sqlite3_free_table (results);
2163     if (srs_id_srs && srs_name)
2164 	gpkg_srs = 1;
2165     if (gpkg_gc && gpkg_srs)
2166 	return 1;
2167   unknown:
2168     return 0;
2169 }
2170 
2171 SPATIALITE_PRIVATE int
checkSpatialMetaData(const void * handle)2172 checkSpatialMetaData (const void *handle)
2173 {
2174 /* just calls checkSpatialMetaData_ex */
2175     return checkSpatialMetaData_ex (handle, NULL);
2176 }
2177 
2178 SPATIALITE_PRIVATE int
checkSpatialMetaData_ex(const void * handle,const char * db_prefix)2179 checkSpatialMetaData_ex (const void *handle, const char *db_prefix)
2180 {
2181 /* internal utility function:
2182 /
2183 / for FDO-OGR interoperability and cross-version seamless compatibility:
2184 / tests the SpatialMetadata type, returning:
2185 /
2186 / -1 -  if no ATTACHED-DB identified by db_prefix exists
2187 / 0 - if no valid SpatialMetaData were found
2188 / 1 - if SpatiaLite-like (legacy) SpatialMetadata were found
2189 / 2 - if FDO-OGR-like SpatialMetadata were found
2190 / 3 - if SpatiaLite-like (current) SpatialMetadata were
2191 / 4 - if GeoPackage SpatialMetadata were found
2192 /
2193 */
2194     sqlite3 *sqlite = (sqlite3 *) handle;
2195     char *xdb_prefix;
2196     int spatialite_legacy_rs = 0;
2197     int spatialite_rs = 0;
2198     int fdo_rs = 0;
2199     int spatialite_legacy_gc = 0;
2200     int spatialite_gc = 0;
2201     int fdo_gc = 0;
2202     int rs_srid = 0;
2203     int auth_name = 0;
2204     int auth_srid = 0;
2205     int srtext = 0;
2206     int ref_sys_name = 0;
2207     int proj4text = 0;
2208     int f_table_name = 0;
2209     int f_geometry_column = 0;
2210     int geometry_type = 0;
2211     int coord_dimension = 0;
2212     int gc_srid = 0;
2213     int geometry_format = 0;
2214     int type = 0;
2215     int spatial_index_enabled = 0;
2216     char sql[1024];
2217     int ret;
2218     const char *name;
2219     int i;
2220     char **results;
2221     int rows;
2222     int columns;
2223 
2224     if (!checkDatabase (handle, db_prefix))
2225 	return -1;
2226 /* checking the GEOMETRY_COLUMNS table */
2227     if (db_prefix == NULL)
2228 	db_prefix = "main";
2229     xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2230     sprintf (sql, "PRAGMA \"%s\".table_info(geometry_columns)", xdb_prefix);
2231     free (xdb_prefix);
2232     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
2233     if (ret != SQLITE_OK)
2234 	goto unknown;
2235     if (rows < 1)
2236 	;
2237     else
2238       {
2239 	  for (i = 1; i <= rows; i++)
2240 	    {
2241 		name = results[(i * columns) + 1];
2242 		if (strcasecmp (name, "f_table_name") == 0)
2243 		    f_table_name = 1;
2244 		if (strcasecmp (name, "f_geometry_column") == 0)
2245 		    f_geometry_column = 1;
2246 		if (strcasecmp (name, "geometry_type") == 0)
2247 		    geometry_type = 1;
2248 		if (strcasecmp (name, "coord_dimension") == 0)
2249 		    coord_dimension = 1;
2250 		if (strcasecmp (name, "srid") == 0)
2251 		    gc_srid = 1;
2252 		if (strcasecmp (name, "geometry_format") == 0)
2253 		    geometry_format = 1;
2254 		if (strcasecmp (name, "type") == 0)
2255 		    type = 1;
2256 		if (strcasecmp (name, "spatial_index_enabled") == 0)
2257 		    spatial_index_enabled = 1;
2258 	    }
2259       }
2260     sqlite3_free_table (results);
2261     if (f_table_name && f_geometry_column && type && coord_dimension
2262 	&& gc_srid && spatial_index_enabled)
2263 	spatialite_legacy_gc = 1;
2264     if (f_table_name && f_geometry_column && geometry_type && coord_dimension
2265 	&& gc_srid && spatial_index_enabled)
2266 	spatialite_gc = 1;
2267     if (f_table_name && f_geometry_column && geometry_type && coord_dimension
2268 	&& gc_srid && geometry_format)
2269 	fdo_gc = 1;
2270 /* checking the SPATIAL_REF_SYS table */
2271     strcpy (sql, "PRAGMA table_info(spatial_ref_sys)");
2272     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
2273     if (ret != SQLITE_OK)
2274 	goto unknown;
2275     if (rows < 1)
2276 	;
2277     else
2278       {
2279 	  for (i = 1; i <= rows; i++)
2280 	    {
2281 		name = results[(i * columns) + 1];
2282 		if (strcasecmp (name, "srid") == 0)
2283 		    rs_srid = 1;
2284 		if (strcasecmp (name, "auth_name") == 0)
2285 		    auth_name = 1;
2286 		if (strcasecmp (name, "auth_srid") == 0)
2287 		    auth_srid = 1;
2288 		if (strcasecmp (name, "srtext") == 0)
2289 		    srtext = 1;
2290 		if (strcasecmp (name, "ref_sys_name") == 0)
2291 		    ref_sys_name = 1;
2292 		if (strcasecmp (name, "proj4text") == 0)
2293 		    proj4text = 1;
2294 	    }
2295       }
2296     sqlite3_free_table (results);
2297     if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text
2298 	&& srtext)
2299 	spatialite_rs = 1;
2300     if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text)
2301 	spatialite_legacy_rs = 1;
2302     if (rs_srid && auth_name && auth_srid && srtext)
2303 	fdo_rs = 1;
2304 /* verifying the MetaData format */
2305     if (spatialite_legacy_gc && spatialite_legacy_rs)
2306 	return 1;
2307     if (fdo_gc && fdo_rs)
2308 	return 2;
2309     if (spatialite_gc && spatialite_rs)
2310 	return 3;
2311   unknown:
2312     if (checkGeoPackage (sqlite, db_prefix))
2313 	return 4;
2314     return 0;
2315 }
2316 
2317 static void
add_fdo_table(struct fdo_table ** first,struct fdo_table ** last,const char * table,int len)2318 add_fdo_table (struct fdo_table **first, struct fdo_table **last,
2319 	       const char *table, int len)
2320 {
2321 /* adds an FDO-OGR styled Geometry Table to corresponding linked list */
2322     struct fdo_table *p = malloc (sizeof (struct fdo_table));
2323     p->table = malloc (len + 1);
2324     strcpy (p->table, table);
2325     p->next = NULL;
2326     if (!(*first))
2327 	(*first) = p;
2328     if ((*last))
2329 	(*last)->next = p;
2330     (*last) = p;
2331 }
2332 
2333 static void
free_fdo_tables(struct fdo_table * first)2334 free_fdo_tables (struct fdo_table *first)
2335 {
2336 /* memory cleanup; destroying the FDO-OGR tables linked list */
2337     struct fdo_table *p;
2338     struct fdo_table *pn;
2339     p = first;
2340     while (p)
2341       {
2342 	  pn = p->next;
2343 	  if (p->table)
2344 	      free (p->table);
2345 	  free (p);
2346 	  p = pn;
2347       }
2348 }
2349 
2350 static void
fnct_AutoFDOStart(sqlite3_context * context,int argc,sqlite3_value ** argv)2351 fnct_AutoFDOStart (sqlite3_context * context, int argc, sqlite3_value ** argv)
2352 {
2353 /* SQL function:
2354 / AutoFDOStart(void)
2355 /     or
2356 / AutoFDOStart(db_prefix TEXT)
2357 /
2358 / for FDO-OGR interoperability:
2359 / tests the SpatialMetadata type, then automatically
2360 / creating a VirtualFDO table for each FDO-OGR main table
2361 / declared within FDO-styled SpatialMetadata
2362 /
2363 */
2364     int ret;
2365     const char *db_prefix = "main";
2366     const char *name;
2367     int i;
2368     char **results;
2369     int rows;
2370     int columns;
2371     char *sql_statement;
2372     int count = 0;
2373     struct fdo_table *first = NULL;
2374     struct fdo_table *last = NULL;
2375     struct fdo_table *p;
2376     int len;
2377     char *xname;
2378     char *xxname;
2379     char *xtable;
2380     sqlite3 *sqlite = sqlite3_context_db_handle (context);
2381     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2382     if (argc == 1)
2383       {
2384 	  if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
2385 	      goto null_prefix;
2386 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
2387 	    {
2388 		sqlite3_result_int (context, -1);
2389 		return;
2390 	    }
2391 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
2392       }
2393   null_prefix:
2394     if (checkSpatialMetaData_ex (sqlite, db_prefix) == 2)
2395       {
2396 	  /* ok, creating VirtualFDO tables */
2397 	  char *xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2398 	  sql_statement =
2399 	      sqlite3_mprintf
2400 	      ("SELECT DISTINCT f_table_name FROM \"%s\".geometry_columns",
2401 	       xdb_prefix);
2402 	  free (xdb_prefix);
2403 	  ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows,
2404 				   &columns, NULL);
2405 	  sqlite3_free (sql_statement);
2406 	  if (ret != SQLITE_OK)
2407 	      goto error;
2408 	  if (rows < 1)
2409 	      ;
2410 	  else
2411 	    {
2412 		for (i = 1; i <= rows; i++)
2413 		  {
2414 		      name = results[(i * columns) + 0];
2415 		      if (name)
2416 			{
2417 			    len = strlen (name);
2418 			    add_fdo_table (&first, &last, name, len);
2419 			}
2420 		  }
2421 	    }
2422 	  sqlite3_free_table (results);
2423 	  p = first;
2424 	  while (p)
2425 	    {
2426 		/* destroying the VirtualFDO table [if existing] */
2427 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2428 		xxname = sqlite3_mprintf ("fdo_%s", p->table);
2429 		xname = gaiaDoubleQuotedSql (xxname);
2430 		sqlite3_free (xxname);
2431 		sql_statement =
2432 		    sqlite3_mprintf ("DROP TABLE IF EXISTS \"%s\".\"%s\"",
2433 				     xdb_prefix, xname);
2434 		free (xname);
2435 		free (xdb_prefix);
2436 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
2437 		sqlite3_free (sql_statement);
2438 		if (ret != SQLITE_OK)
2439 		    goto error;
2440 		/* creating the VirtualFDO table */
2441 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2442 		xxname = sqlite3_mprintf ("fdo_%s", p->table);
2443 		xname = gaiaDoubleQuotedSql (xxname);
2444 		sqlite3_free (xxname);
2445 		xtable = gaiaDoubleQuotedSql (p->table);
2446 		sql_statement =
2447 		    sqlite3_mprintf
2448 		    ("CREATE VIRTUAL TABLE \"%s\".\"%s\" USING VirtualFDO(\"%s\", \"%s\")",
2449 		     xdb_prefix, xname, xdb_prefix, xtable);
2450 		free (xname);
2451 		free (xtable);
2452 		free (xdb_prefix);
2453 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
2454 		sqlite3_free (sql_statement);
2455 		if (ret != SQLITE_OK)
2456 		    goto error;
2457 		count++;
2458 		p = p->next;
2459 	    }
2460 	error:
2461 	  free_fdo_tables (first);
2462 	  sqlite3_result_int (context, count);
2463 	  return;
2464       }
2465     sqlite3_result_int (context, 0);
2466     return;
2467 }
2468 
2469 static void
fnct_AutoFDOStop(sqlite3_context * context,int argc,sqlite3_value ** argv)2470 fnct_AutoFDOStop (sqlite3_context * context, int argc, sqlite3_value ** argv)
2471 {
2472 /* SQL function:
2473 / AutoFDOStop(void)
2474 /     or
2475 / AutoFDOStop(db_prefix TEXT)
2476 /
2477 / for FDO-OGR interoperability:
2478 / tests the SpatialMetadata type, then automatically
2479 / removes any VirtualFDO table
2480 /
2481 */
2482     int ret;
2483     const char *db_prefix = "main";
2484     const char *name;
2485     int i;
2486     char **results;
2487     int rows;
2488     int columns;
2489     char *sql_statement;
2490     int count = 0;
2491     struct fdo_table *first = NULL;
2492     struct fdo_table *last = NULL;
2493     struct fdo_table *p;
2494     int len;
2495     char *xname;
2496     char *xxname;
2497     sqlite3 *sqlite = sqlite3_context_db_handle (context);
2498     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2499     if (argc == 1)
2500       {
2501 	  if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
2502 	      goto null_prefix;
2503 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
2504 	    {
2505 		sqlite3_result_int (context, -1);
2506 		return;
2507 	    }
2508 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
2509       }
2510   null_prefix:
2511     if (checkSpatialMetaData_ex (sqlite, db_prefix) == 2)
2512       {
2513 	  /* ok, removing VirtualFDO tables */
2514 	  char *xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2515 	  sql_statement =
2516 	      sqlite3_mprintf
2517 	      ("SELECT DISTINCT f_table_name FROM \"%s\".geometry_columns",
2518 	       xdb_prefix);
2519 	  free (xdb_prefix);
2520 	  ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows,
2521 				   &columns, NULL);
2522 	  if (ret != SQLITE_OK)
2523 	      goto error;
2524 	  if (rows < 1)
2525 	      ;
2526 	  else
2527 	    {
2528 		for (i = 1; i <= rows; i++)
2529 		  {
2530 		      name = results[(i * columns) + 0];
2531 		      if (name)
2532 			{
2533 			    len = strlen (name);
2534 			    add_fdo_table (&first, &last, name, len);
2535 			}
2536 		  }
2537 	    }
2538 	  sqlite3_free_table (results);
2539 	  p = first;
2540 	  while (p)
2541 	    {
2542 		/* destroying the VirtualFDO table [if existing] */
2543 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
2544 		xxname = sqlite3_mprintf ("fdo_%s", p->table);
2545 		xname = gaiaDoubleQuotedSql (xxname);
2546 		sqlite3_free (xxname);
2547 		sql_statement =
2548 		    sqlite3_mprintf ("DROP TABLE IF EXISTS \"%s\".\"%s\"",
2549 				     xdb_prefix, xname);
2550 		free (xname);
2551 		free (xdb_prefix);
2552 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
2553 		sqlite3_free (sql_statement);
2554 		if (ret != SQLITE_OK)
2555 		    goto error;
2556 		count++;
2557 		p = p->next;
2558 	    }
2559 	error:
2560 	  free_fdo_tables (first);
2561 	  sqlite3_result_int (context, count);
2562 	  return;
2563       }
2564     sqlite3_result_int (context, 0);
2565     return;
2566 }
2567 
2568 static void
fnct_CheckSpatialMetaData(sqlite3_context * context,int argc,sqlite3_value ** argv)2569 fnct_CheckSpatialMetaData (sqlite3_context * context, int argc,
2570 			   sqlite3_value ** argv)
2571 {
2572 /* SQL function:
2573 / CheckSpatialMetaData(void)
2574 /     or
2575 / CheckSpatialMetaData(db_prefix TEXT)
2576 /
2577 / for FDO-OGR interoperability:
2578 / tests the SpatialMetadata type, returning:
2579 /
2580 / -1 - on invalid args or if no ATTACHED-DB idenfied by db_prefix exists
2581 / 0 - if no valid SpatialMetaData were found
2582 / 1 - if SpatiaLite-legacy SpatialMetadata were found
2583 / 2 - if FDO-OGR-like SpatialMetadata were found
2584 / 3 - if SpatiaLite-current SpatialMetadata were found
2585 / 4 - if GeoPackage SpatialMetadata were found
2586 /
2587 */
2588     const char *db_prefix = NULL;
2589     sqlite3 *sqlite;
2590     int ret;
2591     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2592     if (argc == 1)
2593       {
2594 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
2595 	    {
2596 		sqlite3_result_int (context, -1);
2597 		return;
2598 	    }
2599 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
2600       }
2601     sqlite = sqlite3_context_db_handle (context);
2602     ret = checkSpatialMetaData_ex (sqlite, db_prefix);
2603     sqlite3_result_int (context, ret);
2604     return;
2605 }
2606 
2607 static void
fnct_InitSpatialMetaData(sqlite3_context * context,int argc,sqlite3_value ** argv)2608 fnct_InitSpatialMetaData (sqlite3_context * context, int argc,
2609 			  sqlite3_value ** argv)
2610 {
2611 /* SQL function:
2612 / InitSpatialMetaData()
2613 /     or
2614 / InitSpatialMetaData(text mode)
2615 /     or
2616 / InitSpatialMetaData(integer transaction)
2617 /     or
2618 / InitSpatialMetaData(integer transaction, text mode)
2619 /
2620 / creates the SPATIAL_REF_SYS and GEOMETRY_COLUMNS tables
2621 / returns 1 on success
2622 / 0 on failure
2623 */
2624     char sql[8192];
2625     char *errMsg = NULL;
2626     int ret;
2627     int transaction = 0;
2628     const char *xmode;
2629     int mode = GAIA_EPSG_ANY;
2630     sqlite3 *sqlite = sqlite3_context_db_handle (context);
2631     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2632     if (argc == 1)
2633       {
2634 	  if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
2635 	    {
2636 		xmode = (const char *) sqlite3_value_text (argv[0]);
2637 		if (strcasecmp (xmode, "NONE") == 0
2638 		    || strcasecmp (xmode, "EMPTY") == 0)
2639 		    mode = GAIA_EPSG_NONE;
2640 		if (strcasecmp (xmode, "WGS84") == 0
2641 		    || strcasecmp (xmode, "WGS84_ONLY") == 0)
2642 		    mode = GAIA_EPSG_WGS84_ONLY;
2643 	    }
2644 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
2645 	      transaction = sqlite3_value_int (argv[0]);
2646 	  else
2647 	    {
2648 		spatialite_e
2649 		    ("InitSpatialMetaData() error: argument 1 is not of the String or Integer type\n");
2650 		sqlite3_result_int (context, 0);
2651 		return;
2652 	    }
2653       }
2654     if (argc == 2)
2655       {
2656 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
2657 	    {
2658 		spatialite_e
2659 		    ("InitSpatialMetaData() error: argument 1 is not of the Integer type\n");
2660 		sqlite3_result_int (context, 0);
2661 		return;
2662 	    }
2663 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
2664 	    {
2665 		spatialite_e
2666 		    ("InitSpatialMetaData() error: argument 2 is not of the String type\n");
2667 		sqlite3_result_int (context, 0);
2668 		return;
2669 	    }
2670 	  transaction = sqlite3_value_int (argv[0]);
2671 	  xmode = (const char *) sqlite3_value_text (argv[1]);
2672 	  if (strcasecmp (xmode, "NONE") == 0
2673 	      || strcasecmp (xmode, "EMPTY") == 0)
2674 	      mode = GAIA_EPSG_NONE;
2675 	  if (strcasecmp (xmode, "WGS84") == 0
2676 	      || strcasecmp (xmode, "WGS84_ONLY") == 0)
2677 	      mode = GAIA_EPSG_WGS84_ONLY;
2678       }
2679 
2680     if (transaction)
2681       {
2682 	  /* starting a Transaction */
2683 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
2684 	  if (ret != SQLITE_OK)
2685 	      goto error;
2686       }
2687 
2688 /* creating the SPATIAL_REF_SYS table */
2689     strcpy (sql, "CREATE TABLE spatial_ref_sys (\n");
2690     strcat (sql, "srid INTEGER NOT NULL PRIMARY KEY,\n");
2691     strcat (sql, "auth_name TEXT NOT NULL,\n");
2692     strcat (sql, "auth_srid INTEGER NOT NULL,\n");
2693     strcat (sql, "ref_sys_name TEXT NOT NULL DEFAULT 'Unknown',\n");
2694     strcat (sql, "proj4text TEXT NOT NULL,\n");
2695     strcat (sql, "srtext TEXT NOT NULL DEFAULT 'Undefined')");
2696     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2697     if (ret != SQLITE_OK)
2698 	goto error;
2699     strcpy (sql, "CREATE UNIQUE INDEX idx_spatial_ref_sys \n");
2700     strcat (sql, "ON spatial_ref_sys (auth_srid, auth_name)");
2701     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2702     if (ret != SQLITE_OK)
2703 	goto error;
2704     updateSpatiaLiteHistory (sqlite, "spatial_ref_sys", NULL,
2705 			     "table successfully created");
2706 
2707 /* creating the GEOMETRY_COLUMNS table */
2708     if (!createGeometryColumns (sqlite))
2709 	goto error;
2710 
2711 /* creating the GEOM_COLS_REF_SYS view */
2712     strcpy (sql, "CREATE VIEW geom_cols_ref_sys AS\n");
2713     strcat (sql, "SELECT f_table_name, f_geometry_column, geometry_type,\n");
2714     strcat (sql, "coord_dimension, spatial_ref_sys.srid AS srid,\n");
2715     strcat (sql, "auth_name, auth_srid, ref_sys_name, proj4text, srtext\n");
2716     strcat (sql, "FROM geometry_columns, spatial_ref_sys\n");
2717     strcat (sql, "WHERE geometry_columns.srid = spatial_ref_sys.srid");
2718     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2719     updateSpatiaLiteHistory (sqlite, "geom_cols_ref_sys", NULL,
2720 			     "view 'geom_cols_ref_sys' successfully created");
2721     if (ret != SQLITE_OK)
2722 	goto error;
2723     if (spatial_ref_sys_init2 (sqlite, mode, 0))
2724       {
2725 	  if (mode == GAIA_EPSG_NONE)
2726 	      updateSpatiaLiteHistory (sqlite, "spatial_ref_sys", NULL,
2727 				       "table successfully created [empty]");
2728 	  else
2729 	      updateSpatiaLiteHistory (sqlite, "spatial_ref_sys", NULL,
2730 				       "table successfully populated");
2731       }
2732     if (!createAdvancedMetaData (sqlite))
2733 	goto error;
2734 /* creating the SpatialIndex VIRTUAL TABLE */
2735     strcpy (sql, "CREATE VIRTUAL TABLE SpatialIndex ");
2736     strcat (sql, "USING VirtualSpatialIndex()");
2737     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2738     if (ret != SQLITE_OK)
2739 	goto error;
2740 /* creating the ElementaryGeometries VIRTUAL TABLE */
2741     strcpy (sql, "CREATE VIRTUAL TABLE ElementaryGeometries ");
2742     strcat (sql, "USING VirtualElementary()");
2743     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2744     if (ret != SQLITE_OK)
2745 	goto error;
2746 
2747 #ifndef OMIT_KNN		/* only if KNN is enabled */
2748 /* creating the KNN VIRTUAL TABLE */
2749     strcpy (sql, "CREATE VIRTUAL TABLE KNN ");
2750     strcat (sql, "USING VirtualKNN()");
2751     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2752     if (ret != SQLITE_OK)
2753 	goto error;
2754 #endif /* end KNN conditional */
2755 
2756     if (transaction)
2757       {
2758 	  /* confirming the still pending Transaction */
2759 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
2760 	  if (ret != SQLITE_OK)
2761 	      goto error;
2762       }
2763 
2764     sqlite3_result_int (context, 1);
2765     return;
2766   error:
2767     spatialite_e ("InitSpatiaMetaData() error:\"%s\"\n", errMsg);
2768     sqlite3_free (errMsg);
2769     if (transaction)
2770       {
2771 	  /* performing a Rollback */
2772 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
2773 	  if (ret != SQLITE_OK)
2774 	    {
2775 		spatialite_e (" InitSpatiaMetaData() error:\"%s\"\n", errMsg);
2776 		sqlite3_free (errMsg);
2777 	    }
2778       }
2779     sqlite3_result_int (context, 0);
2780     return;
2781 }
2782 
2783 static void
fnct_InitAdvancedMetaData(sqlite3_context * context,int argc,sqlite3_value ** argv)2784 fnct_InitAdvancedMetaData (sqlite3_context * context, int argc,
2785 			   sqlite3_value ** argv)
2786 {
2787 /* SQL function:
2788 / InitAdvancedlMetaData()
2789 /     or
2790 / InitAdvancedMetaData(integer transaction)
2791 /
2792 / safely creates several ancillary MetaData tables
2793 / returns 1 on success
2794 / 0 on failure
2795 */
2796     char sql[8192];
2797     char *errMsg = NULL;
2798     int ret;
2799     int transaction = 0;
2800     sqlite3 *sqlite = sqlite3_context_db_handle (context);
2801     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2802     if (argc == 1)
2803       {
2804 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
2805 	    {
2806 		spatialite_e
2807 		    ("InitAdvancedMetaData() error: argument 1 is not of the Integer type\n");
2808 		sqlite3_result_int (context, 0);
2809 		return;
2810 	    }
2811 	  transaction = sqlite3_value_int (argv[0]);
2812       }
2813 
2814     if (transaction)
2815       {
2816 	  /* starting a Transaction */
2817 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
2818 	  if (ret != SQLITE_OK)
2819 	      goto error;
2820       }
2821 /* creating the GEOM_COLS_REF_SYS view */
2822     strcpy (sql, "CREATE VIEW IF NOT EXISTS geom_cols_ref_sys AS\n");
2823     strcat (sql, "SELECT f_table_name, f_geometry_column, geometry_type,\n");
2824     strcat (sql, "coord_dimension, spatial_ref_sys.srid AS srid,\n");
2825     strcat (sql, "auth_name, auth_srid, ref_sys_name, proj4text, srtext\n");
2826     strcat (sql, "FROM geometry_columns, spatial_ref_sys\n");
2827     strcat (sql, "WHERE geometry_columns.srid = spatial_ref_sys.srid");
2828     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2829     updateSpatiaLiteHistory (sqlite, "geom_cols_ref_sys", NULL,
2830 			     "view 'geom_cols_ref_sys' successfully created");
2831     if (ret != SQLITE_OK)
2832 	goto error;
2833     if (!createAdvancedMetaData (sqlite))
2834 	goto error;
2835 /* creating the SpatialIndex VIRTUAL TABLE */
2836     strcpy (sql, "CREATE VIRTUAL TABLE IF NOT EXISTS SpatialIndex ");
2837     strcat (sql, "USING VirtualSpatialIndex()");
2838     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2839     if (ret != SQLITE_OK)
2840 	goto error;
2841 /* creating the ElementaryGeometries VIRTUAL TABLE */
2842     strcpy (sql, "CREATE VIRTUAL TABLE IF NOT EXISTS ElementaryGeometries ");
2843     strcat (sql, "USING VirtualElementary()");
2844     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2845     if (ret != SQLITE_OK)
2846 	goto error;
2847 
2848 #ifndef OMIT_KNN		/* only if KNN is enabled */
2849 /* creating the KNN VIRTUAL TABLE */
2850     strcpy (sql, "CREATE VIRTUAL TABLE IF NOT EXISTS KNN ");
2851     strcat (sql, "USING VirtualKNN()");
2852     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
2853     if (ret != SQLITE_OK)
2854 	goto error;
2855 #endif /* end KNN conditional */
2856 
2857     if (transaction)
2858       {
2859 	  /* confirming the still pending Transaction */
2860 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
2861 	  if (ret != SQLITE_OK)
2862 	      goto error;
2863       }
2864 
2865     sqlite3_result_int (context, 1);
2866     return;
2867   error:
2868     spatialite_e ("InitSpatiaMetaData() error:\"%s\"\n", errMsg);
2869     sqlite3_free (errMsg);
2870     if (transaction)
2871       {
2872 	  /* performing a Rollback */
2873 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
2874 	  if (ret != SQLITE_OK)
2875 	    {
2876 		spatialite_e (" InitSpatiaMetaData() error:\"%s\"\n", errMsg);
2877 		sqlite3_free (errMsg);
2878 	    }
2879       }
2880     sqlite3_result_int (context, 0);
2881     return;
2882 }
2883 
2884 static int
do_execute_sql_with_retval(sqlite3 * sqlite,const char * sql,char ** errMsg)2885 do_execute_sql_with_retval (sqlite3 * sqlite, const char *sql, char **errMsg)
2886 {
2887 /* helper function for InitSpatialMetaDataFull */
2888     int retval = 0;
2889     int ret;
2890     int i;
2891     char **results;
2892     int rows;
2893     int columns;
2894     char *msg = NULL;
2895 
2896     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &msg);
2897     if (ret != SQLITE_OK)
2898 	goto end;
2899     if (rows < 1)
2900 	;
2901     else
2902       {
2903 	  for (i = 1; i <= rows; i++)
2904 	    {
2905 		if (atoi (results[(i * columns) + 0]) == 1)
2906 		    retval = 1;
2907 	    }
2908       }
2909     sqlite3_free_table (results);
2910 
2911   end:
2912     *errMsg = msg;
2913     return retval;
2914 }
2915 
2916 static void
fnct_InitSpatialMetaDataFull(sqlite3_context * context,int argc,sqlite3_value ** argv)2917 fnct_InitSpatialMetaDataFull (sqlite3_context * context, int argc,
2918 			      sqlite3_value ** argv)
2919 {
2920 /* SQL function:
2921 / InitSpatialMetaDataFull()
2922 /     or
2923 / InitSpatialMetaDataFull(text mode)
2924 /     or
2925 / InitSpatialMetaDataFull(integer transaction)
2926 /     or
2927 / InitSpatialMetaDataFull(integer transaction, text mode)
2928 /
2929 / conveniency "super" function internally calling in a single shot:
2930 /     - InitSpatialMetaData()
2931 /     - CreateIsoMetadataTables()
2932 /     - CreateRasterCoveragesTable()
2933 /     - CreateVectorCoveragesTables()
2934 /     - CreateTopoTables()
2935 /     - CreateStylingTables()
2936 /     - WMS_CreateTables()
2937 /     - StoredProc_CreateTables()
2938 / returns 1 on success
2939 / 0 on failure
2940 */
2941     char *errMsg = NULL;
2942     int ret;
2943     int transaction = 0;
2944     const char *xmode = NULL;
2945     int retval;
2946     char *sql;
2947     int ok_isometa = 0;
2948     sqlite3 *sqlite = sqlite3_context_db_handle (context);
2949     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
2950     if (argc == 1)
2951       {
2952 	  if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
2953 	    {
2954 		xmode = (const char *) sqlite3_value_text (argv[0]);
2955 	    }
2956 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
2957 	      transaction = sqlite3_value_int (argv[0]);
2958 	  else
2959 	    {
2960 		spatialite_e
2961 		    ("InitSpatialMetaDataFull() error: argument 1 is not of the String or Integer type\n");
2962 		sqlite3_result_int (context, 0);
2963 		return;
2964 	    }
2965       }
2966     if (argc == 2)
2967       {
2968 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
2969 	    {
2970 		spatialite_e
2971 		    ("InitSpatialMetaDataFull() error: argument 1 is not of the Integer type\n");
2972 		sqlite3_result_int (context, 0);
2973 		return;
2974 	    }
2975 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
2976 	    {
2977 		spatialite_e
2978 		    ("InitSpatialMetaDataFull() error: argument 2 is not of the String type\n");
2979 		sqlite3_result_int (context, 0);
2980 		return;
2981 	    }
2982 	  transaction = sqlite3_value_int (argv[0]);
2983 	  xmode = (const char *) sqlite3_value_text (argv[1]);
2984       }
2985 
2986     if (transaction)
2987       {
2988 	  /* starting a Transaction */
2989 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
2990 	  if (ret != SQLITE_OK)
2991 	      goto error;
2992       }
2993 
2994 /* executing InitSpatialMetaData() */
2995     if (xmode != NULL)
2996 	sql = sqlite3_mprintf ("SELECT InitSpatialMetaData(0, %Q)", xmode);
2997     else
2998 	sql = sqlite3_mprintf ("SELECT InitSpatialMetaData(0)");
2999     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3000     sqlite3_free (sql);
3001     if (retval != 1)
3002 	goto error;
3003     if (!createAdvancedMetaData (sqlite))
3004 	goto error;
3005 
3006 #ifdef ENABLE_LIBXML2		/* only if LibXML2 support is available */
3007     ok_isometa = 1;
3008     if (xmode != NULL)
3009       {
3010 	  if (strcasecmp (xmode, "NONE") == 0
3011 	      || strcasecmp (xmode, "EMPTY") == 0)
3012 	      ok_isometa = 0;
3013       }
3014     if (ok_isometa)
3015       {
3016 	  /* executing CreateIsoMetadataTables() */
3017 	  sql = sqlite3_mprintf ("SELECT CreateIsoMetadataTables()");
3018 	  retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3019 	  sqlite3_free (sql);
3020 	  if (retval != 1)
3021 	      goto error;
3022       }
3023 #endif
3024 
3025 /* executing CreateRasterCoveragesTable() */
3026     sql = sqlite3_mprintf ("SELECT CreateRasterCoveragesTable()");
3027     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3028     sqlite3_free (sql);
3029     if (retval != 1)
3030 	goto error;
3031 
3032 /* executing CreateVectorCoveragesTables() */
3033     sql = sqlite3_mprintf ("SELECT CreateVectorCoveragesTables()");
3034     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3035     sqlite3_free (sql);
3036     if (retval != 1)
3037 	goto error;
3038 
3039 #ifdef ENABLE_RTTOPO		/* only if RtTopo support is available */
3040 /* executing CreateTopoTables() */
3041     sql = sqlite3_mprintf ("SELECT CreateTopoTables()");
3042     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3043     sqlite3_free (sql);
3044     if (retval != 1)
3045 	goto error;
3046 #endif
3047 
3048 #ifdef ENABLE_LIBXML2		/* only if LibXML2 support is available */
3049 /* executing CreateStylingTables() */
3050     sql = sqlite3_mprintf ("SELECT CreateStylingTables()");
3051     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3052     sqlite3_free (sql);
3053     if (retval != 1)
3054 	goto error;
3055 #endif
3056 
3057 /* executing WMS_CreateTables() */
3058     sql = sqlite3_mprintf ("SELECT WMS_CreateTables()");
3059     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3060     sqlite3_free (sql);
3061     if (retval != 1)
3062 	goto error;
3063 
3064 /* executing StoredProc_CreateTables() */
3065     sql = sqlite3_mprintf ("SELECT StoredProc_CreateTables()");
3066     retval = do_execute_sql_with_retval (sqlite, sql, &errMsg);
3067     sqlite3_free (sql);
3068     if (retval != 1)
3069 	goto error;
3070 
3071     if (transaction)
3072       {
3073 	  /* confirming the still pending Transaction */
3074 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
3075 	  if (ret != SQLITE_OK)
3076 	      goto error;
3077       }
3078 
3079     sqlite3_result_int (context, 1);
3080     return;
3081   error:
3082     spatialite_e ("InitSpatiaMetaDataFull() error:\"%s\"\n", errMsg);
3083     sqlite3_free (errMsg);
3084     if (transaction)
3085       {
3086 	  /* performing a Rollback */
3087 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
3088 	  if (ret != SQLITE_OK)
3089 	    {
3090 		spatialite_e (" InitSpatiaMetaDataFull() error:\"%s\"\n",
3091 			      errMsg);
3092 		sqlite3_free (errMsg);
3093 	    }
3094       }
3095     sqlite3_result_int (context, 0);
3096     return;
3097 }
3098 
3099 static void
fnct_CloneTable(sqlite3_context * context,int argc,sqlite3_value ** argv)3100 fnct_CloneTable (sqlite3_context * context, int argc, sqlite3_value ** argv)
3101 {
3102 /* SQL function:
3103 / CloneTable(text db_prefix, text in_table, text out_table, integer transaction)
3104 / CloneTable(text db_prefix, text in_table, text out_table, integer transaction,
3105 /            ... text option1 ..., ... text option2 ..., text option10)
3106 /
3107 / cloning a whole table [CREATE and then COPY]
3108 / returns 1 on success
3109 / 0 on failure (NULL on invalid arguments)
3110 */
3111     int ret;
3112     char *errMsg = NULL;
3113     const char *db_prefix;
3114     const char *in_table;
3115     const char *out_table;
3116     int transaction = 0;
3117     int active = 0;
3118     const void *cloner = NULL;
3119     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3120     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3121     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
3122 	db_prefix = "MAIN";
3123     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
3124 	db_prefix = (const char *) sqlite3_value_text (argv[0]);
3125     else
3126       {
3127 	  spatialite_e
3128 	      ("CloneTable() error: argument 1 is not of the String or TEXT type\n");
3129 	  sqlite3_result_null (context);
3130 	  return;
3131       }
3132     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
3133 	in_table = (const char *) sqlite3_value_text (argv[1]);
3134     else
3135       {
3136 	  spatialite_e
3137 	      ("CloneTable() error: argument 2 is not of the String or TEXT type\n");
3138 	  sqlite3_result_null (context);
3139 	  return;
3140       }
3141     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
3142 	out_table = (const char *) sqlite3_value_text (argv[2]);
3143     else
3144       {
3145 	  spatialite_e
3146 	      ("CloneTable() error: argument 3 is not of the String or TEXT type\n");
3147 	  sqlite3_result_null (context);
3148 	  return;
3149       }
3150     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
3151 	transaction = sqlite3_value_int (argv[3]);
3152     else
3153       {
3154 	  spatialite_e
3155 	      ("CloneTable() error: argument 4 is not of the Integer type\n");
3156 	  sqlite3_result_null (context);
3157 	  return;
3158       }
3159 
3160 /* additional options */
3161     if (argc > 4 && sqlite3_value_type (argv[4]) != SQLITE_TEXT)
3162       {
3163 	  spatialite_e
3164 	      ("CloneTable() error: argument 5 is not of the String or TEXT type\n");
3165 	  sqlite3_result_null (context);
3166 	  return;
3167       }
3168     if (argc > 5 && sqlite3_value_type (argv[5]) != SQLITE_TEXT)
3169       {
3170 	  spatialite_e
3171 	      ("CloneTable() error: argument 6 is not of the String or TEXT type\n");
3172 	  sqlite3_result_null (context);
3173 	  return;
3174       }
3175     if (argc > 6 && sqlite3_value_type (argv[6]) != SQLITE_TEXT)
3176       {
3177 	  spatialite_e
3178 	      ("CloneTable() error: argument 7 is not of the String or TEXT type\n");
3179 	  sqlite3_result_null (context);
3180 	  return;
3181       }
3182     if (argc > 7 && sqlite3_value_type (argv[7]) != SQLITE_TEXT)
3183       {
3184 	  spatialite_e
3185 	      ("CloneTable() error: argument 8 is not of the String or TEXT type\n");
3186 	  sqlite3_result_null (context);
3187 	  return;
3188       }
3189     if (argc > 8 && sqlite3_value_type (argv[8]) != SQLITE_TEXT)
3190       {
3191 	  spatialite_e
3192 	      ("CloneTable() error: argument 9 is not of the String or TEXT type\n");
3193 	  sqlite3_result_null (context);
3194 	  return;
3195       }
3196     if (argc > 9 && sqlite3_value_type (argv[9]) != SQLITE_TEXT)
3197       {
3198 	  spatialite_e
3199 	      ("CloneTable() error: argument 10 is not of the String or TEXT type\n");
3200 	  sqlite3_result_null (context);
3201 	  return;
3202       }
3203     if (argc > 10 && sqlite3_value_type (argv[10]) != SQLITE_TEXT)
3204       {
3205 	  spatialite_e
3206 	      ("CloneTable() error: argument 11 is not of the String or TEXT type\n");
3207 	  sqlite3_result_null (context);
3208 	  return;
3209       }
3210     if (argc > 11 && sqlite3_value_type (argv[11]) != SQLITE_TEXT)
3211       {
3212 	  spatialite_e
3213 	      ("CloneTable() error: argument 12 is not of the String or TEXT type\n");
3214 	  sqlite3_result_null (context);
3215 	  return;
3216       }
3217     if (argc > 12 && sqlite3_value_type (argv[12]) != SQLITE_TEXT)
3218       {
3219 	  spatialite_e
3220 	      ("CloneTable() error: argument 13 is not of the String or TEXT type\n");
3221 	  sqlite3_result_null (context);
3222 	  return;
3223       }
3224     if (argc > 13 && sqlite3_value_type (argv[13]) != SQLITE_TEXT)
3225       {
3226 	  spatialite_e
3227 	      ("CloneTable() error: argument 14 is not of the String or TEXT type\n");
3228 	  sqlite3_result_null (context);
3229 	  return;
3230       }
3231 
3232     cloner = gaiaAuxClonerCreate (sqlite, db_prefix, in_table, out_table);
3233     if (cloner == NULL)
3234       {
3235 	  sqlite3_result_null (context);
3236 	  return;
3237       }
3238 
3239 /* additional options */
3240     if (argc > 4)
3241 	gaiaAuxClonerAddOption (cloner,
3242 				(const char *) sqlite3_value_text (argv[4]));
3243     if (argc > 5)
3244 	gaiaAuxClonerAddOption (cloner,
3245 				(const char *) sqlite3_value_text (argv[5]));
3246     if (argc > 6)
3247 	gaiaAuxClonerAddOption (cloner,
3248 				(const char *) sqlite3_value_text (argv[6]));
3249     if (argc > 7)
3250 	gaiaAuxClonerAddOption (cloner,
3251 				(const char *) sqlite3_value_text (argv[7]));
3252     if (argc > 8)
3253 	gaiaAuxClonerAddOption (cloner,
3254 				(const char *) sqlite3_value_text (argv[8]));
3255     if (argc > 9)
3256 	gaiaAuxClonerAddOption (cloner,
3257 				(const char *) sqlite3_value_text (argv[9]));
3258     if (argc > 10)
3259 	gaiaAuxClonerAddOption (cloner,
3260 				(const char *) sqlite3_value_text (argv[10]));
3261     if (argc > 11)
3262 	gaiaAuxClonerAddOption (cloner,
3263 				(const char *) sqlite3_value_text (argv[11]));
3264     if (argc > 12)
3265 	gaiaAuxClonerAddOption (cloner,
3266 				(const char *) sqlite3_value_text (argv[12]));
3267     if (argc > 13)
3268 	gaiaAuxClonerAddOption (cloner,
3269 				(const char *) sqlite3_value_text (argv[13]));
3270 
3271     if (!gaiaAuxClonerCheckValidTarget (cloner))
3272 	goto error;
3273 
3274     if (transaction)
3275       {
3276 	  /* starting a Transaction */
3277 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
3278 	  if (ret != SQLITE_OK)
3279 	      goto error;
3280       }
3281     active = 1;
3282 
3283     if (!gaiaAuxClonerExecute (cloner))
3284 	goto error;
3285     gaiaAuxClonerDestroy (cloner);
3286     cloner = NULL;
3287     updateSpatiaLiteHistory (sqlite, out_table, NULL,
3288 			     "table successfully cloned");
3289 
3290     if (transaction)
3291       {
3292 	  /* confirming the still pending Transaction */
3293 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
3294 	  if (ret != SQLITE_OK)
3295 	      goto error;
3296       }
3297 
3298     sqlite3_result_int (context, 1);
3299     return;
3300   error:
3301     if (cloner != NULL)
3302 	gaiaAuxClonerDestroy (cloner);
3303     spatialite_e ("CloneTable() error:\"%s\"\n", errMsg);
3304     sqlite3_free (errMsg);
3305     if (transaction && active)
3306       {
3307 	  /* performing a Rollback */
3308 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
3309 	  if (ret != SQLITE_OK)
3310 	    {
3311 		spatialite_e ("CloneTable() error:\"%s\"\n", errMsg);
3312 		sqlite3_free (errMsg);
3313 	    }
3314       }
3315     sqlite3_result_int (context, 0);
3316     return;
3317 }
3318 
3319 static void
fnct_CreateClonedTable(sqlite3_context * context,int argc,sqlite3_value ** argv)3320 fnct_CreateClonedTable (sqlite3_context * context, int argc,
3321 			sqlite3_value ** argv)
3322 {
3323 /* SQL function:
3324 / CreateClonedTable(text db_prefix, text in_table, text out_table, integer transaction)
3325 / CreateClonedTable(text db_prefix, text in_table, text out_table, integer transaction,
3326 /            ... text option1 ..., ... text option2 ..., text option10)
3327 /
3328 / creating a cloned table [CREATE only without COPYing]
3329 / returns 1 on success
3330 / 0 on failure (NULL on invalid arguments)
3331 */
3332     int ret;
3333     char *errMsg = NULL;
3334     const char *db_prefix;
3335     const char *in_table;
3336     const char *out_table;
3337     int transaction = 0;
3338     int active = 0;
3339     const void *cloner = NULL;
3340     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3341     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3342     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
3343 	db_prefix = (const char *) sqlite3_value_text (argv[0]);
3344     else
3345       {
3346 	  spatialite_e
3347 	      ("CreateClonedTable() error: argument 1 is not of the String or TEXT type\n");
3348 	  sqlite3_result_null (context);
3349 	  return;
3350       }
3351     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
3352 	in_table = (const char *) sqlite3_value_text (argv[1]);
3353     else
3354       {
3355 	  spatialite_e
3356 	      ("CreateClonedTable() error: argument 2 is not of the String or TEXT type\n");
3357 	  sqlite3_result_null (context);
3358 	  return;
3359       }
3360     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
3361 	out_table = (const char *) sqlite3_value_text (argv[2]);
3362     else
3363       {
3364 	  spatialite_e
3365 	      ("CreateClonedTable() error: argument 3 is not of the String or TEXT type\n");
3366 	  sqlite3_result_null (context);
3367 	  return;
3368       }
3369     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
3370 	transaction = sqlite3_value_int (argv[3]);
3371     else
3372       {
3373 	  spatialite_e
3374 	      ("CreateClonedTable() error: argument 4 is not of the Integer type\n");
3375 	  sqlite3_result_null (context);
3376 	  return;
3377       }
3378 
3379 
3380 /* additional options */
3381     if (argc > 4 && sqlite3_value_type (argv[4]) != SQLITE_TEXT)
3382       {
3383 	  spatialite_e
3384 	      ("CreateClonedTable() error: argument 5 is not of the String or TEXT type\n");
3385 	  sqlite3_result_null (context);
3386 	  return;
3387       }
3388     if (argc > 5 && sqlite3_value_type (argv[5]) != SQLITE_TEXT)
3389       {
3390 	  spatialite_e
3391 	      ("CreateClonedTable() error: argument 6 is not of the String or TEXT type\n");
3392 	  sqlite3_result_null (context);
3393 	  return;
3394       }
3395     if (argc > 6 && sqlite3_value_type (argv[6]) != SQLITE_TEXT)
3396       {
3397 	  spatialite_e
3398 	      ("CreateClonedTable() error: argument 7 is not of the String or TEXT type\n");
3399 	  sqlite3_result_null (context);
3400 	  return;
3401       }
3402     if (argc > 7 && sqlite3_value_type (argv[7]) != SQLITE_TEXT)
3403       {
3404 	  spatialite_e
3405 	      ("CreateClonedTable() error: argument 8 is not of the String or TEXT type\n");
3406 	  sqlite3_result_null (context);
3407 	  return;
3408       }
3409     if (argc > 8 && sqlite3_value_type (argv[8]) != SQLITE_TEXT)
3410       {
3411 	  spatialite_e
3412 	      ("CreateClonedTable() error: argument 9 is not of the String or TEXT type\n");
3413 	  sqlite3_result_null (context);
3414 	  return;
3415       }
3416     if (argc > 9 && sqlite3_value_type (argv[9]) != SQLITE_TEXT)
3417       {
3418 	  spatialite_e
3419 	      ("CreateClonedTable() error: argument 10 is not of the String or TEXT type\n");
3420 	  sqlite3_result_null (context);
3421 	  return;
3422       }
3423     if (argc > 10 && sqlite3_value_type (argv[10]) != SQLITE_TEXT)
3424       {
3425 	  spatialite_e
3426 	      ("CreateClonedTable() error: argument 11 is not of the String or TEXT type\n");
3427 	  sqlite3_result_null (context);
3428 	  return;
3429       }
3430     if (argc > 11 && sqlite3_value_type (argv[11]) != SQLITE_TEXT)
3431       {
3432 	  spatialite_e
3433 	      ("CreateClonedTable() error: argument 12 is not of the String or TEXT type\n");
3434 	  sqlite3_result_null (context);
3435 	  return;
3436       }
3437     if (argc > 12 && sqlite3_value_type (argv[12]) != SQLITE_TEXT)
3438       {
3439 	  spatialite_e
3440 	      ("CreateClonedTable() error: argument 13 is not of the String or TEXT type\n");
3441 	  sqlite3_result_null (context);
3442 	  return;
3443       }
3444     if (argc > 13 && sqlite3_value_type (argv[13]) != SQLITE_TEXT)
3445       {
3446 	  spatialite_e
3447 	      ("CreateClonedTable() error: argument 14 is not of the String or TEXT type\n");
3448 	  sqlite3_result_null (context);
3449 	  return;
3450       }
3451 
3452     cloner = gaiaAuxClonerCreateEx (sqlite, db_prefix, in_table, out_table, 1);
3453     if (cloner == NULL)
3454       {
3455 	  sqlite3_result_null (context);
3456 	  return;
3457       }
3458 
3459 /* additional options */
3460     if (argc > 4)
3461 	gaiaAuxClonerAddOption (cloner,
3462 				(const char *) sqlite3_value_text (argv[4]));
3463     if (argc > 5)
3464 	gaiaAuxClonerAddOption (cloner,
3465 				(const char *) sqlite3_value_text (argv[5]));
3466     if (argc > 6)
3467 	gaiaAuxClonerAddOption (cloner,
3468 				(const char *) sqlite3_value_text (argv[6]));
3469     if (argc > 7)
3470 	gaiaAuxClonerAddOption (cloner,
3471 				(const char *) sqlite3_value_text (argv[7]));
3472     if (argc > 8)
3473 	gaiaAuxClonerAddOption (cloner,
3474 				(const char *) sqlite3_value_text (argv[8]));
3475     if (argc > 9)
3476 	gaiaAuxClonerAddOption (cloner,
3477 				(const char *) sqlite3_value_text (argv[9]));
3478     if (argc > 10)
3479 	gaiaAuxClonerAddOption (cloner,
3480 				(const char *) sqlite3_value_text (argv[10]));
3481     if (argc > 11)
3482 	gaiaAuxClonerAddOption (cloner,
3483 				(const char *) sqlite3_value_text (argv[11]));
3484     if (argc > 12)
3485 	gaiaAuxClonerAddOption (cloner,
3486 				(const char *) sqlite3_value_text (argv[12]));
3487     if (argc > 13)
3488 	gaiaAuxClonerAddOption (cloner,
3489 				(const char *) sqlite3_value_text (argv[13]));
3490 
3491     if (!gaiaAuxClonerCheckValidTarget (cloner))
3492 	goto error;
3493 
3494     if (transaction)
3495       {
3496 	  /* starting a Transaction */
3497 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
3498 	  if (ret != SQLITE_OK)
3499 	      goto error;
3500       }
3501     active = 1;
3502 
3503     if (!gaiaAuxClonerExecute (cloner))
3504 	goto error;
3505     gaiaAuxClonerDestroy (cloner);
3506     updateSpatiaLiteHistory (sqlite, out_table, NULL,
3507 			     "table successfully cloned");
3508 
3509     if (transaction)
3510       {
3511 	  /* confirming the still pending Transaction */
3512 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
3513 	  if (ret != SQLITE_OK)
3514 	      goto error;
3515       }
3516 
3517     sqlite3_result_int (context, 1);
3518     return;
3519   error:
3520     if (cloner != NULL)
3521 	gaiaAuxClonerDestroy (cloner);
3522     spatialite_e ("CreateClonedTable() error:\"%s\"\n", errMsg);
3523     sqlite3_free (errMsg);
3524     if (transaction && active)
3525       {
3526 	  /* performing a Rollback */
3527 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
3528 	  if (ret != SQLITE_OK)
3529 	    {
3530 		spatialite_e ("CreateClonedTable() error:\"%s\"\n", errMsg);
3531 		sqlite3_free (errMsg);
3532 	    }
3533       }
3534     sqlite3_result_int (context, 0);
3535     return;
3536 }
3537 
3538 static void
fnct_CheckGeoPackageMetaData(sqlite3_context * context,int argc,sqlite3_value ** argv)3539 fnct_CheckGeoPackageMetaData (sqlite3_context * context, int argc,
3540 			      sqlite3_value ** argv)
3541 {
3542 /* SQL function:
3543 / CheckGeoPackageMetaData(void)
3544 /     or
3545 / CheckGeoPackageMetaData(db_prefix TEXT)
3546 /
3547 / for OGC GeoPackage interoperability:
3548 / tests if GeoPackage metadata tables are found
3549 /
3550 */
3551     const char *db_prefix = NULL;
3552     sqlite3 *sqlite;
3553     int ret;
3554     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3555     if (argc == 1)
3556       {
3557 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
3558 	    {
3559 		sqlite3_result_int (context, -1);
3560 		return;
3561 	    }
3562 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
3563       }
3564     sqlite = sqlite3_context_db_handle (context);
3565     ret = checkGeoPackage (sqlite, db_prefix);
3566     sqlite3_result_int (context, ret);
3567     return;
3568 }
3569 
3570 #ifdef ENABLE_GEOPACKAGE	/* enabling GeoPackage extensions */
3571 
3572 static void
add_gpkg_table(struct gpkg_table ** first,struct gpkg_table ** last,const char * table,int len)3573 add_gpkg_table (struct gpkg_table **first, struct gpkg_table **last,
3574 		const char *table, int len)
3575 {
3576 /* adds a GPKG Geometry Table to corresponding linked list */
3577     struct gpkg_table *p = malloc (sizeof (struct gpkg_table));
3578     p->table = malloc (len + 1);
3579     strcpy (p->table, table);
3580     p->next = NULL;
3581     if (!(*first))
3582 	(*first) = p;
3583     if ((*last))
3584 	(*last)->next = p;
3585     (*last) = p;
3586 }
3587 
3588 static void
free_gpkg_tables(struct gpkg_table * first)3589 free_gpkg_tables (struct gpkg_table *first)
3590 {
3591 /* memory cleanup; destroying the GPKG tables linked list */
3592     struct gpkg_table *p;
3593     struct gpkg_table *pn;
3594     p = first;
3595     while (p)
3596       {
3597 	  pn = p->next;
3598 	  if (p->table)
3599 	      free (p->table);
3600 	  free (p);
3601 	  p = pn;
3602       }
3603 }
3604 
3605 static void
fnct_AutoGPKGStart(sqlite3_context * context,int argc,sqlite3_value ** argv)3606 fnct_AutoGPKGStart (sqlite3_context * context, int argc, sqlite3_value ** argv)
3607 {
3608 /* SQL function:
3609 / AutoGPKGStart(void)
3610 /     or
3611 / AutoGPKGStart(db_prefix TEXT)
3612 /
3613 / for OCG GeoPackage interoperability:
3614 / tests the DB layout, then automatically
3615 / creating a VirtualGPGK table for each GPKG main table
3616 / declared within gpkg_geometry_colums
3617 /
3618 */
3619     int ret;
3620     const char *db_prefix = "main";
3621     const char *name;
3622     int i;
3623     char **results;
3624     int rows;
3625     int columns;
3626     char *sql_statement;
3627     int count = 0;
3628     struct gpkg_table *first = NULL;
3629     struct gpkg_table *last = NULL;
3630     struct gpkg_table *p;
3631     int len;
3632     char *xname;
3633     char *xxname;
3634     char *xtable;
3635     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3636     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3637     if (argc == 1)
3638       {
3639 	  if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
3640 	      goto null_prefix;
3641 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
3642 	    {
3643 		sqlite3_result_int (context, -1);
3644 		return;
3645 	    }
3646 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
3647       }
3648   null_prefix:
3649     if (checkGeoPackage (sqlite, db_prefix))
3650       {
3651 	  /* ok, creating VirtualGPKG tables */
3652 	  char *xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
3653 	  sql_statement =
3654 	      sqlite3_mprintf
3655 	      ("SELECT DISTINCT table_name FROM \"%s\".gpkg_geometry_columns",
3656 	       xdb_prefix);
3657 	  free (xdb_prefix);
3658 	  ret =
3659 	      sqlite3_get_table (sqlite, sql_statement, &results, &rows,
3660 				 &columns, NULL);
3661 	  sqlite3_free (sql_statement);
3662 	  if (ret != SQLITE_OK)
3663 	      goto error;
3664 	  if (rows < 1)
3665 	      ;
3666 	  else
3667 	    {
3668 		for (i = 1; i <= rows; i++)
3669 		  {
3670 		      name = results[(i * columns) + 0];
3671 		      if (name)
3672 			{
3673 			    len = strlen (name);
3674 			    add_gpkg_table (&first, &last, name, len);
3675 			}
3676 		  }
3677 	    }
3678 	  sqlite3_free_table (results);
3679 	  p = first;
3680 	  while (p)
3681 	    {
3682 		/* destroying the VirtualGPKG table [if existing] */
3683 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
3684 		xxname = sqlite3_mprintf ("vgpkg_%s", p->table);
3685 		xname = gaiaDoubleQuotedSql (xxname);
3686 		sqlite3_free (xxname);
3687 		sql_statement =
3688 		    sqlite3_mprintf ("DROP TABLE IF EXISTS \"%s\".\"%s\"",
3689 				     xdb_prefix, xname);
3690 		free (xname);
3691 		free (xdb_prefix);
3692 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
3693 		sqlite3_free (sql_statement);
3694 		if (ret != SQLITE_OK)
3695 		    goto error;
3696 		/* creating the VirtualGPKG table */
3697 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
3698 		xxname = sqlite3_mprintf ("vgpkg_%s", p->table);
3699 		xname = gaiaDoubleQuotedSql (xxname);
3700 		sqlite3_free (xxname);
3701 		xtable = gaiaDoubleQuotedSql (p->table);
3702 		sql_statement =
3703 		    sqlite3_mprintf
3704 		    ("CREATE VIRTUAL TABLE \"%s\".\"%s\" USING VirtualGPKG(\"%s\", \"%s\")",
3705 		     xdb_prefix, xname, xdb_prefix, xtable);
3706 		free (xname);
3707 		free (xtable);
3708 		free (xdb_prefix);
3709 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
3710 		sqlite3_free (sql_statement);
3711 		if (ret != SQLITE_OK)
3712 		    goto error;
3713 		count++;
3714 		p = p->next;
3715 	    }
3716 	error:
3717 	  free_gpkg_tables (first);
3718 	  sqlite3_result_int (context, count);
3719 	  return;
3720       }
3721     sqlite3_result_int (context, 0);
3722     return;
3723 }
3724 
3725 static void
fnct_AutoGPKGStop(sqlite3_context * context,int argc,sqlite3_value ** argv)3726 fnct_AutoGPKGStop (sqlite3_context * context, int argc, sqlite3_value ** argv)
3727 {
3728 /* SQL function:
3729 / AutoGPKGStop(void)
3730 /     or
3731 / AutoGPKGStop(db_prefix TEXT)
3732 /
3733 / for OGC GeoPackage interoperability:
3734 / tests the DB layout, then automatically removes any VirtualGPKG table
3735 /
3736 */
3737     int ret;
3738     const char *db_prefix = "main";
3739     const char *name;
3740     int i;
3741     char **results;
3742     int rows;
3743     int columns;
3744     char *sql_statement;
3745     int count = 0;
3746     struct gpkg_table *first = NULL;
3747     struct gpkg_table *last = NULL;
3748     struct gpkg_table *p;
3749     int len;
3750     char *xname;
3751     char *xxname;
3752     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3753     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3754     if (argc == 1)
3755       {
3756 	  if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
3757 	      goto null_prefix;
3758 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
3759 	    {
3760 		sqlite3_result_int (context, -1);
3761 		return;
3762 	    }
3763 	  db_prefix = (const char *) sqlite3_value_text (argv[0]);
3764       }
3765   null_prefix:
3766     if (checkGeoPackage (sqlite, db_prefix))
3767       {
3768 	  /* ok, removing VirtualGPKG tables */
3769 	  char *xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
3770 	  sql_statement =
3771 	      sqlite3_mprintf
3772 	      ("SELECT DISTINCT table_name FROM \"%s\".gpkg_geometry_columns",
3773 	       xdb_prefix);
3774 	  free (xdb_prefix);
3775 	  ret =
3776 	      sqlite3_get_table (sqlite, sql_statement, &results, &rows,
3777 				 &columns, NULL);
3778 	  sqlite3_free (sql_statement);
3779 	  if (ret != SQLITE_OK)
3780 	      goto error;
3781 	  if (rows < 1)
3782 	      ;
3783 	  else
3784 	    {
3785 		for (i = 1; i <= rows; i++)
3786 		  {
3787 		      name = results[(i * columns) + 0];
3788 		      if (name)
3789 			{
3790 			    len = strlen (name);
3791 			    add_gpkg_table (&first, &last, name, len);
3792 			}
3793 		  }
3794 	    }
3795 	  sqlite3_free_table (results);
3796 	  p = first;
3797 	  while (p)
3798 	    {
3799 		/* destroying the VirtualGPKG table [if existing] */
3800 		xdb_prefix = gaiaDoubleQuotedSql (db_prefix);
3801 		xxname = sqlite3_mprintf ("vgpkg_%s", p->table);
3802 		xname = gaiaDoubleQuotedSql (xxname);
3803 		sqlite3_free (xxname);
3804 		sql_statement =
3805 		    sqlite3_mprintf ("DROP TABLE IF EXISTS \"%s\".\"%s\"",
3806 				     xdb_prefix, xname);
3807 		free (xname);
3808 		free (xdb_prefix);
3809 		ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
3810 		sqlite3_free (sql_statement);
3811 		if (ret != SQLITE_OK)
3812 		    goto error;
3813 		count++;
3814 		p = p->next;
3815 	    }
3816 	error:
3817 	  free_gpkg_tables (first);
3818 	  sqlite3_result_int (context, count);
3819 	  return;
3820       }
3821     sqlite3_result_int (context, 0);
3822     return;
3823 }
3824 
3825 #endif /* end enabling GeoPackage extensions */
3826 
3827 static void
fnct_InsertEpsgSrid(sqlite3_context * context,int argc,sqlite3_value ** argv)3828 fnct_InsertEpsgSrid (sqlite3_context * context, int argc, sqlite3_value ** argv)
3829 {
3830 /* SQL function:
3831 / InsertEpsgSrid(int srid)
3832 /
3833 / returns 1 on success: 0 on failure
3834 */
3835     int srid;
3836     int ret;
3837     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3838     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3839     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
3840 	srid = sqlite3_value_int (argv[0]);
3841     else
3842       {
3843 	  sqlite3_result_int (context, 0);
3844 	  return;
3845       }
3846     ret = insert_epsg_srid (sqlite, srid);
3847     if (!ret)
3848 	sqlite3_result_int (context, 0);
3849     else
3850 	sqlite3_result_int (context, 1);
3851 }
3852 
3853 static void
fnct_SridIsGeographic(sqlite3_context * context,int argc,sqlite3_value ** argv)3854 fnct_SridIsGeographic (sqlite3_context * context, int argc,
3855 		       sqlite3_value ** argv)
3856 {
3857 /* SQL function:
3858 / SridIsGeographic(int srid)
3859 /
3860 / returns 1 on success: 0 on failure
3861 / NULL on invalid argument
3862 */
3863     int srid;
3864     int ret;
3865     int geographic;
3866     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3867     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3868     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
3869 	srid = sqlite3_value_int (argv[0]);
3870     else
3871       {
3872 	  sqlite3_result_null (context);
3873 	  return;
3874       }
3875     ret = srid_is_geographic (sqlite, srid, &geographic);
3876     if (!ret)
3877 	sqlite3_result_null (context);
3878     else
3879       {
3880 	  if (geographic)
3881 	      sqlite3_result_int (context, 1);
3882 	  else
3883 	      sqlite3_result_int (context, 0);
3884       }
3885 }
3886 
3887 static void
fnct_SridIsProjected(sqlite3_context * context,int argc,sqlite3_value ** argv)3888 fnct_SridIsProjected (sqlite3_context * context, int argc,
3889 		      sqlite3_value ** argv)
3890 {
3891 /* SQL function:
3892 / SridIsProjected(int srid)
3893 /
3894 / returns 1 on success: 0 on failure
3895 / NULL on invalid argument
3896 */
3897     int srid;
3898     int ret;
3899     int projected;
3900     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3901     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3902     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
3903 	srid = sqlite3_value_int (argv[0]);
3904     else
3905       {
3906 	  sqlite3_result_null (context);
3907 	  return;
3908       }
3909     ret = srid_is_projected (sqlite, srid, &projected);
3910     if (!ret)
3911 	sqlite3_result_null (context);
3912     else
3913       {
3914 	  if (projected)
3915 	      sqlite3_result_int (context, 1);
3916 	  else
3917 	      sqlite3_result_int (context, 0);
3918       }
3919 }
3920 
3921 static void
fnct_SridHasFlippedAxes(sqlite3_context * context,int argc,sqlite3_value ** argv)3922 fnct_SridHasFlippedAxes (sqlite3_context * context, int argc,
3923 			 sqlite3_value ** argv)
3924 {
3925 /* SQL function:
3926 / SridHasFlippedAxes(int srid)
3927 /
3928 / returns 1 on success: 0 on failure
3929 / NULL on invalid argument
3930 */
3931     int srid;
3932     int ret;
3933     int flipped;
3934     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3935     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3936     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
3937 	srid = sqlite3_value_int (argv[0]);
3938     else
3939       {
3940 	  sqlite3_result_null (context);
3941 	  return;
3942       }
3943     ret = srid_has_flipped_axes (sqlite, srid, &flipped);
3944     if (!ret)
3945 	sqlite3_result_null (context);
3946     else
3947       {
3948 	  if (flipped)
3949 	      sqlite3_result_int (context, 1);
3950 	  else
3951 	      sqlite3_result_int (context, 0);
3952       }
3953 }
3954 
3955 static void
fnct_SridGetSpheroid(sqlite3_context * context,int argc,sqlite3_value ** argv)3956 fnct_SridGetSpheroid (sqlite3_context * context, int argc,
3957 		      sqlite3_value ** argv)
3958 {
3959 /* SQL function:
3960 / SridGetSpheroid(int srid)
3961 / or
3962 / SridGetEllipsoid(int srid)
3963 /
3964 / returns the name of the Spheroid on success
3965 / NULL on failure or on invalid argument
3966 */
3967     int srid;
3968     char *spheroid = NULL;
3969     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3970     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3971     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
3972 	srid = sqlite3_value_int (argv[0]);
3973     else
3974       {
3975 	  sqlite3_result_null (context);
3976 	  return;
3977       }
3978     spheroid = srid_get_spheroid (sqlite, srid);
3979     if (spheroid == NULL)
3980 	sqlite3_result_null (context);
3981     else
3982 	sqlite3_result_text (context, spheroid, strlen (spheroid), free);
3983 }
3984 
3985 static void
fnct_SridGetPrimeMeridian(sqlite3_context * context,int argc,sqlite3_value ** argv)3986 fnct_SridGetPrimeMeridian (sqlite3_context * context, int argc,
3987 			   sqlite3_value ** argv)
3988 {
3989 /* SQL function:
3990 / SridGetPrimeMeridian(int srid)
3991 /
3992 / returns the name of the Prime Meridian on success
3993 / NULL on failure or on invalid argument
3994 */
3995     int srid;
3996     char *prime_meridian = NULL;
3997     sqlite3 *sqlite = sqlite3_context_db_handle (context);
3998     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
3999     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
4000 	srid = sqlite3_value_int (argv[0]);
4001     else
4002       {
4003 	  sqlite3_result_null (context);
4004 	  return;
4005       }
4006     prime_meridian = srid_get_prime_meridian (sqlite, srid);
4007     if (prime_meridian == NULL)
4008 	sqlite3_result_null (context);
4009     else
4010 	sqlite3_result_text (context, prime_meridian, strlen (prime_meridian),
4011 			     free);
4012 }
4013 
4014 static void
fnct_SridGetProjection(sqlite3_context * context,int argc,sqlite3_value ** argv)4015 fnct_SridGetProjection (sqlite3_context * context, int argc,
4016 			sqlite3_value ** argv)
4017 {
4018 /* SQL function:
4019 / SridGetProjection(int srid)
4020 /
4021 / returns the name of the Projection on success
4022 / NULL on failure or on invalid argument
4023 */
4024     int srid;
4025     char *projection = NULL;
4026     sqlite3 *sqlite = sqlite3_context_db_handle (context);
4027     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
4028     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
4029 	srid = sqlite3_value_int (argv[0]);
4030     else
4031       {
4032 	  sqlite3_result_null (context);
4033 	  return;
4034       }
4035     projection = srid_get_projection (sqlite, srid);
4036     if (projection == NULL)
4037 	sqlite3_result_null (context);
4038     else
4039 	sqlite3_result_text (context, projection, strlen (projection), free);
4040 }
4041 
4042 static void
fnct_SridGetDatum(sqlite3_context * context,int argc,sqlite3_value ** argv)4043 fnct_SridGetDatum (sqlite3_context * context, int argc, sqlite3_value ** argv)
4044 {
4045 /* SQL function:
4046 / SridGetDatum(int srid)
4047 /
4048 / returns the name of the Datum on success
4049 / NULL on failure or on invalid argument
4050 */
4051     int srid;
4052     char *datum = NULL;
4053     sqlite3 *sqlite = sqlite3_context_db_handle (context);
4054     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
4055     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
4056 	srid = sqlite3_value_int (argv[0]);
4057     else
4058       {
4059 	  sqlite3_result_null (context);
4060 	  return;
4061       }
4062     datum = srid_get_datum (sqlite, srid);
4063     if (datum == NULL)
4064 	sqlite3_result_null (context);
4065     else
4066 	sqlite3_result_text (context, datum, strlen (datum), free);
4067 }
4068 
4069 static void
fnct_SridGetUnit(sqlite3_context * context,int argc,sqlite3_value ** argv)4070 fnct_SridGetUnit (sqlite3_context * context, int argc, sqlite3_value ** argv)
4071 {
4072 /* SQL function:
4073 / SridGetUnit(int srid)
4074 /
4075 / returns the name of the Spheroid on success
4076 / NULL on failure or on invalid argument
4077 */
4078     int srid;
4079     char *unit = NULL;
4080     sqlite3 *sqlite = sqlite3_context_db_handle (context);
4081     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
4082     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
4083 	srid = sqlite3_value_int (argv[0]);
4084     else
4085       {
4086 	  sqlite3_result_null (context);
4087 	  return;
4088       }
4089     unit = srid_get_unit (sqlite, srid);
4090     if (unit == NULL)
4091 	sqlite3_result_null (context);
4092     else
4093 	sqlite3_result_text (context, unit, strlen (unit), free);
4094 }
4095 
4096 static void
common_srid_axis(sqlite3_context * context,int argc,sqlite3_value ** argv,char axis,char mode)4097 common_srid_axis (sqlite3_context * context, int argc,
4098 		  sqlite3_value ** argv, char axis, char mode)
4099 {
4100 /* commonn implentation - SRID Get Axis */
4101     int srid;
4102     char *result = NULL;
4103     sqlite3 *sqlite = sqlite3_context_db_handle (context);
4104     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
4105     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
4106 	srid = sqlite3_value_int (argv[0]);
4107     else
4108       {
4109 	  sqlite3_result_null (context);
4110 	  return;
4111       }
4112     result = srid_get_axis (sqlite, srid, axis, mode);
4113     if (result == NULL)
4114 	sqlite3_result_null (context);
4115     else
4116 	sqlite3_result_text (context, result, strlen (result), free);
4117 }
4118 
4119 static void
fnct_SridGetAxis1Name(sqlite3_context * context,int argc,sqlite3_value ** argv)4120 fnct_SridGetAxis1Name (sqlite3_context * context, int argc,
4121 		       sqlite3_value ** argv)
4122 {
4123 /* SQL function:
4124 / SridGetAxis_1_Name(int srid)
4125 /
4126 / returns the name of the first Axis on success
4127 / NULL on failure or on invalid argument
4128 */
4129     common_srid_axis (context, argc, argv, SPLITE_AXIS_1, SPLITE_AXIS_NAME);
4130 }
4131 
4132 static void
fnct_SridGetAxis1Orientation(sqlite3_context * context,int argc,sqlite3_value ** argv)4133 fnct_SridGetAxis1Orientation (sqlite3_context * context, int argc,
4134 			      sqlite3_value ** argv)
4135 {
4136 /* SQL function:
4137 / SridGetAxis_1_Orientation(int srid)
4138 /
4139 / returns the orientation of the first Axis on success
4140 / NULL on failure or on invalid argument
4141 */
4142     common_srid_axis (context, argc, argv, SPLITE_AXIS_1,
4143 		      SPLITE_AXIS_ORIENTATION);
4144 }
4145 
4146 static void
fnct_SridGetAxis2Name(sqlite3_context * context,int argc,sqlite3_value ** argv)4147 fnct_SridGetAxis2Name (sqlite3_context * context, int argc,
4148 		       sqlite3_value ** argv)
4149 {
4150 /* SQL function:
4151 / SridGetAxis_2_Name(int srid)
4152 /
4153 / returns the name of the second Axis on success
4154 / NULL on failure or on invalid argument
4155 */
4156     common_srid_axis (context, argc, argv, SPLITE_AXIS_2, SPLITE_AXIS_NAME);
4157 }
4158 
4159 static void
fnct_SridGetAxis2Orientation(sqlite3_context * context,int argc,sqlite3_value ** argv)4160 fnct_SridGetAxis2Orientation (sqlite3_context * context, int argc,
4161 			      sqlite3_value ** argv)
4162 {
4163 /* SQL function:
4164 / SridGetAxis_2_Orientation(int srid)
4165 /
4166 / returns the orientation of the second Axis on success
4167 / NULL on failure or on invalid argument
4168 */
4169     common_srid_axis (context, argc, argv, SPLITE_AXIS_2,
4170 		      SPLITE_AXIS_ORIENTATION);
4171 }
4172 
4173 static int
recoverGeomColumn(sqlite3 * sqlite,const char * table,const char * column,int xtype,int dims,int srid)4174 recoverGeomColumn (sqlite3 * sqlite, const char *table,
4175 		   const char *column, int xtype, int dims, int srid)
4176 {
4177 /* checks if TABLE.COLUMN exists and has the required features */
4178     int ok = 1;
4179     int type;
4180     sqlite3_stmt *stmt;
4181     gaiaGeomCollPtr geom;
4182     const void *blob_value;
4183     int len;
4184     int ret;
4185     int i_col;
4186     int is_nullable = 1;
4187     char *p_table;
4188     char *p_column;
4189     char *sql_statement;
4190 
4191 /* testing if NOT NULL */
4192     p_table = gaiaDoubleQuotedSql (table);
4193     sql_statement = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", p_table);
4194     free (p_table);
4195     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
4196 			      &stmt, NULL);
4197     sqlite3_free (sql_statement);
4198     if (ret != SQLITE_OK)
4199       {
4200 	  spatialite_e ("recoverGeomColumn: \"%s\"\n", sqlite3_errmsg (sqlite));
4201 	  return 0;
4202       }
4203     while (1)
4204       {
4205 	  /* scrolling the result set rows */
4206 	  ret = sqlite3_step (stmt);
4207 	  if (ret == SQLITE_DONE)
4208 	      break;		/* end of result set */
4209 	  if (ret == SQLITE_ROW)
4210 	    {
4211 		if (strcasecmp
4212 		    (column, (const char *) sqlite3_column_text (stmt, 1)) == 0)
4213 		  {
4214 		      if (sqlite3_column_int (stmt, 2) != 0)
4215 			  is_nullable = 0;
4216 		  }
4217 	    }
4218       }
4219     sqlite3_finalize (stmt);
4220 
4221     p_table = gaiaDoubleQuotedSql (table);
4222     p_column = gaiaDoubleQuotedSql (column);
4223     sql_statement =
4224 	sqlite3_mprintf ("SELECT \"%s\" FROM \"%s\"", p_column, p_table);
4225     free (p_table);
4226     free (p_column);
4227 /* compiling SQL prepared statement */
4228     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
4229 			      &stmt, NULL);
4230     sqlite3_free (sql_statement);
4231     if (ret != SQLITE_OK)
4232       {
4233 	  spatialite_e ("recoverGeomColumn: error %d \"%s\"\n",
4234 			sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
4235 	  return 0;
4236       }
4237     sqlite3_reset (stmt);
4238     sqlite3_clear_bindings (stmt);
4239     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4240     sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4241     while (1)
4242       {
4243 	  /* scrolling the result set rows */
4244 	  ret = sqlite3_step (stmt);
4245 	  if (ret == SQLITE_DONE)
4246 	      break;		/* end of result set */
4247 	  if (ret == SQLITE_ROW)
4248 	    {
4249 		/* checking Geometry features */
4250 		geom = NULL;
4251 		for (i_col = 0; i_col < sqlite3_column_count (stmt); i_col++)
4252 		  {
4253 		      if (sqlite3_column_type (stmt, i_col) == SQLITE_NULL)
4254 			{
4255 			    /* found a NULL geometry */
4256 			    if (!is_nullable)
4257 				ok = 0;
4258 			}
4259 		      else if (sqlite3_column_type (stmt, i_col) != SQLITE_BLOB)
4260 			  ok = 0;
4261 		      else
4262 			{
4263 			    blob_value = sqlite3_column_blob (stmt, i_col);
4264 			    len = sqlite3_column_bytes (stmt, i_col);
4265 			    geom = gaiaFromSpatiaLiteBlobWkb (blob_value, len);
4266 			    if (!geom)
4267 				ok = 0;
4268 			    else
4269 			      {
4270 				  if (geom->DimensionModel != dims)
4271 				      ok = 0;
4272 				  if (geom->Srid != srid)
4273 				      ok = 0;
4274 				  type = gaiaGeometryType (geom);
4275 				  if (xtype == -1)
4276 				      ;	/* GEOMETRY */
4277 				  else
4278 				    {
4279 					if (xtype == type)
4280 					    ;
4281 					else
4282 					    ok = 0;
4283 				    }
4284 				  gaiaFreeGeomColl (geom);
4285 			      }
4286 			}
4287 		  }
4288 	    }
4289 	  if (!ok)
4290 	      break;
4291       }
4292     ret = sqlite3_finalize (stmt);
4293     if (ret != SQLITE_OK)
4294       {
4295 	  spatialite_e ("recoverGeomColumn: error %d \"%s\"\n",
4296 			sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
4297 	  return 0;
4298       }
4299     return ok;
4300 }
4301 
4302 static void
fnct_AddGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)4303 fnct_AddGeometryColumn (sqlite3_context * context, int argc,
4304 			sqlite3_value ** argv)
4305 {
4306 /* SQL function:
4307 / AddGeometryColumn(table, column, srid, type [ , dimension  [  , not-null ] ] )
4308 /
4309 / creates a new COLUMN of given TYPE into TABLE
4310 / returns 1 on success
4311 / 0 on failure
4312 */
4313     const char *table;
4314     const char *column;
4315     const unsigned char *type;
4316     const unsigned char *txt_dims;
4317     int xtype;
4318     int srid = -1;
4319     int srid_exists = -1;
4320     int dimension = 2;
4321     int dims = -1;
4322     int auto_dims = -1;
4323     char sql[1024];
4324     int ret;
4325     int notNull = 0;
4326     int metadata_version;
4327     sqlite3_stmt *stmt;
4328     char *p_table = NULL;
4329     char *quoted_table;
4330     char *quoted_column;
4331     const char *p_type = NULL;
4332     const char *p_dims = NULL;
4333     int n_type = 0;
4334     int n_dims = 0;
4335     char *sql_statement;
4336     sqlite3 *sqlite = sqlite3_context_db_handle (context);
4337     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
4338       {
4339 	  spatialite_e
4340 	      ("AddGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
4341 	  sqlite3_result_int (context, 0);
4342 	  return;
4343       }
4344     table = (const char *) sqlite3_value_text (argv[0]);
4345     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
4346       {
4347 	  spatialite_e
4348 	      ("AddGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
4349 	  sqlite3_result_int (context, 0);
4350 	  return;
4351       }
4352     column = (const char *) sqlite3_value_text (argv[1]);
4353     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
4354       {
4355 	  spatialite_e
4356 	      ("AddGeometryColumn() error: argument 3 [SRID] is not of the Integer type\n");
4357 	  sqlite3_result_int (context, 0);
4358 	  return;
4359       }
4360     srid = sqlite3_value_int (argv[2]);
4361     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
4362       {
4363 	  spatialite_e
4364 	      ("AddGeometryColumn() error: argument 4 [geometry_type] is not of the String type\n");
4365 	  sqlite3_result_int (context, 0);
4366 	  return;
4367       }
4368     type = sqlite3_value_text (argv[3]);
4369     if (argc > 4)
4370       {
4371 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
4372 	    {
4373 		dimension = sqlite3_value_int (argv[4]);
4374 		if (dimension == 2)
4375 		    dims = GAIA_XY;
4376 		if (dimension == 3)
4377 		    dims = GAIA_XY_Z;
4378 		if (dimension == 4)
4379 		    dims = GAIA_XY_Z_M;
4380 	    }
4381 	  else if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
4382 	    {
4383 		txt_dims = sqlite3_value_text (argv[4]);
4384 		if (strcasecmp ((char *) txt_dims, "XY") == 0)
4385 		    dims = GAIA_XY;
4386 		if (strcasecmp ((char *) txt_dims, "XYZ") == 0)
4387 		    dims = GAIA_XY_Z;
4388 		if (strcasecmp ((char *) txt_dims, "XYM") == 0)
4389 		    dims = GAIA_XY_M;
4390 		if (strcasecmp ((char *) txt_dims, "XYZM") == 0)
4391 		    dims = GAIA_XY_Z_M;
4392 	    }
4393 	  else
4394 	    {
4395 		spatialite_e
4396 		    ("AddGeometryColumn() error: argument 5 [dimension] is not of the Integer or Text type\n");
4397 		sqlite3_result_int (context, 0);
4398 		return;
4399 	    }
4400       }
4401     if (argc == 6)
4402       {
4403 	  /* optional NOT NULL arg */
4404 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
4405 	    {
4406 		spatialite_e
4407 		    ("AddGeometryColumn() error: argument 6 [not null] is not of the Integer type\n");
4408 		sqlite3_result_int (context, 0);
4409 		return;
4410 	    }
4411 	  notNull = sqlite3_value_int (argv[5]);
4412       }
4413     xtype = GAIA_UNKNOWN;
4414     if (strcasecmp ((char *) type, "POINT") == 0)
4415       {
4416 	  auto_dims = GAIA_XY;
4417 	  xtype = GAIA_POINT;
4418       }
4419     if (strcasecmp ((char *) type, "LINESTRING") == 0)
4420       {
4421 	  auto_dims = GAIA_XY;
4422 	  xtype = GAIA_LINESTRING;
4423       }
4424     if (strcasecmp ((char *) type, "POLYGON") == 0)
4425       {
4426 	  auto_dims = GAIA_XY;
4427 	  xtype = GAIA_POLYGON;
4428       }
4429     if (strcasecmp ((char *) type, "MULTIPOINT") == 0)
4430       {
4431 	  auto_dims = GAIA_XY;
4432 	  xtype = GAIA_MULTIPOINT;
4433       }
4434     if (strcasecmp ((char *) type, "MULTILINESTRING") == 0)
4435       {
4436 	  auto_dims = GAIA_XY;
4437 	  xtype = GAIA_MULTILINESTRING;
4438       }
4439     if (strcasecmp ((char *) type, "MULTIPOLYGON") == 0)
4440       {
4441 	  auto_dims = GAIA_XY;
4442 	  xtype = GAIA_MULTIPOLYGON;
4443       }
4444     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTION") == 0)
4445       {
4446 	  auto_dims = GAIA_XY;
4447 	  xtype = GAIA_GEOMETRYCOLLECTION;
4448       }
4449     if (strcasecmp ((char *) type, "GEOMETRY") == 0)
4450       {
4451 	  auto_dims = GAIA_XY;
4452 	  xtype = -1;
4453       }
4454     if (strcasecmp ((char *) type, "POINTZ") == 0)
4455       {
4456 	  auto_dims = GAIA_XY_Z;
4457 	  xtype = GAIA_POINT;
4458       }
4459     if (strcasecmp ((char *) type, "LINESTRINGZ") == 0)
4460       {
4461 	  auto_dims = GAIA_XY_Z;
4462 	  xtype = GAIA_LINESTRING;
4463       }
4464     if (strcasecmp ((char *) type, "POLYGONZ") == 0)
4465       {
4466 	  auto_dims = GAIA_XY_Z;
4467 	  xtype = GAIA_POLYGON;
4468       }
4469     if (strcasecmp ((char *) type, "MULTIPOINTZ") == 0)
4470       {
4471 	  auto_dims = GAIA_XY_Z;
4472 	  xtype = GAIA_MULTIPOINT;
4473       }
4474     if (strcasecmp ((char *) type, "MULTILINESTRINGZ") == 0)
4475       {
4476 	  auto_dims = GAIA_XY_Z;
4477 	  xtype = GAIA_MULTILINESTRING;
4478       }
4479     if (strcasecmp ((char *) type, "MULTIPOLYGONZ") == 0)
4480       {
4481 	  auto_dims = GAIA_XY_Z;
4482 	  xtype = GAIA_MULTIPOLYGON;
4483       }
4484     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZ") == 0)
4485       {
4486 	  auto_dims = GAIA_XY_Z;
4487 	  xtype = GAIA_GEOMETRYCOLLECTION;
4488       }
4489     if (strcasecmp ((char *) type, "GEOMETRYZ") == 0)
4490       {
4491 	  auto_dims = GAIA_XY_Z;
4492 	  xtype = -1;
4493       }
4494     if (strcasecmp ((char *) type, "POINTM") == 0)
4495       {
4496 	  auto_dims = GAIA_XY_M;
4497 	  xtype = GAIA_POINT;
4498       }
4499     if (strcasecmp ((char *) type, "LINESTRINGM") == 0)
4500       {
4501 	  auto_dims = GAIA_XY_M;
4502 	  xtype = GAIA_LINESTRING;
4503       }
4504     if (strcasecmp ((char *) type, "POLYGONM") == 0)
4505       {
4506 	  auto_dims = GAIA_XY_M;
4507 	  xtype = GAIA_POLYGON;
4508       }
4509     if (strcasecmp ((char *) type, "MULTIPOINTM") == 0)
4510       {
4511 	  auto_dims = GAIA_XY_M;
4512 	  xtype = GAIA_MULTIPOINT;
4513       }
4514     if (strcasecmp ((char *) type, "MULTILINESTRINGM") == 0)
4515       {
4516 	  auto_dims = GAIA_XY_M;
4517 	  xtype = GAIA_MULTILINESTRING;
4518       }
4519     if (strcasecmp ((char *) type, "MULTIPOLYGONM") == 0)
4520       {
4521 	  auto_dims = GAIA_XY_M;
4522 	  xtype = GAIA_MULTIPOLYGON;
4523       }
4524     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONM") == 0)
4525       {
4526 	  auto_dims = GAIA_XY_M;
4527 	  xtype = GAIA_GEOMETRYCOLLECTION;
4528       }
4529     if (strcasecmp ((char *) type, "GEOMETRYM") == 0)
4530       {
4531 	  auto_dims = GAIA_XY_M;
4532 	  xtype = -1;
4533       }
4534     if (strcasecmp ((char *) type, "POINTZM") == 0)
4535       {
4536 	  auto_dims = GAIA_XY_Z_M;
4537 	  xtype = GAIA_POINT;
4538       }
4539     if (strcasecmp ((char *) type, "LINESTRINGZM") == 0)
4540       {
4541 	  auto_dims = GAIA_XY_Z_M;
4542 	  xtype = GAIA_LINESTRING;
4543       }
4544     if (strcasecmp ((char *) type, "POLYGONZM") == 0)
4545       {
4546 	  auto_dims = GAIA_XY_Z_M;
4547 	  xtype = GAIA_POLYGON;
4548       }
4549     if (strcasecmp ((char *) type, "MULTIPOINTZM") == 0)
4550       {
4551 	  auto_dims = GAIA_XY_Z_M;
4552 	  xtype = GAIA_MULTIPOINT;
4553       }
4554     if (strcasecmp ((char *) type, "MULTILINESTRINGZM") == 0)
4555       {
4556 	  auto_dims = GAIA_XY_Z_M;
4557 	  xtype = GAIA_MULTILINESTRING;
4558       }
4559     if (strcasecmp ((char *) type, "MULTIPOLYGONZM") == 0)
4560       {
4561 	  auto_dims = GAIA_XY_Z_M;
4562 	  xtype = GAIA_MULTIPOLYGON;
4563       }
4564     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZM") == 0)
4565       {
4566 	  auto_dims = GAIA_XY_Z_M;
4567 	  xtype = GAIA_GEOMETRYCOLLECTION;
4568       }
4569     if (strcasecmp ((char *) type, "GEOMETRYZM") == 0)
4570       {
4571 	  auto_dims = GAIA_XY_Z_M;
4572 	  xtype = -1;
4573       }
4574     if (xtype == GAIA_UNKNOWN)
4575       {
4576 	  spatialite_e
4577 	      ("AddGeometryColumn() error: argument 4 [geometry_type] has an illegal value\n");
4578 	  sqlite3_result_int (context, 0);
4579 	  return;
4580       }
4581     if (dims < 0)
4582 	dims = auto_dims;
4583     if (dims == GAIA_XY || dims == GAIA_XY_Z || dims == GAIA_XY_M
4584 	|| dims == GAIA_XY_Z_M)
4585 	;
4586     else
4587       {
4588 	  spatialite_e
4589 	      ("AddGeometryColumn() error: argument 5 [dimension] ILLEGAL VALUE\n");
4590 	  sqlite3_result_int (context, 0);
4591 	  return;
4592       }
4593     if (auto_dims != GAIA_XY && dims != auto_dims)
4594       {
4595 	  spatialite_e
4596 	      ("AddGeometryColumn() error: argument 5 [dimension] ILLEGAL VALUE\n");
4597 	  sqlite3_result_int (context, 0);
4598 	  return;
4599       }
4600 /* checking if the table exists */
4601     strcpy (sql,
4602 	    "SELECT name FROM sqlite_master WHERE type = 'table' AND Lower(name) = Lower(?)");
4603     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4604     if (ret != SQLITE_OK)
4605       {
4606 	  spatialite_e ("AddGeometryColumn: \"%s\"\n", sqlite3_errmsg (sqlite));
4607 	  sqlite3_result_int (context, 0);
4608 	  return;
4609       }
4610     sqlite3_reset (stmt);
4611     sqlite3_clear_bindings (stmt);
4612     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4613     while (1)
4614       {
4615 	  /* scrolling the result set rows */
4616 	  ret = sqlite3_step (stmt);
4617 	  if (ret == SQLITE_DONE)
4618 	      break;		/* end of result set */
4619 	  if (ret == SQLITE_ROW)
4620 	    {
4621 		if (p_table != NULL)
4622 		    sqlite3_free (p_table);
4623 		p_table =
4624 		    sqlite3_mprintf ("%s",
4625 				     (const char *) sqlite3_column_text (stmt,
4626 									 0));
4627 	    }
4628       }
4629     sqlite3_finalize (stmt);
4630     if (!p_table)
4631       {
4632 	  spatialite_e
4633 	      ("AddGeometryColumn() error: table '%s' does not exist\n", table);
4634 	  sqlite3_result_int (context, 0);
4635 	  return;
4636       }
4637 /* checking for WITHOUT ROWID */
4638     if (is_without_rowid_table (sqlite, table))
4639       {
4640 	  spatialite_e
4641 	      ("AddGeometryColumn() error: table '%s' is WITHOUT ROWID\n",
4642 	       table);
4643 	  sqlite3_result_int (context, 0);
4644 	  return;
4645       }
4646     metadata_version = checkSpatialMetaData (sqlite);
4647     if (metadata_version == 1 || metadata_version == 3)
4648 	;
4649     else
4650       {
4651 	  spatialite_e
4652 	      ("AddGeometryColumn() error: unexpected metadata layout\n");
4653 	  sqlite3_result_int (context, 0);
4654 	  return;
4655       }
4656 
4657 /*
4658  * the following code has been contributed by Mark Johnson <mj10777@googlemail.com>
4659  * on 2019-01-26
4660 */
4661     sql_statement = NULL;
4662     sql_statement =
4663 	sqlite3_mprintf
4664 	("SELECT CASE WHEN (Exists(SELECT srid FROM spatial_ref_sys WHERE (auth_srid = %d)) = 0) THEN 0 ELSE 1 END",
4665 	 srid);
4666     ret =
4667 	sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
4668 			    &stmt, NULL);
4669     sqlite3_free (sql_statement);
4670     sql_statement = NULL;
4671     while (sqlite3_step (stmt) == SQLITE_ROW)
4672       {
4673 	  if (sqlite3_column_type (stmt, 0) != SQLITE_NULL)
4674 	    {
4675 		srid_exists = sqlite3_column_int (stmt, 0);
4676 	    }
4677       }
4678     sqlite3_finalize (stmt);
4679     if (srid_exists == 0)
4680 	ret = insert_epsg_srid (sqlite, srid);
4681 /* end Mark Johnson 2019-01-26 */
4682 
4683 /* trying to add the column */
4684     switch (xtype)
4685       {
4686       case GAIA_POINT:
4687 	  p_type = "POINT";
4688 	  break;
4689       case GAIA_LINESTRING:
4690 	  p_type = "LINESTRING";
4691 	  break;
4692       case GAIA_POLYGON:
4693 	  p_type = "POLYGON";
4694 	  break;
4695       case GAIA_MULTIPOINT:
4696 	  p_type = "MULTIPOINT";
4697 	  break;
4698       case GAIA_MULTILINESTRING:
4699 	  p_type = "MULTILINESTRING";
4700 	  break;
4701       case GAIA_MULTIPOLYGON:
4702 	  p_type = "MULTIPOLYGON";
4703 	  break;
4704       case GAIA_GEOMETRYCOLLECTION:
4705 	  p_type = "GEOMETRYCOLLECTION";
4706 	  break;
4707       case -1:
4708 	  p_type = "GEOMETRY";
4709 	  break;
4710       };
4711     quoted_table = gaiaDoubleQuotedSql (p_table);
4712     quoted_column = gaiaDoubleQuotedSql (column);
4713     if (notNull)
4714       {
4715 	  /* adding a NOT NULL clause */
4716 	  sql_statement =
4717 	      sqlite3_mprintf ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" "
4718 			       "%s NOT NULL DEFAULT ''", quoted_table,
4719 			       quoted_column, p_type);
4720       }
4721     else
4722 	sql_statement =
4723 	    sqlite3_mprintf ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s ",
4724 			     quoted_table, quoted_column, p_type);
4725     free (quoted_table);
4726     free (quoted_column);
4727     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
4728     sqlite3_free (sql_statement);
4729     if (ret != SQLITE_OK)
4730       {
4731 	  spatialite_e ("AddGeometryColumn: \"%s\"\n", sqlite3_errmsg (sqlite));
4732 	  sqlite3_result_int (context, 0);
4733 	  sqlite3_free (p_table);
4734 	  return;
4735       }
4736 /* ok, inserting into geometry_columns [Spatial Metadata] */
4737     if (metadata_version == 1)
4738       {
4739 	  /* legacy metadata style <= v.3.1.0 */
4740 	  switch (xtype)
4741 	    {
4742 	    case GAIA_POINT:
4743 		p_type = "POINT";
4744 		break;
4745 	    case GAIA_LINESTRING:
4746 		p_type = "LINESTRING";
4747 		break;
4748 	    case GAIA_POLYGON:
4749 		p_type = "POLYGON";
4750 		break;
4751 	    case GAIA_MULTIPOINT:
4752 		p_type = "MULTIPOINT";
4753 		break;
4754 	    case GAIA_MULTILINESTRING:
4755 		p_type = "MULTILINESTRING";
4756 		break;
4757 	    case GAIA_MULTIPOLYGON:
4758 		p_type = "MULTIPOLYGON";
4759 		break;
4760 	    case GAIA_GEOMETRYCOLLECTION:
4761 		p_type = "GEOMETRYCOLLECTION";
4762 		break;
4763 	    case -1:
4764 		p_type = "GEOMETRY";
4765 		break;
4766 	    };
4767 	  switch (dims)
4768 	    {
4769 	    case GAIA_XY:
4770 		p_dims = "XY";
4771 		break;
4772 	    case GAIA_XY_Z:
4773 		p_dims = "XYZ";
4774 		break;
4775 	    case GAIA_XY_M:
4776 		p_dims = "XYM";
4777 		break;
4778 	    case GAIA_XY_Z_M:
4779 		p_dims = "XYZM";
4780 		break;
4781 	    };
4782 	  sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
4783 					   "(f_table_name, f_geometry_column, type, coord_dimension, srid, "
4784 					   "spatial_index_enabled) VALUES (?, ?, %Q, %Q, ?, 0)",
4785 					   p_type, p_dims);
4786       }
4787     else
4788       {
4789 	  /* current metadata style >= v.4.0.0 */
4790 	  switch (xtype)
4791 	    {
4792 	    case GAIA_POINT:
4793 		if (dims == GAIA_XY_Z)
4794 		    n_type = 1001;
4795 		else if (dims == GAIA_XY_M)
4796 		    n_type = 2001;
4797 		else if (dims == GAIA_XY_Z_M)
4798 		    n_type = 3001;
4799 		else
4800 		    n_type = 1;
4801 		break;
4802 	    case GAIA_LINESTRING:
4803 		if (dims == GAIA_XY_Z)
4804 		    n_type = 1002;
4805 		else if (dims == GAIA_XY_M)
4806 		    n_type = 2002;
4807 		else if (dims == GAIA_XY_Z_M)
4808 		    n_type = 3002;
4809 		else
4810 		    n_type = 2;
4811 		break;
4812 	    case GAIA_POLYGON:
4813 		if (dims == GAIA_XY_Z)
4814 		    n_type = 1003;
4815 		else if (dims == GAIA_XY_M)
4816 		    n_type = 2003;
4817 		else if (dims == GAIA_XY_Z_M)
4818 		    n_type = 3003;
4819 		else
4820 		    n_type = 3;
4821 		break;
4822 	    case GAIA_MULTIPOINT:
4823 		if (dims == GAIA_XY_Z)
4824 		    n_type = 1004;
4825 		else if (dims == GAIA_XY_M)
4826 		    n_type = 2004;
4827 		else if (dims == GAIA_XY_Z_M)
4828 		    n_type = 3004;
4829 		else
4830 		    n_type = 4;
4831 		break;
4832 	    case GAIA_MULTILINESTRING:
4833 		if (dims == GAIA_XY_Z)
4834 		    n_type = 1005;
4835 		else if (dims == GAIA_XY_M)
4836 		    n_type = 2005;
4837 		else if (dims == GAIA_XY_Z_M)
4838 		    n_type = 3005;
4839 		else
4840 		    n_type = 5;
4841 		break;
4842 	    case GAIA_MULTIPOLYGON:
4843 		if (dims == GAIA_XY_Z)
4844 		    n_type = 1006;
4845 		else if (dims == GAIA_XY_M)
4846 		    n_type = 2006;
4847 		else if (dims == GAIA_XY_Z_M)
4848 		    n_type = 3006;
4849 		else
4850 		    n_type = 6;
4851 		break;
4852 	    case GAIA_GEOMETRYCOLLECTION:
4853 		if (dims == GAIA_XY_Z)
4854 		    n_type = 1007;
4855 		else if (dims == GAIA_XY_M)
4856 		    n_type = 2007;
4857 		else if (dims == GAIA_XY_Z_M)
4858 		    n_type = 3007;
4859 		else
4860 		    n_type = 7;
4861 		break;
4862 	    case -1:
4863 		if (dims == GAIA_XY_Z)
4864 		    n_type = 1000;
4865 		else if (dims == GAIA_XY_M)
4866 		    n_type = 2000;
4867 		else if (dims == GAIA_XY_Z_M)
4868 		    n_type = 3000;
4869 		else
4870 		    n_type = 0;
4871 		break;
4872 	    };
4873 	  switch (dims)
4874 	    {
4875 	    case GAIA_XY:
4876 		n_dims = 2;
4877 		break;
4878 	    case GAIA_XY_Z:
4879 	    case GAIA_XY_M:
4880 		n_dims = 3;
4881 		break;
4882 	    case GAIA_XY_Z_M:
4883 		n_dims = 4;
4884 		break;
4885 	    };
4886 	  sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
4887 					   "(f_table_name, f_geometry_column, geometry_type, coord_dimension, "
4888 					   "srid, spatial_index_enabled) VALUES (Lower(?), Lower(?), %d, %d, ?, 0)",
4889 					   n_type, n_dims);
4890       }
4891     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
4892 			      &stmt, NULL);
4893     sqlite3_free (sql_statement);
4894     if (ret != SQLITE_OK)
4895       {
4896 	  spatialite_e ("AddGeometryColumn: \"%s\"\n", sqlite3_errmsg (sqlite));
4897 	  sqlite3_result_int (context, 0);
4898 	  sqlite3_free (p_table);
4899 	  return;
4900       }
4901     sqlite3_reset (stmt);
4902     sqlite3_clear_bindings (stmt);
4903     sqlite3_bind_text (stmt, 1, p_table, strlen (p_table), SQLITE_STATIC);
4904     sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4905     if (srid < 0)
4906 	sqlite3_bind_int (stmt, 3, -1);
4907     else
4908 	sqlite3_bind_int (stmt, 3, srid);
4909     ret = sqlite3_step (stmt);
4910     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
4911 	;
4912     else
4913       {
4914 	  spatialite_e ("AddGeometryColumn() error: \"%s\"\n",
4915 			sqlite3_errmsg (sqlite));
4916 	  sqlite3_finalize (stmt);
4917 	  goto error;
4918       }
4919     sqlite3_finalize (stmt);
4920     if (metadata_version == 3)
4921       {
4922 	  /* current metadata style >= v.4.0.0 */
4923 
4924 	  /* inserting a row into GEOMETRY_COLUMNS_AUTH */
4925 	  strcpy (sql,
4926 		  "INSERT OR REPLACE INTO geometry_columns_auth (f_table_name, f_geometry_column, ");
4927 	  strcat (sql, "read_only, hidden) VALUES (Lower(?), Lower(?), 0, 0)");
4928 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4929 	  if (ret != SQLITE_OK)
4930 	    {
4931 		spatialite_e ("AddGeometryColumn: \"%s\"\n",
4932 			      sqlite3_errmsg (sqlite));
4933 		sqlite3_result_int (context, 0);
4934 		sqlite3_free (p_table);
4935 		return;
4936 	    }
4937 	  sqlite3_reset (stmt);
4938 	  sqlite3_clear_bindings (stmt);
4939 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4940 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4941 	  ret = sqlite3_step (stmt);
4942 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
4943 	      ;
4944 	  else
4945 	    {
4946 		spatialite_e ("AddGeometryColumn() error: \"%s\"\n",
4947 			      sqlite3_errmsg (sqlite));
4948 		sqlite3_finalize (stmt);
4949 		goto error;
4950 	    }
4951 	  sqlite3_finalize (stmt);
4952 	  /* inserting a row into GEOMETRY_COLUMNS_STATISTICS */
4953 	  strcpy (sql,
4954 		  "INSERT OR REPLACE INTO geometry_columns_statistics (f_table_name, f_geometry_column) ");
4955 	  strcat (sql, "VALUES (Lower(?), Lower(?))");
4956 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4957 	  if (ret != SQLITE_OK)
4958 	    {
4959 		spatialite_e ("AddGeometryColumn: \"%s\"\n",
4960 			      sqlite3_errmsg (sqlite));
4961 		sqlite3_result_int (context, 0);
4962 		sqlite3_free (p_table);
4963 		return;
4964 	    }
4965 	  sqlite3_reset (stmt);
4966 	  sqlite3_clear_bindings (stmt);
4967 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4968 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4969 	  ret = sqlite3_step (stmt);
4970 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
4971 	      ;
4972 	  else
4973 	    {
4974 		spatialite_e ("AddGeometryColumn() error: \"%s\"\n",
4975 			      sqlite3_errmsg (sqlite));
4976 		sqlite3_finalize (stmt);
4977 		goto error;
4978 	    }
4979 	  sqlite3_finalize (stmt);
4980 	  /* inserting a row into GEOMETRY_COLUMNS_TIME */
4981 	  strcpy (sql,
4982 		  "INSERT OR REPLACE INTO geometry_columns_time (f_table_name, f_geometry_column) ");
4983 	  strcat (sql, "VALUES (Lower(?), Lower(?))");
4984 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4985 	  if (ret != SQLITE_OK)
4986 	    {
4987 		spatialite_e ("AddGeometryColumn: \"%s\"\n",
4988 			      sqlite3_errmsg (sqlite));
4989 		sqlite3_result_int (context, 0);
4990 		sqlite3_free (p_table);
4991 		return;
4992 	    }
4993 	  sqlite3_reset (stmt);
4994 	  sqlite3_clear_bindings (stmt);
4995 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
4996 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
4997 	  ret = sqlite3_step (stmt);
4998 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
4999 	      ;
5000 	  else
5001 	    {
5002 		spatialite_e ("AddGeometryColumn() error: \"%s\"\n",
5003 			      sqlite3_errmsg (sqlite));
5004 		sqlite3_finalize (stmt);
5005 		goto error;
5006 	    }
5007 	  sqlite3_finalize (stmt);
5008       }
5009     updateGeometryTriggers (sqlite, table, column);
5010     sqlite3_result_int (context, 1);
5011     switch (xtype)
5012       {
5013       case GAIA_POINT:
5014 	  p_type = "POINT";
5015 	  break;
5016       case GAIA_LINESTRING:
5017 	  p_type = "LINESTRING";
5018 	  break;
5019       case GAIA_POLYGON:
5020 	  p_type = "POLYGON";
5021 	  break;
5022       case GAIA_MULTIPOINT:
5023 	  p_type = "MULTIPOINT";
5024 	  break;
5025       case GAIA_MULTILINESTRING:
5026 	  p_type = "MULTILINESTRING";
5027 	  break;
5028       case GAIA_MULTIPOLYGON:
5029 	  p_type = "MULTIPOLYGON";
5030 	  break;
5031       case GAIA_GEOMETRYCOLLECTION:
5032 	  p_type = "GEOMETRYCOLLECTION";
5033 	  break;
5034       case -1:
5035 	  p_type = "GEOMETRY";
5036 	  break;
5037       };
5038     switch (dims)
5039       {
5040       case GAIA_XY:
5041 	  p_dims = "XY";
5042 	  break;
5043       case GAIA_XY_Z:
5044 	  p_dims = "XYZ";
5045 	  break;
5046       case GAIA_XY_M:
5047 	  p_dims = "XYM";
5048 	  break;
5049       case GAIA_XY_Z_M:
5050 	  p_dims = "XYZM";
5051 	  break;
5052       };
5053     sql_statement =
5054 	sqlite3_mprintf ("Geometry [%s,%s,SRID=%d] successfully created",
5055 			 p_type, p_dims, (srid <= 0) ? -1 : srid);
5056     updateSpatiaLiteHistory (sqlite, table, column, sql_statement);
5057     sqlite3_free (sql_statement);
5058     sqlite3_free (p_table);
5059     return;
5060   error:
5061     sqlite3_result_int (context, 0);
5062     sqlite3_free (p_table);
5063     return;
5064 }
5065 
5066 static void
fnct_AddTemporaryGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)5067 fnct_AddTemporaryGeometryColumn (sqlite3_context * context, int argc,
5068 				 sqlite3_value ** argv)
5069 {
5070 /* SQL function:
5071 / AddTemporaryGeometryColumn(db-prefix, table, column, srid, type [ , dimension  [  , not-null ] ] )
5072 /
5073 / creates a new COLUMN of given TYPE into TABLE
5074 / returns 1 on success
5075 / 0 on failure
5076 /
5077 / INTENDED ONLY FOR TEMPORARY ATTACHED DATABASES
5078 /
5079 */
5080     const char *db_prefix;
5081     const char *table;
5082     const char *column;
5083     const unsigned char *type;
5084     const unsigned char *txt_dims;
5085     int xtype;
5086     int srid = -1;
5087     int dimension = 2;
5088     int dims = -1;
5089     int auto_dims = -1;
5090     char *sql2;
5091     int ret;
5092     int notNull = 0;
5093     sqlite3_stmt *stmt;
5094     char *p_table = NULL;
5095     char *quoted_prefix;
5096     char *quoted_table;
5097     char *quoted_column;
5098     const char *p_type = NULL;
5099     int n_type = 0;
5100     int n_dims = 0;
5101     char *sql_statement;
5102     sqlite3 *sqlite = sqlite3_context_db_handle (context);
5103     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
5104       {
5105 	  spatialite_e
5106 	      ("AddTemporaryGeometryColumn() error: argument 1 [DB-prefix] is not of the String type\n");
5107 	  sqlite3_result_int (context, 0);
5108 	  return;
5109       }
5110     db_prefix = (const char *) sqlite3_value_text (argv[0]);
5111     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
5112       {
5113 	  spatialite_e
5114 	      ("AddTemporaryGeometryColumn() error: argument 2 [table_name] is not of the String type\n");
5115 	  sqlite3_result_int (context, 0);
5116 	  return;
5117       }
5118     table = (const char *) sqlite3_value_text (argv[1]);
5119     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
5120       {
5121 	  spatialite_e
5122 	      ("AddTemporaryGeometryColumn() error: argument 3 [column_name] is not of the String type\n");
5123 	  sqlite3_result_int (context, 0);
5124 	  return;
5125       }
5126     column = (const char *) sqlite3_value_text (argv[2]);
5127     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
5128       {
5129 	  spatialite_e
5130 	      ("AddTemporaryGeometryColumn() error: argument 4 [SRID] is not of the Integer type\n");
5131 	  sqlite3_result_int (context, 0);
5132 	  return;
5133       }
5134     srid = sqlite3_value_int (argv[3]);
5135     if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
5136       {
5137 	  spatialite_e
5138 	      ("AddTemporaryGeometryColumn() error: argument 5 [geometry_type] is not of the String type\n");
5139 	  sqlite3_result_int (context, 0);
5140 	  return;
5141       }
5142     type = sqlite3_value_text (argv[4]);
5143     if (argc > 5)
5144       {
5145 	  if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
5146 	    {
5147 		dimension = sqlite3_value_int (argv[5]);
5148 		if (dimension == 2)
5149 		    dims = GAIA_XY;
5150 		if (dimension == 3)
5151 		    dims = GAIA_XY_Z;
5152 		if (dimension == 4)
5153 		    dims = GAIA_XY_Z_M;
5154 	    }
5155 	  else if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
5156 	    {
5157 		txt_dims = sqlite3_value_text (argv[5]);
5158 		if (strcasecmp ((char *) txt_dims, "XY") == 0)
5159 		    dims = GAIA_XY;
5160 		if (strcasecmp ((char *) txt_dims, "XYZ") == 0)
5161 		    dims = GAIA_XY_Z;
5162 		if (strcasecmp ((char *) txt_dims, "XYM") == 0)
5163 		    dims = GAIA_XY_M;
5164 		if (strcasecmp ((char *) txt_dims, "XYZM") == 0)
5165 		    dims = GAIA_XY_Z_M;
5166 	    }
5167 	  else
5168 	    {
5169 		spatialite_e
5170 		    ("AddTemporaryGeometryColumn() error: argument 6 [dimension] is not of the Integer or Text type\n");
5171 		sqlite3_result_int (context, 0);
5172 		return;
5173 	    }
5174       }
5175     if (argc == 7)
5176       {
5177 	  /* optional NOT NULL arg */
5178 	  if (sqlite3_value_type (argv[6]) != SQLITE_INTEGER)
5179 	    {
5180 		spatialite_e
5181 		    ("AddTemporaryGeometryColumn() error: argument 7 [not null] is not of the Integer type\n");
5182 		sqlite3_result_int (context, 0);
5183 		return;
5184 	    }
5185 	  notNull = sqlite3_value_int (argv[5]);
5186       }
5187 /* checking if the Attached Database is actually based on :memory: */
5188     if (!is_attached_memory (sqlite, db_prefix))
5189       {
5190 	  spatialite_e
5191 	      ("AddTemporaryGeometryColumn() error: Database '%s' does not exists or is not a Temporary one\n",
5192 	       db_prefix);
5193 	  sqlite3_result_int (context, 0);
5194 	  return;
5195       }
5196     xtype = GAIA_UNKNOWN;
5197     if (strcasecmp ((char *) type, "POINT") == 0)
5198       {
5199 	  auto_dims = GAIA_XY;
5200 	  xtype = GAIA_POINT;
5201       }
5202     if (strcasecmp ((char *) type, "LINESTRING") == 0)
5203       {
5204 	  auto_dims = GAIA_XY;
5205 	  xtype = GAIA_LINESTRING;
5206       }
5207     if (strcasecmp ((char *) type, "POLYGON") == 0)
5208       {
5209 	  auto_dims = GAIA_XY;
5210 	  xtype = GAIA_POLYGON;
5211       }
5212     if (strcasecmp ((char *) type, "MULTIPOINT") == 0)
5213       {
5214 	  auto_dims = GAIA_XY;
5215 	  xtype = GAIA_MULTIPOINT;
5216       }
5217     if (strcasecmp ((char *) type, "MULTILINESTRING") == 0)
5218       {
5219 	  auto_dims = GAIA_XY;
5220 	  xtype = GAIA_MULTILINESTRING;
5221       }
5222     if (strcasecmp ((char *) type, "MULTIPOLYGON") == 0)
5223       {
5224 	  auto_dims = GAIA_XY;
5225 	  xtype = GAIA_MULTIPOLYGON;
5226       }
5227     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTION") == 0)
5228       {
5229 	  auto_dims = GAIA_XY;
5230 	  xtype = GAIA_GEOMETRYCOLLECTION;
5231       }
5232     if (strcasecmp ((char *) type, "GEOMETRY") == 0)
5233       {
5234 	  auto_dims = GAIA_XY;
5235 	  xtype = -1;
5236       }
5237     if (strcasecmp ((char *) type, "POINTZ") == 0)
5238       {
5239 	  auto_dims = GAIA_XY_Z;
5240 	  xtype = GAIA_POINT;
5241       }
5242     if (strcasecmp ((char *) type, "LINESTRINGZ") == 0)
5243       {
5244 	  auto_dims = GAIA_XY_Z;
5245 	  xtype = GAIA_LINESTRING;
5246       }
5247     if (strcasecmp ((char *) type, "POLYGONZ") == 0)
5248       {
5249 	  auto_dims = GAIA_XY_Z;
5250 	  xtype = GAIA_POLYGON;
5251       }
5252     if (strcasecmp ((char *) type, "MULTIPOINTZ") == 0)
5253       {
5254 	  auto_dims = GAIA_XY_Z;
5255 	  xtype = GAIA_MULTIPOINT;
5256       }
5257     if (strcasecmp ((char *) type, "MULTILINESTRINGZ") == 0)
5258       {
5259 	  auto_dims = GAIA_XY_Z;
5260 	  xtype = GAIA_MULTILINESTRING;
5261       }
5262     if (strcasecmp ((char *) type, "MULTIPOLYGONZ") == 0)
5263       {
5264 	  auto_dims = GAIA_XY_Z;
5265 	  xtype = GAIA_MULTIPOLYGON;
5266       }
5267     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZ") == 0)
5268       {
5269 	  auto_dims = GAIA_XY_Z;
5270 	  xtype = GAIA_GEOMETRYCOLLECTION;
5271       }
5272     if (strcasecmp ((char *) type, "GEOMETRYZ") == 0)
5273       {
5274 	  auto_dims = GAIA_XY_Z;
5275 	  xtype = -1;
5276       }
5277     if (strcasecmp ((char *) type, "POINTM") == 0)
5278       {
5279 	  auto_dims = GAIA_XY_M;
5280 	  xtype = GAIA_POINT;
5281       }
5282     if (strcasecmp ((char *) type, "LINESTRINGM") == 0)
5283       {
5284 	  auto_dims = GAIA_XY_M;
5285 	  xtype = GAIA_LINESTRING;
5286       }
5287     if (strcasecmp ((char *) type, "POLYGONM") == 0)
5288       {
5289 	  auto_dims = GAIA_XY_M;
5290 	  xtype = GAIA_POLYGON;
5291       }
5292     if (strcasecmp ((char *) type, "MULTIPOINTM") == 0)
5293       {
5294 	  auto_dims = GAIA_XY_M;
5295 	  xtype = GAIA_MULTIPOINT;
5296       }
5297     if (strcasecmp ((char *) type, "MULTILINESTRINGM") == 0)
5298       {
5299 	  auto_dims = GAIA_XY_M;
5300 	  xtype = GAIA_MULTILINESTRING;
5301       }
5302     if (strcasecmp ((char *) type, "MULTIPOLYGONM") == 0)
5303       {
5304 	  auto_dims = GAIA_XY_M;
5305 	  xtype = GAIA_MULTIPOLYGON;
5306       }
5307     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONM") == 0)
5308       {
5309 	  auto_dims = GAIA_XY_M;
5310 	  xtype = GAIA_GEOMETRYCOLLECTION;
5311       }
5312     if (strcasecmp ((char *) type, "GEOMETRYM") == 0)
5313       {
5314 	  auto_dims = GAIA_XY_M;
5315 	  xtype = -1;
5316       }
5317     if (strcasecmp ((char *) type, "POINTZM") == 0)
5318       {
5319 	  auto_dims = GAIA_XY_Z_M;
5320 	  xtype = GAIA_POINT;
5321       }
5322     if (strcasecmp ((char *) type, "LINESTRINGZM") == 0)
5323       {
5324 	  auto_dims = GAIA_XY_Z_M;
5325 	  xtype = GAIA_LINESTRING;
5326       }
5327     if (strcasecmp ((char *) type, "POLYGONZM") == 0)
5328       {
5329 	  auto_dims = GAIA_XY_Z_M;
5330 	  xtype = GAIA_POLYGON;
5331       }
5332     if (strcasecmp ((char *) type, "MULTIPOINTZM") == 0)
5333       {
5334 	  auto_dims = GAIA_XY_Z_M;
5335 	  xtype = GAIA_MULTIPOINT;
5336       }
5337     if (strcasecmp ((char *) type, "MULTILINESTRINGZM") == 0)
5338       {
5339 	  auto_dims = GAIA_XY_Z_M;
5340 	  xtype = GAIA_MULTILINESTRING;
5341       }
5342     if (strcasecmp ((char *) type, "MULTIPOLYGONZM") == 0)
5343       {
5344 	  auto_dims = GAIA_XY_Z_M;
5345 	  xtype = GAIA_MULTIPOLYGON;
5346       }
5347     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZM") == 0)
5348       {
5349 	  auto_dims = GAIA_XY_Z_M;
5350 	  xtype = GAIA_GEOMETRYCOLLECTION;
5351       }
5352     if (strcasecmp ((char *) type, "GEOMETRYZM") == 0)
5353       {
5354 	  auto_dims = GAIA_XY_Z_M;
5355 	  xtype = -1;
5356       }
5357     if (xtype == GAIA_UNKNOWN)
5358       {
5359 	  spatialite_e
5360 	      ("AddTemporaryGeometryColumn() error: argument 5 [geometry_type] has an illegal value\n");
5361 	  sqlite3_result_int (context, 0);
5362 	  return;
5363       }
5364     if (dims < 0)
5365 	dims = auto_dims;
5366     if (dims == GAIA_XY || dims == GAIA_XY_Z || dims == GAIA_XY_M
5367 	|| dims == GAIA_XY_Z_M)
5368 	;
5369     else
5370       {
5371 	  spatialite_e
5372 	      ("AddTemporaryGeometryColumn() error: argument 6 [dimension] ILLEGAL VALUE\n");
5373 	  sqlite3_result_int (context, 0);
5374 	  return;
5375       }
5376     if (auto_dims != GAIA_XY && dims != auto_dims)
5377       {
5378 	  spatialite_e
5379 	      ("AddTemporaryGeometryColumn() error: argument 6 [dimension] ILLEGAL VALUE\n");
5380 	  sqlite3_result_int (context, 0);
5381 	  return;
5382       }
5383 /* checking if the table exists */
5384     quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5385     sql2 =
5386 	sqlite3_mprintf
5387 	("SELECT name FROM \"%s\".sqlite_master WHERE type = 'table' AND Lower(name) = Lower(?)",
5388 	 quoted_prefix);
5389     free (quoted_prefix);
5390     ret = sqlite3_prepare_v2 (sqlite, sql2, strlen (sql2), &stmt, NULL);
5391     sqlite3_free (sql2);
5392     if (ret != SQLITE_OK)
5393       {
5394 	  spatialite_e ("AddTemporaryGeometryColumn: \"%s\"\n",
5395 			sqlite3_errmsg (sqlite));
5396 	  sqlite3_result_int (context, 0);
5397 	  return;
5398       }
5399     sqlite3_reset (stmt);
5400     sqlite3_clear_bindings (stmt);
5401     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
5402     while (1)
5403       {
5404 	  /* scrolling the result set rows */
5405 	  ret = sqlite3_step (stmt);
5406 	  if (ret == SQLITE_DONE)
5407 	      break;		/* end of result set */
5408 	  if (ret == SQLITE_ROW)
5409 	    {
5410 		if (p_table != NULL)
5411 		    sqlite3_free (p_table);
5412 		p_table =
5413 		    sqlite3_mprintf ("%s",
5414 				     (const char *) sqlite3_column_text (stmt,
5415 									 0));
5416 	    }
5417       }
5418     sqlite3_finalize (stmt);
5419     if (!p_table)
5420       {
5421 	  spatialite_e
5422 	      ("AddTemporaryGeometryColumn() error: table '%s' does not exist\n",
5423 	       table);
5424 	  sqlite3_result_int (context, 0);
5425 	  return;
5426       }
5427 /* checking for WITHOUT ROWID */
5428     if (is_without_rowid_table_attached (sqlite, db_prefix, table))
5429       {
5430 	  spatialite_e
5431 	      ("AddTemporaryGeometryColumn() error: table '%s' is WITHOUT ROWID\n",
5432 	       table);
5433 	  sqlite3_result_int (context, 0);
5434 	  return;
5435       }
5436 
5437 /* trying to add the column */
5438     switch (xtype)
5439       {
5440       case GAIA_POINT:
5441 	  p_type = "POINT";
5442 	  break;
5443       case GAIA_LINESTRING:
5444 	  p_type = "LINESTRING";
5445 	  break;
5446       case GAIA_POLYGON:
5447 	  p_type = "POLYGON";
5448 	  break;
5449       case GAIA_MULTIPOINT:
5450 	  p_type = "MULTIPOINT";
5451 	  break;
5452       case GAIA_MULTILINESTRING:
5453 	  p_type = "MULTILINESTRING";
5454 	  break;
5455       case GAIA_MULTIPOLYGON:
5456 	  p_type = "MULTIPOLYGON";
5457 	  break;
5458       case GAIA_GEOMETRYCOLLECTION:
5459 	  p_type = "GEOMETRYCOLLECTION";
5460 	  break;
5461       case -1:
5462 	  p_type = "GEOMETRY";
5463 	  break;
5464       };
5465     quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5466     quoted_table = gaiaDoubleQuotedSql (p_table);
5467     quoted_column = gaiaDoubleQuotedSql (column);
5468     if (notNull)
5469       {
5470 	  /* adding a NOT NULL clause */
5471 	  sql_statement =
5472 	      sqlite3_mprintf ("ALTER TABLE \"%s\".\"%s\" ADD COLUMN \"%s\" "
5473 			       "%s NOT NULL DEFAULT ''", quoted_prefix,
5474 			       quoted_table, quoted_column, p_type);
5475       }
5476     else
5477 	sql_statement =
5478 	    sqlite3_mprintf ("ALTER TABLE \"%s\".\"%s\" ADD COLUMN \"%s\" %s ",
5479 			     quoted_prefix, quoted_table, quoted_column,
5480 			     p_type);
5481     free (quoted_prefix);
5482     free (quoted_table);
5483     free (quoted_column);
5484     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, NULL);
5485     sqlite3_free (sql_statement);
5486     if (ret != SQLITE_OK)
5487       {
5488 	  spatialite_e ("AddTemporaryGeometryColumn: \"%s\"\n",
5489 			sqlite3_errmsg (sqlite));
5490 	  sqlite3_result_int (context, 0);
5491 	  sqlite3_free (p_table);
5492 	  return;
5493       }
5494 /* ok, inserting into geometry_columns [Spatial Metadata] */
5495     switch (xtype)
5496       {
5497       case GAIA_POINT:
5498 	  if (dims == GAIA_XY_Z)
5499 	      n_type = 1001;
5500 	  else if (dims == GAIA_XY_M)
5501 	      n_type = 2001;
5502 	  else if (dims == GAIA_XY_Z_M)
5503 	      n_type = 3001;
5504 	  else
5505 	      n_type = 1;
5506 	  break;
5507       case GAIA_LINESTRING:
5508 	  if (dims == GAIA_XY_Z)
5509 	      n_type = 1002;
5510 	  else if (dims == GAIA_XY_M)
5511 	      n_type = 2002;
5512 	  else if (dims == GAIA_XY_Z_M)
5513 	      n_type = 3002;
5514 	  else
5515 	      n_type = 2;
5516 	  break;
5517       case GAIA_POLYGON:
5518 	  if (dims == GAIA_XY_Z)
5519 	      n_type = 1003;
5520 	  else if (dims == GAIA_XY_M)
5521 	      n_type = 2003;
5522 	  else if (dims == GAIA_XY_Z_M)
5523 	      n_type = 3003;
5524 	  else
5525 	      n_type = 3;
5526 	  break;
5527       case GAIA_MULTIPOINT:
5528 	  if (dims == GAIA_XY_Z)
5529 	      n_type = 1004;
5530 	  else if (dims == GAIA_XY_M)
5531 	      n_type = 2004;
5532 	  else if (dims == GAIA_XY_Z_M)
5533 	      n_type = 3004;
5534 	  else
5535 	      n_type = 4;
5536 	  break;
5537       case GAIA_MULTILINESTRING:
5538 	  if (dims == GAIA_XY_Z)
5539 	      n_type = 1005;
5540 	  else if (dims == GAIA_XY_M)
5541 	      n_type = 2005;
5542 	  else if (dims == GAIA_XY_Z_M)
5543 	      n_type = 3005;
5544 	  else
5545 	      n_type = 5;
5546 	  break;
5547       case GAIA_MULTIPOLYGON:
5548 	  if (dims == GAIA_XY_Z)
5549 	      n_type = 1006;
5550 	  else if (dims == GAIA_XY_M)
5551 	      n_type = 2006;
5552 	  else if (dims == GAIA_XY_Z_M)
5553 	      n_type = 3006;
5554 	  else
5555 	      n_type = 6;
5556 	  break;
5557       case GAIA_GEOMETRYCOLLECTION:
5558 	  if (dims == GAIA_XY_Z)
5559 	      n_type = 1007;
5560 	  else if (dims == GAIA_XY_M)
5561 	      n_type = 2007;
5562 	  else if (dims == GAIA_XY_Z_M)
5563 	      n_type = 3007;
5564 	  else
5565 	      n_type = 7;
5566 	  break;
5567       case -1:
5568 	  if (dims == GAIA_XY_Z)
5569 	      n_type = 1000;
5570 	  else if (dims == GAIA_XY_M)
5571 	      n_type = 2000;
5572 	  else if (dims == GAIA_XY_Z_M)
5573 	      n_type = 3000;
5574 	  else
5575 	      n_type = 0;
5576 	  break;
5577       };
5578     switch (dims)
5579       {
5580       case GAIA_XY:
5581 	  n_dims = 2;
5582 	  break;
5583       case GAIA_XY_Z:
5584       case GAIA_XY_M:
5585 	  n_dims = 3;
5586 	  break;
5587       case GAIA_XY_Z_M:
5588 	  n_dims = 4;
5589 	  break;
5590       };
5591 
5592 /* attempting to create spatial_ref_sys, just in case */
5593     if (!createTemporarySpatialRefSys (sqlite, db_prefix))
5594       {
5595 	  spatialite_e
5596 	      ("AddTemporaryGeometryColumn() error: unable to create \"spatial_ref_sys\" on Database '%s'\n",
5597 	       db_prefix);
5598 	  sqlite3_result_int (context, 0);
5599 	  return;
5600       }
5601 /* attempting to create geometry_columns, just in case */
5602     if (!createTemporaryGeometryColumns (sqlite, db_prefix))
5603       {
5604 	  spatialite_e
5605 	      ("AddTemporaryGeometryColumn() error: unable to create \"geometry_columns\" on Database '%s'\n",
5606 	       db_prefix);
5607 	  sqlite3_result_int (context, 0);
5608 	  return;
5609       }
5610 
5611     quoted_prefix = gaiaDoubleQuotedSql (db_prefix);
5612     sql_statement = sqlite3_mprintf ("INSERT INTO \"%s\".geometry_columns "
5613 				     "(f_table_name, f_geometry_column, geometry_type, coord_dimension, "
5614 				     "srid, spatial_index_enabled) VALUES (Lower(?), Lower(?), %d, %d, ?, 0)",
5615 				     quoted_prefix, n_type, n_dims);
5616     free (quoted_prefix);
5617     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
5618 			      &stmt, NULL);
5619     sqlite3_free (sql_statement);
5620     if (ret != SQLITE_OK)
5621       {
5622 	  spatialite_e ("AddTemporaryGeometryColumn: \"%s\"\n",
5623 			sqlite3_errmsg (sqlite));
5624 	  sqlite3_result_int (context, 0);
5625 	  sqlite3_free (p_table);
5626 	  return;
5627       }
5628     sqlite3_reset (stmt);
5629     sqlite3_clear_bindings (stmt);
5630     sqlite3_bind_text (stmt, 1, p_table, strlen (p_table), SQLITE_STATIC);
5631     sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
5632     if (srid < 0)
5633 	sqlite3_bind_int (stmt, 3, -1);
5634     else
5635 	sqlite3_bind_int (stmt, 3, srid);
5636     ret = sqlite3_step (stmt);
5637     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
5638 	;
5639     else
5640       {
5641 	  spatialite_e ("AddTemporaryGeometryColumn() error: \"%s\"\n",
5642 			sqlite3_errmsg (sqlite));
5643 	  sqlite3_finalize (stmt);
5644 	  goto error;
5645       }
5646     sqlite3_finalize (stmt);
5647     updateTemporaryGeometryTriggers (sqlite, db_prefix, table, column);
5648     sqlite3_result_int (context, 1);
5649     sqlite3_free (p_table);
5650     return;
5651   error:
5652     sqlite3_result_int (context, 0);
5653     sqlite3_free (p_table);
5654     return;
5655 }
5656 
5657 static void
fnct_RecoverGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)5658 fnct_RecoverGeometryColumn (sqlite3_context * context, int argc,
5659 			    sqlite3_value ** argv)
5660 {
5661 /* SQL function:
5662 / RecoverGeometryColumn(table, column, srid, type , dimension )
5663 /
5664 / checks if an existing TABLE.COLUMN satisfies the required geometric features
5665 / if yes adds it to SpatialMetaData and enabling triggers
5666 / returns 1 on success
5667 / 0 on failure
5668 */
5669     const char *table;
5670     const char *column;
5671     const unsigned char *type;
5672     int xtype;
5673     int xxtype;
5674     int srid = -1;
5675     const unsigned char *txt_dims;
5676     int dimension = 2;
5677     int dims = -1;
5678     int auto_dims = -1;
5679     char sql[1024];
5680     int ret;
5681     int metadata_version;
5682     sqlite3_stmt *stmt;
5683     int exists = 0;
5684     const char *p_type = NULL;
5685     const char *p_dims = NULL;
5686     int n_type = GAIA_UNKNOWN;
5687     int n_dims = -1;
5688     char *sql_statement;
5689     sqlite3 *sqlite = sqlite3_context_db_handle (context);
5690     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
5691     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
5692       {
5693 	  spatialite_e
5694 	      ("RecoverGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
5695 	  sqlite3_result_int (context, 0);
5696 	  return;
5697       }
5698     table = (const char *) sqlite3_value_text (argv[0]);
5699     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
5700       {
5701 	  spatialite_e
5702 	      ("RecoverGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
5703 	  sqlite3_result_int (context, 0);
5704 	  return;
5705       }
5706     column = (const char *) sqlite3_value_text (argv[1]);
5707     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
5708       {
5709 	  spatialite_e
5710 	      ("RecoverGeometryColumn() error: argument 3 [SRID] is not of the Integer type\n");
5711 	  sqlite3_result_int (context, 0);
5712 	  return;
5713       }
5714     srid = sqlite3_value_int (argv[2]);
5715     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
5716       {
5717 	  spatialite_e
5718 	      ("RecoverGeometryColumn() error: argument 4 [geometry_type] is not of the String type\n");
5719 	  sqlite3_result_int (context, 0);
5720 	  return;
5721       }
5722     type = sqlite3_value_text (argv[3]);
5723     if (argc == 5)
5724       {
5725 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
5726 	    {
5727 		dimension = sqlite3_value_int (argv[4]);
5728 		if (dimension == 2)
5729 		    dims = GAIA_XY;
5730 		if (dimension == 3)
5731 		    dims = GAIA_XY_Z;
5732 		if (dimension == 4)
5733 		    dims = GAIA_XY_Z_M;
5734 	    }
5735 	  else if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
5736 	    {
5737 		txt_dims = sqlite3_value_text (argv[4]);
5738 		if (strcasecmp ((char *) txt_dims, "XY") == 0)
5739 		    dims = GAIA_XY;
5740 		if (strcasecmp ((char *) txt_dims, "XYZ") == 0)
5741 		    dims = GAIA_XY_Z;
5742 		if (strcasecmp ((char *) txt_dims, "XYM") == 0)
5743 		    dims = GAIA_XY_M;
5744 		if (strcasecmp ((char *) txt_dims, "XYZM") == 0)
5745 		    dims = GAIA_XY_Z_M;
5746 	    }
5747 	  else
5748 	    {
5749 		spatialite_e
5750 		    ("RecoverGeometryColumn() error: argument 5 [dimension] is not of the Integer or Text type\n");
5751 		sqlite3_result_int (context, 0);
5752 		return;
5753 	    }
5754       }
5755     xtype = GAIA_UNKNOWN;
5756     if (strcasecmp ((char *) type, "POINT") == 0)
5757       {
5758 	  auto_dims = GAIA_XY;
5759 	  xtype = GAIA_POINT;
5760       }
5761     if (strcasecmp ((char *) type, "LINESTRING") == 0)
5762       {
5763 	  auto_dims = GAIA_XY;
5764 	  xtype = GAIA_LINESTRING;
5765       }
5766     if (strcasecmp ((char *) type, "POLYGON") == 0)
5767       {
5768 	  auto_dims = GAIA_XY;
5769 	  xtype = GAIA_POLYGON;
5770       }
5771     if (strcasecmp ((char *) type, "MULTIPOINT") == 0)
5772       {
5773 	  auto_dims = GAIA_XY;
5774 	  xtype = GAIA_MULTIPOINT;
5775       }
5776     if (strcasecmp ((char *) type, "MULTILINESTRING") == 0)
5777       {
5778 	  auto_dims = GAIA_XY;
5779 	  xtype = GAIA_MULTILINESTRING;
5780       }
5781     if (strcasecmp ((char *) type, "MULTIPOLYGON") == 0)
5782       {
5783 	  auto_dims = GAIA_XY;
5784 	  xtype = GAIA_MULTIPOLYGON;
5785       }
5786     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTION") == 0)
5787       {
5788 	  auto_dims = GAIA_XY;
5789 	  xtype = GAIA_GEOMETRYCOLLECTION;
5790       }
5791     if (strcasecmp ((char *) type, "GEOMETRY") == 0)
5792       {
5793 	  auto_dims = GAIA_XY;
5794 	  xtype = -1;
5795       }
5796     if (strcasecmp ((char *) type, "POINTZ") == 0)
5797       {
5798 	  auto_dims = GAIA_XY_Z;
5799 	  xtype = GAIA_POINT;
5800       }
5801     if (strcasecmp ((char *) type, "LINESTRINGZ") == 0)
5802       {
5803 	  auto_dims = GAIA_XY_Z;
5804 	  xtype = GAIA_LINESTRING;
5805       }
5806     if (strcasecmp ((char *) type, "POLYGONZ") == 0)
5807       {
5808 	  auto_dims = GAIA_XY_Z;
5809 	  xtype = GAIA_POLYGON;
5810       }
5811     if (strcasecmp ((char *) type, "MULTIPOINTZ") == 0)
5812       {
5813 	  auto_dims = GAIA_XY_Z;
5814 	  xtype = GAIA_MULTIPOINT;
5815       }
5816     if (strcasecmp ((char *) type, "MULTILINESTRINGZ") == 0)
5817       {
5818 	  auto_dims = GAIA_XY_Z;
5819 	  xtype = GAIA_MULTILINESTRING;
5820       }
5821     if (strcasecmp ((char *) type, "MULTIPOLYGONZ") == 0)
5822       {
5823 	  auto_dims = GAIA_XY_Z;
5824 	  xtype = GAIA_MULTIPOLYGON;
5825       }
5826     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZ") == 0)
5827       {
5828 	  auto_dims = GAIA_XY_Z;
5829 	  xtype = GAIA_GEOMETRYCOLLECTION;
5830       }
5831     if (strcasecmp ((char *) type, "GEOMETRYZ") == 0)
5832       {
5833 	  auto_dims = GAIA_XY_Z;
5834 	  xtype = -1;
5835       }
5836     if (strcasecmp ((char *) type, "POINTM") == 0)
5837       {
5838 	  auto_dims = GAIA_XY_M;
5839 	  xtype = GAIA_POINT;
5840       }
5841     if (strcasecmp ((char *) type, "LINESTRINGM") == 0)
5842       {
5843 	  auto_dims = GAIA_XY_M;
5844 	  xtype = GAIA_LINESTRING;
5845       }
5846     if (strcasecmp ((char *) type, "POLYGONM") == 0)
5847       {
5848 	  auto_dims = GAIA_XY_M;
5849 	  xtype = GAIA_POLYGON;
5850       }
5851     if (strcasecmp ((char *) type, "MULTIPOINTM") == 0)
5852       {
5853 	  auto_dims = GAIA_XY_M;
5854 	  xtype = GAIA_MULTIPOINT;
5855       }
5856     if (strcasecmp ((char *) type, "MULTILINESTRINGM") == 0)
5857       {
5858 	  auto_dims = GAIA_XY_M;
5859 	  xtype = GAIA_MULTILINESTRING;
5860       }
5861     if (strcasecmp ((char *) type, "MULTIPOLYGONM") == 0)
5862       {
5863 	  auto_dims = GAIA_XY_M;
5864 	  xtype = GAIA_MULTIPOLYGON;
5865       }
5866     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONM") == 0)
5867       {
5868 	  auto_dims = GAIA_XY_M;
5869 	  xtype = GAIA_GEOMETRYCOLLECTION;
5870       }
5871     if (strcasecmp ((char *) type, "GEOMETRYM") == 0)
5872       {
5873 	  auto_dims = GAIA_XY_M;
5874 	  xtype = -1;
5875       }
5876     if (strcasecmp ((char *) type, "POINTZM") == 0)
5877       {
5878 	  auto_dims = GAIA_XY_Z_M;
5879 	  xtype = GAIA_POINT;
5880       }
5881     if (strcasecmp ((char *) type, "LINESTRINGZM") == 0)
5882       {
5883 	  auto_dims = GAIA_XY_Z_M;
5884 	  xtype = GAIA_LINESTRING;
5885       }
5886     if (strcasecmp ((char *) type, "POLYGONZM") == 0)
5887       {
5888 	  auto_dims = GAIA_XY_Z_M;
5889 	  xtype = GAIA_POLYGON;
5890       }
5891     if (strcasecmp ((char *) type, "MULTIPOINTZM") == 0)
5892       {
5893 	  auto_dims = GAIA_XY_Z_M;
5894 	  xtype = GAIA_MULTIPOINT;
5895       }
5896     if (strcasecmp ((char *) type, "MULTILINESTRINGZM") == 0)
5897       {
5898 	  auto_dims = GAIA_XY_Z_M;
5899 	  xtype = GAIA_MULTILINESTRING;
5900       }
5901     if (strcasecmp ((char *) type, "MULTIPOLYGONZM") == 0)
5902       {
5903 	  auto_dims = GAIA_XY_Z_M;
5904 	  xtype = GAIA_MULTIPOLYGON;
5905       }
5906     if (strcasecmp ((char *) type, "GEOMETRYCOLLECTIONZM") == 0)
5907       {
5908 	  auto_dims = GAIA_XY_Z_M;
5909 	  xtype = GAIA_GEOMETRYCOLLECTION;
5910       }
5911     if (strcasecmp ((char *) type, "GEOMETRYZM") == 0)
5912       {
5913 	  auto_dims = GAIA_XY_Z_M;
5914 	  xtype = -1;
5915       }
5916     if (dims < 0)
5917 	dims = auto_dims;
5918     if (xtype == GAIA_UNKNOWN)
5919       {
5920 	  spatialite_e
5921 	      ("RecoverGeometryColumn() error: argument 4 [geometry_type] has an illegal value\n");
5922 	  sqlite3_result_int (context, 0);
5923 	  return;
5924       }
5925     if (dims == GAIA_XY || dims == GAIA_XY_Z || dims == GAIA_XY_M
5926 	|| dims == GAIA_XY_Z_M)
5927 	;
5928     else
5929       {
5930 	  spatialite_e
5931 	      ("RecoverGeometryColumn() error: argument 5 [dimension] ILLEGAL VALUE\n");
5932 	  sqlite3_result_int (context, 0);
5933 	  return;
5934       }
5935     if (auto_dims != GAIA_XY && dims != auto_dims)
5936       {
5937 	  spatialite_e
5938 	      ("RecoverGeometryColumn() error: argument 5 [dimension] ILLEGAL VALUE\n");
5939 	  sqlite3_result_int (context, 0);
5940 	  return;
5941       }
5942     metadata_version = checkSpatialMetaData (sqlite);
5943     if (metadata_version == 1 || metadata_version == 3)
5944 	;
5945     else
5946       {
5947 	  spatialite_e
5948 	      ("RecoverGeometryColumn() error: unexpected metadata layout\n");
5949 	  sqlite3_result_int (context, 0);
5950 	  return;
5951       }
5952 /* checking if the table exists */
5953     strcpy (sql,
5954 	    "SELECT name FROM sqlite_master WHERE type = 'table' AND Lower(name) = Lower(?)");
5955     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
5956     if (ret != SQLITE_OK)
5957       {
5958 	  spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
5959 			sqlite3_errmsg (sqlite));
5960 	  sqlite3_result_int (context, 0);
5961 	  return;
5962       }
5963     sqlite3_reset (stmt);
5964     sqlite3_clear_bindings (stmt);
5965     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
5966     while (1)
5967       {
5968 	  /* scrolling the result set rows */
5969 	  ret = sqlite3_step (stmt);
5970 	  if (ret == SQLITE_DONE)
5971 	      break;		/* end of result set */
5972 	  if (ret == SQLITE_ROW)
5973 	    {
5974 		if (sqlite3_column_type (stmt, 0) == SQLITE_TEXT)
5975 		    exists = 1;
5976 	    }
5977       }
5978     sqlite3_finalize (stmt);
5979     if (!exists)
5980       {
5981 	  spatialite_e
5982 	      ("RecoverGeometryColumn() error: table '%s' does not exist\n",
5983 	       table);
5984 	  sqlite3_result_int (context, 0);
5985 	  return;
5986       }
5987     if (is_without_rowid_table (sqlite, table))
5988       {
5989 	  spatialite_e
5990 	      ("RecoverGeometryColumn() error: table '%s' is WITHOUT ROWID\n",
5991 	       table);
5992 	  sqlite3_result_int (context, 0);
5993 	  return;
5994       }
5995 /* adjusting the actual GeometryType */
5996     xxtype = xtype;
5997     xtype = GAIA_UNKNOWN;
5998     if (xxtype == GAIA_POINT)
5999       {
6000 	  switch (dims)
6001 	    {
6002 	    case GAIA_XY_Z:
6003 		xtype = GAIA_POINTZ;
6004 		break;
6005 	    case GAIA_XY_M:
6006 		xtype = GAIA_POINTM;
6007 		break;
6008 	    case GAIA_XY_Z_M:
6009 		xtype = GAIA_POINTZM;
6010 		break;
6011 	    default:
6012 		xtype = GAIA_POINT;
6013 		break;
6014 	    };
6015       }
6016     if (xxtype == GAIA_LINESTRING)
6017       {
6018 	  switch (dims)
6019 	    {
6020 	    case GAIA_XY_Z:
6021 		xtype = GAIA_LINESTRINGZ;
6022 		break;
6023 	    case GAIA_XY_M:
6024 		xtype = GAIA_LINESTRINGM;
6025 		break;
6026 	    case GAIA_XY_Z_M:
6027 		xtype = GAIA_LINESTRINGZM;
6028 		break;
6029 	    default:
6030 		xtype = GAIA_LINESTRING;
6031 		break;
6032 	    };
6033       }
6034     if (xxtype == GAIA_POLYGON)
6035       {
6036 	  switch (dims)
6037 	    {
6038 	    case GAIA_XY_Z:
6039 		xtype = GAIA_POLYGONZ;
6040 		break;
6041 	    case GAIA_XY_M:
6042 		xtype = GAIA_POLYGONM;
6043 		break;
6044 	    case GAIA_XY_Z_M:
6045 		xtype = GAIA_POLYGONZM;
6046 		break;
6047 	    default:
6048 		xtype = GAIA_POLYGON;
6049 		break;
6050 	    };
6051       }
6052     if (xxtype == GAIA_MULTIPOINT)
6053       {
6054 	  switch (dims)
6055 	    {
6056 	    case GAIA_XY_Z:
6057 		xtype = GAIA_MULTIPOINTZ;
6058 		break;
6059 	    case GAIA_XY_M:
6060 		xtype = GAIA_MULTIPOINTM;
6061 		break;
6062 	    case GAIA_XY_Z_M:
6063 		xtype = GAIA_MULTIPOINTZM;
6064 		break;
6065 	    default:
6066 		xtype = GAIA_MULTIPOINT;
6067 		break;
6068 	    };
6069       }
6070     if (xxtype == GAIA_MULTILINESTRING)
6071       {
6072 	  switch (dims)
6073 	    {
6074 	    case GAIA_XY_Z:
6075 		xtype = GAIA_MULTILINESTRINGZ;
6076 		break;
6077 	    case GAIA_XY_M:
6078 		xtype = GAIA_MULTILINESTRINGM;
6079 		break;
6080 	    case GAIA_XY_Z_M:
6081 		xtype = GAIA_MULTILINESTRINGZM;
6082 		break;
6083 	    default:
6084 		xtype = GAIA_MULTILINESTRING;
6085 		break;
6086 	    };
6087       }
6088     if (xxtype == GAIA_MULTIPOLYGON)
6089       {
6090 	  switch (dims)
6091 	    {
6092 	    case GAIA_XY_Z:
6093 		xtype = GAIA_MULTIPOLYGONZ;
6094 		break;
6095 	    case GAIA_XY_M:
6096 		xtype = GAIA_MULTIPOLYGONM;
6097 		break;
6098 	    case GAIA_XY_Z_M:
6099 		xtype = GAIA_MULTIPOLYGONZM;
6100 		break;
6101 	    default:
6102 		xtype = GAIA_MULTIPOLYGON;
6103 		break;
6104 	    };
6105       }
6106     if (xxtype == GAIA_GEOMETRYCOLLECTION)
6107       {
6108 	  switch (dims)
6109 	    {
6110 	    case GAIA_XY_Z:
6111 		xtype = GAIA_GEOMETRYCOLLECTIONZ;
6112 		break;
6113 	    case GAIA_XY_M:
6114 		xtype = GAIA_GEOMETRYCOLLECTIONM;
6115 		break;
6116 	    case GAIA_XY_Z_M:
6117 		xtype = GAIA_GEOMETRYCOLLECTIONZM;
6118 		break;
6119 	    default:
6120 		xtype = GAIA_GEOMETRYCOLLECTION;
6121 		break;
6122 	    };
6123       }
6124     if (xxtype == -1)
6125 	xtype = -1;		/* GEOMETRY */
6126     if (!recoverGeomColumn (sqlite, table, column, xtype, dims, srid))
6127       {
6128 	  spatialite_e ("RecoverGeometryColumn(): validation failed\n");
6129 	  sqlite3_result_int (context, 0);
6130 	  return;
6131       }
6132 /* deleting anyway any previous definition */
6133     sql_statement = sqlite3_mprintf ("DELETE FROM geometry_columns "
6134 				     "WHERE Lower(f_table_name) = Lower(?) AND "
6135 				     "Lower(f_geometry_column) = Lower(?)");
6136     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
6137 			      &stmt, NULL);
6138     sqlite3_free (sql_statement);
6139     if (ret != SQLITE_OK)
6140       {
6141 	  spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
6142 			sqlite3_errmsg (sqlite));
6143 	  sqlite3_result_int (context, 0);
6144 	  return;
6145       }
6146     sqlite3_reset (stmt);
6147     sqlite3_clear_bindings (stmt);
6148     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
6149     sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
6150     ret = sqlite3_step (stmt);
6151     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6152 	;
6153     else
6154       {
6155 	  spatialite_e ("RecoverGeometryColumn() error: \"%s\"\n",
6156 			sqlite3_errmsg (sqlite));
6157 	  sqlite3_finalize (stmt);
6158 	  goto error;
6159       }
6160     sqlite3_finalize (stmt);
6161 
6162     if (metadata_version == 1)
6163       {
6164 	  /* legacy metadata style <= v.3.1.0 */
6165 	  switch (xtype)
6166 	    {
6167 	    case GAIA_POINT:
6168 	    case GAIA_POINTZ:
6169 	    case GAIA_POINTM:
6170 	    case GAIA_POINTZM:
6171 		p_type = "POINT";
6172 		break;
6173 	    case GAIA_LINESTRING:
6174 	    case GAIA_LINESTRINGZ:
6175 	    case GAIA_LINESTRINGM:
6176 	    case GAIA_LINESTRINGZM:
6177 		p_type = "LINESTRING";
6178 		break;
6179 	    case GAIA_POLYGON:
6180 	    case GAIA_POLYGONZ:
6181 	    case GAIA_POLYGONM:
6182 	    case GAIA_POLYGONZM:
6183 		p_type = "POLYGON";
6184 		break;
6185 	    case GAIA_MULTIPOINT:
6186 	    case GAIA_MULTIPOINTZ:
6187 	    case GAIA_MULTIPOINTM:
6188 	    case GAIA_MULTIPOINTZM:
6189 		p_type = "MULTIPOINT";
6190 		break;
6191 	    case GAIA_MULTILINESTRING:
6192 	    case GAIA_MULTILINESTRINGZ:
6193 	    case GAIA_MULTILINESTRINGM:
6194 	    case GAIA_MULTILINESTRINGZM:
6195 		p_type = "MULTILINESTRING";
6196 		break;
6197 	    case GAIA_MULTIPOLYGON:
6198 	    case GAIA_MULTIPOLYGONZ:
6199 	    case GAIA_MULTIPOLYGONM:
6200 	    case GAIA_MULTIPOLYGONZM:
6201 		p_type = "MULTIPOLYGON";
6202 		break;
6203 	    case GAIA_GEOMETRYCOLLECTION:
6204 	    case GAIA_GEOMETRYCOLLECTIONZ:
6205 	    case GAIA_GEOMETRYCOLLECTIONM:
6206 	    case GAIA_GEOMETRYCOLLECTIONZM:
6207 		p_type = "GEOMETRYCOLLECTION";
6208 		break;
6209 	    case -1:
6210 		p_type = "GEOMETRY";
6211 		break;
6212 	    };
6213 	  strcat (sql, "', '");
6214 	  switch (dims)
6215 	    {
6216 	    case GAIA_XY:
6217 		p_dims = "XY";
6218 		break;
6219 	    case GAIA_XY_Z:
6220 		p_dims = "XYZ";
6221 		break;
6222 	    case GAIA_XY_M:
6223 		p_dims = "XYM";
6224 		break;
6225 	    case GAIA_XY_Z_M:
6226 		p_dims = "XYZM";
6227 		break;
6228 	    };
6229 /* Sandro 2013-01-07
6230 / fixing an issue reported by Peter Aronson [ESRI] <paronson@esri.com>
6231 	  sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
6232 					   "(f_table_name, f_geometry_column, type, coord_dimension, srid, "
6233 					   "spatial_index_enabled) VALUES (Lower(?), Lower(?), %Q, %Q, ?, 0)",
6234 					   p_type, p_dims);
6235 */
6236 	  sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
6237 					   "(f_table_name, f_geometry_column, type, coord_dimension, srid, "
6238 					   "spatial_index_enabled) VALUES (?, ?, %Q, %Q, ?, 0)",
6239 					   p_type, p_dims);
6240       }
6241     else
6242       {
6243 	  /* current metadata style >= v.4.0.0 */
6244 	  switch (xtype)
6245 	    {
6246 	    case GAIA_POINT:
6247 		n_type = 1;
6248 		n_dims = 2;
6249 		break;
6250 	    case GAIA_POINTZ:
6251 		n_type = 1001;
6252 		n_dims = 3;
6253 		break;
6254 	    case GAIA_POINTM:
6255 		n_type = 2001;
6256 		n_dims = 3;
6257 		break;
6258 	    case GAIA_POINTZM:
6259 		n_type = 3001;
6260 		n_dims = 4;
6261 		break;
6262 	    case GAIA_LINESTRING:
6263 		n_type = 2;
6264 		n_dims = 2;
6265 		break;
6266 	    case GAIA_LINESTRINGZ:
6267 		n_type = 1002;
6268 		n_dims = 3;
6269 		break;
6270 	    case GAIA_LINESTRINGM:
6271 		n_type = 2002;
6272 		n_dims = 3;
6273 		break;
6274 	    case GAIA_LINESTRINGZM:
6275 		n_type = 3002;
6276 		n_dims = 4;
6277 		break;
6278 	    case GAIA_POLYGON:
6279 		n_type = 3;
6280 		n_dims = 2;
6281 		break;
6282 	    case GAIA_POLYGONZ:
6283 		n_type = 1003;
6284 		n_dims = 3;
6285 		break;
6286 	    case GAIA_POLYGONM:
6287 		n_type = 2003;
6288 		n_dims = 3;
6289 		break;
6290 	    case GAIA_POLYGONZM:
6291 		n_type = 3003;
6292 		n_dims = 4;
6293 		break;
6294 	    case GAIA_MULTIPOINT:
6295 		n_type = 4;
6296 		n_dims = 2;
6297 		break;
6298 	    case GAIA_MULTIPOINTZ:
6299 		n_type = 1004;
6300 		n_dims = 3;
6301 		break;
6302 	    case GAIA_MULTIPOINTM:
6303 		n_type = 2004;
6304 		n_dims = 3;
6305 		break;
6306 	    case GAIA_MULTIPOINTZM:
6307 		n_type = 3004;
6308 		n_dims = 4;
6309 		break;
6310 	    case GAIA_MULTILINESTRING:
6311 		n_type = 5;
6312 		n_dims = 2;
6313 		break;
6314 	    case GAIA_MULTILINESTRINGZ:
6315 		n_type = 1005;
6316 		n_dims = 3;
6317 		break;
6318 	    case GAIA_MULTILINESTRINGM:
6319 		n_type = 2005;
6320 		n_dims = 3;
6321 		break;
6322 	    case GAIA_MULTILINESTRINGZM:
6323 		n_type = 3005;
6324 		n_dims = 4;
6325 		break;
6326 	    case GAIA_MULTIPOLYGON:
6327 		n_type = 6;
6328 		n_dims = 2;
6329 		break;
6330 	    case GAIA_MULTIPOLYGONZ:
6331 		n_type = 1006;
6332 		n_dims = 3;
6333 		break;
6334 	    case GAIA_MULTIPOLYGONM:
6335 		n_type = 2006;
6336 		n_dims = 3;
6337 		break;
6338 	    case GAIA_MULTIPOLYGONZM:
6339 		n_type = 3006;
6340 		n_dims = 4;
6341 		break;
6342 	    case GAIA_GEOMETRYCOLLECTION:
6343 		n_type = 7;
6344 		n_dims = 2;
6345 		break;
6346 	    case GAIA_GEOMETRYCOLLECTIONZ:
6347 		n_type = 1007;
6348 		n_dims = 3;
6349 		break;
6350 	    case GAIA_GEOMETRYCOLLECTIONM:
6351 		n_type = 2007;
6352 		n_dims = 3;
6353 		break;
6354 	    case GAIA_GEOMETRYCOLLECTIONZM:
6355 		n_type = 3007;
6356 		n_dims = 4;
6357 		break;
6358 	    case -1:
6359 		switch (dims)
6360 		  {
6361 		  case GAIA_XY:
6362 		      n_type = 0;
6363 		      n_dims = 2;
6364 		      break;
6365 		  case GAIA_XY_Z:
6366 		      n_type = 1000;
6367 		      n_dims = 3;
6368 		      break;
6369 		  case GAIA_XY_M:
6370 		      n_type = 2000;
6371 		      n_dims = 3;
6372 		      break;
6373 		  case GAIA_XY_Z_M:
6374 		      n_type = 3000;
6375 		      n_dims = 4;
6376 		      break;
6377 		  };
6378 		break;
6379 	    };
6380 	  sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
6381 					   "(f_table_name, f_geometry_column, geometry_type, coord_dimension, "
6382 					   "srid, spatial_index_enabled) VALUES (Lower(?), Lower(?), %d, %d, ?, 0)",
6383 					   n_type, n_dims);
6384       }
6385     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
6386 			      &stmt, NULL);
6387     sqlite3_free (sql_statement);
6388     if (ret != SQLITE_OK)
6389       {
6390 	  spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
6391 			sqlite3_errmsg (sqlite));
6392 	  sqlite3_result_int (context, 0);
6393 	  return;
6394       }
6395     sqlite3_reset (stmt);
6396     sqlite3_clear_bindings (stmt);
6397     sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
6398     sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
6399     if (srid < 0)
6400 	sqlite3_bind_int (stmt, 3, -1);
6401     else
6402 	sqlite3_bind_int (stmt, 3, srid);
6403     ret = sqlite3_step (stmt);
6404     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6405 	;
6406     else
6407       {
6408 	  spatialite_e ("RecoverGeometryColumn() error: \"%s\"\n",
6409 			sqlite3_errmsg (sqlite));
6410 	  sqlite3_finalize (stmt);
6411 	  goto error;
6412       }
6413     sqlite3_finalize (stmt);
6414     if (metadata_version == 3)
6415       {
6416 	  /* current metadata style >= v.4.0.0 */
6417 
6418 	  /* inserting a row into GEOMETRY_COLUMNS_AUTH */
6419 	  strcpy (sql,
6420 		  "INSERT OR REPLACE INTO geometry_columns_auth (f_table_name, f_geometry_column, ");
6421 	  strcat (sql, "read_only, hidden) VALUES (Lower(?), Lower(?), 0, 0)");
6422 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
6423 	  if (ret != SQLITE_OK)
6424 	    {
6425 		spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
6426 			      sqlite3_errmsg (sqlite));
6427 		sqlite3_result_int (context, 0);
6428 		return;
6429 	    }
6430 	  sqlite3_reset (stmt);
6431 	  sqlite3_clear_bindings (stmt);
6432 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
6433 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
6434 	  ret = sqlite3_step (stmt);
6435 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6436 	      ;
6437 	  else
6438 	    {
6439 		spatialite_e ("RecoverGeometryColumn() error: \"%s\"\n",
6440 			      sqlite3_errmsg (sqlite));
6441 		sqlite3_finalize (stmt);
6442 		goto error;
6443 	    }
6444 	  sqlite3_finalize (stmt);
6445 	  /* inserting a row into GEOMETRY_COLUMNS_STATISTICS */
6446 	  strcpy (sql,
6447 		  "INSERT OR REPLACE INTO geometry_columns_statistics (f_table_name, f_geometry_column) ");
6448 	  strcat (sql, "VALUES (Lower(?), Lower(?))");
6449 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
6450 	  if (ret != SQLITE_OK)
6451 	    {
6452 		spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
6453 			      sqlite3_errmsg (sqlite));
6454 		sqlite3_result_int (context, 0);
6455 		return;
6456 	    }
6457 	  sqlite3_reset (stmt);
6458 	  sqlite3_clear_bindings (stmt);
6459 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
6460 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
6461 	  ret = sqlite3_step (stmt);
6462 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6463 	      ;
6464 	  else
6465 	    {
6466 		spatialite_e ("RecoverGeometryColumn() error: \"%s\"\n",
6467 			      sqlite3_errmsg (sqlite));
6468 		sqlite3_finalize (stmt);
6469 		goto error;
6470 	    }
6471 	  sqlite3_finalize (stmt);
6472 	  /* inserting a row into GEOMETRY_COLUMNS_TIME */
6473 	  strcpy (sql,
6474 		  "INSERT OR REPLACE INTO geometry_columns_time (f_table_name, f_geometry_column) ");
6475 	  strcat (sql, "VALUES (Lower(?), Lower(?))");
6476 	  ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
6477 	  if (ret != SQLITE_OK)
6478 	    {
6479 		spatialite_e ("RecoverGeometryColumn: \"%s\"\n",
6480 			      sqlite3_errmsg (sqlite));
6481 		sqlite3_result_int (context, 0);
6482 		return;
6483 	    }
6484 	  sqlite3_reset (stmt);
6485 	  sqlite3_clear_bindings (stmt);
6486 	  sqlite3_bind_text (stmt, 1, table, strlen (table), SQLITE_STATIC);
6487 	  sqlite3_bind_text (stmt, 2, column, strlen (column), SQLITE_STATIC);
6488 	  ret = sqlite3_step (stmt);
6489 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6490 	      ;
6491 	  else
6492 	    {
6493 		spatialite_e ("RecoverGeometryColumn() error: \"%s\"\n",
6494 			      sqlite3_errmsg (sqlite));
6495 		sqlite3_finalize (stmt);
6496 		goto error;
6497 	    }
6498 	  sqlite3_finalize (stmt);
6499       }
6500     updateGeometryTriggers (sqlite, table, column);
6501     sqlite3_result_int (context, 1);
6502     switch (xtype)
6503       {
6504       case GAIA_POINT:
6505       case GAIA_POINTZ:
6506       case GAIA_POINTM:
6507       case GAIA_POINTZM:
6508 	  p_type = "POINT";
6509 	  break;
6510       case GAIA_LINESTRING:
6511       case GAIA_LINESTRINGZ:
6512       case GAIA_LINESTRINGM:
6513       case GAIA_LINESTRINGZM:
6514 	  p_type = "LINESTRING";
6515 	  break;
6516       case GAIA_POLYGON:
6517       case GAIA_POLYGONZ:
6518       case GAIA_POLYGONM:
6519       case GAIA_POLYGONZM:
6520 	  p_type = "POLYGON";
6521 	  break;
6522       case GAIA_MULTIPOINT:
6523       case GAIA_MULTIPOINTZ:
6524       case GAIA_MULTIPOINTM:
6525       case GAIA_MULTIPOINTZM:
6526 	  p_type = "MULTIPOINT";
6527 	  break;
6528       case GAIA_MULTILINESTRING:
6529       case GAIA_MULTILINESTRINGZ:
6530       case GAIA_MULTILINESTRINGM:
6531       case GAIA_MULTILINESTRINGZM:
6532 	  p_type = "MULTILINESTRING";
6533 	  break;
6534       case GAIA_MULTIPOLYGON:
6535       case GAIA_MULTIPOLYGONZ:
6536       case GAIA_MULTIPOLYGONM:
6537       case GAIA_MULTIPOLYGONZM:
6538 	  p_type = "MULTIPOLYGON";
6539 	  break;
6540       case GAIA_GEOMETRYCOLLECTION:
6541       case GAIA_GEOMETRYCOLLECTIONZ:
6542       case GAIA_GEOMETRYCOLLECTIONM:
6543       case GAIA_GEOMETRYCOLLECTIONZM:
6544 	  p_type = "GEOMETRYCOLLECTION";
6545 	  break;
6546       case -1:
6547 	  p_type = "GEOMETRY";
6548 	  break;
6549       };
6550     switch (dims)
6551       {
6552       case GAIA_XY:
6553 	  p_dims = "XY";
6554 	  break;
6555       case GAIA_XY_Z:
6556 	  p_dims = "XYZ";
6557 	  break;
6558       case GAIA_XY_M:
6559 	  p_dims = "XYM";
6560 	  break;
6561       case GAIA_XY_Z_M:
6562 	  p_dims = "XYZM";
6563 	  break;
6564       };
6565     sql_statement =
6566 	sqlite3_mprintf ("Geometry [%s,%s,SRID=%d] successfully recovered",
6567 			 p_type, p_dims, (srid <= 0) ? -1 : srid);
6568     updateSpatiaLiteHistory (sqlite, table, column, sql_statement);
6569     sqlite3_free (sql_statement);
6570     return;
6571   error:
6572     sqlite3_result_int (context, 0);
6573     return;
6574 }
6575 
6576 static void
fnct_DiscardGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)6577 fnct_DiscardGeometryColumn (sqlite3_context * context, int argc,
6578 			    sqlite3_value ** argv)
6579 {
6580 /* SQL function:
6581 / DiscardGeometryColumn(table, column)
6582 /
6583 / removes TABLE.COLUMN from the Spatial MetaData [thus disabling triggers too]
6584 / returns 1 on success
6585 / 0 on failure
6586 */
6587     const unsigned char *table;
6588     const unsigned char *column;
6589     char *p_table = NULL;
6590     char *p_column = NULL;
6591     sqlite3_stmt *stmt;
6592     char *sql_statement;
6593     char *raw;
6594     char *quoted;
6595     char *errMsg = NULL;
6596     int ret;
6597     sqlite3 *sqlite = sqlite3_context_db_handle (context);
6598     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
6599     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
6600       {
6601 	  spatialite_e
6602 	      ("DiscardGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
6603 	  sqlite3_result_int (context, 0);
6604 	  return;
6605       }
6606     table = sqlite3_value_text (argv[0]);
6607     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
6608       {
6609 	  spatialite_e
6610 	      ("DiscardGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
6611 	  sqlite3_result_int (context, 0);
6612 	  return;
6613       }
6614     column = sqlite3_value_text (argv[1]);
6615 
6616     sql_statement = sqlite3_mprintf ("DELETE FROM geometry_columns "
6617 				     "WHERE Lower(f_table_name) = Lower(?) "
6618 				     "AND Lower(f_geometry_column) = Lower(?)");
6619     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
6620 			      &stmt, NULL);
6621     sqlite3_free (sql_statement);
6622     if (ret != SQLITE_OK)
6623       {
6624 	  spatialite_e ("DiscardGeometryColumn: \"%s\"\n",
6625 			sqlite3_errmsg (sqlite));
6626 	  sqlite3_result_int (context, 0);
6627 	  return;
6628       }
6629     sqlite3_reset (stmt);
6630     sqlite3_clear_bindings (stmt);
6631     sqlite3_bind_text (stmt, 1, (const char *) table,
6632 		       strlen ((const char *) table), SQLITE_STATIC);
6633     sqlite3_bind_text (stmt, 2, (const char *) column,
6634 		       strlen ((const char *) column), SQLITE_STATIC);
6635     ret = sqlite3_step (stmt);
6636     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
6637 	;
6638     else
6639       {
6640 	  spatialite_e ("DiscardGeometryColumn() error: \"%s\"\n",
6641 			sqlite3_errmsg (sqlite));
6642 	  sqlite3_finalize (stmt);
6643 	  goto error;
6644       }
6645     sqlite3_finalize (stmt);
6646 /* removing triggers too */
6647     if (!getRealSQLnames
6648 	(sqlite, (const char *) table, (const char *) column, &p_table,
6649 	 &p_column))
6650       {
6651 	  spatialite_e
6652 	      ("DiscardGeometryColumn() error: not existing Table or Column\n");
6653 	  sqlite3_result_int (context, 0);
6654 	  return;
6655       }
6656     raw = sqlite3_mprintf ("ggi_%s_%s", p_table, p_column);
6657     quoted = gaiaDoubleQuotedSql (raw);
6658     sqlite3_free (raw);
6659     sql_statement =
6660 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6661     free (quoted);
6662     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6663     sqlite3_free (sql_statement);
6664     if (ret != SQLITE_OK)
6665 	goto error;
6666     raw = sqlite3_mprintf ("ggu_%s_%s", p_table, p_column);
6667     quoted = gaiaDoubleQuotedSql (raw);
6668     sqlite3_free (raw);
6669     sql_statement =
6670 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6671     free (quoted);
6672     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6673     sqlite3_free (sql_statement);
6674     if (ret != SQLITE_OK)
6675 	goto error;
6676     raw = sqlite3_mprintf ("gii_%s_%s", p_table, p_column);
6677     quoted = gaiaDoubleQuotedSql (raw);
6678     sqlite3_free (raw);
6679     sql_statement =
6680 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6681     free (quoted);
6682     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6683     sqlite3_free (sql_statement);
6684     if (ret != SQLITE_OK)
6685 	goto error;
6686     raw = sqlite3_mprintf ("giu_%s_%s", p_table, p_column);
6687     quoted = gaiaDoubleQuotedSql (raw);
6688     sqlite3_free (raw);
6689     sql_statement =
6690 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6691     free (quoted);
6692     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6693     sqlite3_free (sql_statement);
6694     if (ret != SQLITE_OK)
6695 	goto error;
6696     raw = sqlite3_mprintf ("gid_%s_%s", p_table, p_column);
6697     quoted = gaiaDoubleQuotedSql (raw);
6698     sqlite3_free (raw);
6699     sql_statement =
6700 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6701     free (quoted);
6702     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6703     sqlite3_free (sql_statement);
6704     if (ret != SQLITE_OK)
6705 	goto error;
6706     raw = sqlite3_mprintf ("gci_%s_%s", p_table, p_column);
6707     quoted = gaiaDoubleQuotedSql (raw);
6708     sqlite3_free (raw);
6709     sql_statement =
6710 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6711     free (quoted);
6712     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6713     sqlite3_free (sql_statement);
6714     if (ret != SQLITE_OK)
6715 	goto error;
6716     raw = sqlite3_mprintf ("gcu_%s_%s", p_table, p_column);
6717     quoted = gaiaDoubleQuotedSql (raw);
6718     sqlite3_free (raw);
6719     sql_statement =
6720 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6721     free (quoted);
6722     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6723     sqlite3_free (sql_statement);
6724     if (ret != SQLITE_OK)
6725 	goto error;
6726     raw = sqlite3_mprintf ("gcd_%s_%s", p_table, p_column);
6727     quoted = gaiaDoubleQuotedSql (raw);
6728     sqlite3_free (raw);
6729     sql_statement =
6730 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6731     free (quoted);
6732     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6733     sqlite3_free (sql_statement);
6734     if (ret != SQLITE_OK)
6735 	goto error;
6736     raw = sqlite3_mprintf ("tmi_%s_%s", p_table, p_column);
6737     quoted = gaiaDoubleQuotedSql (raw);
6738     sqlite3_free (raw);
6739     sql_statement =
6740 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6741     free (quoted);
6742     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6743     sqlite3_free (sql_statement);
6744     if (ret != SQLITE_OK)
6745 	goto error;
6746     raw = sqlite3_mprintf ("tmu_%s_%s", p_table, p_column);
6747     quoted = gaiaDoubleQuotedSql (raw);
6748     sqlite3_free (raw);
6749     sql_statement =
6750 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6751     free (quoted);
6752     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6753     sqlite3_free (sql_statement);
6754     if (ret != SQLITE_OK)
6755 	goto error;
6756     raw = sqlite3_mprintf ("tmd_%s_%s", p_table, p_column);
6757     quoted = gaiaDoubleQuotedSql (raw);
6758     sqlite3_free (raw);
6759     sql_statement =
6760 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6761     free (quoted);
6762     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6763     sqlite3_free (sql_statement);
6764     if (ret != SQLITE_OK)
6765 	goto error;
6766 
6767     /* trying to delete old versions [v2.0, v2.2] triggers[if any] */
6768     raw = sqlite3_mprintf ("gti_%s_%s", p_table, p_column);
6769     quoted = gaiaDoubleQuotedSql (raw);
6770     sqlite3_free (raw);
6771     sql_statement =
6772 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6773     free (quoted);
6774     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6775     sqlite3_free (sql_statement);
6776     if (ret != SQLITE_OK)
6777 	goto error;
6778     raw = sqlite3_mprintf ("gtu_%s_%s", p_table, p_column);
6779     quoted = gaiaDoubleQuotedSql (raw);
6780     sqlite3_free (raw);
6781     sql_statement =
6782 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6783     free (quoted);
6784     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6785     sqlite3_free (sql_statement);
6786     if (ret != SQLITE_OK)
6787 	goto error;
6788     raw = sqlite3_mprintf ("gsi_%s_%s", p_table, p_column);
6789     quoted = gaiaDoubleQuotedSql (raw);
6790     sqlite3_free (raw);
6791     sql_statement =
6792 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6793     free (quoted);
6794     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6795     sqlite3_free (sql_statement);
6796     if (ret != SQLITE_OK)
6797 	goto error;
6798     raw = sqlite3_mprintf ("gsu_%s_%s", p_table, p_column);
6799     quoted = gaiaDoubleQuotedSql (raw);
6800     sqlite3_free (raw);
6801     sql_statement =
6802 	sqlite3_mprintf ("DROP TRIGGER IF EXISTS main.\"%s\"", quoted);
6803     free (quoted);
6804     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
6805     sqlite3_free (sql_statement);
6806     if (ret != SQLITE_OK)
6807 	goto error;
6808     /* end deletion old versions [v2.0, v2.2] triggers[if any] */
6809 
6810     sqlite3_result_int (context, 1);
6811     updateSpatiaLiteHistory (sqlite, p_table,
6812 			     p_column, "Geometry successfully discarded");
6813     free (p_table);
6814     free (p_column);
6815     return;
6816   error:
6817     if (p_table)
6818 	free (p_table);
6819     if (p_column)
6820 	free (p_column);
6821     spatialite_e ("DiscardGeometryColumn() error: \"%s\"\n", errMsg);
6822     sqlite3_free (errMsg);
6823     sqlite3_result_int (context, 0);
6824     return;
6825 }
6826 
6827 static int
registerVirtual(sqlite3 * sqlite,const char * table)6828 registerVirtual (sqlite3 * sqlite, const char *table)
6829 {
6830 /* attempting to register a VirtualGeometry */
6831     char gtype[64];
6832     int xtype = -1;
6833     int srid = -1;
6834     char **results;
6835     int ret;
6836     int rows;
6837     int columns;
6838     int i;
6839     char *errMsg = NULL;
6840     int ok_virt_name = 0;
6841     int ok_virt_geometry = 0;
6842     int ok_srid = 0;
6843     int ok_geometry_type = 0;
6844     int ok_type = 0;
6845     int ok_coord_dimension = 0;
6846     int xdims;
6847     char *quoted;
6848     char *sql_statement;
6849 
6850 /* testing the layout of virts_geometry_columns table */
6851     ret = sqlite3_get_table (sqlite,
6852 			     "PRAGMA table_info(virts_geometry_columns)",
6853 			     &results, &rows, &columns, &errMsg);
6854     if (ret != SQLITE_OK)
6855       {
6856 	  spatialite_e ("RegisterVirtualGeometry() error: \"%s\"\n", errMsg);
6857 	  sqlite3_free (errMsg);
6858 	  return 0;
6859       }
6860     for (i = 1; i <= rows; i++)
6861       {
6862 	  if (strcasecmp ("virt_name", results[(i * columns) + 1]) == 0)
6863 	      ok_virt_name = 1;
6864 	  if (strcasecmp ("virt_geometry", results[(i * columns) + 1]) == 0)
6865 	      ok_virt_geometry = 1;
6866 	  if (strcasecmp ("srid", results[(i * columns) + 1]) == 0)
6867 	      ok_srid = 1;
6868 	  if (strcasecmp ("geometry_type", results[(i * columns) + 1]) == 0)
6869 	      ok_geometry_type = 1;
6870 	  if (strcasecmp ("type", results[(i * columns) + 1]) == 0)
6871 	      ok_type = 1;
6872 	  if (strcasecmp ("coord_dimension", results[(i * columns) + 1]) == 0)
6873 	      ok_coord_dimension = 1;
6874       }
6875     sqlite3_free_table (results);
6876 
6877     if (ok_virt_name && ok_virt_geometry && ok_srid && ok_geometry_type
6878 	&& ok_coord_dimension)
6879 	;
6880     else if (ok_virt_name && ok_virt_geometry && ok_srid && ok_type)
6881 	;
6882     else
6883 	return 0;
6884 
6885 /* determining Geometry Type and dims */
6886     quoted = gaiaDoubleQuotedSql (table);
6887     sql_statement =
6888 	sqlite3_mprintf ("SELECT DISTINCT "
6889 			 "ST_GeometryType(Geometry), ST_Srid(Geometry) FROM \"%s\"",
6890 			 quoted);
6891     free (quoted);
6892     ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows, &columns,
6893 			     &errMsg);
6894     sqlite3_free (sql_statement);
6895     if (ret != SQLITE_OK)
6896       {
6897 	  spatialite_e ("RegisterVirtualGeometry() error: \"%s\"\n", errMsg);
6898 	  sqlite3_free (errMsg);
6899 	  return 0;
6900       }
6901     for (i = 1; i <= rows; i++)
6902       {
6903 	  if (results[(i * columns)] == NULL)
6904 	      *gtype = '\0';
6905 	  else
6906 	      strcpy (gtype, results[(i * columns)]);
6907 	  if (results[(i * columns) + 1] == NULL)
6908 	      srid = 0;
6909 	  else
6910 	      srid = atoi (results[(i * columns) + 1]);
6911       }
6912     sqlite3_free_table (results);
6913 
6914 /* normalized Geometry type */
6915     if (strcmp (gtype, "POINT") == 0)
6916 	xtype = 1;
6917     if (strcmp (gtype, "POINT Z") == 0)
6918 	xtype = 1001;
6919     if (strcmp (gtype, "POINT M") == 0)
6920 	xtype = 2001;
6921     if (strcmp (gtype, "POINT ZM") == 0)
6922 	xtype = 3001;
6923     if (strcmp (gtype, "LINESTRING") == 0)
6924 	xtype = 2;
6925     if (strcmp (gtype, "LINESTRING Z") == 0)
6926 	xtype = 1002;
6927     if (strcmp (gtype, "LINESTRING M") == 0)
6928 	xtype = 2002;
6929     if (strcmp (gtype, "LINESTRING ZM") == 0)
6930 	xtype = 3002;
6931     if (strcmp (gtype, "POLYGON") == 0)
6932 	xtype = 3;
6933     if (strcmp (gtype, "POLYGON Z") == 0)
6934 	xtype = 1003;
6935     if (strcmp (gtype, "POLYGON M") == 0)
6936 	xtype = 2003;
6937     if (strcmp (gtype, "POLYGON ZM") == 0)
6938 	xtype = 3003;
6939     if (strcmp (gtype, "MULTIPOINT") == 0)
6940 	xtype = 4;
6941     if (strcmp (gtype, "MULTIPOINT Z") == 0)
6942 	xtype = 1004;
6943     if (strcmp (gtype, "MULTIPOINT M") == 0)
6944 	xtype = 2004;
6945     if (strcmp (gtype, "MULTIPOINT ZM") == 0)
6946 	xtype = 3004;
6947     if (strcmp (gtype, "MULTILINESTRING") == 0)
6948 	xtype = 5;
6949     if (strcmp (gtype, "MULTILINESTRING Z") == 0)
6950 	xtype = 1005;
6951     if (strcmp (gtype, "MULTILINESTRING M") == 0)
6952 	xtype = 2005;
6953     if (strcmp (gtype, "MULTILINESTRING ZM") == 0)
6954 	xtype = 3005;
6955     if (strcmp (gtype, "MULTIPOLYGON") == 0)
6956 	xtype = 6;
6957     if (strcmp (gtype, "MULTIPOLYGON Z") == 0)
6958 	xtype = 1006;
6959     if (strcmp (gtype, "MULTIPOLYGON M") == 0)
6960 	xtype = 2006;
6961     if (strcmp (gtype, "MULTIPOLYGON ZM") == 0)
6962 	xtype = 3006;
6963 
6964 /* updating metadata tables */
6965     xdims = -1;
6966     switch (xtype)
6967       {
6968       case 1:
6969       case 2:
6970       case 3:
6971       case 4:
6972       case 5:
6973       case 6:
6974 	  xdims = 2;
6975 	  break;
6976       case 1001:
6977       case 1002:
6978       case 1003:
6979       case 1004:
6980       case 1005:
6981       case 1006:
6982       case 2001:
6983       case 2002:
6984       case 2003:
6985       case 2004:
6986       case 2005:
6987       case 2006:
6988 	  xdims = 3;
6989 	  break;
6990       case 3001:
6991       case 3002:
6992       case 3003:
6993       case 3004:
6994       case 3005:
6995       case 3006:
6996 	  xdims = 4;
6997 	  break;
6998       };
6999     if (ok_geometry_type)
7000       {
7001 	  /* has the "geometry_type" column */
7002 	  sql_statement =
7003 	      sqlite3_mprintf
7004 	      ("INSERT OR REPLACE INTO virts_geometry_columns "
7005 	       "(virt_name, virt_geometry, geometry_type, coord_dimension, srid) "
7006 	       "VALUES (Lower(%Q), 'geometry', %d, %d, %d)", table, xtype,
7007 	       xdims, srid);
7008       }
7009     else
7010       {
7011 	  /* has the "type" column */
7012 	  const char *xgtype = "UNKNOWN";
7013 	  switch (xtype)
7014 	    {
7015 	    case 1:
7016 	    case 1001:
7017 	    case 2001:
7018 	    case 3001:
7019 		xgtype = "POINT";
7020 		break;
7021 	    case 2:
7022 	    case 1002:
7023 	    case 2002:
7024 	    case 3002:
7025 		xgtype = "LINESTRING";
7026 		break;
7027 	    case 3:
7028 	    case 1003:
7029 	    case 2003:
7030 	    case 3003:
7031 		xgtype = "POLYGON";
7032 		break;
7033 	    case 4:
7034 	    case 1004:
7035 	    case 2004:
7036 	    case 3004:
7037 		xgtype = "MULTIPOINT";
7038 		break;
7039 	    case 5:
7040 	    case 1005:
7041 	    case 2005:
7042 	    case 3005:
7043 		xgtype = "MULTILINESTRING";
7044 		break;
7045 	    case 6:
7046 	    case 1006:
7047 	    case 2006:
7048 	    case 3006:
7049 		xgtype = "MULTIPOLYGON";
7050 		break;
7051 	    };
7052 	  sql_statement =
7053 	      sqlite3_mprintf
7054 	      ("INSERT OR REPLACE INTO virts_geometry_columns "
7055 	       "(virt_name, virt_geometry, type, srid) "
7056 	       "VALUES (Lower(%Q), 'geometry', %Q, %d)", table, xgtype, srid);
7057       }
7058     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7059     sqlite3_free (sql_statement);
7060     if (ret != SQLITE_OK)
7061       {
7062 	  spatialite_e ("RegisterVirtualGeometry() error: \"%s\"\n", errMsg);
7063 	  sqlite3_free (errMsg);
7064 	  return 0;
7065       }
7066     if (checkSpatialMetaData (sqlite) == 3)
7067       {
7068 	  /* current metadata style >= v.4.0.0 */
7069 
7070 	  /* inserting a row into VIRTS_GEOMETRY_COLUMNS_AUTH */
7071 	  sql_statement = sqlite3_mprintf ("INSERT OR REPLACE INTO "
7072 					   "virts_geometry_columns_auth (virt_name, virt_geometry, hidden) "
7073 					   "VALUES (Lower(%Q), 'geometry', 0)",
7074 					   table);
7075 	  ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7076 	  sqlite3_free (sql_statement);
7077 	  if (ret != SQLITE_OK)
7078 	    {
7079 		spatialite_e ("RegisterVirtualGeometry() error: \"%s\"\n",
7080 			      errMsg);
7081 		sqlite3_free (errMsg);
7082 		return 0;
7083 	    }
7084 	  /* inserting a row into GEOMETRY_COLUMNS_STATISTICS */
7085 	  sql_statement = sqlite3_mprintf ("INSERT OR REPLACE INTO "
7086 					   "virts_geometry_columns_statistics (virt_name, virt_geometry) "
7087 					   "VALUES (Lower(%Q), 'geometry')",
7088 					   table);
7089 	  ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7090 	  sqlite3_free (sql_statement);
7091 	  if (ret != SQLITE_OK)
7092 	    {
7093 		spatialite_e ("RegisterVirtualGeometry() error: \"%s\"\n",
7094 			      errMsg);
7095 		sqlite3_free (errMsg);
7096 		return 0;
7097 	    }
7098       }
7099     return 1;
7100 }
7101 
7102 static void
fnct_RegisterVirtualGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)7103 fnct_RegisterVirtualGeometry (sqlite3_context * context, int argc,
7104 			      sqlite3_value ** argv)
7105 {
7106 /* SQL function:
7107 / RegisterVirtualGeometry(table)
7108 /
7109 / insert/updates TABLE.COLUMN into the Spatial MetaData [Virtual Table]
7110 / returns 1 on success
7111 / 0 on failure
7112 */
7113     const unsigned char *table;
7114     char sql[1024];
7115     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7116     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7117     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7118       {
7119 	  spatialite_e
7120 	      ("RegisterVirtualGeometry() error: argument 1 [table_name] is not of the String type\n");
7121 	  sqlite3_result_int (context, 0);
7122 	  return;
7123       }
7124     table = sqlite3_value_text (argv[0]);
7125     if (!registerVirtual (sqlite, (char *) table))
7126 	goto error;
7127     sqlite3_result_int (context, 1);
7128     strcpy (sql, "Virtual Geometry successfully registered");
7129     updateSpatiaLiteHistory (sqlite, (const char *) table, "Geometry", sql);
7130     return;
7131   error:
7132     spatialite_e ("RegisterVirtualGeometry() error\n");
7133     sqlite3_result_int (context, 0);
7134     return;
7135 }
7136 
7137 
7138 static void
fnct_DropVirtualGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)7139 fnct_DropVirtualGeometry (sqlite3_context * context, int argc,
7140 			  sqlite3_value ** argv)
7141 {
7142 /* SQL function:
7143 / DropVirtualGeometry(table)
7144 /
7145 / removes TABLE.COLUMN from the Spatial MetaData and DROPs the Virtual Table
7146 / returns 1 on success
7147 / 0 on failure
7148 */
7149     const unsigned char *table;
7150     char *sql_statement;
7151     char *errMsg = NULL;
7152     int ret;
7153     char *quoted;
7154     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7155     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7156     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7157       {
7158 	  spatialite_e
7159 	      ("DropVirtualGeometry() error: argument 1 [table_name] is not of the String type\n");
7160 	  sqlite3_result_int (context, 0);
7161 	  return;
7162       }
7163     table = sqlite3_value_text (argv[0]);
7164     sql_statement = sqlite3_mprintf ("DELETE FROM virts_geometry_columns "
7165 				     "WHERE Lower(virt_name) = Lower(%Q)",
7166 				     table);
7167     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7168     sqlite3_free (sql_statement);
7169     if (ret != SQLITE_OK)
7170 	goto error;
7171     quoted = gaiaDoubleQuotedSql ((const char *) table);
7172     sql_statement = sqlite3_mprintf ("DROP TABLE IF EXISTS \"%s\"", quoted);
7173     free (quoted);
7174     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7175     sqlite3_free (sql_statement);
7176     if (ret != SQLITE_OK)
7177 	goto error;
7178     sqlite3_result_int (context, 1);
7179     updateSpatiaLiteHistory (sqlite, (const char *) table, "Geometry",
7180 			     "Virtual Geometry successfully dropped");
7181     return;
7182   error:
7183     spatialite_e ("DropVirtualGeometry() error: \"%s\"\n", errMsg);
7184     sqlite3_free (errMsg);
7185     sqlite3_result_int (context, 0);
7186     return;
7187 }
7188 
7189 static void
fnct_InitFDOSpatialMetaData(sqlite3_context * context,int argc,sqlite3_value ** argv)7190 fnct_InitFDOSpatialMetaData (sqlite3_context * context, int argc,
7191 			     sqlite3_value ** argv)
7192 {
7193 /* SQL function:
7194 / InitFDOSpatialMetaData(void)
7195 /
7196 / creates the FDO-styled SPATIAL_REF_SYS and GEOMETRY_COLUMNS tables
7197 / returns 1 on success
7198 / 0 on failure
7199 */
7200     char sql[1024];
7201     char *errMsg = NULL;
7202     int ret;
7203     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7204     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7205 /* creating the SPATIAL_REF_SYS tables */
7206     strcpy (sql, "CREATE TABLE spatial_ref_sys (\n");
7207     strcat (sql, "srid INTEGER PRIMARY KEY,\n");
7208     strcat (sql, "auth_name TEXT,\n");
7209     strcat (sql, "auth_srid INTEGER,\n");
7210     strcat (sql, "srtext TEXT)");
7211     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
7212     if (ret != SQLITE_OK)
7213 	goto error;
7214 /* creating the GEOMETRY_COLUMN tables */
7215     strcpy (sql, "CREATE TABLE geometry_columns (\n");
7216     strcat (sql, "f_table_name TEXT,\n");
7217     strcat (sql, "f_geometry_column TEXT,\n");
7218     strcat (sql, "geometry_type INTEGER,\n");
7219     strcat (sql, "coord_dimension INTEGER,\n");
7220     strcat (sql, "srid INTEGER,\n");
7221     strcat (sql, "geometry_format TEXT)");
7222     ret = sqlite3_exec (sqlite, sql, NULL, NULL, &errMsg);
7223     if (ret != SQLITE_OK)
7224 	goto error;
7225     sqlite3_result_int (context, 1);
7226     return;
7227   error:
7228     spatialite_e ("InitFDOSpatiaMetaData() error: \"%s\"\n", errMsg);
7229     sqlite3_free (errMsg);
7230     sqlite3_result_int (context, 0);
7231     return;
7232 }
7233 
7234 static int
recoverFDOGeomColumn(sqlite3 * sqlite,const unsigned char * table,const unsigned char * column,int xtype,int srid)7235 recoverFDOGeomColumn (sqlite3 * sqlite, const unsigned char *table,
7236 		      const unsigned char *column, int xtype, int srid)
7237 {
7238 /* checks if TABLE.COLUMN exists and has the required features */
7239     int ok = 1;
7240     char *sql_statement;
7241     int type;
7242     sqlite3_stmt *stmt;
7243     gaiaGeomCollPtr geom;
7244     const void *blob_value;
7245     int len;
7246     int ret;
7247     int i_col;
7248     char *xcolumn;
7249     char *xtable;
7250     xcolumn = gaiaDoubleQuotedSql ((char *) column);
7251     xtable = gaiaDoubleQuotedSql ((char *) table);
7252     sql_statement =
7253 	sqlite3_mprintf ("SELECT \"%s\" FROM \"%s\"", xcolumn, xtable);
7254     free (xcolumn);
7255     free (xtable);
7256 /* compiling SQL prepared statement */
7257     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
7258 			      &stmt, NULL);
7259     sqlite3_free (sql_statement);
7260     if (ret != SQLITE_OK)
7261       {
7262 	  spatialite_e ("recoverFDOGeomColumn: error %d \"%s\"\n",
7263 			sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
7264 	  return 0;
7265       }
7266     while (1)
7267       {
7268 	  /* scrolling the result set rows */
7269 	  ret = sqlite3_step (stmt);
7270 	  if (ret == SQLITE_DONE)
7271 	      break;		/* end of result set */
7272 	  if (ret == SQLITE_ROW)
7273 	    {
7274 		/* checking Geometry features */
7275 		geom = NULL;
7276 		for (i_col = 0; i_col < sqlite3_column_count (stmt); i_col++)
7277 		  {
7278 		      if (sqlite3_column_type (stmt, i_col) != SQLITE_BLOB)
7279 			  ok = 0;
7280 		      else
7281 			{
7282 			    blob_value = sqlite3_column_blob (stmt, i_col);
7283 			    len = sqlite3_column_bytes (stmt, i_col);
7284 			    geom = gaiaFromSpatiaLiteBlobWkb (blob_value, len);
7285 			    if (!geom)
7286 				ok = 0;
7287 			    else
7288 			      {
7289 				  if (geom->Srid != srid)
7290 				      ok = 0;
7291 				  /* normalizing Geometry Type */
7292 				  switch (gaiaGeometryType (geom))
7293 				    {
7294 				    case GAIA_POINT:
7295 				    case GAIA_POINTZ:
7296 				    case GAIA_POINTM:
7297 				    case GAIA_POINTZM:
7298 					type = GAIA_POINT;
7299 					break;
7300 				    case GAIA_LINESTRING:
7301 				    case GAIA_LINESTRINGZ:
7302 				    case GAIA_LINESTRINGM:
7303 				    case GAIA_LINESTRINGZM:
7304 					type = GAIA_LINESTRING;
7305 					break;
7306 				    case GAIA_POLYGON:
7307 				    case GAIA_POLYGONZ:
7308 				    case GAIA_POLYGONM:
7309 				    case GAIA_POLYGONZM:
7310 					type = GAIA_POLYGON;
7311 					break;
7312 				    case GAIA_MULTIPOINT:
7313 				    case GAIA_MULTIPOINTZ:
7314 				    case GAIA_MULTIPOINTM:
7315 				    case GAIA_MULTIPOINTZM:
7316 					type = GAIA_MULTIPOINT;
7317 					break;
7318 				    case GAIA_MULTILINESTRING:
7319 				    case GAIA_MULTILINESTRINGZ:
7320 				    case GAIA_MULTILINESTRINGM:
7321 				    case GAIA_MULTILINESTRINGZM:
7322 					type = GAIA_MULTILINESTRING;
7323 					break;
7324 				    case GAIA_MULTIPOLYGON:
7325 				    case GAIA_MULTIPOLYGONZ:
7326 				    case GAIA_MULTIPOLYGONM:
7327 				    case GAIA_MULTIPOLYGONZM:
7328 					type = GAIA_MULTIPOLYGON;
7329 					break;
7330 				    case GAIA_GEOMETRYCOLLECTION:
7331 				    case GAIA_GEOMETRYCOLLECTIONZ:
7332 				    case GAIA_GEOMETRYCOLLECTIONM:
7333 				    case GAIA_GEOMETRYCOLLECTIONZM:
7334 					type = GAIA_GEOMETRYCOLLECTION;
7335 					break;
7336 				    default:
7337 					type = -1;
7338 					break;
7339 				    };
7340 				  if (xtype == type)
7341 				      ;
7342 				  else
7343 				      ok = 0;
7344 				  gaiaFreeGeomColl (geom);
7345 			      }
7346 			}
7347 		  }
7348 	    }
7349 	  if (!ok)
7350 	      break;
7351       }
7352     ret = sqlite3_finalize (stmt);
7353     if (ret != SQLITE_OK)
7354       {
7355 	  spatialite_e ("recoverFDOGeomColumn: error %d \"%s\"\n",
7356 			sqlite3_errcode (sqlite), sqlite3_errmsg (sqlite));
7357 	  return 0;
7358       }
7359     return ok;
7360 }
7361 
7362 static void
fnct_AddFDOGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)7363 fnct_AddFDOGeometryColumn (sqlite3_context * context, int argc,
7364 			   sqlite3_value ** argv)
7365 {
7366 /* SQL function:
7367 / AddFDOGeometryColumn(table, column, srid, geometry_type , dimension, geometry_format )
7368 /
7369 / creates a new COLUMN of given TYPE into TABLE
7370 / Adds a matching entry into spatial_ref_sys when needed [Mark Johnson patch]
7371 / returns 1 on success
7372 / 0 on failure
7373 */
7374     const char *table;
7375     const char *column;
7376     const char *format;
7377     char xformat[64];
7378     int type;
7379     int srid = -1;
7380     int srid_exists = -1;
7381     struct epsg_defs *first = NULL;
7382     struct epsg_defs *last = NULL;
7383     sqlite3_stmt *stmt_sql;
7384     int dimension = 2;
7385     char *sql_statement;
7386     char *errMsg = NULL;
7387     int ret;
7388     char **results;
7389     int rows;
7390     int columns;
7391     int i;
7392     int oktbl;
7393     char *xtable;
7394     char *xcolumn;
7395     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7396     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7397     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7398       {
7399 	  spatialite_e
7400 	      ("AddFDOGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
7401 	  sqlite3_result_int (context, 0);
7402 	  return;
7403       }
7404     table = (const char *) sqlite3_value_text (argv[0]);
7405     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
7406       {
7407 	  spatialite_e
7408 	      ("AddFDOGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
7409 	  sqlite3_result_int (context, 0);
7410 	  return;
7411       }
7412     column = (const char *) sqlite3_value_text (argv[1]);
7413     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
7414       {
7415 	  spatialite_e
7416 	      ("AddFDOGeometryColumn() error: argument 3 [SRID] is not of the Integer type\n");
7417 	  sqlite3_result_int (context, 0);
7418 	  return;
7419       }
7420     srid = sqlite3_value_int (argv[2]);
7421     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
7422       {
7423 	  spatialite_e
7424 	      ("AddFDOGeometryColumn() error: argument 4 [geometry_type] is not of the Integer type\n");
7425 	  sqlite3_result_int (context, 0);
7426 	  return;
7427       }
7428     type = sqlite3_value_int (argv[3]);
7429     if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
7430       {
7431 	  spatialite_e
7432 	      ("AddFDOGeometryColumn() error: argument 5 [dimension] is not of the Integer type\n");
7433 	  sqlite3_result_int (context, 0);
7434 	  return;
7435       }
7436     dimension = sqlite3_value_int (argv[4]);
7437     if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
7438       {
7439 	  spatialite_e
7440 	      ("AddFDOGeometryColumn() error: argument 6 [geometry_format] is not of the String type\n");
7441 	  sqlite3_result_int (context, 0);
7442 	  return;
7443       }
7444     format = (const char *) sqlite3_value_text (argv[5]);
7445     if (type ==
7446 	GAIA_POINT
7447 	|| type ==
7448 	GAIA_LINESTRING
7449 	|| type ==
7450 	GAIA_POLYGON
7451 	|| type ==
7452 	GAIA_MULTIPOINT
7453 	|| type ==
7454 	GAIA_MULTILINESTRING
7455 	|| type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
7456 	;
7457     else
7458       {
7459 	  spatialite_e
7460 	      ("AddFDOGeometryColumn() error: argument 4 [geometry_type] has an illegal value\n");
7461 	  sqlite3_result_int (context, 0);
7462 	  return;
7463       }
7464     if (dimension < 2 || dimension > 4)
7465       {
7466 	  spatialite_e
7467 	      ("AddFDOGeometryColumn() error: argument 5 [dimension] current version only accepts dimension=2,3,4\n");
7468 	  sqlite3_result_int (context, 0);
7469 	  return;
7470       }
7471     if (strcasecmp (format, "WKT") == 0)
7472 	strcpy (xformat, "WKT");
7473     else if (strcasecmp (format, "WKB") == 0)
7474 	strcpy (xformat, "WKB");
7475     else if (strcasecmp (format, "FGF") == 0)
7476 	strcpy (xformat, "FGF");
7477     else if (strcasecmp (format, "SPATIALITE") == 0)
7478 	strcpy (xformat, "SPATIALITE");
7479     else
7480       {
7481 	  spatialite_e
7482 	      ("AddFDOGeometryColumn() error: argument 6 [geometry_format] has to be one of: WKT,WKB,FGF,SPATIALITE\n");
7483 	  sqlite3_result_int (context, 0);
7484 	  return;
7485       }
7486 /* checking if the table exists */
7487     xtable = gaiaDoubleQuotedSql (table);
7488     xcolumn = gaiaDoubleQuotedSql (column);
7489     sql_statement = sqlite3_mprintf ("SELECT name FROM sqlite_master "
7490 				     "WHERE type = 'table' AND Upper(name) = Upper(%Q)",
7491 				     table);
7492     free (xtable);
7493     free (xcolumn);
7494     ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows, &columns,
7495 			     &errMsg);
7496     sqlite3_free (sql_statement);
7497     if (ret != SQLITE_OK)
7498       {
7499 	  spatialite_e ("AddFDOGeometryColumn: \"%s\"\n", errMsg);
7500 	  sqlite3_free (errMsg);
7501 	  return;
7502       }
7503     oktbl = 0;
7504     for (i = 1; i <= rows; i++)
7505 	oktbl = 1;
7506     sqlite3_free_table (results);
7507     if (!oktbl)
7508       {
7509 	  spatialite_e
7510 	      ("AddFDOGeometryColumn() error: table '%s' does not exist\n",
7511 	       table);
7512 	  sqlite3_result_int (context, 0);
7513 	  return;
7514       }
7515 
7516 /*
7517  * the following code has been contributed by Mark Johnson <mj10777@googlemail.com>
7518  * on 2019-01-26
7519 */
7520     sql_statement =
7521 	sqlite3_mprintf
7522 	("SELECT CASE WHEN (Exists(SELECT srid FROM spatial_ref_sys WHERE (auth_srid = %d)) = 0) THEN 0 ELSE 1 END",
7523 	 srid);
7524     ret =
7525 	sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
7526 			    &stmt_sql, NULL);
7527     sqlite3_free (sql_statement);
7528     if (ret != SQLITE_OK)
7529       {
7530 	  sqlite3_result_error (context, sqlite3_errmsg (sqlite), -1);
7531 	  sqlite3_free (errMsg);
7532 	  return;
7533       }
7534     while (sqlite3_step (stmt_sql) == SQLITE_ROW)
7535       {
7536 	  if (sqlite3_column_type (stmt_sql, 0) != SQLITE_NULL)
7537 	    {
7538 		srid_exists = sqlite3_column_int (stmt_sql, 0);
7539 	    }
7540       }
7541     sqlite3_finalize (stmt_sql);
7542     if (srid_exists == 0)
7543       {
7544 	  /* get the EPSG definition for this SRID from our master list */
7545 	  initialize_epsg (srid, &first, &last);
7546 	  if (first == NULL)
7547 	    {
7548 		sql_statement =
7549 		    sqlite3_mprintf
7550 		    ("AddFDOGeometryColumn() error: srid[%d] is not defined in the EPSG inlined dataset",
7551 		     srid);
7552 		sqlite3_result_error (context, sql_statement, -1);
7553 		sqlite3_free (sql_statement);
7554 		return;
7555 	    }
7556 	  /* add the definition for the SRID */
7557 	  sql_statement =
7558 	      sqlite3_mprintf
7559 	      ("INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid,srtext) VALUES (?, ?, ?, ?)");
7560 	  ret =
7561 	      sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
7562 				  &stmt_sql, NULL);
7563 	  if (ret != SQLITE_OK)
7564 	    {
7565 		sqlite3_free (sql_statement);
7566 		sqlite3_result_error (context, sqlite3_errmsg (sqlite), -1);
7567 		/* freeing the EPSG defs list */
7568 		free_epsg (first);
7569 		return;
7570 	    }
7571 	  sqlite3_bind_int (stmt_sql, 1, first->srid);
7572 	  sqlite3_bind_text (stmt_sql, 2, first->auth_name,
7573 			     strlen (first->auth_name), SQLITE_STATIC);
7574 	  sqlite3_bind_int (stmt_sql, 3, first->auth_srid);
7575 	  if (strlen (first->srs_wkt) == 0)
7576 	    {
7577 		sqlite3_bind_text (stmt_sql, 4, "Undefined", 9, SQLITE_STATIC);
7578 	    }
7579 	  else
7580 	    {
7581 		sqlite3_bind_text (stmt_sql, 4, first->srs_wkt,
7582 				   strlen (first->srs_wkt), SQLITE_STATIC);
7583 	    }
7584 	  ret = sqlite3_step (stmt_sql);
7585 	  /* freeing the EPSG defs list */
7586 	  free_epsg (first);
7587 	  if (stmt_sql != NULL)
7588 	    {
7589 		sqlite3_finalize (stmt_sql);
7590 	    }
7591 	  sqlite3_free (sql_statement);
7592 	  if (ret != SQLITE_DONE && ret != SQLITE_ROW)
7593 	    {
7594 		sqlite3_result_error (context, sqlite3_errmsg (sqlite), -1);
7595 		return;
7596 	    }
7597       }
7598     /* The EPSG definition for this SRID exists in spatial_ref_sys */
7599 /* end Mark Johnson 2019-01-26 */
7600 
7601 /* trying to add the column */
7602     xtable = gaiaDoubleQuotedSql (table);
7603     xcolumn = gaiaDoubleQuotedSql (column);
7604     sql_statement = sqlite3_mprintf ("ALTER TABLE \"%s\" "
7605 				     "ADD COLUMN \"%s\" BLOB", xtable, xcolumn);
7606     free (xtable);
7607     free (xcolumn);
7608     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7609     sqlite3_free (sql_statement);
7610     if (ret != SQLITE_OK)
7611 	goto error;
7612 /*ok, inserting into geometry_columns [FDO Spatial Metadata] */
7613     sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
7614 				     "(f_table_name, f_geometry_column, geometry_type, "
7615 				     "coord_dimension, srid, geometry_format) VALUES (%Q, %Q, %d, %d, %d, %Q)",
7616 				     table, column, type, dimension,
7617 				     (srid <= 0) ? -1 : srid, xformat);
7618     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7619     sqlite3_free (sql_statement);
7620     if (ret != SQLITE_OK)
7621 	goto error;
7622     sqlite3_result_int (context, 1);
7623     return;
7624   error:
7625     spatialite_e ("AddFDOGeometryColumn() error: \"%s\"\n", errMsg);
7626     sqlite3_free (errMsg);
7627     sqlite3_result_int (context, 0);
7628     return;
7629 }
7630 
7631 static void
fnct_RecoverFDOGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)7632 fnct_RecoverFDOGeometryColumn (sqlite3_context * context, int argc,
7633 			       sqlite3_value ** argv)
7634 {
7635 /* SQL function:
7636 / RecoverFDOGeometryColumn(table, column, srid, geometry_type , dimension, geometry_format )
7637 /
7638 / checks if an existing TABLE.COLUMN satisfies the required geometric features
7639 / if yes adds it to FDO-styled SpatialMetaData
7640 / returns 1 on success
7641 / 0 on failure
7642 */
7643     const char *table;
7644     const char *column;
7645     const char *format;
7646     char xformat[64];
7647     int type;
7648     int srid = -1;
7649     int dimension = 2;
7650     char *sql_statement;
7651     char *errMsg = NULL;
7652     int ret;
7653     char **results;
7654     int rows;
7655     int columns;
7656     int i;
7657     int ok_tbl;
7658     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7659     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7660     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7661       {
7662 	  spatialite_e
7663 	      ("RecoverFDOGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
7664 	  sqlite3_result_int (context, 0);
7665 	  return;
7666       }
7667     table = (const char *) sqlite3_value_text (argv[0]);
7668     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
7669       {
7670 	  spatialite_e
7671 	      ("RecoverFDOGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
7672 	  sqlite3_result_int (context, 0);
7673 	  return;
7674       }
7675     column = (const char *) sqlite3_value_text (argv[1]);
7676     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
7677       {
7678 	  spatialite_e
7679 	      ("RecoverFDOGeometryColumn() error: argument 3 [SRID] is not of the Integer type\n");
7680 	  sqlite3_result_int (context, 0);
7681 	  return;
7682       }
7683     srid = sqlite3_value_int (argv[2]);
7684     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
7685       {
7686 	  spatialite_e
7687 	      ("RecoverFDOGeometryColumn() error: argument 4 [geometry_type] is not of the Integer type\n");
7688 	  sqlite3_result_int (context, 0);
7689 	  return;
7690       }
7691     type = sqlite3_value_int (argv[3]);
7692     if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
7693       {
7694 	  spatialite_e
7695 	      ("RecoverFDOGeometryColumn() error: argument 5 [dimension] is not of the Integer type\n");
7696 	  sqlite3_result_int (context, 0);
7697 	  return;
7698       }
7699     dimension = sqlite3_value_int (argv[4]);
7700     if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
7701       {
7702 	  spatialite_e
7703 	      ("RecoverFDOGeometryColumn() error: argument 6 [geometry_format] is not of the String type\n");
7704 	  sqlite3_result_int (context, 0);
7705 	  return;
7706       }
7707     format = (const char *) sqlite3_value_text (argv[5]);
7708     if (type ==
7709 	GAIA_POINT
7710 	|| type ==
7711 	GAIA_LINESTRING
7712 	|| type ==
7713 	GAIA_POLYGON
7714 	|| type ==
7715 	GAIA_MULTIPOINT
7716 	|| type ==
7717 	GAIA_MULTILINESTRING
7718 	|| type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
7719 	;
7720     else
7721       {
7722 	  spatialite_e
7723 	      ("RecoverFDOGeometryColumn() error: argument 4 [geometry_type] has an illegal value\n");
7724 	  sqlite3_result_int (context, 0);
7725 	  return;
7726       }
7727     if (dimension < 2 || dimension > 4)
7728       {
7729 	  spatialite_e
7730 	      ("RecoverFDOGeometryColumn() error: argument 5 [dimension] current version only accepts dimension=2,3,4\n");
7731 	  sqlite3_result_int (context, 0);
7732 	  return;
7733       }
7734     if (strcasecmp (format, "WKT") == 0)
7735 	strcpy (xformat, "WKT");
7736     else if (strcasecmp (format, "WKB") == 0)
7737 	strcpy (xformat, "WKB");
7738     else if (strcasecmp (format, "FGF") == 0)
7739 	strcpy (xformat, "FGF");
7740     else if (strcasecmp (format, "SPATIALITE") == 0)
7741 	strcpy (xformat, "SPATIALITE");
7742     else
7743       {
7744 	  spatialite_e
7745 	      ("RecoverFDOGeometryColumn() error: argument 6 [geometry_format] has to be one of: WKT,WKB,FGF\n");
7746 	  sqlite3_result_int (context, 0);
7747 	  return;
7748       }
7749 /* checking if the table exists */
7750     sql_statement = sqlite3_mprintf ("SELECT name FROM sqlite_master "
7751 				     "WHERE type = 'table' AND Upper(name) = Upper(%Q)",
7752 				     table);
7753     ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows, &columns,
7754 			     &errMsg);
7755     sqlite3_free (sql_statement);
7756     if (ret != SQLITE_OK)
7757       {
7758 	  spatialite_e ("RecoverFDOGeometryColumn: \"%s\"\n", errMsg);
7759 	  sqlite3_free (errMsg);
7760 	  return;
7761       }
7762     ok_tbl = 0;
7763     for (i = 1; i <= rows; i++)
7764 	ok_tbl = 1;
7765     sqlite3_free_table (results);
7766     if (!ok_tbl)
7767       {
7768 	  spatialite_e
7769 	      ("RecoverFDOGeometryColumn() error: table '%s' does not exist\n",
7770 	       table);
7771 	  sqlite3_result_int (context, 0);
7772 	  return;
7773       }
7774     if (!recoverFDOGeomColumn
7775 	(sqlite, (const unsigned char *) table,
7776 	 (const unsigned char *) column, type, srid))
7777       {
7778 	  spatialite_e ("RecoverFDOGeometryColumn(): validation failed\n");
7779 	  sqlite3_result_int (context, 0);
7780 	  return;
7781       }
7782     sql_statement = sqlite3_mprintf ("INSERT INTO geometry_columns "
7783 				     "(f_table_name, f_geometry_column, geometry_type, "
7784 				     "coord_dimension, srid, geometry_format) VALUES (%Q, %Q, %d, %d, %d, %Q)",
7785 				     table, column, type, dimension,
7786 				     (srid <= 0) ? -1 : srid, xformat);
7787     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7788     sqlite3_free (sql_statement);
7789     if (ret != SQLITE_OK)
7790 	goto error;
7791     sqlite3_result_int (context, 1);
7792     return;
7793   error:
7794     spatialite_e ("RecoverFDOGeometryColumn() error: \"%s\"\n", errMsg);
7795     sqlite3_free (errMsg);
7796     sqlite3_result_int (context, 0);
7797     return;
7798 }
7799 
7800 static void
fnct_DiscardFDOGeometryColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)7801 fnct_DiscardFDOGeometryColumn (sqlite3_context * context, int argc,
7802 			       sqlite3_value ** argv)
7803 {
7804 /* SQL function:
7805 / DiscardFDOGeometryColumn(table, column)
7806 /
7807 / removes TABLE.COLUMN from the Spatial MetaData
7808 / returns 1 on success
7809 / 0 on failure
7810 */
7811     const unsigned char *table;
7812     const unsigned char *column;
7813     char *sql_statement;
7814     char *errMsg = NULL;
7815     int ret;
7816     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7817     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7818     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7819       {
7820 	  spatialite_e
7821 	      ("DiscardFDOGeometryColumn() error: argument 1 [table_name] is not of the String type\n");
7822 	  sqlite3_result_int (context, 0);
7823 	  return;
7824       }
7825     table = sqlite3_value_text (argv[0]);
7826     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
7827       {
7828 	  spatialite_e
7829 	      ("DiscardFDOGeometryColumn() error: argument 2 [column_name] is not of the String type\n");
7830 	  sqlite3_result_int (context, 0);
7831 	  return;
7832       }
7833     column = sqlite3_value_text (argv[1]);
7834     sql_statement =
7835 	sqlite3_mprintf
7836 	("DELETE FROM geometry_columns WHERE Upper(f_table_name) = "
7837 	 "Upper(%Q) AND Upper(f_geometry_column) = Upper(%Q)", table, column);
7838     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
7839     sqlite3_free (sql_statement);
7840     if (ret != SQLITE_OK)
7841 	goto error;
7842     sqlite3_result_int (context, 1);
7843     return;
7844   error:
7845     spatialite_e ("DiscardFDOGeometryColumn() error: \"%s\"\n", errMsg);
7846     sqlite3_free (errMsg);
7847     sqlite3_result_int (context, 0);
7848     return;
7849 }
7850 
7851 static void
fnct_GetDbObjectScope(sqlite3_context * context,int argc,sqlite3_value ** argv)7852 fnct_GetDbObjectScope (sqlite3_context * context, int argc,
7853 		       sqlite3_value ** argv)
7854 {
7855 /* SQL function:
7856 / GetDbObjectScope(da-prefix, name)
7857 /
7858 / returns the intended scope of some DB Object
7859 / returns a text string
7860 / NULL on invalid arguments
7861 */
7862     const char *db_prefix = NULL;
7863     const char *name;
7864     char *scope;
7865     sqlite3 *sqlite = sqlite3_context_db_handle (context);
7866     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
7867     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
7868 	;
7869     else if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
7870       {
7871 	  sqlite3_result_null (context);
7872 	  return;
7873       }
7874     else
7875 	name = (const char *) sqlite3_value_text (argv[0]);
7876     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
7877       {
7878 	  sqlite3_result_null (context);
7879 	  return;
7880       }
7881     name = (const char *) sqlite3_value_text (argv[1]);
7882     scope = gaiaGetDbObjectScope (sqlite, db_prefix, name);
7883     if (scope == NULL)
7884       {
7885 	  sqlite3_result_null (context);
7886 	  return;
7887       }
7888     sqlite3_result_text (context, scope, strlen (scope), sqlite3_free);
7889 }
7890 
7891 static int
eval_rtree_entry(int ok_geom,double geom_value,int ok_rtree,double rtree_value)7892 eval_rtree_entry (int ok_geom, double geom_value, int ok_rtree,
7893 		  double rtree_value)
7894 {
7895 /* evaluating geom-coord and rtree-coord */
7896     if (!ok_geom && !ok_rtree)
7897 	return 1;
7898     if (ok_geom && ok_rtree)
7899       {
7900 	  float g = (float) geom_value;
7901 	  float r = (float) rtree_value;
7902 	  double tic = fabs (geom_value - r) * 2.0;
7903 	  float diff = g - r;
7904 	  if (diff >= 1.5)
7905 	      return 0;
7906 	  if (diff > tic)
7907 	      return 0;
7908 	  return 1;
7909       }
7910     return 0;
7911 }
7912 
7913 static int
check_spatial_index(sqlite3 * sqlite,const unsigned char * table,const unsigned char * geom)7914 check_spatial_index (sqlite3 * sqlite, const unsigned char *table,
7915 		     const unsigned char *geom)
7916 {
7917 /* attempting to check an R*Tree for consistency */
7918     char *xtable = NULL;
7919     char *xgeom = NULL;
7920     char *idx_name;
7921     char *xidx_name = NULL;
7922     char sql[1024];
7923     char *sql_statement;
7924     int ret;
7925     int is_defined = 0;
7926     sqlite3_stmt *stmt;
7927     sqlite3_int64 count_geom = 0;
7928     sqlite3_int64 count_rtree = 0;
7929     sqlite3_int64 count_rev = 0;
7930     double g_xmin = DBL_MAX;
7931     double g_ymin = DBL_MAX;
7932     double g_xmax = 0.0 - DBL_MAX;
7933     double g_ymax = 0.0 - DBL_MAX;
7934     int ok_g_xmin;
7935     int ok_g_ymin;
7936     int ok_g_xmax;
7937     int ok_g_ymax;
7938     double i_xmin = DBL_MAX;
7939     double i_ymin = DBL_MAX;
7940     double i_xmax = 0.0 - DBL_MAX;
7941     double i_ymax = 0.0 - DBL_MAX;
7942     int ok_i_xmin;
7943     int ok_i_ymin;
7944     int ok_i_xmax;
7945     int ok_i_ymax;
7946     int rowid_column = 0;
7947     int without_rowid = 0;
7948 
7949     if (is_without_rowid_table (sqlite, (char *) table))
7950       {
7951 	  spatialite_e
7952 	      ("check_spatial_index: table \"%s\" is WITHOUT ROWID\n", table);
7953 	  without_rowid = 1;
7954 	  goto err_label;
7955       }
7956 
7957 /* checking if the R*Tree Spatial Index is defined */
7958     sql_statement = sqlite3_mprintf ("SELECT Count(*) FROM geometry_columns "
7959 				     "WHERE Upper(f_table_name) = Upper(%Q) "
7960 				     "AND Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 1",
7961 				     table, geom);
7962     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
7963 			      &stmt, NULL);
7964     sqlite3_free (sql_statement);
7965     if (ret != SQLITE_OK)
7966       {
7967 	  spatialite_e ("CheckSpatialIndex SQL error: %s\n",
7968 			sqlite3_errmsg (sqlite));
7969 	  goto err_label;
7970       }
7971     while (1)
7972       {
7973 	  ret = sqlite3_step (stmt);
7974 	  if (ret == SQLITE_DONE)
7975 	      break;
7976 	  if (ret == SQLITE_ROW)
7977 	      is_defined = sqlite3_column_int (stmt, 0);
7978 	  else
7979 	    {
7980 		spatialite_e ("sqlite3_step() error: %s\n",
7981 			      sqlite3_errmsg (sqlite));
7982 		sqlite3_finalize (stmt);
7983 		goto err_label;
7984 	    }
7985       }
7986     sqlite3_finalize (stmt);
7987     if (!is_defined)
7988 	goto err_label;
7989 
7990     xgeom = gaiaDoubleQuotedSql ((char *) geom);
7991     xtable = gaiaDoubleQuotedSql ((char *) table);
7992     idx_name = sqlite3_mprintf ("idx_%s_%s", table, geom);
7993     xidx_name = gaiaDoubleQuotedSql (idx_name);
7994     sqlite3_free (idx_name);
7995 
7996     if (!validateRowid (sqlite, (const char *) table))
7997       {
7998 	  /* a physical column named "rowid" shadows the real ROWID */
7999 	  rowid_column = 1;
8000 	  goto err_label;
8001       }
8002 
8003 /* counting how many Geometries are set into the main-table */
8004     sql_statement = sqlite3_mprintf ("SELECT Count(*) FROM \"%s\" "
8005 				     "WHERE ST_GeometryType(\"%s\") IS NOT NULL",
8006 				     xtable, xgeom);
8007     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8008 			      &stmt, NULL);
8009     sqlite3_free (sql_statement);
8010     if (ret != SQLITE_OK)
8011       {
8012 	  spatialite_e ("CheckSpatialIndex SQL error: %s\n",
8013 			sqlite3_errmsg (sqlite));
8014 	  goto err_label;
8015       }
8016     while (1)
8017       {
8018 	  ret = sqlite3_step (stmt);
8019 	  if (ret == SQLITE_DONE)
8020 	      break;
8021 	  if (ret == SQLITE_ROW)
8022 	      count_geom = sqlite3_column_int64 (stmt, 0);
8023 	  else
8024 	    {
8025 		spatialite_e ("sqlite3_step() error: %s\n",
8026 			      sqlite3_errmsg (sqlite));
8027 		sqlite3_finalize (stmt);
8028 		goto err_label;
8029 	    }
8030       }
8031     sqlite3_finalize (stmt);
8032 
8033 /* counting how many R*Tree entries are defined */
8034     sql_statement = sqlite3_mprintf ("SELECT Count(*) FROM \"%s\"", xidx_name);
8035     ret =
8036 	sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8037 			    &stmt, NULL);
8038     sqlite3_free (sql_statement);
8039     if (ret != SQLITE_OK)
8040       {
8041 	  spatialite_e ("CheckSpatialIndex SQL error: %s\n",
8042 			sqlite3_errmsg (sqlite));
8043 	  goto err_label;
8044       }
8045     while (1)
8046       {
8047 	  ret = sqlite3_step (stmt);
8048 	  if (ret == SQLITE_DONE)
8049 	      break;
8050 	  if (ret == SQLITE_ROW)
8051 	      count_rtree = sqlite3_column_int64 (stmt, 0);
8052 	  else
8053 	    {
8054 		spatialite_e ("sqlite3_step() error: %s\n",
8055 			      sqlite3_errmsg (sqlite));
8056 		sqlite3_finalize (stmt);
8057 		goto err_label;
8058 	    }
8059       }
8060     sqlite3_finalize (stmt);
8061     if (count_geom != count_rtree)
8062       {
8063 	  /* unexpected count difference */
8064 	  goto mismatching_zero;
8065       }
8066 
8067 /* now we'll check the R*Tree against the corresponding geometry-table */
8068     sql_statement =
8069 	sqlite3_mprintf ("SELECT MbrMinX(g.\"%s\"), MbrMinY(g.\"%s\"), "
8070 			 "MbrMaxX(g.\"%s\"), MbrMaxY(g.\"%s\"), i.xmin, i.ymin, i.xmax, i.ymax\n"
8071 			 "FROM \"%s\" AS i\nLEFT JOIN \"%s\" AS g ON (g.ROWID = i.pkid)",
8072 			 xgeom, xgeom, xgeom, xgeom, xidx_name, xtable);
8073     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8074 			      &stmt, NULL);
8075     sqlite3_free (sql_statement);
8076     if (ret != SQLITE_OK)
8077       {
8078 	  spatialite_e ("CheckSpatialIndex SQL error: %s\n",
8079 			sqlite3_errmsg (sqlite));
8080 	  goto err_label;
8081       }
8082     while (1)
8083       {
8084 	  ret = sqlite3_step (stmt);
8085 	  if (ret == SQLITE_DONE)
8086 	      break;
8087 	  if (ret == SQLITE_ROW)
8088 	    {
8089 		/* checking a row */
8090 		count_rev++;
8091 		ok_g_xmin = 1;
8092 		ok_g_ymin = 1;
8093 		ok_g_xmax = 1;
8094 		ok_g_ymax = 1;
8095 		ok_i_xmin = 1;
8096 		ok_i_ymin = 1;
8097 		ok_i_xmax = 1;
8098 		ok_i_ymax = 1;
8099 		if (sqlite3_column_type (stmt, 0) == SQLITE_NULL)
8100 		    ok_g_xmin = 0;
8101 		else
8102 		    g_xmin = sqlite3_column_double (stmt, 0);
8103 		if (sqlite3_column_type (stmt, 1) == SQLITE_NULL)
8104 		    ok_g_ymin = 0;
8105 		else
8106 		    g_ymin = sqlite3_column_double (stmt, 1);
8107 		if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
8108 		    ok_g_xmax = 0;
8109 		else
8110 		    g_xmax = sqlite3_column_double (stmt, 2);
8111 		if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
8112 		    ok_g_ymax = 0;
8113 		else
8114 		    g_ymax = sqlite3_column_double (stmt, 3);
8115 		if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
8116 		    ok_i_xmin = 0;
8117 		else
8118 		    i_xmin = sqlite3_column_double (stmt, 4);
8119 		if (sqlite3_column_type (stmt, 5) == SQLITE_NULL)
8120 		    ok_i_ymin = 0;
8121 		else
8122 		    i_ymin = sqlite3_column_double (stmt, 5);
8123 		if (sqlite3_column_type (stmt, 6) == SQLITE_NULL)
8124 		    ok_i_xmax = 0;
8125 		else
8126 		    i_xmax = sqlite3_column_double (stmt, 6);
8127 		if (sqlite3_column_type (stmt, 7) == SQLITE_NULL)
8128 		    ok_i_ymax = 0;
8129 		else
8130 		    i_ymax = sqlite3_column_double (stmt, 7);
8131 		if (eval_rtree_entry (ok_g_xmin, g_xmin, ok_i_xmin, i_xmin)
8132 		    == 0)
8133 		    goto mismatching;
8134 		if (eval_rtree_entry (ok_g_ymin, g_ymin, ok_i_ymin, i_ymin)
8135 		    == 0)
8136 		    goto mismatching;
8137 		if (eval_rtree_entry (ok_g_xmax, g_xmax, ok_i_xmax, i_xmax)
8138 		    == 0)
8139 		    goto mismatching;
8140 		if (eval_rtree_entry (ok_g_ymax, g_ymax, ok_i_ymax, i_ymax)
8141 		    == 0)
8142 		    goto mismatching;
8143 	    }
8144 	  else
8145 	    {
8146 		spatialite_e ("sqlite3_step() error: %s\n",
8147 			      sqlite3_errmsg (sqlite));
8148 		sqlite3_finalize (stmt);
8149 		goto err_label;
8150 	    }
8151       }
8152     sqlite3_finalize (stmt);
8153     if (count_geom != count_rev)
8154 	goto mismatching;
8155     strcpy (sql, "Check SpatialIndex: is valid");
8156     updateSpatiaLiteHistory (sqlite, (const char *) table,
8157 			     (const char *) geom, sql);
8158     free (xgeom);
8159     free (xtable);
8160     free (xidx_name);
8161     return 1;
8162   mismatching:
8163     sqlite3_finalize (stmt);
8164     strcpy (sql, "Check SpatialIndex: INCONSISTENCIES detected");
8165     updateSpatiaLiteHistory (sqlite, (const char *) table,
8166 			     (const char *) geom, sql);
8167   mismatching_zero:
8168     if (xgeom)
8169 	free (xgeom);
8170     if (xtable)
8171 	free (xtable);
8172     if (xidx_name)
8173 	free (xidx_name);
8174     return 0;
8175   err_label:
8176     if (xgeom)
8177 	free (xgeom);
8178     if (xtable)
8179 	free (xtable);
8180     if (xidx_name)
8181 	free (xidx_name);
8182     if (rowid_column)
8183 	return -2;
8184     if (without_rowid)
8185 	return -3;
8186     return -1;
8187 }
8188 
8189 static int
check_any_spatial_index(sqlite3 * sqlite)8190 check_any_spatial_index (sqlite3 * sqlite)
8191 {
8192 /* attempting to check any defined R*Tree for consistency */
8193     const unsigned char *table;
8194     const unsigned char *column;
8195     int status;
8196     char sql[1024];
8197     int ret;
8198     int invalid_rtree = 0;
8199     sqlite3_stmt *stmt;
8200 
8201 /* retrieving any defined R*Tree */
8202     strcpy (sql,
8203 	    "SELECT f_table_name, f_geometry_column FROM geometry_columns ");
8204     strcat (sql, "WHERE spatial_index_enabled = 1");
8205     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
8206     if (ret != SQLITE_OK)
8207       {
8208 	  spatialite_e ("CheckSpatialIndex SQL error: %s\n",
8209 			sqlite3_errmsg (sqlite));
8210 	  return -1;
8211       }
8212     while (1)
8213       {
8214 	  ret = sqlite3_step (stmt);
8215 	  if (ret == SQLITE_DONE)
8216 	      break;
8217 	  if (ret == SQLITE_ROW)
8218 	    {
8219 		/* checking a single R*Tree */
8220 		table = sqlite3_column_text (stmt, 0);
8221 		column = sqlite3_column_text (stmt, 1);
8222 		status = check_spatial_index (sqlite, table, column);
8223 		if (status < 0)
8224 		  {
8225 		      sqlite3_finalize (stmt);
8226 		      return status;
8227 		  }
8228 		if (status == 0)
8229 		    invalid_rtree = 1;
8230 	    }
8231 	  else
8232 	    {
8233 		spatialite_e ("sqlite3_step() error: %s\n",
8234 			      sqlite3_errmsg (sqlite));
8235 		sqlite3_finalize (stmt);
8236 		return -1;
8237 	    }
8238       }
8239     sqlite3_finalize (stmt);
8240     if (invalid_rtree)
8241 	return 0;
8242     return 1;
8243 }
8244 
8245 static void
fnct_CheckSpatialIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)8246 fnct_CheckSpatialIndex (sqlite3_context * context, int argc,
8247 			sqlite3_value ** argv)
8248 {
8249 /* SQL function:
8250 / CheckSpatialIndex()
8251 / CheckSpatialIndex(table, column)
8252 /
8253 / checks a SpatialIndex for consistency, returning:
8254 / 1 - the R*Tree is fully consistent
8255 / 0 - the R*Tree is inconsistent
8256 / -1 if any physical "ROWID" column exist shadowing the real ROWID
8257 / NULL on failure
8258 */
8259     const unsigned char *table;
8260     const unsigned char *column;
8261     int status;
8262     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8263     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8264     if (argc == 0)
8265       {
8266 	  /* no arguments: we must check any defined R*Tree */
8267 	  status = check_any_spatial_index (sqlite);
8268 	  if (status < 0)
8269 	    {
8270 		if (status == -2)
8271 		    sqlite3_result_int (context, -1);
8272 		else
8273 		    sqlite3_result_null (context);
8274 	    }
8275 	  else if (status > 0)
8276 	      sqlite3_result_int (context, 1);
8277 	  else
8278 	      sqlite3_result_int (context, 0);
8279 	  return;
8280       }
8281 
8282     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
8283       {
8284 	  spatialite_e
8285 	      ("CheckSpatialIndex() error: argument 1 [table_name] is not of the String type\n");
8286 	  sqlite3_result_null (context);
8287 	  return;
8288       }
8289     table = sqlite3_value_text (argv[0]);
8290     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
8291       {
8292 	  spatialite_e
8293 	      ("CheckSpatialIndex() error: argument 2 [column_name] is not of the String type\n");
8294 	  sqlite3_result_null (context);
8295 	  return;
8296       }
8297     column = sqlite3_value_text (argv[1]);
8298     status = check_spatial_index (sqlite, table, column);
8299     if (status == -2)
8300 	sqlite3_result_int (context, -1);
8301     else if (status == -3)
8302 	sqlite3_result_int (context, -1);
8303     else if (status < 0)
8304 	sqlite3_result_null (context);
8305     else if (status > 0)
8306 	sqlite3_result_int (context, 1);
8307     else
8308 	sqlite3_result_int (context, 0);
8309 }
8310 
8311 static gaiaGeomCollPtr
get_gpkg_spatial_index_extent(sqlite3 * sqlite,const char * db_prefix,const char * table,const char * geom)8312 get_gpkg_spatial_index_extent (sqlite3 * sqlite, const char *db_prefix,
8313 			       const char *table, const char *geom)
8314 {
8315 /* attempting to get the Spatial Index Full Extent   GeoPackage */
8316     char *xprefix = NULL;
8317     char *idx_name;
8318     char *sql_statement;
8319     int ret;
8320     int srid = -1234567890;
8321     sqlite3_stmt *stmt;
8322     gaiaGeomCollPtr envelope;
8323 
8324 /* checking if the R*Tree Spatial Index is defined - Spatial Table */
8325     xprefix = gaiaDoubleQuotedSql (db_prefix);
8326     sql_statement =
8327 	sqlite3_mprintf ("SELECT srs_id FROM \"%s\".gpkg_geometry_columns "
8328 			 "WHERE Upper(table_name) = Upper(%Q) "
8329 			 "AND Upper(column_name) = Upper(%Q)", xprefix, table,
8330 			 geom);
8331     free (xprefix);
8332     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8333 			      &stmt, NULL);
8334     sqlite3_free (sql_statement);
8335     if (ret != SQLITE_OK)
8336       {
8337 	  spatialite_e ("GetSpatialIndexExtent SQL error: %s\n",
8338 			sqlite3_errmsg (sqlite));
8339 	  goto err;
8340       }
8341     while (1)
8342       {
8343 	  ret = sqlite3_step (stmt);
8344 	  if (ret == SQLITE_DONE)
8345 	      break;
8346 	  if (ret == SQLITE_ROW)
8347 	      srid = sqlite3_column_int (stmt, 0);
8348 	  else
8349 	    {
8350 		spatialite_e ("sqlite3_step() error: %s\n",
8351 			      sqlite3_errmsg (sqlite));
8352 		sqlite3_finalize (stmt);
8353 		goto err;
8354 	    }
8355       }
8356     sqlite3_finalize (stmt);
8357     if (srid == -1234567890)
8358 	goto err;
8359 
8360     idx_name = sqlite3_mprintf ("rtree_%s_%s", table, geom);
8361     envelope = gaiaGetGpkgRTreeFullExtent (sqlite, db_prefix, idx_name, srid);
8362     sqlite3_free (idx_name);
8363     return envelope;
8364 
8365   err:
8366     return NULL;
8367 }
8368 
8369 static gaiaGeomCollPtr
get_spatial_index_extent(sqlite3 * sqlite,const char * db_prefix,const char * table,const char * geom)8370 get_spatial_index_extent (sqlite3 * sqlite, const char *db_prefix,
8371 			  const char *table, const char *geom)
8372 {
8373 /* attempting to get the Spatial Index Full Extent - SpatiaLite */
8374     char *xprefix = NULL;
8375     char *idx_name;
8376     char *sql_statement;
8377     int ret;
8378     int srid = -1234567890;
8379     sqlite3_stmt *stmt;
8380     gaiaGeomCollPtr envelope;
8381 
8382 /* checking if the R*Tree Spatial Index is defined - Spatial Table */
8383     xprefix = gaiaDoubleQuotedSql (db_prefix);
8384     sql_statement = sqlite3_mprintf ("SELECT srid FROM \"%s\".geometry_columns "
8385 				     "WHERE Upper(f_table_name) = Upper(%Q) "
8386 				     "AND Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 1",
8387 				     xprefix, table, geom);
8388     free (xprefix);
8389     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8390 			      &stmt, NULL);
8391     sqlite3_free (sql_statement);
8392     if (ret != SQLITE_OK)
8393       {
8394 	  spatialite_e ("GetSpatialIndexExtent SQL error: %s\n",
8395 			sqlite3_errmsg (sqlite));
8396 	  goto err;
8397       }
8398     while (1)
8399       {
8400 	  ret = sqlite3_step (stmt);
8401 	  if (ret == SQLITE_DONE)
8402 	      break;
8403 	  if (ret == SQLITE_ROW)
8404 	      srid = sqlite3_column_int (stmt, 0);
8405 	  else
8406 	    {
8407 		spatialite_e ("sqlite3_step() error: %s\n",
8408 			      sqlite3_errmsg (sqlite));
8409 		sqlite3_finalize (stmt);
8410 		goto err;
8411 	    }
8412       }
8413     sqlite3_finalize (stmt);
8414     if (srid != -1234567890)
8415       {
8416 	  idx_name = sqlite3_mprintf ("idx_%s_%s", table, geom);
8417 	  goto done;
8418       }
8419 
8420 /* checking if the R*Tree Spatial Index is defined - Spatial View */
8421     xprefix = gaiaDoubleQuotedSql (db_prefix);
8422     sql_statement =
8423 	sqlite3_mprintf ("SELECT g.f_table_name, g.f_geometry_column, g.srid "
8424 			 "FROM \"%s\".views_geometry_columns AS v "
8425 			 "JOIN geometry_columns AS g ON (Upper(v.f_table_name) = Upper(g.f_table_name) "
8426 			 "AND Upper(v.f_geometry_column) = Upper(g.f_geometry_column) "
8427 			 "AND g.spatial_index_enabled = 1) "
8428 			 "WHERE Upper(view_name) = Upper(%Q) AND Upper(view_geometry) = Upper(%Q)",
8429 			 xprefix, table, geom);
8430     free (xprefix);
8431     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8432 			      &stmt, NULL);
8433     sqlite3_free (sql_statement);
8434     if (ret != SQLITE_OK)
8435       {
8436 	  spatialite_e ("GetSpatialIndexExtent SQL error: %s\n",
8437 			sqlite3_errmsg (sqlite));
8438 	  goto err;
8439       }
8440     while (1)
8441       {
8442 	  ret = sqlite3_step (stmt);
8443 	  if (ret == SQLITE_DONE)
8444 	      break;
8445 	  if (ret == SQLITE_ROW)
8446 	    {
8447 		const char *name = (const char *) sqlite3_column_text (stmt, 0);
8448 		const char *column =
8449 		    (const char *) sqlite3_column_text (stmt, 1);
8450 		idx_name = sqlite3_mprintf ("idx_%s_%s", name, column);
8451 		srid = sqlite3_column_int (stmt, 2);
8452 	    }
8453 	  else
8454 	    {
8455 		spatialite_e ("sqlite3_step() error: %s\n",
8456 			      sqlite3_errmsg (sqlite));
8457 		sqlite3_finalize (stmt);
8458 		goto err;
8459 	    }
8460       }
8461     sqlite3_finalize (stmt);
8462     if (srid == -1234567890)
8463 	goto err;
8464 
8465   done:
8466     envelope = gaiaGetRTreeFullExtent (sqlite, db_prefix, idx_name, srid);
8467     sqlite3_free (idx_name);
8468     return envelope;
8469 
8470   err:
8471     return NULL;
8472 }
8473 
8474 static void
fnct_GetSpatialIndexExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)8475 fnct_GetSpatialIndexExtent (sqlite3_context * context, int argc,
8476 			    sqlite3_value ** argv)
8477 {
8478 /* SQL function:
8479 / GetSpatialIndexExtent(db-prefix, table, column)
8480 /
8481 / evaluates a SpatialIndex, returning:
8482 / - a Rectangle Geometry corresponding to the Spatial Index Full Extent
8483 / - NULL on invalid arguments or on not existing Spatial Index
8484 */
8485     const char *db_prefix = "main";
8486     const char *table;
8487     const char *column;
8488     gaiaGeomCollPtr envelope;
8489     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8490     int gpkg_mode = 0;
8491     int tiny_point = 0;
8492     int gpkg_layout = 0;
8493     struct splite_internal_cache *cache = sqlite3_user_data (context);
8494     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8495     if (cache != NULL)
8496       {
8497 	  gpkg_mode = cache->gpkg_mode;
8498 	  tiny_point = cache->tinyPointEnabled;
8499       }
8500     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
8501 	;
8502     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
8503 	db_prefix = (const char *) sqlite3_value_text (argv[0]);
8504     else
8505       {
8506 	  spatialite_e
8507 	      ("GetSpatialIndexExtent() error: argument 1 [db-prefix] is not of the String type\n");
8508 	  sqlite3_result_null (context);
8509 	  return;
8510       }
8511     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
8512       {
8513 	  spatialite_e
8514 	      ("GetSpatialIndexExtent() error: argument 2 [table_name] is not of the String type\n");
8515 	  sqlite3_result_null (context);
8516 	  return;
8517       }
8518     table = (const char *) sqlite3_value_text (argv[1]);
8519     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
8520       {
8521 	  spatialite_e
8522 	      ("GetSpatialIndexExtent() error: argument 3 [column_name] is not of the String type\n");
8523 	  sqlite3_result_null (context);
8524 	  return;
8525       }
8526     if (checkSpatialMetaData_ex (sqlite, db_prefix) == 4)
8527 	gpkg_layout = 1;
8528     column = (const char *) sqlite3_value_text (argv[2]);
8529 
8530     if (gpkg_layout)
8531 	envelope =
8532 	    get_gpkg_spatial_index_extent (sqlite, db_prefix, table, column);
8533     else
8534 	envelope = get_spatial_index_extent (sqlite, db_prefix, table, column);
8535     if (envelope != NULL)
8536       {
8537 	  /* builds the BLOB geometry to be returned */
8538 	  unsigned char *blob;
8539 	  int len;
8540 	  gaiaToSpatiaLiteBlobWkbEx2 (envelope, &blob, &len, gpkg_mode,
8541 				      tiny_point);
8542 	  sqlite3_result_blob (context, blob, len, free);
8543 	  gaiaFreeGeomColl (envelope);
8544       }
8545     else
8546 	sqlite3_result_null (context);
8547 }
8548 
8549 static int
recover_spatial_index(sqlite3 * sqlite,const unsigned char * table,const unsigned char * geom)8550 recover_spatial_index (sqlite3 * sqlite, const unsigned char *table,
8551 		       const unsigned char *geom)
8552 {
8553 /* attempting to rebuild an R*Tree */
8554     char *sql_statement;
8555     char *errMsg = NULL;
8556     int ret;
8557     char *idx_name;
8558     char *xidx_name;
8559     char sql[1024];
8560     int is_defined = 0;
8561     sqlite3_stmt *stmt;
8562     int status;
8563 
8564 /* checking if the R*Tree Spatial Index is defined */
8565     sql_statement = sqlite3_mprintf ("SELECT Count(*) FROM geometry_columns "
8566 				     "WHERE Upper(f_table_name) = Upper(%Q) "
8567 				     "AND Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 1",
8568 				     table, geom);
8569     ret = sqlite3_prepare_v2 (sqlite, sql_statement, strlen (sql_statement),
8570 			      &stmt, NULL);
8571     sqlite3_free (sql_statement);
8572     if (ret != SQLITE_OK)
8573       {
8574 	  spatialite_e ("RecoverSpatialIndex SQL error: %s\n",
8575 			sqlite3_errmsg (sqlite));
8576 	  return -1;
8577       }
8578     while (1)
8579       {
8580 	  ret = sqlite3_step (stmt);
8581 	  if (ret == SQLITE_DONE)
8582 	      break;
8583 	  if (ret == SQLITE_ROW)
8584 	      is_defined = sqlite3_column_int (stmt, 0);
8585 	  else
8586 	    {
8587 		spatialite_e ("sqlite3_step() error: %s\n",
8588 			      sqlite3_errmsg (sqlite));
8589 		sqlite3_finalize (stmt);
8590 		return -1;
8591 	    }
8592       }
8593     sqlite3_finalize (stmt);
8594     if (!is_defined)
8595 	return -1;
8596 
8597 /* erasing the R*Tree table */
8598     idx_name = sqlite3_mprintf ("idx_%s_%s", table, geom);
8599     xidx_name = gaiaDoubleQuotedSql (idx_name);
8600     sqlite3_free (idx_name);
8601     sql_statement = sqlite3_mprintf ("DELETE FROM \"%s\"", xidx_name);
8602     free (xidx_name);
8603     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
8604     sqlite3_free (sql_statement);
8605     if (ret != SQLITE_OK)
8606 	goto error;
8607 /* populating the R*Tree table from scratch */
8608     status = buildSpatialIndexEx (sqlite, table, (const char *) geom);
8609     if (status == 0)
8610 	;
8611     else
8612       {
8613 	  if (status == -2)
8614 	    {
8615 		strcpy (sql,
8616 			"SpatialIndex: a physical column named ROWID shadows the real ROWID");
8617 		updateSpatiaLiteHistory (sqlite, (const char *) table,
8618 					 (const char *) geom, sql);
8619 	    }
8620 	  else
8621 	    {
8622 		strcpy (sql, "SpatialIndex: unable to rebuild the R*Tree");
8623 		updateSpatiaLiteHistory (sqlite, (const char *) table,
8624 					 (const char *) geom, sql);
8625 	    }
8626 	  return status;
8627       }
8628     strcpy (sql, "SpatialIndex: successfully recovered");
8629     updateSpatiaLiteHistory (sqlite, (const char *) table,
8630 			     (const char *) geom, sql);
8631     return 1;
8632   error:
8633     spatialite_e ("RecoverSpatialIndex() error: \"%s\"\n", errMsg);
8634     sqlite3_free (errMsg);
8635     return 0;
8636 }
8637 
8638 static int
recover_any_spatial_index(sqlite3 * sqlite,int no_check)8639 recover_any_spatial_index (sqlite3 * sqlite, int no_check)
8640 {
8641 /* attempting to rebuild any defined R*Tree */
8642     const unsigned char *table;
8643     const unsigned char *column;
8644     int status;
8645     char sql[1024];
8646     int ret;
8647     int to_be_fixed;
8648     int rowid_column = 0;
8649     int without_rowid = 0;
8650     sqlite3_stmt *stmt;
8651 
8652 /* retrieving any defined R*Tree */
8653     strcpy (sql,
8654 	    "SELECT f_table_name, f_geometry_column FROM geometry_columns ");
8655     strcat (sql, "WHERE spatial_index_enabled = 1");
8656     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
8657     if (ret != SQLITE_OK)
8658       {
8659 	  spatialite_e ("RecoverSpatialIndex SQL error: %s\n",
8660 			sqlite3_errmsg (sqlite));
8661 	  return -1;
8662       }
8663     while (1)
8664       {
8665 	  ret = sqlite3_step (stmt);
8666 	  if (ret == SQLITE_DONE)
8667 	      break;
8668 	  if (ret == SQLITE_ROW)
8669 	    {
8670 		/* checking a single R*Tree */
8671 		table = sqlite3_column_text (stmt, 0);
8672 		column = sqlite3_column_text (stmt, 1);
8673 		to_be_fixed = 1;
8674 		if (!no_check)
8675 		  {
8676 		      status = check_spatial_index (sqlite, table, column);
8677 		      if (status < 0)
8678 			{
8679 			    /* some unexpected error occurred */
8680 			    if (status == -2)
8681 				rowid_column = 1;
8682 			    if (status == -3)
8683 				without_rowid = 1;
8684 			    goto fatal_error;
8685 			}
8686 		      else if (status > 0)
8687 			{
8688 			    /* the Spatial Index is already valid */
8689 			    to_be_fixed = 0;
8690 			}
8691 		  }
8692 		if (to_be_fixed)
8693 		  {
8694 		      /* rebuilding the Spatial Index */
8695 		      status = recover_spatial_index (sqlite, table, column);
8696 		      if (status < 0)
8697 			{
8698 			    /* some unexpected error occurred */
8699 			    if (status == -2)
8700 				rowid_column = 1;
8701 			    if (status == -3)
8702 				without_rowid = 1;
8703 			    goto fatal_error;
8704 			}
8705 		      else if (status == 0)
8706 			  goto error;
8707 		  }
8708 	    }
8709 	  else
8710 	    {
8711 		spatialite_e ("sqlite3_step() error: %s\n",
8712 			      sqlite3_errmsg (sqlite));
8713 		sqlite3_finalize (stmt);
8714 		return -1;
8715 	    }
8716       }
8717     sqlite3_finalize (stmt);
8718     return 1;
8719   error:
8720     sqlite3_finalize (stmt);
8721     return 0;
8722   fatal_error:
8723     sqlite3_finalize (stmt);
8724     if (rowid_column)
8725 	return -2;
8726     if (without_rowid)
8727 	return -3;
8728     return -1;
8729 }
8730 
8731 static void
fnct_RecoverSpatialIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)8732 fnct_RecoverSpatialIndex (sqlite3_context * context, int argc,
8733 			  sqlite3_value ** argv)
8734 {
8735 /* SQL function:
8736 / RecoverSpatialIndex()
8737 / RecoverSpatialIndex(no_check)
8738 / RecoverSpatialIndex(table, column)
8739 / RecoverSpatialIndex(table, column, no_check)
8740 /
8741 / attempts to rebuild a SpatialIndex, returning:
8742 / 1 - on success
8743 / 0 - on failure
8744 / -1 if any physical "ROWID" column exist shadowing the real ROWID
8745 /    or if the table was created WITHOUT ROWID
8746 / NULL if any syntax error is detected
8747 */
8748     const unsigned char *table;
8749     const unsigned char *column;
8750     int no_check = 0;
8751     int status;
8752     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8753     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8754     if (argc <= 1)
8755       {
8756 	  /* no arguments: we must rebuild any defined R*Tree */
8757 	  if (argc == 1)
8758 	    {
8759 		if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
8760 		    no_check = sqlite3_value_int (argv[0]);
8761 		else
8762 		  {
8763 		      spatialite_e
8764 			  ("RecoverSpatialIndex() error: argument 1 [no_check] is not of the Integer type\n");
8765 		      sqlite3_result_null (context);
8766 		      return;
8767 		  }
8768 	    }
8769 	  status = recover_any_spatial_index (sqlite, no_check);
8770 	  if (status < 0)
8771 	    {
8772 		if (status == -2)
8773 		    sqlite3_result_int (context, -1);
8774 		else if (status == -3)
8775 		    sqlite3_result_int (context, -1);
8776 		else
8777 		    sqlite3_result_null (context);
8778 	    }
8779 	  else if (status > 0)
8780 	      sqlite3_result_int (context, 1);
8781 	  else
8782 	      sqlite3_result_int (context, 0);
8783 	  return;
8784       }
8785 
8786     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
8787       {
8788 	  spatialite_e
8789 	      ("RecoverSpatialIndex() error: argument 1 [table_name] is not of the String type\n");
8790 	  sqlite3_result_null (context);
8791 	  return;
8792       }
8793     table = sqlite3_value_text (argv[0]);
8794     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
8795       {
8796 	  spatialite_e
8797 	      ("RecoverSpatialIndex() error: argument 2 [column_name] is not of the String type\n");
8798 	  sqlite3_result_null (context);
8799 	  return;
8800       }
8801     column = sqlite3_value_text (argv[1]);
8802     if (argc == 3)
8803       {
8804 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
8805 	      no_check = sqlite3_value_int (argv[2]);
8806 	  else
8807 	    {
8808 		spatialite_e
8809 		    ("RecoverSpatialIndex() error: argument 2 [no_check] is not of the Integer type\n");
8810 		sqlite3_result_null (context);
8811 		return;
8812 	    }
8813       }
8814     if (!no_check)
8815       {
8816 	  /* checking the current SpatialIndex validity */
8817 	  status = check_spatial_index (sqlite, table, column);
8818 	  if (status < 0)
8819 	    {
8820 		/* some unexpected error occurred */
8821 		if (status == -2 || status == -3)
8822 		    sqlite3_result_int (context, -1);
8823 		else
8824 		    sqlite3_result_null (context);
8825 		return;
8826 	    }
8827 	  else if (status > 0)
8828 	    {
8829 		/* the Spatial Index is already valid */
8830 		sqlite3_result_int (context, 1);
8831 		return;
8832 	    }
8833       }
8834 /* rebuilding the Spatial Index */
8835     status = recover_spatial_index (sqlite, table, column);
8836     if (status == -2)
8837 	sqlite3_result_int (context, -1);
8838     else if (status < 0)
8839 	sqlite3_result_null (context);
8840     else if (status > 0)
8841 	sqlite3_result_int (context, 1);
8842     else
8843 	sqlite3_result_int (context, 0);
8844 }
8845 
8846 static void
fnct_CheckShadowedRowid(sqlite3_context * context,int argc,sqlite3_value ** argv)8847 fnct_CheckShadowedRowid (sqlite3_context * context, int argc,
8848 			 sqlite3_value ** argv)
8849 {
8850 /* SQL function:
8851 / CheckShadowedRowid(table)
8852 /
8853 / checks if some table has a "rowid" physical column shadowing the real ROWID
8854 / 1 - yes, the ROWID is shadowed
8855 / 0 - no, the ROWID isn't shadowed
8856 / NULL on failure (e.g. not existing table)
8857 */
8858     const unsigned char *table;
8859     int ret;
8860     char sql[128];
8861     sqlite3_stmt *stmt;
8862     int exists = 0;
8863     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8864     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8865 
8866     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
8867       {
8868 	  spatialite_e
8869 	      ("CheckShadowedRowid() error: argument 1 [table_name] is not of the String type\n");
8870 	  sqlite3_result_null (context);
8871 	  return;
8872       }
8873     table = sqlite3_value_text (argv[0]);
8874 
8875 /* checking if the table exists */
8876     strcpy (sql,
8877 	    "SELECT name FROM sqlite_master WHERE type = 'table' AND Lower(name) = Lower(?)");
8878     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
8879     if (ret != SQLITE_OK)
8880       {
8881 	  spatialite_e ("CheckShadowedRowid: \"%s\"\n",
8882 			sqlite3_errmsg (sqlite));
8883 	  sqlite3_result_null (context);
8884 	  return;
8885       }
8886     sqlite3_reset (stmt);
8887     sqlite3_clear_bindings (stmt);
8888     sqlite3_bind_text (stmt, 1, (const char *) table,
8889 		       strlen ((const char *) table), SQLITE_STATIC);
8890     while (1)
8891       {
8892 	  /* scrolling the result set rows */
8893 	  ret = sqlite3_step (stmt);
8894 	  if (ret == SQLITE_DONE)
8895 	      break;		/* end of result set */
8896 	  if (ret == SQLITE_ROW)
8897 	      exists = 1;
8898       }
8899     sqlite3_finalize (stmt);
8900     if (!exists)
8901 	sqlite3_result_null (context);
8902     else
8903       {
8904 	  if (!validateRowid (sqlite, (const char *) table))
8905 	      sqlite3_result_int (context, 1);
8906 	  else
8907 	      sqlite3_result_int (context, 0);
8908       }
8909 }
8910 
8911 static void
fnct_CheckWithoutRowid(sqlite3_context * context,int argc,sqlite3_value ** argv)8912 fnct_CheckWithoutRowid (sqlite3_context * context, int argc,
8913 			sqlite3_value ** argv)
8914 {
8915 /* SQL function:
8916 / CheckWithoutRowid(table)
8917 /
8918 / checks if some table has been created WITHOUT ROWID
8919 / 1 - yes, the table is WITHOUT ROWID
8920 / 0 - no, the ROWID should be supported
8921 / NULL on failure (e.g. not existing table)
8922 */
8923     const unsigned char *table;
8924     int ret;
8925     char sql[128];
8926     sqlite3_stmt *stmt;
8927     int exists = 0;
8928     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8929     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8930 
8931     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
8932       {
8933 	  spatialite_e
8934 	      ("CheckWithoutRowid() error: argument 1 [table_name] is not of the String type\n");
8935 	  sqlite3_result_null (context);
8936 	  return;
8937       }
8938     table = sqlite3_value_text (argv[0]);
8939 
8940 /* checking if the table exists */
8941     strcpy (sql,
8942 	    "SELECT name FROM sqlite_master WHERE type = 'table' AND Lower(name) = Lower(?)");
8943     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
8944     if (ret != SQLITE_OK)
8945       {
8946 	  spatialite_e ("CheckWithoutRowid: \"%s\"\n", sqlite3_errmsg (sqlite));
8947 	  sqlite3_result_null (context);
8948 	  return;
8949       }
8950     sqlite3_reset (stmt);
8951     sqlite3_clear_bindings (stmt);
8952     sqlite3_bind_text (stmt, 1, (const char *) table,
8953 		       strlen ((const char *) table), SQLITE_STATIC);
8954     while (1)
8955       {
8956 	  /* scrolling the result set rows */
8957 	  ret = sqlite3_step (stmt);
8958 	  if (ret == SQLITE_DONE)
8959 	      break;		/* end of result set */
8960 	  if (ret == SQLITE_ROW)
8961 	      exists = 1;
8962       }
8963     sqlite3_finalize (stmt);
8964     if (!exists)
8965 	sqlite3_result_null (context);
8966     else
8967       {
8968 	  if (is_without_rowid_table (sqlite, (const char *) table))
8969 	      sqlite3_result_int (context, 1);
8970 	  else
8971 	      sqlite3_result_int (context, 0);
8972       }
8973 }
8974 
8975 static void
fnct_CreateTemporarySpatialIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)8976 fnct_CreateTemporarySpatialIndex (sqlite3_context * context, int argc,
8977 				  sqlite3_value ** argv)
8978 {
8979 /* SQL function:
8980 / CreateTemporarySpatialIndex(db_prefix, table, column )
8981 /
8982 / creates a SpatialIndex based on Column and Table
8983 / returns 1 on success
8984 / 0 on failure
8985 */
8986     const char *db_prefix;
8987     const char *table;
8988     const char *column;
8989     char *sql_statement;
8990     char *prefix;
8991     char *errMsg = NULL;
8992     int ret;
8993     sqlite3 *sqlite = sqlite3_context_db_handle (context);
8994     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
8995     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
8996       {
8997 	  spatialite_e
8998 	      ("CreateTemporarySpatialIndex() error: argument 1 [db-prefix] is not of the String type\n");
8999 	  sqlite3_result_int (context, 0);
9000 	  return;
9001       }
9002     db_prefix = (const char *) sqlite3_value_text (argv[0]);
9003     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9004       {
9005 	  spatialite_e
9006 	      ("CreateTemporarySpatialIndex() error: argument 2 [table_name] is not of the String type\n");
9007 	  sqlite3_result_int (context, 0);
9008 	  return;
9009       }
9010     table = (const char *) sqlite3_value_text (argv[1]);
9011     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
9012       {
9013 	  spatialite_e
9014 	      ("CreateTemporarySpatialIndex() error: argument 3 [column_name] is not of the String type\n");
9015 	  sqlite3_result_int (context, 0);
9016 	  return;
9017       }
9018     column = (const char *) sqlite3_value_text (argv[2]);
9019     if (is_without_rowid_table_attached (sqlite, db_prefix, table))
9020       {
9021 	  spatialite_e
9022 	      ("CreateTemporarySpatialIndex() error: table '%s' is WITHOUT ROWID\n",
9023 	       table);
9024 	  sqlite3_result_int (context, -1);
9025 	  return;
9026       }
9027 /* checking if the Attached Database is actually based on :memory: */
9028     if (!is_attached_memory (sqlite, db_prefix))
9029       {
9030 	  spatialite_e
9031 	      ("CreateTemporarySpatialIndex\n() error: Database '%s' does not exists or is not a Temporary one\n",
9032 	       db_prefix);
9033 	  sqlite3_result_int (context, 0);
9034 	  return;
9035       }
9036     if (!validateTemporaryRowid (sqlite, db_prefix, table))
9037       {
9038 	  spatialite_e
9039 	      ("CreateTemporarySpatialIndex() error: a physical column named ROWID shadows the real ROWID\n");
9040 	  sqlite3_result_int (context, -1);
9041 	  return;
9042       }
9043     prefix = gaiaDoubleQuotedSql (db_prefix);
9044     sql_statement =
9045 	sqlite3_mprintf
9046 	("UPDATE \"%s\".geometry_columns SET spatial_index_enabled = 1 "
9047 	 "WHERE Upper(f_table_name) = Upper(%Q) AND "
9048 	 "Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 0",
9049 	 prefix, table, column);
9050     free (prefix);
9051     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
9052     sqlite3_free (sql_statement);
9053     if (ret != SQLITE_OK)
9054 	goto error;
9055     if (sqlite3_changes (sqlite) == 0)
9056       {
9057 	  spatialite_e
9058 	      ("CreateTemporarySpatialIndex() error: either \"%s\".\"%s\" isn't a Geometry column or a SpatialIndex is already defined\n",
9059 	       table, column);
9060 	  sqlite3_result_int (context, 0);
9061 	  return;
9062       }
9063     updateTemporaryGeometryTriggers (sqlite, db_prefix, table, column);
9064     sqlite3_result_int (context, 1);
9065     return;
9066   error:
9067     spatialite_e ("CreateTemporarySpatialIndex() error: \"%s\"\n", errMsg);
9068     sqlite3_free (errMsg);
9069     sqlite3_result_int (context, 0);
9070     return;
9071 }
9072 
9073 static void
fnct_CreateSpatialIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)9074 fnct_CreateSpatialIndex (sqlite3_context * context, int argc,
9075 			 sqlite3_value ** argv)
9076 {
9077 /* SQL function:
9078 / CreateSpatialIndex(table, column )
9079 /
9080 / creates a SpatialIndex based on Column and Table
9081 / returns 1 on success
9082 / 0 on failure
9083 */
9084     const char *table;
9085     const char *column;
9086     char *sql_statement;
9087     char sql[1024];
9088     char *errMsg = NULL;
9089     int ret;
9090     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9091     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9092     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9093       {
9094 	  spatialite_e
9095 	      ("CreateSpatialIndex() error: argument 1 [table_name] is not of the String type\n");
9096 	  sqlite3_result_int (context, 0);
9097 	  return;
9098       }
9099     table = (const char *) sqlite3_value_text (argv[0]);
9100     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9101       {
9102 	  spatialite_e
9103 	      ("CreateSpatialIndex() error: argument 2 [column_name] is not of the String type\n");
9104 	  sqlite3_result_int (context, 0);
9105 	  return;
9106       }
9107     column = (const char *) sqlite3_value_text (argv[1]);
9108     if (is_without_rowid_table (sqlite, table))
9109       {
9110 	  spatialite_e
9111 	      ("CreateSpatialIndex() error: table '%s' is WITHOUT ROWID\n",
9112 	       table);
9113 	  sqlite3_result_int (context, -1);
9114 	  return;
9115       }
9116     if (!validateRowid (sqlite, table))
9117       {
9118 	  spatialite_e
9119 	      ("CreateSpatialIndex() error: a physical column named ROWID shadows the real ROWID\n");
9120 	  sqlite3_result_int (context, -1);
9121 	  return;
9122       }
9123     sql_statement =
9124 	sqlite3_mprintf
9125 	("UPDATE geometry_columns SET spatial_index_enabled = 1 "
9126 	 "WHERE Upper(f_table_name) = Upper(%Q) AND "
9127 	 "Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 0",
9128 	 table, column);
9129     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
9130     sqlite3_free (sql_statement);
9131     if (ret != SQLITE_OK)
9132 	goto error;
9133     if (sqlite3_changes (sqlite) == 0)
9134       {
9135 	  spatialite_e
9136 	      ("CreateSpatialIndex() error: either \"%s\".\"%s\" isn't a Geometry column or a SpatialIndex is already defined\n",
9137 	       table, column);
9138 	  sqlite3_result_int (context, 0);
9139 	  return;
9140       }
9141     updateGeometryTriggers (sqlite, table, column);
9142     sqlite3_result_int (context, 1);
9143     strcpy (sql, "R*Tree Spatial Index successfully created");
9144     updateSpatiaLiteHistory (sqlite, table, column, sql);
9145     return;
9146   error:
9147     spatialite_e ("CreateSpatialIndex() error: \"%s\"\n", errMsg);
9148     sqlite3_free (errMsg);
9149     sqlite3_result_int (context, 0);
9150     return;
9151 }
9152 
9153 static void
fnct_CreateMbrCache(sqlite3_context * context,int argc,sqlite3_value ** argv)9154 fnct_CreateMbrCache (sqlite3_context * context, int argc, sqlite3_value ** argv)
9155 {
9156 /* SQL function:
9157 / CreateMbrCache(table, column )
9158 /
9159 / creates an MBR Cache based on Column and Table
9160 / returns 1 on success
9161 / 0 on failure
9162 */
9163     const char *table;
9164     const char *column;
9165     char *sql_statement;
9166     char sql[1024];
9167     char *errMsg = NULL;
9168     int ret;
9169     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9170     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9171     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9172       {
9173 	  spatialite_e
9174 	      ("CreateMbrCache() error: argument 1 [table_name] is not of the String type\n");
9175 	  sqlite3_result_int (context, 0);
9176 	  return;
9177       }
9178     table = (const char *) sqlite3_value_text (argv[0]);
9179     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9180       {
9181 	  spatialite_e
9182 	      ("CreateMbrCache() error: argument 2 [column_name] is not of the String type\n");
9183 	  sqlite3_result_int (context, 0);
9184 	  return;
9185       }
9186     column = (const char *) sqlite3_value_text (argv[1]);
9187     sql_statement =
9188 	sqlite3_mprintf
9189 	("UPDATE geometry_columns SET spatial_index_enabled = 2 "
9190 	 "WHERE Upper(f_table_name) = Upper(%Q) "
9191 	 "AND Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled = 0",
9192 	 table, column);
9193     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
9194     sqlite3_free (sql_statement);
9195     if (ret != SQLITE_OK)
9196 	goto error;
9197     if (sqlite3_changes (sqlite) == 0)
9198       {
9199 	  spatialite_e
9200 	      ("CreateMbrCache() error: either \"%s\".\"%s\" isn't a Geometry column or a SpatialIndex is already defined\n",
9201 	       table, column);
9202 	  sqlite3_result_int (context, 0);
9203 	  return;
9204       }
9205     updateGeometryTriggers (sqlite, table, column);
9206     sqlite3_result_int (context, 1);
9207     strcpy (sql, "MbrCache successfully created");
9208     updateSpatiaLiteHistory (sqlite, table, column, sql);
9209     return;
9210   error:
9211     spatialite_e ("CreateMbrCache() error: \"%s\"\n", errMsg);
9212     sqlite3_free (errMsg);
9213     sqlite3_result_int (context, 0);
9214     return;
9215 }
9216 
9217 static void
fnct_DisableSpatialIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)9218 fnct_DisableSpatialIndex (sqlite3_context * context, int argc,
9219 			  sqlite3_value ** argv)
9220 {
9221 /* SQL function:
9222 / DisableSpatialIndex(table, column )
9223 /
9224 / disables a SpatialIndex based on Column and Table
9225 / returns 1 on success
9226 / 0 on failure
9227 */
9228     const char *table;
9229     const char *column;
9230     char sql[1024];
9231     char *sql_statement;
9232     char *errMsg = NULL;
9233     int ret;
9234     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9235     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9236     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9237       {
9238 	  spatialite_e
9239 	      ("DisableSpatialIndex() error: argument 1 [table_name] is not of the String type\n");
9240 	  sqlite3_result_int (context, 0);
9241 	  return;
9242       }
9243     table = (const char *) sqlite3_value_text (argv[0]);
9244     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9245       {
9246 	  spatialite_e
9247 	      ("DisableSpatialIndex() error: argument 2 [column_name] is not of the String type\n");
9248 	  sqlite3_result_int (context, 0);
9249 	  return;
9250       }
9251     column = (const char *) sqlite3_value_text (argv[1]);
9252 
9253     sql_statement =
9254 	sqlite3_mprintf
9255 	("UPDATE geometry_columns SET spatial_index_enabled = 0 "
9256 	 "WHERE Upper(f_table_name) = Upper(%Q) AND "
9257 	 "Upper(f_geometry_column) = Upper(%Q) AND spatial_index_enabled <> 0",
9258 	 table, column);
9259     ret = sqlite3_exec (sqlite, sql_statement, NULL, NULL, &errMsg);
9260     sqlite3_free (sql_statement);
9261     if (ret != SQLITE_OK)
9262 	goto error;
9263     if (sqlite3_changes (sqlite) == 0)
9264       {
9265 	  spatialite_e
9266 	      ("DisableSpatialIndex() error: either \"%s\".\"%s\" isn't a Geometry column or no SpatialIndex is defined\n",
9267 	       table, column);
9268 	  sqlite3_result_int (context, 0);
9269 	  return;
9270       }
9271     updateGeometryTriggers (sqlite, table, column);
9272     sqlite3_result_int (context, 1);
9273     strcpy (sql, "SpatialIndex successfully disabled");
9274     updateSpatiaLiteHistory (sqlite, table, column, sql);
9275     return;
9276   error:
9277     spatialite_e ("DisableSpatialIndex() error: \"%s\"\n", errMsg);
9278     sqlite3_free (errMsg);
9279     sqlite3_result_int (context, 0);
9280     return;
9281 }
9282 
9283 static void
fnct_RebuildGeometryTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)9284 fnct_RebuildGeometryTriggers (sqlite3_context * context, int argc,
9285 			      sqlite3_value ** argv)
9286 {
9287 /* SQL function:
9288 / RebuildGeometryTriggers(table, column )
9289 /
9290 / rebuilds Geometry Triggers (constraints)  based on Column and Table
9291 / returns 1 on success
9292 / 0 on failure
9293 */
9294     const char *table;
9295     const char *column;
9296     char *sql_statement;
9297     char *errMsg = NULL;
9298     int ret;
9299     char **results;
9300     int rows;
9301     int columns;
9302     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9303     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9304     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9305       {
9306 	  spatialite_e
9307 	      ("RebuildGeometryTriggers() error: argument 1 [table_name] is not of the String type\n");
9308 	  sqlite3_result_int (context, 0);
9309 	  return;
9310       }
9311     table = (const char *) sqlite3_value_text (argv[0]);
9312     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9313       {
9314 	  spatialite_e
9315 	      ("RebuildGeometryTriggers() error: argument 2 [column_name] is not of the String type\n");
9316 	  sqlite3_result_int (context, 0);
9317 	  return;
9318       }
9319     column = (const char *) sqlite3_value_text (argv[1]);
9320     sql_statement =
9321 	sqlite3_mprintf ("SELECT f_table_name FROM geometry_columns "
9322 			 "WHERE Upper(f_table_name) = Upper(%Q) AND Upper(f_geometry_column) = Upper (%Q)",
9323 			 table, column);
9324     ret = sqlite3_get_table (sqlite, sql_statement, &results, &rows, &columns,
9325 			     NULL);
9326     sqlite3_free (sql_statement);
9327     if (ret != SQLITE_OK)
9328 	goto error;
9329     sqlite3_free_table (results);
9330     if (rows <= 0)
9331       {
9332 	  spatialite_e
9333 	      ("RebuildGeometryTriggers() error: \"%s\".\"%s\" isn't a Geometry column\n",
9334 	       table, column);
9335 	  sqlite3_result_int (context, 0);
9336 	  return;
9337       }
9338     updateGeometryTriggers (sqlite, table, column);
9339     sqlite3_result_int (context, 1);
9340     updateSpatiaLiteHistory (sqlite, table, column,
9341 			     "Geometry Triggers successfully rebuilt");
9342     return;
9343   error:
9344     spatialite_e ("RebuildGeometryTriggers() error: \"%s\"\n", errMsg);
9345     sqlite3_free (errMsg);
9346     sqlite3_result_int (context, 0);
9347     return;
9348 }
9349 
9350 static void
fnct_UpdateLayerStatistics(sqlite3_context * context,int argc,sqlite3_value ** argv)9351 fnct_UpdateLayerStatistics (sqlite3_context * context, int argc,
9352 			    sqlite3_value ** argv)
9353 {
9354 /* SQL function:
9355 / UpdateLayerStatistics(table, column )
9356 /
9357 / Updates LAYER_STATISTICS [based on Column and Table]
9358 / returns 1 on success
9359 / 0 on failure
9360 */
9361     const char *sql;
9362     const char *table = NULL;
9363     const char *column = NULL;
9364     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9365     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9366     if (argc >= 1)
9367       {
9368 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9369 	    {
9370 		spatialite_e
9371 		    ("UpdateLayerStatistics() error: argument 1 [table_name] is not of the String type\n");
9372 		sqlite3_result_int (context, 0);
9373 		return;
9374 	    }
9375 	  table = (const char *) sqlite3_value_text (argv[0]);
9376       }
9377     if (argc >= 2)
9378       {
9379 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9380 	    {
9381 		spatialite_e
9382 		    ("UpdateLayerStatistics() error: argument 2 [column_name] is not of the String type\n");
9383 		sqlite3_result_int (context, 0);
9384 		return;
9385 	    }
9386 	  column = (const char *) sqlite3_value_text (argv[1]);
9387       }
9388     if (!update_layer_statistics (sqlite, table, column))
9389 	goto error;
9390     sqlite3_result_int (context, 1);
9391     sql = "UpdateLayerStatistics";
9392     if (table == NULL)
9393 	table = "ALL-TABLES";
9394     if (column == NULL)
9395 	column = "ALL-GEOMETRY-COLUMNS";
9396     updateSpatiaLiteHistory (sqlite, (const char *) table,
9397 			     (const char *) column, sql);
9398     return;
9399   error:
9400     sqlite3_result_int (context, 0);
9401     return;
9402 }
9403 
9404 static void
fnct_UpgradeGeometryTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)9405 fnct_UpgradeGeometryTriggers (sqlite3_context * context, int argc,
9406 			      sqlite3_value ** argv)
9407 {
9408 /* SQL function:
9409 / UpgradeGeometryTriggers(transaction TRUE|FALSE)
9410 /
9411 / Upgrades (reinstalls) all Geometry Triggers - requires a DB > 4.0.0
9412 / returns 1 on success
9413 / 0 on failure (NULL on invalid args)
9414 */
9415     char *errMsg = NULL;
9416     int ret;
9417     int transaction = 0;
9418     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9419     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9420 
9421     if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
9422       {
9423 	  spatialite_e
9424 	      ("UpgradeGeometryTriggers() error: argument 1 [TRANSACTION] is not of the Integer type\n");
9425 	  sqlite3_result_int (context, 0);
9426 	  return;
9427       }
9428     if (checkSpatialMetaData (sqlite) < 3)
9429       {
9430 	  spatialite_e
9431 	      ("UpgradeGeometryTriggers() error: invalid DB Layout (< v.4.0.0)\n");
9432 	  sqlite3_result_int (context, 0);
9433 	  return;
9434       }
9435     transaction = sqlite3_value_int (argv[0]);
9436     if (transaction)
9437       {
9438 	  /* starting a Transaction */
9439 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
9440 	  if (ret != SQLITE_OK)
9441 	      goto error;
9442       }
9443     if (!upgradeGeometryTriggers (sqlite))
9444 	goto error;
9445     if (transaction)
9446       {
9447 	  /* committing the still pending Transaction */
9448 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
9449 	  if (ret != SQLITE_OK)
9450 	      goto error;
9451       }
9452     updateSpatiaLiteHistory (sqlite, "ALL-TABLES", NULL,
9453 			     "Upgraded Geometry Triggers");
9454     sqlite3_result_int (context, 1);
9455     return;
9456 
9457   error:
9458     if (transaction)
9459       {
9460 	  /* performing a Rollback */
9461 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
9462 	  if (ret != SQLITE_OK)
9463 	      sqlite3_free (errMsg);
9464       }
9465     sqlite3_result_int (context, 0);
9466     return;
9467 }
9468 
9469 static void
fnct_GetLayerExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)9470 fnct_GetLayerExtent (sqlite3_context * context, int argc, sqlite3_value ** argv)
9471 {
9472 /* SQL function:
9473 / GetLayerExtent(table)
9474 / GetLayerExtent(table, column )
9475 / GetLayerExtent(table, column, pessimistic )
9476 /
9477 / Return a Geometry (Envelope) corresponding to the full layer
9478 / extent [eventually updating the supporting statistics
9479 / NULL on failure
9480 */
9481     const char *table = NULL;
9482     const char *column = NULL;
9483     int pessimistic = 0;
9484     int len;
9485     unsigned char *p_result = NULL;
9486     gaiaGeomCollPtr geom;
9487     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9488     int gpkg_mode = 0;
9489     int tiny_point = 0;
9490     struct splite_internal_cache *cache = sqlite3_user_data (context);
9491     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9492     if (cache != NULL)
9493       {
9494 	  gpkg_mode = cache->gpkg_mode;
9495 	  tiny_point = cache->tinyPointEnabled;
9496       }
9497     if (argc >= 1)
9498       {
9499 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9500 	    {
9501 		spatialite_e
9502 		    ("GetLayerExtent() error: argument 1 [table_name] is not of the String type\n");
9503 		sqlite3_result_null (context);
9504 		return;
9505 	    }
9506 	  table = (const char *) sqlite3_value_text (argv[0]);
9507       }
9508     if (argc >= 2)
9509       {
9510 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9511 	    {
9512 		spatialite_e
9513 		    ("GetLayerExtent() error: argument 2 [column_name] is not of the String type\n");
9514 		sqlite3_result_null (context);
9515 		return;
9516 	    }
9517 	  column = (const char *) sqlite3_value_text (argv[1]);
9518       }
9519     if (argc >= 3)
9520       {
9521 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
9522 	    {
9523 		spatialite_e
9524 		    ("GetLayerExtent() error: argument 3 [OPTIMISTIC/PESSIMISTIC] is not of the Integer type\n");
9525 		sqlite3_result_null (context);
9526 		return;
9527 	    }
9528 	  pessimistic = sqlite3_value_int (argv[2]);
9529       }
9530     geom = gaiaGetLayerExtent (sqlite, table, column, pessimistic);
9531     if (!geom)
9532 	goto error;
9533 /* builds the BLOB geometry to be returned */
9534     gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode, tiny_point);
9535     sqlite3_result_blob (context, p_result, len, free);
9536     gaiaFreeGeomColl (geom);
9537     return;
9538   error:
9539     sqlite3_result_null (context);
9540     return;
9541 }
9542 
9543 static void
fnct_InvalidateLayerStatistics(sqlite3_context * context,int argc,sqlite3_value ** argv)9544 fnct_InvalidateLayerStatistics (sqlite3_context * context, int argc,
9545 				sqlite3_value ** argv)
9546 {
9547 /* SQL function:
9548 / InvalidateLayerStatistics(void)
9549 / InvalidateLayerStatistics(table)
9550 / InvalidateLayerStatistics(table, column )
9551 /
9552 / Immediately and unconditionally invalidates Layer Statistics
9553 / returns 1 on success
9554 / 0 on failure
9555 */
9556     const char *sql;
9557     const char *table = NULL;
9558     const char *column = NULL;
9559     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9560     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9561     if (argc >= 1)
9562       {
9563 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9564 	    {
9565 		spatialite_e
9566 		    ("InvalidateLayerStatistics() error: argument 1 [table_name] is not of the String type\n");
9567 		sqlite3_result_int (context, 0);
9568 		return;
9569 	    }
9570 	  table = (const char *) sqlite3_value_text (argv[0]);
9571       }
9572     if (argc >= 2)
9573       {
9574 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
9575 	    {
9576 		spatialite_e
9577 		    ("InvalidateLayerStatistics() error: argument 2 [column_name] is not of the String type\n");
9578 		sqlite3_result_int (context, 0);
9579 		return;
9580 	    }
9581 	  column = (const char *) sqlite3_value_text (argv[1]);
9582       }
9583     if (!gaiaStatisticsInvalidate (sqlite, table, column))
9584 	goto error;
9585     sqlite3_result_int (context, 1);
9586     sql = "InvalidateLayerStatistics";
9587     if (table == NULL)
9588 	table = "ALL-TABLES";
9589     if (column == NULL)
9590 	column = "ALL-GEOMETRY-COLUMNS";
9591     updateSpatiaLiteHistory (sqlite, (const char *) table,
9592 			     (const char *) column, sql);
9593     return;
9594   error:
9595     sqlite3_result_int (context, 0);
9596     return;
9597 }
9598 
9599 static void
fnct_CreateRasterCoveragesTable(sqlite3_context * context,int argc,sqlite3_value ** argv)9600 fnct_CreateRasterCoveragesTable (sqlite3_context * context, int argc,
9601 				 sqlite3_value ** argv)
9602 {
9603 /* SQL function:
9604 / CreateRasterCoveragesTable()
9605 /
9606 / creates the main RasterCoverages table
9607 / returns 1 on success
9608 / 0 on failure
9609 */
9610     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9611     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9612 
9613     if (!createRasterCoveragesTable (sqlite))
9614 	goto error;
9615     updateSpatiaLiteHistory (sqlite, "*** Raster Coverages ***", NULL,
9616 			     "Main table successfully created");
9617     sqlite3_result_int (context, 1);
9618     return;
9619 
9620   error:
9621     sqlite3_result_int (context, 0);
9622     return;
9623 }
9624 
9625 static void
fnct_ReCreateRasterCoveragesTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)9626 fnct_ReCreateRasterCoveragesTriggers (sqlite3_context * context, int argc,
9627 				      sqlite3_value ** argv)
9628 {
9629 /* SQL function:
9630 / ReCreateRasterCoveragesTriggers()
9631 /
9632 / (re)creates the RasterCoverages triggers
9633 / returns 1 on success
9634 / 0 on failure
9635 */
9636     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9637     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9638 
9639     if (!reCreateRasterCoveragesTriggers (sqlite))
9640 	goto error;
9641     updateSpatiaLiteHistory (sqlite, "*** Raster Coverages ***", NULL,
9642 			     "Triggers successfully (re)created");
9643     sqlite3_result_int (context, 1);
9644     return;
9645 
9646   error:
9647     sqlite3_result_int (context, 0);
9648     return;
9649 }
9650 
9651 static void
fnct_CreateVectorCoveragesTables(sqlite3_context * context,int argc,sqlite3_value ** argv)9652 fnct_CreateVectorCoveragesTables (sqlite3_context * context, int argc,
9653 				  sqlite3_value ** argv)
9654 {
9655 /* SQL function:
9656 / CreateVectorCoveragesTables()
9657 /
9658 / creates the main VectorCoverages table
9659 / returns 1 on success
9660 / 0 on failure
9661 */
9662     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9663     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9664 
9665     if (!createVectorCoveragesTable (sqlite))
9666 	goto error;
9667     updateSpatiaLiteHistory (sqlite, "*** Vector Coverages ***", NULL,
9668 			     "Main table successfully created");
9669     sqlite3_result_int (context, 1);
9670     return;
9671 
9672   error:
9673     sqlite3_result_int (context, 0);
9674     return;
9675 }
9676 
9677 static void
fnct_ReCreateVectorCoveragesTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)9678 fnct_ReCreateVectorCoveragesTriggers (sqlite3_context * context, int argc,
9679 				      sqlite3_value ** argv)
9680 {
9681 /* SQL function:
9682 / ReCreateVectorCoveragesTriggers()
9683 /
9684 / (re)creates the VectorCoverages triggers
9685 / returns 1 on success
9686 / 0 on failure
9687 */
9688     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9689     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9690 
9691     if (!reCreateVectorCoveragesTriggers (sqlite))
9692 	goto error;
9693     updateSpatiaLiteHistory (sqlite, "*** Vector Coverages ***", NULL,
9694 			     "Triggers successfully (re)created");
9695     sqlite3_result_int (context, 1);
9696     return;
9697 
9698   error:
9699     sqlite3_result_int (context, 0);
9700     return;
9701 }
9702 
9703 static void
fnct_CreateWMSTables(sqlite3_context * context,int argc,sqlite3_value ** argv)9704 fnct_CreateWMSTables (sqlite3_context * context, int argc,
9705 		      sqlite3_value ** argv)
9706 {
9707 /* SQL function:
9708 / WMS_CreateTables()
9709 /
9710 / creates the WMS support tables
9711 / returns 1 on success
9712 / 0 on failure
9713 */
9714     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9715     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9716 
9717     if (!createWMSTables (sqlite))
9718 	goto error;
9719     updateSpatiaLiteHistory (sqlite, "*** WMS ***", NULL,
9720 			     "Support tables successfully created");
9721     sqlite3_result_int (context, 1);
9722     return;
9723 
9724   error:
9725     sqlite3_result_int (context, 0);
9726     return;
9727 }
9728 
9729 static void
fnct_RegisterWMSGetCapabilities(sqlite3_context * context,int argc,sqlite3_value ** argv)9730 fnct_RegisterWMSGetCapabilities (sqlite3_context * context, int argc,
9731 				 sqlite3_value ** argv)
9732 {
9733 /* SQL function:
9734 / WMS_RegisterGetCapabilities(Text url)
9735 /   or
9736 / WMS_RegisterGetCapabilities(Text url, Text title,
9737 /                        Text abstract)
9738 /
9739 / inserts a WMS GetCapabilities
9740 / returns 1 on success
9741 / 0 on failure, -1 on invalid arguments
9742 */
9743     int ret;
9744     const char *url;
9745     const char *title = NULL;
9746     const char *abstract = NULL;
9747     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9748     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9749     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9750       {
9751 	  sqlite3_result_int (context, -1);
9752 	  return;
9753       }
9754     url = (const char *) sqlite3_value_text (argv[0]);
9755     if (argc >= 3)
9756       {
9757 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT
9758 	      || sqlite3_value_type (argv[2]) != SQLITE_TEXT)
9759 	    {
9760 		sqlite3_result_int (context, -1);
9761 		return;
9762 	    }
9763 	  title = (const char *) sqlite3_value_text (argv[1]);
9764 	  abstract = (const char *) sqlite3_value_text (argv[2]);
9765       }
9766     ret = register_wms_getcapabilities (sqlite, url, title, abstract);
9767     sqlite3_result_int (context, ret);
9768 }
9769 
9770 static void
fnct_UnregisterWMSGetCapabilities(sqlite3_context * context,int argc,sqlite3_value ** argv)9771 fnct_UnregisterWMSGetCapabilities (sqlite3_context * context, int argc,
9772 				   sqlite3_value ** argv)
9773 {
9774 /* SQL function:
9775 / WMS_UnRegisterGetCapabilities(Text url)
9776 /
9777 / deletes a WMS GetCapabilities (and all related children)
9778 / returns 1 on success
9779 / 0 on failure, -1 on invalid arguments
9780 */
9781     int ret;
9782     const char *url;
9783     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9784     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9785     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
9786       {
9787 	  sqlite3_result_int (context, -1);
9788 	  return;
9789       }
9790     url = (const char *) sqlite3_value_text (argv[0]);
9791     ret = unregister_wms_getcapabilities (sqlite, url);
9792     sqlite3_result_int (context, ret);
9793 }
9794 
9795 static void
fnct_SetWMSGetCapabilitiesInfos(sqlite3_context * context,int argc,sqlite3_value ** argv)9796 fnct_SetWMSGetCapabilitiesInfos (sqlite3_context * context, int argc,
9797 				 sqlite3_value ** argv)
9798 {
9799 /* SQL function:
9800 / WMS_SetGetCapabilitiesInfos(Text url, Text title,
9801 /                        Text abstract)
9802 /
9803 / updates the descriptive infos supporting a WMS GetCapabilities
9804 / returns 1 on success
9805 / 0 on failure, -1 on invalid arguments
9806 */
9807     int ret;
9808     const char *url;
9809     const char *title = NULL;
9810     const char *abstract = NULL;
9811     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9812     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
9813     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
9814 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
9815 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
9816       {
9817 	  sqlite3_result_int (context, -1);
9818 	  return;
9819       }
9820     url = (const char *) sqlite3_value_text (argv[0]);
9821     title = (const char *) sqlite3_value_text (argv[1]);
9822     abstract = (const char *) sqlite3_value_text (argv[2]);
9823     ret = set_wms_getcapabilities_infos (sqlite, url, title, abstract);
9824     sqlite3_result_int (context, ret);
9825 }
9826 
9827 static int
validate_wms_bgcolor(const char * bgcolor)9828 validate_wms_bgcolor (const char *bgcolor)
9829 {
9830 /* testing for a valid HexRGB color value */
9831     const char *p = bgcolor;
9832     int len = strlen (bgcolor);
9833     if (len != 6)
9834 	return 0;
9835     while (*p != '\0')
9836       {
9837 	  int ok = 0;
9838 	  if (*p >= 'a' && *p <= 'f')
9839 	      ok = 1;
9840 	  if (*p >= 'A' && *p <= 'F')
9841 	      ok = 1;
9842 	  if (*p >= '0' && *p <= '9')
9843 	      ok = 1;
9844 	  if (!ok)
9845 	      return 0;
9846 	  p++;
9847       }
9848     return 1;
9849 }
9850 
9851 static void
fnct_RegisterWMSGetMap(sqlite3_context * context,int argc,sqlite3_value ** argv)9852 fnct_RegisterWMSGetMap (sqlite3_context * context, int argc,
9853 			sqlite3_value ** argv)
9854 {
9855 /* SQL function:
9856 / WMS_RegisterGetMap(Text getcapabilitites_url, Text getmap_url,
9857 /                    Text layer_name, Text version, Text ref_sys,
9858 /                    Text image_format, Text style, Int transparent,
9859 /                    Int flip_axes)
9860 /   or
9861 / WMS_RegisterGetMap(Text getcapabilitites_url, Text getmap_url,
9862 /                    Text layer_name, Text version, Text ref_sys,
9863 /                    Text image_format, Text style, Int transparent,
9864 /                    Int flip_axes,  Int tiled, Int cached,
9865 /                    Int tile_width, Int tile_height)
9866 /   or
9867 / WMS_RegisterGetMap(Text getcapabilitites_url, Text getmap_url,
9868 /                    Text layer_name, Text title, Text abstract,
9869 /                    Text version, Text ref_sys, Text image_format,
9870 /                    Text style, Int transparent, Int flip_axes,
9871 /                    Int tiled, Int cached, Int tile_width,
9872 /                    Int tile_height, Text bgcolor, Int is_queryable,
9873 /                    Text getfeatureinfo_url)
9874 /
9875 / inserts a WMS GetMap
9876 / returns 1 on success
9877 / 0 on failure, -1 on invalid arguments
9878 */
9879     int ret;
9880     const char *getcapabilities_url;
9881     const char *getmap_url;
9882     const char *layer_name;
9883     const char *title = NULL;
9884     const char *abstract = NULL;
9885     const char *version;
9886     const char *ref_sys;
9887     const char *image_format;
9888     const char *style;
9889     int transparent;
9890     int flip_axes;
9891     int tiled = 0;
9892     int cached = 0;
9893     int tile_width = 512;
9894     int tile_height = 512;
9895     const char *bgcolor = NULL;
9896     int is_queryable = 0;
9897     const char *getfeatureinfo_url = NULL;
9898     sqlite3 *sqlite = sqlite3_context_db_handle (context);
9899     GAIA_UNUSED ();
9900     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
9901 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
9902 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
9903       {
9904 	  sqlite3_result_int (context, -1);
9905 	  return;
9906       }
9907     getcapabilities_url = (const char *) sqlite3_value_text (argv[0]);
9908     getmap_url = (const char *) sqlite3_value_text (argv[1]);
9909     layer_name = (const char *) sqlite3_value_text (argv[2]);
9910     if (argc == 9 || argc == 13)
9911       {
9912 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT ||
9913 	      sqlite3_value_type (argv[4]) != SQLITE_TEXT ||
9914 	      sqlite3_value_type (argv[5]) != SQLITE_TEXT ||
9915 	      sqlite3_value_type (argv[6]) != SQLITE_TEXT)
9916 	    {
9917 		sqlite3_result_int (context, -1);
9918 		return;
9919 	    }
9920 	  version = (const char *) sqlite3_value_text (argv[3]);
9921 	  ref_sys = (const char *) sqlite3_value_text (argv[4]);
9922 	  image_format = (const char *) sqlite3_value_text (argv[5]);
9923 	  style = (const char *) sqlite3_value_text (argv[6]);
9924 	  if (sqlite3_value_type (argv[7]) != SQLITE_INTEGER ||
9925 	      sqlite3_value_type (argv[8]) != SQLITE_INTEGER)
9926 	    {
9927 		sqlite3_result_int (context, -1);
9928 		return;
9929 	    }
9930 	  transparent = sqlite3_value_int (argv[7]);
9931 	  flip_axes = sqlite3_value_int (argv[8]);
9932       }
9933     if (argc == 13)
9934       {
9935 	  if (sqlite3_value_type (argv[9]) != SQLITE_INTEGER ||
9936 	      sqlite3_value_type (argv[10]) != SQLITE_INTEGER ||
9937 	      sqlite3_value_type (argv[11]) != SQLITE_INTEGER ||
9938 	      sqlite3_value_type (argv[12]) != SQLITE_INTEGER)
9939 	    {
9940 		sqlite3_result_int (context, -1);
9941 		return;
9942 	    }
9943 	  tiled = sqlite3_value_int (argv[9]);
9944 	  cached = sqlite3_value_int (argv[10]);
9945 	  tile_width = sqlite3_value_int (argv[11]);
9946 	  tile_height = sqlite3_value_int (argv[12]);
9947       }
9948     if (argc == 18)
9949       {
9950 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
9951 	      || sqlite3_value_type (argv[1]) != SQLITE_TEXT
9952 	      || sqlite3_value_type (argv[2]) != SQLITE_TEXT
9953 	      || sqlite3_value_type (argv[3]) != SQLITE_TEXT
9954 	      || sqlite3_value_type (argv[4]) != SQLITE_TEXT ||
9955 	      sqlite3_value_type (argv[5]) != SQLITE_TEXT ||
9956 	      sqlite3_value_type (argv[6]) != SQLITE_TEXT ||
9957 	      sqlite3_value_type (argv[7]) != SQLITE_TEXT ||
9958 	      sqlite3_value_type (argv[8]) != SQLITE_TEXT)
9959 	    {
9960 		sqlite3_result_int (context, -1);
9961 		return;
9962 	    }
9963 	  getcapabilities_url = (const char *) sqlite3_value_text (argv[0]);
9964 	  getmap_url = (const char *) sqlite3_value_text (argv[1]);
9965 	  layer_name = (const char *) sqlite3_value_text (argv[2]);
9966 	  title = (const char *) sqlite3_value_text (argv[3]);
9967 	  abstract = (const char *) sqlite3_value_text (argv[4]);
9968 	  version = (const char *) sqlite3_value_text (argv[5]);
9969 	  ref_sys = (const char *) sqlite3_value_text (argv[6]);
9970 	  image_format = (const char *) sqlite3_value_text (argv[7]);
9971 	  style = (const char *) sqlite3_value_text (argv[8]);
9972 	  if (sqlite3_value_type (argv[9]) != SQLITE_INTEGER ||
9973 	      sqlite3_value_type (argv[10]) != SQLITE_INTEGER ||
9974 	      sqlite3_value_type (argv[11]) != SQLITE_INTEGER ||
9975 	      sqlite3_value_type (argv[12]) != SQLITE_INTEGER ||
9976 	      sqlite3_value_type (argv[13]) != SQLITE_INTEGER ||
9977 	      sqlite3_value_type (argv[14]) != SQLITE_INTEGER ||
9978 	      sqlite3_value_type (argv[16]) != SQLITE_INTEGER)
9979 	    {
9980 		sqlite3_result_int (context, -1);
9981 		return;
9982 	    }
9983 	  transparent = sqlite3_value_int (argv[9]);
9984 	  flip_axes = sqlite3_value_int (argv[10]);
9985 	  tiled = sqlite3_value_int (argv[11]);
9986 	  cached = sqlite3_value_int (argv[12]);
9987 	  tile_width = sqlite3_value_int (argv[13]);
9988 	  tile_height = sqlite3_value_int (argv[14]);
9989 	  is_queryable = sqlite3_value_int (argv[16]);
9990 	  if (sqlite3_value_type (argv[15]) == SQLITE_NULL)
9991 	      bgcolor = NULL;
9992 	  else if (sqlite3_value_type (argv[15]) == SQLITE_TEXT)
9993 	    {
9994 		bgcolor = (const char *) sqlite3_value_text (argv[15]);
9995 		if (!validate_wms_bgcolor (bgcolor))
9996 		  {
9997 		      sqlite3_result_int (context, -1);
9998 		      return;
9999 		  }
10000 	    }
10001 	  else
10002 	    {
10003 		sqlite3_result_int (context, -1);
10004 		return;
10005 	    }
10006 	  if (sqlite3_value_type (argv[17]) == SQLITE_NULL)
10007 	      getfeatureinfo_url = NULL;
10008 	  else if (sqlite3_value_type (argv[17]) == SQLITE_TEXT)
10009 	      getfeatureinfo_url = (const char *) sqlite3_value_text (argv[17]);
10010 	  else
10011 	    {
10012 		sqlite3_result_int (context, -1);
10013 		return;
10014 	    }
10015       }
10016     ret =
10017 	register_wms_getmap (sqlite, getcapabilities_url, getmap_url,
10018 			     layer_name, title, abstract, version, ref_sys,
10019 			     image_format, style, transparent, flip_axes,
10020 			     tiled, cached, tile_width, tile_height, bgcolor,
10021 			     is_queryable, getfeatureinfo_url);
10022     sqlite3_result_int (context, ret);
10023 }
10024 
10025 static void
fnct_UnregisterWMSGetMap(sqlite3_context * context,int argc,sqlite3_value ** argv)10026 fnct_UnregisterWMSGetMap (sqlite3_context * context, int argc,
10027 			  sqlite3_value ** argv)
10028 {
10029 /* SQL function:
10030 / WMS_UnRegisterGetMap(Text url, Text layer_name)
10031 /
10032 / deletes a WMS GetMap (and all related children)
10033 / returns 1 on success
10034 / 0 on failure, -1 on invalid arguments
10035 */
10036     int ret;
10037     const char *url;
10038     const char *layer_name;
10039     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10040     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10041     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
10042 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10043       {
10044 	  sqlite3_result_int (context, -1);
10045 	  return;
10046       }
10047     url = (const char *) sqlite3_value_text (argv[0]);
10048     layer_name = (const char *) sqlite3_value_text (argv[1]);
10049     ret = unregister_wms_getmap (sqlite, url, layer_name);
10050     sqlite3_result_int (context, ret);
10051 }
10052 
10053 static void
fnct_SetWMSGetMapInfos(sqlite3_context * context,int argc,sqlite3_value ** argv)10054 fnct_SetWMSGetMapInfos (sqlite3_context * context, int argc,
10055 			sqlite3_value ** argv)
10056 {
10057 /* SQL function:
10058 / WMS_SetGetMapInfos(Text url, Text layer_name, Text title, Text abstract)
10059 /
10060 / updates the descriptive infos supporting a WMS GetMap
10061 / returns 1 on success
10062 / 0 on failure, -1 on invalid arguments
10063 */
10064     int ret;
10065     const char *url;
10066     const char *layer_name;
10067     const char *title;
10068     const char *abstract;
10069     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10070     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10071     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
10072 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
10073 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT
10074 	|| sqlite3_value_type (argv[3]) != SQLITE_TEXT)
10075       {
10076 	  sqlite3_result_int (context, -1);
10077 	  return;
10078       }
10079     url = (const char *) sqlite3_value_text (argv[0]);
10080     layer_name = (const char *) sqlite3_value_text (argv[1]);
10081     title = (const char *) sqlite3_value_text (argv[2]);
10082     abstract = (const char *) sqlite3_value_text (argv[3]);
10083     ret = set_wms_getmap_infos (sqlite, url, layer_name, title, abstract);
10084     sqlite3_result_int (context, ret);
10085 }
10086 
10087 static void
fnct_SetWMSGetMapCopyright(sqlite3_context * context,int argc,sqlite3_value ** argv)10088 fnct_SetWMSGetMapCopyright (sqlite3_context * context, int argc,
10089 			    sqlite3_value ** argv)
10090 {
10091 /* SQL function:
10092 / WMS_SetGetMapCopyright(Text url, Text layer_name, Text copyright)
10093 /    or
10094 / WMS_SetGetMapCopyright(Text url, Text layer_name, Text copyright,
10095 /                        Text license)
10096 /
10097 / updates copyright infos supporting a WMS GetMap
10098 / returns 1 on success
10099 / 0 on failure, -1 on invalid arguments
10100 */
10101     int ret;
10102     const char *url;
10103     const char *layer_name;
10104     const char *copyright = NULL;
10105     const char *license = NULL;
10106     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10107     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10108     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
10109 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10110       {
10111 	  sqlite3_result_int (context, -1);
10112 	  return;
10113       }
10114     url = (const char *) sqlite3_value_text (argv[0]);
10115     layer_name = (const char *) sqlite3_value_text (argv[1]);
10116     if (sqlite3_value_type (argv[2]) == SQLITE_NULL)
10117 	;
10118     else if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
10119 	copyright = (const char *) sqlite3_value_text (argv[2]);
10120     else
10121       {
10122 	  sqlite3_result_int (context, -1);
10123 	  return;
10124       }
10125     if (argc >= 4)
10126       {
10127 	  if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
10128 	      license = (const char *) sqlite3_value_text (argv[3]);
10129 	  else
10130 	    {
10131 		sqlite3_result_int (context, -1);
10132 		return;
10133 	    }
10134       }
10135     ret =
10136 	set_wms_getmap_copyright (sqlite, url, layer_name, copyright, license);
10137     sqlite3_result_int (context, ret);
10138 }
10139 
10140 static void
fnct_SetWMSGetMapOptions(sqlite3_context * context,int argc,sqlite3_value ** argv)10141 fnct_SetWMSGetMapOptions (sqlite3_context * context, int argc,
10142 			  sqlite3_value ** argv)
10143 {
10144 /* SQL function:
10145 / WMS_SetGetMapOptions(Text url, Text layer_name, Int transparent,
10146 /                      Int flip_axes)
10147 /   or
10148 / WMS_SetGetMapOptions(Text url, Text layer_name, Int tiled, Int cached,
10149 /                      Int tile_width, Int tile_height)
10150 /   or
10151 / WMS_SetGetMapOptions(Text url, Text layer_name, Int is_queryable,
10152 /                      Text getfeatureinfo_url)
10153 /   or
10154 / WMS_SetGetMapOptions(Text url, Text layer_name, Text bgcolor)
10155 /
10156 / updates the options supporting a WMS GetMap
10157 / returns 1 on success
10158 / 0 on failure, -1 on invalid arguments
10159 */
10160     int ret;
10161     const char *url;
10162     const char *layer_name;
10163     int transparent;
10164     int flip_axes;
10165     int is_queryable;
10166     int tiled;
10167     int cached;
10168     int tile_width = 512;
10169     int tile_height = 512;
10170     const char *getfeatureinfo_url = NULL;
10171     const char *bgcolor = NULL;
10172     char mode = '\0';
10173     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10174     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10175     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
10176 	sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10177       {
10178 	  sqlite3_result_int (context, -1);
10179 	  return;
10180       }
10181     url = (const char *) sqlite3_value_text (argv[0]);
10182     layer_name = (const char *) sqlite3_value_text (argv[1]);
10183     if (argc == 3)
10184       {
10185 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
10186 	    {
10187 		mode = 'B';
10188 		bgcolor = (const char *) sqlite3_value_text (argv[2]);
10189 		if (!validate_wms_bgcolor (bgcolor))
10190 		  {
10191 		      sqlite3_result_int (context, -1);
10192 		      return;
10193 		  }
10194 	    }
10195 	  else if (sqlite3_value_type (argv[2]) == SQLITE_NULL)
10196 	    {
10197 		mode = 'B';
10198 		bgcolor = NULL;
10199 	    }
10200 	  else
10201 	    {
10202 		sqlite3_result_int (context, -1);
10203 		return;
10204 	    }
10205       }
10206     if (argc == 4)
10207       {
10208 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER
10209 	      && sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
10210 	    {
10211 		mode = 'F';
10212 		transparent = sqlite3_value_int (argv[2]);
10213 		flip_axes = sqlite3_value_int (argv[3]);
10214 	    }
10215 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER
10216 		   && sqlite3_value_type (argv[3]) == SQLITE_TEXT)
10217 	    {
10218 		mode = 'Q';
10219 		is_queryable = sqlite3_value_int (argv[2]);
10220 		getfeatureinfo_url =
10221 		    (const char *) sqlite3_value_text (argv[3]);
10222 	    }
10223 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER
10224 		   && sqlite3_value_type (argv[3]) == SQLITE_NULL)
10225 	    {
10226 		mode = 'Q';
10227 		is_queryable = sqlite3_value_int (argv[2]);
10228 		getfeatureinfo_url = NULL;
10229 	    }
10230 	  else
10231 	    {
10232 		sqlite3_result_int (context, -1);
10233 		return;
10234 	    }
10235       }
10236     if (argc == 6)
10237       {
10238 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER ||
10239 	      sqlite3_value_type (argv[3]) != SQLITE_INTEGER ||
10240 	      sqlite3_value_type (argv[4]) != SQLITE_INTEGER ||
10241 	      sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
10242 	    {
10243 		sqlite3_result_int (context, -1);
10244 		return;
10245 	    }
10246 	  mode = 'T';
10247 	  tiled = sqlite3_value_int (argv[2]);
10248 	  cached = sqlite3_value_int (argv[3]);
10249 	  tile_width = sqlite3_value_int (argv[4]);
10250 	  tile_height = sqlite3_value_int (argv[5]);
10251       }
10252     switch (mode)
10253       {
10254       case 'B':
10255 	  ret = set_wms_getmap_bgcolor (sqlite, url, layer_name, bgcolor);
10256 	  break;
10257       case 'F':
10258 	  ret =
10259 	      set_wms_getmap_options (sqlite, url, layer_name, transparent,
10260 				      flip_axes);
10261 	  break;
10262       case 'Q':
10263 	  ret =
10264 	      set_wms_getmap_queryable (sqlite, url, layer_name, is_queryable,
10265 					getfeatureinfo_url);
10266 	  break;
10267       case 'T':
10268 	  ret =
10269 	      set_wms_getmap_tiled (sqlite, url, layer_name, tiled, cached,
10270 				    tile_width, tile_height);
10271 	  break;
10272       default:
10273 	  ret = -1;
10274       };
10275     sqlite3_result_int (context, ret);
10276 }
10277 
10278 static void
fnct_RegisterWMSSetting(sqlite3_context * context,int argc,sqlite3_value ** argv)10279 fnct_RegisterWMSSetting (sqlite3_context * context, int argc,
10280 			 sqlite3_value ** argv)
10281 {
10282 /* SQL function:
10283 / WMS_RegisterSetting(Text url, Text layer_name, Text key, Text value)
10284 /   or
10285 / WMS_RegisterSetting(Text url, Text layer_name, Text key, Text value,
10286 /                     Int default)
10287 /
10288 / inserts a WMS GetMap Setting
10289 / returns 1 on success
10290 / 0 on failure, -1 on invalid arguments
10291 */
10292     int ret;
10293     const char *url;
10294     const char *layer_name;
10295     const char *key;
10296     const char *value;
10297     int is_default = 0;
10298     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10299     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10300     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10301       {
10302 	  sqlite3_result_int (context, -1);
10303 	  return;
10304       }
10305     url = (const char *) sqlite3_value_text (argv[0]);
10306     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10307       {
10308 	  sqlite3_result_int (context, -1);
10309 	  return;
10310       }
10311     layer_name = (const char *) sqlite3_value_text (argv[1]);
10312     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
10313       {
10314 	  sqlite3_result_int (context, -1);
10315 	  return;
10316       }
10317     key = (const char *) sqlite3_value_text (argv[2]);
10318     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
10319       {
10320 	  sqlite3_result_int (context, -1);
10321 	  return;
10322       }
10323     value = (const char *) sqlite3_value_text (argv[3]);
10324     if (argc >= 5)
10325       {
10326 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
10327 	    {
10328 		sqlite3_result_int (context, -1);
10329 		return;
10330 	    }
10331 	  is_default = sqlite3_value_int (argv[4]);
10332       }
10333     ret =
10334 	register_wms_setting (sqlite, url, layer_name, key, value, is_default);
10335     sqlite3_result_int (context, ret);
10336 }
10337 
10338 static void
fnct_UnregisterWMSSetting(sqlite3_context * context,int argc,sqlite3_value ** argv)10339 fnct_UnregisterWMSSetting (sqlite3_context * context, int argc,
10340 			   sqlite3_value ** argv)
10341 {
10342 /* SQL function:
10343 / WMS_UnRegisterSetting(Text url, Text layer_name, Text key, Text value)
10344 /
10345 / deletes a WMS GetMap Setting
10346 / returns 1 on success
10347 / 0 on failure, -1 on invalid arguments
10348 */
10349     int ret;
10350     const char *url;
10351     const char *layer_name;
10352     const char *key;
10353     const char *value;
10354     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10355     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10356     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10357       {
10358 	  sqlite3_result_int (context, -1);
10359 	  return;
10360       }
10361     url = (const char *) sqlite3_value_text (argv[0]);
10362     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10363       {
10364 	  sqlite3_result_int (context, -1);
10365 	  return;
10366       }
10367     layer_name = (const char *) sqlite3_value_text (argv[1]);
10368     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
10369       {
10370 	  sqlite3_result_int (context, -1);
10371 	  return;
10372       }
10373     key = (const char *) sqlite3_value_text (argv[2]);
10374     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
10375       {
10376 	  sqlite3_result_int (context, -1);
10377 	  return;
10378       }
10379     value = (const char *) sqlite3_value_text (argv[3]);
10380     ret = unregister_wms_setting (sqlite, url, layer_name, key, value);
10381     sqlite3_result_int (context, ret);
10382 }
10383 
10384 static void
fnct_DefaultWMSSetting(sqlite3_context * context,int argc,sqlite3_value ** argv)10385 fnct_DefaultWMSSetting (sqlite3_context * context, int argc,
10386 			sqlite3_value ** argv)
10387 {
10388 /* SQL function:
10389 / WMS_DefaultSetting(Text url, Text layer_name, Text key, Text value)
10390 /
10391 / updates some GetMap default setting
10392 / returns 1 on success
10393 / 0 on failure, -1 on invalid arguments
10394 */
10395     int ret;
10396     const char *url;
10397     const char *layer_name;
10398     const char *key;
10399     const char *value;
10400     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10401     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10402     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
10403 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
10404 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT
10405 	|| sqlite3_value_type (argv[3]) != SQLITE_TEXT)
10406       {
10407 	  sqlite3_result_int (context, -1);
10408 	  return;
10409       }
10410     url = (const char *) sqlite3_value_text (argv[0]);
10411     layer_name = (const char *) sqlite3_value_text (argv[1]);
10412     key = (const char *) sqlite3_value_text (argv[2]);
10413     value = (const char *) sqlite3_value_text (argv[3]);
10414     ret = set_wms_default_setting (sqlite, url, layer_name, key, value);
10415     sqlite3_result_int (context, ret);
10416 }
10417 
10418 static void
fnct_RegisterWMSRefSys(sqlite3_context * context,int argc,sqlite3_value ** argv)10419 fnct_RegisterWMSRefSys (sqlite3_context * context, int argc,
10420 			sqlite3_value ** argv)
10421 {
10422 /* SQL function:
10423 / WMS_RegisterRefSys(Text url, Text layer_name, Text ref_sys, Double minx,
10424 /                    Double miny, Double maxx, Double maxy)
10425 /   or
10426 / WMS_RegisterRefSys(Text url, Text layer_name, Text ref_sys, Double minx,
10427 /                    Double miny, Double maxx, Double maxy, Int default)
10428 /
10429 / inserts a WMS GetMap SRS
10430 / returns 1 on success
10431 / 0 on failure, -1 on invalid arguments
10432 */
10433     int ret;
10434     const char *url;
10435     const char *layer_name;
10436     const char *ref_sys;
10437     double minx;
10438     double miny;
10439     double maxx;
10440     double maxy;
10441     int is_default = 0;
10442     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10443     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10444     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10445       {
10446 	  sqlite3_result_int (context, -1);
10447 	  return;
10448       }
10449     url = (const char *) sqlite3_value_text (argv[0]);
10450     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10451       {
10452 	  sqlite3_result_int (context, -1);
10453 	  return;
10454       }
10455     layer_name = (const char *) sqlite3_value_text (argv[1]);
10456     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
10457       {
10458 	  sqlite3_result_int (context, -1);
10459 	  return;
10460       }
10461     ref_sys = (const char *) sqlite3_value_text (argv[2]);
10462     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
10463       {
10464 	  int val = sqlite3_value_int (argv[3]);
10465 	  minx = val;
10466       }
10467     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
10468 	minx = sqlite3_value_double (argv[3]);
10469     else
10470       {
10471 	  sqlite3_result_int (context, -1);
10472 	  return;
10473       }
10474     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
10475       {
10476 	  int val = sqlite3_value_int (argv[4]);
10477 	  miny = val;
10478       }
10479     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
10480 	miny = sqlite3_value_double (argv[4]);
10481     else
10482       {
10483 	  sqlite3_result_int (context, -1);
10484 	  return;
10485       }
10486     if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
10487       {
10488 	  int val = sqlite3_value_int (argv[5]);
10489 	  maxx = val;
10490       }
10491     else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
10492 	maxx = sqlite3_value_double (argv[5]);
10493     else
10494       {
10495 	  sqlite3_result_int (context, -1);
10496 	  return;
10497       }
10498     if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
10499       {
10500 	  int val = sqlite3_value_int (argv[6]);
10501 	  maxy = val;
10502       }
10503     else if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
10504 	maxy = sqlite3_value_double (argv[6]);
10505     else
10506       {
10507 	  sqlite3_result_int (context, -1);
10508 	  return;
10509       }
10510     if (argc >= 8)
10511       {
10512 	  if (sqlite3_value_type (argv[7]) != SQLITE_INTEGER)
10513 	    {
10514 		sqlite3_result_int (context, -1);
10515 		return;
10516 	    }
10517 	  is_default = sqlite3_value_int (argv[7]);
10518       }
10519     ret =
10520 	register_wms_srs (sqlite, url, layer_name, ref_sys, minx, miny, maxx,
10521 			  maxy, is_default);
10522     sqlite3_result_int (context, ret);
10523 }
10524 
10525 static void
fnct_UnregisterWMSRefSys(sqlite3_context * context,int argc,sqlite3_value ** argv)10526 fnct_UnregisterWMSRefSys (sqlite3_context * context, int argc,
10527 			  sqlite3_value ** argv)
10528 {
10529 /* SQL function:
10530 / WMS_UnRegisterRefSys(Text url, Text layer_name, Text ref_sys)
10531 /
10532 / deletes a WMS GetMap SRS
10533 / returns 1 on success
10534 / 0 on failure, -1 on invalid arguments
10535 */
10536     int ret;
10537     const char *url;
10538     const char *layer_name;
10539     const char *ref_sys;
10540     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10541     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10542     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10543       {
10544 	  sqlite3_result_int (context, -1);
10545 	  return;
10546       }
10547     url = (const char *) sqlite3_value_text (argv[0]);
10548     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10549       {
10550 	  sqlite3_result_int (context, -1);
10551 	  return;
10552       }
10553     layer_name = (const char *) sqlite3_value_text (argv[1]);
10554     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
10555       {
10556 	  sqlite3_result_int (context, -1);
10557 	  return;
10558       }
10559     ref_sys = (const char *) sqlite3_value_text (argv[2]);
10560     ret = unregister_wms_srs (sqlite, url, layer_name, ref_sys);
10561     sqlite3_result_int (context, ret);
10562 }
10563 
10564 static void
fnct_DefaultWMSRefSys(sqlite3_context * context,int argc,sqlite3_value ** argv)10565 fnct_DefaultWMSRefSys (sqlite3_context * context, int argc,
10566 		       sqlite3_value ** argv)
10567 {
10568 /* SQL function:
10569 / WMS_DefaultRefSys(Text url, Text layer_name, Text ref_sys)
10570 /
10571 / updates some GetMap default SRS
10572 / returns 1 on success
10573 / 0 on failure, -1 on invalid arguments
10574 */
10575     int ret;
10576     const char *url;
10577     const char *layer_name;
10578     const char *ref_sys;
10579     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10580     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10581     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
10582 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
10583 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
10584       {
10585 	  sqlite3_result_int (context, -1);
10586 	  return;
10587       }
10588     url = (const char *) sqlite3_value_text (argv[0]);
10589     layer_name = (const char *) sqlite3_value_text (argv[1]);
10590     ref_sys = (const char *) sqlite3_value_text (argv[2]);
10591     ret = set_wms_default_srs (sqlite, url, layer_name, ref_sys);
10592     sqlite3_result_int (context, ret);
10593 }
10594 
10595 static void
fnct_WMSGetMapRequestURL(sqlite3_context * context,int argc,sqlite3_value ** argv)10596 fnct_WMSGetMapRequestURL (sqlite3_context * context, int argc,
10597 			  sqlite3_value ** argv)
10598 {
10599 /* SQL function:
10600 / WMS_GetMapRequestURL(Text getmap_url, Text layer_name, Int width,
10601 /                      Int height, Double minx, Double miny,
10602 /                      Double maxx, Double maxy)
10603 /
10604 / returns a WMS GetMap request URL on success
10605 / NULL on invalid arguments
10606 */
10607     char *url;
10608     const char *getmap_url;
10609     const char *layer_name;
10610     int width;
10611     int height;
10612     double minx;
10613     double miny;
10614     double maxx;
10615     double maxy;
10616     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10617     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10618     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10619       {
10620 	  sqlite3_result_null (context);
10621 	  return;
10622       }
10623     getmap_url = (const char *) sqlite3_value_text (argv[0]);
10624     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10625       {
10626 	  sqlite3_result_null (context);
10627 	  return;
10628       }
10629     layer_name = (const char *) sqlite3_value_text (argv[1]);
10630     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
10631       {
10632 	  sqlite3_result_null (context);
10633 	  return;
10634       }
10635     width = sqlite3_value_int (argv[2]);
10636     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
10637       {
10638 	  sqlite3_result_null (context);
10639 	  return;
10640       }
10641     height = sqlite3_value_int (argv[3]);
10642     if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
10643 	minx = sqlite3_value_double (argv[4]);
10644     else if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
10645       {
10646 	  int val = sqlite3_value_int (argv[4]);
10647 	  minx = val;
10648       }
10649     else
10650       {
10651 	  sqlite3_result_null (context);
10652 	  return;
10653       }
10654     if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
10655 	miny = sqlite3_value_double (argv[5]);
10656     else if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
10657       {
10658 	  int val = sqlite3_value_int (argv[5]);
10659 	  miny = val;
10660       }
10661     else
10662       {
10663 	  sqlite3_result_null (context);
10664 	  return;
10665       }
10666     if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
10667 	maxx = sqlite3_value_double (argv[6]);
10668     else if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
10669       {
10670 	  int val = sqlite3_value_int (argv[6]);
10671 	  maxx = val;
10672       }
10673     else
10674       {
10675 	  sqlite3_result_null (context);
10676 	  return;
10677       }
10678     if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
10679 	maxy = sqlite3_value_double (argv[7]);
10680     else if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
10681       {
10682 	  int val = sqlite3_value_int (argv[7]);
10683 	  maxy = val;
10684       }
10685     else
10686       {
10687 	  sqlite3_result_null (context);
10688 	  return;
10689       }
10690     url =
10691 	wms_getmap_request_url (sqlite, getmap_url, layer_name, width, height,
10692 				minx, miny, maxx, maxy);
10693     if (url == NULL)
10694 	sqlite3_result_null (context);
10695     else
10696 	sqlite3_result_text (context, url, strlen (url), sqlite3_free);
10697 }
10698 
10699 static void
fnct_WMSGetFeatureInfoRequestURL(sqlite3_context * context,int argc,sqlite3_value ** argv)10700 fnct_WMSGetFeatureInfoRequestURL (sqlite3_context * context, int argc,
10701 				  sqlite3_value ** argv)
10702 {
10703 /* SQL function:
10704 / WMS_GetFeatureInfoRequestURL(Text getmap_url, Text layer_name, Int width,
10705 /                              Int height, int x, int y, Double minx,
10706 /                              Double miny, Double maxx, Double maxy)
10707 /   or
10708 / WMS_GetFeatureInfoRequestURL(Text getmap_url, Text layer_name, Int width,
10709 /                              Int height, int x, int y, Double minx,
10710 /                              Double miny, Double maxx, Double maxy,
10711 /                              Int feature_count )
10712 /
10713 / returns a WMS GetFeatureInfo request URL on success
10714 / NULL on invalid arguments
10715 */
10716     char *url;
10717     const char *getmap_url;
10718     const char *layer_name;
10719     int width;
10720     int height;
10721     int x;
10722     int y;
10723     double minx;
10724     double miny;
10725     double maxx;
10726     double maxy;
10727     int feature_count = 1;
10728     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10729     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10730     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10731       {
10732 	  sqlite3_result_null (context);
10733 	  return;
10734       }
10735     getmap_url = (const char *) sqlite3_value_text (argv[0]);
10736     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10737       {
10738 	  sqlite3_result_null (context);
10739 	  return;
10740       }
10741     layer_name = (const char *) sqlite3_value_text (argv[1]);
10742     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
10743       {
10744 	  sqlite3_result_null (context);
10745 	  return;
10746       }
10747     width = sqlite3_value_int (argv[2]);
10748     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
10749       {
10750 	  sqlite3_result_null (context);
10751 	  return;
10752       }
10753     height = sqlite3_value_int (argv[3]);
10754     if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
10755       {
10756 	  sqlite3_result_null (context);
10757 	  return;
10758       }
10759     x = sqlite3_value_int (argv[4]);
10760     if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
10761       {
10762 	  sqlite3_result_null (context);
10763 	  return;
10764       }
10765     y = sqlite3_value_int (argv[5]);
10766     if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
10767 	minx = sqlite3_value_double (argv[6]);
10768     else if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
10769       {
10770 	  int val = sqlite3_value_int (argv[6]);
10771 	  minx = val;
10772       }
10773     else
10774       {
10775 	  sqlite3_result_null (context);
10776 	  return;
10777       }
10778     if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
10779 	miny = sqlite3_value_double (argv[7]);
10780     else if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
10781       {
10782 	  int val = sqlite3_value_int (argv[7]);
10783 	  miny = val;
10784       }
10785     else
10786       {
10787 	  sqlite3_result_null (context);
10788 	  return;
10789       }
10790     if (sqlite3_value_type (argv[8]) == SQLITE_FLOAT)
10791 	maxx = sqlite3_value_double (argv[8]);
10792     else if (sqlite3_value_type (argv[8]) == SQLITE_INTEGER)
10793       {
10794 	  int val = sqlite3_value_int (argv[8]);
10795 	  maxx = val;
10796       }
10797     else
10798       {
10799 	  sqlite3_result_null (context);
10800 	  return;
10801       }
10802     if (sqlite3_value_type (argv[9]) == SQLITE_FLOAT)
10803 	maxy = sqlite3_value_double (argv[9]);
10804     else if (sqlite3_value_type (argv[9]) == SQLITE_INTEGER)
10805       {
10806 	  int val = sqlite3_value_int (argv[9]);
10807 	  maxy = val;
10808       }
10809     else
10810       {
10811 	  sqlite3_result_null (context);
10812 	  return;
10813       }
10814     if (argc >= 11)
10815       {
10816 	  if (sqlite3_value_type (argv[10]) != SQLITE_INTEGER)
10817 	    {
10818 		sqlite3_result_null (context);
10819 		return;
10820 	    }
10821 	  feature_count = sqlite3_value_int (argv[10]);
10822       }
10823     url =
10824 	wms_getfeatureinfo_request_url (sqlite, getmap_url, layer_name, width,
10825 					height, x, y, minx, miny, maxx, maxy,
10826 					feature_count);
10827     if (url == NULL)
10828 	sqlite3_result_null (context);
10829     else
10830 	sqlite3_result_text (context, url, strlen (url), sqlite3_free);
10831 }
10832 
10833 static void
fnct_RegisterDataLicense(sqlite3_context * context,int argc,sqlite3_value ** argv)10834 fnct_RegisterDataLicense (sqlite3_context * context, int argc,
10835 			  sqlite3_value ** argv)
10836 {
10837 /* SQL function:
10838 / RegisterDataLicense(Text license_name)
10839 /    or
10840 / RegisterDataLicense(Text license_name, Text license_url)
10841 /
10842 / inserts a Data License
10843 / returns 1 on success
10844 / 0 on failure, -1 on invalid arguments
10845 */
10846     int ret;
10847     const char *license_name;
10848     const char *url = NULL;
10849     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10850     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10851     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10852       {
10853 	  sqlite3_result_int (context, -1);
10854 	  return;
10855       }
10856     license_name = (const char *) sqlite3_value_text (argv[0]);
10857     if (argc >= 2)
10858       {
10859 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
10860 	      url = (const char *) sqlite3_value_text (argv[1]);
10861 	  else
10862 	    {
10863 		sqlite3_result_int (context, -1);
10864 		return;
10865 	    }
10866       }
10867     ret = register_data_license (sqlite, license_name, url);
10868     sqlite3_result_int (context, ret);
10869 }
10870 
10871 static void
fnct_UnRegisterDataLicense(sqlite3_context * context,int argc,sqlite3_value ** argv)10872 fnct_UnRegisterDataLicense (sqlite3_context * context, int argc,
10873 			    sqlite3_value ** argv)
10874 {
10875 /* SQL function:
10876 / UnRegisterDataLicense(Text license_name)
10877 /
10878 / deletes a Data License
10879 / returns 1 on success
10880 / 0 on failure, -1 on invalid arguments
10881 */
10882     int ret;
10883     const char *license_name;
10884     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10885     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10886     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
10887       {
10888 	  sqlite3_result_int (context, -1);
10889 	  return;
10890       }
10891     license_name = (const char *) sqlite3_value_text (argv[0]);
10892     ret = unregister_data_license (sqlite, license_name);
10893     sqlite3_result_int (context, ret);
10894 }
10895 
10896 static void
fnct_RenameDataLicense(sqlite3_context * context,int argc,sqlite3_value ** argv)10897 fnct_RenameDataLicense (sqlite3_context * context, int argc,
10898 			sqlite3_value ** argv)
10899 {
10900 /* SQL function:
10901 / RenameDataLicense(Text old_name, Text new_name)
10902 /
10903 / renames an existing Data License
10904 / returns 1 on success
10905 / 0 on failure, -1 on invalid arguments
10906 */
10907     int ret;
10908     const char *old_name;
10909     const char *new_name;
10910     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10911     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10912     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
10913 	sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10914       {
10915 	  sqlite3_result_int (context, -1);
10916 	  return;
10917       }
10918     old_name = (const char *) sqlite3_value_text (argv[0]);
10919     new_name = (const char *) sqlite3_value_text (argv[1]);
10920     ret = rename_data_license (sqlite, old_name, new_name);
10921     sqlite3_result_int (context, ret);
10922 }
10923 
10924 static void
fnct_SetDataLicenseUrl(sqlite3_context * context,int argc,sqlite3_value ** argv)10925 fnct_SetDataLicenseUrl (sqlite3_context * context, int argc,
10926 			sqlite3_value ** argv)
10927 {
10928 /* SQL function:
10929 / SetDataLicenseUrl(Text license_name, Text license_url)
10930 /
10931 / updates a Data License URL
10932 / returns 1 on success
10933 / 0 on failure, -1 on invalid arguments
10934 */
10935     int ret;
10936     const char *license_name;
10937     const char *url;
10938     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10939     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10940     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
10941 	sqlite3_value_type (argv[1]) != SQLITE_TEXT)
10942       {
10943 	  sqlite3_result_int (context, -1);
10944 	  return;
10945       }
10946     license_name = (const char *) sqlite3_value_text (argv[0]);
10947     url = (const char *) sqlite3_value_text (argv[1]);
10948     ret = set_data_license_url (sqlite, license_name, url);
10949     sqlite3_result_int (context, ret);
10950 }
10951 
10952 static void
fnct_CreateMetaCatalogTables(sqlite3_context * context,int argc,sqlite3_value ** argv)10953 fnct_CreateMetaCatalogTables (sqlite3_context * context, int argc,
10954 			      sqlite3_value ** argv)
10955 {
10956 /* SQL function:
10957 / CreateMetaCatalogTables(transaction TRUE|FALSE)
10958 /
10959 / creates (or re-creates) both "splite_metacatalog"
10960 / and "splite_metacatalog_statistics" tables
10961 / returns 1 on success
10962 / 0 on failure
10963 */
10964     char *errMsg = NULL;
10965     int ret;
10966     int transaction = 0;
10967     sqlite3 *sqlite = sqlite3_context_db_handle (context);
10968     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
10969 
10970     if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
10971       {
10972 	  spatialite_e
10973 	      ("CreateMetaCatalogTables() error: argument 1 [TRANSACTION] is not of the Integer type\n");
10974 	  sqlite3_result_null (context);
10975 	  return;
10976       }
10977     transaction = sqlite3_value_int (argv[0]);
10978     if (transaction)
10979       {
10980 	  /* starting a Transaction */
10981 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
10982 	  if (ret != SQLITE_OK)
10983 	      goto error;
10984       }
10985     if (!gaiaCreateMetaCatalogTables (sqlite))
10986 	goto error;
10987     if (transaction)
10988       {
10989 	  /* committing the still pending Transaction */
10990 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
10991 	  if (ret != SQLITE_OK)
10992 	      goto error;
10993       }
10994     updateSpatiaLiteHistory (sqlite, "*** MetaCatalog ***", NULL,
10995 			     "Tables successfully created and initialized");
10996     sqlite3_result_int (context, 1);
10997     return;
10998 
10999   error:
11000     if (transaction)
11001       {
11002 	  /* performing a Rollback */
11003 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
11004 	  if (ret != SQLITE_OK)
11005 	      sqlite3_free (errMsg);
11006       }
11007     sqlite3_result_int (context, 0);
11008     return;
11009 }
11010 
11011 static void
fnct_UpdateMetaCatalogStatistics(sqlite3_context * context,int argc,sqlite3_value ** argv)11012 fnct_UpdateMetaCatalogStatistics (sqlite3_context * context, int argc,
11013 				  sqlite3_value ** argv)
11014 {
11015 /* SQL function:
11016 / UpdateMetaCatalogStatistics(transaction TRUE|FALSE, table, column)
11017 / UpdateMetaCatalogStatistics(transaction TRUE|FALSE, master_table, table_name, column_name)
11018 /
11019 / updates the MetaCatalog statistics
11020 / returns 1 on success
11021 / 0 on failure
11022 */
11023     char *errMsg = NULL;
11024     int ret;
11025     int transaction = 0;
11026     const char *master_table = NULL;
11027     const char *table = NULL;
11028     const char *column = NULL;
11029     sqlite3 *sqlite = sqlite3_context_db_handle (context);
11030     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11031 
11032     if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
11033       {
11034 	  spatialite_e
11035 	      ("UpdateMetaCatalogStatistics() error: argument 1 [TRANSACTION] is not of the Integer type\n");
11036 	  sqlite3_result_null (context);
11037 	  return;
11038       }
11039     transaction = sqlite3_value_int (argv[0]);
11040     if (argc == 3)
11041       {
11042 	  /* table & column mode */
11043 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
11044 	      table = (const char *) sqlite3_value_text (argv[1]);
11045 	  else
11046 	    {
11047 		spatialite_e
11048 		    ("UpdateMetaCatalogStatistics() error: argument 2 [TABLE_NAME] is not of the Text type\n");
11049 		sqlite3_result_null (context);
11050 		return;
11051 	    }
11052 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
11053 	      column = (const char *) sqlite3_value_text (argv[2]);
11054 	  else
11055 	    {
11056 		spatialite_e
11057 		    ("UpdateMetaCatalogStatistics() error: argument 2 [COLUMN_NAME] is not of the Text type\n");
11058 		sqlite3_result_null (context);
11059 		return;
11060 	    }
11061       }
11062     else
11063       {
11064 	  /* master-table & table_name & column_name mode */
11065 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
11066 	      master_table = (const char *) sqlite3_value_text (argv[1]);
11067 	  else
11068 	    {
11069 		spatialite_e
11070 		    ("UpdateMetaCatalogStatistics() error: argument 2 [MASTER_TABLE] is not of the Text type\n");
11071 		sqlite3_result_null (context);
11072 		return;
11073 	    }
11074 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
11075 	      table = (const char *) sqlite3_value_text (argv[2]);
11076 	  else
11077 	    {
11078 		spatialite_e
11079 		    ("UpdateMetaCatalogStatistics() error: argument 3 [TABLE_NAME] is not of the Text type\n");
11080 		sqlite3_result_null (context);
11081 		return;
11082 	    }
11083 	  if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
11084 	      column = (const char *) sqlite3_value_text (argv[3]);
11085 	  else
11086 	    {
11087 		spatialite_e
11088 		    ("UpdateMetaCatalogStatistics() error: argument 3 [COLUMN_NAME] is not of the Text type\n");
11089 		sqlite3_result_null (context);
11090 		return;
11091 	    }
11092       }
11093     if (transaction)
11094       {
11095 	  /* starting a Transaction */
11096 	  ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &errMsg);
11097 	  if (ret != SQLITE_OK)
11098 	      goto error;
11099       }
11100     if (master_table != NULL)
11101       {
11102 	  if (!gaiaUpdateMetaCatalogStatisticsFromMaster
11103 	      (sqlite, master_table, table, column))
11104 	      goto error;
11105       }
11106     else
11107       {
11108 	  if (!gaiaUpdateMetaCatalogStatistics (sqlite, table, column))
11109 	      goto error;
11110       }
11111     if (transaction)
11112       {
11113 	  /* committing the still pending Transaction */
11114 	  ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &errMsg);
11115 	  if (ret != SQLITE_OK)
11116 	      goto error;
11117       }
11118     updateSpatiaLiteHistory (sqlite, "*** MetaCatalog ***", NULL,
11119 			     "Statistics successfully updated");
11120     sqlite3_result_int (context, 1);
11121     return;
11122 
11123   error:
11124     if (transaction)
11125       {
11126 	  /* performing a Rollback */
11127 	  ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &errMsg);
11128 	  if (ret != SQLITE_OK)
11129 	      sqlite3_free (errMsg);
11130       }
11131     sqlite3_result_int (context, 0);
11132     return;
11133 }
11134 
11135 static gaiaPointPtr
simplePoint(gaiaGeomCollPtr geo)11136 simplePoint (gaiaGeomCollPtr geo)
11137 {
11138 /* helper function
11139 / if this GEOMETRY contains only one POINT, and no other elementary geometry
11140 / the POINT address will be returned
11141 / otherwise NULL will be returned
11142 */
11143     int cnt = 0;
11144     gaiaPointPtr point;
11145     gaiaPointPtr this_point = NULL;
11146     if (!geo)
11147 	return NULL;
11148     if (geo->FirstLinestring || geo->FirstPolygon)
11149 	return NULL;
11150     point = geo->FirstPoint;
11151     while (point)
11152       {
11153 	  /* counting how many POINTs are there */
11154 	  cnt++;
11155 	  this_point = point;
11156 	  point = point->Next;
11157       }
11158     if (cnt == 1 && this_point)
11159 	return this_point;
11160     return NULL;
11161 }
11162 
11163 static gaiaLinestringPtr
simpleLinestring(gaiaGeomCollPtr geo)11164 simpleLinestring (gaiaGeomCollPtr geo)
11165 {
11166 /* helper function
11167 / if this GEOMETRY contains only one LINESTRING, and no other elementary geometry
11168 / the LINESTRING address will be returned
11169 / otherwise NULL will be returned
11170 */
11171     int cnt = 0;
11172     gaiaLinestringPtr line;
11173     gaiaLinestringPtr this_line = NULL;
11174     if (!geo)
11175 	return NULL;
11176     if (geo->FirstPoint || geo->FirstPolygon)
11177 	return NULL;
11178     line = geo->FirstLinestring;
11179     while (line)
11180       {
11181 	  /* counting how many LINESTRINGs are there */
11182 	  cnt++;
11183 	  this_line = line;
11184 	  line = line->Next;
11185       }
11186     if (cnt == 1 && this_line)
11187 	return this_line;
11188     return NULL;
11189 }
11190 
11191 static gaiaPolygonPtr
simplePolygon(gaiaGeomCollPtr geo)11192 simplePolygon (gaiaGeomCollPtr geo)
11193 {
11194 /* helper function
11195 / if this GEOMETRY contains only one POLYGON, and no other elementary geometry
11196 / the POLYGON address will be returned
11197 / otherwise NULL will be returned
11198 */
11199     int cnt = 0;
11200     gaiaPolygonPtr polyg;
11201     gaiaPolygonPtr this_polyg = NULL;
11202     if (!geo)
11203 	return NULL;
11204     if (geo->FirstPoint || geo->FirstLinestring)
11205 	return NULL;
11206     polyg = geo->FirstPolygon;
11207     while (polyg)
11208       {
11209 	  /* counting how many POLYGONs are there */
11210 	  cnt++;
11211 	  this_polyg = polyg;
11212 	  polyg = polyg->Next;
11213       }
11214     if (cnt == 1 && this_polyg)
11215 	return this_polyg;
11216     return NULL;
11217 }
11218 
11219 static void
fnct_AsText(sqlite3_context * context,int argc,sqlite3_value ** argv)11220 fnct_AsText (sqlite3_context * context, int argc, sqlite3_value ** argv)
11221 {
11222 /* SQL function:
11223 / AsText(BLOB encoded geometry)
11224 /
11225 / returns the corresponding WKT encoded value
11226 / or NULL if any error is encountered
11227 */
11228     unsigned char *p_blob;
11229     int n_bytes;
11230     int len;
11231     gaiaOutBuffer out_buf;
11232     gaiaGeomCollPtr geo = NULL;
11233     int decimal_precision = -1;
11234     int gpkg_amphibious = 0;
11235     int gpkg_mode = 0;
11236     struct splite_internal_cache *cache = sqlite3_user_data (context);
11237     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11238     if (cache != NULL)
11239       {
11240 	  decimal_precision = cache->decimal_precision;
11241 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11242 	  gpkg_mode = cache->gpkg_mode;
11243       }
11244     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11245       {
11246 	  sqlite3_result_null (context);
11247 	  return;
11248       }
11249     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11250     n_bytes = sqlite3_value_bytes (argv[0]);
11251     gaiaOutBufferInitialize (&out_buf);
11252     geo =
11253 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11254 				     gpkg_amphibious);
11255     if (!geo)
11256 	sqlite3_result_null (context);
11257     else
11258       {
11259 	  if (decimal_precision >= 0)
11260 	      gaiaOutWktEx (&out_buf, geo, decimal_precision);
11261 	  else
11262 	      gaiaOutWkt (&out_buf, geo);
11263 	  if (out_buf.Error || out_buf.Buffer == NULL)
11264 	      sqlite3_result_null (context);
11265 	  else
11266 	    {
11267 		len = out_buf.WriteOffset;
11268 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11269 		out_buf.Buffer = NULL;
11270 	    }
11271       }
11272     gaiaFreeGeomColl (geo);
11273     gaiaOutBufferReset (&out_buf);
11274 }
11275 
11276 static void
fnct_AsWkt(sqlite3_context * context,int argc,sqlite3_value ** argv)11277 fnct_AsWkt (sqlite3_context * context, int argc, sqlite3_value ** argv)
11278 {
11279 /* SQL function:
11280 / AsWkt(BLOB encoded geometry [, Integer precision])
11281 /
11282 / returns the corresponding WKT encoded value
11283 / or NULL if any error is encountered
11284 */
11285     unsigned char *p_blob;
11286     int n_bytes;
11287     int len;
11288     int precision = 15;
11289     gaiaOutBuffer out_buf;
11290     gaiaGeomCollPtr geo = NULL;
11291     int gpkg_amphibious = 0;
11292     int gpkg_mode = 0;
11293     struct splite_internal_cache *cache = sqlite3_user_data (context);
11294     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11295     if (cache != NULL)
11296       {
11297 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11298 	  gpkg_mode = cache->gpkg_mode;
11299       }
11300     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11301       {
11302 	  sqlite3_result_null (context);
11303 	  return;
11304       }
11305     if (argc == 2)
11306       {
11307 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
11308 	      precision = sqlite3_value_int (argv[1]);
11309 	  else
11310 	    {
11311 		sqlite3_result_null (context);
11312 		return;
11313 	    }
11314       }
11315     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11316     n_bytes = sqlite3_value_bytes (argv[0]);
11317     geo =
11318 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11319 				     gpkg_amphibious);
11320     gaiaOutBufferInitialize (&out_buf);
11321     if (!geo)
11322 	sqlite3_result_null (context);
11323     else
11324       {
11325 	  gaiaOutWktStrict (&out_buf, geo, precision);
11326 	  if (out_buf.Error || out_buf.Buffer == NULL)
11327 	      sqlite3_result_null (context);
11328 	  else
11329 	    {
11330 		len = out_buf.WriteOffset;
11331 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11332 		out_buf.Buffer = NULL;
11333 	    }
11334       }
11335     gaiaFreeGeomColl (geo);
11336     gaiaOutBufferReset (&out_buf);
11337 }
11338 
11339 /*
11340 /
11341 / AsSvg(geometry,[relative], [precision]) implementation
11342 /
11343 ////////////////////////////////////////////////////////////
11344 /
11345 / Author: Klaus Foerster klaus.foerster@svg.cc
11346 / version 0.9. 2008 September 21
11347  /
11348  */
11349 
11350 static void
fnct_AsSvg(sqlite3_context * context,int argc,sqlite3_value ** argv,int relative,int precision)11351 fnct_AsSvg (sqlite3_context * context, int argc, sqlite3_value ** argv,
11352 	    int relative, int precision)
11353 {
11354 /* SQL function:
11355    AsSvg(BLOB encoded geometry, [int relative], [int precision])
11356    returns the corresponding SVG encoded value or NULL if any error is encountered
11357 */
11358     unsigned char *p_blob;
11359     int n_bytes;
11360     int len;
11361     gaiaOutBuffer out_buf;
11362     gaiaGeomCollPtr geo = NULL;
11363     int gpkg_amphibious = 0;
11364     int gpkg_mode = 0;
11365     struct splite_internal_cache *cache = sqlite3_user_data (context);
11366     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11367     if (cache != NULL)
11368       {
11369 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11370 	  gpkg_mode = cache->gpkg_mode;
11371       }
11372     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11373       {
11374 	  sqlite3_result_null (context);
11375 	  return;
11376       }
11377     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11378     n_bytes = sqlite3_value_bytes (argv[0]);
11379     geo =
11380 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11381 				     gpkg_amphibious);
11382     if (!geo)
11383       {
11384 	  sqlite3_result_null (context);
11385 	  return;
11386       }
11387     else
11388       {
11389 	  /* make sure relative is 0 or 1 */
11390 	  if (relative > 0)
11391 	      relative = 1;
11392 	  else
11393 	      relative = 0;
11394 	  /* make sure precision is between 0 and 15 - default to 6 if absent */
11395 	  if (precision > GAIA_SVG_DEFAULT_MAX_PRECISION)
11396 	      precision = GAIA_SVG_DEFAULT_MAX_PRECISION;
11397 	  if (precision < 0)
11398 	      precision = 0;
11399 	  /* produce SVG-notation - actual work is done in gaiageo/gg_wkt.c */
11400 	  gaiaOutBufferInitialize (&out_buf);
11401 	  gaiaOutSvg (&out_buf, geo, relative, precision);
11402 	  if (out_buf.Error || out_buf.Buffer == NULL)
11403 	      sqlite3_result_null (context);
11404 	  else
11405 	    {
11406 		len = out_buf.WriteOffset;
11407 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11408 		out_buf.Buffer = NULL;
11409 	    }
11410       }
11411     gaiaFreeGeomColl (geo);
11412     gaiaOutBufferReset (&out_buf);
11413 }
11414 
11415 static void
fnct_AsSvg1(sqlite3_context * context,int argc,sqlite3_value ** argv)11416 fnct_AsSvg1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
11417 {
11418 /* called without additional arguments */
11419     fnct_AsSvg (context, argc, argv, GAIA_SVG_DEFAULT_RELATIVE,
11420 		GAIA_SVG_DEFAULT_PRECISION);
11421 }
11422 
11423 static void
fnct_AsSvg2(sqlite3_context * context,int argc,sqlite3_value ** argv)11424 fnct_AsSvg2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
11425 {
11426 /* called with relative-switch */
11427     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
11428 	fnct_AsSvg (context, argc, argv, sqlite3_value_int (argv[1]),
11429 		    GAIA_SVG_DEFAULT_PRECISION);
11430     else
11431 	sqlite3_result_null (context);
11432 }
11433 
11434 static void
fnct_AsSvg3(sqlite3_context * context,int argc,sqlite3_value ** argv)11435 fnct_AsSvg3 (sqlite3_context * context, int argc, sqlite3_value ** argv)
11436 {
11437 /* called with relative-switch and precision-argument */
11438     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER
11439 	&& sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
11440 	fnct_AsSvg (context, argc, argv, sqlite3_value_int (argv[1]),
11441 		    sqlite3_value_int (argv[2]));
11442     else
11443 	sqlite3_result_null (context);
11444 }
11445 
11446 /* END of Klaus Foerster AsSvg() implementation */
11447 
11448 
11449 #ifndef OMIT_PROJ		/* PROJ.4 is strictly required to support KML */
11450 static void
fnct_AsKml1(sqlite3_context * context,int argc,sqlite3_value ** argv)11451 fnct_AsKml1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
11452 {
11453 /* SQL function:
11454 / AsKml(BLOB encoded geometry [, Integer precision])
11455 /
11456 / returns the corresponding 'bare geom' KML representation
11457 / or NULL if any error is encountered
11458 */
11459     unsigned char *p_blob;
11460     int n_bytes;
11461     int len;
11462     gaiaOutBuffer out_buf;
11463     gaiaGeomCollPtr geo = NULL;
11464     gaiaGeomCollPtr geo_wgs84;
11465     char *proj_from = NULL;
11466     char *proj_to = NULL;
11467     int precision = 15;
11468     void *data = sqlite3_user_data (context);
11469     sqlite3 *sqlite = sqlite3_context_db_handle (context);
11470     int gpkg_amphibious = 0;
11471     int gpkg_mode = 0;
11472     struct splite_internal_cache *cache = sqlite3_user_data (context);
11473     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11474     if (cache != NULL)
11475       {
11476 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11477 	  gpkg_mode = cache->gpkg_mode;
11478       }
11479     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11480       {
11481 	  sqlite3_result_null (context);
11482 	  return;
11483       }
11484     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11485     n_bytes = sqlite3_value_bytes (argv[0]);
11486     if (argc == 2)
11487       {
11488 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
11489 	      precision = sqlite3_value_int (argv[1]);
11490 	  else
11491 	    {
11492 		sqlite3_result_null (context);
11493 		return;
11494 	    }
11495       }
11496     gaiaOutBufferInitialize (&out_buf);
11497     geo =
11498 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11499 				     gpkg_amphibious);
11500     if (!geo)
11501 	sqlite3_result_null (context);
11502     else
11503       {
11504 	  if (geo->Srid == 4326)
11505 	      ;			/* already WGS84 */
11506 	  else if (geo->Srid <= 0)
11507 	    {
11508 		/* unknown SRID: giving up */
11509 		sqlite3_result_null (context);
11510 		goto stop;
11511 	    }
11512 	  else
11513 	    {
11514 		/* attempting to reproject into WGS84 */
11515 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
11516 		getProjAuthNameSrid (sqlite, geo->Srid, &proj_from);
11517 		getProjAuthNameSrid (sqlite, 4326, &proj_to);
11518 #else /* supporting old PROJ.4 */
11519 		getProjParams (sqlite, geo->Srid, &proj_from);
11520 		getProjParams (sqlite, 4326, &proj_to);
11521 #endif
11522 		if (proj_to == NULL || proj_from == NULL)
11523 		  {
11524 		      if (proj_from)
11525 			  free (proj_from);
11526 		      if (proj_to)
11527 			  free (proj_to);
11528 		      sqlite3_result_null (context);
11529 		      goto stop;
11530 		  }
11531 		if (data != NULL)
11532 		    geo_wgs84 = gaiaTransform_r (data, geo, proj_from, proj_to);
11533 		else
11534 		    geo_wgs84 = gaiaTransform (geo, proj_from, proj_to);
11535 		free (proj_from);
11536 		free (proj_to);
11537 		if (!geo_wgs84)
11538 		  {
11539 		      sqlite3_result_null (context);
11540 		      goto stop;
11541 		  }
11542 		/* ok, reprojection was successful */
11543 		gaiaFreeGeomColl (geo);
11544 		geo = geo_wgs84;
11545 	    }
11546 	  /* produce KML-notation - actual work is done in gaiageo/gg_wkt.c */
11547 	  gaiaOutBareKml (&out_buf, geo, precision);
11548 	  if (out_buf.Error || out_buf.Buffer == NULL)
11549 	      sqlite3_result_null (context);
11550 	  else
11551 	    {
11552 		len = out_buf.WriteOffset;
11553 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11554 		out_buf.Buffer = NULL;
11555 	    }
11556       }
11557   stop:
11558     gaiaFreeGeomColl (geo);
11559     gaiaOutBufferReset (&out_buf);
11560 }
11561 
11562 static void
fnct_AsKml3(sqlite3_context * context,int argc,sqlite3_value ** argv)11563 fnct_AsKml3 (sqlite3_context * context, int argc, sqlite3_value ** argv)
11564 {
11565 /* SQL function:
11566 / AsKml(Anything name, Anything description, BLOB encoded geometry [, Integer precision])
11567 /
11568 / returns the corresponding 'full' KML representation
11569 / or NULL if any error is encountered
11570 */
11571     unsigned char *p_blob;
11572     int n_bytes;
11573     int len;
11574     gaiaOutBuffer out_buf;
11575     gaiaGeomCollPtr geo = NULL;
11576     gaiaGeomCollPtr geo_wgs84;
11577     sqlite3_int64 int_value;
11578     double dbl_value;
11579     const char *name;
11580     const char *desc;
11581     char *name_malloc = NULL;
11582     char *desc_malloc = NULL;
11583     char dummy[128];
11584     char *xdummy;
11585     char *proj_from = NULL;
11586     char *proj_to = NULL;
11587     int precision = 15;
11588     void *data = sqlite3_user_data (context);
11589     sqlite3 *sqlite = sqlite3_context_db_handle (context);
11590     int gpkg_amphibious = 0;
11591     int gpkg_mode = 0;
11592     struct splite_internal_cache *cache = sqlite3_user_data (context);
11593     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11594     if (cache != NULL)
11595       {
11596 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11597 	  gpkg_mode = cache->gpkg_mode;
11598       }
11599     switch (sqlite3_value_type (argv[0]))
11600       {
11601       case SQLITE_TEXT:
11602 	  name = (const char *) sqlite3_value_text (argv[0]);
11603 	  len = strlen (name);
11604 	  name_malloc = malloc (len + 1);
11605 	  strcpy (name_malloc, name);
11606 	  name = name_malloc;
11607 	  break;
11608       case SQLITE_INTEGER:
11609 	  int_value = sqlite3_value_int64 (argv[0]);
11610 	  sprintf (dummy, FRMT64, int_value);
11611 	  len = strlen (dummy);
11612 	  name_malloc = malloc (len + 1);
11613 	  strcpy (name_malloc, dummy);
11614 	  name = name_malloc;
11615 	  break;
11616       case SQLITE_FLOAT:
11617 	  dbl_value = sqlite3_value_double (argv[0]);
11618 	  xdummy = sqlite3_mprintf ("%1.6f", dbl_value);
11619 	  len = strlen (xdummy);
11620 	  name_malloc = malloc (len + 1);
11621 	  strcpy (name_malloc, xdummy);
11622 	  sqlite3_free (xdummy);
11623 	  name = name_malloc;
11624 	  break;
11625       case SQLITE_BLOB:
11626 	  name = "BLOB";
11627 	  break;
11628       default:
11629 	  name = "NULL";
11630 	  break;
11631       };
11632     switch (sqlite3_value_type (argv[1]))
11633       {
11634       case SQLITE_TEXT:
11635 	  desc = (const char *) sqlite3_value_text (argv[1]);
11636 	  len = strlen (desc);
11637 	  desc_malloc = malloc (len + 1);
11638 	  strcpy (desc_malloc, desc);
11639 	  desc = desc_malloc;
11640 	  break;
11641       case SQLITE_INTEGER:
11642 	  int_value = sqlite3_value_int64 (argv[1]);
11643 	  sprintf (dummy, FRMT64, int_value);
11644 	  len = strlen (dummy);
11645 	  desc_malloc = malloc (len + 1);
11646 	  strcpy (desc_malloc, dummy);
11647 	  desc = desc_malloc;
11648 	  break;
11649       case SQLITE_FLOAT:
11650 	  dbl_value = sqlite3_value_double (argv[1]);
11651 	  xdummy = sqlite3_mprintf ("%1.6f", dbl_value);
11652 	  len = strlen (xdummy);
11653 	  desc_malloc = malloc (len + 1);
11654 	  strcpy (desc_malloc, xdummy);
11655 	  sqlite3_free (xdummy);
11656 	  desc = desc_malloc;
11657 	  break;
11658       case SQLITE_BLOB:
11659 	  desc = "BLOB";
11660 	  break;
11661       default:
11662 	  desc = "NULL";
11663 	  break;
11664       };
11665     gaiaOutBufferInitialize (&out_buf);
11666     if (sqlite3_value_type (argv[2]) != SQLITE_BLOB)
11667       {
11668 	  sqlite3_result_null (context);
11669 	  goto stop;
11670       }
11671     p_blob = (unsigned char *) sqlite3_value_blob (argv[2]);
11672     n_bytes = sqlite3_value_bytes (argv[2]);
11673     if (argc == 4)
11674       {
11675 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
11676 	      precision = sqlite3_value_int (argv[3]);
11677 	  else
11678 	    {
11679 		sqlite3_result_null (context);
11680 		goto stop;
11681 	    }
11682       }
11683     geo =
11684 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11685 				     gpkg_amphibious);
11686     if (!geo)
11687 	sqlite3_result_null (context);
11688     else
11689       {
11690 	  if (geo->Srid == 4326)
11691 	      ;			/* already WGS84 */
11692 	  else if (geo->Srid == 0)
11693 	    {
11694 		/* unknown SRID: giving up */
11695 		sqlite3_result_null (context);
11696 		goto stop;
11697 	    }
11698 	  else
11699 	    {
11700 		/* attempting to reproject into WGS84 */
11701 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
11702 		getProjAuthNameSrid (sqlite, geo->Srid, &proj_from);
11703 		getProjAuthNameSrid (sqlite, 4326, &proj_to);
11704 #else /* supporting old PROJ.4 */
11705 		getProjParams (sqlite, geo->Srid, &proj_from);
11706 		getProjParams (sqlite, 4326, &proj_to);
11707 #endif
11708 		if (proj_to == NULL || proj_from == NULL)
11709 		  {
11710 		      if (proj_from != NULL)
11711 			  free (proj_from);
11712 		      if (proj_to != NULL)
11713 			  free (proj_to);
11714 		      sqlite3_result_null (context);
11715 		      goto stop;
11716 		  }
11717 		if (data != NULL)
11718 		    geo_wgs84 = gaiaTransform_r (data, geo, proj_from, proj_to);
11719 		else
11720 		    geo_wgs84 = gaiaTransform (geo, proj_from, proj_to);
11721 		free (proj_from);
11722 		free (proj_to);
11723 		if (!geo_wgs84)
11724 		  {
11725 		      sqlite3_result_null (context);
11726 		      goto stop;
11727 		  }
11728 		/* ok, reprojection was successful */
11729 		gaiaFreeGeomColl (geo);
11730 		geo = geo_wgs84;
11731 	    }
11732 	  /* produce KML-notation - actual work is done in gaiageo/gg_wkt.c */
11733 	  gaiaOutFullKml (&out_buf, name, desc, geo, precision);
11734 	  if (out_buf.Error || out_buf.Buffer == NULL)
11735 	      sqlite3_result_null (context);
11736 	  else
11737 	    {
11738 		len = out_buf.WriteOffset;
11739 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11740 		out_buf.Buffer = NULL;
11741 	    }
11742       }
11743   stop:
11744     gaiaFreeGeomColl (geo);
11745     if (name_malloc)
11746 	free (name_malloc);
11747     if (desc_malloc)
11748 	free (desc_malloc);
11749     gaiaOutBufferReset (&out_buf);
11750 }
11751 
11752 static void
fnct_AsKml(sqlite3_context * context,int argc,sqlite3_value ** argv)11753 fnct_AsKml (sqlite3_context * context, int argc, sqlite3_value ** argv)
11754 {
11755 /* SQL function:
11756 / AsKml(Anything name, Anything description, BLOB encoded geometry)
11757 /     or
11758 / AsKml(BLOB encoded geometry)
11759 /
11760 / returns the corresponding KML representation
11761 / or NULL if any error is encountered
11762 */
11763     if (argc == 3 || argc == 4)
11764 	fnct_AsKml3 (context, argc, argv);
11765     else
11766 	fnct_AsKml1 (context, argc, argv);
11767 }
11768 #endif /* end including PROJ.4 */
11769 
11770 static void
fnct_AsGml(sqlite3_context * context,int argc,sqlite3_value ** argv)11771 fnct_AsGml (sqlite3_context * context, int argc, sqlite3_value ** argv)
11772 {
11773 /* SQL function:
11774 / AsGml(BLOB encoded geometry)
11775 /    or
11776 / AsGml(integer version, BLOB encoded geometry)
11777 /    or
11778 / AsGml(integer version, BLOB encoded geometry, integer precision)
11779 /
11780 / *version* may be 2 (GML 2.1.2) or 3 (GML 3.1.1)
11781 / default *version*: 2
11782 /
11783 / *precision* is the number of output decimal digits
11784 / default *precision*: 15
11785 /
11786 / returns the corresponding GML representation
11787 / or NULL if any error is encountered
11788 */
11789     unsigned char *p_blob;
11790     int n_bytes;
11791     int len;
11792     int version = 2;
11793     int precision = 15;
11794     gaiaOutBuffer out_buf;
11795     gaiaGeomCollPtr geo = NULL;
11796     int gpkg_amphibious = 0;
11797     int gpkg_mode = 0;
11798     struct splite_internal_cache *cache = sqlite3_user_data (context);
11799     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11800     if (cache != NULL)
11801       {
11802 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
11803 	  gpkg_mode = cache->gpkg_mode;
11804       }
11805     if (argc == 3)
11806       {
11807 	  if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
11808 	      version = sqlite3_value_int (argv[0]);
11809 	  else
11810 	    {
11811 		sqlite3_result_null (context);
11812 		return;
11813 	    }
11814 	  if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
11815 	    {
11816 		sqlite3_result_null (context);
11817 		return;
11818 	    }
11819 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
11820 	  n_bytes = sqlite3_value_bytes (argv[1]);
11821 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
11822 	      precision = sqlite3_value_int (argv[2]);
11823 	  else
11824 	    {
11825 		sqlite3_result_null (context);
11826 		return;
11827 	    }
11828       }
11829     else if (argc == 2)
11830       {
11831 	  if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER
11832 	      && sqlite3_value_type (argv[1]) == SQLITE_BLOB)
11833 	    {
11834 		version = sqlite3_value_int (argv[0]);
11835 		p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
11836 		n_bytes = sqlite3_value_bytes (argv[1]);
11837 	    }
11838 	  else if (sqlite3_value_type (argv[0]) == SQLITE_BLOB
11839 		   && sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
11840 	    {
11841 		p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11842 		n_bytes = sqlite3_value_bytes (argv[0]);
11843 		precision = sqlite3_value_int (argv[1]);
11844 	    }
11845 	  else
11846 	    {
11847 		sqlite3_result_null (context);
11848 		return;
11849 	    }
11850       }
11851     else
11852       {
11853 	  if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11854 	    {
11855 		sqlite3_result_null (context);
11856 		return;
11857 	    }
11858 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11859 	  n_bytes = sqlite3_value_bytes (argv[0]);
11860       }
11861     gaiaOutBufferInitialize (&out_buf);
11862     geo =
11863 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11864 				     gpkg_amphibious);
11865     if (!geo)
11866 	sqlite3_result_null (context);
11867     else
11868       {
11869 	  /* produce GML-notation - actual work is done in gaiageo/gg_wkt.c */
11870 	  gaiaOutGml (&out_buf, version, precision, geo);
11871 	  if (out_buf.Error || out_buf.Buffer == NULL)
11872 	      sqlite3_result_null (context);
11873 	  else
11874 	    {
11875 		len = out_buf.WriteOffset;
11876 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11877 		out_buf.Buffer = NULL;
11878 	    }
11879       }
11880     gaiaFreeGeomColl (geo);
11881     gaiaOutBufferReset (&out_buf);
11882 }
11883 
11884 static void
fnct_AsGeoJSON(sqlite3_context * context,int argc,sqlite3_value ** argv)11885 fnct_AsGeoJSON (sqlite3_context * context, int argc, sqlite3_value ** argv)
11886 {
11887 /* SQL function:
11888 / AsGeoJSON(BLOB encoded geometry)
11889 /    or
11890 / AsGeoJSON(BLOB encoded geometry, integer precision)
11891 /    or
11892 / AsGeoJSON(BLOB encoded geometry, integer precision, integer options)
11893 /
11894 / *precision* is the number of output decimal digits
11895 / default *precision*: 15
11896 /
11897 / *options* may be one of the followings:
11898 /   0 = no options [default]
11899 /   1 = GeoJSON MBR
11900 /   2 = GeoJSON Short CRS (e.g EPSG:4326)
11901 /   3 = 1 + 2 (Mbr + shortCrs)
11902 /   4 = GeoJSON Long CRS (e.g urn:ogc:def:crs:EPSG::4326)
11903 /   5 = 1 + 4 (Mbr + longCrs)
11904 /
11905 / returns the corresponding GML representation
11906 / or NULL if any error is encountered
11907 */
11908     unsigned char *p_blob;
11909     int n_bytes;
11910     int len;
11911     int precision = 15;
11912     int options = 0;
11913     gaiaOutBuffer out_buf;
11914     gaiaGeomCollPtr geo = NULL;
11915     int gpkg_amphibious = 0;
11916     int gpkg_mode = 0;
11917     struct splite_internal_cache *cache = sqlite3_user_data (context);
11918     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
11919     if (cache != NULL)
11920 	gpkg_amphibious = cache->gpkg_mode = cache->gpkg_mode;;
11921     if (argc == 3)
11922       {
11923 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB
11924 	      && sqlite3_value_type (argv[1]) == SQLITE_INTEGER
11925 	      && sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
11926 	    {
11927 		p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11928 		n_bytes = sqlite3_value_bytes (argv[0]);
11929 		precision = sqlite3_value_int (argv[1]);
11930 		options = sqlite3_value_int (argv[2]);
11931 		if (options >= 1 && options <= 5)
11932 		    ;
11933 		else
11934 		    options = 0;
11935 	    }
11936 	  else
11937 	    {
11938 		sqlite3_result_null (context);
11939 		return;
11940 	    }
11941       }
11942     else if (argc == 2)
11943       {
11944 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB
11945 	      && sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
11946 	    {
11947 		p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11948 		n_bytes = sqlite3_value_bytes (argv[0]);
11949 		precision = sqlite3_value_int (argv[1]);
11950 	    }
11951 	  else
11952 	    {
11953 		sqlite3_result_null (context);
11954 		return;
11955 	    }
11956       }
11957     else
11958       {
11959 	  if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
11960 	    {
11961 		sqlite3_result_null (context);
11962 		return;
11963 	    }
11964 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
11965 	  n_bytes = sqlite3_value_bytes (argv[0]);
11966       }
11967     gaiaOutBufferInitialize (&out_buf);
11968     geo =
11969 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
11970 				     gpkg_amphibious);
11971     if (!geo)
11972 	sqlite3_result_null (context);
11973     else
11974       {
11975 	  /* produce GeoJSON-notation - actual work is done in gaiageo/gg_wkt.c */
11976 	  gaiaOutGeoJSON (&out_buf, geo, precision, options);
11977 	  if (out_buf.Error || out_buf.Buffer == NULL)
11978 	      sqlite3_result_null (context);
11979 	  else
11980 	    {
11981 		len = out_buf.WriteOffset;
11982 		sqlite3_result_text (context, out_buf.Buffer, len, free);
11983 		out_buf.Buffer = NULL;
11984 	    }
11985       }
11986     gaiaFreeGeomColl (geo);
11987     gaiaOutBufferReset (&out_buf);
11988 }
11989 
11990 static void
fnct_AsBinary(sqlite3_context * context,int argc,sqlite3_value ** argv)11991 fnct_AsBinary (sqlite3_context * context, int argc, sqlite3_value ** argv)
11992 {
11993 /* SQL function:
11994 / AsBinary(BLOB encoded geometry)
11995 /
11996 / returns the corresponding WKB encoded value
11997 / or NULL if any error is encountered
11998 */
11999     unsigned char *p_blob;
12000     int n_bytes;
12001     int len;
12002     unsigned char *p_result = NULL;
12003     gaiaGeomCollPtr geo = NULL;
12004     int gpkg_amphibious = 0;
12005     int gpkg_mode = 0;
12006     struct splite_internal_cache *cache = sqlite3_user_data (context);
12007     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12008     if (cache != NULL)
12009       {
12010 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
12011 	  gpkg_mode = cache->gpkg_mode;
12012       }
12013     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
12014       {
12015 	  sqlite3_result_null (context);
12016 	  return;
12017       }
12018     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
12019     n_bytes = sqlite3_value_bytes (argv[0]);
12020     geo =
12021 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
12022 				     gpkg_amphibious);
12023     if (!geo)
12024 	sqlite3_result_null (context);
12025     else
12026       {
12027 	  gaiaToWkb (geo, &p_result, &len);
12028 	  if (!p_result)
12029 	      sqlite3_result_null (context);
12030 	  else
12031 	      sqlite3_result_blob (context, p_result, len, free);
12032       }
12033     gaiaFreeGeomColl (geo);
12034 }
12035 
12036 static void
fnct_AsFGF(sqlite3_context * context,int argc,sqlite3_value ** argv)12037 fnct_AsFGF (sqlite3_context * context, int argc, sqlite3_value ** argv)
12038 {
12039 /* SQL function:
12040 / AsFGF(BLOB encoded geometry, int dims)
12041 /
12042 / returns the corresponding FGF encoded value
12043 / or NULL if any error is encountered
12044 */
12045     unsigned char *p_blob;
12046     int n_bytes;
12047     int len;
12048     unsigned char *p_result = NULL;
12049     gaiaGeomCollPtr geo = NULL;
12050     int coord_dims;
12051     int gpkg_amphibious = 0;
12052     int gpkg_mode = 0;
12053     struct splite_internal_cache *cache = sqlite3_user_data (context);
12054     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12055     if (cache != NULL)
12056       {
12057 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
12058 	  gpkg_mode = cache->gpkg_mode;
12059       }
12060     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
12061       {
12062 	  sqlite3_result_null (context);
12063 	  return;
12064       }
12065     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
12066     n_bytes = sqlite3_value_bytes (argv[0]);
12067     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
12068       {
12069 	  spatialite_e
12070 	      ("AsFGF() error: argument 2 [geom_coords] is not of the Integer type\n");
12071 	  sqlite3_result_null (context);
12072 	  return;
12073       }
12074     coord_dims = sqlite3_value_int (argv[1]);
12075     if (coord_dims
12076 	== 0 || coord_dims == 1 || coord_dims == 2 || coord_dims == 3)
12077 	;
12078     else
12079       {
12080 	  spatialite_e
12081 	      ("AsFGF() error: argument 2 [geom_coords] out of range [0,1,2,3]\n");
12082 	  sqlite3_result_null (context);
12083 	  return;
12084       }
12085     geo =
12086 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
12087 				     gpkg_amphibious);
12088     if (!geo)
12089 	sqlite3_result_null (context);
12090     else
12091       {
12092 	  gaiaToFgf (geo, &p_result, &len, coord_dims);
12093 	  if (!p_result)
12094 	      sqlite3_result_null (context);
12095 	  else
12096 	      sqlite3_result_blob (context, p_result, len, free);
12097       }
12098     gaiaFreeGeomColl (geo);
12099 }
12100 
12101 static void
fnct_tiny_point_encode(sqlite3_context * context,int argc,sqlite3_value ** argv)12102 fnct_tiny_point_encode (sqlite3_context * context, int argc,
12103 			sqlite3_value ** argv)
12104 {
12105 /* SQL function:
12106 / TinyPointEncode(variable-type)
12107 /
12108 / returns a BLOB TinyPoint if the received argument is a BLOB-GEOMETRY POINT
12109 / in any other case the received argument will be returned "as is"
12110 */
12111     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12112     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
12113       {
12114 	  int geom_point = 1;
12115 	  const unsigned char *blob =
12116 	      (const unsigned char *) sqlite3_value_blob (argv[0]);
12117 	  int size = sqlite3_value_bytes (argv[0]);
12118 	  if (size < 45)
12119 	      geom_point = 0;
12120 	  else
12121 	    {
12122 		int endian_arch = gaiaEndianArch ();
12123 		int type;
12124 		int little_endian = 0;
12125 		if (*(blob + 0) != GAIA_MARK_START)
12126 		    geom_point = 0;
12127 		if (*(blob + (size - 1)) != GAIA_MARK_END)
12128 		    geom_point = 0;
12129 		if (*(blob + 38) != GAIA_MARK_MBR)
12130 		    geom_point = 0;
12131 		if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
12132 		    little_endian = 1;
12133 		else if (*(blob + 1) == GAIA_BIG_ENDIAN)
12134 		    ;
12135 		else
12136 		    geom_point = 0;
12137 		type = gaiaImport32 (blob + 39, little_endian, endian_arch);
12138 		if (type == GAIA_POINT || type == GAIA_POINTZ
12139 		    || type == GAIA_POINTM || type == GAIA_POINTZM)
12140 		    ;
12141 		else
12142 		    geom_point = 0;
12143 	    }
12144 	  if (geom_point)
12145 	    {
12146 		int endian_arch = gaiaEndianArch ();
12147 		int type;
12148 		int little_endian = 0;
12149 		int srid;
12150 		double x;
12151 		double y;
12152 		double z;
12153 		double m;
12154 		unsigned char *out;
12155 		int out_sz;
12156 		if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
12157 		    little_endian = 1;
12158 		srid = gaiaImport32 (blob + 2, little_endian, endian_arch);
12159 		type = gaiaImport32 (blob + 39, little_endian, endian_arch);
12160 		x = gaiaImport64 (blob + 43, little_endian, endian_arch);
12161 		y = gaiaImport64 (blob + 51, little_endian, endian_arch);
12162 		switch (type)
12163 		  {
12164 		  case GAIA_POINT:
12165 		      gaiaMakePointEx (1, x, y, srid, &out, &out_sz);
12166 		      break;
12167 		  case GAIA_POINTZ:
12168 		      z = gaiaImport64 (blob + 59, little_endian, endian_arch);
12169 		      gaiaMakePointZEx (1, x, y, z, srid, &out, &out_sz);
12170 		      break;
12171 		  case GAIA_POINTM:
12172 		      m = gaiaImport64 (blob + 59, little_endian, endian_arch);
12173 		      gaiaMakePointMEx (1, x, y, m, srid, &out, &out_sz);
12174 		      break;
12175 		  case GAIA_POINTZM:
12176 		      z = gaiaImport64 (blob + 59, little_endian, endian_arch);
12177 		      m = gaiaImport64 (blob + 67, little_endian, endian_arch);
12178 		      gaiaMakePointZMEx (1, x, y, z, m, srid, &out, &out_sz);
12179 		      break;
12180 		  };
12181 		sqlite3_result_blob (context, out, out_sz, free);
12182 	    }
12183 	  else
12184 	      sqlite3_result_blob (context, blob, size, SQLITE_TRANSIENT);
12185 
12186       }
12187     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12188 	sqlite3_result_int (context, sqlite3_value_int (argv[0]));
12189     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12190 	sqlite3_result_double (context, sqlite3_value_double (argv[0]));
12191     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
12192 	sqlite3_result_text (context,
12193 			     (const char *) sqlite3_value_text (argv[0]),
12194 			     sqlite3_value_bytes (argv[0]), SQLITE_TRANSIENT);
12195     else
12196 	sqlite3_result_null (context);
12197 }
12198 
12199 static void
fnct_geometry_point_encode(sqlite3_context * context,int argc,sqlite3_value ** argv)12200 fnct_geometry_point_encode (sqlite3_context * context, int argc,
12201 			    sqlite3_value ** argv)
12202 {
12203 /* SQL function:
12204 / GeometryPointEncode(variable-type)
12205 /
12206 / returns a BLOB GEOMETRY if the received argument is a BLOB-TinyPoint POINT
12207 / in any other case the received argument will be returned "as is"
12208 */
12209     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12210     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
12211       {
12212 	  int tiny_point = 1;
12213 	  const unsigned char *blob =
12214 	      (const unsigned char *) sqlite3_value_blob (argv[0]);
12215 	  int size = sqlite3_value_bytes (argv[0]);
12216 	  if (size < 24)
12217 	      tiny_point = 0;
12218 	  else
12219 	    {
12220 		if (size == 24 || size == 32 || size == 40)
12221 		    ;
12222 		else
12223 		    tiny_point = 0;
12224 		if (*(blob + 0) != GAIA_MARK_START)
12225 		    tiny_point = 0;
12226 		if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN
12227 		    || *(blob + 1) == GAIA_TINYPOINT_BIG_ENDIAN)
12228 		    ;
12229 		else
12230 		    tiny_point = 0;
12231 		if (*(blob + 6) == GAIA_TINYPOINT_XY
12232 		    || *(blob + 6) == GAIA_TINYPOINT_XYZ
12233 		    || *(blob + 6) == GAIA_TINYPOINT_XYM
12234 		    || *(blob + 6) == GAIA_TINYPOINT_XYZM)
12235 		    ;
12236 		else
12237 		    tiny_point = 0;
12238 		if (*(blob + (size - 1)) != GAIA_MARK_END)
12239 		    tiny_point = 0;
12240 	    }
12241 	  if (tiny_point)
12242 	    {
12243 		int endian_arch = gaiaEndianArch ();
12244 		int type = *(blob + 6);
12245 		int little_endian = 0;
12246 		int srid;
12247 		double x;
12248 		double y;
12249 		double z;
12250 		double m;
12251 		unsigned char *out;
12252 		int out_sz;
12253 		if (*(blob + 1) == GAIA_TINYPOINT_LITTLE_ENDIAN)
12254 		    little_endian = 1;
12255 		srid = gaiaImport32 (blob + 2, little_endian, endian_arch);
12256 		x = gaiaImport64 (blob + 7, little_endian, endian_arch);
12257 		y = gaiaImport64 (blob + 15, little_endian, endian_arch);
12258 		switch (type)
12259 		  {
12260 		  case GAIA_TINYPOINT_XY:
12261 		      gaiaMakePointEx (0, x, y, srid, &out, &out_sz);
12262 		      break;
12263 		  case GAIA_TINYPOINT_XYZ:
12264 		      z = gaiaImport64 (blob + 23, little_endian, endian_arch);
12265 		      gaiaMakePointZEx (0, x, y, z, srid, &out, &out_sz);
12266 		      break;
12267 		  case GAIA_TINYPOINT_XYM:
12268 		      m = gaiaImport64 (blob + 23, little_endian, endian_arch);
12269 		      gaiaMakePointMEx (0, x, y, m, srid, &out, &out_sz);
12270 		      break;
12271 		  case GAIA_TINYPOINT_XYZM:
12272 		      z = gaiaImport64 (blob + 23, little_endian, endian_arch);
12273 		      m = gaiaImport64 (blob + 31, little_endian, endian_arch);
12274 		      gaiaMakePointZMEx (0, x, y, z, m, srid, &out, &out_sz);
12275 		      break;
12276 		  };
12277 		sqlite3_result_blob (context, out, out_sz, free);
12278 	    }
12279 	  else
12280 	      sqlite3_result_blob (context, blob, size, SQLITE_TRANSIENT);
12281       }
12282     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12283 	sqlite3_result_int (context, sqlite3_value_int (argv[0]));
12284     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12285 	sqlite3_result_double (context, sqlite3_value_double (argv[0]));
12286     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
12287 	sqlite3_result_text (context,
12288 			     (const char *) sqlite3_value_text (argv[0]),
12289 			     sqlite3_value_bytes (argv[0]), SQLITE_TRANSIENT);
12290     else
12291 	sqlite3_result_null (context);
12292 }
12293 
12294 static void
fnct_MakePoint1(sqlite3_context * context,int argc,sqlite3_value ** argv)12295 fnct_MakePoint1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12296 {
12297 /* SQL function:
12298 / MakePoint(double X, double Y)
12299 /    alias
12300 / ST_Point(double X, double Y)
12301 /
12302 / builds a POINT
12303 / or NULL if any error is encountered
12304 */
12305     int len;
12306     int int_value;
12307     unsigned char *p_result = NULL;
12308     double x;
12309     double y;
12310     int tiny_point = 0;
12311     struct splite_internal_cache *cache = sqlite3_user_data (context);
12312     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12313     if (cache != NULL)
12314 	tiny_point = cache->tinyPointEnabled;
12315     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12316 	x = sqlite3_value_double (argv[0]);
12317     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12318       {
12319 	  int_value = sqlite3_value_int (argv[0]);
12320 	  x = int_value;
12321       }
12322     else
12323       {
12324 	  sqlite3_result_null (context);
12325 	  return;
12326       }
12327     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12328 	y = sqlite3_value_double (argv[1]);
12329     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12330       {
12331 	  int_value = sqlite3_value_int (argv[1]);
12332 	  y = int_value;
12333       }
12334     else
12335       {
12336 	  sqlite3_result_null (context);
12337 	  return;
12338       }
12339     gaiaMakePointEx (tiny_point, x, y, 0, &p_result, &len);
12340     if (!p_result)
12341 	sqlite3_result_null (context);
12342     else
12343 	sqlite3_result_blob (context, p_result, len, free);
12344 }
12345 
12346 static void
fnct_MakePoint2(sqlite3_context * context,int argc,sqlite3_value ** argv)12347 fnct_MakePoint2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12348 {
12349 /* SQL function:
12350 / MakePoint(double X, double Y, int SRID)
12351 /
12352 / builds a POINT
12353 / or NULL if any error is encountered
12354 */
12355     int len;
12356     int int_value;
12357     unsigned char *p_result = NULL;
12358     double x;
12359     double y;
12360     int srid;
12361     int tiny_point = 0;
12362     struct splite_internal_cache *cache = sqlite3_user_data (context);
12363     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12364     if (cache != NULL)
12365 	tiny_point = cache->tinyPointEnabled;
12366     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12367 	x = sqlite3_value_double (argv[0]);
12368     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12369       {
12370 	  int_value = sqlite3_value_int (argv[0]);
12371 	  x = int_value;
12372       }
12373     else
12374       {
12375 	  sqlite3_result_null (context);
12376 	  return;
12377       }
12378     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12379 	y = sqlite3_value_double (argv[1]);
12380     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12381       {
12382 	  int_value = sqlite3_value_int (argv[1]);
12383 	  y = int_value;
12384       }
12385     else
12386       {
12387 	  sqlite3_result_null (context);
12388 	  return;
12389       }
12390     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12391 	srid = sqlite3_value_int (argv[2]);
12392     else
12393       {
12394 	  sqlite3_result_null (context);
12395 	  return;
12396       }
12397     gaiaMakePointEx (tiny_point, x, y, srid, &p_result, &len);
12398     if (!p_result)
12399 	sqlite3_result_null (context);
12400     else
12401 	sqlite3_result_blob (context, p_result, len, free);
12402 }
12403 
12404 static void
fnct_MakePointZ1(sqlite3_context * context,int argc,sqlite3_value ** argv)12405 fnct_MakePointZ1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12406 {
12407 /* SQL function:
12408 / MakePointZ(double X, double Y, double Z)
12409 /
12410 / builds a POINT Z
12411 / or NULL if any error is encountered
12412 */
12413     int len;
12414     int int_value;
12415     unsigned char *p_result = NULL;
12416     double x;
12417     double y;
12418     double z;
12419     int tiny_point = 0;
12420     struct splite_internal_cache *cache = sqlite3_user_data (context);
12421     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12422     if (cache != NULL)
12423 	tiny_point = cache->tinyPointEnabled;
12424     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12425 	x = sqlite3_value_double (argv[0]);
12426     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12427       {
12428 	  int_value = sqlite3_value_int (argv[0]);
12429 	  x = int_value;
12430       }
12431     else
12432       {
12433 	  sqlite3_result_null (context);
12434 	  return;
12435       }
12436     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12437 	y = sqlite3_value_double (argv[1]);
12438     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12439       {
12440 	  int_value = sqlite3_value_int (argv[1]);
12441 	  y = int_value;
12442       }
12443     else
12444       {
12445 	  sqlite3_result_null (context);
12446 	  return;
12447       }
12448     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12449 	z = sqlite3_value_double (argv[2]);
12450     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12451       {
12452 	  int_value = sqlite3_value_int (argv[2]);
12453 	  z = int_value;
12454       }
12455     else
12456       {
12457 	  sqlite3_result_null (context);
12458 	  return;
12459       }
12460     gaiaMakePointZEx (tiny_point, x, y, z, 0, &p_result, &len);
12461     if (!p_result)
12462 	sqlite3_result_null (context);
12463     else
12464 	sqlite3_result_blob (context, p_result, len, free);
12465 }
12466 
12467 static void
fnct_MakePointZ2(sqlite3_context * context,int argc,sqlite3_value ** argv)12468 fnct_MakePointZ2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12469 {
12470 /* SQL function:
12471 / MakePointZ(double X, double Y, double Z, int SRID)
12472 /
12473 / builds a POINT Z
12474 / or NULL if any error is encountered
12475 */
12476     int len;
12477     int int_value;
12478     unsigned char *p_result = NULL;
12479     double x;
12480     double y;
12481     double z;
12482     int srid;
12483     int tiny_point = 0;
12484     struct splite_internal_cache *cache = sqlite3_user_data (context);
12485     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12486     if (cache != NULL)
12487 	tiny_point = cache->tinyPointEnabled;
12488     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12489 	x = sqlite3_value_double (argv[0]);
12490     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12491       {
12492 	  int_value = sqlite3_value_int (argv[0]);
12493 	  x = int_value;
12494       }
12495     else
12496       {
12497 	  sqlite3_result_null (context);
12498 	  return;
12499       }
12500     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12501 	y = sqlite3_value_double (argv[1]);
12502     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12503       {
12504 	  int_value = sqlite3_value_int (argv[1]);
12505 	  y = int_value;
12506       }
12507     else
12508       {
12509 	  sqlite3_result_null (context);
12510 	  return;
12511       }
12512     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12513 	z = sqlite3_value_double (argv[2]);
12514     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12515       {
12516 	  int_value = sqlite3_value_int (argv[2]);
12517 	  z = int_value;
12518       }
12519     else
12520       {
12521 	  sqlite3_result_null (context);
12522 	  return;
12523       }
12524     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
12525 	srid = sqlite3_value_int (argv[3]);
12526     else
12527       {
12528 	  sqlite3_result_null (context);
12529 	  return;
12530       }
12531     gaiaMakePointZEx (tiny_point, x, y, z, srid, &p_result, &len);
12532     if (!p_result)
12533 	sqlite3_result_null (context);
12534     else
12535 	sqlite3_result_blob (context, p_result, len, free);
12536 }
12537 
12538 static void
fnct_MakePointM1(sqlite3_context * context,int argc,sqlite3_value ** argv)12539 fnct_MakePointM1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12540 {
12541 /* SQL function:
12542 / MakePointM(double X, double Y, double M)
12543 /
12544 / builds a POINT M
12545 / or NULL if any error is encountered
12546 */
12547     int len;
12548     int int_value;
12549     unsigned char *p_result = NULL;
12550     double x;
12551     double y;
12552     double m;
12553     int tiny_point = 0;
12554     struct splite_internal_cache *cache = sqlite3_user_data (context);
12555     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12556     if (cache != NULL)
12557 	tiny_point = cache->tinyPointEnabled;
12558     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12559 	x = sqlite3_value_double (argv[0]);
12560     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12561       {
12562 	  int_value = sqlite3_value_int (argv[0]);
12563 	  x = int_value;
12564       }
12565     else
12566       {
12567 	  sqlite3_result_null (context);
12568 	  return;
12569       }
12570     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12571 	y = sqlite3_value_double (argv[1]);
12572     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12573       {
12574 	  int_value = sqlite3_value_int (argv[1]);
12575 	  y = int_value;
12576       }
12577     else
12578       {
12579 	  sqlite3_result_null (context);
12580 	  return;
12581       }
12582     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12583 	m = sqlite3_value_double (argv[2]);
12584     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12585       {
12586 	  int_value = sqlite3_value_int (argv[2]);
12587 	  m = int_value;
12588       }
12589     else
12590       {
12591 	  sqlite3_result_null (context);
12592 	  return;
12593       }
12594     gaiaMakePointMEx (tiny_point, x, y, m, 0, &p_result, &len);
12595     if (!p_result)
12596 	sqlite3_result_null (context);
12597     else
12598 	sqlite3_result_blob (context, p_result, len, free);
12599 }
12600 
12601 static void
fnct_MakePointM2(sqlite3_context * context,int argc,sqlite3_value ** argv)12602 fnct_MakePointM2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12603 {
12604 /* SQL function:
12605 / MakePointM(double X, double Y, double M, int SRID)
12606 /
12607 / builds a POINT M
12608 / or NULL if any error is encountered
12609 */
12610     int len;
12611     int int_value;
12612     unsigned char *p_result = NULL;
12613     double x;
12614     double y;
12615     double m;
12616     int srid;
12617     int tiny_point = 0;
12618     struct splite_internal_cache *cache = sqlite3_user_data (context);
12619     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12620     if (cache != NULL)
12621 	tiny_point = cache->tinyPointEnabled;
12622     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12623 	x = sqlite3_value_double (argv[0]);
12624     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12625       {
12626 	  int_value = sqlite3_value_int (argv[0]);
12627 	  x = int_value;
12628       }
12629     else
12630       {
12631 	  sqlite3_result_null (context);
12632 	  return;
12633       }
12634     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12635 	y = sqlite3_value_double (argv[1]);
12636     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12637       {
12638 	  int_value = sqlite3_value_int (argv[1]);
12639 	  y = int_value;
12640       }
12641     else
12642       {
12643 	  sqlite3_result_null (context);
12644 	  return;
12645       }
12646     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12647 	m = sqlite3_value_double (argv[2]);
12648     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12649       {
12650 	  int_value = sqlite3_value_int (argv[2]);
12651 	  m = int_value;
12652       }
12653     else
12654       {
12655 	  sqlite3_result_null (context);
12656 	  return;
12657       }
12658     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
12659 	srid = sqlite3_value_int (argv[3]);
12660     else
12661       {
12662 	  sqlite3_result_null (context);
12663 	  return;
12664       }
12665     gaiaMakePointMEx (tiny_point, x, y, m, srid, &p_result, &len);
12666     if (!p_result)
12667 	sqlite3_result_null (context);
12668     else
12669 	sqlite3_result_blob (context, p_result, len, free);
12670 }
12671 
12672 static void
fnct_MakePointZM1(sqlite3_context * context,int argc,sqlite3_value ** argv)12673 fnct_MakePointZM1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12674 {
12675 /* SQL function:
12676 / MakePointZM(double X, double Y, double Z, double M)
12677 /
12678 / builds a POINT ZM
12679 / or NULL if any error is encountered
12680 */
12681     int len;
12682     int int_value;
12683     unsigned char *p_result = NULL;
12684     double x;
12685     double y;
12686     double z;
12687     double m;
12688     int tiny_point = 0;
12689     struct splite_internal_cache *cache = sqlite3_user_data (context);
12690     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12691     if (cache != NULL)
12692 	tiny_point = cache->tinyPointEnabled;
12693     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12694 	x = sqlite3_value_double (argv[0]);
12695     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12696       {
12697 	  int_value = sqlite3_value_int (argv[0]);
12698 	  x = int_value;
12699       }
12700     else
12701       {
12702 	  sqlite3_result_null (context);
12703 	  return;
12704       }
12705     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12706 	y = sqlite3_value_double (argv[1]);
12707     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12708       {
12709 	  int_value = sqlite3_value_int (argv[1]);
12710 	  y = int_value;
12711       }
12712     else
12713       {
12714 	  sqlite3_result_null (context);
12715 	  return;
12716       }
12717     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12718 	z = sqlite3_value_double (argv[2]);
12719     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12720       {
12721 	  int_value = sqlite3_value_int (argv[2]);
12722 	  z = int_value;
12723       }
12724     else
12725       {
12726 	  sqlite3_result_null (context);
12727 	  return;
12728       }
12729     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
12730 	m = sqlite3_value_double (argv[3]);
12731     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
12732       {
12733 	  int_value = sqlite3_value_int (argv[3]);
12734 	  m = int_value;
12735       }
12736     else
12737       {
12738 	  sqlite3_result_null (context);
12739 	  return;
12740       }
12741     gaiaMakePointZMEx (tiny_point, x, y, z, m, 0, &p_result, &len);
12742     if (!p_result)
12743 	sqlite3_result_null (context);
12744     else
12745 	sqlite3_result_blob (context, p_result, len, free);
12746 }
12747 
12748 static void
fnct_MakePointZM2(sqlite3_context * context,int argc,sqlite3_value ** argv)12749 fnct_MakePointZM2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
12750 {
12751 /* SQL function:
12752 / MakePointZM(double X, double Y, double Z, double M, int SRID)
12753 /
12754 / builds a POINT
12755 / or NULL if any error is encountered
12756 */
12757     int len;
12758     int int_value;
12759     unsigned char *p_result = NULL;
12760     double x;
12761     double y;
12762     double z;
12763     double m;
12764     int srid;
12765     int tiny_point = 0;
12766     struct splite_internal_cache *cache = sqlite3_user_data (context);
12767     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12768     if (cache != NULL)
12769 	tiny_point = cache->tinyPointEnabled;
12770     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
12771 	x = sqlite3_value_double (argv[0]);
12772     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
12773       {
12774 	  int_value = sqlite3_value_int (argv[0]);
12775 	  x = int_value;
12776       }
12777     else
12778       {
12779 	  sqlite3_result_null (context);
12780 	  return;
12781       }
12782     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
12783 	y = sqlite3_value_double (argv[1]);
12784     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
12785       {
12786 	  int_value = sqlite3_value_int (argv[1]);
12787 	  y = int_value;
12788       }
12789     else
12790       {
12791 	  sqlite3_result_null (context);
12792 	  return;
12793       }
12794     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
12795 	z = sqlite3_value_double (argv[2]);
12796     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
12797       {
12798 	  int_value = sqlite3_value_int (argv[2]);
12799 	  z = int_value;
12800       }
12801     else
12802       {
12803 	  sqlite3_result_null (context);
12804 	  return;
12805       }
12806     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
12807 	m = sqlite3_value_double (argv[3]);
12808     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
12809       {
12810 	  int_value = sqlite3_value_int (argv[3]);
12811 	  m = int_value;
12812       }
12813     else
12814       {
12815 	  sqlite3_result_null (context);
12816 	  return;
12817       }
12818     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
12819 	srid = sqlite3_value_int (argv[4]);
12820     else
12821       {
12822 	  sqlite3_result_null (context);
12823 	  return;
12824       }
12825     gaiaMakePointZMEx (tiny_point, x, y, z, m, srid, &p_result, &len);
12826     if (!p_result)
12827 	sqlite3_result_null (context);
12828     else
12829 	sqlite3_result_blob (context, p_result, len, free);
12830 }
12831 
12832 static void
addGeomPointToDynamicLine(gaiaDynamicLinePtr dyn,gaiaGeomCollPtr geom)12833 addGeomPointToDynamicLine (gaiaDynamicLinePtr dyn, gaiaGeomCollPtr geom)
12834 {
12835 /* appending a simple-Point Geometry to a Dynamic Line */
12836     int pts;
12837     int lns;
12838     int pgs;
12839     gaiaPointPtr pt;
12840     gaiaLinestringPtr ln;
12841     gaiaPolygonPtr pg;
12842 
12843     if (dyn == NULL)
12844 	return;
12845     if (dyn->Error)
12846 	return;
12847 /* checking if GEOM simply is a POINT */
12848     if (geom == NULL)
12849       {
12850 	  dyn->Error = 1;
12851 	  return;
12852       }
12853     pts = 0;
12854     lns = 0;
12855     pgs = 0;
12856     pt = geom->FirstPoint;
12857     while (pt)
12858       {
12859 	  pts++;
12860 	  pt = pt->Next;
12861       }
12862     ln = geom->FirstLinestring;
12863     while (ln)
12864       {
12865 	  lns++;
12866 	  ln = ln->Next;
12867       }
12868     pg = geom->FirstPolygon;
12869     while (pg)
12870       {
12871 	  pgs++;
12872 	  pg = pg->Next;
12873       }
12874     if (pts == 1 && lns == 0 && pgs == 0)
12875 	;
12876     else
12877       {
12878 	  /* failure: not a simple POINT */
12879 	  dyn->Error = 1;
12880 	  return;
12881       }
12882 
12883     if (dyn->Srid != geom->Srid)
12884       {
12885 	  /* failure: SRID mismatch */
12886 	  dyn->Error = 1;
12887 	  return;
12888       }
12889 
12890     switch (geom->FirstPoint->DimensionModel)
12891       {
12892       case GAIA_XY_Z_M:
12893 	  gaiaAppendPointZMToDynamicLine (dyn, geom->FirstPoint->X,
12894 					  geom->FirstPoint->Y,
12895 					  geom->FirstPoint->Z,
12896 					  geom->FirstPoint->M);
12897 	  break;
12898       case GAIA_XY_Z:
12899 	  gaiaAppendPointZToDynamicLine (dyn, geom->FirstPoint->X,
12900 					 geom->FirstPoint->Y,
12901 					 geom->FirstPoint->Z);
12902 	  break;
12903       case GAIA_XY_M:
12904 	  gaiaAppendPointMToDynamicLine (dyn, geom->FirstPoint->X,
12905 					 geom->FirstPoint->Y,
12906 					 geom->FirstPoint->M);
12907 	  break;
12908       default:
12909 	  gaiaAppendPointToDynamicLine (dyn, geom->FirstPoint->X,
12910 					geom->FirstPoint->Y);
12911 	  break;
12912       }
12913 }
12914 
12915 static void
fnct_MakeLine_step(sqlite3_context * context,int argc,sqlite3_value ** argv)12916 fnct_MakeLine_step (sqlite3_context * context, int argc, sqlite3_value ** argv)
12917 {
12918 /* SQL function:
12919 / MakeLine(BLOBencoded geom)
12920 /
12921 / aggregate function - STEP
12922 /
12923 */
12924     unsigned char *p_blob;
12925     int n_bytes;
12926     gaiaGeomCollPtr geom;
12927     gaiaDynamicLinePtr *p;
12928     int gpkg_amphibious = 0;
12929     int gpkg_mode = 0;
12930     struct splite_internal_cache *cache = sqlite3_user_data (context);
12931     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
12932     if (cache != NULL)
12933       {
12934 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
12935 	  gpkg_mode = cache->gpkg_mode;
12936       }
12937     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
12938       {
12939 	  sqlite3_result_null (context);
12940 	  return;
12941       }
12942     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
12943     n_bytes = sqlite3_value_bytes (argv[0]);
12944     geom =
12945 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
12946 				     gpkg_amphibious);
12947     if (!geom)
12948 	return;
12949     p = sqlite3_aggregate_context (context, sizeof (gaiaDynamicLinePtr));
12950     if (!(*p))
12951       {
12952 	  /* this is the first row */
12953 	  *p = gaiaAllocDynamicLine ();
12954 	  (*p)->Srid = geom->Srid;
12955 	  addGeomPointToDynamicLine (*p, geom);
12956 	  gaiaFreeGeomColl (geom);
12957       }
12958     else
12959       {
12960 	  /* subsequent rows */
12961 	  addGeomPointToDynamicLine (*p, geom);
12962 	  gaiaFreeGeomColl (geom);
12963       }
12964 }
12965 
12966 static gaiaGeomCollPtr
geomFromDynamicLine(gaiaDynamicLinePtr dyn)12967 geomFromDynamicLine (gaiaDynamicLinePtr dyn)
12968 {
12969 /* attempting to build a Geometry from a Dynamic Line */
12970     gaiaGeomCollPtr geom = NULL;
12971     gaiaLinestringPtr ln = NULL;
12972     gaiaPointPtr pt;
12973     int iv;
12974     int count = 0;
12975     int dims = GAIA_XY;
12976 
12977     if (dyn == NULL)
12978 	return NULL;
12979     if (dyn->Error)
12980 	return NULL;
12981 
12982     pt = dyn->First;
12983     while (pt)
12984       {
12985 	  /* counting points and checking dims */
12986 	  count++;
12987 	  if (dims == GAIA_XY && pt->DimensionModel != GAIA_XY)
12988 	      dims = pt->DimensionModel;
12989 	  if (dims == GAIA_XY_Z
12990 	      && (pt->DimensionModel == GAIA_XY_M
12991 		  || pt->DimensionModel == GAIA_XY_Z_M))
12992 	      dims = GAIA_XY_Z_M;
12993 	  if (dims == GAIA_XY_M
12994 	      && (pt->DimensionModel == GAIA_XY_Z
12995 		  || pt->DimensionModel == GAIA_XY_Z_M))
12996 	      dims = GAIA_XY_Z_M;
12997 	  pt = pt->Next;
12998       }
12999     if (count < 2)
13000 	return NULL;
13001 
13002     switch (dims)
13003       {
13004       case GAIA_XY_Z_M:
13005 	  geom = gaiaAllocGeomCollXYZM ();
13006 	  ln = gaiaAllocLinestringXYZM (count);
13007 	  break;
13008       case GAIA_XY_Z:
13009 	  geom = gaiaAllocGeomCollXYZ ();
13010 	  ln = gaiaAllocLinestringXYZ (count);
13011 	  break;
13012       case GAIA_XY_M:
13013 	  geom = gaiaAllocGeomCollXYM ();
13014 	  ln = gaiaAllocLinestringXYM (count);
13015 	  break;
13016       default:
13017 	  geom = gaiaAllocGeomColl ();
13018 	  ln = gaiaAllocLinestring (count);
13019 	  break;
13020       };
13021 
13022     if (geom != NULL && ln != NULL)
13023       {
13024 	  gaiaInsertLinestringInGeomColl (geom, ln);
13025 	  geom->Srid = dyn->Srid;
13026       }
13027     else
13028       {
13029 	  if (geom)
13030 	      gaiaFreeGeomColl (geom);
13031 	  if (ln)
13032 	      gaiaFreeLinestring (ln);
13033 	  return NULL;
13034       }
13035 
13036     iv = 0;
13037     pt = dyn->First;
13038     while (pt)
13039       {
13040 	  /* setting linestring points */
13041 	  if (dims == GAIA_XY_Z_M)
13042 	    {
13043 		gaiaSetPointXYZM (ln->Coords, iv, pt->X, pt->Y, pt->Z, pt->M);
13044 	    }
13045 	  else if (dims == GAIA_XY_Z)
13046 	    {
13047 		gaiaSetPointXYZ (ln->Coords, iv, pt->X, pt->Y, pt->Z);
13048 	    }
13049 	  else if (dims == GAIA_XY_M)
13050 	    {
13051 		gaiaSetPointXYM (ln->Coords, iv, pt->X, pt->Y, pt->M);
13052 	    }
13053 	  else
13054 	    {
13055 		gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y);
13056 	    }
13057 	  iv++;
13058 	  pt = pt->Next;
13059       }
13060     return geom;
13061 }
13062 
13063 static void
fnct_MakeLine_final(sqlite3_context * context)13064 fnct_MakeLine_final (sqlite3_context * context)
13065 {
13066 /* SQL function:
13067 / MakeLine(BLOBencoded geom)
13068 /
13069 / aggregate function - FINAL
13070 /
13071 */
13072     gaiaGeomCollPtr result;
13073     gaiaDynamicLinePtr *p = sqlite3_aggregate_context (context, 0);
13074     int gpkg_mode = 0;
13075     int tiny_point = 0;
13076     struct splite_internal_cache *cache = sqlite3_user_data (context);
13077     if (cache != NULL)
13078       {
13079 	  gpkg_mode = cache->gpkg_mode;
13080 	  tiny_point = cache->tinyPointEnabled;
13081       }
13082     if (!p)
13083       {
13084 	  sqlite3_result_null (context);
13085 	  return;
13086       }
13087     result = geomFromDynamicLine (*p);
13088     gaiaFreeDynamicLine (*p);
13089     if (!result)
13090 	sqlite3_result_null (context);
13091     else
13092       {
13093 	  /* builds the BLOB geometry to be returned */
13094 	  int len;
13095 	  unsigned char *p_result = NULL;
13096 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
13097 				      tiny_point);
13098 	  sqlite3_result_blob (context, p_result, len, free);
13099 	  gaiaFreeGeomColl (result);
13100       }
13101 }
13102 
13103 static void
buildLineFromMultiPoint(sqlite3_context * context,gaiaGeomCollPtr geom,int direction)13104 buildLineFromMultiPoint (sqlite3_context * context, gaiaGeomCollPtr geom,
13105 			 int direction)
13106 {
13107 /* internal: building a Linestring from a MultiPolygon */
13108     gaiaGeomCollPtr result;
13109     gaiaDynamicLinePtr dyn;
13110     int n_pts = 0;
13111     int n_lns = 0;
13112     int n_pgs = 0;
13113     gaiaPointPtr pt;
13114     gaiaLinestringPtr ln;
13115     gaiaPolygonPtr pg;
13116     int gpkg_mode = 0;
13117     int tiny_point = 0;
13118     struct splite_internal_cache *cache = sqlite3_user_data (context);
13119     if (cache != NULL)
13120       {
13121 	  gpkg_mode = cache->gpkg_mode;
13122 	  tiny_point = cache->tinyPointEnabled;
13123       }
13124     if (geom)
13125       {
13126 	  pt = geom->FirstPoint;
13127 	  while (pt)
13128 	    {
13129 		n_pts++;
13130 		pt = pt->Next;
13131 	    }
13132 	  ln = geom->FirstLinestring;
13133 	  while (ln)
13134 	    {
13135 		n_lns++;
13136 		ln = ln->Next;
13137 	    }
13138 	  pg = geom->FirstPolygon;
13139 	  while (pg)
13140 	    {
13141 		n_pgs++;
13142 		pg = pg->Next;
13143 	    }
13144       }
13145     /* checking if really is a MultiPoint */
13146     if (n_pts >= 2 && n_lns == 0 && n_pgs == 0)
13147 	;
13148     else
13149       {
13150 	  sqlite3_result_null (context);
13151 	  goto end;
13152       }
13153     dyn = gaiaAllocDynamicLine ();
13154     dyn->Srid = geom->Srid;
13155     pt = geom->FirstPoint;
13156     while (pt)
13157       {
13158 	  /* inserting all Points accordingly to required direction */
13159 	  if (direction)
13160 	    {
13161 		/* conformant direction */
13162 		switch (pt->DimensionModel)
13163 		  {
13164 		  case GAIA_XY_Z_M:
13165 		      gaiaAppendPointZMToDynamicLine (dyn, pt->X, pt->Y,
13166 						      pt->Z, pt->M);
13167 		      break;
13168 		  case GAIA_XY_Z:
13169 		      gaiaAppendPointZToDynamicLine (dyn, pt->X, pt->Y, pt->Z);
13170 		      break;
13171 		  case GAIA_XY_M:
13172 		      gaiaAppendPointMToDynamicLine (dyn, pt->X, pt->Y, pt->M);
13173 		      break;
13174 		  default:
13175 		      gaiaAppendPointToDynamicLine (dyn, pt->X, pt->Y);
13176 		      break;
13177 		  }
13178 	    }
13179 	  else
13180 	    {
13181 		/* reverse direction */
13182 		switch (pt->DimensionModel)
13183 		  {
13184 		  case GAIA_XY_Z_M:
13185 		      gaiaPrependPointZMToDynamicLine (dyn, pt->X, pt->Y,
13186 						       pt->Z, pt->M);
13187 		      break;
13188 		  case GAIA_XY_Z:
13189 		      gaiaPrependPointZToDynamicLine (dyn, pt->X, pt->Y, pt->Z);
13190 		      break;
13191 		  case GAIA_XY_M:
13192 		      gaiaPrependPointMToDynamicLine (dyn, pt->X, pt->Y, pt->M);
13193 		      break;
13194 		  default:
13195 		      gaiaPrependPointToDynamicLine (dyn, pt->X, pt->Y);
13196 		      break;
13197 		  }
13198 	    }
13199 	  pt = pt->Next;
13200       }
13201     result = geomFromDynamicLine (dyn);
13202     gaiaFreeDynamicLine (dyn);
13203     if (!result)
13204 	sqlite3_result_null (context);
13205     else
13206       {
13207 	  /* builds the BLOB geometry to be returned */
13208 	  int len;
13209 	  unsigned char *p_result = NULL;
13210 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
13211 				      tiny_point);
13212 	  sqlite3_result_blob (context, p_result, len, free);
13213 	  gaiaFreeGeomColl (result);
13214       }
13215   end:
13216     gaiaFreeGeomColl (geom);
13217 }
13218 
13219 static void
fnct_MakeLine(sqlite3_context * context,int argc,sqlite3_value ** argv)13220 fnct_MakeLine (sqlite3_context * context, int argc, sqlite3_value ** argv)
13221 {
13222 /* SQL function:
13223 / MakeLine(point-geometry geom1, point-geometry geom2)
13224 /     or
13225 / MakeLine(multipoint geom, boolean direction)
13226 /
13227 / - builds a SEGMENT joining two POINTs
13228 / - the MultiPoint version works exactely as the corresponding aggregate
13229 /   function, but not requiring aggregation; direction=TRUE direct order,
13230 /   direction=FALSE reverse order
13231 / - or NULL if any error is encountered
13232 */
13233     int len;
13234     unsigned char *p_blob;
13235     int n_bytes;
13236     unsigned char *p_result = NULL;
13237     gaiaGeomCollPtr geo1 = NULL;
13238     gaiaGeomCollPtr geo2 = NULL;
13239     int gpkg_amphibious = 0;
13240     int gpkg_mode = 0;
13241     struct splite_internal_cache *cache = sqlite3_user_data (context);
13242     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13243     if (cache != NULL)
13244       {
13245 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
13246 	  gpkg_mode = cache->gpkg_mode;
13247       }
13248     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
13249       {
13250 	  sqlite3_result_null (context);
13251 	  goto stop;
13252       }
13253     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
13254     n_bytes = sqlite3_value_bytes (argv[0]);
13255     geo1 =
13256 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
13257 				     gpkg_amphibious);
13258     if (!geo1)
13259       {
13260 	  sqlite3_result_null (context);
13261 	  goto stop;
13262       }
13263     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13264       {
13265 	  /* expecting a single MultiPoint input */
13266 	  int direction = sqlite3_value_int (argv[1]);
13267 	  buildLineFromMultiPoint (context, geo1, direction);
13268 	  return;
13269       }
13270     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
13271       {
13272 	  sqlite3_result_null (context);
13273 	  goto stop;
13274       }
13275     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
13276     n_bytes = sqlite3_value_bytes (argv[1]);
13277     geo2 =
13278 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
13279 				     gpkg_amphibious);
13280     if (!geo2)
13281       {
13282 	  sqlite3_result_null (context);
13283 	  goto stop;
13284       }
13285     gaiaMakeLine (geo1, geo2, &p_result, &len);
13286     if (!p_result)
13287 	sqlite3_result_null (context);
13288     else
13289 	sqlite3_result_blob (context, p_result, len, free);
13290   stop:
13291     if (geo1)
13292 	gaiaFreeGeomColl (geo1);
13293     if (geo2)
13294 	gaiaFreeGeomColl (geo2);
13295 }
13296 
13297 static void
fnct_MakeCircle(sqlite3_context * context,int argc,sqlite3_value ** argv)13298 fnct_MakeCircle (sqlite3_context * context, int argc, sqlite3_value ** argv)
13299 {
13300 /* SQL function:
13301 / MakeCircle(double cx, double cy, double radius)
13302 /     or
13303 / MakeCircle(double cx, double cy, double radius, int srid)
13304 /     or
13305 / MakeCircle(double cx, double cy, double radius, int srid, double step)
13306 /
13307 / - builds a Linestring approximating a Circle
13308 / - step is the angular distance (in degrees) between points on
13309 /   the circurmference (by default: every 10 degs)
13310 / - or NULL if any error is encountered
13311 */
13312     int len;
13313     unsigned char *p_result = NULL;
13314     gaiaGeomCollPtr geom = NULL;
13315     int ival;
13316     double cx;
13317     double cy;
13318     double r;
13319     int srid = 0;
13320     double step = 10.0;
13321     int gpkg_mode = 0;
13322     int tiny_point = 0;
13323     struct splite_internal_cache *cache = sqlite3_user_data (context);
13324     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13325     if (cache != NULL)
13326       {
13327 	  gpkg_mode = cache->gpkg_mode;
13328 	  tiny_point = cache->tinyPointEnabled;
13329       }
13330     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
13331       {
13332 	  ival = sqlite3_value_int (argv[0]);
13333 	  cx = ival;
13334       }
13335     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
13336 	cx = sqlite3_value_double (argv[0]);
13337     else
13338       {
13339 	  sqlite3_result_null (context);
13340 	  return;
13341       }
13342     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13343       {
13344 	  ival = sqlite3_value_int (argv[1]);
13345 	  cy = ival;
13346       }
13347     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
13348 	cy = sqlite3_value_double (argv[1]);
13349     else
13350       {
13351 	  sqlite3_result_null (context);
13352 	  return;
13353       }
13354     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
13355       {
13356 	  ival = sqlite3_value_int (argv[2]);
13357 	  r = ival;
13358       }
13359     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
13360 	r = sqlite3_value_double (argv[2]);
13361     else
13362       {
13363 	  sqlite3_result_null (context);
13364 	  return;
13365       }
13366     if (argc >= 4)
13367       {
13368 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
13369 	      srid = sqlite3_value_int (argv[3]);
13370 	  else
13371 	    {
13372 		sqlite3_result_null (context);
13373 		return;
13374 	    }
13375       }
13376     if (argc == 5)
13377       {
13378 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
13379 	    {
13380 		ival = sqlite3_value_int (argv[4]);
13381 		step = ival;
13382 	    }
13383 	  else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
13384 	      step = sqlite3_value_double (argv[4]);
13385 	  else
13386 	    {
13387 		sqlite3_result_null (context);
13388 		return;
13389 	    }
13390       }
13391 
13392     geom = gaiaMakeCircle (cx, cy, r, step);
13393     if (!geom)
13394 	sqlite3_result_null (context);
13395     else
13396       {
13397 	  if (srid != 0)
13398 	      geom->Srid = srid;
13399 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode,
13400 				      tiny_point);
13401 	  sqlite3_result_blob (context, p_result, len, free);
13402       }
13403     if (geom)
13404 	gaiaFreeGeomColl (geom);
13405 }
13406 
13407 static void
fnct_MakeArc(sqlite3_context * context,int argc,sqlite3_value ** argv)13408 fnct_MakeArc (sqlite3_context * context, int argc, sqlite3_value ** argv)
13409 {
13410 /* SQL function:
13411 / MakeArc(double cx, double cy, double radius, double start, double stop)
13412 /     or
13413 / MakeArc(double cx, double cy, double radius, double start, double stop,
13414 /         int srid)
13415 /     or
13416 / MakeArc(double cx, double cy, double radius, double start, double stop,
13417 /         int srid, double step)
13418 /
13419 / - builds a Linestring approximating a Circular Arc
13420 / - start and stop are the initial and final angles (in degrees)
13421 / - step is the angular distance (in degrees) between points on
13422 /   the circurmference (by default: every 10 degs)
13423 / - or NULL if any error is encountered
13424 */
13425     int len;
13426     unsigned char *p_result = NULL;
13427     gaiaGeomCollPtr geom = NULL;
13428     int ival;
13429     double cx;
13430     double cy;
13431     double r;
13432     double start;
13433     double stop;
13434     int srid = 0;
13435     double step = 10.0;
13436     int gpkg_mode = 0;
13437     int tiny_point = 0;
13438     struct splite_internal_cache *cache = sqlite3_user_data (context);
13439     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13440     if (cache != NULL)
13441       {
13442 	  gpkg_mode = cache->gpkg_mode;
13443 	  tiny_point = cache->tinyPointEnabled;
13444       }
13445     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
13446       {
13447 	  ival = sqlite3_value_int (argv[0]);
13448 	  cx = ival;
13449       }
13450     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
13451 	cx = sqlite3_value_double (argv[0]);
13452     else
13453       {
13454 	  sqlite3_result_null (context);
13455 	  return;
13456       }
13457     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13458       {
13459 	  ival = sqlite3_value_int (argv[1]);
13460 	  cy = ival;
13461       }
13462     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
13463 	cy = sqlite3_value_double (argv[1]);
13464     else
13465       {
13466 	  sqlite3_result_null (context);
13467 	  return;
13468       }
13469     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
13470       {
13471 	  ival = sqlite3_value_int (argv[2]);
13472 	  r = ival;
13473       }
13474     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
13475 	r = sqlite3_value_double (argv[2]);
13476     else
13477       {
13478 	  sqlite3_result_null (context);
13479 	  return;
13480       }
13481     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
13482       {
13483 	  ival = sqlite3_value_int (argv[3]);
13484 	  start = ival;
13485       }
13486     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
13487 	start = sqlite3_value_double (argv[3]);
13488     else
13489       {
13490 	  sqlite3_result_null (context);
13491 	  return;
13492       }
13493     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
13494       {
13495 	  ival = sqlite3_value_int (argv[4]);
13496 	  stop = ival;
13497       }
13498     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
13499 	stop = sqlite3_value_double (argv[4]);
13500     else
13501       {
13502 	  sqlite3_result_null (context);
13503 	  return;
13504       }
13505     if (argc >= 6)
13506       {
13507 	  if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
13508 	      srid = sqlite3_value_int (argv[5]);
13509 	  else
13510 	    {
13511 		sqlite3_result_null (context);
13512 		return;
13513 	    }
13514       }
13515     if (argc == 7)
13516       {
13517 	  if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
13518 	    {
13519 		ival = sqlite3_value_int (argv[6]);
13520 		step = ival;
13521 	    }
13522 	  else if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
13523 	      step = sqlite3_value_double (argv[6]);
13524 	  else
13525 	    {
13526 		sqlite3_result_null (context);
13527 		return;
13528 	    }
13529       }
13530 
13531     geom = gaiaMakeArc (cx, cy, r, start, stop, step);
13532     if (!geom)
13533 	sqlite3_result_null (context);
13534     else
13535       {
13536 	  if (srid != 0)
13537 	      geom->Srid = srid;
13538 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode,
13539 				      tiny_point);
13540 	  sqlite3_result_blob (context, p_result, len, free);
13541       }
13542     if (geom)
13543 	gaiaFreeGeomColl (geom);
13544 }
13545 
13546 static void
fnct_MakeEllipse(sqlite3_context * context,int argc,sqlite3_value ** argv)13547 fnct_MakeEllipse (sqlite3_context * context, int argc, sqlite3_value ** argv)
13548 {
13549 /* SQL function:
13550 / MakeEllipse(double cx, double cy, double x_axis, double y_axis)
13551 /     or
13552 / MakeEllipse(double cx, double cy, double x_axis, double y_axis,
13553 /            int srid)
13554 /     or
13555 / MakeEllipse(double cx, double cy, double x_axis, double y_axis,
13556 /             int srid, double step)
13557 /
13558 / - builds a Linestring approximating an Ellipse
13559 / - step is the angular distance (in degrees) between points on
13560 /   the ellipse (by default: every 10 degs)
13561 / - or NULL if any error is encountered
13562 */
13563     int len;
13564     unsigned char *p_result = NULL;
13565     gaiaGeomCollPtr geom = NULL;
13566     int ival;
13567     double cx;
13568     double cy;
13569     double x_axis;
13570     double y_axis;
13571     int srid = 0;
13572     double step = 10.0;
13573     int gpkg_mode = 0;
13574     int tiny_point = 0;
13575     struct splite_internal_cache *cache = sqlite3_user_data (context);
13576     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13577     if (cache != NULL)
13578       {
13579 	  gpkg_mode = cache->gpkg_mode;
13580 	  tiny_point = cache->tinyPointEnabled;
13581       }
13582     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
13583       {
13584 	  ival = sqlite3_value_int (argv[0]);
13585 	  cx = ival;
13586       }
13587     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
13588 	cx = sqlite3_value_double (argv[0]);
13589     else
13590       {
13591 	  sqlite3_result_null (context);
13592 	  return;
13593       }
13594     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13595       {
13596 	  ival = sqlite3_value_int (argv[1]);
13597 	  cy = ival;
13598       }
13599     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
13600 	cy = sqlite3_value_double (argv[1]);
13601     else
13602       {
13603 	  sqlite3_result_null (context);
13604 	  return;
13605       }
13606     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
13607       {
13608 	  ival = sqlite3_value_int (argv[2]);
13609 	  x_axis = ival;
13610       }
13611     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
13612 	x_axis = sqlite3_value_double (argv[2]);
13613     else
13614       {
13615 	  sqlite3_result_null (context);
13616 	  return;
13617       }
13618     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
13619       {
13620 	  ival = sqlite3_value_int (argv[3]);
13621 	  y_axis = ival;
13622       }
13623     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
13624 	y_axis = sqlite3_value_double (argv[3]);
13625     else
13626       {
13627 	  sqlite3_result_null (context);
13628 	  return;
13629       }
13630     if (argc >= 5)
13631       {
13632 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
13633 	      srid = sqlite3_value_int (argv[4]);
13634 	  else
13635 	    {
13636 		sqlite3_result_null (context);
13637 		return;
13638 	    }
13639       }
13640     if (argc == 6)
13641       {
13642 	  if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
13643 	    {
13644 		ival = sqlite3_value_int (argv[5]);
13645 		step = ival;
13646 	    }
13647 	  else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
13648 	      step = sqlite3_value_double (argv[5]);
13649 	  else
13650 	    {
13651 		sqlite3_result_null (context);
13652 		return;
13653 	    }
13654       }
13655     geom = gaiaMakeEllipse (cx, cy, x_axis, y_axis, step);
13656     if (!geom)
13657 	sqlite3_result_null (context);
13658     else
13659       {
13660 	  if (srid != 0)
13661 	      geom->Srid = srid;
13662 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode,
13663 				      tiny_point);
13664 	  sqlite3_result_blob (context, p_result, len, free);
13665       }
13666     if (geom)
13667 	gaiaFreeGeomColl (geom);
13668 }
13669 
13670 static void
fnct_MakeEllipticArc(sqlite3_context * context,int argc,sqlite3_value ** argv)13671 fnct_MakeEllipticArc (sqlite3_context * context, int argc,
13672 		      sqlite3_value ** argv)
13673 {
13674 /* SQL function:
13675 / MakeEllipticArc(double cx, double cy, double x_axis, double y_axis,
13676 /                 double start, double stop)
13677 /     or
13678 / MakeEllipticArc(double cx, double cy, double x_axis, double y_axis,
13679 /                 double start, double stop, int srid)
13680 /     or
13681 / MakeEllipticArc(double cx, double cy, double x_axis, double y_axis,
13682 /                 double start, double stop, int srid, double step)
13683 /
13684 / - builds a Linestring approximating an Elliptic Arc
13685 / - start and stop are the initial and final angles (in degrees)
13686 / - step is the angular distance (in degrees) between points on
13687 /   the ellipse (by default: every 10 degs)
13688 / - or NULL if any error is encountered
13689 */
13690     int len;
13691     unsigned char *p_result = NULL;
13692     gaiaGeomCollPtr geom = NULL;
13693     int ival;
13694     double cx;
13695     double cy;
13696     double x_axis;
13697     double y_axis;
13698     double start;
13699     double stop;
13700     int srid = 0;
13701     double step = 10.0;
13702     int gpkg_mode = 0;
13703     int tiny_point = 0;
13704     struct splite_internal_cache *cache = sqlite3_user_data (context);
13705     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13706     if (cache != NULL)
13707       {
13708 	  gpkg_mode = cache->gpkg_mode;
13709 	  tiny_point = cache->tinyPointEnabled;
13710       }
13711     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
13712       {
13713 	  ival = sqlite3_value_int (argv[0]);
13714 	  cx = ival;
13715       }
13716     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
13717 	cx = sqlite3_value_double (argv[0]);
13718     else
13719       {
13720 	  sqlite3_result_null (context);
13721 	  return;
13722       }
13723     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13724       {
13725 	  ival = sqlite3_value_int (argv[1]);
13726 	  cy = ival;
13727       }
13728     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
13729 	cy = sqlite3_value_double (argv[1]);
13730     else
13731       {
13732 	  sqlite3_result_null (context);
13733 	  return;
13734       }
13735     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
13736       {
13737 	  ival = sqlite3_value_int (argv[2]);
13738 	  x_axis = ival;
13739       }
13740     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
13741 	x_axis = sqlite3_value_double (argv[2]);
13742     else
13743       {
13744 	  sqlite3_result_null (context);
13745 	  return;
13746       }
13747     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
13748       {
13749 	  ival = sqlite3_value_int (argv[3]);
13750 	  y_axis = ival;
13751       }
13752     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
13753 	y_axis = sqlite3_value_double (argv[3]);
13754     else
13755       {
13756 	  sqlite3_result_null (context);
13757 	  return;
13758       }
13759     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
13760       {
13761 	  ival = sqlite3_value_int (argv[4]);
13762 	  start = ival;
13763       }
13764     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
13765 	start = sqlite3_value_double (argv[4]);
13766     else
13767       {
13768 	  sqlite3_result_null (context);
13769 	  return;
13770       }
13771     if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
13772       {
13773 	  ival = sqlite3_value_int (argv[5]);
13774 	  stop = ival;
13775       }
13776     else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
13777 	stop = sqlite3_value_double (argv[5]);
13778     else
13779       {
13780 	  sqlite3_result_null (context);
13781 	  return;
13782       }
13783     if (argc >= 7)
13784       {
13785 	  if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
13786 	      srid = sqlite3_value_int (argv[6]);
13787 	  else
13788 	    {
13789 		sqlite3_result_null (context);
13790 		return;
13791 	    }
13792       }
13793     if (argc == 8)
13794       {
13795 	  if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
13796 	    {
13797 		ival = sqlite3_value_int (argv[7]);
13798 		step = ival;
13799 	    }
13800 	  else if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
13801 	      step = sqlite3_value_double (argv[7]);
13802 	  else
13803 	    {
13804 		sqlite3_result_null (context);
13805 		return;
13806 	    }
13807       }
13808 
13809     geom = gaiaMakeEllipticArc (cx, cy, x_axis, y_axis, start, stop, step);
13810     if (!geom)
13811 	sqlite3_result_null (context);
13812     else
13813       {
13814 	  if (srid != 0)
13815 	      geom->Srid = srid;
13816 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode,
13817 				      tiny_point);
13818 	  sqlite3_result_blob (context, p_result, len, free);
13819       }
13820     if (geom)
13821 	gaiaFreeGeomColl (geom);
13822 }
13823 
13824 static void
fnct_MakeCircularSector(sqlite3_context * context,int argc,sqlite3_value ** argv)13825 fnct_MakeCircularSector (sqlite3_context * context, int argc,
13826 			 sqlite3_value ** argv)
13827 {
13828 /* SQL function:
13829 / MakeCircularSector(double cx, double cy, double radius, double start, double stop)
13830 /     or
13831 / MakeCircularSector(double cx, double cy, double radius, double start, double stop,
13832 /         int srid)
13833 /     or
13834 / MakeCircularSector(double cx, double cy, double radius, double start, double stop,
13835 /         int srid, double step)
13836 /
13837 / - builds a Polygon approximating a Circular Sector
13838 / - start and stop are the initial and final angles (in degrees)
13839 / - step is the angular distance (in degrees) between points on
13840 /   the circurmference (by default: every 10 degs)
13841 / - or NULL if any error is encountered
13842 */
13843     int len;
13844     unsigned char *p_result = NULL;
13845     gaiaGeomCollPtr geom = NULL;
13846     gaiaGeomCollPtr sector = NULL;
13847     int ival;
13848     double cx;
13849     double cy;
13850     double r;
13851     double start;
13852     double stop;
13853     int srid = 0;
13854     double step = 10.0;
13855     int gpkg_mode = 0;
13856     int tiny_point = 0;
13857     struct splite_internal_cache *cache = sqlite3_user_data (context);
13858     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
13859     if (cache != NULL)
13860       {
13861 	  gpkg_mode = cache->gpkg_mode;
13862 	  tiny_point = cache->tinyPointEnabled;
13863       }
13864     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
13865       {
13866 	  ival = sqlite3_value_int (argv[0]);
13867 	  cx = ival;
13868       }
13869     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
13870 	cx = sqlite3_value_double (argv[0]);
13871     else
13872       {
13873 	  sqlite3_result_null (context);
13874 	  return;
13875       }
13876     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
13877       {
13878 	  ival = sqlite3_value_int (argv[1]);
13879 	  cy = ival;
13880       }
13881     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
13882 	cy = sqlite3_value_double (argv[1]);
13883     else
13884       {
13885 	  sqlite3_result_null (context);
13886 	  return;
13887       }
13888     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
13889       {
13890 	  ival = sqlite3_value_int (argv[2]);
13891 	  r = ival;
13892       }
13893     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
13894 	r = sqlite3_value_double (argv[2]);
13895     else
13896       {
13897 	  sqlite3_result_null (context);
13898 	  return;
13899       }
13900     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
13901       {
13902 	  ival = sqlite3_value_int (argv[3]);
13903 	  start = ival;
13904       }
13905     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
13906 	start = sqlite3_value_double (argv[3]);
13907     else
13908       {
13909 	  sqlite3_result_null (context);
13910 	  return;
13911       }
13912     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
13913       {
13914 	  ival = sqlite3_value_int (argv[4]);
13915 	  stop = ival;
13916       }
13917     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
13918 	stop = sqlite3_value_double (argv[4]);
13919     else
13920       {
13921 	  sqlite3_result_null (context);
13922 	  return;
13923       }
13924     if (argc >= 6)
13925       {
13926 	  if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
13927 	      srid = sqlite3_value_int (argv[5]);
13928 	  else
13929 	    {
13930 		sqlite3_result_null (context);
13931 		return;
13932 	    }
13933       }
13934     if (argc == 7)
13935       {
13936 	  if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
13937 	    {
13938 		ival = sqlite3_value_int (argv[6]);
13939 		step = ival;
13940 	    }
13941 	  else if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
13942 	      step = sqlite3_value_double (argv[6]);
13943 	  else
13944 	    {
13945 		sqlite3_result_null (context);
13946 		return;
13947 	    }
13948       }
13949 
13950     geom = gaiaMakeArc (cx, cy, r, start, stop, step);
13951     if (!geom)
13952 	sqlite3_result_null (context);
13953     else
13954       {
13955 	  int ii;
13956 	  int io = 0;
13957 	  double x;
13958 	  double y;
13959 	  gaiaLinestringPtr in = geom->FirstLinestring;
13960 	  gaiaPolygonPtr pg;
13961 	  gaiaRingPtr out;
13962 	  sector = gaiaAllocGeomColl ();
13963 	  pg = gaiaAddPolygonToGeomColl (sector, in->Points + 2, 0);
13964 	  out = pg->Exterior;
13965 	  /* inserting the Centre - first point */
13966 	  gaiaSetPoint (out->Coords, io, cx, cy);
13967 	  io++;
13968 	  for (ii = 0; ii < in->Points; ii++)
13969 	    {
13970 		/* copying the Arc's points */
13971 		gaiaGetPoint (in->Coords, ii, &x, &y);
13972 		gaiaSetPoint (out->Coords, io, x, y);
13973 		io++;
13974 	    }
13975 	  /* inserting the Centre - last point */
13976 	  gaiaSetPoint (out->Coords, io, cx, cy);
13977 	  if (srid != 0)
13978 	      sector->Srid = srid;
13979 	  gaiaToSpatiaLiteBlobWkbEx2 (sector, &p_result, &len, gpkg_mode,
13980 				      tiny_point);
13981 	  sqlite3_result_blob (context, p_result, len, free);
13982       }
13983     if (geom)
13984 	gaiaFreeGeomColl (geom);
13985     if (sector)
13986 	gaiaFreeGeomColl (sector);
13987 }
13988 
13989 static void
fnct_MakeCircularStripe(sqlite3_context * context,int argc,sqlite3_value ** argv)13990 fnct_MakeCircularStripe (sqlite3_context * context, int argc,
13991 			 sqlite3_value ** argv)
13992 {
13993 /* SQL function:
13994 / MakeCircularStripe(double cx, double cy, double radius_1, double radius_2,
13995 /                    double start, double stop)
13996 /     or
13997 / MakeCircularStripe(double cx, double cy, double radius_1, double radius_2,
13998 /                    double start, double stop, int srid)
13999 /     or
14000 / MakeCircularStripe(double cx, double cy, double radius_1, double radius_2,
14001 /                    double start, double stop, int srid, double step)
14002 /
14003 / - builds a Polygon approximating a Circular Stripe delimited by two
14004 /   arcs sharing the same Centre-Point but having different radii
14005 / - start and stop are the initial and final angles (in degrees)
14006 / - step is the angular distance (in degrees) between points on
14007 /   the circurmference (by default: every 10 degs)
14008 / - or NULL if any error is encountered
14009 */
14010     int len;
14011     unsigned char *p_result = NULL;
14012     gaiaGeomCollPtr arc1 = NULL;
14013     gaiaGeomCollPtr arc2 = NULL;
14014     gaiaGeomCollPtr stripe = NULL;
14015     int ival;
14016     double cx;
14017     double cy;
14018     double r1;
14019     double r2;
14020     double start;
14021     double stop;
14022     int srid = 0;
14023     double step = 10.0;
14024     int gpkg_mode = 0;
14025     int tiny_point = 0;
14026     struct splite_internal_cache *cache = sqlite3_user_data (context);
14027     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14028     if (cache != NULL)
14029       {
14030 	  gpkg_mode = cache->gpkg_mode;
14031 	  tiny_point = cache->tinyPointEnabled;
14032       }
14033     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
14034       {
14035 	  ival = sqlite3_value_int (argv[0]);
14036 	  cx = ival;
14037       }
14038     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
14039 	cx = sqlite3_value_double (argv[0]);
14040     else
14041       {
14042 	  sqlite3_result_null (context);
14043 	  return;
14044       }
14045     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
14046       {
14047 	  ival = sqlite3_value_int (argv[1]);
14048 	  cy = ival;
14049       }
14050     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
14051 	cy = sqlite3_value_double (argv[1]);
14052     else
14053       {
14054 	  sqlite3_result_null (context);
14055 	  return;
14056       }
14057     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
14058       {
14059 	  ival = sqlite3_value_int (argv[2]);
14060 	  r1 = ival;
14061       }
14062     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
14063 	r1 = sqlite3_value_double (argv[2]);
14064     else
14065       {
14066 	  sqlite3_result_null (context);
14067 	  return;
14068       }
14069     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
14070       {
14071 	  ival = sqlite3_value_int (argv[3]);
14072 	  r2 = ival;
14073       }
14074     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
14075 	r2 = sqlite3_value_double (argv[3]);
14076     else
14077       {
14078 	  sqlite3_result_null (context);
14079 	  return;
14080       }
14081     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
14082       {
14083 	  ival = sqlite3_value_int (argv[4]);
14084 	  start = ival;
14085       }
14086     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
14087 	start = sqlite3_value_double (argv[4]);
14088     else
14089       {
14090 	  sqlite3_result_null (context);
14091 	  return;
14092       }
14093     if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
14094       {
14095 	  ival = sqlite3_value_int (argv[5]);
14096 	  stop = ival;
14097       }
14098     else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
14099 	stop = sqlite3_value_double (argv[5]);
14100     else
14101       {
14102 	  sqlite3_result_null (context);
14103 	  return;
14104       }
14105     if (argc >= 7)
14106       {
14107 	  if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
14108 	      srid = sqlite3_value_int (argv[6]);
14109 	  else
14110 	    {
14111 		sqlite3_result_null (context);
14112 		return;
14113 	    }
14114       }
14115     if (argc == 8)
14116       {
14117 	  if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
14118 	    {
14119 		ival = sqlite3_value_int (argv[7]);
14120 		step = ival;
14121 	    }
14122 	  else if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
14123 	      step = sqlite3_value_double (argv[7]);
14124 	  else
14125 	    {
14126 		sqlite3_result_null (context);
14127 		return;
14128 	    }
14129       }
14130 
14131     arc1 = gaiaMakeArc (cx, cy, r1, start, stop, step);
14132     arc2 = gaiaMakeArc (cx, cy, r2, start, stop, step);
14133     if (arc1 == NULL || arc2 == NULL)
14134 	sqlite3_result_null (context);
14135     else
14136       {
14137 	  int ii;
14138 	  int io = 0;
14139 	  double x;
14140 	  double y;
14141 	  gaiaLinestringPtr in1 = arc1->FirstLinestring;
14142 	  gaiaLinestringPtr in2 = arc2->FirstLinestring;
14143 	  gaiaPolygonPtr pg;
14144 	  gaiaRingPtr out;
14145 	  stripe = gaiaAllocGeomColl ();
14146 	  pg = gaiaAddPolygonToGeomColl (stripe,
14147 					 in1->Points + in2->Points + 1, 0);
14148 	  out = pg->Exterior;
14149 	  for (ii = 0; ii < in1->Points; ii++)
14150 	    {
14151 		/* copying the first Arc's points - direct order */
14152 		gaiaGetPoint (in1->Coords, ii, &x, &y);
14153 		gaiaSetPoint (out->Coords, io, x, y);
14154 		io++;
14155 	    }
14156 	  for (ii = in2->Points - 1; ii >= 0; ii--)
14157 	    {
14158 		/* copying the second Arc's points - reverse order */
14159 		gaiaGetPoint (in2->Coords, ii, &x, &y);
14160 		gaiaSetPoint (out->Coords, io, x, y);
14161 		io++;
14162 	    }
14163 	  /* closing the Polygon Ring */
14164 	  gaiaGetPoint (out->Coords, 0, &x, &y);
14165 	  gaiaSetPoint (out->Coords, io, x, y);
14166 	  if (srid != 0)
14167 	      stripe->Srid = srid;
14168 	  gaiaToSpatiaLiteBlobWkbEx2 (stripe, &p_result, &len, gpkg_mode,
14169 				      tiny_point);
14170 	  sqlite3_result_blob (context, p_result, len, free);
14171       }
14172     if (arc1)
14173 	gaiaFreeGeomColl (arc1);
14174     if (arc2)
14175 	gaiaFreeGeomColl (arc2);
14176     if (stripe)
14177 	gaiaFreeGeomColl (stripe);
14178 }
14179 
14180 static void
fnct_MakeEllipticSector(sqlite3_context * context,int argc,sqlite3_value ** argv)14181 fnct_MakeEllipticSector (sqlite3_context * context, int argc,
14182 			 sqlite3_value ** argv)
14183 {
14184 /* SQL function:
14185 / MakeEllipticSector(double cx, double cy, double x_axis, double y_axis,
14186 /                 double start, double stop)
14187 /     or
14188 / MakeEllipticSector(double cx, double cy, double x_axis, double y_axis,
14189 /                 double start, double stop, int srid)
14190 /     or
14191 / MakeEllipticSector(double cx, double cy, double x_axis, double y_axis,
14192 /                 double start, double stop, int srid, double step)
14193 /
14194 / - builds a Polygon approximating an Elliptic Sector
14195 / - start and stop are the initial and final angles (in degrees)
14196 / - step is the angular distance (in degrees) between points on
14197 /   the ellipse (by default: every 10 degs)
14198 / - or NULL if any error is encountered
14199 */
14200     int len;
14201     unsigned char *p_result = NULL;
14202     gaiaGeomCollPtr geom = NULL;
14203     gaiaGeomCollPtr sector = NULL;
14204     int ival;
14205     double cx;
14206     double cy;
14207     double x_axis;
14208     double y_axis;
14209     double start;
14210     double stop;
14211     int srid = 0;
14212     double step = 10.0;
14213     int gpkg_mode = 0;
14214     int tiny_point = 0;
14215     struct splite_internal_cache *cache = sqlite3_user_data (context);
14216     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14217     if (cache != NULL)
14218       {
14219 	  gpkg_mode = cache->gpkg_mode;
14220 	  tiny_point = cache->tinyPointEnabled;
14221       }
14222     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
14223       {
14224 	  ival = sqlite3_value_int (argv[0]);
14225 	  cx = ival;
14226       }
14227     else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
14228 	cx = sqlite3_value_double (argv[0]);
14229     else
14230       {
14231 	  sqlite3_result_null (context);
14232 	  return;
14233       }
14234     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
14235       {
14236 	  ival = sqlite3_value_int (argv[1]);
14237 	  cy = ival;
14238       }
14239     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
14240 	cy = sqlite3_value_double (argv[1]);
14241     else
14242       {
14243 	  sqlite3_result_null (context);
14244 	  return;
14245       }
14246     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
14247       {
14248 	  ival = sqlite3_value_int (argv[2]);
14249 	  x_axis = ival;
14250       }
14251     else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
14252 	x_axis = sqlite3_value_double (argv[2]);
14253     else
14254       {
14255 	  sqlite3_result_null (context);
14256 	  return;
14257       }
14258     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
14259       {
14260 	  ival = sqlite3_value_int (argv[3]);
14261 	  y_axis = ival;
14262       }
14263     else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
14264 	y_axis = sqlite3_value_double (argv[3]);
14265     else
14266       {
14267 	  sqlite3_result_null (context);
14268 	  return;
14269       }
14270     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
14271       {
14272 	  ival = sqlite3_value_int (argv[4]);
14273 	  start = ival;
14274       }
14275     else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
14276 	start = sqlite3_value_double (argv[4]);
14277     else
14278       {
14279 	  sqlite3_result_null (context);
14280 	  return;
14281       }
14282     if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
14283       {
14284 	  ival = sqlite3_value_int (argv[5]);
14285 	  stop = ival;
14286       }
14287     else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
14288 	stop = sqlite3_value_double (argv[5]);
14289     else
14290       {
14291 	  sqlite3_result_null (context);
14292 	  return;
14293       }
14294     if (argc >= 7)
14295       {
14296 	  if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
14297 	      srid = sqlite3_value_int (argv[6]);
14298 	  else
14299 	    {
14300 		sqlite3_result_null (context);
14301 		return;
14302 	    }
14303       }
14304     if (argc == 8)
14305       {
14306 	  if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
14307 	    {
14308 		ival = sqlite3_value_int (argv[7]);
14309 		step = ival;
14310 	    }
14311 	  else if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
14312 	      step = sqlite3_value_double (argv[7]);
14313 	  else
14314 	    {
14315 		sqlite3_result_null (context);
14316 		return;
14317 	    }
14318       }
14319 
14320     geom = gaiaMakeEllipticArc (cx, cy, x_axis, y_axis, start, stop, step);
14321     if (!geom)
14322 	sqlite3_result_null (context);
14323     else
14324       {
14325 	  int ii;
14326 	  int io = 0;
14327 	  double x;
14328 	  double y;
14329 	  gaiaLinestringPtr in = geom->FirstLinestring;
14330 	  gaiaPolygonPtr pg;
14331 	  gaiaRingPtr out;
14332 	  sector = gaiaAllocGeomColl ();
14333 	  pg = gaiaAddPolygonToGeomColl (sector, in->Points + 2, 0);
14334 	  out = pg->Exterior;
14335 	  /* inserting the Centre - first point */
14336 	  gaiaSetPoint (out->Coords, io, cx, cy);
14337 	  io++;
14338 	  for (ii = 0; ii < in->Points; ii++)
14339 	    {
14340 		/* copying the Arc's points */
14341 		gaiaGetPoint (in->Coords, ii, &x, &y);
14342 		gaiaSetPoint (out->Coords, io, x, y);
14343 		io++;
14344 	    }
14345 	  /* inserting the Centre - last point */
14346 	  gaiaSetPoint (out->Coords, io, cx, cy);
14347 	  if (srid != 0)
14348 	      sector->Srid = srid;
14349 	  gaiaToSpatiaLiteBlobWkbEx2 (sector, &p_result, &len, gpkg_mode,
14350 				      tiny_point);
14351 	  sqlite3_result_blob (context, p_result, len, free);
14352       }
14353     if (geom)
14354 	gaiaFreeGeomColl (geom);
14355     if (sector)
14356 	gaiaFreeGeomColl (sector);
14357 }
14358 
14359 static void
fnct_Collect_step(sqlite3_context * context,int argc,sqlite3_value ** argv)14360 fnct_Collect_step (sqlite3_context * context, int argc, sqlite3_value ** argv)
14361 {
14362 /* SQL function:
14363 / Collect(BLOBencoded geom)
14364 /
14365 / aggregate function - STEP
14366 /
14367 */
14368     unsigned char *p_blob;
14369     int n_bytes;
14370     gaiaGeomCollPtr geom;
14371     gaiaGeomCollPtr result;
14372     gaiaGeomCollPtr *p;
14373     int gpkg_amphibious = 0;
14374     int gpkg_mode = 0;
14375     struct splite_internal_cache *cache = sqlite3_user_data (context);
14376     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14377     if (cache != NULL)
14378       {
14379 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
14380 	  gpkg_mode = cache->gpkg_mode;
14381       }
14382     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14383       {
14384 	  sqlite3_result_null (context);
14385 	  return;
14386       }
14387     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
14388     n_bytes = sqlite3_value_bytes (argv[0]);
14389     geom =
14390 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
14391 				     gpkg_amphibious);
14392     if (!geom)
14393 	return;
14394     p = sqlite3_aggregate_context (context, sizeof (gaiaGeomCollPtr));
14395     if (!(*p))
14396       {
14397 	  /* this is the first row */
14398 	  *p = geom;
14399       }
14400     else
14401       {
14402 	  /* subsequent rows */
14403 	  void *data = sqlite3_user_data (context);
14404 	  if (data != NULL)
14405 	      result = gaiaMergeGeometries_r (data, *p, geom);
14406 	  else
14407 	      result = gaiaMergeGeometries (*p, geom);
14408 	  *p = result;
14409 	  gaiaFreeGeomColl (geom);
14410       }
14411 }
14412 
14413 static void
fnct_Collect_final(sqlite3_context * context)14414 fnct_Collect_final (sqlite3_context * context)
14415 {
14416 /* SQL function:
14417 / Collect(BLOBencoded geom)
14418 /
14419 / aggregate function - FINAL
14420 /
14421 */
14422     gaiaGeomCollPtr result;
14423     gaiaGeomCollPtr *p = sqlite3_aggregate_context (context, 0);
14424     int gpkg_mode = 0;
14425     int tiny_point = 0;
14426     struct splite_internal_cache *cache = sqlite3_user_data (context);
14427     if (cache != NULL)
14428       {
14429 	  gpkg_mode = cache->gpkg_mode;
14430 	  tiny_point = cache->tinyPointEnabled;
14431       }
14432     if (!p)
14433       {
14434 	  sqlite3_result_null (context);
14435 	  return;
14436       }
14437     result = *p;
14438     if (!result)
14439 	sqlite3_result_null (context);
14440     else if (gaiaIsEmpty (result))
14441       {
14442 	  gaiaFreeGeomColl (result);
14443 	  sqlite3_result_null (context);
14444       }
14445     else
14446       {
14447 	  /* builds the BLOB geometry to be returned */
14448 	  int len;
14449 	  unsigned char *p_result = NULL;
14450 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
14451 				      tiny_point);
14452 	  sqlite3_result_blob (context, p_result, len, free);
14453 	  gaiaFreeGeomColl (result);
14454       }
14455 }
14456 
14457 static void
fnct_Collect(sqlite3_context * context,int argc,sqlite3_value ** argv)14458 fnct_Collect (sqlite3_context * context, int argc, sqlite3_value ** argv)
14459 {
14460 /* SQL function:
14461 / Collect(geometry geom1, geometry geom2)
14462 /
14463 / merges two generic GEOMETRIES into a single one
14464 / or NULL if any error is encountered
14465 */
14466     unsigned char *p_blob;
14467     int n_bytes;
14468     gaiaGeomCollPtr geo1 = NULL;
14469     gaiaGeomCollPtr geo2 = NULL;
14470     gaiaGeomCollPtr result;
14471     int gpkg_amphibious = 0;
14472     int gpkg_mode = 0;
14473     int tiny_point = 0;
14474     struct splite_internal_cache *cache = sqlite3_user_data (context);
14475     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14476     if (cache != NULL)
14477       {
14478 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
14479 	  gpkg_mode = cache->gpkg_mode;
14480 	  tiny_point = cache->tinyPointEnabled;
14481       }
14482     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14483       {
14484 	  sqlite3_result_null (context);
14485 	  return;
14486       }
14487     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
14488       {
14489 	  sqlite3_result_null (context);
14490 	  return;
14491       }
14492     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
14493     n_bytes = sqlite3_value_bytes (argv[0]);
14494     geo1 =
14495 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
14496 				     gpkg_amphibious);
14497     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
14498     n_bytes = sqlite3_value_bytes (argv[1]);
14499     geo2 =
14500 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
14501 				     gpkg_amphibious);
14502     if (!geo1 || !geo2)
14503       {
14504 	  if (geo1 != NULL)
14505 	      gaiaFreeGeomColl (geo1);
14506 	  if (geo2 != NULL)
14507 	      gaiaFreeGeomColl (geo2);
14508 	  geo1 = NULL;
14509 	  geo2 = NULL;
14510 	  sqlite3_result_null (context);
14511       }
14512     else
14513       {
14514 	  void *data = sqlite3_user_data (context);
14515 	  if (data != NULL)
14516 	      result = gaiaMergeGeometries_r (data, geo1, geo2);
14517 	  else
14518 	      result = gaiaMergeGeometries (geo1, geo2);
14519 	  if (!result)
14520 	      sqlite3_result_null (context);
14521 	  else if (gaiaIsEmpty (result))
14522 	    {
14523 		gaiaFreeGeomColl (result);
14524 		sqlite3_result_null (context);
14525 	    }
14526 	  else
14527 	    {
14528 		/* builds the BLOB geometry to be returned */
14529 		int len;
14530 		unsigned char *p_result = NULL;
14531 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
14532 					    gpkg_mode, tiny_point);
14533 		sqlite3_result_blob (context, p_result, len, free);
14534 		gaiaFreeGeomColl (result);
14535 	    }
14536       }
14537     gaiaFreeGeomColl (geo2);
14538 }
14539 
14540 static void
geom_from_text1(sqlite3_context * context,int argc,sqlite3_value ** argv,short type)14541 geom_from_text1 (sqlite3_context * context, int argc, sqlite3_value ** argv,
14542 		 short type)
14543 {
14544 /* SQL function:
14545 / GeomFromText(WKT encoded geometry)
14546 /
14547 / returns the current geometry by parsing WKT encoded string
14548 / or NULL if any error is encountered
14549 /
14550 / if *type* is a negative value can accept any GEOMETRY CLASS
14551 / otherwise only requests conforming with required CLASS are valid
14552 */
14553     int len;
14554     unsigned char *p_result = NULL;
14555     const unsigned char *text;
14556     gaiaGeomCollPtr geo = NULL;
14557     int gpkg_mode = 0;
14558     int tiny_point = 0;
14559     struct splite_internal_cache *cache = sqlite3_user_data (context);
14560     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14561     if (cache != NULL)
14562       {
14563 	  gpkg_mode = cache->gpkg_mode;
14564 	  tiny_point = cache->tinyPointEnabled;
14565       }
14566     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
14567       {
14568 	  sqlite3_result_null (context);
14569 	  return;
14570       }
14571     text = sqlite3_value_text (argv[0]);
14572     geo = gaiaParseWkt (text, type);
14573     if (geo == NULL)
14574       {
14575 	  sqlite3_result_null (context);
14576 	  return;
14577       }
14578     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14579     gaiaFreeGeomColl (geo);
14580     sqlite3_result_blob (context, p_result, len, free);
14581 }
14582 
14583 static void
geom_from_text2(sqlite3_context * context,int argc,sqlite3_value ** argv,short type)14584 geom_from_text2 (sqlite3_context * context, int argc, sqlite3_value ** argv,
14585 		 short type)
14586 {
14587 /* SQL function:
14588 / GeomFromText(WKT encoded geometry, SRID)
14589 /
14590 / returns the current geometry by parsing WKT encoded string
14591 / or NULL if any error is encountered
14592 /
14593 / if *type* is a negative value can accept any GEOMETRY CLASS
14594 / otherwise only requests conforming with required CLASS are valid
14595 */
14596     int len;
14597     unsigned char *p_result = NULL;
14598     const unsigned char *text;
14599     gaiaGeomCollPtr geo = NULL;
14600     int gpkg_mode = 0;
14601     int tiny_point = 0;
14602     struct splite_internal_cache *cache = sqlite3_user_data (context);
14603     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14604     if (cache != NULL)
14605       {
14606 	  gpkg_mode = cache->gpkg_mode;
14607 	  tiny_point = cache->tinyPointEnabled;
14608       }
14609     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
14610       {
14611 	  sqlite3_result_null (context);
14612 	  return;
14613       }
14614     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
14615       {
14616 	  sqlite3_result_null (context);
14617 	  return;
14618       }
14619     text = sqlite3_value_text (argv[0]);
14620     geo = gaiaParseWkt (text, type);
14621     if (geo == NULL)
14622       {
14623 	  sqlite3_result_null (context);
14624 	  return;
14625       }
14626     geo->Srid = sqlite3_value_int (argv[1]);
14627     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14628     gaiaFreeGeomColl (geo);
14629     sqlite3_result_blob (context, p_result, len, free);
14630 }
14631 
14632 static int
check_wkb(const unsigned char * wkb,int size,short type)14633 check_wkb (const unsigned char *wkb, int size, short type)
14634 {
14635 /* checking type coherency for WKB encoded GEOMETRY */
14636     int little_endian;
14637     int wkb_type;
14638     int endian_arch = gaiaEndianArch ();
14639     if (size < 5)
14640 	return 0;		/* too short to be a WKB */
14641     if (*(wkb + 0) == 0x01)
14642 	little_endian = GAIA_LITTLE_ENDIAN;
14643     else if (*(wkb + 0) == 0x00)
14644 	little_endian = GAIA_BIG_ENDIAN;
14645     else
14646 	return 0;		/* illegal byte ordering; neither BIG-ENDIAN nor LITTLE-ENDIAN */
14647     wkb_type = gaiaImport32 (wkb + 1, little_endian, endian_arch);
14648     if (wkb_type == GAIA_POINT || wkb_type == GAIA_LINESTRING
14649 	|| wkb_type == GAIA_POLYGON || wkb_type == GAIA_MULTIPOINT
14650 	|| wkb_type == GAIA_MULTILINESTRING || wkb_type == GAIA_MULTIPOLYGON
14651 	|| wkb_type == GAIA_GEOMETRYCOLLECTION || wkb_type == GAIA_POINTZ
14652 	|| wkb_type == GAIA_LINESTRINGZ || wkb_type == GAIA_POLYGONZ
14653 	|| wkb_type == GAIA_MULTIPOINTZ || wkb_type == GAIA_MULTILINESTRINGZ
14654 	|| wkb_type == GAIA_MULTIPOLYGONZ
14655 	|| wkb_type == GAIA_GEOMETRYCOLLECTIONZ || wkb_type == GAIA_POINTM
14656 	|| wkb_type == GAIA_LINESTRINGM || wkb_type == GAIA_POLYGONM
14657 	|| wkb_type == GAIA_MULTIPOINTM || wkb_type == GAIA_MULTILINESTRINGM
14658 	|| wkb_type == GAIA_MULTIPOLYGONM
14659 	|| wkb_type == GAIA_GEOMETRYCOLLECTIONM || wkb_type == GAIA_POINTZM
14660 	|| wkb_type == GAIA_LINESTRINGZM || wkb_type == GAIA_POLYGONZM
14661 	|| wkb_type == GAIA_MULTIPOINTZM || wkb_type == GAIA_MULTILINESTRINGZM
14662 	|| wkb_type == GAIA_MULTIPOLYGONZM
14663 	|| wkb_type == GAIA_GEOMETRYCOLLECTIONZM)
14664 	;
14665     else
14666 	return 0;		/* illegal GEOMETRY CLASS */
14667     if (type < 0)
14668 	;			/* no restrinction about GEOMETRY CLASS TYPE */
14669     else
14670       {
14671 	  if (wkb_type != type)
14672 	      return 0;		/* invalid CLASS TYPE for request */
14673       }
14674     return 1;
14675 }
14676 
14677 static void
geom_from_wkb1(sqlite3_context * context,int argc,sqlite3_value ** argv,short type)14678 geom_from_wkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv,
14679 		short type)
14680 {
14681 /* SQL function:
14682 / GeomFromWKB(WKB encoded geometry)
14683 /
14684 / returns the current geometry by parsing a WKB encoded blob
14685 / or NULL if any error is encountered
14686 /
14687 / if *type* is a negative value can accept any GEOMETRY CLASS
14688 / otherwise only requests conforming with required CLASS are valid
14689 */
14690     int len;
14691     int n_bytes;
14692     unsigned char *p_result = NULL;
14693     const unsigned char *wkb;
14694     gaiaGeomCollPtr geo = NULL;
14695     int gpkg_mode = 0;
14696     int tiny_point = 0;
14697     struct splite_internal_cache *cache = sqlite3_user_data (context);
14698     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14699     if (cache != NULL)
14700       {
14701 	  gpkg_mode = cache->gpkg_mode;
14702 	  tiny_point = cache->tinyPointEnabled;
14703       }
14704     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14705       {
14706 	  sqlite3_result_null (context);
14707 	  return;
14708       }
14709     wkb = sqlite3_value_blob (argv[0]);
14710     n_bytes = sqlite3_value_bytes (argv[0]);
14711     if (!check_wkb (wkb, n_bytes, type))
14712 	return;
14713     geo = gaiaFromWkb (wkb, n_bytes);
14714     if (geo == NULL)
14715       {
14716 	  sqlite3_result_null (context);
14717 	  return;
14718       }
14719     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14720     gaiaFreeGeomColl (geo);
14721     sqlite3_result_blob (context, p_result, len, free);
14722 }
14723 
14724 static void
geom_from_wkb2(sqlite3_context * context,int argc,sqlite3_value ** argv,short type)14725 geom_from_wkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv,
14726 		short type)
14727 {
14728 /* SQL function:
14729 / GeomFromWKB(WKB encoded geometry, SRID)
14730 /
14731 / returns the current geometry by parsing a WKB encoded blob
14732 / or NULL if any error is encountered
14733 /
14734 / if *type* is a negative value can accept any GEOMETRY CLASS
14735 / otherwise only requests conforming with required CLASS are valid
14736 */
14737     int len;
14738     int n_bytes;
14739     unsigned char *p_result = NULL;
14740     const unsigned char *wkb;
14741     gaiaGeomCollPtr geo = NULL;
14742     int gpkg_mode = 0;
14743     int tiny_point = 0;
14744     struct splite_internal_cache *cache = sqlite3_user_data (context);
14745     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14746     if (cache != NULL)
14747       {
14748 	  gpkg_mode = cache->gpkg_mode;
14749 	  tiny_point = cache->tinyPointEnabled;
14750       }
14751     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14752       {
14753 	  sqlite3_result_null (context);
14754 	  return;
14755       }
14756     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
14757       {
14758 	  sqlite3_result_null (context);
14759 	  return;
14760       }
14761     wkb = sqlite3_value_blob (argv[0]);
14762     n_bytes = sqlite3_value_bytes (argv[0]);
14763     if (!check_wkb (wkb, n_bytes, type))
14764 	return;
14765     geo = gaiaFromWkb (wkb, n_bytes);
14766     if (geo == NULL)
14767       {
14768 	  sqlite3_result_null (context);
14769 	  return;
14770       }
14771     geo->Srid = sqlite3_value_int (argv[1]);
14772     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14773     gaiaFreeGeomColl (geo);
14774     sqlite3_result_blob (context, p_result, len, free);
14775 }
14776 
14777 static void
fnct_GeometryFromFGF1(sqlite3_context * context,int argc,sqlite3_value ** argv)14778 fnct_GeometryFromFGF1 (sqlite3_context * context, int argc,
14779 		       sqlite3_value ** argv)
14780 {
14781 /* SQL function:
14782 / GeomFromFGF(FGF encoded geometry)
14783 /
14784 / returns the current geometry by parsing an FGF encoded blob
14785 / or NULL if any error is encountered
14786 /
14787 / if *type* is a negative value can accept any GEOMETRY CLASS
14788 / otherwise only requests conforming with required CLASS are valid
14789 */
14790     int len;
14791     int n_bytes;
14792     unsigned char *p_result = NULL;
14793     const unsigned char *fgf;
14794     gaiaGeomCollPtr geo = NULL;
14795     int gpkg_mode = 0;
14796     int tiny_point = 0;
14797     struct splite_internal_cache *cache = sqlite3_user_data (context);
14798     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14799     if (cache != NULL)
14800       {
14801 	  gpkg_mode = cache->gpkg_mode;
14802 	  tiny_point = cache->tinyPointEnabled;
14803       }
14804     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14805       {
14806 	  sqlite3_result_null (context);
14807 	  return;
14808       }
14809     fgf = sqlite3_value_blob (argv[0]);
14810     n_bytes = sqlite3_value_bytes (argv[0]);
14811     geo = gaiaFromFgf (fgf, n_bytes);
14812     if (geo == NULL)
14813       {
14814 	  sqlite3_result_null (context);
14815 	  return;
14816       }
14817     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14818     gaiaFreeGeomColl (geo);
14819     sqlite3_result_blob (context, p_result, len, free);
14820 }
14821 
14822 static void
fnct_GeometryFromFGF2(sqlite3_context * context,int argc,sqlite3_value ** argv)14823 fnct_GeometryFromFGF2 (sqlite3_context * context, int argc,
14824 		       sqlite3_value ** argv)
14825 {
14826 /* SQL function:
14827 / GeomFromFGF(FGF encoded geometry, SRID)
14828 /
14829 / returns the current geometry by parsing an FGF encoded string
14830 / or NULL if any error is encountered
14831 /
14832 / if *type* is a negative value can accept any GEOMETRY CLASS
14833 / otherwise only requests conforming with required CLASS are valid
14834 */
14835     int len;
14836     int n_bytes;
14837     unsigned char *p_result = NULL;
14838     const unsigned char *fgf;
14839     gaiaGeomCollPtr geo = NULL;
14840     int gpkg_mode = 0;
14841     int tiny_point = 0;
14842     struct splite_internal_cache *cache = sqlite3_user_data (context);
14843     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14844     if (cache != NULL)
14845       {
14846 	  gpkg_mode = cache->gpkg_mode;
14847 	  tiny_point = cache->tinyPointEnabled;
14848       }
14849     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
14850       {
14851 	  sqlite3_result_null (context);
14852 	  return;
14853       }
14854     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
14855       {
14856 	  sqlite3_result_null (context);
14857 	  return;
14858       }
14859     fgf = sqlite3_value_blob (argv[0]);
14860     n_bytes = sqlite3_value_bytes (argv[0]);
14861     geo = gaiaFromFgf (fgf, n_bytes);
14862     if (geo == NULL)
14863       {
14864 	  sqlite3_result_null (context);
14865 	  return;
14866       }
14867     geo->Srid = sqlite3_value_int (argv[1]);
14868     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
14869     gaiaFreeGeomColl (geo);
14870     sqlite3_result_blob (context, p_result, len, free);
14871 }
14872 
14873 /*
14874 / the following functions simply readdress the request to geom_from_text?()
14875 / setting the appropriate GEOMETRY CLASS TYPE
14876 */
14877 
14878 static void
fnct_GeomFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14879 fnct_GeomFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14880 {
14881     geom_from_text1 (context, argc, argv, (short) -1);
14882 }
14883 
14884 static void
fnct_GeomFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14885 fnct_GeomFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14886 {
14887     geom_from_text2 (context, argc, argv, (short) -1);
14888 }
14889 
14890 static void
fnct_GeomCollFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14891 fnct_GeomCollFromText1 (sqlite3_context * context, int argc,
14892 			sqlite3_value ** argv)
14893 {
14894     geom_from_text1 (context, argc, argv, (short) GAIA_GEOMETRYCOLLECTION);
14895 }
14896 
14897 static void
fnct_GeomCollFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14898 fnct_GeomCollFromText2 (sqlite3_context * context, int argc,
14899 			sqlite3_value ** argv)
14900 {
14901     geom_from_text2 (context, argc, argv, (short) GAIA_GEOMETRYCOLLECTION);
14902 }
14903 
14904 static void
fnct_LineFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14905 fnct_LineFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14906 {
14907     geom_from_text1 (context, argc, argv, (short) GAIA_LINESTRING);
14908 }
14909 
14910 static void
fnct_LineFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14911 fnct_LineFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14912 {
14913     geom_from_text2 (context, argc, argv, (short) GAIA_LINESTRING);
14914 }
14915 
14916 static void
fnct_PointFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14917 fnct_PointFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14918 {
14919     geom_from_text1 (context, argc, argv, (short) GAIA_POINT);
14920 }
14921 
14922 static void
fnct_PointFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14923 fnct_PointFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14924 {
14925     geom_from_text2 (context, argc, argv, (short) GAIA_POINT);
14926 }
14927 
14928 static void
fnct_PolyFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14929 fnct_PolyFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14930 {
14931     geom_from_text1 (context, argc, argv, (short) GAIA_POLYGON);
14932 }
14933 
14934 static void
fnct_PolyFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14935 fnct_PolyFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14936 {
14937     geom_from_text2 (context, argc, argv, (short) GAIA_POLYGON);
14938 }
14939 
14940 static void
fnct_MLineFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14941 fnct_MLineFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14942 {
14943     geom_from_text1 (context, argc, argv, (short) GAIA_MULTILINESTRING);
14944 }
14945 
14946 static void
fnct_MLineFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14947 fnct_MLineFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14948 {
14949     geom_from_text2 (context, argc, argv, (short) GAIA_MULTILINESTRING);
14950 }
14951 
14952 static void
fnct_MPointFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14953 fnct_MPointFromText1 (sqlite3_context * context, int argc,
14954 		      sqlite3_value ** argv)
14955 {
14956     geom_from_text1 (context, argc, argv, (short) GAIA_MULTIPOINT);
14957 }
14958 
14959 static void
fnct_MPointFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14960 fnct_MPointFromText2 (sqlite3_context * context, int argc,
14961 		      sqlite3_value ** argv)
14962 {
14963     geom_from_text2 (context, argc, argv, (short) GAIA_MULTIPOINT);
14964 }
14965 
14966 static void
fnct_MPolyFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)14967 fnct_MPolyFromText1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14968 {
14969     geom_from_text1 (context, argc, argv, (short) GAIA_MULTIPOLYGON);
14970 }
14971 
14972 static void
fnct_MPolyFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)14973 fnct_MPolyFromText2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
14974 {
14975     geom_from_text2 (context, argc, argv, (short) GAIA_MULTIPOLYGON);
14976 }
14977 
14978 static void
fnct_WktToSql(sqlite3_context * context,int argc,sqlite3_value ** argv)14979 fnct_WktToSql (sqlite3_context * context, int argc, sqlite3_value ** argv)
14980 {
14981 /* SQL function:
14982 / ST_WKTToSQL(WKT encoded geometry)
14983 /
14984 / returns the current geometry by parsing WKT encoded string
14985 / or NULL if any error is encountered
14986 /
14987 / the SRID is always 0 [SQL/MM function]
14988 */
14989     int len;
14990     unsigned char *p_result = NULL;
14991     const unsigned char *text;
14992     gaiaGeomCollPtr geo = NULL;
14993     int gpkg_mode = 0;
14994     int tiny_point = 0;
14995     struct splite_internal_cache *cache = sqlite3_user_data (context);
14996     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
14997     if (cache != NULL)
14998       {
14999 	  gpkg_mode = cache->gpkg_mode;
15000 	  tiny_point = cache->tinyPointEnabled;
15001       }
15002     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
15003       {
15004 	  sqlite3_result_null (context);
15005 	  return;
15006       }
15007     text = sqlite3_value_text (argv[0]);
15008     geo = gaiaParseWkt (text, -1);
15009     if (geo == NULL)
15010       {
15011 	  sqlite3_result_null (context);
15012 	  return;
15013       }
15014     geo->Srid = 0;
15015     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
15016     gaiaFreeGeomColl (geo);
15017     sqlite3_result_blob (context, p_result, len, free);
15018 }
15019 
15020 /*
15021 / the following functions simply readdress the request to geom_from_wkb?()
15022 / setting the appropriate GEOMETRY CLASS TYPE
15023 */
15024 
15025 static void
fnct_GeomFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15026 fnct_GeomFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15027 {
15028     geom_from_wkb1 (context, argc, argv, (short) -1);
15029 }
15030 
15031 static void
fnct_GeomFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15032 fnct_GeomFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15033 {
15034     geom_from_wkb2 (context, argc, argv, (short) -1);
15035 }
15036 
15037 static void
fnct_GeomCollFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15038 fnct_GeomCollFromWkb1 (sqlite3_context * context, int argc,
15039 		       sqlite3_value ** argv)
15040 {
15041     geom_from_wkb1 (context, argc, argv, (short) GAIA_GEOMETRYCOLLECTION);
15042 }
15043 
15044 static void
fnct_GeomCollFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15045 fnct_GeomCollFromWkb2 (sqlite3_context * context, int argc,
15046 		       sqlite3_value ** argv)
15047 {
15048     geom_from_wkb2 (context, argc, argv, (short) GAIA_GEOMETRYCOLLECTION);
15049 }
15050 
15051 static void
fnct_LineFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15052 fnct_LineFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15053 {
15054     geom_from_wkb1 (context, argc, argv, (short) GAIA_LINESTRING);
15055 }
15056 
15057 static void
fnct_LineFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15058 fnct_LineFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15059 {
15060     geom_from_wkb2 (context, argc, argv, (short) GAIA_LINESTRING);
15061 }
15062 
15063 static void
fnct_PointFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15064 fnct_PointFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15065 {
15066     geom_from_wkb1 (context, argc, argv, (short) GAIA_POINT);
15067 }
15068 
15069 static void
fnct_PointFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15070 fnct_PointFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15071 {
15072     geom_from_wkb2 (context, argc, argv, (short) GAIA_POINT);
15073 }
15074 
15075 static void
fnct_PolyFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15076 fnct_PolyFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15077 {
15078     geom_from_wkb1 (context, argc, argv, (short) GAIA_POLYGON);
15079 }
15080 
15081 static void
fnct_PolyFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15082 fnct_PolyFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15083 {
15084     geom_from_wkb2 (context, argc, argv, (short) GAIA_POLYGON);
15085 }
15086 
15087 static void
fnct_MLineFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15088 fnct_MLineFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15089 {
15090     geom_from_wkb1 (context, argc, argv, (short) GAIA_MULTILINESTRING);
15091 }
15092 
15093 static void
fnct_MLineFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15094 fnct_MLineFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15095 {
15096     geom_from_wkb2 (context, argc, argv, (short) GAIA_MULTILINESTRING);
15097 }
15098 
15099 static void
fnct_MPointFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15100 fnct_MPointFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15101 {
15102     geom_from_wkb1 (context, argc, argv, (short) GAIA_MULTIPOINT);
15103 }
15104 
15105 static void
fnct_MPointFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15106 fnct_MPointFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15107 {
15108     geom_from_wkb2 (context, argc, argv, (short) GAIA_MULTIPOINT);
15109 }
15110 
15111 static void
fnct_MPolyFromWkb1(sqlite3_context * context,int argc,sqlite3_value ** argv)15112 fnct_MPolyFromWkb1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15113 {
15114     geom_from_wkb1 (context, argc, argv, (short) GAIA_MULTIPOLYGON);
15115 }
15116 
15117 static void
fnct_MPolyFromWkb2(sqlite3_context * context,int argc,sqlite3_value ** argv)15118 fnct_MPolyFromWkb2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
15119 {
15120     geom_from_wkb2 (context, argc, argv, (short) GAIA_MULTIPOLYGON);
15121 }
15122 
15123 static void
fnct_WkbToSql(sqlite3_context * context,int argc,sqlite3_value ** argv)15124 fnct_WkbToSql (sqlite3_context * context, int argc, sqlite3_value ** argv)
15125 {
15126 /* SQL function:
15127 / ST_WKBToSQL(WKB encoded geometry)
15128 /
15129 / returns the current geometry by parsing a WKB encoded blob
15130 / or NULL if any error is encountered
15131 /
15132 / the SRID is always 0 [SQL/MM function]
15133 */
15134     int len;
15135     int n_bytes;
15136     unsigned char *p_result = NULL;
15137     const unsigned char *wkb;
15138     gaiaGeomCollPtr geo = NULL;
15139     int gpkg_mode = 0;
15140     int tiny_point = 0;
15141     struct splite_internal_cache *cache = sqlite3_user_data (context);
15142     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15143     if (cache != NULL)
15144       {
15145 	  gpkg_mode = cache->gpkg_mode;
15146 	  tiny_point = cache->tinyPointEnabled;
15147       }
15148     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15149       {
15150 	  sqlite3_result_null (context);
15151 	  return;
15152       }
15153     wkb = sqlite3_value_blob (argv[0]);
15154     n_bytes = sqlite3_value_bytes (argv[0]);
15155     if (!check_wkb (wkb, n_bytes, -1))
15156 	return;
15157     geo = gaiaFromWkb (wkb, n_bytes);
15158     if (geo == NULL)
15159       {
15160 	  sqlite3_result_null (context);
15161 	  return;
15162       }
15163     geo->Srid = 0;
15164     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
15165     gaiaFreeGeomColl (geo);
15166     sqlite3_result_blob (context, p_result, len, free);
15167 }
15168 
15169 static void
fnct_CompressGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)15170 fnct_CompressGeometry (sqlite3_context * context, int argc,
15171 		       sqlite3_value ** argv)
15172 {
15173 /* SQL function:
15174 / CompressGeometry(BLOB encoded geometry)
15175 /
15176 / returns a COMPRESSED geometry [if a valid Geometry was supplied]
15177 / or NULL in any other case
15178 */
15179     unsigned char *p_blob;
15180     int n_bytes;
15181     int len;
15182     unsigned char *p_result = NULL;
15183     gaiaGeomCollPtr geo = NULL;
15184     int gpkg_amphibious = 0;
15185     int gpkg_mode = 0;
15186     struct splite_internal_cache *cache = sqlite3_user_data (context);
15187     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15188     if (cache != NULL)
15189       {
15190 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15191 	  gpkg_mode = cache->gpkg_mode;
15192       }
15193     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15194       {
15195 	  sqlite3_result_null (context);
15196 	  return;
15197       }
15198     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15199     n_bytes = sqlite3_value_bytes (argv[0]);
15200     geo =
15201 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15202 				     gpkg_amphibious);
15203     if (!geo)
15204 	sqlite3_result_null (context);
15205     else
15206       {
15207 	  gaiaToCompressedBlobWkb (geo, &p_result, &len);
15208 	  sqlite3_result_blob (context, p_result, len, free);
15209       }
15210     gaiaFreeGeomColl (geo);
15211 }
15212 
15213 static void
fnct_UncompressGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)15214 fnct_UncompressGeometry (sqlite3_context * context, int argc,
15215 			 sqlite3_value ** argv)
15216 {
15217 /* SQL function:
15218 / UncompressGeometry(BLOB encoded geometry)
15219 /
15220 / returns an UNCOMPRESSED geometry [if a valid Geometry was supplied]
15221 / or NULL in any other case
15222 */
15223     unsigned char *p_blob;
15224     int n_bytes;
15225     int len;
15226     unsigned char *p_result = NULL;
15227     gaiaGeomCollPtr geo = NULL;
15228     int gpkg_amphibious = 0;
15229     int gpkg_mode = 0;
15230     int tiny_point = 0;
15231     struct splite_internal_cache *cache = sqlite3_user_data (context);
15232     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15233     if (cache != NULL)
15234       {
15235 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15236 	  gpkg_mode = cache->gpkg_mode;
15237 	  tiny_point = cache->tinyPointEnabled;
15238       }
15239     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15240       {
15241 	  sqlite3_result_null (context);
15242 	  return;
15243       }
15244     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15245     n_bytes = sqlite3_value_bytes (argv[0]);
15246     geo =
15247 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15248 				     gpkg_amphibious);
15249     if (!geo)
15250 	sqlite3_result_null (context);
15251     else
15252       {
15253 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
15254 				      tiny_point);
15255 	  sqlite3_result_blob (context, p_result, len, free);
15256       }
15257     gaiaFreeGeomColl (geo);
15258 }
15259 
15260 static void
fnct_SanitizeGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)15261 fnct_SanitizeGeometry (sqlite3_context * context, int argc,
15262 		       sqlite3_value ** argv)
15263 {
15264 /* SQL function:
15265 / SanitizeGeometry(BLOB encoded geometry)
15266 /
15267 / returns a SANITIZED geometry [if a valid Geometry was supplied]
15268 / or NULL in any other case
15269 /
15270 / Sanitizing includes:
15271 / - repeated vertices suppression
15272 / - enforcing ring closure
15273 /
15274 */
15275     unsigned char *p_blob;
15276     int n_bytes;
15277     int len;
15278     unsigned char *p_result = NULL;
15279     gaiaGeomCollPtr geo = NULL;
15280     gaiaGeomCollPtr sanitized = NULL;
15281     int gpkg_amphibious = 0;
15282     int gpkg_mode = 0;
15283     int tiny_point = 0;
15284     struct splite_internal_cache *cache = sqlite3_user_data (context);
15285     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15286     if (cache != NULL)
15287       {
15288 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15289 	  gpkg_mode = cache->gpkg_mode;
15290 	  tiny_point = cache->tinyPointEnabled;
15291       }
15292     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15293       {
15294 	  sqlite3_result_null (context);
15295 	  return;
15296       }
15297     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15298     n_bytes = sqlite3_value_bytes (argv[0]);
15299     geo =
15300 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15301 				     gpkg_amphibious);
15302     if (!geo)
15303 	sqlite3_result_null (context);
15304     else
15305       {
15306 	  sanitized = gaiaSanitize (geo);
15307 	  gaiaToSpatiaLiteBlobWkbEx2 (sanitized, &p_result, &len, gpkg_mode,
15308 				      tiny_point);
15309 	  sqlite3_result_blob (context, p_result, len, free);
15310       }
15311     gaiaFreeGeomColl (geo);
15312     gaiaFreeGeomColl (sanitized);
15313 }
15314 
15315 static void
fnct_EnsureClosedRings(sqlite3_context * context,int argc,sqlite3_value ** argv)15316 fnct_EnsureClosedRings (sqlite3_context * context, int argc,
15317 			sqlite3_value ** argv)
15318 {
15319 /* SQL function:
15320 / EnsureClosedRings(BLOB encoded geometry)
15321 /
15322 / returns a SANITIZED geometry [if a valid Geometry was supplied]
15323 / or NULL in any other case
15324 /
15325 / Sanitizing includes only enforcing ring closure
15326 /
15327 */
15328     unsigned char *p_blob;
15329     int n_bytes;
15330     int len;
15331     unsigned char *p_result = NULL;
15332     gaiaGeomCollPtr geo = NULL;
15333     gaiaGeomCollPtr sanitized = NULL;
15334     int gpkg_amphibious = 0;
15335     int gpkg_mode = 0;
15336     int tiny_point = 0;
15337     struct splite_internal_cache *cache = sqlite3_user_data (context);
15338     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15339     if (cache != NULL)
15340       {
15341 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15342 	  gpkg_mode = cache->gpkg_mode;
15343 	  tiny_point = cache->tinyPointEnabled;
15344       }
15345     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15346       {
15347 	  sqlite3_result_null (context);
15348 	  return;
15349       }
15350     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15351     n_bytes = sqlite3_value_bytes (argv[0]);
15352     geo =
15353 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15354 				     gpkg_amphibious);
15355     if (!geo)
15356 	sqlite3_result_null (context);
15357     else
15358       {
15359 	  sanitized = gaiaEnsureClosedRings (geo);
15360 	  gaiaToSpatiaLiteBlobWkbEx2 (sanitized, &p_result, &len, gpkg_mode,
15361 				      tiny_point);
15362 	  sqlite3_result_blob (context, p_result, len, free);
15363       }
15364     gaiaFreeGeomColl (geo);
15365     gaiaFreeGeomColl (sanitized);
15366 }
15367 
15368 static void
fnct_RemoveRepeatedPoints(sqlite3_context * context,int argc,sqlite3_value ** argv)15369 fnct_RemoveRepeatedPoints (sqlite3_context * context, int argc,
15370 			   sqlite3_value ** argv)
15371 {
15372 /* SQL function:
15373 / RemoveRepeatedPoints(BLOB encoded geometry)
15374 / RemoveRepeatedPoints(BLOB encoded geometry, double tolerance)
15375 /
15376 / returns a SANITIZED geometry [if a valid Geometry was supplied]
15377 / or NULL in any other case
15378 /
15379 / Sanitizing includes only repeated vertices suppression
15380 /
15381 */
15382     unsigned char *p_blob;
15383     int n_bytes;
15384     int len;
15385     unsigned char *p_result = NULL;
15386     gaiaGeomCollPtr geo = NULL;
15387     gaiaGeomCollPtr sanitized = NULL;
15388     double tolerance = 0.0;
15389     int gpkg_amphibious = 0;
15390     int gpkg_mode = 0;
15391     int tiny_point = 0;
15392     struct splite_internal_cache *cache = sqlite3_user_data (context);
15393     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15394     if (cache != NULL)
15395       {
15396 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15397 	  gpkg_mode = cache->gpkg_mode;
15398 	  tiny_point = cache->tinyPointEnabled;
15399       }
15400     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15401       {
15402 	  sqlite3_result_null (context);
15403 	  return;
15404       }
15405     if (argc >= 2)
15406       {
15407 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
15408 	    {
15409 		int tol = sqlite3_value_int (argv[1]);
15410 		tolerance = tol;
15411 	    }
15412 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
15413 	      tolerance = sqlite3_value_double (argv[1]);
15414 	  else
15415 	    {
15416 		sqlite3_result_null (context);
15417 		return;
15418 	    }
15419       }
15420     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15421     n_bytes = sqlite3_value_bytes (argv[0]);
15422     geo =
15423 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15424 				     gpkg_amphibious);
15425     if (!geo)
15426 	sqlite3_result_null (context);
15427     else
15428       {
15429 	  sanitized = gaiaRemoveRepeatedPoints (geo, tolerance);
15430 	  gaiaToSpatiaLiteBlobWkbEx2 (sanitized, &p_result, &len, gpkg_mode,
15431 				      tiny_point);
15432 	  sqlite3_result_blob (context, p_result, len, free);
15433       }
15434     gaiaFreeGeomColl (geo);
15435     gaiaFreeGeomColl (sanitized);
15436 }
15437 
15438 static void
cast_count(gaiaGeomCollPtr geom,int * pts,int * lns,int * pgs)15439 cast_count (gaiaGeomCollPtr geom, int *pts, int *lns, int *pgs)
15440 {
15441 /* counting elementary geometries */
15442     int n_pts = 0;
15443     int n_lns = 0;
15444     int n_pgs = 0;
15445     gaiaPointPtr pt;
15446     gaiaLinestringPtr ln;
15447     gaiaPolygonPtr pg;
15448     if (geom)
15449       {
15450 	  pt = geom->FirstPoint;
15451 	  while (pt)
15452 	    {
15453 		n_pts++;
15454 		pt = pt->Next;
15455 	    }
15456 	  ln = geom->FirstLinestring;
15457 	  while (ln)
15458 	    {
15459 		n_lns++;
15460 		ln = ln->Next;
15461 	    }
15462 	  pg = geom->FirstPolygon;
15463 	  while (pg)
15464 	    {
15465 		n_pgs++;
15466 		pg = pg->Next;
15467 	    }
15468       }
15469     *pts = n_pts;
15470     *lns = n_lns;
15471     *pgs = n_pgs;
15472 }
15473 
15474 static void
fnct_CastAutomagic(sqlite3_context * context,int argc,sqlite3_value ** argv)15475 fnct_CastAutomagic (sqlite3_context * context, int argc, sqlite3_value ** argv)
15476 {
15477 /* SQL function:
15478 / CastAutomagic(BLOB encoded geometry)
15479 /
15480 / accepts on input both a valid SpatiaLite BLOB geometry
15481 / or a valid GPKG BLOB geometry, thus returning a SpatiaLite
15482 / BLOB geometry
15483 / will return NULL in any other case
15484 */
15485     unsigned char *p_blob;
15486     int n_bytes;
15487     int len;
15488     unsigned char *p_result = NULL;
15489     gaiaGeomCollPtr geo = NULL;
15490     int gpkg_mode = 0;
15491     int tiny_point = 0;
15492     struct splite_internal_cache *cache = sqlite3_user_data (context);
15493     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15494     if (cache != NULL)
15495       {
15496 	  gpkg_mode = cache->gpkg_mode;
15497 	  tiny_point = cache->tinyPointEnabled;
15498       }
15499     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15500       {
15501 	  sqlite3_result_null (context);
15502 	  return;
15503       }
15504     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15505     n_bytes = sqlite3_value_bytes (argv[0]);
15506     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
15507     if (!geo)
15508       {
15509 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
15510 	  if (gaiaIsValidGPB (p_blob, n_bytes))
15511 	    {
15512 		geo = gaiaFromGeoPackageGeometryBlob (p_blob, n_bytes);
15513 		if (geo == NULL)
15514 		    sqlite3_result_null (context);
15515 		else
15516 		  {
15517 		      gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len,
15518 						  gpkg_mode, tiny_point);
15519 		      gaiaFreeGeomColl (geo);
15520 		      sqlite3_result_blob (context, p_result, len, free);
15521 		  }
15522 		return;
15523 	    }
15524 	  else
15525 #endif /* end GEOPACKAGE: supporting GPKG geometries */
15526 	      sqlite3_result_null (context);
15527       }
15528     else
15529       {
15530 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
15531 				      tiny_point);
15532 	  gaiaFreeGeomColl (geo);
15533 	  sqlite3_result_blob (context, p_result, len, free);
15534       }
15535 }
15536 
15537 static void
fnct_CastToPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)15538 fnct_CastToPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
15539 {
15540 /* SQL function:
15541 / CastToPoint(BLOB encoded geometry)
15542 /
15543 / returns a POINT-type geometry [if conversion is possible]
15544 / or NULL in any other case
15545 */
15546     unsigned char *p_blob;
15547     int n_bytes;
15548     int len;
15549     unsigned char *p_result = NULL;
15550     int pts;
15551     int lns;
15552     int pgs;
15553     gaiaGeomCollPtr geo = NULL;
15554     gaiaGeomCollPtr geom2 = NULL;
15555     int gpkg_amphibious = 0;
15556     int gpkg_mode = 0;
15557     int tiny_point = 0;
15558     struct splite_internal_cache *cache = sqlite3_user_data (context);
15559     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15560     if (cache != NULL)
15561       {
15562 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15563 	  gpkg_mode = cache->gpkg_mode;
15564 	  tiny_point = cache->tinyPointEnabled;
15565       }
15566     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15567       {
15568 	  sqlite3_result_null (context);
15569 	  return;
15570       }
15571     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15572     n_bytes = sqlite3_value_bytes (argv[0]);
15573     geo =
15574 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15575 				     gpkg_amphibious);
15576     if (!geo)
15577 	sqlite3_result_null (context);
15578     else
15579       {
15580 	  cast_count (geo, &pts, &lns, &pgs);
15581 	  if (pts == 1 && lns == 0 && pgs == 0)
15582 	    {
15583 		geom2 = gaiaCloneGeomColl (geo);
15584 		geom2->Srid = geo->Srid;
15585 		geom2->DeclaredType = GAIA_POINT;
15586 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15587 					    tiny_point);
15588 		gaiaFreeGeomColl (geom2);
15589 		sqlite3_result_blob (context, p_result, len, free);
15590 	    }
15591 	  else
15592 	      sqlite3_result_null (context);
15593       }
15594     gaiaFreeGeomColl (geo);
15595 }
15596 
15597 static void
fnct_CastToLinestring(sqlite3_context * context,int argc,sqlite3_value ** argv)15598 fnct_CastToLinestring (sqlite3_context * context, int argc,
15599 		       sqlite3_value ** argv)
15600 {
15601 /* SQL function:
15602 / CastToLinestring(BLOB encoded geometry)
15603 /
15604 / returns a LINESTRING-type geometry [if conversion is possible]
15605 / or NULL in any other case
15606 */
15607     unsigned char *p_blob;
15608     int n_bytes;
15609     int len;
15610     unsigned char *p_result = NULL;
15611     int pts;
15612     int lns;
15613     int pgs;
15614     gaiaGeomCollPtr geo = NULL;
15615     gaiaGeomCollPtr geom2 = NULL;
15616     int gpkg_amphibious = 0;
15617     int gpkg_mode = 0;
15618     int tiny_point = 0;
15619     struct splite_internal_cache *cache = sqlite3_user_data (context);
15620     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15621     if (cache != NULL)
15622       {
15623 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15624 	  gpkg_mode = cache->gpkg_mode;
15625 	  tiny_point = cache->tinyPointEnabled;
15626       }
15627     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15628       {
15629 	  sqlite3_result_null (context);
15630 	  return;
15631       }
15632     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15633     n_bytes = sqlite3_value_bytes (argv[0]);
15634     geo =
15635 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15636 				     gpkg_amphibious);
15637     if (!geo)
15638 	sqlite3_result_null (context);
15639     else
15640       {
15641 	  cast_count (geo, &pts, &lns, &pgs);
15642 	  if (pts == 0 && lns == 1 && pgs == 0)
15643 	    {
15644 		geom2 = gaiaCloneGeomColl (geo);
15645 		geom2->Srid = geo->Srid;
15646 		geom2->DeclaredType = GAIA_LINESTRING;
15647 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15648 					    tiny_point);
15649 		gaiaFreeGeomColl (geom2);
15650 		sqlite3_result_blob (context, p_result, len, free);
15651 	    }
15652 	  else
15653 	      sqlite3_result_null (context);
15654       }
15655     gaiaFreeGeomColl (geo);
15656 }
15657 
15658 static void
fnct_CastToPolygon(sqlite3_context * context,int argc,sqlite3_value ** argv)15659 fnct_CastToPolygon (sqlite3_context * context, int argc, sqlite3_value ** argv)
15660 {
15661 /* SQL function:
15662 / CastToPolygon(BLOB encoded geometry)
15663 /
15664 / returns a POLYGON-type geometry [if conversion is possible]
15665 / or NULL in any other case
15666 */
15667     unsigned char *p_blob;
15668     int n_bytes;
15669     int len;
15670     unsigned char *p_result = NULL;
15671     int pts;
15672     int lns;
15673     int pgs;
15674     gaiaGeomCollPtr geo = NULL;
15675     gaiaGeomCollPtr geom2 = NULL;
15676     int gpkg_amphibious = 0;
15677     int gpkg_mode = 0;
15678     int tiny_point = 0;
15679     struct splite_internal_cache *cache = sqlite3_user_data (context);
15680     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15681     if (cache != NULL)
15682       {
15683 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15684 	  gpkg_mode = cache->gpkg_mode;
15685 	  tiny_point = cache->tinyPointEnabled;
15686       }
15687     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15688       {
15689 	  sqlite3_result_null (context);
15690 	  return;
15691       }
15692     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15693     n_bytes = sqlite3_value_bytes (argv[0]);
15694     geo =
15695 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15696 				     gpkg_amphibious);
15697     if (!geo)
15698 	sqlite3_result_null (context);
15699     else
15700       {
15701 	  cast_count (geo, &pts, &lns, &pgs);
15702 	  if (pts == 0 && lns == 0 && pgs == 1)
15703 	    {
15704 		geom2 = gaiaCloneGeomColl (geo);
15705 		geom2->Srid = geo->Srid;
15706 		geom2->DeclaredType = GAIA_POLYGON;
15707 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15708 					    tiny_point);
15709 		gaiaFreeGeomColl (geom2);
15710 		sqlite3_result_blob (context, p_result, len, free);
15711 	    }
15712 	  else
15713 	      sqlite3_result_null (context);
15714       }
15715     gaiaFreeGeomColl (geo);
15716 }
15717 
15718 static void
fnct_CastToMultiPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)15719 fnct_CastToMultiPoint (sqlite3_context * context, int argc,
15720 		       sqlite3_value ** argv)
15721 {
15722 /* SQL function:
15723 / CastToMultiPoint(BLOB encoded geometry)
15724 /
15725 / returns a MULTIPOINT-type geometry [if conversion is possible]
15726 / or NULL in any other case
15727 */
15728     unsigned char *p_blob;
15729     int n_bytes;
15730     int len;
15731     unsigned char *p_result = NULL;
15732     int pts;
15733     int lns;
15734     int pgs;
15735     gaiaGeomCollPtr geo = NULL;
15736     gaiaGeomCollPtr geom2 = NULL;
15737     int gpkg_amphibious = 0;
15738     int gpkg_mode = 0;
15739     int tiny_point = 0;
15740     struct splite_internal_cache *cache = sqlite3_user_data (context);
15741     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15742     if (cache != NULL)
15743       {
15744 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15745 	  gpkg_mode = cache->gpkg_mode;
15746 	  tiny_point = cache->tinyPointEnabled;
15747       }
15748     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15749       {
15750 	  sqlite3_result_null (context);
15751 	  return;
15752       }
15753     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15754     n_bytes = sqlite3_value_bytes (argv[0]);
15755     geo =
15756 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15757 				     gpkg_amphibious);
15758     if (!geo)
15759 	sqlite3_result_null (context);
15760     else
15761       {
15762 	  cast_count (geo, &pts, &lns, &pgs);
15763 	  if (pts >= 1 && lns == 0 && pgs == 0)
15764 	    {
15765 		geom2 = gaiaCloneGeomColl (geo);
15766 		geom2->Srid = geo->Srid;
15767 		geom2->DeclaredType = GAIA_MULTIPOINT;
15768 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15769 					    tiny_point);
15770 		gaiaFreeGeomColl (geom2);
15771 		sqlite3_result_blob (context, p_result, len, free);
15772 	    }
15773 	  else
15774 	      sqlite3_result_null (context);
15775       }
15776     gaiaFreeGeomColl (geo);
15777 }
15778 
15779 static void
fnct_CastToMultiLinestring(sqlite3_context * context,int argc,sqlite3_value ** argv)15780 fnct_CastToMultiLinestring (sqlite3_context * context, int argc,
15781 			    sqlite3_value ** argv)
15782 {
15783 /* SQL function:
15784 / CastToMultiLinestring(BLOB encoded geometry)
15785 /
15786 / returns a MULTILINESTRING-type geometry [if conversion is possible]
15787 / or NULL in any other case
15788 */
15789     unsigned char *p_blob;
15790     int n_bytes;
15791     int len;
15792     unsigned char *p_result = NULL;
15793     int pts;
15794     int lns;
15795     int pgs;
15796     gaiaGeomCollPtr geo = NULL;
15797     gaiaGeomCollPtr geom2 = NULL;
15798     int gpkg_amphibious = 0;
15799     int gpkg_mode = 0;
15800     int tiny_point = 0;
15801     struct splite_internal_cache *cache = sqlite3_user_data (context);
15802     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15803     if (cache != NULL)
15804       {
15805 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15806 	  gpkg_mode = cache->gpkg_mode;
15807 	  tiny_point = cache->tinyPointEnabled;
15808       }
15809     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15810       {
15811 	  sqlite3_result_null (context);
15812 	  return;
15813       }
15814     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15815     n_bytes = sqlite3_value_bytes (argv[0]);
15816     geo =
15817 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15818 				     gpkg_amphibious);
15819     if (!geo)
15820 	sqlite3_result_null (context);
15821     else
15822       {
15823 	  cast_count (geo, &pts, &lns, &pgs);
15824 	  if (pts == 0 && lns >= 1 && pgs == 0)
15825 	    {
15826 		geom2 = gaiaCloneGeomColl (geo);
15827 		geom2->Srid = geo->Srid;
15828 		geom2->DeclaredType = GAIA_MULTILINESTRING;
15829 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15830 					    tiny_point);
15831 		gaiaFreeGeomColl (geom2);
15832 		sqlite3_result_blob (context, p_result, len, free);
15833 	    }
15834 	  else
15835 	      sqlite3_result_null (context);
15836       }
15837     gaiaFreeGeomColl (geo);
15838 }
15839 
15840 static void
fnct_CastToMultiPolygon(sqlite3_context * context,int argc,sqlite3_value ** argv)15841 fnct_CastToMultiPolygon (sqlite3_context * context, int argc,
15842 			 sqlite3_value ** argv)
15843 {
15844 /* SQL function:
15845 / CastToMultiPolygon(BLOB encoded geometry)
15846 /
15847 / returns a MULTIPOLYGON-type geometry [if conversion is possible]
15848 / or NULL in any other case
15849 */
15850     unsigned char *p_blob;
15851     int n_bytes;
15852     int len;
15853     unsigned char *p_result = NULL;
15854     int pts;
15855     int lns;
15856     int pgs;
15857     gaiaGeomCollPtr geo = NULL;
15858     gaiaGeomCollPtr geom2 = NULL;
15859     int gpkg_amphibious = 0;
15860     int gpkg_mode = 0;
15861     int tiny_point = 0;
15862     struct splite_internal_cache *cache = sqlite3_user_data (context);
15863     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15864     if (cache != NULL)
15865       {
15866 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15867 	  gpkg_mode = cache->gpkg_mode;
15868 	  tiny_point = cache->tinyPointEnabled;
15869       }
15870     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15871       {
15872 	  sqlite3_result_null (context);
15873 	  return;
15874       }
15875     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15876     n_bytes = sqlite3_value_bytes (argv[0]);
15877     geo =
15878 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15879 				     gpkg_amphibious);
15880     if (!geo)
15881 	sqlite3_result_null (context);
15882     else
15883       {
15884 	  cast_count (geo, &pts, &lns, &pgs);
15885 	  if (pts == 0 && lns == 0 && pgs >= 1)
15886 	    {
15887 		geom2 = gaiaCloneGeomColl (geo);
15888 		geom2->Srid = geo->Srid;
15889 		geom2->DeclaredType = GAIA_MULTIPOLYGON;
15890 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15891 					    tiny_point);
15892 		gaiaFreeGeomColl (geom2);
15893 		sqlite3_result_blob (context, p_result, len, free);
15894 	    }
15895 	  else
15896 	      sqlite3_result_null (context);
15897       }
15898     gaiaFreeGeomColl (geo);
15899 }
15900 
15901 static void
fnct_CastToGeometryCollection(sqlite3_context * context,int argc,sqlite3_value ** argv)15902 fnct_CastToGeometryCollection (sqlite3_context * context, int argc,
15903 			       sqlite3_value ** argv)
15904 {
15905 /* SQL function:
15906 / CastToGeometryCollection(BLOB encoded geometry)
15907 /
15908 / returns a GEOMETRYCOLLECTION-type geometry [if conversion is possible]
15909 / or NULL in any other case
15910 */
15911     unsigned char *p_blob;
15912     int n_bytes;
15913     int len;
15914     unsigned char *p_result = NULL;
15915     int pts;
15916     int lns;
15917     int pgs;
15918     gaiaGeomCollPtr geo = NULL;
15919     gaiaGeomCollPtr geom2 = NULL;
15920     int gpkg_amphibious = 0;
15921     int gpkg_mode = 0;
15922     int tiny_point = 0;
15923     struct splite_internal_cache *cache = sqlite3_user_data (context);
15924     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15925     if (cache != NULL)
15926       {
15927 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15928 	  gpkg_mode = cache->gpkg_mode;
15929 	  tiny_point = cache->tinyPointEnabled;
15930       }
15931     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15932       {
15933 	  sqlite3_result_null (context);
15934 	  return;
15935       }
15936     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15937     n_bytes = sqlite3_value_bytes (argv[0]);
15938     geo =
15939 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
15940 				     gpkg_amphibious);
15941     if (!geo)
15942 	sqlite3_result_null (context);
15943     else
15944       {
15945 	  cast_count (geo, &pts, &lns, &pgs);
15946 	  if (pts >= 1 || lns >= 1 || pgs >= 1)
15947 	    {
15948 		geom2 = gaiaCloneGeomColl (geo);
15949 		geom2->Srid = geo->Srid;
15950 		geom2->DeclaredType = GAIA_GEOMETRYCOLLECTION;
15951 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
15952 					    tiny_point);
15953 		gaiaFreeGeomColl (geom2);
15954 		sqlite3_result_blob (context, p_result, len, free);
15955 	    }
15956 	  else
15957 	      sqlite3_result_null (context);
15958       }
15959     gaiaFreeGeomColl (geo);
15960 }
15961 
15962 static void
fnct_CastToMulti(sqlite3_context * context,int argc,sqlite3_value ** argv)15963 fnct_CastToMulti (sqlite3_context * context, int argc, sqlite3_value ** argv)
15964 {
15965 /* SQL function:
15966 / CastToMulti(BLOB encoded geometry)
15967 /
15968 / returns a MULTIPOINT, MULTILINESTRING, MULTIPOLYGON or
15969 / GEOMETRYCOLLECTION-type geometry [if conversion is possible]
15970 / or NULL in any other case
15971 */
15972     unsigned char *p_blob;
15973     int n_bytes;
15974     int len;
15975     unsigned char *p_result = NULL;
15976     int pts;
15977     int lns;
15978     int pgs;
15979     gaiaGeomCollPtr geo = NULL;
15980     gaiaGeomCollPtr geom2 = NULL;
15981     int gpkg_amphibious = 0;
15982     int gpkg_mode = 0;
15983     int tiny_point = 0;
15984     struct splite_internal_cache *cache = sqlite3_user_data (context);
15985     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
15986     if (cache != NULL)
15987       {
15988 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
15989 	  gpkg_mode = cache->gpkg_mode;
15990 	  tiny_point = cache->tinyPointEnabled;
15991       }
15992     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
15993       {
15994 	  sqlite3_result_null (context);
15995 	  return;
15996       }
15997     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
15998     n_bytes = sqlite3_value_bytes (argv[0]);
15999     geo =
16000 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16001 				     gpkg_amphibious);
16002     if (!geo)
16003 	sqlite3_result_null (context);
16004     else
16005       {
16006 	  cast_count (geo, &pts, &lns, &pgs);
16007 	  if (pts >= 1 || lns >= 1 || pgs >= 1)
16008 	    {
16009 		geom2 = gaiaCloneGeomColl (geo);
16010 		geom2->Srid = geo->Srid;
16011 		if (pts >= 1 && lns == 0 && pgs == 0)
16012 		    geom2->DeclaredType = GAIA_MULTIPOINT;
16013 		else if (pts == 0 && lns >= 1 && pgs == 0)
16014 		    geom2->DeclaredType = GAIA_MULTILINESTRING;
16015 		else if (pts == 0 && lns == 0 && pgs >= 1)
16016 		    geom2->DeclaredType = GAIA_MULTIPOLYGON;
16017 		else
16018 		    geom2->DeclaredType = GAIA_GEOMETRYCOLLECTION;
16019 		if (geo->DeclaredType == GAIA_GEOMETRYCOLLECTION)
16020 		    geom2->DeclaredType = GAIA_GEOMETRYCOLLECTION;
16021 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16022 					    tiny_point);
16023 		gaiaFreeGeomColl (geom2);
16024 		sqlite3_result_blob (context, p_result, len, free);
16025 	    }
16026 	  else
16027 	      sqlite3_result_null (context);
16028       }
16029     gaiaFreeGeomColl (geo);
16030 }
16031 
16032 static void
fnct_CastToSingle(sqlite3_context * context,int argc,sqlite3_value ** argv)16033 fnct_CastToSingle (sqlite3_context * context, int argc, sqlite3_value ** argv)
16034 {
16035 /* SQL function:
16036 / CastToSingle(BLOB encoded geometry)
16037 /
16038 / returns a POINT, LINESTRING or POLYGON-type geometry [if conversion is possible]
16039 / or NULL in any other case
16040 */
16041     unsigned char *p_blob;
16042     int n_bytes;
16043     int len;
16044     unsigned char *p_result = NULL;
16045     int pts;
16046     int lns;
16047     int pgs;
16048     int ok;
16049     gaiaGeomCollPtr geo = NULL;
16050     gaiaGeomCollPtr geom2 = NULL;
16051     int gpkg_amphibious = 0;
16052     int gpkg_mode = 0;
16053     int tiny_point = 0;
16054     struct splite_internal_cache *cache = sqlite3_user_data (context);
16055     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16056     if (cache != NULL)
16057       {
16058 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16059 	  gpkg_mode = cache->gpkg_mode;
16060 	  tiny_point = cache->tinyPointEnabled;
16061       }
16062     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16063       {
16064 	  sqlite3_result_null (context);
16065 	  return;
16066       }
16067     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16068     n_bytes = sqlite3_value_bytes (argv[0]);
16069     geo =
16070 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16071 				     gpkg_amphibious);
16072     if (!geo)
16073 	sqlite3_result_null (context);
16074     else
16075       {
16076 	  cast_count (geo, &pts, &lns, &pgs);
16077 	  ok = 0;
16078 	  if (pts == 1 && lns == 0 && pgs == 0)
16079 	      ok = 1;
16080 	  if (pts == 0 && lns == 1 && pgs == 0)
16081 	      ok = 1;
16082 	  if (pts == 0 && lns == 0 && pgs == 1)
16083 	      ok = 1;
16084 	  if (ok)
16085 	    {
16086 		geom2 = gaiaCloneGeomColl (geo);
16087 		geom2->Srid = geo->Srid;
16088 		if (pts == 1)
16089 		    geom2->DeclaredType = GAIA_POINT;
16090 		else if (lns == 1)
16091 		    geom2->DeclaredType = GAIA_LINESTRING;
16092 		else
16093 		    geom2->DeclaredType = GAIA_POLYGON;
16094 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16095 					    tiny_point);
16096 		gaiaFreeGeomColl (geom2);
16097 		sqlite3_result_blob (context, p_result, len, free);
16098 	    }
16099 	  else
16100 	      sqlite3_result_null (context);
16101       }
16102     gaiaFreeGeomColl (geo);
16103 }
16104 
16105 static void
fnct_CastToXY(sqlite3_context * context,int argc,sqlite3_value ** argv)16106 fnct_CastToXY (sqlite3_context * context, int argc, sqlite3_value ** argv)
16107 {
16108 /* SQL function:
16109 / CastToXY(BLOB encoded geometry)
16110 /
16111 / returns an XY-dimension Geometry [if conversion is possible]
16112 / or NULL in any other case
16113 */
16114     unsigned char *p_blob;
16115     int n_bytes;
16116     int len;
16117     unsigned char *p_result = NULL;
16118     gaiaGeomCollPtr geo = NULL;
16119     gaiaGeomCollPtr geom2 = NULL;
16120     int gpkg_amphibious = 0;
16121     int gpkg_mode = 0;
16122     int tiny_point = 0;
16123     struct splite_internal_cache *cache = sqlite3_user_data (context);
16124     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16125     if (cache != NULL)
16126       {
16127 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16128 	  gpkg_mode = cache->gpkg_mode;
16129 	  tiny_point = cache->tinyPointEnabled;
16130       }
16131     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16132       {
16133 	  sqlite3_result_null (context);
16134 	  return;
16135       }
16136     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16137     n_bytes = sqlite3_value_bytes (argv[0]);
16138     geo =
16139 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16140 				     gpkg_amphibious);
16141     if (!geo)
16142 	sqlite3_result_null (context);
16143     else
16144       {
16145 	  geom2 = gaiaCastGeomCollToXY (geo);
16146 	  if (geom2)
16147 	    {
16148 		geom2->Srid = geo->Srid;
16149 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16150 					    tiny_point);
16151 		gaiaFreeGeomColl (geom2);
16152 		sqlite3_result_blob (context, p_result, len, free);
16153 	    }
16154 	  else
16155 	      sqlite3_result_null (context);
16156       }
16157     gaiaFreeGeomColl (geo);
16158 }
16159 
16160 static void
fnct_CastToXYZ(sqlite3_context * context,int argc,sqlite3_value ** argv)16161 fnct_CastToXYZ (sqlite3_context * context, int argc, sqlite3_value ** argv)
16162 {
16163 /* SQL function:
16164 / CastToXYZ(BLOB encoded geometry)
16165 /    or
16166 / CastToXYZ(BLOB encoded geometry, nodata double)
16167 /
16168 / returns an XY-dimension Geometry [if conversion is possible]
16169 / or NULL in any other case
16170 */
16171     unsigned char *p_blob;
16172     int n_bytes;
16173     int len;
16174     unsigned char *p_result = NULL;
16175     double no_data;
16176     int has_no_data = 0;
16177     gaiaGeomCollPtr geo = NULL;
16178     gaiaGeomCollPtr geom2 = NULL;
16179     int gpkg_amphibious = 0;
16180     int gpkg_mode = 0;
16181     int tiny_point = 0;
16182     struct splite_internal_cache *cache = sqlite3_user_data (context);
16183     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16184     if (cache != NULL)
16185       {
16186 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16187 	  gpkg_mode = cache->gpkg_mode;
16188 	  tiny_point = cache->tinyPointEnabled;
16189       }
16190     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16191       {
16192 	  sqlite3_result_null (context);
16193 	  return;
16194       }
16195     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16196     n_bytes = sqlite3_value_bytes (argv[0]);
16197     if (argc >= 2)
16198       {
16199 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
16200 	    {
16201 		int val = sqlite3_value_int (argv[1]);
16202 		no_data = val;
16203 		has_no_data = 1;
16204 	    }
16205 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
16206 	    {
16207 		no_data = sqlite3_value_double (argv[1]);
16208 		has_no_data = 1;
16209 	    }
16210 	  else
16211 	    {
16212 		sqlite3_result_null (context);
16213 		return;
16214 	    }
16215       }
16216     geo =
16217 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16218 				     gpkg_amphibious);
16219     if (!geo)
16220 	sqlite3_result_null (context);
16221     else
16222       {
16223 	  if (has_no_data)
16224 	      geom2 = gaiaCastGeomCollToXYZnoData (geo, no_data);
16225 	  else
16226 	      geom2 = gaiaCastGeomCollToXYZ (geo);
16227 	  if (geom2)
16228 	    {
16229 		geom2->Srid = geo->Srid;
16230 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16231 					    tiny_point);
16232 		gaiaFreeGeomColl (geom2);
16233 		sqlite3_result_blob (context, p_result, len, free);
16234 	    }
16235 	  else
16236 	      sqlite3_result_null (context);
16237       }
16238     gaiaFreeGeomColl (geo);
16239 }
16240 
16241 static void
fnct_CastToXYM(sqlite3_context * context,int argc,sqlite3_value ** argv)16242 fnct_CastToXYM (sqlite3_context * context, int argc, sqlite3_value ** argv)
16243 {
16244 /* SQL function:
16245 / CastToXYM(BLOB encoded geometry)
16246 /    or
16247 / CastToXYM(BLOB encoded geometry. nodata double)
16248 /
16249 / returns an XYM-dimension Geometry [if conversion is possible]
16250 / or NULL in any other case
16251 */
16252     unsigned char *p_blob;
16253     int n_bytes;
16254     int len;
16255     unsigned char *p_result = NULL;
16256     double no_data;
16257     int has_no_data = 0;
16258     gaiaGeomCollPtr geo = NULL;
16259     gaiaGeomCollPtr geom2 = NULL;
16260     int gpkg_amphibious = 0;
16261     int gpkg_mode = 0;
16262     int tiny_point = 0;
16263     struct splite_internal_cache *cache = sqlite3_user_data (context);
16264     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16265     if (cache != NULL)
16266       {
16267 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16268 	  gpkg_mode = cache->gpkg_mode;
16269 	  tiny_point = cache->tinyPointEnabled;
16270       }
16271     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16272       {
16273 	  sqlite3_result_null (context);
16274 	  return;
16275       }
16276     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16277     n_bytes = sqlite3_value_bytes (argv[0]);
16278     if (argc >= 2)
16279       {
16280 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
16281 	    {
16282 		int val = sqlite3_value_int (argv[1]);
16283 		no_data = val;
16284 		has_no_data = 1;
16285 	    }
16286 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
16287 	    {
16288 		no_data = sqlite3_value_double (argv[1]);
16289 		has_no_data = 1;
16290 	    }
16291 	  else
16292 	    {
16293 		sqlite3_result_null (context);
16294 		return;
16295 	    }
16296       }
16297     geo =
16298 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16299 				     gpkg_amphibious);
16300     if (!geo)
16301 	sqlite3_result_null (context);
16302     else
16303       {
16304 	  if (has_no_data)
16305 	      geom2 = gaiaCastGeomCollToXYMnoData (geo, no_data);
16306 	  else
16307 	      geom2 = gaiaCastGeomCollToXYM (geo);
16308 	  if (geom2)
16309 	    {
16310 		geom2->Srid = geo->Srid;
16311 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16312 					    tiny_point);
16313 		gaiaFreeGeomColl (geom2);
16314 		sqlite3_result_blob (context, p_result, len, free);
16315 	    }
16316 	  else
16317 	      sqlite3_result_null (context);
16318       }
16319     gaiaFreeGeomColl (geo);
16320 }
16321 
16322 static void
fnct_CastToXYZM(sqlite3_context * context,int argc,sqlite3_value ** argv)16323 fnct_CastToXYZM (sqlite3_context * context, int argc, sqlite3_value ** argv)
16324 {
16325 /* SQL function:
16326 / CastToXYZM(BLOB encoded geometry)
16327 /    or
16328 / CastToXYZM(BLOB encoded geometry, nodata_z double, nodata_m double)
16329 /
16330 / returns an XYZM-dimension Geometry [if conversion is possible]
16331 / or NULL in any other case
16332 */
16333     unsigned char *p_blob;
16334     int n_bytes;
16335     int len;
16336     unsigned char *p_result = NULL;
16337     double z_no_data;
16338     double m_no_data;
16339     int has_no_data = 0;
16340     gaiaGeomCollPtr geo = NULL;
16341     gaiaGeomCollPtr geom2 = NULL;
16342     int gpkg_amphibious = 0;
16343     int gpkg_mode = 0;
16344     int tiny_point = 0;
16345     struct splite_internal_cache *cache = sqlite3_user_data (context);
16346     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16347     if (cache != NULL)
16348       {
16349 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16350 	  gpkg_mode = cache->gpkg_mode;
16351 	  tiny_point = cache->tinyPointEnabled;
16352       }
16353     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16354       {
16355 	  sqlite3_result_null (context);
16356 	  return;
16357       }
16358     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16359     n_bytes = sqlite3_value_bytes (argv[0]);
16360     if (argc >= 3)
16361       {
16362 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
16363 	    {
16364 		int val = sqlite3_value_int (argv[1]);
16365 		z_no_data = val;
16366 	    }
16367 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
16368 	      z_no_data = sqlite3_value_double (argv[1]);
16369 	  else
16370 	    {
16371 		sqlite3_result_null (context);
16372 		return;
16373 	    }
16374 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
16375 	    {
16376 		int val = sqlite3_value_int (argv[2]);
16377 		m_no_data = val;
16378 	    }
16379 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
16380 	      m_no_data = sqlite3_value_double (argv[2]);
16381 	  else
16382 	    {
16383 		sqlite3_result_null (context);
16384 		return;
16385 	    }
16386 	  has_no_data = 1;
16387       }
16388     geo =
16389 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16390 				     gpkg_amphibious);
16391     if (!geo)
16392 	sqlite3_result_null (context);
16393     else
16394       {
16395 	  if (has_no_data)
16396 	      geom2 = gaiaCastGeomCollToXYZMnoData (geo, z_no_data, m_no_data);
16397 	  else
16398 	      geom2 = gaiaCastGeomCollToXYZM (geo);
16399 	  if (geom2)
16400 	    {
16401 		geom2->Srid = geo->Srid;
16402 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16403 					    tiny_point);
16404 		gaiaFreeGeomColl (geom2);
16405 		sqlite3_result_blob (context, p_result, len, free);
16406 	    }
16407 	  else
16408 	      sqlite3_result_null (context);
16409       }
16410     gaiaFreeGeomColl (geo);
16411 }
16412 
16413 static void
fnct_ExtractMultiPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)16414 fnct_ExtractMultiPoint (sqlite3_context * context, int argc,
16415 			sqlite3_value ** argv)
16416 {
16417 /* SQL function:
16418 / ExtractMultiPoint(BLOB encoded geometry)
16419 /
16420 / returns a MULTIPOINT-type geometry [if conversion is possible]
16421 / or NULL in any other case
16422 */
16423     unsigned char *p_blob;
16424     int n_bytes;
16425     int len;
16426     unsigned char *p_result = NULL;
16427     int pts;
16428     int lns;
16429     int pgs;
16430     gaiaGeomCollPtr geo = NULL;
16431     gaiaGeomCollPtr geom2 = NULL;
16432     int gpkg_amphibious = 0;
16433     int gpkg_mode = 0;
16434     int tiny_point = 0;
16435     struct splite_internal_cache *cache = sqlite3_user_data (context);
16436     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16437     if (cache != NULL)
16438       {
16439 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16440 	  gpkg_mode = cache->gpkg_mode;
16441 	  tiny_point = cache->tinyPointEnabled;
16442       }
16443     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16444       {
16445 	  sqlite3_result_null (context);
16446 	  return;
16447       }
16448     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16449     n_bytes = sqlite3_value_bytes (argv[0]);
16450     geo =
16451 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16452 				     gpkg_amphibious);
16453     if (!geo)
16454 	sqlite3_result_null (context);
16455     else
16456       {
16457 	  cast_count (geo, &pts, &lns, &pgs);
16458 	  if (pts >= 1)
16459 	    {
16460 		geom2 = gaiaCloneGeomCollPoints (geo);
16461 		geom2->Srid = geo->Srid;
16462 		geom2->DeclaredType = GAIA_MULTIPOINT;
16463 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16464 					    tiny_point);
16465 		gaiaFreeGeomColl (geom2);
16466 		sqlite3_result_blob (context, p_result, len, free);
16467 	    }
16468 	  else
16469 	      sqlite3_result_null (context);
16470       }
16471     gaiaFreeGeomColl (geo);
16472 }
16473 
16474 static void
fnct_ExtractMultiLinestring(sqlite3_context * context,int argc,sqlite3_value ** argv)16475 fnct_ExtractMultiLinestring (sqlite3_context * context, int argc,
16476 			     sqlite3_value ** argv)
16477 {
16478 /* SQL function:
16479 / ExtractMultiLinestring(BLOB encoded geometry)
16480 /
16481 / returns a MULTILINESTRING-type geometry [if conversion is possible]
16482 / or NULL in any other case
16483 */
16484     unsigned char *p_blob;
16485     int n_bytes;
16486     int len;
16487     unsigned char *p_result = NULL;
16488     int pts;
16489     int lns;
16490     int pgs;
16491     gaiaGeomCollPtr geo = NULL;
16492     gaiaGeomCollPtr geom2 = NULL;
16493     int gpkg_amphibious = 0;
16494     int gpkg_mode = 0;
16495     int tiny_point = 0;
16496     struct splite_internal_cache *cache = sqlite3_user_data (context);
16497     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16498     if (cache != NULL)
16499       {
16500 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16501 	  gpkg_mode = cache->gpkg_mode;
16502 	  tiny_point = cache->tinyPointEnabled;
16503       }
16504     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16505       {
16506 	  sqlite3_result_null (context);
16507 	  return;
16508       }
16509     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16510     n_bytes = sqlite3_value_bytes (argv[0]);
16511     geo =
16512 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16513 				     gpkg_amphibious);
16514     if (!geo)
16515 	sqlite3_result_null (context);
16516     else
16517       {
16518 	  cast_count (geo, &pts, &lns, &pgs);
16519 	  if (lns >= 1)
16520 	    {
16521 		geom2 = gaiaCloneGeomCollLinestrings (geo);
16522 		geom2->Srid = geo->Srid;
16523 		geom2->DeclaredType = GAIA_MULTILINESTRING;
16524 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16525 					    tiny_point);
16526 		gaiaFreeGeomColl (geom2);
16527 		sqlite3_result_blob (context, p_result, len, free);
16528 	    }
16529 	  else
16530 	      sqlite3_result_null (context);
16531       }
16532     gaiaFreeGeomColl (geo);
16533 }
16534 
16535 static void
fnct_ExtractMultiPolygon(sqlite3_context * context,int argc,sqlite3_value ** argv)16536 fnct_ExtractMultiPolygon (sqlite3_context * context, int argc,
16537 			  sqlite3_value ** argv)
16538 {
16539 /* SQL function:
16540 / ExtractMultiPolygon(BLOB encoded geometry)
16541 /
16542 / returns a MULTIPOLYGON-type geometry [if conversion is possible]
16543 / or NULL in any other case
16544 */
16545     unsigned char *p_blob;
16546     int n_bytes;
16547     int len;
16548     unsigned char *p_result = NULL;
16549     int pts;
16550     int lns;
16551     int pgs;
16552     gaiaGeomCollPtr geo = NULL;
16553     gaiaGeomCollPtr geom2 = NULL;
16554     int gpkg_amphibious = 0;
16555     int gpkg_mode = 0;
16556     int tiny_point = 0;
16557     struct splite_internal_cache *cache = sqlite3_user_data (context);
16558     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16559     if (cache != NULL)
16560       {
16561 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16562 	  gpkg_mode = cache->gpkg_mode;
16563 	  tiny_point = cache->tinyPointEnabled;
16564       }
16565     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16566       {
16567 	  sqlite3_result_null (context);
16568 	  return;
16569       }
16570     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16571     n_bytes = sqlite3_value_bytes (argv[0]);
16572     geo =
16573 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16574 				     gpkg_amphibious);
16575     if (!geo)
16576 	sqlite3_result_null (context);
16577     else
16578       {
16579 	  cast_count (geo, &pts, &lns, &pgs);
16580 	  if (pgs >= 1)
16581 	    {
16582 		geom2 = gaiaCloneGeomCollPolygons (geo);
16583 		geom2->Srid = geo->Srid;
16584 		geom2->DeclaredType = GAIA_MULTIPOLYGON;
16585 		gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16586 					    tiny_point);
16587 		gaiaFreeGeomColl (geom2);
16588 		sqlite3_result_blob (context, p_result, len, free);
16589 	    }
16590 	  else
16591 	      sqlite3_result_null (context);
16592       }
16593     gaiaFreeGeomColl (geo);
16594 }
16595 
16596 static void
fnct_Reverse(sqlite3_context * context,int argc,sqlite3_value ** argv)16597 fnct_Reverse (sqlite3_context * context, int argc, sqlite3_value ** argv)
16598 {
16599 /* SQL function:
16600 / ST_Reverse(BLOB encoded geometry)
16601 /
16602 / returns a new Geometry: any Linestring or Ring will be in reverse order
16603 / or NULL in any other case
16604 */
16605     unsigned char *p_blob;
16606     int n_bytes;
16607     int len;
16608     unsigned char *p_result = NULL;
16609     gaiaGeomCollPtr geo = NULL;
16610     gaiaGeomCollPtr geom2 = NULL;
16611     int gpkg_amphibious = 0;
16612     int gpkg_mode = 0;
16613     int tiny_point = 0;
16614     struct splite_internal_cache *cache = sqlite3_user_data (context);
16615     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16616     if (cache != NULL)
16617       {
16618 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16619 	  gpkg_mode = cache->gpkg_mode;
16620 	  tiny_point = cache->tinyPointEnabled;
16621       }
16622     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16623       {
16624 	  sqlite3_result_null (context);
16625 	  return;
16626       }
16627     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16628     n_bytes = sqlite3_value_bytes (argv[0]);
16629     geo =
16630 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16631 				     gpkg_amphibious);
16632     if (!geo)
16633 	sqlite3_result_null (context);
16634     else
16635       {
16636 	  geom2 = gaiaCloneGeomCollSpecial (geo, GAIA_REVERSE_ORDER);
16637 	  geom2->Srid = geo->Srid;
16638 	  gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16639 				      tiny_point);
16640 	  gaiaFreeGeomColl (geom2);
16641 	  sqlite3_result_blob (context, p_result, len, free);
16642 	  gaiaFreeGeomColl (geo);
16643       }
16644 }
16645 
16646 static void
fnct_ForcePolygonCW(sqlite3_context * context,int argc,sqlite3_value ** argv)16647 fnct_ForcePolygonCW (sqlite3_context * context, int argc, sqlite3_value ** argv)
16648 {
16649 /* SQL function:
16650 / ST_ForcePolygonCW(BLOB encoded geometry)
16651 /    or
16652 / ST_ForceLHR(BLOB encoded geometry)
16653 /
16654 / returns a new Geometry: any Exterior Ring will be in clockwise orientation
16655 /         and any Interior Ring will be in counter-clockwise orientation
16656 / or NULL on invalid geometries
16657 */
16658     unsigned char *p_blob;
16659     int n_bytes;
16660     int len;
16661     unsigned char *p_result = NULL;
16662     gaiaGeomCollPtr geo = NULL;
16663     gaiaGeomCollPtr geom2 = NULL;
16664     int gpkg_amphibious = 0;
16665     int gpkg_mode = 0;
16666     int tiny_point = 0;
16667     struct splite_internal_cache *cache = sqlite3_user_data (context);
16668     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16669     if (cache != NULL)
16670       {
16671 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16672 	  gpkg_mode = cache->gpkg_mode;
16673 	  tiny_point = cache->tinyPointEnabled;
16674       }
16675     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16676       {
16677 	  sqlite3_result_null (context);
16678 	  return;
16679       }
16680     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16681     n_bytes = sqlite3_value_bytes (argv[0]);
16682     geo =
16683 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16684 				     gpkg_amphibious);
16685     if (!geo)
16686 	sqlite3_result_null (context);
16687     else
16688       {
16689 	  geom2 = gaiaCloneGeomCollSpecial (geo, GAIA_CW_ORDER);
16690 	  geom2->Srid = geo->Srid;
16691 	  gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16692 				      tiny_point);
16693 	  gaiaFreeGeomColl (geom2);
16694 	  sqlite3_result_blob (context, p_result, len, free);
16695 	  gaiaFreeGeomColl (geo);
16696       }
16697 }
16698 
16699 static void
fnct_ForcePolygonCCW(sqlite3_context * context,int argc,sqlite3_value ** argv)16700 fnct_ForcePolygonCCW (sqlite3_context * context, int argc,
16701 		      sqlite3_value ** argv)
16702 {
16703 /* SQL function:
16704 / ST_ForcePolygonCCW(BLOB encoded geometry)
16705 /
16706 / returns a new Geometry: any Exterior Ring will be in counter-clockwise
16707 / orientation and any Interior Ring will be in clockwise orientation
16708 / or NULL on invalid geometries
16709 */
16710     unsigned char *p_blob;
16711     int n_bytes;
16712     int len;
16713     unsigned char *p_result = NULL;
16714     gaiaGeomCollPtr geo = NULL;
16715     gaiaGeomCollPtr geom2 = NULL;
16716     int gpkg_amphibious = 0;
16717     int gpkg_mode = 0;
16718     int tiny_point = 0;
16719     struct splite_internal_cache *cache = sqlite3_user_data (context);
16720     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16721     if (cache != NULL)
16722       {
16723 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16724 	  gpkg_mode = cache->gpkg_mode;
16725 	  tiny_point = cache->tinyPointEnabled;
16726       }
16727     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16728       {
16729 	  sqlite3_result_null (context);
16730 	  return;
16731       }
16732     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16733     n_bytes = sqlite3_value_bytes (argv[0]);
16734     geo =
16735 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16736 				     gpkg_amphibious);
16737     if (!geo)
16738 	sqlite3_result_null (context);
16739     else
16740       {
16741 	  geom2 = gaiaCloneGeomCollSpecial (geo, GAIA_CCW_ORDER);
16742 	  geom2->Srid = geo->Srid;
16743 	  gaiaToSpatiaLiteBlobWkbEx2 (geom2, &p_result, &len, gpkg_mode,
16744 				      tiny_point);
16745 	  gaiaFreeGeomColl (geom2);
16746 	  sqlite3_result_blob (context, p_result, len, free);
16747 	  gaiaFreeGeomColl (geo);
16748       }
16749 }
16750 
16751 static void
fnct_IsPolygonCW(sqlite3_context * context,int argc,sqlite3_value ** argv)16752 fnct_IsPolygonCW (sqlite3_context * context, int argc, sqlite3_value ** argv)
16753 {
16754 /* SQL function:
16755 / ST_IsPolygonCW(BLOB encoded geometry)
16756 /
16757 / returns TRUE if all Exterior Rings are in clockwise orientation
16758 / and all Interior Ring are in counter-clockwise orientation,
16759 / FALSE if not
16760 / and -1 on invalid geometries
16761 */
16762     unsigned char *p_blob;
16763     int n_bytes;
16764     gaiaGeomCollPtr geo = NULL;
16765     int gpkg_amphibious = 0;
16766     int gpkg_mode = 0;
16767     struct splite_internal_cache *cache = sqlite3_user_data (context);
16768     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16769     if (cache != NULL)
16770       {
16771 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16772 	  gpkg_mode = cache->gpkg_mode;
16773       }
16774     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16775       {
16776 	  sqlite3_result_int (context, -1);
16777 	  return;
16778       }
16779     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16780     n_bytes = sqlite3_value_bytes (argv[0]);
16781     geo =
16782 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16783 				     gpkg_amphibious);
16784     if (!geo)
16785 	sqlite3_result_int (context, -1);
16786     else
16787       {
16788 	  int retval = gaiaCheckClockwise (geo);
16789 	  sqlite3_result_int (context, retval);
16790 	  gaiaFreeGeomColl (geo);
16791       }
16792 }
16793 
16794 static void
fnct_IsPolygonCCW(sqlite3_context * context,int argc,sqlite3_value ** argv)16795 fnct_IsPolygonCCW (sqlite3_context * context, int argc, sqlite3_value ** argv)
16796 {
16797 /* SQL function:
16798 / ST_IsPolygonCCW(BLOB encoded geometry)
16799 /
16800 / returns TRUE if all Exterior Rings are in counter-clockwise
16801 / orientation and all Interior Ring are in clockwise orientation,
16802 / FALSE if not
16803 / and NULL on invalid geometries
16804 */
16805     unsigned char *p_blob;
16806     int n_bytes;
16807     gaiaGeomCollPtr geo = NULL;
16808     int gpkg_amphibious = 0;
16809     int gpkg_mode = 0;
16810     struct splite_internal_cache *cache = sqlite3_user_data (context);
16811     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16812     if (cache != NULL)
16813       {
16814 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16815 	  gpkg_mode = cache->gpkg_mode;
16816       }
16817     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16818       {
16819 	  sqlite3_result_int (context, -1);
16820 	  return;
16821       }
16822     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16823     n_bytes = sqlite3_value_bytes (argv[0]);
16824     geo =
16825 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16826 				     gpkg_amphibious);
16827     if (!geo)
16828 	sqlite3_result_int (context, -1);
16829     else
16830       {
16831 	  int retval = gaiaCheckCounterClockwise (geo);
16832 	  sqlite3_result_int (context, retval);
16833 	  gaiaFreeGeomColl (geo);
16834       }
16835 }
16836 
16837 static void
fnct_Dimension(sqlite3_context * context,int argc,sqlite3_value ** argv)16838 fnct_Dimension (sqlite3_context * context, int argc, sqlite3_value ** argv)
16839 {
16840 /* SQL function:
16841 / Dimension(BLOB encoded geometry)
16842 /
16843 / returns:
16844 / 0 if geometry is a POINT or MULTIPOINT
16845 / 1 if geometry is a LINESTRING or MULTILINESTRING
16846 / 2 if geometry is a POLYGON or MULTIPOLYGON
16847 / 0, 1, 2, for GEOMETRYCOLLECTIONS according to geometries contained inside
16848 / or NULL if any error is encountered
16849 */
16850     unsigned char *p_blob;
16851     int n_bytes;
16852     int dim;
16853     gaiaGeomCollPtr geo = NULL;
16854     int gpkg_amphibious = 0;
16855     int gpkg_mode = 0;
16856     struct splite_internal_cache *cache = sqlite3_user_data (context);
16857     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16858     if (cache != NULL)
16859       {
16860 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16861 	  gpkg_mode = cache->gpkg_mode;
16862       }
16863     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16864       {
16865 	  sqlite3_result_null (context);
16866 	  return;
16867       }
16868     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16869     n_bytes = sqlite3_value_bytes (argv[0]);
16870     geo =
16871 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16872 				     gpkg_amphibious);
16873     if (!geo)
16874 	sqlite3_result_null (context);
16875     else
16876       {
16877 	  dim = gaiaDimension (geo);
16878 	  sqlite3_result_int (context, dim);
16879       }
16880     gaiaFreeGeomColl (geo);
16881 }
16882 
16883 static void
fnct_CoordDimension(sqlite3_context * context,int argc,sqlite3_value ** argv)16884 fnct_CoordDimension (sqlite3_context * context, int argc, sqlite3_value ** argv)
16885 {
16886 /* SQL function:
16887 / CoordDimension(BLOB encoded geometry)
16888 /
16889 / returns:
16890 / 'XY', 'XYM', 'XYZ', 'XYZM'
16891 / or NULL if any error is encountered
16892 */
16893     unsigned char *p_blob;
16894     int n_bytes;
16895     int len;
16896     char *p_dim = NULL;
16897     char *p_result = NULL;
16898     gaiaGeomCollPtr geo = NULL;
16899     int gpkg_amphibious = 0;
16900     int gpkg_mode = 0;
16901     struct splite_internal_cache *cache = sqlite3_user_data (context);
16902     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16903     if (cache != NULL)
16904       {
16905 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16906 	  gpkg_mode = cache->gpkg_mode;
16907       }
16908     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16909       {
16910 	  sqlite3_result_null (context);
16911 	  return;
16912       }
16913     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16914     n_bytes = sqlite3_value_bytes (argv[0]);
16915     geo =
16916 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16917 				     gpkg_amphibious);
16918     if (!geo)
16919 	sqlite3_result_null (context);
16920     else
16921       {
16922 	  if (geo->DimensionModel == GAIA_XY)
16923 	      p_dim = "XY";
16924 	  else if (geo->DimensionModel == GAIA_XY_Z)
16925 	      p_dim = "XYZ";
16926 	  else if (geo->DimensionModel == GAIA_XY_M)
16927 	      p_dim = "XYM";
16928 	  else if (geo->DimensionModel == GAIA_XY_Z_M)
16929 	      p_dim = "XYZM";
16930 	  if (p_dim)
16931 	    {
16932 		len = strlen (p_dim);
16933 		p_result = malloc (len + 1);
16934 		strcpy (p_result, p_dim);
16935 	    }
16936 	  if (!p_result)
16937 	      sqlite3_result_null (context);
16938 	  else
16939 	    {
16940 		len = strlen (p_result);
16941 		sqlite3_result_text (context, p_result, len, free);
16942 	    }
16943       }
16944     gaiaFreeGeomColl (geo);
16945 }
16946 
16947 static void
fnct_NDims(sqlite3_context * context,int argc,sqlite3_value ** argv)16948 fnct_NDims (sqlite3_context * context, int argc, sqlite3_value ** argv)
16949 {
16950 /* SQL function:
16951 / ST_NDims(BLOB encoded geometry)
16952 /
16953 / returns:
16954 / 2, 3 or 4
16955 / or NULL if any error is encountered
16956 */
16957     unsigned char *p_blob;
16958     int n_bytes;
16959     int result = 0;
16960     gaiaGeomCollPtr geo = NULL;
16961     int gpkg_amphibious = 0;
16962     int gpkg_mode = 0;
16963     struct splite_internal_cache *cache = sqlite3_user_data (context);
16964     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
16965     if (cache != NULL)
16966       {
16967 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
16968 	  gpkg_mode = cache->gpkg_mode;
16969       }
16970     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
16971       {
16972 	  sqlite3_result_null (context);
16973 	  return;
16974       }
16975     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
16976     n_bytes = sqlite3_value_bytes (argv[0]);
16977     geo =
16978 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
16979 				     gpkg_amphibious);
16980     if (!geo)
16981 	sqlite3_result_null (context);
16982     else
16983       {
16984 	  if (geo->DimensionModel == GAIA_XY)
16985 	      result = 2;
16986 	  else if (geo->DimensionModel == GAIA_XY_Z)
16987 	      result = 3;
16988 	  else if (geo->DimensionModel == GAIA_XY_M)
16989 	      result = 3;
16990 	  else if (geo->DimensionModel == GAIA_XY_Z_M)
16991 	      result = 4;
16992 	  sqlite3_result_int (context, result);
16993       }
16994     gaiaFreeGeomColl (geo);
16995 }
16996 
16997 static void
fnct_GeometryType(sqlite3_context * context,int argc,sqlite3_value ** argv)16998 fnct_GeometryType (sqlite3_context * context, int argc, sqlite3_value ** argv)
16999 {
17000 /* SQL function:
17001 / GeometryType(BLOB encoded geometry)
17002 /
17003 / returns the class for current geometry:
17004 / 'POINT' or 'MULTIPOINT' [Z, M, ZM]
17005 / 'LINESTRING' or 'MULTILINESTRING' [Z, M, ZM]
17006 / 'POLYGON' or 'MULTIPOLYGON' [Z, M, ZM]
17007 / 'GEOMETRYCOLLECTION'  [Z, M, ZM]
17008 / or NULL if any error is encountered
17009 */
17010     unsigned char *p_blob;
17011     int n_bytes;
17012     int len;
17013     int type;
17014     char *p_type = NULL;
17015     char *p_result = NULL;
17016     gaiaGeomCollPtr geo = NULL;
17017     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17018     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17019       {
17020 	  sqlite3_result_null (context);
17021 	  return;
17022       }
17023     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17024     n_bytes = sqlite3_value_bytes (argv[0]);
17025     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17026     if (!geo)
17027       {
17028 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17029 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17030 	    {
17031 		char *gpb_type = gaiaGetGeometryTypeFromGPB (p_blob, n_bytes);
17032 		if (gpb_type == NULL)
17033 		    sqlite3_result_null (context);
17034 		else
17035 		  {
17036 		      len = strlen (gpb_type);
17037 		      sqlite3_result_text (context, gpb_type, len, free);
17038 		  }
17039 		return;
17040 	    }
17041 	  else
17042 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17043 	      sqlite3_result_null (context);
17044       }
17045     else
17046       {
17047 	  type = gaiaGeometryType (geo);
17048 	  switch (type)
17049 	    {
17050 	    case GAIA_POINT:
17051 		p_type = "POINT";
17052 		break;
17053 	    case GAIA_POINTZ:
17054 		p_type = "POINT Z";
17055 		break;
17056 	    case GAIA_POINTM:
17057 		p_type = "POINT M";
17058 		break;
17059 	    case GAIA_POINTZM:
17060 		p_type = "POINT ZM";
17061 		break;
17062 	    case GAIA_MULTIPOINT:
17063 		p_type = "MULTIPOINT";
17064 		break;
17065 	    case GAIA_MULTIPOINTZ:
17066 		p_type = "MULTIPOINT Z";
17067 		break;
17068 	    case GAIA_MULTIPOINTM:
17069 		p_type = "MULTIPOINT M";
17070 		break;
17071 	    case GAIA_MULTIPOINTZM:
17072 		p_type = "MULTIPOINT ZM";
17073 		break;
17074 	    case GAIA_LINESTRING:
17075 	    case GAIA_COMPRESSED_LINESTRING:
17076 		p_type = "LINESTRING";
17077 		break;
17078 	    case GAIA_LINESTRINGZ:
17079 	    case GAIA_COMPRESSED_LINESTRINGZ:
17080 		p_type = "LINESTRING Z";
17081 		break;
17082 	    case GAIA_LINESTRINGM:
17083 	    case GAIA_COMPRESSED_LINESTRINGM:
17084 		p_type = "LINESTRING M";
17085 		break;
17086 	    case GAIA_LINESTRINGZM:
17087 	    case GAIA_COMPRESSED_LINESTRINGZM:
17088 		p_type = "LINESTRING ZM";
17089 		break;
17090 	    case GAIA_MULTILINESTRING:
17091 		p_type = "MULTILINESTRING";
17092 		break;
17093 	    case GAIA_MULTILINESTRINGZ:
17094 		p_type = "MULTILINESTRING Z";
17095 		break;
17096 	    case GAIA_MULTILINESTRINGM:
17097 		p_type = "MULTILINESTRING M";
17098 		break;
17099 	    case GAIA_MULTILINESTRINGZM:
17100 		p_type = "MULTILINESTRING ZM";
17101 		break;
17102 	    case GAIA_POLYGON:
17103 	    case GAIA_COMPRESSED_POLYGON:
17104 		p_type = "POLYGON";
17105 		break;
17106 	    case GAIA_POLYGONZ:
17107 	    case GAIA_COMPRESSED_POLYGONZ:
17108 		p_type = "POLYGON Z";
17109 		break;
17110 	    case GAIA_POLYGONM:
17111 	    case GAIA_COMPRESSED_POLYGONM:
17112 		p_type = "POLYGON M";
17113 		break;
17114 	    case GAIA_POLYGONZM:
17115 	    case GAIA_COMPRESSED_POLYGONZM:
17116 		p_type = "POLYGON ZM";
17117 		break;
17118 	    case GAIA_MULTIPOLYGON:
17119 		p_type = "MULTIPOLYGON";
17120 		break;
17121 	    case GAIA_MULTIPOLYGONZ:
17122 		p_type = "MULTIPOLYGON Z";
17123 		break;
17124 	    case GAIA_MULTIPOLYGONM:
17125 		p_type = "MULTIPOLYGON M";
17126 		break;
17127 	    case GAIA_MULTIPOLYGONZM:
17128 		p_type = "MULTIPOLYGON ZM";
17129 		break;
17130 	    case GAIA_GEOMETRYCOLLECTION:
17131 		p_type = "GEOMETRYCOLLECTION";
17132 		break;
17133 	    case GAIA_GEOMETRYCOLLECTIONZ:
17134 		p_type = "GEOMETRYCOLLECTION Z";
17135 		break;
17136 	    case GAIA_GEOMETRYCOLLECTIONM:
17137 		p_type = "GEOMETRYCOLLECTION M";
17138 		break;
17139 	    case GAIA_GEOMETRYCOLLECTIONZM:
17140 		p_type = "GEOMETRYCOLLECTION ZM";
17141 		break;
17142 	    };
17143 	  if (p_type)
17144 	    {
17145 		len = strlen (p_type);
17146 		p_result = malloc (len + 1);
17147 		strcpy (p_result, p_type);
17148 	    }
17149 	  if (!p_result)
17150 	      sqlite3_result_null (context);
17151 	  else
17152 	    {
17153 		len = strlen (p_result);
17154 		sqlite3_result_text (context, p_result, len, free);
17155 	    }
17156       }
17157     gaiaFreeGeomColl (geo);
17158 }
17159 
17160 static void
fnct_GeometryAliasType(sqlite3_context * context,int argc,sqlite3_value ** argv)17161 fnct_GeometryAliasType (sqlite3_context * context, int argc,
17162 			sqlite3_value ** argv)
17163 {
17164 /* SQL function:
17165 / GeometryAliasType(BLOB encoded geometry)
17166 /
17167 / returns the alias-class for current geometry:
17168 / 'POINT'
17169 / 'LINESTRING'
17170 / 'POLYGON'
17171 / 'MULTIPOINT'
17172 / 'MULTILINESTRING'
17173 / 'MULTIPOLYGON'
17174 / 'GEOMETRYCOLLECTION'
17175 / or NULL if any error is encountered
17176 */
17177     unsigned char *p_blob;
17178     int n_bytes;
17179     int len;
17180     int type;
17181     char *p_type = NULL;
17182     char *p_result = NULL;
17183     gaiaGeomCollPtr geo = NULL;
17184     int gpkg_amphibious = 0;
17185     int gpkg_mode = 0;
17186     struct splite_internal_cache *cache = sqlite3_user_data (context);
17187     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17188     if (cache != NULL)
17189       {
17190 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
17191 	  gpkg_mode = cache->gpkg_mode;
17192       }
17193     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17194       {
17195 	  sqlite3_result_null (context);
17196 	  return;
17197       }
17198     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17199     n_bytes = sqlite3_value_bytes (argv[0]);
17200     geo =
17201 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
17202 				     gpkg_amphibious);
17203     if (!geo)
17204 	sqlite3_result_null (context);
17205     else
17206       {
17207 	  type = gaiaGeometryAliasType (geo);
17208 	  switch (type)
17209 	    {
17210 	    case GAIA_POINT:
17211 		p_type = "POINT";
17212 		break;
17213 	    case GAIA_MULTIPOINT:
17214 		p_type = "MULTIPOINT";
17215 		break;
17216 	    case GAIA_LINESTRING:
17217 		p_type = "LINESTRING";
17218 		break;
17219 	    case GAIA_MULTILINESTRING:
17220 		p_type = "MULTILINESTRING";
17221 		break;
17222 	    case GAIA_POLYGON:
17223 		p_type = "POLYGON";
17224 		break;
17225 	    case GAIA_MULTIPOLYGON:
17226 		p_type = "MULTIPOLYGON";
17227 		break;
17228 	    case GAIA_GEOMETRYCOLLECTION:
17229 		p_type = "GEOMETRYCOLLECTION";
17230 		break;
17231 	    };
17232 	  if (p_type)
17233 	    {
17234 		len = strlen (p_type);
17235 		p_result = malloc (len + 1);
17236 		strcpy (p_result, p_type);
17237 	    }
17238 	  if (!p_result)
17239 	      sqlite3_result_null (context);
17240 	  else
17241 	    {
17242 		len = strlen (p_result);
17243 		sqlite3_result_text (context, p_result, len, free);
17244 	    }
17245       }
17246     gaiaFreeGeomColl (geo);
17247 }
17248 
17249 static void
fnct_SridFromAuthCRS(sqlite3_context * context,int argc,sqlite3_value ** argv)17250 fnct_SridFromAuthCRS (sqlite3_context * context, int argc,
17251 		      sqlite3_value ** argv)
17252 {
17253 /* SQL function:
17254 / SridFromAuthCRS(auth_name, auth_srid)
17255 /
17256 / returns the SRID
17257 / or NULL if any error is encountered
17258 */
17259     const unsigned char *auth_name;
17260     int auth_srid;
17261     int srid = -1;
17262     char *sql;
17263     char **results;
17264     int n_rows;
17265     int n_columns;
17266     char *err_msg = NULL;
17267     int ret;
17268     int i;
17269     sqlite3 *sqlite = sqlite3_context_db_handle (context);
17270     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17271     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
17272       {
17273 	  sqlite3_result_null (context);
17274 	  return;
17275       }
17276     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
17277       {
17278 	  sqlite3_result_null (context);
17279 	  return;
17280       }
17281     auth_name = sqlite3_value_text (argv[0]);
17282     auth_srid = sqlite3_value_int (argv[1]);
17283 
17284     sql = sqlite3_mprintf ("SELECT srid FROM spatial_ref_sys "
17285 			   "WHERE Upper(auth_name) = Upper(%Q) AND auth_srid = %d",
17286 			   auth_name, auth_srid);
17287     ret = sqlite3_get_table (sqlite, sql, &results, &n_rows, &n_columns,
17288 			     &err_msg);
17289     sqlite3_free (sql);
17290     if (ret != SQLITE_OK)
17291 	goto done;
17292     if (n_rows >= 1)
17293       {
17294 	  for (i = 1; i <= n_rows; i++)
17295 	      srid = atoi (results[(i * n_columns) + 0]);
17296       }
17297     sqlite3_free_table (results);
17298   done:
17299     sqlite3_result_int (context, srid);
17300 }
17301 
17302 static void
fnct_SRID(sqlite3_context * context,int argc,sqlite3_value ** argv)17303 fnct_SRID (sqlite3_context * context, int argc, sqlite3_value ** argv)
17304 {
17305 /* SQL function:
17306 / Srid(BLOB encoded geometry)
17307 /
17308 / returns the SRID
17309 / or NULL if any error is encountered
17310 */
17311     unsigned char *p_blob;
17312     int n_bytes;
17313     gaiaGeomCollPtr geo = NULL;
17314     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17315     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17316       {
17317 	  sqlite3_result_null (context);
17318 	  return;
17319       }
17320     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17321     n_bytes = sqlite3_value_bytes (argv[0]);
17322     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17323     if (!geo)
17324       {
17325 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17326 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17327 	    {
17328 		int srid = gaiaGetSridFromGPB (p_blob, n_bytes);
17329 		sqlite3_result_int (context, srid);
17330 	    }
17331 	  else
17332 	      sqlite3_result_null (context);
17333 	  return;
17334 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17335 	  sqlite3_result_null (context);
17336       }
17337     else
17338 	sqlite3_result_int (context, geo->Srid);
17339     gaiaFreeGeomColl (geo);
17340 }
17341 
17342 static void
fnct_SetSRID(sqlite3_context * context,int argc,sqlite3_value ** argv)17343 fnct_SetSRID (sqlite3_context * context, int argc, sqlite3_value ** argv)
17344 {
17345 /* SQL function:
17346 / SetSrid(BLOBencoded geometry, srid)
17347 /
17348 / returns a new geometry that is the original one received, but with the new SRID [no coordinates translation is applied]
17349 / or NULL if any error is encountered
17350 */
17351     unsigned char *p_blob;
17352     int n_bytes;
17353     gaiaGeomCollPtr geo = NULL;
17354     int srid;
17355     unsigned char *p_result = NULL;
17356     int gpkg_amphibious = 0;
17357     int gpkg_mode = 0;
17358     int tiny_point = 0;
17359     struct splite_internal_cache *cache = sqlite3_user_data (context);
17360     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17361     if (cache != NULL)
17362       {
17363 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
17364 	  gpkg_mode = cache->gpkg_mode;
17365 	  tiny_point = cache->tinyPointEnabled;
17366       }
17367     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17368       {
17369 	  sqlite3_result_null (context);
17370 	  return;
17371       }
17372     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
17373 	srid = sqlite3_value_int (argv[1]);
17374     else
17375       {
17376 	  sqlite3_result_null (context);
17377 	  return;
17378       }
17379     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17380     n_bytes = sqlite3_value_bytes (argv[0]);
17381     geo =
17382 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
17383 				     gpkg_amphibious);
17384     if (!geo)
17385 	sqlite3_result_null (context);
17386     else
17387       {
17388 	  geo->Srid = srid;
17389 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &n_bytes, gpkg_mode,
17390 				      tiny_point);
17391 	  sqlite3_result_blob (context, p_result, n_bytes, free);
17392       }
17393     gaiaFreeGeomColl (geo);
17394 }
17395 
17396 static void
fnct_IsEmpty(sqlite3_context * context,int argc,sqlite3_value ** argv)17397 fnct_IsEmpty (sqlite3_context * context, int argc, sqlite3_value ** argv)
17398 {
17399 /* SQL function:
17400 / IsEmpty(BLOB encoded geometry)
17401 /
17402 / returns:
17403 / 1 if this geometry contains no elementary geometries
17404 / 0 otherwise
17405 / or -1 if any error is encountered
17406 */
17407     unsigned char *p_blob;
17408     int n_bytes;
17409     gaiaGeomCollPtr geo = NULL;
17410     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17411     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17412       {
17413 	  sqlite3_result_int (context, -1);
17414 	  return;
17415       }
17416     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17417     n_bytes = sqlite3_value_bytes (argv[0]);
17418     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17419     if (!geo)
17420       {
17421 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17422 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17423 	    {
17424 		int is_empty = gaiaIsEmptyGPB (p_blob, n_bytes);
17425 		sqlite3_result_int (context, is_empty);
17426 	    }
17427 	  else
17428 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17429 	      sqlite3_result_int (context, -1);
17430       }
17431     else
17432 	sqlite3_result_int (context, gaiaIsEmpty (geo));
17433     gaiaFreeGeomColl (geo);
17434 }
17435 
17436 static void
fnct_Is3D(sqlite3_context * context,int argc,sqlite3_value ** argv)17437 fnct_Is3D (sqlite3_context * context, int argc, sqlite3_value ** argv)
17438 {
17439 /* SQL function:
17440 / Is3D(BLOB encoded geometry)
17441 /
17442 / returns:
17443 / 1 if this geometry has Z coords
17444 / 0 otherwise
17445 / or -1 if any error is encountered
17446 */
17447     unsigned char *p_blob;
17448     int n_bytes;
17449     gaiaGeomCollPtr geo = NULL;
17450     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17451     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17452       {
17453 	  sqlite3_result_int (context, -1);
17454 	  return;
17455       }
17456     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17457     n_bytes = sqlite3_value_bytes (argv[0]);
17458     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17459     if (!geo)
17460       {
17461 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17462 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17463 	    {
17464 		double min_x;
17465 		double max_x;
17466 		double min_y;
17467 		double max_y;
17468 		int has_z;
17469 		double min_z;
17470 		double max_z;
17471 		int has_m;
17472 		double min_m;
17473 		double max_m;
17474 		if (gaiaGetEnvelopeFromGPB
17475 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17476 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17477 		  {
17478 		      sqlite3_result_int (context, has_z);
17479 		  }
17480 	    }
17481 	  else
17482 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17483 	      sqlite3_result_int (context, -1);
17484       }
17485     else
17486       {
17487 	  if (geo->DimensionModel == GAIA_XY_Z
17488 	      || geo->DimensionModel == GAIA_XY_Z_M)
17489 	      sqlite3_result_int (context, 1);
17490 	  else
17491 	      sqlite3_result_int (context, 0);
17492       }
17493     gaiaFreeGeomColl (geo);
17494 }
17495 
17496 static void
fnct_IsMeasured(sqlite3_context * context,int argc,sqlite3_value ** argv)17497 fnct_IsMeasured (sqlite3_context * context, int argc, sqlite3_value ** argv)
17498 {
17499 /* SQL function:
17500 / IsMeasured(BLOB encoded geometry)
17501 /
17502 / returns:
17503 / 1 if this geometry has M coords
17504 / 0 otherwise
17505 / or -1 if any error is encountered
17506 */
17507     unsigned char *p_blob;
17508     int n_bytes;
17509     gaiaGeomCollPtr geo = NULL;
17510     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17511     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17512       {
17513 	  sqlite3_result_int (context, -1);
17514 	  return;
17515       }
17516     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17517     n_bytes = sqlite3_value_bytes (argv[0]);
17518     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17519     if (!geo)
17520       {
17521 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17522 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17523 	    {
17524 		double min_x;
17525 		double max_x;
17526 		double min_y;
17527 		double max_y;
17528 		int has_z;
17529 		double min_z;
17530 		double max_z;
17531 		int has_m;
17532 		double min_m;
17533 		double max_m;
17534 		if (gaiaGetEnvelopeFromGPB
17535 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17536 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17537 		  {
17538 		      sqlite3_result_int (context, has_m);
17539 		  }
17540 	    }
17541 	  else
17542 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17543 	      sqlite3_result_int (context, -1);
17544       }
17545     else
17546       {
17547 	  if (geo->DimensionModel == GAIA_XY_M
17548 	      || geo->DimensionModel == GAIA_XY_Z_M)
17549 	      sqlite3_result_int (context, 1);
17550 	  else
17551 	      sqlite3_result_int (context, 0);
17552       }
17553     gaiaFreeGeomColl (geo);
17554 }
17555 
17556 static void
fnct_MinZ(sqlite3_context * context,int argc,sqlite3_value ** argv)17557 fnct_MinZ (sqlite3_context * context, int argc, sqlite3_value ** argv)
17558 {
17559 /* SQL function:
17560 / ST_MinZ(BLOB encoded GEMETRY)
17561 /    or
17562 / ST_MinZ(BLOB encoded GEOMETRY, DOUBLE nodata-value)
17563 /
17564 / returns the MinZ coordinate for current geometry
17565 / or NULL if any error is encountered
17566 */
17567     unsigned char *p_blob;
17568     int n_bytes;
17569     double min;
17570     double max;
17571     double nodata = DBL_MAX;
17572     int hasNodata = 0;
17573     gaiaGeomCollPtr geo = NULL;
17574     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17575     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17576       {
17577 	  sqlite3_result_null (context);
17578 	  return;
17579       }
17580     if (argc == 2)
17581       {
17582 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
17583 	    {
17584 		nodata = sqlite3_value_double (argv[1]);
17585 		hasNodata = 1;
17586 	    }
17587 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
17588 	    {
17589 		int intval = sqlite3_value_int (argv[1]);
17590 		nodata = intval;
17591 		hasNodata = 1;
17592 	    }
17593 	  else
17594 	      sqlite3_result_null (context);
17595 	  return;
17596       }
17597     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17598     n_bytes = sqlite3_value_bytes (argv[0]);
17599     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17600     if (!geo)
17601       {
17602 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17603 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17604 	    {
17605 		double min_x;
17606 		double max_x;
17607 		double min_y;
17608 		double max_y;
17609 		int has_z;
17610 		double min_z;
17611 		double max_z;
17612 		int has_m;
17613 		double min_m;
17614 		double max_m;
17615 		if (gaiaGetEnvelopeFromGPB
17616 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17617 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17618 		  {
17619 		      if (has_z)
17620 			  sqlite3_result_double (context, min_z);
17621 		      else
17622 			  sqlite3_result_null (context);
17623 		  }
17624 	    }
17625 	  else
17626 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17627 	      sqlite3_result_null (context);
17628       }
17629     else
17630       {
17631 	  if (geo->DimensionModel == GAIA_XY_Z
17632 	      || geo->DimensionModel == GAIA_XY_Z_M)
17633 	    {
17634 		if (hasNodata)
17635 		    gaiaZRangeGeometryEx (geo, nodata, &min, &max);
17636 		else
17637 		    gaiaZRangeGeometry (geo, &min, &max);
17638 		sqlite3_result_double (context, min);
17639 	    }
17640 	  else
17641 	      sqlite3_result_null (context);
17642 	  gaiaFreeGeomColl (geo);
17643       }
17644 }
17645 
17646 static void
fnct_MaxZ(sqlite3_context * context,int argc,sqlite3_value ** argv)17647 fnct_MaxZ (sqlite3_context * context, int argc, sqlite3_value ** argv)
17648 {
17649 /* SQL function:
17650 / ST_MaxZ(BLOB encoded GEMETRY)
17651 /    or
17652 / ST_MaxZ(BLOB encoded GEOMETRY, DOUBLE nodata-value)
17653 /
17654 / returns the MaxZ coordinate for current geometry
17655 / or NULL if any error is encountered
17656 */
17657     unsigned char *p_blob;
17658     int n_bytes;
17659     double min;
17660     double max;
17661     double nodata = DBL_MAX;
17662     int hasNodata = 0;
17663     gaiaGeomCollPtr geo = NULL;
17664     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17665     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17666       {
17667 	  sqlite3_result_null (context);
17668 	  return;
17669       }
17670     if (argc == 2)
17671       {
17672 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
17673 	    {
17674 		nodata = sqlite3_value_double (argv[1]);
17675 		hasNodata = 1;
17676 	    }
17677 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
17678 	    {
17679 		int intval = sqlite3_value_int (argv[1]);
17680 		nodata = intval;
17681 		hasNodata = 1;
17682 	    }
17683 	  else
17684 	      sqlite3_result_null (context);
17685 	  return;
17686       }
17687     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17688     n_bytes = sqlite3_value_bytes (argv[0]);
17689     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17690     if (!geo)
17691       {
17692 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17693 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17694 	    {
17695 		double min_x;
17696 		double max_x;
17697 		double min_y;
17698 		double max_y;
17699 		int has_z;
17700 		double min_z;
17701 		double max_z;
17702 		int has_m;
17703 		double min_m;
17704 		double max_m;
17705 		if (gaiaGetEnvelopeFromGPB
17706 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17707 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17708 		  {
17709 		      if (has_z)
17710 			  sqlite3_result_double (context, max_z);
17711 		      else
17712 			  sqlite3_result_null (context);
17713 		  }
17714 	    }
17715 	  else
17716 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17717 	      sqlite3_result_null (context);
17718       }
17719     else
17720       {
17721 	  if (geo->DimensionModel == GAIA_XY_Z
17722 	      || geo->DimensionModel == GAIA_XY_Z_M)
17723 	    {
17724 		if (hasNodata)
17725 		    gaiaZRangeGeometryEx (geo, nodata, &min, &max);
17726 		else
17727 		    gaiaZRangeGeometry (geo, &min, &max);
17728 		sqlite3_result_double (context, max);
17729 	    }
17730 	  else
17731 	      sqlite3_result_null (context);
17732 	  gaiaFreeGeomColl (geo);
17733       }
17734 }
17735 
17736 static void
fnct_MinM(sqlite3_context * context,int argc,sqlite3_value ** argv)17737 fnct_MinM (sqlite3_context * context, int argc, sqlite3_value ** argv)
17738 {
17739 /* SQL function:
17740 / ST_MinM(BLOB encoded GEMETRY)
17741 /    or
17742 / ST_MinM(BLOB encoded GEOMETRY, DOUBLE nodata-value)
17743 /
17744 / returns the MinM coordinate for current geometry
17745 / or NULL if any error is encountered
17746 */
17747     unsigned char *p_blob;
17748     int n_bytes;
17749     double min;
17750     double max;
17751     double nodata = DBL_MAX;
17752     int hasNodata = 0;
17753     gaiaGeomCollPtr geo = NULL;
17754     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17755     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17756       {
17757 	  sqlite3_result_null (context);
17758 	  return;
17759       }
17760     if (argc == 2)
17761       {
17762 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
17763 	    {
17764 		nodata = sqlite3_value_double (argv[1]);
17765 		hasNodata = 1;
17766 	    }
17767 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
17768 	    {
17769 		int intval = sqlite3_value_int (argv[1]);
17770 		nodata = intval;
17771 		hasNodata = 1;
17772 	    }
17773 	  else
17774 	      sqlite3_result_null (context);
17775 	  return;
17776       }
17777     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17778     n_bytes = sqlite3_value_bytes (argv[0]);
17779     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17780     if (!geo)
17781       {
17782 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17783 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17784 	    {
17785 		double min_x;
17786 		double max_x;
17787 		double min_y;
17788 		double max_y;
17789 		int has_z;
17790 		double min_z;
17791 		double max_z;
17792 		int has_m;
17793 		double min_m;
17794 		double max_m;
17795 		if (gaiaGetEnvelopeFromGPB
17796 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17797 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17798 		  {
17799 		      if (has_m)
17800 			  sqlite3_result_double (context, min_m);
17801 		      else
17802 			  sqlite3_result_null (context);
17803 		  }
17804 	    }
17805 	  else
17806 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17807 	      sqlite3_result_null (context);
17808       }
17809     else
17810       {
17811 	  if (geo->DimensionModel == GAIA_XY_M
17812 	      || geo->DimensionModel == GAIA_XY_Z_M)
17813 	    {
17814 		if (hasNodata)
17815 		    gaiaMRangeGeometryEx (geo, nodata, &min, &max);
17816 		else
17817 		    gaiaMRangeGeometry (geo, &min, &max);
17818 		sqlite3_result_double (context, min);
17819 	    }
17820 	  else
17821 	      sqlite3_result_null (context);
17822 	  gaiaFreeGeomColl (geo);
17823       }
17824 }
17825 
17826 static void
fnct_MaxM(sqlite3_context * context,int argc,sqlite3_value ** argv)17827 fnct_MaxM (sqlite3_context * context, int argc, sqlite3_value ** argv)
17828 {
17829 /* SQL function:
17830 / ST_MaxM(BLOB encoded GEMETRY)
17831 /    or
17832 / ST_MaxM(BLOB encoded GEOMETRY, DOUBLE nodata-value)
17833 /
17834 / returns the MaxM coordinate for current geometry
17835 / or NULL if any error is encountered
17836 */
17837     unsigned char *p_blob;
17838     int n_bytes;
17839     double min;
17840     double max;
17841     double nodata = DBL_MAX;
17842     int hasNodata = 0;
17843     gaiaGeomCollPtr geo = NULL;
17844     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17845     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17846       {
17847 	  sqlite3_result_null (context);
17848 	  return;
17849       }
17850     if (argc == 2)
17851       {
17852 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
17853 	    {
17854 		nodata = sqlite3_value_double (argv[1]);
17855 		hasNodata = 1;
17856 	    }
17857 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
17858 	    {
17859 		int intval = sqlite3_value_int (argv[1]);
17860 		nodata = intval;
17861 		hasNodata = 1;
17862 	    }
17863 	  else
17864 	      sqlite3_result_null (context);
17865 	  return;
17866       }
17867     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17868     n_bytes = sqlite3_value_bytes (argv[0]);
17869     geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
17870     if (!geo)
17871       {
17872 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
17873 	  if (gaiaIsValidGPB (p_blob, n_bytes))
17874 	    {
17875 		double min_x;
17876 		double max_x;
17877 		double min_y;
17878 		double max_y;
17879 		int has_z;
17880 		double min_z;
17881 		double max_z;
17882 		int has_m;
17883 		double min_m;
17884 		double max_m;
17885 		if (gaiaGetEnvelopeFromGPB
17886 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
17887 		     &min_z, &max_z, &has_m, &min_m, &max_m))
17888 		  {
17889 		      if (has_m)
17890 			  sqlite3_result_double (context, max_m);
17891 		      else
17892 			  sqlite3_result_null (context);
17893 		  }
17894 	    }
17895 	  else
17896 #endif /* end GEOPACKAGE: supporting GPKG geometries */
17897 	      sqlite3_result_null (context);
17898       }
17899     else
17900       {
17901 	  if (geo->DimensionModel == GAIA_XY_M
17902 	      || geo->DimensionModel == GAIA_XY_Z_M)
17903 	    {
17904 		if (hasNodata)
17905 		    gaiaMRangeGeometryEx (geo, nodata, &min, &max);
17906 		else
17907 		    gaiaMRangeGeometry (geo, &min, &max);
17908 		sqlite3_result_double (context, max);
17909 	    }
17910 	  else
17911 	      sqlite3_result_null (context);
17912 	  gaiaFreeGeomColl (geo);
17913       }
17914 }
17915 
17916 static void
fnct_Envelope(sqlite3_context * context,int argc,sqlite3_value ** argv)17917 fnct_Envelope (sqlite3_context * context, int argc, sqlite3_value ** argv)
17918 {
17919 /* SQL function:
17920 / Envelope(BLOB encoded geometry)
17921 /
17922 / returns the MBR for current geometry
17923 / or NULL if any error is encountered
17924 */
17925     unsigned char *p_blob;
17926     int n_bytes;
17927     int len;
17928     unsigned char *p_result = NULL;
17929     gaiaGeomCollPtr geo = NULL;
17930     gaiaGeomCollPtr bbox;
17931     gaiaPolygonPtr polyg;
17932     gaiaRingPtr rect;
17933     int gpkg_amphibious = 0;
17934     int gpkg_mode = 0;
17935     int tiny_point = 0;
17936     struct splite_internal_cache *cache = sqlite3_user_data (context);
17937     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
17938     if (cache != NULL)
17939       {
17940 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
17941 	  gpkg_mode = cache->gpkg_mode;
17942 	  tiny_point = cache->tinyPointEnabled;
17943       }
17944     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
17945       {
17946 	  sqlite3_result_null (context);
17947 	  return;
17948       }
17949     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
17950     n_bytes = sqlite3_value_bytes (argv[0]);
17951     geo =
17952 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
17953 				     gpkg_amphibious);
17954     if (!geo)
17955 	sqlite3_result_null (context);
17956     else
17957       {
17958 	  gaiaMbrGeometry (geo);
17959 	  bbox = gaiaAllocGeomColl ();
17960 	  bbox->Srid = geo->Srid;
17961 	  polyg = gaiaAddPolygonToGeomColl (bbox, 5, 0);
17962 	  rect = polyg->Exterior;
17963 	  gaiaSetPoint (rect->Coords, 0, geo->MinX, geo->MinY);	/* vertex # 1 */
17964 	  gaiaSetPoint (rect->Coords, 1, geo->MaxX, geo->MinY);	/* vertex # 2 */
17965 	  gaiaSetPoint (rect->Coords, 2, geo->MaxX, geo->MaxY);	/* vertex # 3 */
17966 	  gaiaSetPoint (rect->Coords, 3, geo->MinX, geo->MaxY);	/* vertex # 4 */
17967 	  gaiaSetPoint (rect->Coords, 4, geo->MinX, geo->MinY);	/* vertex # 5 [same as vertex # 1 to close the polygon] */
17968 	  gaiaToSpatiaLiteBlobWkbEx2 (bbox, &p_result, &len, gpkg_mode,
17969 				      tiny_point);
17970 	  gaiaFreeGeomColl (bbox);
17971 	  sqlite3_result_blob (context, p_result, len, free);
17972       }
17973     gaiaFreeGeomColl (geo);
17974 }
17975 
17976 static void
fnct_Expand(sqlite3_context * context,int argc,sqlite3_value ** argv)17977 fnct_Expand (sqlite3_context * context, int argc, sqlite3_value ** argv)
17978 {
17979 /* SQL function:
17980 / ST_Expand(BLOB encoded geometry, double amount)
17981 /
17982 / returns the MBR for current geometry expanded by "amount" in each direction
17983 / or NULL if any error is encountered
17984 */
17985     unsigned char *p_blob;
17986     int n_bytes;
17987     int len;
17988     unsigned char *p_result = NULL;
17989     gaiaGeomCollPtr geo = NULL;
17990     gaiaGeomCollPtr bbox;
17991     gaiaPolygonPtr polyg;
17992     gaiaRingPtr rect;
17993     double tic;
17994     int int_value;
17995     int gpkg_amphibious = 0;
17996     int gpkg_mode = 0;
17997     int tiny_point = 0;
17998     struct splite_internal_cache *cache = sqlite3_user_data (context);
17999     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18000     if (cache != NULL)
18001       {
18002 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
18003 	  gpkg_mode = cache->gpkg_mode;
18004 	  tiny_point = cache->tinyPointEnabled;
18005       }
18006     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18007       {
18008 	  sqlite3_result_null (context);
18009 	  return;
18010       }
18011     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18012 	tic = sqlite3_value_double (argv[1]);
18013     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18014       {
18015 	  int_value = sqlite3_value_int (argv[1]);
18016 	  tic = int_value;
18017       }
18018     else
18019       {
18020 	  sqlite3_result_null (context);
18021 	  return;
18022       }
18023     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18024     n_bytes = sqlite3_value_bytes (argv[0]);
18025     geo =
18026 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
18027 				     gpkg_amphibious);
18028     if (!geo)
18029 	sqlite3_result_null (context);
18030     else
18031       {
18032 	  gaiaMbrGeometry (geo);
18033 	  bbox = gaiaAllocGeomColl ();
18034 	  bbox->Srid = geo->Srid;
18035 	  polyg = gaiaAddPolygonToGeomColl (bbox, 5, 0);
18036 	  rect = polyg->Exterior;
18037 	  gaiaSetPoint (rect->Coords, 0, geo->MinX - tic, geo->MinY - tic);	/* vertex # 1 */
18038 	  gaiaSetPoint (rect->Coords, 1, geo->MaxX + tic, geo->MinY - tic);	/* vertex # 2 */
18039 	  gaiaSetPoint (rect->Coords, 2, geo->MaxX + tic, geo->MaxY + tic);	/* vertex # 3 */
18040 	  gaiaSetPoint (rect->Coords, 3, geo->MinX - tic, geo->MaxY + tic);	/* vertex # 4 */
18041 	  gaiaSetPoint (rect->Coords, 4, geo->MinX - tic, geo->MinY - tic);	/* vertex # 5 [same as vertex # 1 to close the polygon] */
18042 	  gaiaToSpatiaLiteBlobWkbEx2 (bbox, &p_result, &len, gpkg_mode,
18043 				      tiny_point);
18044 	  gaiaFreeGeomColl (bbox);
18045 	  sqlite3_result_blob (context, p_result, len, free);
18046       }
18047     gaiaFreeGeomColl (geo);
18048 }
18049 
18050 static void
build_filter_mbr(sqlite3_context * context,int argc,sqlite3_value ** argv,int mode)18051 build_filter_mbr (sqlite3_context * context, int argc,
18052 		  sqlite3_value ** argv, int mode)
18053 {
18054 /* SQL functions:
18055 / BuildMbrFilter(double X1, double Y1, double X2, double Y2)
18056 / FilterMBRWithin(double X1, double Y1, double X2, double Y2)
18057 / FilterMBRContain(double X1, double Y1, double X2, double Y2)
18058 / FilterMBRIntersects(double X1, double Y1, double X2, double Y2)
18059 /
18060 / builds a generic filter for MBR from two points (identifying a rectangle's diagonal)
18061 / or NULL if any error is encountered
18062 */
18063     int len;
18064     unsigned char *p_result = NULL;
18065     double x1;
18066     double y1;
18067     double x2;
18068     double y2;
18069     int int_value;
18070     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18071     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
18072 	x1 = sqlite3_value_double (argv[0]);
18073     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
18074       {
18075 	  int_value = sqlite3_value_int (argv[0]);
18076 	  x1 = int_value;
18077       }
18078     else
18079       {
18080 	  sqlite3_result_null (context);
18081 	  return;
18082       }
18083     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18084 	y1 = sqlite3_value_double (argv[1]);
18085     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18086       {
18087 	  int_value = sqlite3_value_int (argv[1]);
18088 	  y1 = int_value;
18089       }
18090     else
18091       {
18092 	  sqlite3_result_null (context);
18093 	  return;
18094       }
18095     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
18096 	x2 = sqlite3_value_double (argv[2]);
18097     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
18098       {
18099 	  int_value = sqlite3_value_int (argv[2]);
18100 	  x2 = int_value;
18101       }
18102     else
18103       {
18104 	  sqlite3_result_null (context);
18105 	  return;
18106       }
18107     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
18108 	y2 = sqlite3_value_double (argv[3]);
18109     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
18110       {
18111 	  int_value = sqlite3_value_int (argv[3]);
18112 	  y2 = int_value;
18113       }
18114     else
18115       {
18116 	  sqlite3_result_null (context);
18117 	  return;
18118       }
18119     gaiaBuildFilterMbr (x1, y1, x2, y2, mode, &p_result, &len);
18120     if (!p_result)
18121 	sqlite3_result_null (context);
18122     else
18123 	sqlite3_result_blob (context, p_result, len, free);
18124 }
18125 
18126 /*
18127 / the following functions simply readdress the request to build_filter_mbr()
18128 / setting the appropriate MODe
18129 */
18130 
18131 static void
fnct_BuildMbrFilter(sqlite3_context * context,int argc,sqlite3_value ** argv)18132 fnct_BuildMbrFilter (sqlite3_context * context, int argc, sqlite3_value ** argv)
18133 {
18134     build_filter_mbr (context, argc, argv, GAIA_FILTER_MBR_DECLARE);
18135 }
18136 
18137 static void
fnct_FilterMbrWithin(sqlite3_context * context,int argc,sqlite3_value ** argv)18138 fnct_FilterMbrWithin (sqlite3_context * context, int argc,
18139 		      sqlite3_value ** argv)
18140 {
18141     build_filter_mbr (context, argc, argv, GAIA_FILTER_MBR_WITHIN);
18142 }
18143 
18144 static void
fnct_FilterMbrContains(sqlite3_context * context,int argc,sqlite3_value ** argv)18145 fnct_FilterMbrContains (sqlite3_context * context, int argc,
18146 			sqlite3_value ** argv)
18147 {
18148     build_filter_mbr (context, argc, argv, GAIA_FILTER_MBR_CONTAINS);
18149 }
18150 
18151 static void
fnct_FilterMbrIntersects(sqlite3_context * context,int argc,sqlite3_value ** argv)18152 fnct_FilterMbrIntersects (sqlite3_context * context, int argc,
18153 			  sqlite3_value ** argv)
18154 {
18155     build_filter_mbr (context, argc, argv, GAIA_FILTER_MBR_INTERSECTS);
18156 }
18157 
18158 static void
fnct_BuildMbr1(sqlite3_context * context,int argc,sqlite3_value ** argv)18159 fnct_BuildMbr1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
18160 {
18161 /* SQL function:
18162 / BuildMBR(double X1, double Y1, double X2, double Y2)
18163 /
18164 / builds an MBR from two points (identifying a rectangle's diagonal)
18165 / or NULL if any error is encountered
18166 */
18167     int len;
18168     unsigned char *p_result = NULL;
18169     double x1;
18170     double y1;
18171     double x2;
18172     double y2;
18173     int int_value;
18174     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18175     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
18176 	x1 = sqlite3_value_double (argv[0]);
18177     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
18178       {
18179 	  int_value = sqlite3_value_int (argv[0]);
18180 	  x1 = int_value;
18181       }
18182     else
18183       {
18184 	  sqlite3_result_null (context);
18185 	  return;
18186       }
18187     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18188 	y1 = sqlite3_value_double (argv[1]);
18189     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18190       {
18191 	  int_value = sqlite3_value_int (argv[1]);
18192 	  y1 = int_value;
18193       }
18194     else
18195       {
18196 	  sqlite3_result_null (context);
18197 	  return;
18198       }
18199     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
18200 	x2 = sqlite3_value_double (argv[2]);
18201     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
18202       {
18203 	  int_value = sqlite3_value_int (argv[2]);
18204 	  x2 = int_value;
18205       }
18206     else
18207       {
18208 	  sqlite3_result_null (context);
18209 	  return;
18210       }
18211     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
18212 	y2 = sqlite3_value_double (argv[3]);
18213     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
18214       {
18215 	  int_value = sqlite3_value_int (argv[3]);
18216 	  y2 = int_value;
18217       }
18218     else
18219       {
18220 	  sqlite3_result_null (context);
18221 	  return;
18222       }
18223     gaiaBuildMbr (x1, y1, x2, y2, -1, &p_result, &len);
18224     if (!p_result)
18225 	sqlite3_result_null (context);
18226     else
18227 	sqlite3_result_blob (context, p_result, len, free);
18228 }
18229 
18230 static void
fnct_BuildMbr2(sqlite3_context * context,int argc,sqlite3_value ** argv)18231 fnct_BuildMbr2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
18232 {
18233 /* SQL function:
18234 / BuildMBR(double X1, double Y1, double X2, double Y2, int SRID)
18235 /
18236 / builds an MBR from two points (identifying a rectangle's diagonal)
18237 / or NULL if any error is encountered
18238 */
18239     int len;
18240     unsigned char *p_result = NULL;
18241     double x1;
18242     double y1;
18243     double x2;
18244     double y2;
18245     int int_value;
18246     int srid;
18247     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18248     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
18249 	x1 = sqlite3_value_double (argv[0]);
18250     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
18251       {
18252 	  int_value = sqlite3_value_int (argv[0]);
18253 	  x1 = int_value;
18254       }
18255     else
18256       {
18257 	  sqlite3_result_null (context);
18258 	  return;
18259       }
18260     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18261 	y1 = sqlite3_value_double (argv[1]);
18262     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18263       {
18264 	  int_value = sqlite3_value_int (argv[1]);
18265 	  y1 = int_value;
18266       }
18267     else
18268       {
18269 	  sqlite3_result_null (context);
18270 	  return;
18271       }
18272     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
18273 	x2 = sqlite3_value_double (argv[2]);
18274     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
18275       {
18276 	  int_value = sqlite3_value_int (argv[2]);
18277 	  x2 = int_value;
18278       }
18279     else
18280       {
18281 	  sqlite3_result_null (context);
18282 	  return;
18283       }
18284     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
18285 	y2 = sqlite3_value_double (argv[3]);
18286     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
18287       {
18288 	  int_value = sqlite3_value_int (argv[3]);
18289 	  y2 = int_value;
18290       }
18291     else
18292       {
18293 	  sqlite3_result_null (context);
18294 	  return;
18295       }
18296     if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
18297 	srid = sqlite3_value_int (argv[4]);
18298     else
18299       {
18300 	  sqlite3_result_null (context);
18301 	  return;
18302       }
18303     gaiaBuildMbr (x1, y1, x2, y2, srid, &p_result, &len);
18304     if (!p_result)
18305 	sqlite3_result_null (context);
18306     else
18307 	sqlite3_result_blob (context, p_result, len, free);
18308 }
18309 
18310 static void
fnct_BuildCircleMbr1(sqlite3_context * context,int argc,sqlite3_value ** argv)18311 fnct_BuildCircleMbr1 (sqlite3_context * context, int argc,
18312 		      sqlite3_value ** argv)
18313 {
18314 /* SQL function:
18315 / BuildCircleMBR(double X, double Y, double radius)
18316 /
18317 / builds an MBR from two points (identifying a rectangle's diagonal)
18318 / or NULL if any error is encountered
18319 */
18320     int len;
18321     unsigned char *p_result = NULL;
18322     double x;
18323     double y;
18324     double radius;
18325     int int_value;
18326     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18327     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
18328 	x = sqlite3_value_double (argv[0]);
18329     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
18330       {
18331 	  int_value = sqlite3_value_int (argv[0]);
18332 	  x = int_value;
18333       }
18334     else
18335       {
18336 	  sqlite3_result_null (context);
18337 	  return;
18338       }
18339     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18340 	y = sqlite3_value_double (argv[1]);
18341     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18342       {
18343 	  int_value = sqlite3_value_int (argv[1]);
18344 	  y = int_value;
18345       }
18346     else
18347       {
18348 	  sqlite3_result_null (context);
18349 	  return;
18350       }
18351     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
18352 	radius = sqlite3_value_double (argv[2]);
18353     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
18354       {
18355 	  int_value = sqlite3_value_int (argv[2]);
18356 	  radius = int_value;
18357       }
18358     else
18359       {
18360 	  sqlite3_result_null (context);
18361 	  return;
18362       }
18363     gaiaBuildCircleMbr (x, y, radius, -1, &p_result, &len);
18364     if (!p_result)
18365 	sqlite3_result_null (context);
18366     else
18367 	sqlite3_result_blob (context, p_result, len, free);
18368 }
18369 
18370 static void
fnct_BuildCircleMbr2(sqlite3_context * context,int argc,sqlite3_value ** argv)18371 fnct_BuildCircleMbr2 (sqlite3_context * context, int argc,
18372 		      sqlite3_value ** argv)
18373 {
18374 /* SQL function:
18375 / BuildCircleMBR(double X, double Y, double radius, int SRID)
18376 /
18377 / builds an MBR from two points (identifying a rectangle's diagonal)
18378 / or NULL if any error is encountered
18379 */
18380     int len;
18381     unsigned char *p_result = NULL;
18382     double x;
18383     double y;
18384     double radius;
18385     int int_value;
18386     int srid;
18387     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18388     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
18389 	x = sqlite3_value_double (argv[0]);
18390     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
18391       {
18392 	  int_value = sqlite3_value_int (argv[0]);
18393 	  x = int_value;
18394       }
18395     else
18396       {
18397 	  sqlite3_result_null (context);
18398 	  return;
18399       }
18400     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
18401 	y = sqlite3_value_double (argv[1]);
18402     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
18403       {
18404 	  int_value = sqlite3_value_int (argv[1]);
18405 	  y = int_value;
18406       }
18407     else
18408       {
18409 	  sqlite3_result_null (context);
18410 	  return;
18411       }
18412     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
18413 	radius = sqlite3_value_double (argv[2]);
18414     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
18415       {
18416 	  int_value = sqlite3_value_int (argv[2]);
18417 	  radius = int_value;
18418       }
18419     else
18420       {
18421 	  sqlite3_result_null (context);
18422 	  return;
18423       }
18424     if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
18425 	srid = sqlite3_value_int (argv[3]);
18426     else
18427       {
18428 	  sqlite3_result_null (context);
18429 	  return;
18430       }
18431     gaiaBuildCircleMbr (x, y, radius, srid, &p_result, &len);
18432     if (!p_result)
18433 	sqlite3_result_null (context);
18434     else
18435 	sqlite3_result_blob (context, p_result, len, free);
18436 }
18437 
18438 static void
fnct_Extent_step(sqlite3_context * context,int argc,sqlite3_value ** argv)18439 fnct_Extent_step (sqlite3_context * context, int argc, sqlite3_value ** argv)
18440 {
18441 /* SQL function:
18442 / Extent(BLOBencoded geom)
18443 /
18444 / aggregate function - STEP
18445 /
18446 */
18447     unsigned char *p_blob;
18448     int n_bytes;
18449     gaiaGeomCollPtr geom;
18450     double **p;
18451     double *max_min;
18452     int *srid_check;
18453     int gpkg_amphibious = 0;
18454     int gpkg_mode = 0;
18455     struct splite_internal_cache *cache = sqlite3_user_data (context);
18456     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18457     if (cache != NULL)
18458       {
18459 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
18460 	  gpkg_mode = cache->gpkg_mode;
18461       }
18462     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18463       {
18464 	  sqlite3_result_null (context);
18465 	  return;
18466       }
18467     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18468     n_bytes = sqlite3_value_bytes (argv[0]);
18469     geom =
18470 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
18471 				     gpkg_amphibious);
18472     if (!geom)
18473 	return;
18474     gaiaMbrGeometry (geom);
18475     p = sqlite3_aggregate_context (context, sizeof (double **));
18476     if (!(*p))
18477       {
18478 	  /* this is the first row */
18479 	  max_min = malloc ((sizeof (double) * 5));
18480 	  *(max_min + 0) = geom->MinX;
18481 	  *(max_min + 1) = geom->MinY;
18482 	  *(max_min + 2) = geom->MaxX;
18483 	  *(max_min + 3) = geom->MaxY;
18484 	  srid_check = (int *) (max_min + 4);
18485 	  *(srid_check + 0) = geom->Srid;
18486 	  *(srid_check + 1) = geom->Srid;
18487 	  *p = max_min;
18488       }
18489     else
18490       {
18491 	  /* subsequent rows */
18492 	  max_min = *p;
18493 	  if (geom->MinX < *(max_min + 0))
18494 	      *(max_min + 0) = geom->MinX;
18495 	  if (geom->MinY < *(max_min + 1))
18496 	      *(max_min + 1) = geom->MinY;
18497 	  if (geom->MaxX > *(max_min + 2))
18498 	      *(max_min + 2) = geom->MaxX;
18499 	  if (geom->MaxY > *(max_min + 3))
18500 	      *(max_min + 3) = geom->MaxY;
18501 	  srid_check = (int *) (max_min + 4);
18502 	  if (*(srid_check + 1) != geom->Srid)
18503 	      *(srid_check + 1) = geom->Srid;
18504       }
18505     gaiaFreeGeomColl (geom);
18506 }
18507 
18508 static void
fnct_Extent_final(sqlite3_context * context)18509 fnct_Extent_final (sqlite3_context * context)
18510 {
18511 /* SQL function:
18512 / Extent(BLOBencoded geom)
18513 /
18514 / aggregate function - FINAL
18515 /
18516 */
18517     gaiaGeomCollPtr result;
18518     gaiaPolygonPtr polyg;
18519     gaiaRingPtr rect;
18520     double *max_min;
18521     double minx;
18522     double miny;
18523     double maxx;
18524     double maxy;
18525     int *srid_check;
18526     double **p = sqlite3_aggregate_context (context, 0);
18527     int gpkg_mode = 0;
18528     int tiny_point = 0;
18529     struct splite_internal_cache *cache = sqlite3_user_data (context);
18530     if (cache != NULL)
18531       {
18532 	  gpkg_mode = cache->gpkg_mode;
18533 	  tiny_point = cache->tinyPointEnabled;
18534       }
18535     if (!p)
18536       {
18537 	  sqlite3_result_null (context);
18538 	  return;
18539       }
18540     max_min = *p;
18541     if (!max_min)
18542       {
18543 	  sqlite3_result_null (context);
18544 	  return;
18545       }
18546     srid_check = (int *) (max_min + 4);
18547     if (*(srid_check + 0) != *(srid_check + 1))
18548       {
18549 	  sqlite3_result_null (context);
18550 	  return;
18551       }
18552     result = gaiaAllocGeomColl ();
18553     if (!result)
18554 	sqlite3_result_null (context);
18555     else
18556       {
18557 	  /* builds the BLOB geometry to be returned */
18558 	  int len;
18559 	  unsigned char *p_result = NULL;
18560 	  result->Srid = *(srid_check + 0);
18561 	  polyg = gaiaAddPolygonToGeomColl (result, 5, 0);
18562 	  rect = polyg->Exterior;
18563 	  minx = *(max_min + 0);
18564 	  miny = *(max_min + 1);
18565 	  maxx = *(max_min + 2);
18566 	  maxy = *(max_min + 3);
18567 	  gaiaSetPoint (rect->Coords, 0, minx, miny);	/* vertex # 1 */
18568 	  gaiaSetPoint (rect->Coords, 1, maxx, miny);	/* vertex # 2 */
18569 	  gaiaSetPoint (rect->Coords, 2, maxx, maxy);	/* vertex # 3 */
18570 	  gaiaSetPoint (rect->Coords, 3, minx, maxy);	/* vertex # 4 */
18571 	  gaiaSetPoint (rect->Coords, 4, minx, miny);	/* vertex # 5 [same as vertex # 1 to close the polygon] */
18572 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
18573 				      tiny_point);
18574 	  sqlite3_result_blob (context, p_result, len, free);
18575 	  gaiaFreeGeomColl (result);
18576       }
18577     free (max_min);
18578 }
18579 
18580 static void
fnct_MbrMinX(sqlite3_context * context,int argc,sqlite3_value ** argv)18581 fnct_MbrMinX (sqlite3_context * context, int argc, sqlite3_value ** argv)
18582 {
18583 /* SQL function:
18584 / MbrMinX(BLOB encoded GEMETRY)
18585 /
18586 / returns the MinX coordinate for current geometry's MBR
18587 / or NULL if any error is encountered
18588 */
18589     unsigned char *p_blob;
18590     int n_bytes;
18591     double coord;
18592     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18593     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18594       {
18595 	  sqlite3_result_null (context);
18596 	  return;
18597       }
18598     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18599     n_bytes = sqlite3_value_bytes (argv[0]);
18600     if (!gaiaGetMbrMinX (p_blob, n_bytes, &coord))
18601       {
18602 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
18603 	  if (gaiaIsValidGPB (p_blob, n_bytes))
18604 	    {
18605 		double min_x;
18606 		double max_x;
18607 		double min_y;
18608 		double max_y;
18609 		int has_z;
18610 		double min_z;
18611 		double max_z;
18612 		int has_m;
18613 		double min_m;
18614 		double max_m;
18615 		if (gaiaGetEnvelopeFromGPB
18616 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
18617 		     &min_z, &max_z, &has_m, &min_m, &max_m))
18618 		  {
18619 		      sqlite3_result_double (context, min_x);
18620 		  }
18621 	    }
18622 	  else
18623 #endif /* end GEOPACKAGE: supporting GPKG geometries */
18624 	      sqlite3_result_null (context);
18625       }
18626     else
18627 	sqlite3_result_double (context, coord);
18628 }
18629 
18630 static void
fnct_MbrMaxX(sqlite3_context * context,int argc,sqlite3_value ** argv)18631 fnct_MbrMaxX (sqlite3_context * context, int argc, sqlite3_value ** argv)
18632 {
18633 /* SQL function:
18634 / MbrMaxX(BLOB encoded GEMETRY)
18635 /
18636 / returns the MaxX coordinate for current geometry's MBR
18637 / or NULL if any error is encountered
18638 */
18639     unsigned char *p_blob;
18640     int n_bytes;
18641     double coord;
18642     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18643     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18644       {
18645 	  sqlite3_result_null (context);
18646 	  return;
18647       }
18648     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18649     n_bytes = sqlite3_value_bytes (argv[0]);
18650     if (!gaiaGetMbrMaxX (p_blob, n_bytes, &coord))
18651       {
18652 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
18653 	  if (gaiaIsValidGPB (p_blob, n_bytes))
18654 	    {
18655 		double min_x;
18656 		double max_x;
18657 		double min_y;
18658 		double max_y;
18659 		int has_z;
18660 		double min_z;
18661 		double max_z;
18662 		int has_m;
18663 		double min_m;
18664 		double max_m;
18665 		if (gaiaGetEnvelopeFromGPB
18666 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
18667 		     &min_z, &max_z, &has_m, &min_m, &max_m))
18668 		  {
18669 		      sqlite3_result_double (context, max_x);
18670 		  }
18671 	    }
18672 	  else
18673 #endif /* end GEOPACKAGE: supporting GPKG geometries */
18674 	      sqlite3_result_null (context);
18675       }
18676     else
18677 	sqlite3_result_double (context, coord);
18678 }
18679 
18680 static void
fnct_MbrMinY(sqlite3_context * context,int argc,sqlite3_value ** argv)18681 fnct_MbrMinY (sqlite3_context * context, int argc, sqlite3_value ** argv)
18682 {
18683 /* SQL function:
18684 / MbrMinY(BLOB encoded GEMETRY)
18685 /
18686 / returns the MinY coordinate for current geometry's MBR
18687 / or NULL if any error is encountered
18688 */
18689     unsigned char *p_blob;
18690     int n_bytes;
18691     double coord;
18692     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18693     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18694       {
18695 	  sqlite3_result_null (context);
18696 	  return;
18697       }
18698     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18699     n_bytes = sqlite3_value_bytes (argv[0]);
18700     if (!gaiaGetMbrMinY (p_blob, n_bytes, &coord))
18701       {
18702 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
18703 	  if (gaiaIsValidGPB (p_blob, n_bytes))
18704 	    {
18705 		double min_x;
18706 		double max_x;
18707 		double min_y;
18708 		double max_y;
18709 		int has_z;
18710 		double min_z;
18711 		double max_z;
18712 		int has_m;
18713 		double min_m;
18714 		double max_m;
18715 		if (gaiaGetEnvelopeFromGPB
18716 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
18717 		     &min_z, &max_z, &has_m, &min_m, &max_m))
18718 		  {
18719 		      sqlite3_result_double (context, min_y);
18720 		  }
18721 	    }
18722 	  else
18723 #endif /* end GEOPACKAGE: supporting GPKG geometries */
18724 	      sqlite3_result_null (context);
18725       }
18726     else
18727 	sqlite3_result_double (context, coord);
18728 }
18729 
18730 static void
fnct_MbrMaxY(sqlite3_context * context,int argc,sqlite3_value ** argv)18731 fnct_MbrMaxY (sqlite3_context * context, int argc, sqlite3_value ** argv)
18732 {
18733 /* SQL function:
18734 / MbrMaxY(BLOB encoded GEMETRY)
18735 /
18736 / returns the MaxY coordinate for current geometry's MBR
18737 / or NULL if any error is encountered
18738 */
18739     unsigned char *p_blob;
18740     int n_bytes;
18741     double coord;
18742     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18743     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18744       {
18745 	  sqlite3_result_null (context);
18746 	  return;
18747       }
18748     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18749     n_bytes = sqlite3_value_bytes (argv[0]);
18750     if (!gaiaGetMbrMaxY (p_blob, n_bytes, &coord))
18751       {
18752 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
18753 	  if (gaiaIsValidGPB (p_blob, n_bytes))
18754 	    {
18755 		double min_x;
18756 		double max_x;
18757 		double min_y;
18758 		double max_y;
18759 		int has_z;
18760 		double min_z;
18761 		double max_z;
18762 		int has_m;
18763 		double min_m;
18764 		double max_m;
18765 		if (gaiaGetEnvelopeFromGPB
18766 		    (p_blob, n_bytes, &min_x, &max_x, &min_y, &max_y, &has_z,
18767 		     &min_z, &max_z, &has_m, &min_m, &max_m))
18768 		  {
18769 		      sqlite3_result_double (context, max_y);
18770 		  }
18771 	    }
18772 	  else
18773 #endif /* end GEOPACKAGE: supporting GPKG geometries */
18774 	      sqlite3_result_null (context);
18775       }
18776     else
18777 	sqlite3_result_double (context, coord);
18778 }
18779 
18780 #ifndef OMIT_GEOCALLBACKS	/* supporting RTree geometry callbacks */
18781 static void
gaia_mbr_del(void * p)18782 gaia_mbr_del (void *p)
18783 {
18784 /* freeing data used by R*Tree Geometry Callback */
18785     sqlite3_free (p);
18786 }
18787 
18788 static int
fnct_RTreeIntersects(sqlite3_rtree_geometry * p,int nCoord,double * aCoord,int * pRes)18789 fnct_RTreeIntersects (sqlite3_rtree_geometry * p, int nCoord, double *aCoord,
18790 		      int *pRes)
18791 {
18792 /* R*Tree Geometry callback function:
18793 / ... MATCH RTreeIntersects(double x1, double y1, double x2, double y2)
18794 */
18795     struct gaia_rtree_mbr *mbr;
18796     double xmin;
18797     double xmax;
18798     double ymin;
18799     double ymax;
18800     float fminx;
18801     float fminy;
18802     float fmaxx;
18803     float fmaxy;
18804     double tic;
18805     double tic2;
18806 
18807     if (p->pUser == 0)
18808       {
18809 	  /* first call: we must check args and then initialize the MBR struct */
18810 	  if (nCoord != 4)
18811 	      return SQLITE_ERROR;
18812 	  if (p->nParam != 4)
18813 	      return SQLITE_ERROR;
18814 	  mbr = (struct gaia_rtree_mbr *) (p->pUser =
18815 					   sqlite3_malloc (sizeof
18816 							   (struct
18817 							    gaia_rtree_mbr)));
18818 	  if (!mbr)
18819 	      return SQLITE_NOMEM;
18820 	  p->xDelUser = gaia_mbr_del;
18821 	  xmin = p->aParam[0];
18822 	  ymin = p->aParam[1];
18823 	  xmax = p->aParam[2];
18824 	  ymax = p->aParam[3];
18825 	  if (xmin > xmax)
18826 	    {
18827 		xmin = p->aParam[2];
18828 		xmax = p->aParam[0];
18829 	    }
18830 	  if (ymin > ymax)
18831 	    {
18832 		ymin = p->aParam[3];
18833 		ymax = p->aParam[1];
18834 	    }
18835 
18836 	  /* adjusting the MBR so to compensate for DOUBLE/FLOAT truncations */
18837 	  fminx = (float) xmin;
18838 	  fminy = (float) ymin;
18839 	  fmaxx = (float) xmax;
18840 	  fmaxy = (float) ymax;
18841 	  tic = fabs (xmin - fminx);
18842 	  tic2 = fabs (ymin - fminy);
18843 	  if (tic2 > tic)
18844 	      tic = tic2;
18845 	  tic2 = fabs (xmax - fmaxx);
18846 	  if (tic2 > tic)
18847 	      tic = tic2;
18848 	  tic2 = fabs (ymax - fmaxy);
18849 	  if (tic2 > tic)
18850 	      tic = tic2;
18851 	  tic *= 2.0;
18852 
18853 	  mbr->minx = xmin - tic;
18854 	  mbr->miny = ymin - tic;
18855 	  mbr->maxx = xmax + tic;
18856 	  mbr->maxy = ymax + tic;
18857       }
18858 
18859     mbr = (struct gaia_rtree_mbr *) (p->pUser);
18860     xmin = aCoord[0];
18861     xmax = aCoord[1];
18862     ymin = aCoord[2];
18863     ymax = aCoord[3];
18864     *pRes = 1;
18865 /* evaluating Intersects relationship */
18866     if (xmin > mbr->maxx)
18867 	*pRes = 0;
18868     if (xmax < mbr->minx)
18869 	*pRes = 0;
18870     if (ymin > mbr->maxy)
18871 	*pRes = 0;
18872     if (ymax < mbr->miny)
18873 	*pRes = 0;
18874     return SQLITE_OK;
18875 }
18876 
18877 static int
fnct_RTreeDistWithin(sqlite3_rtree_geometry * p,int nCoord,double * aCoord,int * pRes)18878 fnct_RTreeDistWithin (sqlite3_rtree_geometry * p, int nCoord, double *aCoord,
18879 		      int *pRes)
18880 {
18881 /* R*Tree Geometry callback function:
18882 / ... MATCH RTreeDistWithin(double x, double y, double radius)
18883 */
18884     struct gaia_rtree_mbr *mbr;
18885     double xmin;
18886     double xmax;
18887     double ymin;
18888     double ymax;
18889 
18890     if (p->pUser == 0)
18891       {
18892 	  /* first call: we must check args and then initialize the MBR struct */
18893 	  if (nCoord != 4)
18894 	      return SQLITE_ERROR;
18895 	  if (p->nParam != 3)
18896 	      return SQLITE_ERROR;
18897 	  mbr = (struct gaia_rtree_mbr *) (p->pUser =
18898 					   sqlite3_malloc (sizeof
18899 							   (struct
18900 							    gaia_rtree_mbr)));
18901 	  if (!mbr)
18902 	      return SQLITE_NOMEM;
18903 	  p->xDelUser = gaia_mbr_del;
18904 	  mbr->minx = p->aParam[0] - p->aParam[2];
18905 	  mbr->miny = p->aParam[1] - p->aParam[2];
18906 	  mbr->maxx = p->aParam[0] + p->aParam[2];
18907 	  mbr->maxy = p->aParam[1] + p->aParam[2];
18908       }
18909 
18910     mbr = (struct gaia_rtree_mbr *) (p->pUser);
18911     xmin = aCoord[0];
18912     xmax = aCoord[1];
18913     ymin = aCoord[2];
18914     ymax = aCoord[3];
18915     *pRes = 1;
18916 /* evaluating Intersects relationship */
18917     if (xmin > mbr->maxx)
18918 	*pRes = 0;
18919     if (xmax < mbr->minx)
18920 	*pRes = 0;
18921     if (ymin > mbr->maxy)
18922 	*pRes = 0;
18923     if (ymax < mbr->miny)
18924 	*pRes = 0;
18925     return SQLITE_OK;
18926 }
18927 #endif /* end RTree geometry callbacks */
18928 
18929 static void
fnct_X(sqlite3_context * context,int argc,sqlite3_value ** argv)18930 fnct_X (sqlite3_context * context, int argc, sqlite3_value ** argv)
18931 {
18932 /* SQL function:
18933 / X(BLOB encoded POINT)
18934 /
18935 / returns the X coordinate for current POINT geometry
18936 / or NULL if any error is encountered
18937 */
18938     unsigned char *p_blob;
18939     int n_bytes;
18940     gaiaGeomCollPtr geo = NULL;
18941     gaiaPointPtr point;
18942     int gpkg_amphibious = 0;
18943     int gpkg_mode = 0;
18944     struct splite_internal_cache *cache = sqlite3_user_data (context);
18945     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18946     if (cache != NULL)
18947       {
18948 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
18949 	  gpkg_mode = cache->gpkg_mode;
18950       }
18951     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18952       {
18953 	  sqlite3_result_null (context);
18954 	  return;
18955       }
18956     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
18957     n_bytes = sqlite3_value_bytes (argv[0]);
18958     geo =
18959 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
18960 				     gpkg_amphibious);
18961     if (!geo)
18962 	sqlite3_result_null (context);
18963     else
18964       {
18965 	  point = simplePoint (geo);
18966 	  if (!point)
18967 	      sqlite3_result_null (context);
18968 	  else
18969 	      sqlite3_result_double (context, point->X);
18970       }
18971     gaiaFreeGeomColl (geo);
18972 }
18973 
18974 static void
fnct_Y(sqlite3_context * context,int argc,sqlite3_value ** argv)18975 fnct_Y (sqlite3_context * context, int argc, sqlite3_value ** argv)
18976 {
18977 /* SQL function:
18978 / Y(BLOB encoded POINT)
18979 /
18980 / returns the Y coordinate for current POINT geometry
18981 / or NULL if any error is encountered
18982 */
18983     unsigned char *p_blob;
18984     int n_bytes;
18985     gaiaGeomCollPtr geo = NULL;
18986     gaiaPointPtr point;
18987     int gpkg_amphibious = 0;
18988     int gpkg_mode = 0;
18989     struct splite_internal_cache *cache = sqlite3_user_data (context);
18990     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
18991     if (cache != NULL)
18992       {
18993 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
18994 	  gpkg_mode = cache->gpkg_mode;
18995       }
18996     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
18997       {
18998 	  sqlite3_result_null (context);
18999 	  return;
19000       }
19001     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19002     n_bytes = sqlite3_value_bytes (argv[0]);
19003     geo =
19004 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19005 				     gpkg_amphibious);
19006     if (!geo)
19007 	sqlite3_result_null (context);
19008     else
19009       {
19010 	  point = simplePoint (geo);
19011 	  if (!point)
19012 	      sqlite3_result_null (context);
19013 	  else
19014 	      sqlite3_result_double (context, point->Y);
19015       }
19016     gaiaFreeGeomColl (geo);
19017 }
19018 
19019 static void
fnct_Z(sqlite3_context * context,int argc,sqlite3_value ** argv)19020 fnct_Z (sqlite3_context * context, int argc, sqlite3_value ** argv)
19021 {
19022 /* SQL function:
19023 / Z(BLOB encoded POINT)
19024 /
19025 / returns the Z coordinate for current POINT geometry
19026 / or NULL if any error is encountered
19027 */
19028     unsigned char *p_blob;
19029     int n_bytes;
19030     gaiaGeomCollPtr geo = NULL;
19031     gaiaPointPtr point;
19032     int gpkg_amphibious = 0;
19033     int gpkg_mode = 0;
19034     struct splite_internal_cache *cache = sqlite3_user_data (context);
19035     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19036     if (cache != NULL)
19037       {
19038 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19039 	  gpkg_mode = cache->gpkg_mode;
19040       }
19041     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19042       {
19043 	  sqlite3_result_null (context);
19044 	  return;
19045       }
19046     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19047     n_bytes = sqlite3_value_bytes (argv[0]);
19048     geo =
19049 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19050 				     gpkg_amphibious);
19051     if (!geo)
19052 	sqlite3_result_null (context);
19053     else
19054       {
19055 	  point = simplePoint (geo);
19056 	  if (!point)
19057 	      sqlite3_result_null (context);
19058 	  else
19059 	    {
19060 		if (point->DimensionModel == GAIA_XY_Z
19061 		    || point->DimensionModel == GAIA_XY_Z_M)
19062 		    sqlite3_result_double (context, point->Z);
19063 		else
19064 		    sqlite3_result_null (context);
19065 	    }
19066       }
19067     gaiaFreeGeomColl (geo);
19068 }
19069 
19070 static void
fnct_M(sqlite3_context * context,int argc,sqlite3_value ** argv)19071 fnct_M (sqlite3_context * context, int argc, sqlite3_value ** argv)
19072 {
19073 /* SQL function:
19074 / M(BLOB encoded POINT)
19075 /
19076 / returns the M coordinate for current POINT geometry
19077 / or NULL if any error is encountered
19078 */
19079     unsigned char *p_blob;
19080     int n_bytes;
19081     gaiaGeomCollPtr geo = NULL;
19082     gaiaPointPtr point;
19083     int gpkg_amphibious = 0;
19084     int gpkg_mode = 0;
19085     struct splite_internal_cache *cache = sqlite3_user_data (context);
19086     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19087     if (cache != NULL)
19088       {
19089 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19090 	  gpkg_mode = cache->gpkg_mode;
19091       }
19092     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19093       {
19094 	  sqlite3_result_null (context);
19095 	  return;
19096       }
19097     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19098     n_bytes = sqlite3_value_bytes (argv[0]);
19099     geo =
19100 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19101 				     gpkg_amphibious);
19102     if (!geo)
19103 	sqlite3_result_null (context);
19104     else
19105       {
19106 	  point = simplePoint (geo);
19107 	  if (!point)
19108 	      sqlite3_result_null (context);
19109 	  else
19110 	    {
19111 		if (point->DimensionModel == GAIA_XY_M
19112 		    || point->DimensionModel == GAIA_XY_Z_M)
19113 		    sqlite3_result_double (context, point->M);
19114 		else
19115 		    sqlite3_result_null (context);
19116 	    }
19117       }
19118     gaiaFreeGeomColl (geo);
19119 }
19120 
19121 static void
fnct_NumPoints(sqlite3_context * context,int argc,sqlite3_value ** argv)19122 fnct_NumPoints (sqlite3_context * context, int argc, sqlite3_value ** argv)
19123 {
19124 /* SQL function:
19125 / NumPoints(BLOB encoded LINESTRING)
19126 /
19127 / returns the number of vertices for current LINESTRING geometry
19128 / or NULL if any error is encountered
19129 */
19130     unsigned char *p_blob;
19131     int n_bytes;
19132     gaiaGeomCollPtr geo = NULL;
19133     gaiaLinestringPtr line;
19134     int gpkg_amphibious = 0;
19135     int gpkg_mode = 0;
19136     struct splite_internal_cache *cache = sqlite3_user_data (context);
19137     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19138     if (cache != NULL)
19139       {
19140 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19141 	  gpkg_mode = cache->gpkg_mode;
19142       }
19143     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19144       {
19145 	  sqlite3_result_null (context);
19146 	  return;
19147       }
19148     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19149     n_bytes = sqlite3_value_bytes (argv[0]);
19150     geo =
19151 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19152 				     gpkg_amphibious);
19153     if (!geo)
19154 	sqlite3_result_null (context);
19155     else
19156       {
19157 	  line = simpleLinestring (geo);
19158 	  if (!line)
19159 	      sqlite3_result_null (context);
19160 	  else
19161 	      sqlite3_result_int (context, line->Points);
19162       }
19163     gaiaFreeGeomColl (geo);
19164 }
19165 
19166 static void
point_n(sqlite3_context * context,int argc,sqlite3_value ** argv,int request)19167 point_n (sqlite3_context * context, int argc, sqlite3_value ** argv,
19168 	 int request)
19169 {
19170 /* SQL functions:
19171 / StartPoint(BLOB encoded LINESTRING geometry)
19172 / EndPoint(BLOB encoded LINESTRING geometry)
19173 / PointN(BLOB encoded LINESTRING geometry, integer point_no)
19174 /
19175 / returns the Nth POINT for current LINESTRING geometry
19176 / or NULL if any error is encountered
19177 */
19178     unsigned char *p_blob;
19179     int n_bytes;
19180     int vertex;
19181     int len;
19182     double x;
19183     double y;
19184     double z;
19185     double m;
19186     unsigned char *p_result = NULL;
19187     gaiaGeomCollPtr geo = NULL;
19188     gaiaGeomCollPtr result;
19189     gaiaLinestringPtr line;
19190     int gpkg_amphibious = 0;
19191     int gpkg_mode = 0;
19192     int tiny_point = 0;
19193     struct splite_internal_cache *cache = sqlite3_user_data (context);
19194     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19195     if (cache != NULL)
19196       {
19197 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19198 	  gpkg_mode = cache->gpkg_mode;
19199 	  tiny_point = cache->tinyPointEnabled;
19200       }
19201     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19202       {
19203 	  sqlite3_result_null (context);
19204 	  return;
19205       }
19206     if (request == GAIA_POINTN)
19207       {
19208 	  /* PointN() requires point index to be defined as an SQL function argument */
19209 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
19210 	    {
19211 		sqlite3_result_null (context);
19212 		return;
19213 	    }
19214 	  vertex = sqlite3_value_int (argv[1]);
19215       }
19216     else if (request == GAIA_END_POINT)
19217 	vertex = -1;		/* EndPoint() specifies a negative point index */
19218     else
19219 	vertex = 1;		/* StartPoint() */
19220     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19221     n_bytes = sqlite3_value_bytes (argv[0]);
19222     geo =
19223 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19224 				     gpkg_amphibious);
19225     if (!geo)
19226 	sqlite3_result_null (context);
19227     else
19228       {
19229 	  line = simpleLinestring (geo);
19230 	  if (!line)
19231 	      sqlite3_result_null (context);
19232 	  else
19233 	    {
19234 		if (vertex < 0)
19235 		    vertex = line->Points - 1;
19236 		else
19237 		    vertex -= 1;	/* decreasing the point index by 1, because PointN counts starting at index 1 */
19238 		if (vertex >= 0 && vertex < line->Points)
19239 		  {
19240 		      if (line->DimensionModel == GAIA_XY_Z)
19241 			{
19242 			    gaiaGetPointXYZ (line->Coords, vertex, &x, &y, &z);
19243 			    result = gaiaAllocGeomCollXYZ ();
19244 			    result->Srid = geo->Srid;
19245 			    gaiaAddPointToGeomCollXYZ (result, x, y, z);
19246 			}
19247 		      else if (line->DimensionModel == GAIA_XY_M)
19248 			{
19249 			    gaiaGetPointXYM (line->Coords, vertex, &x, &y, &m);
19250 			    result = gaiaAllocGeomCollXYM ();
19251 			    result->Srid = geo->Srid;
19252 			    gaiaAddPointToGeomCollXYM (result, x, y, m);
19253 			}
19254 		      else if (line->DimensionModel == GAIA_XY_Z_M)
19255 			{
19256 			    gaiaGetPointXYZM (line->Coords, vertex, &x, &y,
19257 					      &z, &m);
19258 			    result = gaiaAllocGeomCollXYZM ();
19259 			    result->Srid = geo->Srid;
19260 			    gaiaAddPointToGeomCollXYZM (result, x, y, z, m);
19261 			}
19262 		      else
19263 			{
19264 			    gaiaGetPoint (line->Coords, vertex, &x, &y);
19265 			    result = gaiaAllocGeomColl ();
19266 			    result->Srid = geo->Srid;
19267 			    gaiaAddPointToGeomColl (result, x, y);
19268 			}
19269 		  }
19270 		else
19271 		    result = NULL;
19272 		if (!result)
19273 		    sqlite3_result_null (context);
19274 		else
19275 		  {
19276 		      gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
19277 						  gpkg_mode, tiny_point);
19278 		      gaiaFreeGeomColl (result);
19279 		      sqlite3_result_blob (context, p_result, len, free);
19280 		  }
19281 	    }
19282       }
19283     gaiaFreeGeomColl (geo);
19284 }
19285 
19286 /*
19287 / the following functions simply readdress the request to point_n()
19288 / setting the appropriate request mode
19289 */
19290 
19291 static void
fnct_StartPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)19292 fnct_StartPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
19293 {
19294     point_n (context, argc, argv, GAIA_START_POINT);
19295 }
19296 
19297 static void
fnct_EndPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)19298 fnct_EndPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
19299 {
19300     point_n (context, argc, argv, GAIA_END_POINT);
19301 }
19302 
19303 static void
fnct_PointN(sqlite3_context * context,int argc,sqlite3_value ** argv)19304 fnct_PointN (sqlite3_context * context, int argc, sqlite3_value ** argv)
19305 {
19306     point_n (context, argc, argv, GAIA_POINTN);
19307 }
19308 
19309 static void
fnct_ExteriorRing(sqlite3_context * context,int argc,sqlite3_value ** argv)19310 fnct_ExteriorRing (sqlite3_context * context, int argc, sqlite3_value ** argv)
19311 {
19312 /* SQL functions:
19313 / ExteriorRing(BLOB encoded POLYGON geometry)
19314 /
19315 / returns the EXTERIOR RING for current POLYGON geometry
19316 / or NULL if any error is encountered
19317 */
19318     unsigned char *p_blob;
19319     int n_bytes;
19320     int iv;
19321     double x;
19322     double y;
19323     double z;
19324     double m;
19325     int len;
19326     unsigned char *p_result = NULL;
19327     gaiaGeomCollPtr geo = NULL;
19328     gaiaGeomCollPtr result;
19329     gaiaPolygonPtr polyg;
19330     gaiaRingPtr ring;
19331     gaiaLinestringPtr line;
19332     int gpkg_amphibious = 0;
19333     int gpkg_mode = 0;
19334     int tiny_point = 0;
19335     struct splite_internal_cache *cache = sqlite3_user_data (context);
19336     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19337     if (cache != NULL)
19338       {
19339 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19340 	  gpkg_mode = cache->gpkg_mode;
19341 	  tiny_point = cache->tinyPointEnabled;
19342       }
19343     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19344       {
19345 	  sqlite3_result_null (context);
19346 	  return;
19347       }
19348     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19349     n_bytes = sqlite3_value_bytes (argv[0]);
19350     geo =
19351 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19352 				     gpkg_amphibious);
19353     if (!geo)
19354 	sqlite3_result_null (context);
19355     else
19356       {
19357 	  polyg = simplePolygon (geo);
19358 	  if (!polyg)
19359 	      sqlite3_result_null (context);
19360 	  else
19361 	    {
19362 		ring = polyg->Exterior;
19363 		if (ring->DimensionModel == GAIA_XY_Z)
19364 		    result = gaiaAllocGeomCollXYZ ();
19365 		else if (ring->DimensionModel == GAIA_XY_M)
19366 		    result = gaiaAllocGeomCollXYM ();
19367 		else if (ring->DimensionModel == GAIA_XY_Z_M)
19368 		    result = gaiaAllocGeomCollXYZM ();
19369 		else
19370 		    result = gaiaAllocGeomColl ();
19371 		result->Srid = geo->Srid;
19372 		line = gaiaAddLinestringToGeomColl (result, ring->Points);
19373 		for (iv = 0; iv < line->Points; iv++)
19374 		  {
19375 		      if (ring->DimensionModel == GAIA_XY_Z)
19376 			{
19377 			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
19378 			    gaiaSetPointXYZ (line->Coords, iv, x, y, z);
19379 			}
19380 		      else if (ring->DimensionModel == GAIA_XY_M)
19381 			{
19382 			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
19383 			    gaiaSetPointXYM (line->Coords, iv, x, y, m);
19384 			}
19385 		      else if (ring->DimensionModel == GAIA_XY_Z_M)
19386 			{
19387 			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
19388 			    gaiaSetPointXYZM (line->Coords, iv, x, y, z, m);
19389 			}
19390 		      else
19391 			{
19392 			    gaiaGetPoint (ring->Coords, iv, &x, &y);
19393 			    gaiaSetPoint (line->Coords, iv, x, y);
19394 			}
19395 		  }
19396 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
19397 					    gpkg_mode, tiny_point);
19398 		gaiaFreeGeomColl (result);
19399 		sqlite3_result_blob (context, p_result, len, free);
19400 	    }
19401       }
19402     gaiaFreeGeomColl (geo);
19403 }
19404 
19405 static void
fnct_NumInteriorRings(sqlite3_context * context,int argc,sqlite3_value ** argv)19406 fnct_NumInteriorRings (sqlite3_context * context, int argc,
19407 		       sqlite3_value ** argv)
19408 {
19409 /* SQL function:
19410 / NumInteriorRings(BLOB encoded POLYGON)
19411 /
19412 / returns the number of INTERIOR RINGS for current POLYGON geometry
19413 / or NULL if any error is encountered
19414 */
19415     unsigned char *p_blob;
19416     int n_bytes;
19417     gaiaGeomCollPtr geo = NULL;
19418     gaiaPolygonPtr polyg;
19419     int gpkg_amphibious = 0;
19420     int gpkg_mode = 0;
19421     struct splite_internal_cache *cache = sqlite3_user_data (context);
19422     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19423     if (cache != NULL)
19424       {
19425 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19426 	  gpkg_mode = cache->gpkg_mode;
19427       }
19428     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19429       {
19430 	  sqlite3_result_null (context);
19431 	  return;
19432       }
19433     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19434     n_bytes = sqlite3_value_bytes (argv[0]);
19435     geo =
19436 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19437 				     gpkg_amphibious);
19438     if (!geo)
19439 	sqlite3_result_null (context);
19440     else
19441       {
19442 	  polyg = simplePolygon (geo);
19443 	  if (!polyg)
19444 	      sqlite3_result_null (context);
19445 	  else
19446 	      sqlite3_result_int (context, polyg->NumInteriors);
19447       }
19448     gaiaFreeGeomColl (geo);
19449 }
19450 
19451 static void
fnct_InteriorRingN(sqlite3_context * context,int argc,sqlite3_value ** argv)19452 fnct_InteriorRingN (sqlite3_context * context, int argc, sqlite3_value ** argv)
19453 {
19454 /* SQL functions:
19455 / InteriorRingN(BLOB encoded POLYGON geometry)
19456 /
19457 / returns the Nth INTERIOR RING for current POLYGON geometry
19458 / or NULL if any error is encountered
19459 */
19460     unsigned char *p_blob;
19461     int n_bytes;
19462     int border;
19463     int iv;
19464     double x;
19465     double y;
19466     double z;
19467     double m;
19468     int len;
19469     unsigned char *p_result = NULL;
19470     gaiaGeomCollPtr geo = NULL;
19471     gaiaGeomCollPtr result;
19472     gaiaPolygonPtr polyg;
19473     gaiaRingPtr ring;
19474     gaiaLinestringPtr line;
19475     int gpkg_amphibious = 0;
19476     int gpkg_mode = 0;
19477     int tiny_point = 0;
19478     struct splite_internal_cache *cache = sqlite3_user_data (context);
19479     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19480     if (cache != NULL)
19481       {
19482 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19483 	  gpkg_mode = cache->gpkg_mode;
19484 	  tiny_point = cache->tinyPointEnabled;
19485       }
19486     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19487       {
19488 	  sqlite3_result_null (context);
19489 	  return;
19490       }
19491     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
19492       {
19493 	  sqlite3_result_null (context);
19494 	  return;
19495       }
19496     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19497     n_bytes = sqlite3_value_bytes (argv[0]);
19498     border = sqlite3_value_int (argv[1]);
19499     geo =
19500 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19501 				     gpkg_amphibious);
19502     if (!geo)
19503 	sqlite3_result_null (context);
19504     else
19505       {
19506 	  polyg = simplePolygon (geo);
19507 	  if (!polyg)
19508 	      sqlite3_result_null (context);
19509 	  else
19510 	    {
19511 		if (border >= 1 && border <= polyg->NumInteriors)
19512 		  {
19513 		      ring = polyg->Interiors + (border - 1);
19514 		      if (ring->DimensionModel == GAIA_XY_Z)
19515 			  result = gaiaAllocGeomCollXYZ ();
19516 		      else if (ring->DimensionModel == GAIA_XY_M)
19517 			  result = gaiaAllocGeomCollXYM ();
19518 		      else if (ring->DimensionModel == GAIA_XY_Z_M)
19519 			  result = gaiaAllocGeomCollXYZM ();
19520 		      else
19521 			  result = gaiaAllocGeomColl ();
19522 		      result->Srid = geo->Srid;
19523 		      line = gaiaAddLinestringToGeomColl (result, ring->Points);
19524 		      for (iv = 0; iv < line->Points; iv++)
19525 			{
19526 			    if (ring->DimensionModel == GAIA_XY_Z)
19527 			      {
19528 				  gaiaGetPointXYZ (ring->Coords, iv, &x,
19529 						   &y, &z);
19530 				  gaiaSetPointXYZ (line->Coords, iv, x, y, z);
19531 			      }
19532 			    else if (ring->DimensionModel == GAIA_XY_M)
19533 			      {
19534 				  gaiaGetPointXYM (ring->Coords, iv, &x,
19535 						   &y, &m);
19536 				  gaiaSetPointXYM (line->Coords, iv, x, y, m);
19537 			      }
19538 			    else if (ring->DimensionModel == GAIA_XY_Z_M)
19539 			      {
19540 				  gaiaGetPointXYZM (ring->Coords, iv, &x,
19541 						    &y, &z, &m);
19542 				  gaiaSetPointXYZM (line->Coords, iv, x,
19543 						    y, z, m);
19544 			      }
19545 			    else
19546 			      {
19547 				  gaiaGetPoint (ring->Coords, iv, &x, &y);
19548 				  gaiaSetPoint (line->Coords, iv, x, y);
19549 			      }
19550 			}
19551 		      gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
19552 						  gpkg_mode, tiny_point);
19553 		      gaiaFreeGeomColl (result);
19554 		      sqlite3_result_blob (context, p_result, len, free);
19555 		  }
19556 		else
19557 		    sqlite3_result_null (context);
19558 	    }
19559       }
19560     gaiaFreeGeomColl (geo);
19561 }
19562 
19563 static void
fnct_NumGeometries(sqlite3_context * context,int argc,sqlite3_value ** argv)19564 fnct_NumGeometries (sqlite3_context * context, int argc, sqlite3_value ** argv)
19565 {
19566 /* SQL function:
19567 / NumGeometries(BLOB encoded GEOMETRYCOLLECTION)
19568 /
19569 / returns the number of elementary geometries for current geometry
19570 / or NULL if any error is encountered
19571 */
19572     unsigned char *p_blob;
19573     int n_bytes;
19574     int cnt = 0;
19575     gaiaPointPtr point;
19576     gaiaLinestringPtr line;
19577     gaiaPolygonPtr polyg;
19578     gaiaGeomCollPtr geo = NULL;
19579     int gpkg_amphibious = 0;
19580     int gpkg_mode = 0;
19581     struct splite_internal_cache *cache = sqlite3_user_data (context);
19582     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19583     if (cache != NULL)
19584       {
19585 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19586 	  gpkg_mode = cache->gpkg_mode;
19587       }
19588     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19589       {
19590 	  sqlite3_result_null (context);
19591 	  return;
19592       }
19593     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19594     n_bytes = sqlite3_value_bytes (argv[0]);
19595     geo =
19596 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19597 				     gpkg_amphibious);
19598     if (!geo)
19599 	sqlite3_result_null (context);
19600     else
19601       {
19602 	  point = geo->FirstPoint;
19603 	  while (point)
19604 	    {
19605 		/* counts how many points are there */
19606 		cnt++;
19607 		point = point->Next;
19608 	    }
19609 	  line = geo->FirstLinestring;
19610 	  while (line)
19611 	    {
19612 		/* counts how many linestrings are there */
19613 		cnt++;
19614 		line = line->Next;
19615 	    }
19616 	  polyg = geo->FirstPolygon;
19617 	  while (polyg)
19618 	    {
19619 		/* counts how many polygons are there */
19620 		cnt++;
19621 		polyg = polyg->Next;
19622 	    }
19623 	  sqlite3_result_int (context, cnt);
19624       }
19625     gaiaFreeGeomColl (geo);
19626 }
19627 
19628 static void
fnct_NPoints(sqlite3_context * context,int argc,sqlite3_value ** argv)19629 fnct_NPoints (sqlite3_context * context, int argc, sqlite3_value ** argv)
19630 {
19631 /* SQL function:
19632 / ST_NPoints(BLOB encoded GEOMETRYCOLLECTION)
19633 /
19634 / returns the total number of points/vertices for current geometry
19635 / or NULL if any error is encountered
19636 */
19637     unsigned char *p_blob;
19638     int n_bytes;
19639     int cnt = 0;
19640     int ib;
19641     gaiaPointPtr point;
19642     gaiaLinestringPtr line;
19643     gaiaPolygonPtr polyg;
19644     gaiaRingPtr rng;
19645     gaiaGeomCollPtr geo = NULL;
19646     int gpkg_amphibious = 0;
19647     int gpkg_mode = 0;
19648     struct splite_internal_cache *cache = sqlite3_user_data (context);
19649     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19650     if (cache != NULL)
19651       {
19652 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19653 	  gpkg_mode = cache->gpkg_mode;
19654       }
19655     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19656       {
19657 	  sqlite3_result_null (context);
19658 	  return;
19659       }
19660     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19661     n_bytes = sqlite3_value_bytes (argv[0]);
19662     geo =
19663 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19664 				     gpkg_amphibious);
19665     if (!geo)
19666 	sqlite3_result_null (context);
19667     else
19668       {
19669 	  point = geo->FirstPoint;
19670 	  while (point)
19671 	    {
19672 		/* counts how many points are there */
19673 		cnt++;
19674 		point = point->Next;
19675 	    }
19676 	  line = geo->FirstLinestring;
19677 	  while (line)
19678 	    {
19679 		/* counts how many points are there */
19680 		cnt += line->Points;
19681 		line = line->Next;
19682 	    }
19683 	  polyg = geo->FirstPolygon;
19684 	  while (polyg)
19685 	    {
19686 		/* counts how many points are in the exterior ring */
19687 		rng = polyg->Exterior;
19688 		cnt += rng->Points;
19689 		for (ib = 0; ib < polyg->NumInteriors; ib++)
19690 		  {
19691 		      /* processing any interior ring */
19692 		      rng = polyg->Interiors + ib;
19693 		      cnt += rng->Points;
19694 		  }
19695 		polyg = polyg->Next;
19696 	    }
19697 	  sqlite3_result_int (context, cnt);
19698       }
19699     gaiaFreeGeomColl (geo);
19700 }
19701 
19702 static void
fnct_NRings(sqlite3_context * context,int argc,sqlite3_value ** argv)19703 fnct_NRings (sqlite3_context * context, int argc, sqlite3_value ** argv)
19704 {
19705 /* SQL function:
19706 / ST_NRings(BLOB encoded GEOMETRYCOLLECTION)
19707 /
19708 / returns the total number of rings for current geometry
19709 / (this including both interior and exterior rings)
19710 / or NULL if any error is encountered
19711 */
19712     unsigned char *p_blob;
19713     int n_bytes;
19714     int cnt = 0;
19715     gaiaPolygonPtr polyg;
19716     gaiaGeomCollPtr geo = NULL;
19717     int gpkg_amphibious = 0;
19718     int gpkg_mode = 0;
19719     struct splite_internal_cache *cache = sqlite3_user_data (context);
19720     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19721     if (cache != NULL)
19722       {
19723 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19724 	  gpkg_mode = cache->gpkg_mode;
19725       }
19726     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19727       {
19728 	  sqlite3_result_null (context);
19729 	  return;
19730       }
19731     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19732     n_bytes = sqlite3_value_bytes (argv[0]);
19733     geo =
19734 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19735 				     gpkg_amphibious);
19736     if (!geo)
19737 	sqlite3_result_null (context);
19738     else
19739       {
19740 	  polyg = geo->FirstPolygon;
19741 	  while (polyg)
19742 	    {
19743 		/* counts how many rings are there */
19744 		cnt += polyg->NumInteriors + 1;
19745 		polyg = polyg->Next;
19746 	    }
19747 	  sqlite3_result_int (context, cnt);
19748       }
19749     gaiaFreeGeomColl (geo);
19750 }
19751 
19752 static int
is_single_point(gaiaGeomCollPtr geom)19753 is_single_point (gaiaGeomCollPtr geom)
19754 {
19755 /* check if this geometry is a simple Point */
19756     int pts = 0;
19757     int lns = 0;
19758     int pgs = 0;
19759     gaiaPointPtr pt;
19760     gaiaLinestringPtr ln;
19761     gaiaPolygonPtr pg;
19762     pt = geom->FirstPoint;
19763     while (pt)
19764       {
19765 	  pts++;
19766 	  pt = pt->Next;
19767       }
19768     ln = geom->FirstLinestring;
19769     while (ln)
19770       {
19771 	  lns++;
19772 	  ln = ln->Next;
19773       }
19774     pg = geom->FirstPolygon;
19775     while (pg)
19776       {
19777 	  pgs++;
19778 	  pg = pg->Next;
19779       }
19780     if (pts == 1 && lns == 0 && pgs == 0)
19781 	return 1;
19782     return 0;
19783 }
19784 
19785 static int
is_single_linestring(gaiaGeomCollPtr geom)19786 is_single_linestring (gaiaGeomCollPtr geom)
19787 {
19788 /* check if this geometry is a simple Linestring */
19789     int pts = 0;
19790     int lns = 0;
19791     int pgs = 0;
19792     gaiaPointPtr pt;
19793     gaiaLinestringPtr ln;
19794     gaiaPolygonPtr pg;
19795     pt = geom->FirstPoint;
19796     while (pt)
19797       {
19798 	  pts++;
19799 	  pt = pt->Next;
19800       }
19801     ln = geom->FirstLinestring;
19802     while (ln)
19803       {
19804 	  lns++;
19805 	  ln = ln->Next;
19806       }
19807     pg = geom->FirstPolygon;
19808     while (pg)
19809       {
19810 	  pgs++;
19811 	  pg = pg->Next;
19812       }
19813     if (pts == 0 && lns == 1 && pgs == 0)
19814 	return 1;
19815     return 0;
19816 }
19817 
19818 static void
fnct_AddPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)19819 fnct_AddPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
19820 {
19821 /* SQL functions:
19822 / ST_AddPoint(BLOB encoded LINESTRING line, BLOB encoded POINT point)
19823 / ST_AddPoint(BLOB encoded LINESTRING line, BLOB encoded POINT point, INTEGER position)
19824 /
19825 / returns a new Linestring by adding a new Point before "position" (zero-based index)
19826 / a negative "position" (default) means appending to the end
19827 / or NULL if any error is encountered
19828 */
19829     unsigned char *p_blob;
19830     int n_bytes;
19831     gaiaLinestringPtr ln;
19832     gaiaLinestringPtr out_ln;
19833     gaiaPointPtr pt;
19834     int position = -1;
19835     gaiaGeomCollPtr line = NULL;
19836     gaiaGeomCollPtr point = NULL;
19837     gaiaGeomCollPtr out;
19838     int len;
19839     unsigned char *p_result = NULL;
19840     int iv;
19841     int out_iv;
19842     double x;
19843     double y;
19844     double m;
19845     double z;
19846     int gpkg_amphibious = 0;
19847     int gpkg_mode = 0;
19848     int tiny_point = 0;
19849     struct splite_internal_cache *cache = sqlite3_user_data (context);
19850     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
19851     if (cache != NULL)
19852       {
19853 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
19854 	  gpkg_mode = cache->gpkg_mode;
19855 	  tiny_point = cache->tinyPointEnabled;
19856       }
19857     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
19858       {
19859 	  sqlite3_result_null (context);
19860 	  return;
19861       }
19862     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
19863     n_bytes = sqlite3_value_bytes (argv[0]);
19864     line =
19865 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19866 				     gpkg_amphibious);
19867     if (!line)
19868       {
19869 	  sqlite3_result_null (context);
19870 	  return;
19871       }
19872     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
19873       {
19874 	  gaiaFreeGeomColl (line);
19875 	  sqlite3_result_null (context);
19876 	  return;
19877       }
19878     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
19879     n_bytes = sqlite3_value_bytes (argv[1]);
19880     point =
19881 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
19882 				     gpkg_amphibious);
19883     if (!point)
19884       {
19885 	  gaiaFreeGeomColl (line);
19886 	  sqlite3_result_null (context);
19887 	  return;
19888       }
19889     if (argc == 3)
19890       {
19891 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
19892 	    {
19893 		sqlite3_result_null (context);
19894 		goto stop;
19895 	    }
19896 	  position = sqlite3_value_int (argv[2]);
19897       }
19898     if (is_single_linestring (line) && is_single_point (point))
19899 	;
19900     else
19901       {
19902 	  sqlite3_result_null (context);
19903 	  goto stop;
19904       }
19905     ln = line->FirstLinestring;
19906     pt = point->FirstPoint;
19907     if (position >= 0 && position >= ln->Points)
19908       {
19909 	  sqlite3_result_null (context);
19910 	  goto stop;
19911       }
19912 /* creating the output Geometry */
19913     if (line->DimensionModel == GAIA_XY_Z)
19914 	out = gaiaAllocGeomCollXYZ ();
19915     else if (line->DimensionModel == GAIA_XY_M)
19916 	out = gaiaAllocGeomCollXYM ();
19917     else if (line->DimensionModel == GAIA_XY_Z_M)
19918 	out = gaiaAllocGeomCollXYZM ();
19919     else
19920 	out = gaiaAllocGeomColl ();
19921     out->Srid = line->Srid;
19922     out->DeclaredType = line->DeclaredType;
19923     out_ln = gaiaAddLinestringToGeomColl (out, ln->Points + 1);
19924     if (position < 0)
19925       {
19926 	  /* appending the new Point */
19927 	  for (iv = 0; iv < ln->Points; iv++)
19928 	    {
19929 		if (line->DimensionModel == GAIA_XY_Z)
19930 		  {
19931 		      gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
19932 		      gaiaSetPointXYZ (out_ln->Coords, iv, x, y, z);
19933 		  }
19934 		else if (line->DimensionModel == GAIA_XY_M)
19935 		  {
19936 		      gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
19937 		      gaiaSetPointXYM (out_ln->Coords, iv, x, y, m);
19938 		  }
19939 		else if (line->DimensionModel == GAIA_XY_Z_M)
19940 		  {
19941 		      gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
19942 		      gaiaSetPointXYZM (out_ln->Coords, iv, x, y, z, m);
19943 		  }
19944 		else
19945 		  {
19946 		      gaiaGetPoint (ln->Coords, iv, &x, &y);
19947 		      gaiaSetPoint (out_ln->Coords, iv, x, y);
19948 		  }
19949 	    }
19950 	  /* appending the new Point */
19951 	  x = pt->X;
19952 	  y = pt->Y;
19953 	  z = pt->Z;
19954 	  m = pt->M;
19955 	  out_iv = ln->Points;
19956 	  if (line->DimensionModel == GAIA_XY_Z)
19957 	    {
19958 		gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
19959 	    }
19960 	  else if (line->DimensionModel == GAIA_XY_M)
19961 	    {
19962 		gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
19963 	    }
19964 	  else if (line->DimensionModel == GAIA_XY_Z_M)
19965 	    {
19966 		gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
19967 	    }
19968 	  else
19969 	    {
19970 		gaiaSetPoint (out_ln->Coords, out_iv, x, y);
19971 	    }
19972       }
19973     else
19974       {
19975 	  /* inserting the new Point before "position" */
19976 	  out_iv = 0;
19977 	  for (iv = 0; iv < position; iv++)
19978 	    {
19979 		/* copying all Points before "position" */
19980 		if (line->DimensionModel == GAIA_XY_Z)
19981 		  {
19982 		      gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
19983 		      gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
19984 		  }
19985 		else if (line->DimensionModel == GAIA_XY_M)
19986 		  {
19987 		      gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
19988 		      gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
19989 		  }
19990 		else if (line->DimensionModel == GAIA_XY_Z_M)
19991 		  {
19992 		      gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
19993 		      gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
19994 		  }
19995 		else
19996 		  {
19997 		      gaiaGetPoint (ln->Coords, iv, &x, &y);
19998 		      gaiaSetPoint (out_ln->Coords, out_iv, x, y);
19999 		  }
20000 		out_iv++;
20001 	    }
20002 	  /* inserting the new Point */
20003 	  x = pt->X;
20004 	  y = pt->Y;
20005 	  z = pt->Z;
20006 	  m = pt->M;
20007 	  if (line->DimensionModel == GAIA_XY_Z)
20008 	    {
20009 		gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
20010 	    }
20011 	  else if (line->DimensionModel == GAIA_XY_M)
20012 	    {
20013 		gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
20014 	    }
20015 	  else if (line->DimensionModel == GAIA_XY_Z_M)
20016 	    {
20017 		gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
20018 	    }
20019 	  else
20020 	    {
20021 		gaiaSetPoint (out_ln->Coords, out_iv, x, y);
20022 	    }
20023 	  out_iv++;
20024 	  for (iv = position; iv < ln->Points; iv++)
20025 	    {
20026 		/* copying all Points after "position" */
20027 		if (line->DimensionModel == GAIA_XY_Z)
20028 		  {
20029 		      gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
20030 		      gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
20031 		  }
20032 		else if (line->DimensionModel == GAIA_XY_M)
20033 		  {
20034 		      gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
20035 		      gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
20036 		  }
20037 		else if (line->DimensionModel == GAIA_XY_Z_M)
20038 		  {
20039 		      gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
20040 		      gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
20041 		  }
20042 		else
20043 		  {
20044 		      gaiaGetPoint (ln->Coords, iv, &x, &y);
20045 		      gaiaSetPoint (out_ln->Coords, out_iv, x, y);
20046 		  }
20047 		out_iv++;
20048 	    }
20049       }
20050     gaiaToSpatiaLiteBlobWkbEx2 (out, &p_result, &len, gpkg_mode, tiny_point);
20051     gaiaFreeGeomColl (out);
20052     sqlite3_result_blob (context, p_result, len, free);
20053   stop:
20054     gaiaFreeGeomColl (line);
20055     gaiaFreeGeomColl (point);
20056 }
20057 
20058 static void
commont_set_point(sqlite3_context * context,gaiaGeomCollPtr line,int position,gaiaGeomCollPtr point)20059 commont_set_point (sqlite3_context * context, gaiaGeomCollPtr line,
20060 		   int position, gaiaGeomCollPtr point)
20061 {
20062 /* SetPoint - common implementation */
20063     gaiaGeomCollPtr out;
20064     gaiaLinestringPtr ln;
20065     gaiaLinestringPtr out_ln;
20066     gaiaPointPtr pt;
20067     unsigned char *p_result = NULL;
20068     int len;
20069     int iv;
20070     double x = 0.0;
20071     double y = 0.0;
20072     double m = 0.0;
20073     double z = 0.0;
20074     int gpkg_mode = 0;
20075     int tiny_point = 0;
20076     struct splite_internal_cache *cache = sqlite3_user_data (context);
20077     if (cache != NULL)
20078       {
20079 	  gpkg_mode = cache->gpkg_mode;
20080 	  tiny_point = cache->tinyPointEnabled;
20081       }
20082 
20083     if (is_single_linestring (line) && is_single_point (point))
20084 	;
20085     else
20086       {
20087 	  sqlite3_result_null (context);
20088 	  goto stop;
20089       }
20090     ln = line->FirstLinestring;
20091     pt = point->FirstPoint;
20092     if (position < 0 || position >= ln->Points)
20093       {
20094 	  sqlite3_result_null (context);
20095 	  goto stop;
20096       }
20097 /* creating the output Geometry */
20098     if (line->DimensionModel == GAIA_XY_Z)
20099 	out = gaiaAllocGeomCollXYZ ();
20100     else if (line->DimensionModel == GAIA_XY_M)
20101 	out = gaiaAllocGeomCollXYM ();
20102     else if (line->DimensionModel == GAIA_XY_Z_M)
20103 	out = gaiaAllocGeomCollXYZM ();
20104     else
20105 	out = gaiaAllocGeomColl ();
20106     out->Srid = line->Srid;
20107     out->DeclaredType = line->DeclaredType;
20108     out_ln = gaiaAddLinestringToGeomColl (out, ln->Points);
20109     for (iv = 0; iv < ln->Points; iv++)
20110       {
20111 	  if (line->DimensionModel == GAIA_XY_Z)
20112 	    {
20113 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
20114 	    }
20115 	  else if (line->DimensionModel == GAIA_XY_M)
20116 	    {
20117 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
20118 	    }
20119 	  else if (line->DimensionModel == GAIA_XY_Z_M)
20120 	    {
20121 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
20122 	    }
20123 	  else
20124 	    {
20125 		gaiaGetPoint (ln->Coords, iv, &x, &y);
20126 	    }
20127 	  if (iv == position)
20128 	    {
20129 		/* replacing the new Point */
20130 		x = pt->X;
20131 		y = pt->Y;
20132 		z = pt->Z;
20133 		m = pt->M;
20134 	    }
20135 	  if (line->DimensionModel == GAIA_XY_Z)
20136 	    {
20137 		gaiaSetPointXYZ (out_ln->Coords, iv, x, y, z);
20138 	    }
20139 	  else if (line->DimensionModel == GAIA_XY_M)
20140 	    {
20141 		gaiaSetPointXYM (out_ln->Coords, iv, x, y, m);
20142 	    }
20143 	  else if (line->DimensionModel == GAIA_XY_Z_M)
20144 	    {
20145 		gaiaSetPointXYZM (out_ln->Coords, iv, x, y, z, m);
20146 	    }
20147 	  else
20148 	    {
20149 		gaiaSetPoint (out_ln->Coords, iv, x, y);
20150 	    }
20151       }
20152     gaiaToSpatiaLiteBlobWkbEx2 (out, &p_result, &len, gpkg_mode, tiny_point);
20153     gaiaFreeGeomColl (out);
20154     sqlite3_result_blob (context, p_result, len, free);
20155   stop:
20156     gaiaFreeGeomColl (line);
20157     gaiaFreeGeomColl (point);
20158 }
20159 
20160 static void
fnct_SetPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)20161 fnct_SetPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
20162 {
20163 /* SQL functions:
20164 / ST_SetPoint(BLOB encoded LINESTRING line, INTEGER position, BLOB encoded POINT point)
20165 /
20166 / returns a new Linestring by replacing the Point at "position" (zero-based index)
20167 / or NULL if any error is encountered
20168 */
20169     unsigned char *p_blob;
20170     int n_bytes;
20171     int position;
20172     gaiaGeomCollPtr line = NULL;
20173     gaiaGeomCollPtr point = NULL;
20174     int gpkg_amphibious = 0;
20175     int gpkg_mode = 0;
20176     struct splite_internal_cache *cache = sqlite3_user_data (context);
20177     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20178     if (cache != NULL)
20179       {
20180 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20181 	  gpkg_mode = cache->gpkg_mode;
20182       }
20183     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20184       {
20185 	  sqlite3_result_null (context);
20186 	  return;
20187       }
20188     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20189     n_bytes = sqlite3_value_bytes (argv[0]);
20190     line =
20191 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20192 				     gpkg_amphibious);
20193     if (!line)
20194       {
20195 	  sqlite3_result_null (context);
20196 	  return;
20197       }
20198     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
20199       {
20200 	  gaiaFreeGeomColl (line);
20201 	  sqlite3_result_null (context);
20202 	  return;
20203       }
20204     position = sqlite3_value_int (argv[1]);
20205     if (sqlite3_value_type (argv[2]) != SQLITE_BLOB)
20206       {
20207 	  gaiaFreeGeomColl (line);
20208 	  sqlite3_result_null (context);
20209 	  return;
20210       }
20211     p_blob = (unsigned char *) sqlite3_value_blob (argv[2]);
20212     n_bytes = sqlite3_value_bytes (argv[2]);
20213     point =
20214 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20215 				     gpkg_amphibious);
20216     if (!point)
20217       {
20218 	  gaiaFreeGeomColl (line);
20219 	  sqlite3_result_null (context);
20220 	  return;
20221       }
20222     commont_set_point (context, line, position, point);
20223 }
20224 
20225 static void
fnct_SetStartPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)20226 fnct_SetStartPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
20227 {
20228 /* SQL functions:
20229 / ST_SetStartPoint(BLOB encoded LINESTRING line, BLOB encoded POINT point)
20230 /
20231 / returns a new Linestring by replacing its StartPoint
20232 / or NULL if any error is encountered
20233 */
20234     unsigned char *p_blob;
20235     int n_bytes;
20236     gaiaGeomCollPtr line = NULL;
20237     gaiaGeomCollPtr point = NULL;
20238     int gpkg_amphibious = 0;
20239     int gpkg_mode = 0;
20240     struct splite_internal_cache *cache = sqlite3_user_data (context);
20241     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20242     if (cache != NULL)
20243       {
20244 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20245 	  gpkg_mode = cache->gpkg_mode;
20246       }
20247     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20248       {
20249 	  sqlite3_result_null (context);
20250 	  return;
20251       }
20252     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20253     n_bytes = sqlite3_value_bytes (argv[0]);
20254     line =
20255 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20256 				     gpkg_amphibious);
20257     if (!line)
20258       {
20259 	  sqlite3_result_null (context);
20260 	  return;
20261       }
20262     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
20263       {
20264 	  gaiaFreeGeomColl (line);
20265 	  sqlite3_result_null (context);
20266 	  return;
20267       }
20268     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
20269     n_bytes = sqlite3_value_bytes (argv[1]);
20270     point =
20271 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20272 				     gpkg_amphibious);
20273     if (!point)
20274       {
20275 	  gaiaFreeGeomColl (line);
20276 	  sqlite3_result_null (context);
20277 	  return;
20278       }
20279     commont_set_point (context, line, 0, point);
20280 }
20281 
20282 static void
fnct_SetEndPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)20283 fnct_SetEndPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
20284 {
20285 /* SQL functions:
20286 / ST_SetEndPoint(BLOB encoded LINESTRING line, BLOB encoded POINT point)
20287 /
20288 / returns a new Linestring by replacing its EndPoint
20289 / or NULL if any error is encountered
20290 */
20291     unsigned char *p_blob;
20292     int n_bytes;
20293     gaiaLinestringPtr ln;
20294     gaiaGeomCollPtr line = NULL;
20295     gaiaGeomCollPtr point = NULL;
20296     int position;
20297     int gpkg_amphibious = 0;
20298     int gpkg_mode = 0;
20299     struct splite_internal_cache *cache = sqlite3_user_data (context);
20300     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20301     if (cache != NULL)
20302       {
20303 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20304 	  gpkg_mode = cache->gpkg_mode;
20305       }
20306     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20307       {
20308 	  sqlite3_result_null (context);
20309 	  return;
20310       }
20311     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20312     n_bytes = sqlite3_value_bytes (argv[0]);
20313     line =
20314 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20315 				     gpkg_amphibious);
20316     if (!line)
20317       {
20318 	  sqlite3_result_null (context);
20319 	  return;
20320       }
20321     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
20322       {
20323 	  gaiaFreeGeomColl (line);
20324 	  sqlite3_result_null (context);
20325 	  return;
20326       }
20327     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
20328     n_bytes = sqlite3_value_bytes (argv[1]);
20329     point =
20330 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20331 				     gpkg_amphibious);
20332     if (!point)
20333       {
20334 	  gaiaFreeGeomColl (line);
20335 	  sqlite3_result_null (context);
20336 	  return;
20337       }
20338     if (is_single_linestring (line) && is_single_point (point))
20339 	;
20340     else
20341       {
20342 	  sqlite3_result_null (context);
20343 	  goto stop;
20344       }
20345     ln = line->FirstLinestring;
20346     position = ln->Points - 1;
20347     commont_set_point (context, line, position, point);
20348     return;
20349   stop:
20350     gaiaFreeGeomColl (line);
20351     gaiaFreeGeomColl (point);
20352 }
20353 
20354 static void
fnct_RemovePoint(sqlite3_context * context,int argc,sqlite3_value ** argv)20355 fnct_RemovePoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
20356 {
20357 /* SQL functions:
20358 / ST_RemovePoint(BLOB encoded LINESTRING line, INTEGER position)
20359 /
20360 / returns a new Linestring by removing the Point at "position" (zero-based index)
20361 / or NULL if any error is encountered
20362 */
20363     unsigned char *p_blob;
20364     int n_bytes;
20365     gaiaLinestringPtr ln;
20366     gaiaLinestringPtr out_ln;
20367     int position;
20368     gaiaGeomCollPtr line = NULL;
20369     gaiaGeomCollPtr out;
20370     int len;
20371     unsigned char *p_result = NULL;
20372     int iv;
20373     int out_iv;
20374     double x;
20375     double y;
20376     double m;
20377     double z;
20378     int gpkg_amphibious = 0;
20379     int gpkg_mode = 0;
20380     int tiny_point = 0;
20381     struct splite_internal_cache *cache = sqlite3_user_data (context);
20382     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20383     if (cache != NULL)
20384       {
20385 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20386 	  gpkg_mode = cache->gpkg_mode;
20387 	  tiny_point = cache->tinyPointEnabled;
20388       }
20389     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20390       {
20391 	  sqlite3_result_null (context);
20392 	  return;
20393       }
20394     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20395     n_bytes = sqlite3_value_bytes (argv[0]);
20396     line =
20397 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20398 				     gpkg_amphibious);
20399     if (!line)
20400       {
20401 	  sqlite3_result_null (context);
20402 	  return;
20403       }
20404     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
20405       {
20406 	  sqlite3_result_null (context);
20407 	  goto stop;
20408       }
20409     position = sqlite3_value_int (argv[1]);
20410     if (!is_single_linestring (line))
20411       {
20412 	  sqlite3_result_null (context);
20413 	  goto stop;
20414       }
20415     ln = line->FirstLinestring;
20416     if (position < 0 || position >= ln->Points)
20417       {
20418 	  sqlite3_result_null (context);
20419 	  goto stop;
20420       }
20421 /* creating the output Geometry */
20422     if (line->DimensionModel == GAIA_XY_Z)
20423 	out = gaiaAllocGeomCollXYZ ();
20424     else if (line->DimensionModel == GAIA_XY_M)
20425 	out = gaiaAllocGeomCollXYM ();
20426     else if (line->DimensionModel == GAIA_XY_Z_M)
20427 	out = gaiaAllocGeomCollXYZM ();
20428     else
20429 	out = gaiaAllocGeomColl ();
20430     out->Srid = line->Srid;
20431     out->DeclaredType = line->DeclaredType;
20432     out_ln = gaiaAddLinestringToGeomColl (out, ln->Points - 1);
20433     out_iv = 0;
20434     for (iv = 0; iv < position; iv++)
20435       {
20436 	  /* copying all Points before "position" */
20437 	  if (line->DimensionModel == GAIA_XY_Z)
20438 	    {
20439 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
20440 		gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
20441 	    }
20442 	  else if (line->DimensionModel == GAIA_XY_M)
20443 	    {
20444 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
20445 		gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
20446 	    }
20447 	  else if (line->DimensionModel == GAIA_XY_Z_M)
20448 	    {
20449 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
20450 		gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
20451 	    }
20452 	  else
20453 	    {
20454 		gaiaGetPoint (ln->Coords, iv, &x, &y);
20455 		gaiaSetPoint (out_ln->Coords, out_iv, x, y);
20456 	    }
20457 	  out_iv++;
20458       }
20459     for (iv = position + 1; iv < ln->Points; iv++)
20460       {
20461 	  /* copying all Points after "position" */
20462 	  if (line->DimensionModel == GAIA_XY_Z)
20463 	    {
20464 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
20465 		gaiaSetPointXYZ (out_ln->Coords, out_iv, x, y, z);
20466 	    }
20467 	  else if (line->DimensionModel == GAIA_XY_M)
20468 	    {
20469 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
20470 		gaiaSetPointXYM (out_ln->Coords, out_iv, x, y, m);
20471 	    }
20472 	  else if (line->DimensionModel == GAIA_XY_Z_M)
20473 	    {
20474 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
20475 		gaiaSetPointXYZM (out_ln->Coords, out_iv, x, y, z, m);
20476 	    }
20477 	  else
20478 	    {
20479 		gaiaGetPoint (ln->Coords, iv, &x, &y);
20480 		gaiaSetPoint (out_ln->Coords, out_iv, x, y);
20481 	    }
20482 	  out_iv++;
20483       }
20484     gaiaToSpatiaLiteBlobWkbEx2 (out, &p_result, &len, gpkg_mode, tiny_point);
20485     gaiaFreeGeomColl (out);
20486     sqlite3_result_blob (context, p_result, len, free);
20487   stop:
20488     gaiaFreeGeomColl (line);
20489 }
20490 
20491 static void
fnct_MakePolygon(sqlite3_context * context,int argc,sqlite3_value ** argv)20492 fnct_MakePolygon (sqlite3_context * context, int argc, sqlite3_value ** argv)
20493 {
20494 /* SQL functions:
20495 / ST_MakePolygon(BLOB encoded LINESTRING line)
20496 / ST_MakePolygon(BLOB encoded LINESTRING line, BLOB encoded (MULTI)LINESTING holes)
20497 /
20498 / returns a new POLYGON from the given exterior and interior rings
20499 / or NULL if any error is encountered
20500 */
20501     unsigned char *p_blob;
20502     int n_bytes;
20503     gaiaGeomCollPtr exterior = NULL;
20504     gaiaGeomCollPtr interiors = NULL;
20505     gaiaGeomCollPtr out;
20506     int len;
20507     unsigned char *p_result = NULL;
20508     int gpkg_amphibious = 0;
20509     int gpkg_mode = 0;
20510     int tiny_point = 0;
20511     struct splite_internal_cache *cache = sqlite3_user_data (context);
20512     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20513     if (cache != NULL)
20514       {
20515 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20516 	  gpkg_mode = cache->gpkg_mode;
20517 	  tiny_point = cache->tinyPointEnabled;
20518       }
20519     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20520       {
20521 	  sqlite3_result_null (context);
20522 	  goto stop;
20523       }
20524     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20525     n_bytes = sqlite3_value_bytes (argv[0]);
20526     exterior =
20527 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20528 				     gpkg_amphibious);
20529     if (!exterior)
20530       {
20531 	  sqlite3_result_null (context);
20532 	  goto stop;
20533       }
20534     if (argc == 2)
20535       {
20536 	  if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
20537 	    {
20538 		sqlite3_result_null (context);
20539 		goto stop;
20540 	    }
20541 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
20542 	  n_bytes = sqlite3_value_bytes (argv[1]);
20543 	  interiors =
20544 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20545 					   gpkg_amphibious);
20546 	  if (!interiors)
20547 	    {
20548 		sqlite3_result_null (context);
20549 		goto stop;
20550 	    }
20551       }
20552     out = gaiaMakePolygon (exterior, interiors);
20553     if (!out)
20554       {
20555 	  sqlite3_result_null (context);
20556 	  goto stop;
20557       }
20558     gaiaToSpatiaLiteBlobWkbEx2 (out, &p_result, &len, gpkg_mode, tiny_point);
20559     gaiaFreeGeomColl (out);
20560     sqlite3_result_blob (context, p_result, len, free);
20561   stop:
20562     gaiaFreeGeomColl (exterior);
20563     gaiaFreeGeomColl (interiors);
20564 }
20565 
20566 static int
getXYZMSinglePoint(gaiaGeomCollPtr geom,double * x,double * y,double * z,double * m)20567 getXYZMSinglePoint (gaiaGeomCollPtr geom, double *x, double *y, double *z,
20568 		    double *m)
20569 {
20570 /* check if this geometry is a simple Point (returning full coords) */
20571     int pts = 0;
20572     int lns = 0;
20573     int pgs = 0;
20574     gaiaPointPtr pt;
20575     gaiaLinestringPtr ln;
20576     gaiaPolygonPtr pg;
20577     pt = geom->FirstPoint;
20578     while (pt)
20579       {
20580 	  pts++;
20581 	  pt = pt->Next;
20582       }
20583     ln = geom->FirstLinestring;
20584     while (ln)
20585       {
20586 	  lns++;
20587 	  ln = ln->Next;
20588       }
20589     pg = geom->FirstPolygon;
20590     while (pg)
20591       {
20592 	  pgs++;
20593 	  pg = pg->Next;
20594       }
20595     if (pts == 1 && lns == 0 && pgs == 0)
20596 	;
20597     else
20598 	return 0;
20599     *x = geom->FirstPoint->X;
20600     *y = geom->FirstPoint->Y;
20601     if (geom->DimensionModel == GAIA_XY_Z
20602 	|| geom->DimensionModel == GAIA_XY_Z_M)
20603 	*z = geom->FirstPoint->Z;
20604     else
20605 	*z = 0.0;
20606     if (geom->DimensionModel == GAIA_XY_M
20607 	|| geom->DimensionModel == GAIA_XY_Z_M)
20608 	*m = geom->FirstPoint->M;
20609     else
20610 	*m = 0.0;
20611     return 1;
20612 }
20613 
20614 static void
fnct_SnapToGrid(sqlite3_context * context,int argc,sqlite3_value ** argv)20615 fnct_SnapToGrid (sqlite3_context * context, int argc, sqlite3_value ** argv)
20616 {
20617 /* SQL function:
20618 / ST_SnapToGrid(BLOBencoded geom, double size)
20619 / ST_SnapToGrid(BLOBencoded geom, double sizeX, double sizeY)
20620 / ST_SnapToGrid(BLOBencoded geom, double originX, double originY,
20621 /               double sizeX, double sizeY)
20622 /
20623 / Snap all points of the input geometry to the grid defined by its
20624 / origin and cell size. Remove consecutive points falling on the same
20625 / cell. Collapsed geometries in a collection are stripped from it.
20626 /
20627 /
20628 / ST_SnapToGrid(BLOBencoded geom, BLOBencoded point, double sizeX,
20629 /               double sizeY, double sizeZ, double sizeM)
20630 /
20631 / Snap all points of the input geometry to the grid defined by its
20632 / origin (the second argument, must be a point) and cell sizes.
20633 /
20634 / Specify 0 as size for any dimension you don't want to snap to
20635 / a grid.
20636 / return NULL if any error is encountered
20637 */
20638     unsigned char *p_blob;
20639     int n_bytes;
20640     int int_value;
20641     double origin_x = 0.0;
20642     double origin_y = 0.0;
20643     double origin_z = 0.0;
20644     double origin_m = 0.0;
20645     double size_x = 0.0;
20646     double size_y = 0.0;
20647     double size_z = 0.0;
20648     double size_m = 0.0;
20649     gaiaGeomCollPtr geo = NULL;
20650     gaiaGeomCollPtr point = NULL;
20651     gaiaGeomCollPtr result = NULL;
20652     int gpkg_amphibious = 0;
20653     int gpkg_mode = 0;
20654     int tiny_point = 0;
20655     struct splite_internal_cache *cache = sqlite3_user_data (context);
20656     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20657     if (cache != NULL)
20658       {
20659 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
20660 	  gpkg_mode = cache->gpkg_mode;
20661 	  tiny_point = cache->tinyPointEnabled;
20662       }
20663     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
20664       {
20665 	  sqlite3_result_null (context);
20666 	  return;
20667       }
20668     if (argc == 2)
20669       {
20670 	  /* ST_SnapToGrid(BLOBencoded geom, double size) */
20671 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
20672 	    {
20673 		int_value = sqlite3_value_int (argv[1]);
20674 		size_x = int_value;
20675 		size_y = size_x;
20676 	    }
20677 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
20678 	    {
20679 		size_x = sqlite3_value_double (argv[1]);
20680 		size_y = size_x;
20681 	    }
20682 	  else
20683 	    {
20684 		sqlite3_result_null (context);
20685 		return;
20686 	    }
20687       }
20688     if (argc == 3)
20689       {
20690 	  /* ST_SnapToGrid(BLOBencoded geom, double sizeX, double sizeY) */
20691 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
20692 	    {
20693 		int_value = sqlite3_value_int (argv[1]);
20694 		size_x = int_value;
20695 	    }
20696 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
20697 	    {
20698 		size_x = sqlite3_value_double (argv[1]);
20699 	    }
20700 	  else
20701 	    {
20702 		sqlite3_result_null (context);
20703 		return;
20704 	    }
20705 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
20706 	    {
20707 		int_value = sqlite3_value_int (argv[2]);
20708 		size_y = int_value;
20709 	    }
20710 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
20711 	    {
20712 		size_y = sqlite3_value_double (argv[2]);
20713 	    }
20714 	  else
20715 	    {
20716 		sqlite3_result_null (context);
20717 		return;
20718 	    }
20719       }
20720     if (argc == 5)
20721       {
20722 	  /*
20723 	     / ST_SnapToGrid(BLOBencoded geom, double originX, double originY,
20724 	     /               double sizeX, double sizeY)
20725 	   */
20726 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
20727 	    {
20728 		int_value = sqlite3_value_int (argv[1]);
20729 		origin_x = int_value;
20730 	    }
20731 	  else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
20732 	    {
20733 		origin_x = sqlite3_value_double (argv[1]);
20734 	    }
20735 	  else
20736 	    {
20737 		sqlite3_result_null (context);
20738 		return;
20739 	    }
20740 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
20741 	    {
20742 		int_value = sqlite3_value_int (argv[2]);
20743 		origin_y = int_value;
20744 	    }
20745 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
20746 	    {
20747 		origin_y = sqlite3_value_double (argv[2]);
20748 	    }
20749 	  else
20750 	    {
20751 		sqlite3_result_null (context);
20752 		return;
20753 	    }
20754 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
20755 	    {
20756 		int_value = sqlite3_value_int (argv[3]);
20757 		size_x = int_value;
20758 	    }
20759 	  else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
20760 	    {
20761 		size_x = sqlite3_value_double (argv[3]);
20762 	    }
20763 	  else
20764 	    {
20765 		sqlite3_result_null (context);
20766 		return;
20767 	    }
20768 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
20769 	    {
20770 		int_value = sqlite3_value_int (argv[4]);
20771 		size_y = int_value;
20772 	    }
20773 	  else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
20774 	    {
20775 		size_y = sqlite3_value_double (argv[4]);
20776 	    }
20777 	  else
20778 	    {
20779 		sqlite3_result_null (context);
20780 		return;
20781 	    }
20782       }
20783     if (argc == 6)
20784       {
20785 	  /*
20786 	     / ST_SnapToGrid(BLOBencoded geom, BLOBencoded point, double sizeX,
20787 	     /               double sizeY, double sizeZ, double sizeM)
20788 	   */
20789 	  if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
20790 	    {
20791 		sqlite3_result_null (context);
20792 		return;
20793 	    }
20794 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
20795 	  n_bytes = sqlite3_value_bytes (argv[1]);
20796 	  point =
20797 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20798 					   gpkg_amphibious);
20799 	  if (!point)
20800 	    {
20801 		sqlite3_result_null (context);
20802 		return;
20803 	    }
20804 	  if (!getXYZMSinglePoint
20805 	      (point, &origin_x, &origin_y, &origin_z, &origin_m))
20806 	    {
20807 		gaiaFreeGeomColl (point);
20808 		sqlite3_result_null (context);
20809 		return;
20810 	    }
20811 	  gaiaFreeGeomColl (point);
20812 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
20813 	    {
20814 		int_value = sqlite3_value_int (argv[2]);
20815 		size_x = int_value;
20816 	    }
20817 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
20818 	    {
20819 		size_x = sqlite3_value_double (argv[2]);
20820 	    }
20821 	  else
20822 	    {
20823 		sqlite3_result_null (context);
20824 		return;
20825 	    }
20826 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
20827 	    {
20828 		int_value = sqlite3_value_int (argv[3]);
20829 		size_y = int_value;
20830 	    }
20831 	  else if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
20832 	    {
20833 		size_y = sqlite3_value_double (argv[3]);
20834 	    }
20835 	  else
20836 	    {
20837 		sqlite3_result_null (context);
20838 		return;
20839 	    }
20840 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
20841 	    {
20842 		int_value = sqlite3_value_int (argv[4]);
20843 		size_z = int_value;
20844 	    }
20845 	  else if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
20846 	    {
20847 		size_z = sqlite3_value_double (argv[4]);
20848 	    }
20849 	  else
20850 	    {
20851 		sqlite3_result_null (context);
20852 		return;
20853 	    }
20854 	  if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
20855 	    {
20856 		int_value = sqlite3_value_int (argv[5]);
20857 		size_m = int_value;
20858 	    }
20859 	  else if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
20860 	    {
20861 		size_m = sqlite3_value_double (argv[5]);
20862 	    }
20863 	  else
20864 	    {
20865 		sqlite3_result_null (context);
20866 		return;
20867 	    }
20868       }
20869     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
20870     n_bytes = sqlite3_value_bytes (argv[0]);
20871     geo =
20872 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
20873 				     gpkg_amphibious);
20874     if (!geo)
20875 	sqlite3_result_null (context);
20876     else
20877       {
20878 	  result =
20879 	      gaiaSnapToGrid (geo, origin_x, origin_y, origin_z, origin_m,
20880 			      size_x, size_y, size_z, size_m);
20881 	  if (result == NULL)
20882 	      sqlite3_result_null (context);
20883 	  else
20884 	    {
20885 		/* builds the BLOB geometry to be returned */
20886 		int len;
20887 		unsigned char *p_result = NULL;
20888 		result->Srid = geo->Srid;
20889 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
20890 					    gpkg_mode, tiny_point);
20891 		sqlite3_result_blob (context, p_result, len, free);
20892 		gaiaFreeGeomColl (result);
20893 	    }
20894       }
20895     gaiaFreeGeomColl (geo);
20896 }
20897 
20898 static char garsMapping[24] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J',
20899     'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
20900 };
20901 
20902 static char
garsLetterCode(int value)20903 garsLetterCode (int value)
20904 {
20905     return garsMapping[value];
20906 }
20907 
20908 static int
garsMappingIndex(const char letter)20909 garsMappingIndex (const char letter)
20910 {
20911     int i = 0;
20912     for (i = 0; i < 24; ++i)
20913       {
20914 	  if (letter == garsMapping[i])
20915 	      return i;
20916       }
20917     return -1;
20918 }
20919 
20920 static double
garsLetterToDegreesLat(char msd,char lsd)20921 garsLetterToDegreesLat (char msd, char lsd)
20922 {
20923     double high = garsMappingIndex (msd) * 24.0;
20924     double low = garsMappingIndex (lsd);
20925     if ((high < 0) || (low < 0))
20926       {
20927 	  return -100.0;
20928       }
20929     return (((high + low) * 0.5) - 90.0);
20930 }
20931 
20932 
20933 static void
fnct_GARSMbr(sqlite3_context * context,int argc,sqlite3_value ** argv)20934 fnct_GARSMbr (sqlite3_context * context, int argc, sqlite3_value ** argv)
20935 {
20936 /* SQL function:
20937 / GARSMbr(Text)
20938 /
20939 / converts the Text (which should be a valid GARS area) to the corresponding
20940 / MBR geometry.
20941 / This function will return NULL if an error occurs
20942 */
20943     const char *text = NULL;
20944     int len = 0;
20945     unsigned char *p_result = NULL;
20946     double x1 = 0.0;
20947     double y1 = 0.0;
20948     double x2 = 0.0;
20949     double y2 = 0.0;
20950 
20951     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
20952     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
20953       {
20954 	  sqlite3_result_null (context);
20955 	  return;
20956       }
20957     text = (const char *) sqlite3_value_text (argv[0]);
20958     if ((strlen (text) < 5) || (strlen (text) > 7))
20959       {
20960 	  sqlite3_result_null (context);
20961 	  return;
20962       }
20963     if (strlen (text) == 5)
20964       {
20965 	  int numMatch = 0;
20966 	  unsigned int digit100 = 0;
20967 	  char letterMSD = '\0';
20968 	  char letterLSD = '\0';
20969 	  numMatch = sscanf (text, "%u%c%c", &digit100, &letterMSD, &letterLSD);
20970 	  if (numMatch != 3)
20971 	    {
20972 		sqlite3_result_null (context);
20973 		return;
20974 	    }
20975 	  x1 = ((digit100 - 1) * 0.5) - 180.0;
20976 	  y1 = garsLetterToDegreesLat (letterMSD, letterLSD);
20977 	  if ((x1 < -180.0) || (x1 > 179.5) || (y1 < -90.0) || (y1 > 89.5))
20978 	    {
20979 		sqlite3_result_null (context);
20980 		return;
20981 	    }
20982 	  x2 = x1 + 0.5;
20983 	  y2 = y1 + 0.5;
20984       }
20985     if (strlen (text) == 6)
20986       {
20987 	  unsigned int numMatch = 0;
20988 	  unsigned int digit100 = 0;
20989 	  char letterMSD = '\0';
20990 	  char letterLSD = '\0';
20991 	  unsigned int digitSegment = 0;
20992 	  numMatch =
20993 	      sscanf (text, "%u%c%c%u", &digit100, &letterMSD, &letterLSD,
20994 		      &digitSegment);
20995 	  if (numMatch != 4)
20996 	    {
20997 		sqlite3_result_null (context);
20998 		return;
20999 	    }
21000 	  if ((digitSegment < 1) || (digitSegment > 4))
21001 	    {
21002 		sqlite3_result_null (context);
21003 		return;
21004 	    }
21005 	  x1 = ((digit100 - 1) * 0.5) - 180.0;
21006 	  if ((digitSegment == 2) || (digitSegment == 4))
21007 	    {
21008 		x1 += 0.25;
21009 	    }
21010 	  y1 = garsLetterToDegreesLat (letterMSD, letterLSD);
21011 	  if ((digitSegment == 1) || (digitSegment == 2))
21012 	    {
21013 		y1 += 0.25;
21014 	    }
21015 	  if ((x1 < -180.0) || (x1 > 179.75) || (y1 < -90.0) || (y1 > 89.75))
21016 	    {
21017 		sqlite3_result_null (context);
21018 		return;
21019 	    }
21020 	  x2 = x1 + 0.25;
21021 	  y2 = y1 + 0.25;
21022       }
21023     if (strlen (text) == 7)
21024       {
21025 	  unsigned int numMatch = 0;
21026 	  unsigned int digit100 = 0;
21027 	  char letterMSD = '\0';
21028 	  char letterLSD = '\0';
21029 	  unsigned int digitAndKeypad = 0;
21030 	  unsigned int digitSegment = 0;
21031 	  unsigned int keypadNumber = 0;
21032 	  numMatch =
21033 	      sscanf (text, "%u%c%c%u", &digit100, &letterMSD, &letterLSD,
21034 		      &digitAndKeypad);
21035 	  if (numMatch != 4)
21036 	    {
21037 		sqlite3_result_null (context);
21038 		return;
21039 	    }
21040 	  digitSegment = digitAndKeypad / 10;
21041 	  keypadNumber = digitAndKeypad % 10;
21042 	  if ((digitSegment < 1) || (digitSegment > 4))
21043 	    {
21044 		sqlite3_result_null (context);
21045 		return;
21046 	    }
21047 	  if (keypadNumber < 1)
21048 	    {
21049 		sqlite3_result_null (context);
21050 		return;
21051 	    }
21052 	  x1 = ((digit100 - 1) * 0.5) - 180.0;
21053 	  if ((digitSegment == 2) || (digitSegment == 4))
21054 	    {
21055 		x1 += 0.25;
21056 	    }
21057 	  y1 = garsLetterToDegreesLat (letterMSD, letterLSD);
21058 	  if ((digitSegment == 1) || (digitSegment == 2))
21059 	    {
21060 		y1 += 0.25;
21061 	    }
21062 	  switch (keypadNumber)
21063 	    {
21064 	    case 1:
21065 		x1 += 0 * 0.25 / 3;
21066 		y1 += 2 * 0.25 / 3;
21067 		break;
21068 	    case 2:
21069 		x1 += 1 * 0.25 / 3;
21070 		y1 += 2 * 0.25 / 3;
21071 		break;
21072 	    case 3:
21073 		x1 += 2 * 0.25 / 3;
21074 		y1 += 2 * 0.25 / 3;
21075 		break;
21076 	    case 4:
21077 		x1 += 0 * 0.25 / 3;
21078 		y1 += 1 * 0.25 / 3;
21079 		break;
21080 	    case 5:
21081 		x1 += 1 * 0.25 / 3;
21082 		y1 += 1 * 0.25 / 3;
21083 		break;
21084 	    case 6:
21085 		x1 += 2 * 0.25 / 3;
21086 		y1 += 1 * 0.25 / 3;
21087 		break;
21088 	    case 7:
21089 		x1 += 0 * 0.25 / 3;
21090 		y1 += 0 * 0.25 / 3;
21091 		break;
21092 	    case 8:
21093 		x1 += 1 * 0.25 / 3;
21094 		y1 += 0 * 0.25 / 3;
21095 		break;
21096 	    case 9:
21097 		x1 += 2 * 0.25 / 3;
21098 		y1 += 0 * 0.25 / 3;
21099 		break;
21100 	    }
21101 	  if ((x1 < -180.0) || (x1 >= 180.0) || (y1 < -90.0) || (y1 >= 90.0))
21102 	    {
21103 		sqlite3_result_null (context);
21104 		return;
21105 	    }
21106 	  x2 = x1 + (0.25 / 3);
21107 	  y2 = y1 + (0.25 / 3);
21108       }
21109     gaiaBuildMbr (x1, y1, x2, y2, 4326, &p_result, &len);
21110     if (!p_result)
21111       {
21112 	  sqlite3_result_null (context);
21113 	  spatialite_e ("bad p_result\n");
21114       }
21115     else
21116 	sqlite3_result_blob (context, p_result, len, free);
21117 }
21118 
21119 static void
fnct_ToGARS(sqlite3_context * context,int argc,sqlite3_value ** argv)21120 fnct_ToGARS (sqlite3_context * context, int argc, sqlite3_value ** argv)
21121 {
21122 /* SQL function:
21123 / ToGARS(BLOB encoded POINT)
21124 /
21125 / returns the Global Area Reference System coordinate area for a given point,
21126 / or NULL if an error occurs
21127 */
21128     unsigned char *p_blob;
21129     int n_bytes;
21130     int pts = 0;
21131     int lns = 0;
21132     int pgs = 0;
21133     gaiaPointPtr point;
21134     gaiaLinestringPtr line;
21135     gaiaPolygonPtr polyg;
21136     gaiaGeomCollPtr geo = NULL;
21137     char p_result[8];
21138     int lon_band = 0;
21139     double lon_minutes = 0;
21140     int segmentNumber = 0;
21141     int lat_band = 0;
21142     double lat_minutes = 0;
21143     int gpkg_amphibious = 0;
21144     int gpkg_mode = 0;
21145     struct splite_internal_cache *cache = sqlite3_user_data (context);
21146     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21147     if (cache != NULL)
21148       {
21149 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21150 	  gpkg_mode = cache->gpkg_mode;
21151       }
21152     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21153       {
21154 	  sqlite3_result_null (context);
21155 	  return;
21156       }
21157     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21158     n_bytes = sqlite3_value_bytes (argv[0]);
21159     geo =
21160 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21161 				     gpkg_amphibious);
21162     if (!geo)
21163       {
21164 	  sqlite3_result_null (context);
21165 	  return;
21166       }
21167     gaiaNormalizeLonLat (geo);
21168     point = geo->FirstPoint;
21169     while (point != NULL)
21170       {
21171 	  pts++;
21172 	  point = point->Next;
21173       }
21174     line = geo->FirstLinestring;
21175     while (line != NULL)
21176       {
21177 	  lns++;
21178 	  line = line->Next;
21179       }
21180     polyg = geo->FirstPolygon;
21181     while (polyg != NULL)
21182       {
21183 	  pgs++;
21184 	  polyg = polyg->Next;
21185       }
21186     if (pts == 1 && lns == 0 && pgs == 0)
21187 	point = geo->FirstPoint;
21188     else
21189       {
21190 	  /* not a single Point */
21191 	  gaiaFreeGeomColl (geo);
21192 	  sqlite3_result_null (context);
21193 	  return;
21194       }
21195     /* longitude band */
21196     lon_band = 1 + (int) ((point->X + 180.0) * 2);
21197     sprintf (p_result, "%03i", lon_band);
21198     /* latitude band */
21199     lat_band = (int) ((point->Y + 90.0) * 2);
21200     p_result[3] = garsLetterCode (lat_band / 24);
21201     p_result[4] = garsLetterCode (lat_band % 24);
21202     /* quadrant */
21203     lon_minutes = fmod ((point->X + 180.0), 0.5) * 60.0;
21204     if (lon_minutes < 15.0)
21205       {
21206 	  segmentNumber = 1;
21207       }
21208     else
21209       {
21210 	  segmentNumber = 2;
21211 	  lon_minutes -= 15.0;
21212       }
21213     lat_minutes = fmod ((point->Y + 90.0), 0.5) * 60.0;
21214     if (lat_minutes < 15.0)
21215       {
21216 	  segmentNumber += 2;
21217       }
21218     else
21219       {
21220 	  /* we already have the right segment */
21221 	  lat_minutes -= 15.0;
21222       }
21223     sprintf (&(p_result[5]), "%i", segmentNumber);
21224     /* area */
21225     segmentNumber = 0;
21226     if (lon_minutes >= 10.0)
21227       {
21228 	  segmentNumber = 3;
21229       }
21230     else if (lon_minutes >= 5.0)
21231       {
21232 	  segmentNumber = 2;
21233       }
21234     else
21235       {
21236 	  segmentNumber = 1;
21237       }
21238     if (lat_minutes >= 10.0)
21239       {
21240 	  /* nothing to add */
21241       }
21242     else if (lat_minutes >= 5.0)
21243       {
21244 	  segmentNumber += 3;
21245       }
21246     else
21247       {
21248 	  segmentNumber += 6;
21249       }
21250     sprintf (&(p_result[6]), "%i", segmentNumber);
21251     sqlite3_result_text (context, p_result, 7, SQLITE_TRANSIENT);
21252     gaiaFreeGeomColl (geo);
21253 }
21254 
21255 static void
fnct_GeometryN(sqlite3_context * context,int argc,sqlite3_value ** argv)21256 fnct_GeometryN (sqlite3_context * context, int argc, sqlite3_value ** argv)
21257 {
21258 /* SQL function:
21259 / GeometryN(BLOB encoded GEOMETRYCOLLECTION geometry)
21260 /
21261 / returns the Nth geometry for current GEOMETRYCOLLECTION or MULTIxxxx geometry
21262 / or NULL if any error is encountered
21263 */
21264     unsigned char *p_blob;
21265     int n_bytes;
21266     int entity;
21267     int len;
21268     int cnt = 0;
21269     int iv;
21270     int ib;
21271     double x;
21272     double y;
21273     double z;
21274     double m;
21275     gaiaPointPtr point;
21276     gaiaLinestringPtr line;
21277     gaiaLinestringPtr line2;
21278     gaiaPolygonPtr polyg;
21279     gaiaPolygonPtr polyg2;
21280     gaiaRingPtr ring_in;
21281     gaiaRingPtr ring_out;
21282     unsigned char *p_result = NULL;
21283     gaiaGeomCollPtr geo = NULL;
21284     gaiaGeomCollPtr result = NULL;
21285     int gpkg_amphibious = 0;
21286     int gpkg_mode = 0;
21287     int tiny_point = 0;
21288     struct splite_internal_cache *cache = sqlite3_user_data (context);
21289     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21290     if (cache != NULL)
21291       {
21292 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21293 	  gpkg_mode = cache->gpkg_mode;
21294 	  tiny_point = cache->tinyPointEnabled;
21295       }
21296     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21297       {
21298 	  sqlite3_result_null (context);
21299 	  return;
21300       }
21301     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
21302       {
21303 	  sqlite3_result_null (context);
21304 	  return;
21305       }
21306     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21307     n_bytes = sqlite3_value_bytes (argv[0]);
21308     entity = sqlite3_value_int (argv[1]);
21309     geo =
21310 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21311 				     gpkg_amphibious);
21312     if (!geo)
21313 	sqlite3_result_null (context);
21314     else
21315       {
21316 	  point = geo->FirstPoint;
21317 	  while (point)
21318 	    {
21319 		/* counts how many points are there */
21320 		cnt++;
21321 		if (cnt == entity)
21322 		  {
21323 		      /* ok, required elementary geometry is this POINT */
21324 		      if (point->DimensionModel == GAIA_XY_Z)
21325 			  result = gaiaAllocGeomCollXYZ ();
21326 		      else if (point->DimensionModel == GAIA_XY_M)
21327 			  result = gaiaAllocGeomCollXYM ();
21328 		      else if (point->DimensionModel == GAIA_XY_Z_M)
21329 			  result = gaiaAllocGeomCollXYZM ();
21330 		      else
21331 			  result = gaiaAllocGeomColl ();
21332 		      result->Srid = geo->Srid;
21333 		      if (point->DimensionModel == GAIA_XY_Z)
21334 			  gaiaAddPointToGeomCollXYZ (result, point->X,
21335 						     point->Y, point->Z);
21336 		      else if (point->DimensionModel == GAIA_XY_M)
21337 			  gaiaAddPointToGeomCollXYM (result, point->X,
21338 						     point->Y, point->M);
21339 		      else if (point->DimensionModel == GAIA_XY_Z_M)
21340 			  gaiaAddPointToGeomCollXYZM (result, point->X,
21341 						      point->Y, point->Z,
21342 						      point->M);
21343 		      else
21344 			  gaiaAddPointToGeomColl (result, point->X, point->Y);
21345 		      goto skip;
21346 		  }
21347 		point = point->Next;
21348 	    }
21349 	  line = geo->FirstLinestring;
21350 	  while (line)
21351 	    {
21352 		/* counts how many linestrings are there */
21353 		cnt++;
21354 		if (cnt == entity)
21355 		  {
21356 		      /* ok, required elementary geometry is this LINESTRING */
21357 		      if (line->DimensionModel == GAIA_XY_Z)
21358 			  result = gaiaAllocGeomCollXYZ ();
21359 		      else if (line->DimensionModel == GAIA_XY_M)
21360 			  result = gaiaAllocGeomCollXYM ();
21361 		      else if (line->DimensionModel == GAIA_XY_Z_M)
21362 			  result = gaiaAllocGeomCollXYZM ();
21363 		      else
21364 			  result = gaiaAllocGeomColl ();
21365 		      result->Srid = geo->Srid;
21366 		      line2 =
21367 			  gaiaAddLinestringToGeomColl (result, line->Points);
21368 		      for (iv = 0; iv < line2->Points; iv++)
21369 			{
21370 			    if (line->DimensionModel == GAIA_XY_Z)
21371 			      {
21372 				  gaiaGetPointXYZ (line->Coords, iv, &x,
21373 						   &y, &z);
21374 				  gaiaSetPointXYZ (line2->Coords, iv, x, y, z);
21375 			      }
21376 			    else if (line->DimensionModel == GAIA_XY_M)
21377 			      {
21378 				  gaiaGetPointXYM (line->Coords, iv, &x,
21379 						   &y, &m);
21380 				  gaiaSetPointXYM (line2->Coords, iv, x, y, m);
21381 			      }
21382 			    else if (line->DimensionModel == GAIA_XY_Z_M)
21383 			      {
21384 				  gaiaGetPointXYZM (line->Coords, iv, &x,
21385 						    &y, &z, &m);
21386 				  gaiaSetPointXYZM (line2->Coords, iv, x,
21387 						    y, z, m);
21388 			      }
21389 			    else
21390 			      {
21391 				  gaiaGetPoint (line->Coords, iv, &x, &y);
21392 				  gaiaSetPoint (line2->Coords, iv, x, y);
21393 			      }
21394 			}
21395 		      goto skip;
21396 		  }
21397 		line = line->Next;
21398 	    }
21399 	  polyg = geo->FirstPolygon;
21400 	  while (polyg)
21401 	    {
21402 		/* counts how many polygons are there */
21403 		cnt++;
21404 		if (cnt == entity)
21405 		  {
21406 		      /* ok, required elementary geometry is this POLYGON */
21407 		      if (polyg->DimensionModel == GAIA_XY_Z)
21408 			  result = gaiaAllocGeomCollXYZ ();
21409 		      else if (polyg->DimensionModel == GAIA_XY_M)
21410 			  result = gaiaAllocGeomCollXYM ();
21411 		      else if (polyg->DimensionModel == GAIA_XY_Z_M)
21412 			  result = gaiaAllocGeomCollXYZM ();
21413 		      else
21414 			  result = gaiaAllocGeomColl ();
21415 		      result->Srid = geo->Srid;
21416 		      ring_in = polyg->Exterior;
21417 		      polyg2 =
21418 			  gaiaAddPolygonToGeomColl (result,
21419 						    ring_in->Points,
21420 						    polyg->NumInteriors);
21421 		      ring_out = polyg2->Exterior;
21422 		      for (iv = 0; iv < ring_out->Points; iv++)
21423 			{
21424 			    /* copying the exterior ring POINTs */
21425 			    if (ring_in->DimensionModel == GAIA_XY_Z)
21426 			      {
21427 				  gaiaGetPointXYZ (ring_in->Coords, iv,
21428 						   &x, &y, &z);
21429 				  gaiaSetPointXYZ (ring_out->Coords, iv,
21430 						   x, y, z);
21431 			      }
21432 			    else if (ring_in->DimensionModel == GAIA_XY_M)
21433 			      {
21434 				  gaiaGetPointXYM (ring_in->Coords, iv,
21435 						   &x, &y, &m);
21436 				  gaiaSetPointXYM (ring_out->Coords, iv,
21437 						   x, y, m);
21438 			      }
21439 			    else if (ring_in->DimensionModel == GAIA_XY_Z_M)
21440 			      {
21441 				  gaiaGetPointXYZM (ring_in->Coords, iv,
21442 						    &x, &y, &z, &m);
21443 				  gaiaSetPointXYZM (ring_out->Coords, iv,
21444 						    x, y, z, m);
21445 			      }
21446 			    else
21447 			      {
21448 				  gaiaGetPoint (ring_in->Coords, iv, &x, &y);
21449 				  gaiaSetPoint (ring_out->Coords, iv, x, y);
21450 			      }
21451 			}
21452 		      for (ib = 0; ib < polyg2->NumInteriors; ib++)
21453 			{
21454 			    /* processing the interior rings */
21455 			    ring_in = polyg->Interiors + ib;
21456 			    ring_out =
21457 				gaiaAddInteriorRing (polyg2, ib,
21458 						     ring_in->Points);
21459 			    for (iv = 0; iv < ring_out->Points; iv++)
21460 			      {
21461 				  if (ring_in->DimensionModel == GAIA_XY_Z)
21462 				    {
21463 					gaiaGetPointXYZ (ring_in->Coords,
21464 							 iv, &x, &y, &z);
21465 					gaiaSetPointXYZ (ring_out->Coords, iv,
21466 							 x, y, z);
21467 				    }
21468 				  else if (ring_in->DimensionModel == GAIA_XY_M)
21469 				    {
21470 					gaiaGetPointXYM (ring_in->Coords,
21471 							 iv, &x, &y, &m);
21472 					gaiaSetPointXYM (ring_out->Coords, iv,
21473 							 x, y, m);
21474 				    }
21475 				  else if (ring_in->DimensionModel ==
21476 					   GAIA_XY_Z_M)
21477 				    {
21478 					gaiaGetPointXYZM (ring_in->Coords, iv,
21479 							  &x, &y, &z, &m);
21480 					gaiaSetPointXYZM (ring_out->Coords,
21481 							  iv, x, y, z, m);
21482 				    }
21483 				  else
21484 				    {
21485 					gaiaGetPoint (ring_in->Coords,
21486 						      iv, &x, &y);
21487 					gaiaSetPoint (ring_out->Coords,
21488 						      iv, x, y);
21489 				    }
21490 			      }
21491 			}
21492 		      goto skip;
21493 		  }
21494 		polyg = polyg->Next;
21495 	    }
21496 	skip:
21497 	  if (result)
21498 	    {
21499 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
21500 					    gpkg_mode, tiny_point);
21501 		gaiaFreeGeomColl (result);
21502 		sqlite3_result_blob (context, p_result, len, free);
21503 	    }
21504 	  else
21505 	      sqlite3_result_null (context);
21506       }
21507     gaiaFreeGeomColl (geo);
21508 }
21509 
21510 static void
mbrs_eval(sqlite3_context * context,int argc,sqlite3_value ** argv,int request)21511 mbrs_eval (sqlite3_context * context, int argc, sqlite3_value ** argv,
21512 	   int request)
21513 {
21514 /* SQL function:
21515 / MBRsomething(BLOB encoded GEOMETRY-1, BLOB encoded GEOMETRY-2)
21516 /
21517 / returns:
21518 / 1 if the required spatial relationship between the two MBRs is TRUE
21519 / 0 otherwise
21520 / or -1 if any error is encountered
21521 */
21522     unsigned char *p_blob;
21523     int n_bytes;
21524     int ret;
21525     gaiaGeomCollPtr geo1 = NULL;
21526     gaiaGeomCollPtr geo2 = NULL;
21527     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21528     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21529       {
21530 	  sqlite3_result_int (context, -1);
21531 	  return;
21532       }
21533     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
21534       {
21535 	  sqlite3_result_int (context, -1);
21536 	  return;
21537       }
21538     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21539     n_bytes = sqlite3_value_bytes (argv[0]);
21540     geo1 = gaiaFromSpatiaLiteBlobMbr (p_blob, n_bytes);
21541     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
21542     n_bytes = sqlite3_value_bytes (argv[1]);
21543     geo2 = gaiaFromSpatiaLiteBlobMbr (p_blob, n_bytes);
21544     if (!geo1 || !geo2)
21545 	sqlite3_result_int (context, -1);
21546     else
21547       {
21548 	  ret = 0;
21549 	  gaiaMbrGeometry (geo1);
21550 	  gaiaMbrGeometry (geo2);
21551 	  switch (request)
21552 	    {
21553 	    case GAIA_MBR_CONTAINS:
21554 		ret = gaiaMbrsContains (geo1, geo2);
21555 		break;
21556 	    case GAIA_MBR_DISJOINT:
21557 		ret = gaiaMbrsDisjoint (geo1, geo2);
21558 		break;
21559 	    case GAIA_MBR_EQUAL:
21560 		ret = gaiaMbrsEqual (geo1, geo2);
21561 		break;
21562 	    case GAIA_MBR_INTERSECTS:
21563 		ret = gaiaMbrsIntersects (geo1, geo2);
21564 		break;
21565 	    case GAIA_MBR_OVERLAPS:
21566 		ret = gaiaMbrsOverlaps (geo1, geo2);
21567 		break;
21568 	    case GAIA_MBR_TOUCHES:
21569 		ret = gaiaMbrsTouches (geo1, geo2);
21570 		break;
21571 	    case GAIA_MBR_WITHIN:
21572 		ret = gaiaMbrsWithin (geo1, geo2);
21573 		break;
21574 	    }
21575 	  if (ret < 0)
21576 	      sqlite3_result_int (context, -1);
21577 	  else
21578 	      sqlite3_result_int (context, ret);
21579       }
21580     gaiaFreeGeomColl (geo1);
21581     gaiaFreeGeomColl (geo2);
21582 }
21583 
21584 /*
21585 / the following functions simply readdress the mbr_eval()
21586 / setting the appropriate request mode
21587 */
21588 
21589 static void
fnct_MbrContains(sqlite3_context * context,int argc,sqlite3_value ** argv)21590 fnct_MbrContains (sqlite3_context * context, int argc, sqlite3_value ** argv)
21591 {
21592     mbrs_eval (context, argc, argv, GAIA_MBR_CONTAINS);
21593 }
21594 
21595 static void
fnct_MbrDisjoint(sqlite3_context * context,int argc,sqlite3_value ** argv)21596 fnct_MbrDisjoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
21597 {
21598     mbrs_eval (context, argc, argv, GAIA_MBR_DISJOINT);
21599 }
21600 
21601 static void
fnct_MbrEqual(sqlite3_context * context,int argc,sqlite3_value ** argv)21602 fnct_MbrEqual (sqlite3_context * context, int argc, sqlite3_value ** argv)
21603 {
21604     mbrs_eval (context, argc, argv, GAIA_MBR_EQUAL);
21605 }
21606 
21607 static void
fnct_MbrIntersects(sqlite3_context * context,int argc,sqlite3_value ** argv)21608 fnct_MbrIntersects (sqlite3_context * context, int argc, sqlite3_value ** argv)
21609 {
21610     mbrs_eval (context, argc, argv, GAIA_MBR_INTERSECTS);
21611 }
21612 
21613 static void
fnct_EnvIntersects(sqlite3_context * context,int argc,sqlite3_value ** argv)21614 fnct_EnvIntersects (sqlite3_context * context, int argc, sqlite3_value ** argv)
21615 {
21616 /* SQL function:
21617 / ST_EnvIntersects(Geometry geom, double X1, double Y1, double X2, double Y2)
21618 / ST_EnvelopesIntersects(Geometry geom, double X1, double Y1, double X2, double Y2)
21619 /
21620 / the second MBR is defined by two points (identifying a rectangle's diagonal)
21621 /
21622 / returns:
21623 / 1 if the required spatial intersection is TRUE
21624 / 0 otherwise
21625 / or -1 if any error is encountered
21626 */
21627     double x1;
21628     double y1;
21629     double x2;
21630     double y2;
21631     int int_value;
21632     unsigned char *p_blob;
21633     int n_bytes;
21634     int ret = 0;
21635     gaiaGeomCollPtr geo1 = NULL;
21636     gaiaGeomCollPtr geo2 = NULL;
21637     gaiaLinestringPtr ln;
21638     int gpkg_amphibious = 0;
21639     int gpkg_mode = 0;
21640     struct splite_internal_cache *cache = sqlite3_user_data (context);
21641     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21642     if (cache != NULL)
21643       {
21644 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21645 	  gpkg_mode = cache->gpkg_mode;
21646       }
21647     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21648       {
21649 	  sqlite3_result_int (context, -1);
21650 	  return;
21651       }
21652     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
21653 	x1 = sqlite3_value_double (argv[1]);
21654     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
21655       {
21656 	  int_value = sqlite3_value_int (argv[1]);
21657 	  x1 = int_value;
21658       }
21659     else
21660       {
21661 	  sqlite3_result_int (context, -1);
21662 	  return;
21663       }
21664     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
21665 	y1 = sqlite3_value_double (argv[2]);
21666     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
21667       {
21668 	  int_value = sqlite3_value_int (argv[2]);
21669 	  y1 = int_value;
21670       }
21671     else
21672       {
21673 	  sqlite3_result_int (context, -1);
21674 	  return;
21675       }
21676     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
21677 	x2 = sqlite3_value_double (argv[3]);
21678     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
21679       {
21680 	  int_value = sqlite3_value_int (argv[3]);
21681 	  x2 = int_value;
21682       }
21683     else
21684       {
21685 	  sqlite3_result_int (context, -1);
21686 	  return;
21687       }
21688     if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
21689 	y2 = sqlite3_value_double (argv[4]);
21690     else if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
21691       {
21692 	  int_value = sqlite3_value_int (argv[4]);
21693 	  y2 = int_value;
21694       }
21695     else
21696       {
21697 	  sqlite3_result_int (context, -1);
21698 	  return;
21699       }
21700     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21701     n_bytes = sqlite3_value_bytes (argv[0]);
21702     geo1 =
21703 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21704 				     gpkg_amphibious);
21705     if (!geo1)
21706 	sqlite3_result_int (context, -1);
21707     else
21708       {
21709 	  gaiaMbrGeometry (geo1);
21710 	  geo2 = gaiaAllocGeomColl ();
21711 	  ln = gaiaAddLinestringToGeomColl (geo2, 2);
21712 	  gaiaSetPoint (ln->Coords, 0, x1, y1);
21713 	  gaiaSetPoint (ln->Coords, 1, x2, y2);
21714 	  gaiaMbrGeometry (geo2);
21715 	  ret = gaiaMbrsIntersects (geo1, geo2);
21716 	  sqlite3_result_int (context, ret);
21717       }
21718     gaiaFreeGeomColl (geo1);
21719     gaiaFreeGeomColl (geo2);
21720 }
21721 
21722 
21723 static void
fnct_MbrOverlaps(sqlite3_context * context,int argc,sqlite3_value ** argv)21724 fnct_MbrOverlaps (sqlite3_context * context, int argc, sqlite3_value ** argv)
21725 {
21726     mbrs_eval (context, argc, argv, GAIA_MBR_OVERLAPS);
21727 }
21728 
21729 static void
fnct_MbrTouches(sqlite3_context * context,int argc,sqlite3_value ** argv)21730 fnct_MbrTouches (sqlite3_context * context, int argc, sqlite3_value ** argv)
21731 {
21732     mbrs_eval (context, argc, argv, GAIA_MBR_TOUCHES);
21733 }
21734 
21735 static void
fnct_MbrWithin(sqlite3_context * context,int argc,sqlite3_value ** argv)21736 fnct_MbrWithin (sqlite3_context * context, int argc, sqlite3_value ** argv)
21737 {
21738     mbrs_eval (context, argc, argv, GAIA_MBR_WITHIN);
21739 }
21740 
21741 static void
fnct_ShiftCoords(sqlite3_context * context,int argc,sqlite3_value ** argv)21742 fnct_ShiftCoords (sqlite3_context * context, int argc, sqlite3_value ** argv)
21743 {
21744 /* SQL function:
21745 / ShiftCoords(BLOBencoded geometry, shiftX, shiftY)
21746 /
21747 / returns a new geometry that is the original one received, but with shifted coordinates
21748 / or NULL if any error is encountered
21749 */
21750     unsigned char *p_blob;
21751     int n_bytes;
21752     int len;
21753     unsigned char *p_result = NULL;
21754     gaiaGeomCollPtr geo = NULL;
21755     double shift_x;
21756     double shift_y;
21757     int int_value;
21758     int gpkg_amphibious = 0;
21759     int gpkg_mode = 0;
21760     int tiny_point = 0;
21761     struct splite_internal_cache *cache = sqlite3_user_data (context);
21762     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21763     if (cache != NULL)
21764       {
21765 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21766 	  gpkg_mode = cache->gpkg_mode;
21767 	  tiny_point = cache->tinyPointEnabled;
21768       }
21769     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21770       {
21771 	  sqlite3_result_null (context);
21772 	  return;
21773       }
21774     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
21775 	shift_x = sqlite3_value_double (argv[1]);
21776     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
21777       {
21778 	  int_value = sqlite3_value_int (argv[1]);
21779 	  shift_x = int_value;
21780       }
21781     else
21782       {
21783 	  sqlite3_result_null (context);
21784 	  return;
21785       }
21786     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
21787 	shift_y = sqlite3_value_double (argv[2]);
21788     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
21789       {
21790 	  int_value = sqlite3_value_int (argv[2]);
21791 	  shift_y = int_value;
21792       }
21793     else
21794       {
21795 	  sqlite3_result_null (context);
21796 	  return;
21797       }
21798     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21799     n_bytes = sqlite3_value_bytes (argv[0]);
21800     geo =
21801 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21802 				     gpkg_amphibious);
21803     if (!geo)
21804 	sqlite3_result_null (context);
21805     else
21806       {
21807 	  gaiaShiftCoords (geo, shift_x, shift_y);
21808 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
21809 				      tiny_point);
21810 	  if (!p_result)
21811 	      sqlite3_result_null (context);
21812 	  else
21813 	      sqlite3_result_blob (context, p_result, len, free);
21814       }
21815     gaiaFreeGeomColl (geo);
21816 }
21817 
21818 static void
fnct_Translate(sqlite3_context * context,int argc,sqlite3_value ** argv)21819 fnct_Translate (sqlite3_context * context, int argc, sqlite3_value ** argv)
21820 {
21821 /* SQL function:
21822 / Translate(BLOBencoded geometry, shiftX, shiftY, shiftZ)
21823 /
21824 / returns a new geometry that is the original one received, but with shifted coordinates
21825 / or NULL if any error is encountered
21826 */
21827     unsigned char *p_blob;
21828     int n_bytes;
21829     int len;
21830     unsigned char *p_result = NULL;
21831     gaiaGeomCollPtr geo = NULL;
21832     double shift_x;
21833     double shift_y;
21834     double shift_z;
21835     int int_value;
21836     int gpkg_amphibious = 0;
21837     int gpkg_mode = 0;
21838     int tiny_point = 0;
21839     struct splite_internal_cache *cache = sqlite3_user_data (context);
21840     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21841     if (cache != NULL)
21842       {
21843 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21844 	  gpkg_mode = cache->gpkg_mode;
21845 	  tiny_point = cache->tinyPointEnabled;
21846       }
21847     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21848       {
21849 	  sqlite3_result_null (context);
21850 	  return;
21851       }
21852     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
21853 	shift_x = sqlite3_value_double (argv[1]);
21854     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
21855       {
21856 	  int_value = sqlite3_value_int (argv[1]);
21857 	  shift_x = int_value;
21858       }
21859     else
21860       {
21861 	  sqlite3_result_null (context);
21862 	  return;
21863       }
21864     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
21865 	shift_y = sqlite3_value_double (argv[2]);
21866     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
21867       {
21868 	  int_value = sqlite3_value_int (argv[2]);
21869 	  shift_y = int_value;
21870       }
21871     else
21872       {
21873 	  sqlite3_result_null (context);
21874 	  return;
21875       }
21876     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
21877 	shift_z = sqlite3_value_double (argv[3]);
21878     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
21879       {
21880 	  int_value = sqlite3_value_int (argv[3]);
21881 	  shift_z = int_value;
21882       }
21883     else
21884       {
21885 	  sqlite3_result_null (context);
21886 	  return;
21887       }
21888     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21889     n_bytes = sqlite3_value_bytes (argv[0]);
21890     geo =
21891 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21892 				     gpkg_amphibious);
21893     if (!geo)
21894 	sqlite3_result_null (context);
21895     else
21896       {
21897 	  gaiaShiftCoords3D (geo, shift_x, shift_y, shift_z);
21898 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
21899 				      tiny_point);
21900 	  if (!p_result)
21901 	      sqlite3_result_null (context);
21902 	  else
21903 	      sqlite3_result_blob (context, p_result, len, free);
21904       }
21905     gaiaFreeGeomColl (geo);
21906 }
21907 
21908 
21909 static void
fnct_ShiftLongitude(sqlite3_context * context,int argc,sqlite3_value ** argv)21910 fnct_ShiftLongitude (sqlite3_context * context, int argc, sqlite3_value ** argv)
21911 {
21912 /* SQL function:
21913 / ShiftLongitude(BLOBencoded geometry)
21914 /
21915 / returns a new geometry that is the original one received, but with negative
21916 / longitudes shifted by 360
21917 / or NULL if any error is encountered
21918 */
21919     unsigned char *p_blob;
21920     int n_bytes;
21921     int len;
21922     unsigned char *p_result = NULL;
21923     gaiaGeomCollPtr geo = NULL;
21924     int gpkg_amphibious = 0;
21925     int gpkg_mode = 0;
21926     int tiny_point = 0;
21927     struct splite_internal_cache *cache = sqlite3_user_data (context);
21928     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21929     if (cache != NULL)
21930       {
21931 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21932 	  gpkg_mode = cache->gpkg_mode;
21933 	  tiny_point = cache->tinyPointEnabled;
21934       }
21935     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21936       {
21937 	  sqlite3_result_null (context);
21938 	  return;
21939       }
21940     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21941     n_bytes = sqlite3_value_bytes (argv[0]);
21942     geo =
21943 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21944 				     gpkg_amphibious);
21945     if (!geo)
21946 	sqlite3_result_null (context);
21947     else
21948       {
21949 	  gaiaShiftLongitude (geo);
21950 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
21951 				      tiny_point);
21952 	  if (!p_result)
21953 	      sqlite3_result_null (context);
21954 	  else
21955 	      sqlite3_result_blob (context, p_result, len, free);
21956       }
21957     gaiaFreeGeomColl (geo);
21958 }
21959 
21960 static void
fnct_NormalizeLonLat(sqlite3_context * context,int argc,sqlite3_value ** argv)21961 fnct_NormalizeLonLat (sqlite3_context * context, int argc,
21962 		      sqlite3_value ** argv)
21963 {
21964 /* SQL function:
21965 / NormalizeLonLat (BLOBencoded geometry)
21966 /
21967 / returns a new geometry that is the original one received, but with longitude
21968 / and latitude values shifted into the range [-180 - 180, -90 - 90].
21969 / NULL is returned if any error is encountered
21970 */
21971     unsigned char *p_blob;
21972     int n_bytes;
21973     int len;
21974     unsigned char *p_result = NULL;
21975     gaiaGeomCollPtr geo = NULL;
21976     int gpkg_amphibious = 0;
21977     int gpkg_mode = 0;
21978     int tiny_point = 0;
21979     struct splite_internal_cache *cache = sqlite3_user_data (context);
21980     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
21981     if (cache != NULL)
21982       {
21983 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
21984 	  gpkg_mode = cache->gpkg_mode;
21985 	  tiny_point = cache->tinyPointEnabled;
21986       }
21987     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
21988       {
21989 	  sqlite3_result_null (context);
21990 	  return;
21991       }
21992     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
21993     n_bytes = sqlite3_value_bytes (argv[0]);
21994     geo =
21995 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
21996 				     gpkg_amphibious);
21997     if (!geo)
21998 	sqlite3_result_null (context);
21999     else
22000       {
22001 	  gaiaNormalizeLonLat (geo);
22002 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
22003 				      tiny_point);
22004 	  if (!p_result)
22005 	      sqlite3_result_null (context);
22006 	  else
22007 	      sqlite3_result_blob (context, p_result, len, free);
22008       }
22009     gaiaFreeGeomColl (geo);
22010 }
22011 
22012 static void
fnct_ScaleCoords(sqlite3_context * context,int argc,sqlite3_value ** argv)22013 fnct_ScaleCoords (sqlite3_context * context, int argc, sqlite3_value ** argv)
22014 {
22015 /* SQL function:
22016 / ScaleCoords(BLOBencoded geometry, scale_factor_x [, scale_factor_y])
22017 /
22018 / returns a new geometry that is the original one received, but with scaled coordinates
22019 / or NULL if any error is encountered
22020 */
22021     unsigned char *p_blob;
22022     int n_bytes;
22023     int len;
22024     unsigned char *p_result = NULL;
22025     gaiaGeomCollPtr geo = NULL;
22026     double scale_x;
22027     double scale_y;
22028     int int_value;
22029     int gpkg_amphibious = 0;
22030     int gpkg_mode = 0;
22031     int tiny_point = 0;
22032     struct splite_internal_cache *cache = sqlite3_user_data (context);
22033     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22034     if (cache != NULL)
22035       {
22036 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22037 	  gpkg_mode = cache->gpkg_mode;
22038 	  tiny_point = cache->tinyPointEnabled;
22039       }
22040     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22041       {
22042 	  sqlite3_result_null (context);
22043 	  return;
22044       }
22045     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
22046 	scale_x = sqlite3_value_double (argv[1]);
22047     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
22048       {
22049 	  int_value = sqlite3_value_int (argv[1]);
22050 	  scale_x = int_value;
22051       }
22052     else
22053       {
22054 	  sqlite3_result_null (context);
22055 	  return;
22056       }
22057     if (argc == 2)
22058 	scale_y = scale_x;	/* this one is an isotropic scaling request */
22059     else
22060       {
22061 	  /* an anisotropic scaling is requested */
22062 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
22063 	      scale_y = sqlite3_value_double (argv[2]);
22064 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
22065 	    {
22066 		int_value = sqlite3_value_int (argv[2]);
22067 		scale_y = int_value;
22068 	    }
22069 	  else
22070 	    {
22071 		sqlite3_result_null (context);
22072 		return;
22073 	    }
22074       }
22075     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22076     n_bytes = sqlite3_value_bytes (argv[0]);
22077     geo =
22078 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22079 				     gpkg_amphibious);
22080     if (!geo)
22081 	sqlite3_result_null (context);
22082     else
22083       {
22084 	  gaiaScaleCoords (geo, scale_x, scale_y);
22085 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
22086 				      tiny_point);
22087 	  if (!p_result)
22088 	      sqlite3_result_null (context);
22089 	  else
22090 	      sqlite3_result_blob (context, p_result, len, free);
22091       }
22092     gaiaFreeGeomColl (geo);
22093 }
22094 
22095 static void
fnct_RotateCoords(sqlite3_context * context,int argc,sqlite3_value ** argv)22096 fnct_RotateCoords (sqlite3_context * context, int argc, sqlite3_value ** argv)
22097 {
22098 /* SQL function:
22099 / RotateCoords(BLOBencoded geometry, angle)
22100 /
22101 / returns a new geometry that is the original one received, but with rotated coordinates
22102 / or NULL if any error is encountered
22103 */
22104     unsigned char *p_blob;
22105     int n_bytes;
22106     int len;
22107     unsigned char *p_result = NULL;
22108     gaiaGeomCollPtr geo = NULL;
22109     double angle;
22110     int int_value;
22111     int gpkg_amphibious = 0;
22112     int gpkg_mode = 0;
22113     int tiny_point = 0;
22114     struct splite_internal_cache *cache = sqlite3_user_data (context);
22115     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22116     if (cache != NULL)
22117       {
22118 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22119 	  gpkg_mode = cache->gpkg_mode;
22120 	  tiny_point = cache->tinyPointEnabled;
22121       }
22122     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22123       {
22124 	  sqlite3_result_null (context);
22125 	  return;
22126       }
22127     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
22128 	angle = sqlite3_value_double (argv[1]);
22129     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
22130       {
22131 	  int_value = sqlite3_value_int (argv[1]);
22132 	  angle = int_value;
22133       }
22134     else
22135       {
22136 	  sqlite3_result_null (context);
22137 	  return;
22138       }
22139     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22140     n_bytes = sqlite3_value_bytes (argv[0]);
22141     geo =
22142 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22143 				     gpkg_amphibious);
22144     if (!geo)
22145 	sqlite3_result_null (context);
22146     else
22147       {
22148 	  gaiaRotateCoords (geo, angle);
22149 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
22150 				      tiny_point);
22151 	  if (!p_result)
22152 	      sqlite3_result_null (context);
22153 	  else
22154 	      sqlite3_result_blob (context, p_result, len, free);
22155       }
22156     gaiaFreeGeomColl (geo);
22157 }
22158 
22159 static void
fnct_ReflectCoords(sqlite3_context * context,int argc,sqlite3_value ** argv)22160 fnct_ReflectCoords (sqlite3_context * context, int argc, sqlite3_value ** argv)
22161 {
22162 /* SQL function:
22163 / ReflectCoords(BLOBencoded geometry, x_axis,  y_axis)
22164 /
22165 / returns a new geometry that is the original one received, but with mirrored coordinates
22166 / or NULL if any error is encountered
22167 */
22168     unsigned char *p_blob;
22169     int n_bytes;
22170     int len;
22171     unsigned char *p_result = NULL;
22172     gaiaGeomCollPtr geo = NULL;
22173     int x_axis;
22174     int y_axis;
22175     int gpkg_amphibious = 0;
22176     int gpkg_mode = 0;
22177     int tiny_point = 0;
22178     struct splite_internal_cache *cache = sqlite3_user_data (context);
22179     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22180     if (cache != NULL)
22181       {
22182 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22183 	  gpkg_mode = cache->gpkg_mode;
22184 	  tiny_point = cache->tinyPointEnabled;
22185       }
22186     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22187       {
22188 	  sqlite3_result_null (context);
22189 	  return;
22190       }
22191     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
22192 	x_axis = sqlite3_value_int (argv[1]);
22193     else
22194       {
22195 	  sqlite3_result_null (context);
22196 	  return;
22197       }
22198     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
22199 	y_axis = sqlite3_value_int (argv[2]);
22200     else
22201       {
22202 	  sqlite3_result_null (context);
22203 	  return;
22204       }
22205     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22206     n_bytes = sqlite3_value_bytes (argv[0]);
22207     geo =
22208 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22209 				     gpkg_amphibious);
22210     if (!geo)
22211 	sqlite3_result_null (context);
22212     else
22213       {
22214 	  gaiaReflectCoords (geo, x_axis, y_axis);
22215 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
22216 				      tiny_point);
22217 	  if (!p_result)
22218 	      sqlite3_result_null (context);
22219 	  else
22220 	      sqlite3_result_blob (context, p_result, len, free);
22221       }
22222     gaiaFreeGeomColl (geo);
22223 }
22224 
22225 static void
fnct_SwapCoords(sqlite3_context * context,int argc,sqlite3_value ** argv)22226 fnct_SwapCoords (sqlite3_context * context, int argc, sqlite3_value ** argv)
22227 {
22228 /* SQL function:
22229 / SwapCoords(BLOBencoded geometry)
22230 /
22231 / returns a new geometry that is the original one received, but with swapped x- and y-coordinate
22232 / or NULL if any error is encountered
22233 */
22234     unsigned char *p_blob;
22235     int n_bytes;
22236     int len;
22237     unsigned char *p_result = NULL;
22238     gaiaGeomCollPtr geo = NULL;
22239     int gpkg_amphibious = 0;
22240     int gpkg_mode = 0;
22241     int tiny_point = 0;
22242     struct splite_internal_cache *cache = sqlite3_user_data (context);
22243     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22244     if (cache != NULL)
22245       {
22246 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22247 	  gpkg_mode = cache->gpkg_mode;
22248 	  tiny_point = cache->tinyPointEnabled;
22249       }
22250     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22251       {
22252 	  sqlite3_result_null (context);
22253 	  return;
22254       }
22255     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22256     n_bytes = sqlite3_value_bytes (argv[0]);
22257     geo =
22258 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22259 				     gpkg_amphibious);
22260     if (!geo)
22261 	sqlite3_result_null (context);
22262     else
22263       {
22264 	  gaiaSwapCoords (geo);
22265 	  gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode,
22266 				      tiny_point);
22267 	  if (!p_result)
22268 	      sqlite3_result_null (context);
22269 	  else
22270 	      sqlite3_result_blob (context, p_result, len, free);
22271       }
22272     gaiaFreeGeomColl (geo);
22273 }
22274 
22275 SPATIALITE_PRIVATE int
getEllipsoidParams(void * p_sqlite,int srid,double * a,double * b,double * rf)22276 getEllipsoidParams (void *p_sqlite, int srid, double *a, double *b, double *rf)
22277 {
22278 /*
22279 / retrieves the PROJ +ellps=xx [+a=xx +b=xx] params
22280 /from SPATIAL_SYS_REF table, if possible
22281 */
22282     sqlite3 *sqlite = (sqlite3 *) p_sqlite;
22283     char *proj4text;
22284     char *p_proj;
22285     char *p_ellps;
22286     char *p_datum;
22287     char *p_a;
22288     char *p_b;
22289     char *p_end;
22290 
22291     if (srid == 0)
22292       {
22293 	  /*
22294 	     / SRID=0 is formally defined as "Undefined Geographic"
22295 	     / so will default to SRID=4326 (WGS84 Long/Lat)
22296 	   */
22297 	  srid = 4326;
22298       }
22299     getProjParams (sqlite, srid, &proj4text);
22300     if (proj4text == NULL)
22301 	return 0;
22302 /* parsing the proj4text geodesic string */
22303     p_proj = strstr (proj4text, "+proj=");
22304     p_datum = strstr (proj4text, "+datum=");
22305     p_ellps = strstr (proj4text, "+ellps=");
22306     p_a = strstr (proj4text, "+a=");
22307     p_b = strstr (proj4text, "+b=");
22308 /* checking if +proj=longlat is true */
22309     if (!p_proj)
22310 	goto invalid;
22311     p_end = strchr (p_proj, ' ');
22312     if (p_end)
22313 	*p_end = '\0';
22314     if (strcmp (p_proj + 6, "longlat") != 0)
22315 	goto invalid;
22316     if (p_ellps)
22317       {
22318 	  /* trying to retrieve the ellipsoid params by name */
22319 	  p_end = strchr (p_ellps, ' ');
22320 	  if (p_end)
22321 	      *p_end = '\0';
22322 	  if (gaiaEllipseParams (p_ellps + 7, a, b, rf))
22323 	      goto valid;
22324       }
22325     else if (p_datum)
22326       {
22327 	  /*
22328 	     / starting since GDAL 1.9.0 the WGS84 [4326] PROJ.4 def doesn't
22329 	     / declares any longer the "+ellps=" param
22330 	     / in this case we'll attempt to recover using "+datum=".
22331 	   */
22332 	  p_end = strchr (p_datum, ' ');
22333 	  if (p_end)
22334 	      *p_end = '\0';
22335 	  if (gaiaEllipseParams (p_datum + 7, a, b, rf))
22336 	      goto valid;
22337       }
22338     if (p_a && p_b)
22339       {
22340 	  /* trying to retrieve the +a=xx and +b=xx args */
22341 	  p_end = strchr (p_a, ' ');
22342 	  if (p_end)
22343 	      *p_end = '\0';
22344 	  p_end = strchr (p_b, ' ');
22345 	  if (p_end)
22346 	      *p_end = '\0';
22347 	  *a = atof (p_a + 3);
22348 	  *b = atof (p_b + 3);
22349 	  *rf = 1.0 / ((*a - *b) / *a);
22350 	  goto valid;
22351       }
22352 
22353   valid:
22354     free (proj4text);
22355     return 1;
22356 
22357   invalid:
22358     free (proj4text);
22359     return 0;
22360 }
22361 
22362 static void
fnct_FromEWKB(sqlite3_context * context,int argc,sqlite3_value ** argv)22363 fnct_FromEWKB (sqlite3_context * context, int argc, sqlite3_value ** argv)
22364 {
22365 /* SQL function:
22366 / GeomFromEWKB(EWKB encoded geometry)
22367 /
22368 / returns the current geometry by parsing Geos/PostGis EWKB encoded string
22369 / or NULL if any error is encountered
22370 */
22371     int len;
22372     unsigned char *p_result = NULL;
22373     const unsigned char *text;
22374     gaiaGeomCollPtr geo = NULL;
22375     int gpkg_mode = 0;
22376     int tiny_point = 0;
22377     struct splite_internal_cache *cache = sqlite3_user_data (context);
22378     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22379     if (cache != NULL)
22380       {
22381 	  gpkg_mode = cache->gpkg_mode;
22382 	  tiny_point = cache->tinyPointEnabled;
22383       }
22384     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
22385       {
22386 	  sqlite3_result_null (context);
22387 	  return;
22388       }
22389     text = sqlite3_value_text (argv[0]);
22390     geo = gaiaFromEWKB (text);
22391     if (geo == NULL)
22392       {
22393 	  sqlite3_result_null (context);
22394 	  return;
22395       }
22396     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
22397     gaiaFreeGeomColl (geo);
22398     sqlite3_result_blob (context, p_result, len, free);
22399 }
22400 
22401 static void
fnct_ToEWKB(sqlite3_context * context,int argc,sqlite3_value ** argv)22402 fnct_ToEWKB (sqlite3_context * context, int argc, sqlite3_value ** argv)
22403 {
22404 /* SQL function:
22405 / AsEWKB(BLOB encoded geometry)
22406 /
22407 / returns a text string corresponding to Geos/PostGIS EWKB notation
22408 / or NULL if any error is encountered
22409 */
22410     unsigned char *p_blob;
22411     int n_bytes;
22412     int len;
22413     gaiaOutBuffer out_buf;
22414     gaiaGeomCollPtr geo = NULL;
22415     int gpkg_amphibious = 0;
22416     int gpkg_mode = 0;
22417     struct splite_internal_cache *cache = sqlite3_user_data (context);
22418     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22419     if (cache != NULL)
22420       {
22421 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22422 	  gpkg_mode = cache->gpkg_mode;
22423       }
22424     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22425       {
22426 	  sqlite3_result_null (context);
22427 	  return;
22428       }
22429     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22430     n_bytes = sqlite3_value_bytes (argv[0]);
22431     geo =
22432 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22433 				     gpkg_amphibious);
22434     if (!geo)
22435       {
22436 	  sqlite3_result_null (context);
22437 	  return;
22438       }
22439     else
22440       {
22441 	  gaiaOutBufferInitialize (&out_buf);
22442 	  gaiaToEWKB (&out_buf, geo);
22443 	  if (out_buf.Error || out_buf.Buffer == NULL)
22444 	      sqlite3_result_null (context);
22445 	  else
22446 	    {
22447 		len = out_buf.WriteOffset;
22448 		sqlite3_result_text (context, out_buf.Buffer, len, free);
22449 		out_buf.Buffer = NULL;
22450 	    }
22451       }
22452     gaiaFreeGeomColl (geo);
22453     gaiaOutBufferReset (&out_buf);
22454 }
22455 
22456 static void
fnct_ToEWKT(sqlite3_context * context,int argc,sqlite3_value ** argv)22457 fnct_ToEWKT (sqlite3_context * context, int argc, sqlite3_value ** argv)
22458 {
22459 /* SQL function:
22460 / AsEWKT(BLOB encoded geometry)
22461 /
22462 / returns the corresponding PostGIS EWKT encoded value
22463 / or NULL if any error is encountered
22464 */
22465     unsigned char *p_blob;
22466     int n_bytes;
22467     int len;
22468     gaiaOutBuffer out_buf;
22469     gaiaGeomCollPtr geo = NULL;
22470     int gpkg_amphibious = 0;
22471     int gpkg_mode = 0;
22472     struct splite_internal_cache *cache = sqlite3_user_data (context);
22473     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22474     if (cache != NULL)
22475       {
22476 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22477 	  gpkg_mode = cache->gpkg_mode;
22478       }
22479     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22480       {
22481 	  sqlite3_result_null (context);
22482 	  return;
22483       }
22484     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22485     n_bytes = sqlite3_value_bytes (argv[0]);
22486     gaiaOutBufferInitialize (&out_buf);
22487     geo =
22488 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22489 				     gpkg_amphibious);
22490     if (!geo)
22491 	sqlite3_result_null (context);
22492     else
22493       {
22494 	  gaiaToEWKT (&out_buf, geo);
22495 	  if (out_buf.Error || out_buf.Buffer == NULL)
22496 	      sqlite3_result_null (context);
22497 	  else
22498 	    {
22499 		len = out_buf.WriteOffset;
22500 		sqlite3_result_text (context, out_buf.Buffer, len, free);
22501 		out_buf.Buffer = NULL;
22502 	    }
22503       }
22504     gaiaFreeGeomColl (geo);
22505     gaiaOutBufferReset (&out_buf);
22506 }
22507 
22508 static void
fnct_FromEWKT(sqlite3_context * context,int argc,sqlite3_value ** argv)22509 fnct_FromEWKT (sqlite3_context * context, int argc, sqlite3_value ** argv)
22510 {
22511 /* SQL function:
22512 / GeomFromEWKT(EWKT encoded geometry)
22513 /
22514 / returns the current geometry by parsing EWKT  (PostGIS) encoded string
22515 / or NULL if any error is encountered
22516 */
22517     int len;
22518     unsigned char *p_result = NULL;
22519     const unsigned char *text;
22520     gaiaGeomCollPtr geo = NULL;
22521     int gpkg_mode = 0;
22522     int tiny_point = 0;
22523     struct splite_internal_cache *cache = sqlite3_user_data (context);
22524     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22525     if (cache != NULL)
22526       {
22527 	  gpkg_mode = cache->gpkg_mode;
22528 	  tiny_point = cache->tinyPointEnabled;
22529       }
22530     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
22531       {
22532 	  sqlite3_result_null (context);
22533 	  return;
22534       }
22535     text = sqlite3_value_text (argv[0]);
22536     geo = gaiaParseEWKT (text);
22537     if (geo == NULL)
22538       {
22539 	  sqlite3_result_null (context);
22540 	  return;
22541       }
22542     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
22543     gaiaFreeGeomColl (geo);
22544     sqlite3_result_blob (context, p_result, len, free);
22545 }
22546 
22547 static void
fnct_FromGeoJSON(sqlite3_context * context,int argc,sqlite3_value ** argv)22548 fnct_FromGeoJSON (sqlite3_context * context, int argc, sqlite3_value ** argv)
22549 {
22550 /* SQL function:
22551 / GeomFromGeoJSON(GeoJSON encoded geometry)
22552 /
22553 / returns the current geometry by parsing GeoJSON encoded string
22554 / or NULL if any error is encountered
22555 */
22556     int len;
22557     unsigned char *p_result = NULL;
22558     const unsigned char *text;
22559     gaiaGeomCollPtr geo = NULL;
22560     int gpkg_mode = 0;
22561     int tiny_point = 0;
22562     struct splite_internal_cache *cache = sqlite3_user_data (context);
22563     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22564     if (cache != NULL)
22565       {
22566 	  gpkg_mode = cache->gpkg_mode;
22567 	  tiny_point = cache->tinyPointEnabled;
22568       }
22569     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
22570       {
22571 	  sqlite3_result_null (context);
22572 	  return;
22573       }
22574     text = sqlite3_value_text (argv[0]);
22575     geo = gaiaParseGeoJSON (text);
22576     if (geo == NULL)
22577       {
22578 	  sqlite3_result_null (context);
22579 	  return;
22580       }
22581     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
22582     gaiaFreeGeomColl (geo);
22583     sqlite3_result_blob (context, p_result, len, free);
22584 }
22585 
22586 static void
fnct_FromKml(sqlite3_context * context,int argc,sqlite3_value ** argv)22587 fnct_FromKml (sqlite3_context * context, int argc, sqlite3_value ** argv)
22588 {
22589 /* SQL function:
22590 / GeomFromKml(KML encoded geometry)
22591 /
22592 / returns the current geometry by parsing KML encoded string
22593 / or NULL if any error is encountered
22594 */
22595     int len;
22596     unsigned char *p_result = NULL;
22597     const unsigned char *text;
22598     gaiaGeomCollPtr geo = NULL;
22599     int gpkg_mode = 0;
22600     int tiny_point = 0;
22601     struct splite_internal_cache *cache = sqlite3_user_data (context);
22602     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22603     if (cache != NULL)
22604       {
22605 	  gpkg_mode = cache->gpkg_mode;
22606 	  tiny_point = cache->tinyPointEnabled;
22607       }
22608     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
22609       {
22610 	  sqlite3_result_null (context);
22611 	  return;
22612       }
22613     text = sqlite3_value_text (argv[0]);
22614     geo = gaiaParseKml (text);
22615     if (geo == NULL)
22616       {
22617 	  sqlite3_result_null (context);
22618 	  return;
22619       }
22620     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
22621     gaiaFreeGeomColl (geo);
22622     sqlite3_result_blob (context, p_result, len, free);
22623 }
22624 
22625 static void
fnct_FromGml(sqlite3_context * context,int argc,sqlite3_value ** argv)22626 fnct_FromGml (sqlite3_context * context, int argc, sqlite3_value ** argv)
22627 {
22628 /* SQL function:
22629 / GeomFromGml(GML encoded geometry)
22630 /
22631 / returns the current geometry by parsing GML encoded string
22632 / or NULL if any error is encountered
22633 */
22634     int len;
22635     unsigned char *p_result = NULL;
22636     const unsigned char *text;
22637     gaiaGeomCollPtr geo = NULL;
22638     void *data = sqlite3_user_data (context);
22639     sqlite3 *sqlite = sqlite3_context_db_handle (context);
22640     int gpkg_mode = 0;
22641     int tiny_point = 0;
22642     struct splite_internal_cache *cache = sqlite3_user_data (context);
22643     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22644     if (cache != NULL)
22645       {
22646 	  gpkg_mode = cache->gpkg_mode;
22647 	  tiny_point = cache->tinyPointEnabled;
22648       }
22649     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
22650       {
22651 	  sqlite3_result_null (context);
22652 	  return;
22653       }
22654     text = sqlite3_value_text (argv[0]);
22655     if (data != NULL)
22656 	geo = gaiaParseGml_r (data, text, sqlite);
22657     else
22658 	geo = gaiaParseGml (text, sqlite);
22659     if (geo == NULL)
22660       {
22661 	  sqlite3_result_null (context);
22662 	  return;
22663       }
22664     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
22665     gaiaFreeGeomColl (geo);
22666     sqlite3_result_blob (context, p_result, len, free);
22667 }
22668 
22669 static void
fnct_LinesFromRings(sqlite3_context * context,int argc,sqlite3_value ** argv)22670 fnct_LinesFromRings (sqlite3_context * context, int argc, sqlite3_value ** argv)
22671 {
22672 /* SQL function:
22673 / LinesFromRings(BLOBencoded geometry, BOOL multi_linestring)
22674 /
22675 / returns a new geometry [LINESTRING or MULTILINESTRING] representing
22676 / the linearization for current (MULTI)POLYGON geometry
22677 / or NULL if any error is encountered
22678 */
22679     unsigned char *p_blob;
22680     int n_bytes;
22681     gaiaGeomCollPtr geo = NULL;
22682     gaiaGeomCollPtr geom_new = NULL;
22683     int len;
22684     int multi_linestring = 0;
22685     unsigned char *p_result = NULL;
22686     int gpkg_amphibious = 0;
22687     int gpkg_mode = 0;
22688     int tiny_point = 0;
22689     struct splite_internal_cache *cache = sqlite3_user_data (context);
22690     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22691     if (cache != NULL)
22692       {
22693 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22694 	  gpkg_mode = cache->gpkg_mode;
22695 	  tiny_point = cache->tinyPointEnabled;
22696       }
22697     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22698       {
22699 	  sqlite3_result_null (context);
22700 	  return;
22701       }
22702     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22703     n_bytes = sqlite3_value_bytes (argv[0]);
22704     geo =
22705 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22706 				     gpkg_amphibious);
22707     if (geo == NULL)
22708       {
22709 	  sqlite3_result_null (context);
22710 	  return;
22711       }
22712     if (argc == 2)
22713       {
22714 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
22715 	      multi_linestring = sqlite3_value_int (argv[1]);
22716       }
22717     geom_new = gaiaLinearize (geo, multi_linestring);
22718     if (!geom_new)
22719 	goto invalid;
22720     gaiaFreeGeomColl (geo);
22721     gaiaToSpatiaLiteBlobWkbEx2 (geom_new, &p_result, &len, gpkg_mode,
22722 				tiny_point);
22723     gaiaFreeGeomColl (geom_new);
22724     sqlite3_result_blob (context, p_result, len, free);
22725     return;
22726   invalid:
22727     if (geo)
22728 	gaiaFreeGeomColl (geo);
22729     sqlite3_result_null (context);
22730 }
22731 
22732 #ifndef OMIT_GEOS		/* including GEOS */
22733 
22734 static void
fnct_BuildArea(sqlite3_context * context,int argc,sqlite3_value ** argv)22735 fnct_BuildArea (sqlite3_context * context, int argc, sqlite3_value ** argv)
22736 {
22737 /* SQL function:
22738 / BuildArea(BLOBencoded geometry)
22739 /
22740 / Assuming that Geometry represents a set of sparse Linestrings,
22741 / this function will attempt to reassemble a single Polygon
22742 / (or a set of Polygons)
22743 / NULL is returned for invalid arguments
22744 */
22745     unsigned char *p_blob;
22746     int n_bytes;
22747     gaiaGeomCollPtr geo = NULL;
22748     gaiaGeomCollPtr result;
22749     int gpkg_amphibious = 0;
22750     int gpkg_mode = 0;
22751     int tiny_point = 0;
22752     struct splite_internal_cache *cache = sqlite3_user_data (context);
22753     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22754     if (cache != NULL)
22755       {
22756 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22757 	  gpkg_mode = cache->gpkg_mode;
22758 	  tiny_point = cache->tinyPointEnabled;
22759       }
22760     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22761       {
22762 	  sqlite3_result_null (context);
22763 	  return;
22764       }
22765     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22766     n_bytes = sqlite3_value_bytes (argv[0]);
22767     geo =
22768 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22769 				     gpkg_amphibious);
22770     if (geo == NULL)
22771 	sqlite3_result_null (context);
22772     else
22773       {
22774 	  void *data = sqlite3_user_data (context);
22775 	  if (data != NULL)
22776 	      result = gaiaPolygonize_r (data, geo, 0);
22777 	  else
22778 	      result = gaiaPolygonize (geo, 0);
22779 	  if (result == NULL)
22780 	      sqlite3_result_null (context);
22781 	  else
22782 	    {
22783 		/* builds the BLOB geometry to be returned */
22784 		int len;
22785 		unsigned char *p_result = NULL;
22786 		result->Srid = geo->Srid;
22787 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
22788 					    gpkg_mode, tiny_point);
22789 		sqlite3_result_blob (context, p_result, len, free);
22790 		gaiaFreeGeomColl (result);
22791 	    }
22792       }
22793     gaiaFreeGeomColl (geo);
22794 }
22795 
22796 
22797 static void
fnct_Polygonize_step(sqlite3_context * context,int argc,sqlite3_value ** argv)22798 fnct_Polygonize_step (sqlite3_context * context, int argc,
22799 		      sqlite3_value ** argv)
22800 {
22801 /* SQL function:
22802 / Polygonize(BLOBencoded geom)
22803 /
22804 / aggregate function - STEP
22805 /
22806 */
22807     unsigned char *p_blob;
22808     int n_bytes;
22809     gaiaGeomCollPtr geom;
22810     gaiaGeomCollPtr result;
22811     gaiaGeomCollPtr *p;
22812     int gpkg_amphibious = 0;
22813     int gpkg_mode = 0;
22814     struct splite_internal_cache *cache = sqlite3_user_data (context);
22815     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22816     if (cache != NULL)
22817       {
22818 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22819 	  gpkg_mode = cache->gpkg_mode;
22820       }
22821     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22822       {
22823 	  sqlite3_result_null (context);
22824 	  return;
22825       }
22826     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22827     n_bytes = sqlite3_value_bytes (argv[0]);
22828     geom =
22829 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22830 				     gpkg_amphibious);
22831     if (!geom)
22832 	return;
22833     p = sqlite3_aggregate_context (context, sizeof (gaiaGeomCollPtr));
22834     if (!(*p))
22835       {
22836 	  /* this is the first row */
22837 	  *p = geom;
22838       }
22839     else
22840       {
22841 	  /* subsequent rows */
22842 	  void *data = sqlite3_user_data (context);
22843 	  if (data != NULL)
22844 	      result = gaiaMergeGeometries_r (data, *p, geom);
22845 	  else
22846 	      result = gaiaMergeGeometries (*p, geom);
22847 	  *p = result;
22848 	  gaiaFreeGeomColl (geom);
22849       }
22850 }
22851 
22852 static void
fnct_Polygonize_final(sqlite3_context * context)22853 fnct_Polygonize_final (sqlite3_context * context)
22854 {
22855 /* SQL function:
22856 / Polygonize(BLOBencoded geom)
22857 /
22858 / aggregate function - FINAL
22859 /
22860 */
22861     gaiaGeomCollPtr result;
22862     gaiaGeomCollPtr geom;
22863     gaiaGeomCollPtr *p = sqlite3_aggregate_context (context, 0);
22864     int gpkg_mode = 0;
22865     int tiny_point = 0;
22866     struct splite_internal_cache *cache = sqlite3_user_data (context);
22867     if (cache != NULL)
22868       {
22869 	  gpkg_mode = cache->gpkg_mode;
22870 	  tiny_point = cache->tinyPointEnabled;
22871       }
22872     if (!p)
22873       {
22874 	  sqlite3_result_null (context);
22875 	  return;
22876       }
22877     result = *p;
22878     if (!result)
22879 	sqlite3_result_null (context);
22880     else
22881       {
22882 	  void *data = sqlite3_user_data (context);
22883 	  if (data != NULL)
22884 	      geom = gaiaPolygonize_r (data, result, 0);
22885 	  else
22886 	      geom = gaiaPolygonize (result, 0);
22887 	  if (geom == NULL)
22888 	      sqlite3_result_null (context);
22889 	  else
22890 	    {
22891 		/* builds the BLOB geometry to be returned */
22892 		int len;
22893 		unsigned char *p_result = NULL;
22894 		geom->Srid = result->Srid;
22895 		gaiaToSpatiaLiteBlobWkbEx2 (geom, &p_result, &len, gpkg_mode,
22896 					    tiny_point);
22897 		sqlite3_result_blob (context, p_result, len, free);
22898 		gaiaFreeGeomColl (geom);
22899 	    }
22900 	  gaiaFreeGeomColl (result);
22901       }
22902 }
22903 
22904 #endif /* end including GEOS */
22905 
22906 static void
fnct_DissolveSegments(sqlite3_context * context,int argc,sqlite3_value ** argv)22907 fnct_DissolveSegments (sqlite3_context * context, int argc,
22908 		       sqlite3_value ** argv)
22909 {
22910 /* SQL function:
22911 / DissolveSegments(BLOBencoded geometry)
22912 /
22913 / Dissolves any LINESTRING or RING into elementary segments
22914 / NULL is returned for invalid arguments
22915 */
22916     unsigned char *p_blob;
22917     int n_bytes;
22918     gaiaGeomCollPtr geo = NULL;
22919     gaiaGeomCollPtr result;
22920     int gpkg_amphibious = 0;
22921     int gpkg_mode = 0;
22922     int tiny_point = 0;
22923     struct splite_internal_cache *cache = sqlite3_user_data (context);
22924     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22925     if (cache != NULL)
22926       {
22927 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22928 	  gpkg_mode = cache->gpkg_mode;
22929 	  tiny_point = cache->tinyPointEnabled;
22930       }
22931     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22932       {
22933 	  sqlite3_result_null (context);
22934 	  return;
22935       }
22936     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22937     n_bytes = sqlite3_value_bytes (argv[0]);
22938     geo =
22939 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22940 				     gpkg_amphibious);
22941     if (geo == NULL)
22942 	sqlite3_result_null (context);
22943     else
22944       {
22945 	  result = gaiaDissolveSegments (geo);
22946 	  if (result == NULL)
22947 	      sqlite3_result_null (context);
22948 	  else
22949 	    {
22950 		/* builds the BLOB geometry to be returned */
22951 		int len;
22952 		unsigned char *p_result = NULL;
22953 		result->Srid = geo->Srid;
22954 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
22955 					    gpkg_mode, tiny_point);
22956 		sqlite3_result_blob (context, p_result, len, free);
22957 		gaiaFreeGeomColl (result);
22958 	    }
22959       }
22960     gaiaFreeGeomColl (geo);
22961 }
22962 
22963 static void
fnct_DissolvePoints(sqlite3_context * context,int argc,sqlite3_value ** argv)22964 fnct_DissolvePoints (sqlite3_context * context, int argc, sqlite3_value ** argv)
22965 {
22966 /* SQL function:
22967 / DissolvePoints(BLOBencoded geometry)
22968 /
22969 / Dissolves any LINESTRING or RING into elementary Vertices
22970 / NULL is returned for invalid arguments
22971 */
22972     unsigned char *p_blob;
22973     int n_bytes;
22974     gaiaGeomCollPtr geo = NULL;
22975     gaiaGeomCollPtr result;
22976     int gpkg_amphibious = 0;
22977     int gpkg_mode = 0;
22978     int tiny_point = 0;
22979     struct splite_internal_cache *cache = sqlite3_user_data (context);
22980     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
22981     if (cache != NULL)
22982       {
22983 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
22984 	  gpkg_mode = cache->gpkg_mode;
22985 	  tiny_point = cache->tinyPointEnabled;
22986       }
22987     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
22988       {
22989 	  sqlite3_result_null (context);
22990 	  return;
22991       }
22992     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
22993     n_bytes = sqlite3_value_bytes (argv[0]);
22994     geo =
22995 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
22996 				     gpkg_amphibious);
22997     if (geo == NULL)
22998 	sqlite3_result_null (context);
22999     else
23000       {
23001 	  result = gaiaDissolvePoints (geo);
23002 	  if (result == NULL)
23003 	      sqlite3_result_null (context);
23004 	  else
23005 	    {
23006 		/* builds the BLOB geometry to be returned */
23007 		int len;
23008 		unsigned char *p_result = NULL;
23009 		result->Srid = geo->Srid;
23010 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23011 					    gpkg_mode, tiny_point);
23012 		sqlite3_result_blob (context, p_result, len, free);
23013 		gaiaFreeGeomColl (result);
23014 	    }
23015       }
23016     gaiaFreeGeomColl (geo);
23017 }
23018 
23019 static void
fnct_CollectionExtract(sqlite3_context * context,int argc,sqlite3_value ** argv)23020 fnct_CollectionExtract (sqlite3_context * context, int argc,
23021 			sqlite3_value ** argv)
23022 {
23023 /* SQL function:
23024 / CollectionExtract(BLOBencoded geometry, Integer type)
23025 /
23026 / Extracts from a GEOMETRYCOLLECTION any item of the required TYPE
23027 / 1=Point - 2=Linestring - 3=Polygon
23028 / NULL is returned for invalid arguments
23029 */
23030     unsigned char *p_blob;
23031     int n_bytes;
23032     int type;
23033     gaiaGeomCollPtr geo = NULL;
23034     gaiaGeomCollPtr result = NULL;
23035     int gpkg_amphibious = 0;
23036     int gpkg_mode = 0;
23037     int tiny_point = 0;
23038     struct splite_internal_cache *cache = sqlite3_user_data (context);
23039     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23040     if (cache != NULL)
23041       {
23042 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23043 	  gpkg_mode = cache->gpkg_mode;
23044 	  tiny_point = cache->tinyPointEnabled;
23045       }
23046     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23047       {
23048 	  sqlite3_result_null (context);
23049 	  return;
23050       }
23051     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23052 	type = sqlite3_value_int (argv[1]);
23053     else
23054       {
23055 	  sqlite3_result_null (context);
23056 	  return;
23057       }
23058     if (type == 1 || type == 2 || type == 3)
23059 	;
23060     else
23061       {
23062 	  sqlite3_result_null (context);
23063 	  return;
23064       }
23065     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23066     n_bytes = sqlite3_value_bytes (argv[0]);
23067     geo =
23068 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23069 				     gpkg_amphibious);
23070     if (geo == NULL)
23071 	sqlite3_result_null (context);
23072     else
23073       {
23074 	  switch (type)
23075 	    {
23076 	    case 1:
23077 		result = gaiaExtractPointsFromGeomColl (geo);
23078 		break;
23079 	    case 2:
23080 		result = gaiaExtractLinestringsFromGeomColl (geo);
23081 		break;
23082 	    case 3:
23083 		result = gaiaExtractPolygonsFromGeomColl (geo);
23084 		break;
23085 	    };
23086 	  if (result == NULL)
23087 	      sqlite3_result_null (context);
23088 	  else
23089 	    {
23090 		/* builds the BLOB geometry to be returned */
23091 		int len;
23092 		unsigned char *p_result = NULL;
23093 		result->Srid = geo->Srid;
23094 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23095 					    gpkg_mode, tiny_point);
23096 		sqlite3_result_blob (context, p_result, len, free);
23097 		gaiaFreeGeomColl (result);
23098 	    }
23099       }
23100     gaiaFreeGeomColl (geo);
23101 }
23102 
23103 static void
fnct_AddMeasure(sqlite3_context * context,int argc,sqlite3_value ** argv)23104 fnct_AddMeasure (sqlite3_context * context, int argc, sqlite3_value ** argv)
23105 {
23106 /* SQL functions:
23107 / ST_AddMeasure(BLOBencoded geometry, Double m_start, Double m_end)
23108 /
23109 / Will return a new GEOMETRY (supporting M) with measures linearly
23110 / interpolated between the start and end points.
23111 / the input Geometry is expected to be a Linestring or MultiLinestring
23112 / NULL is returned for invalid arguments
23113 */
23114     unsigned char *p_blob;
23115     int n_bytes;
23116     double m_start;
23117     double m_end;
23118     int intval;
23119     gaiaGeomCollPtr geo = NULL;
23120     gaiaGeomCollPtr result;
23121     int gpkg_amphibious = 0;
23122     int gpkg_mode = 0;
23123     int tiny_point = 0;
23124     struct splite_internal_cache *cache = sqlite3_user_data (context);
23125     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23126     if (cache != NULL)
23127       {
23128 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23129 	  gpkg_mode = cache->gpkg_mode;
23130 	  tiny_point = cache->tinyPointEnabled;
23131       }
23132     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23133       {
23134 	  sqlite3_result_null (context);
23135 	  return;
23136       }
23137     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
23138 	m_start = sqlite3_value_double (argv[1]);
23139     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23140       {
23141 	  intval = sqlite3_value_int (argv[1]);
23142 	  m_start = intval;
23143       }
23144     else
23145       {
23146 	  sqlite3_result_null (context);
23147 	  return;
23148       }
23149     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
23150 	m_end = sqlite3_value_double (argv[2]);
23151     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
23152       {
23153 	  intval = sqlite3_value_int (argv[2]);
23154 	  m_end = intval;
23155       }
23156     else
23157       {
23158 	  sqlite3_result_null (context);
23159 	  return;
23160       }
23161     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23162     n_bytes = sqlite3_value_bytes (argv[0]);
23163     geo =
23164 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23165 				     gpkg_amphibious);
23166     if (geo == NULL)
23167 	sqlite3_result_null (context);
23168     else
23169       {
23170 	  result = gaiaAddMeasure (geo, m_start, m_end);
23171 	  if (result == NULL)
23172 	      sqlite3_result_null (context);
23173 	  else
23174 	    {
23175 		/* builds the BLOB geometry to be returned */
23176 		int len;
23177 		unsigned char *p_result = NULL;
23178 		result->Srid = geo->Srid;
23179 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23180 					    gpkg_mode, tiny_point);
23181 		sqlite3_result_blob (context, p_result, len, free);
23182 		gaiaFreeGeomColl (result);
23183 	    }
23184       }
23185     gaiaFreeGeomColl (geo);
23186 }
23187 
23188 static void
fnct_InterpolatePoint(sqlite3_context * context,int argc,sqlite3_value ** argv)23189 fnct_InterpolatePoint (sqlite3_context * context, int argc,
23190 		       sqlite3_value ** argv)
23191 {
23192 /* SQL functions:
23193 / ST_InterpolatePoint(BLOBencoded line-geometry, BLOBencoded point-geometry)
23194 /
23195 / Will return the M-value at the interpolated point nearest to the given point
23196 / the first input Geometry is expected to be a Linestring supporting M,
23197 / the second input Geometry is expected to be a Point
23198 / NULL is returned for invalid arguments
23199 */
23200     unsigned char *p_blob1;
23201     int n_bytes1;
23202     unsigned char *p_blob2;
23203     int n_bytes2;
23204     gaiaGeomCollPtr line = NULL;
23205     gaiaGeomCollPtr point = NULL;
23206     double m_value;
23207     int gpkg_amphibious = 0;
23208     int gpkg_mode = 0;
23209     struct splite_internal_cache *cache = sqlite3_user_data (context);
23210     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23211     if (cache != NULL)
23212       {
23213 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23214 	  gpkg_mode = cache->gpkg_mode;
23215       }
23216     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23217       {
23218 	  sqlite3_result_null (context);
23219 	  return;
23220       }
23221     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
23222       {
23223 	  sqlite3_result_null (context);
23224 	  return;
23225       }
23226     p_blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
23227     n_bytes1 = sqlite3_value_bytes (argv[0]);
23228     line =
23229 	gaiaFromSpatiaLiteBlobWkbEx (p_blob1, n_bytes1, gpkg_mode,
23230 				     gpkg_amphibious);
23231     p_blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
23232     n_bytes2 = sqlite3_value_bytes (argv[1]);
23233     point =
23234 	gaiaFromSpatiaLiteBlobWkbEx (p_blob2, n_bytes2, gpkg_mode,
23235 				     gpkg_amphibious);
23236     if (line == NULL || point == NULL)
23237 	sqlite3_result_null (context);
23238     else
23239       {
23240 	  if (!gaiaInterpolatePoint (cache, line, point, &m_value))
23241 	      sqlite3_result_null (context);
23242 	  else
23243 	      sqlite3_result_double (context, m_value);
23244       }
23245     if (line != NULL)
23246 	gaiaFreeGeomColl (line);
23247     if (point != NULL)
23248 	gaiaFreeGeomColl (point);
23249 }
23250 
23251 static void
fnct_LocateBetweenMeasures(sqlite3_context * context,int argc,sqlite3_value ** argv)23252 fnct_LocateBetweenMeasures (sqlite3_context * context, int argc,
23253 			    sqlite3_value ** argv)
23254 {
23255 /* SQL functions:
23256 / ST_Locate_Along_Measure(BLOBencoded geometry, Double m_value)
23257 / ST_LocateAlong(BLOBencoded geometry, Double m_value)
23258 / ST_Locate_Between_Measures(BLOBencoded geometry, Double m_start, Double m_end)
23259 / ST_LocateBetween(BLOBencoded geometry, Double m_start, Double m_end)
23260 /
23261 / Extracts from a GEOMETRY (supporting M) any Point/Linestring
23262 / matching the range of measures
23263 / NULL is returned for invalid arguments
23264 */
23265     unsigned char *p_blob;
23266     int n_bytes;
23267     double m_start;
23268     double m_end;
23269     int intval;
23270     gaiaGeomCollPtr geo = NULL;
23271     gaiaGeomCollPtr result;
23272     int gpkg_amphibious = 0;
23273     int gpkg_mode = 0;
23274     int tiny_point = 0;
23275     struct splite_internal_cache *cache = sqlite3_user_data (context);
23276     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23277     if (cache != NULL)
23278       {
23279 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23280 	  gpkg_mode = cache->gpkg_mode;
23281 	  tiny_point = cache->tinyPointEnabled;
23282       }
23283     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23284       {
23285 	  sqlite3_result_null (context);
23286 	  return;
23287       }
23288     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
23289 	m_start = sqlite3_value_double (argv[1]);
23290     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23291       {
23292 	  intval = sqlite3_value_int (argv[1]);
23293 	  m_start = intval;
23294       }
23295     else
23296       {
23297 	  sqlite3_result_null (context);
23298 	  return;
23299       }
23300     if (argc > 2)
23301       {
23302 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
23303 	      m_end = sqlite3_value_double (argv[2]);
23304 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
23305 	    {
23306 		intval = sqlite3_value_int (argv[2]);
23307 		m_end = intval;
23308 	    }
23309 	  else
23310 	    {
23311 		sqlite3_result_null (context);
23312 		return;
23313 	    }
23314       }
23315     else
23316 	m_end = m_start;
23317     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23318     n_bytes = sqlite3_value_bytes (argv[0]);
23319     geo =
23320 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23321 				     gpkg_amphibious);
23322     if (geo == NULL)
23323 	sqlite3_result_null (context);
23324     else
23325       {
23326 	  result = gaiaLocateBetweenMeasures (geo, m_start, m_end);
23327 	  if (result == NULL)
23328 	      sqlite3_result_null (context);
23329 	  else
23330 	    {
23331 		/* builds the BLOB geometry to be returned */
23332 		int len;
23333 		unsigned char *p_result = NULL;
23334 		result->Srid = geo->Srid;
23335 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23336 					    gpkg_mode, tiny_point);
23337 		sqlite3_result_blob (context, p_result, len, free);
23338 		gaiaFreeGeomColl (result);
23339 	    }
23340       }
23341     gaiaFreeGeomColl (geo);
23342 }
23343 
23344 static void
fnct_IsValidTrajectory(sqlite3_context * context,int argc,sqlite3_value ** argv)23345 fnct_IsValidTrajectory (sqlite3_context * context, int argc,
23346 			sqlite3_value ** argv)
23347 {
23348 /* SQL function:
23349 / ST_IsValidTrajectory(BLOBencoded geometry)
23350 /
23351 / returns:
23352 / 1 if this GEOMETRY is a LINESTRING supporting M-values and
23353 /   presenting M-values growing from o vertex to the next
23354 / 0 otherwise
23355 / or -1 if any error is encountered
23356 */
23357     unsigned char *p_blob;
23358     int n_bytes;
23359     int intval;
23360     gaiaGeomCollPtr geo = NULL;
23361     int gpkg_amphibious = 0;
23362     int gpkg_mode = 0;
23363     struct splite_internal_cache *cache = sqlite3_user_data (context);
23364     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23365     if (cache != NULL)
23366       {
23367 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23368 	  gpkg_mode = cache->gpkg_mode;
23369       }
23370     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23371       {
23372 	  sqlite3_result_int (context, -1);
23373 	  return;
23374       }
23375     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23376     n_bytes = sqlite3_value_bytes (argv[0]);
23377     geo =
23378 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23379 				     gpkg_amphibious);
23380     if (geo == NULL)
23381 	sqlite3_result_int (context, -1);
23382     else
23383       {
23384 	  intval = gaiaIsValidTrajectory (geo);
23385 	  sqlite3_result_int (context, intval);
23386 	  gaiaFreeGeomColl (geo);
23387       }
23388 }
23389 
23390 static void
fnct_TrajectoryInterpolatePoint(sqlite3_context * context,int argc,sqlite3_value ** argv)23391 fnct_TrajectoryInterpolatePoint (sqlite3_context * context, int argc,
23392 				 sqlite3_value ** argv)
23393 {
23394 /* SQL function:
23395 / ST_TrajectoryInterpolatePoint(BLOBencoded geometry, DOUBLE m)
23396 /
23397 / returns a new geometry representing a point interpolated along a Trajectory
23398 / accordingly to given M-Value
23399 / or NULL if any error is encountered
23400 */
23401     unsigned char *p_blob;
23402     int n_bytes;
23403     int intval;
23404     double m;
23405     gaiaGeomCollPtr geo = NULL;
23406     gaiaGeomCollPtr result;
23407     int gpkg_amphibious = 0;
23408     int gpkg_mode = 0;
23409     int tiny_point = 0;
23410     struct splite_internal_cache *cache = sqlite3_user_data (context);
23411     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23412     if (cache != NULL)
23413       {
23414 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23415 	  gpkg_mode = cache->gpkg_mode;
23416 	  tiny_point = cache->tinyPointEnabled;
23417       }
23418     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23419       {
23420 	  sqlite3_result_null (context);
23421 	  return;
23422       }
23423     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23424       {
23425 	  intval = sqlite3_value_int (argv[1]);
23426 	  m = intval;
23427       }
23428     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
23429 	m = sqlite3_value_double (argv[1]);
23430     else
23431       {
23432 	  sqlite3_result_null (context);
23433 	  return;
23434       }
23435     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23436     n_bytes = sqlite3_value_bytes (argv[0]);
23437     geo =
23438 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23439 				     gpkg_amphibious);
23440     if (geo == NULL)
23441 	sqlite3_result_int (context, -1);
23442     else
23443       {
23444 	  intval = gaiaIsValidTrajectory (geo);
23445 	  result = gaiaTrajectoryInterpolatePoint (geo, m);
23446 	  if (result == NULL)
23447 	      sqlite3_result_null (context);
23448 	  else
23449 	    {
23450 		/* builds the BLOB geometry to be returned */
23451 		int len;
23452 		unsigned char *p_result = NULL;
23453 		result->Srid = geo->Srid;
23454 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23455 					    gpkg_mode, tiny_point);
23456 		sqlite3_result_blob (context, p_result, len, free);
23457 		gaiaFreeGeomColl (result);
23458 	    }
23459 	  gaiaFreeGeomColl (geo);
23460       }
23461 }
23462 
23463 #ifndef OMIT_PROJ		/* including PROJ.4 */
23464 
23465 static void
fnct_Transform(sqlite3_context * context,int argc,sqlite3_value ** argv)23466 fnct_Transform (sqlite3_context * context, int argc, sqlite3_value ** argv)
23467 {
23468 /* SQL function:
23469 / Transform(BLOBencoded geometry, srid)
23470 / Transform(BLOBencoded geometry, srid, BBOXgeometry)
23471 / Transform(BLOBencoded geometry, srid, BBOXgeometry, string_1)
23472 / Transform(BLOBencoded geometry, srid, BBOXgeometry, string_1, string_2)
23473 /
23474 / returns a new geometry that is the original one received, but
23475 / transformed / translated to the new SRID [coordinates translation
23476 / is applied]
23477 / or NULL if any error is encountered
23478 */
23479     unsigned char *p_blob;
23480     int n_bytes;
23481     gaiaGeomCollPtr geo = NULL;
23482     gaiaGeomCollPtr result;
23483     int srid_from;
23484     int srid_to;
23485     char *proj_from = NULL;
23486     char *proj_to = NULL;
23487     const char *proj_string_1 = NULL;
23488     const char *proj_string_2 = NULL;
23489     sqlite3 *sqlite = sqlite3_context_db_handle (context);
23490     int gpkg_amphibious = 0;
23491     int gpkg_mode = 0;
23492     int tiny_point = 0;
23493     struct splite_internal_cache *cache = sqlite3_user_data (context);
23494     const char *msg;
23495     int check_origin_destination = 0;
23496 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23497     char *msg2;
23498     gaiaGeomCollPtr bbox = NULL;
23499     gaiaProjArea proj_area;
23500     gaiaProjAreaPtr proj_bbox = NULL;
23501 #else /* supporting old PROJ.4 */
23502 #endif
23503     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23504     if (cache != NULL)
23505       {
23506 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23507 	  gpkg_mode = cache->gpkg_mode;
23508 	  tiny_point = cache->tinyPointEnabled;
23509       }
23510     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23511       {
23512 	  sqlite3_result_null (context);
23513 	  return;
23514       }
23515     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23516 	srid_to = sqlite3_value_int (argv[1]);
23517     else
23518       {
23519 	  sqlite3_result_null (context);
23520 	  return;
23521       }
23522     if (argc >= 3)
23523       {
23524 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23525 	  if (sqlite3_value_type (argv[2]) == SQLITE_NULL)
23526 	      ;
23527 	  else if (sqlite3_value_type (argv[2]) != SQLITE_BLOB)
23528 	    {
23529 		msg =
23530 		    "ST_Transform exception - 3rd argument is neither a BLOB nor NULL.";
23531 		sqlite3_result_error (context, msg, -1);
23532 		return;
23533 	    }
23534 	  else
23535 	    {
23536 		p_blob = (unsigned char *) sqlite3_value_blob (argv[2]);
23537 		n_bytes = sqlite3_value_bytes (argv[2]);
23538 		bbox = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
23539 		if (!bbox)
23540 		  {
23541 		      gaiaFreeGeomColl (bbox);
23542 		      msg =
23543 			  "ST_Transform exception - 3rd argument is not a valid BLOB Geometry.";
23544 		      sqlite3_result_error (context, msg, -1);
23545 		      return;
23546 		  }
23547 		if (bbox->Srid != 4326)
23548 		  {
23549 		      gaiaFreeGeomColl (bbox);
23550 		      msg =
23551 			  "ST_Transform exception - 3rd argument is not a SRID=4326 Geometry.";
23552 		      sqlite3_result_error (context, msg, -1);
23553 		      return;
23554 		  }
23555 		proj_area.WestLongitude = bbox->MinX;
23556 		proj_area.EastLongitude = bbox->MaxX;
23557 		proj_area.SouthLatitude = bbox->MinY;
23558 		proj_area.NorthLatitude = bbox->MaxY;
23559 		proj_bbox = &proj_area;
23560 		gaiaFreeGeomColl (bbox);
23561 	    }
23562 #else /* supporting old PROJ.4 */
23563 	  msg =
23564 	      "ST_Transform exception - extra arguments require using PROJ.6 or later.";
23565 	  sqlite3_result_error (context, msg, -1);
23566 	  return;
23567 #endif
23568       }
23569     if (argc >= 4)
23570       {
23571 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23572 	  if (sqlite3_value_type (argv[3]) == SQLITE_NULL)
23573 	      ;
23574 	  else if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
23575 	    {
23576 		msg =
23577 		    "ST_Transform exception - 4th argument is neither a TEXT string nor NULL.";
23578 		sqlite3_result_error (context, msg, -1);
23579 		return;
23580 	    }
23581 	  else
23582 	      proj_string_1 = (const char *) sqlite3_value_text (argv[3]);
23583 #else /* supporting old PROJ.4 */
23584 	  msg =
23585 	      "ST_Transform exception - extra arguments require using PROJ.6 or later.";
23586 	  sqlite3_result_error (context, msg, -1);
23587 	  return;
23588 #endif
23589       }
23590     if (argc >= 5)
23591       {
23592 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23593 	  if (sqlite3_value_type (argv[4]) == SQLITE_NULL)
23594 	      ;
23595 	  else if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
23596 	    {
23597 		msg =
23598 		    "ST_Transform exception - 5th argument is neither a TEXT string nor NULL.";
23599 		sqlite3_result_error (context, msg, -1);
23600 		return;
23601 	    }
23602 	  else
23603 	      proj_string_2 = (const char *) sqlite3_value_text (argv[4]);
23604 #else /* supporting old PROJ.4 */
23605 	  msg =
23606 	      "ST_Transform exception - extra arguments require using PROJ.6 or later.";
23607 	  sqlite3_result_error (context, msg, -1);
23608 	  return;
23609 #endif
23610       }
23611     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23612     n_bytes = sqlite3_value_bytes (argv[0]);
23613     geo =
23614 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23615 				     gpkg_amphibious);
23616     if (!geo)
23617       {
23618 	  sqlite3_result_null (context);
23619 	  return;
23620       }
23621     else
23622       {
23623 	  srid_from = geo->Srid;
23624 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23625 	  if (proj_string_1 == NULL && proj_string_2 == NULL)
23626 	    {
23627 		getProjAuthNameSrid (sqlite, srid_from, &proj_from);
23628 		getProjAuthNameSrid (sqlite, srid_to, &proj_to);
23629 		proj_string_1 = proj_from;
23630 		proj_string_2 = proj_to;
23631 		check_origin_destination = 1;
23632 	    }
23633 	  else if (proj_string_1 != NULL && proj_string_2 != NULL)
23634 	      check_origin_destination = 0;
23635 	  else if (proj_string_1 != NULL && proj_string_2 == NULL)
23636 	      check_origin_destination = 0;
23637 	  else
23638 	    {
23639 		sqlite3_result_null (context);
23640 		return;
23641 	    }
23642 #else /* supporting old PROJ.4 */
23643 	  getProjParams (sqlite, srid_from, &proj_from);
23644 	  getProjParams (sqlite, srid_to, &proj_to);
23645 	  proj_string_1 = proj_from;
23646 	  proj_string_2 = proj_to;
23647 	  check_origin_destination = 1;
23648 #endif
23649 	  if (check_origin_destination)
23650 	    {
23651 		if (proj_to == NULL || proj_from == NULL)
23652 		  {
23653 		      if (proj_from)
23654 			  free (proj_from);
23655 		      if (proj_to)
23656 			  free (proj_to);
23657 		      gaiaFreeGeomColl (geo);
23658 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23659 		      if (proj_string_1 == NULL)
23660 			{
23661 			    msg =
23662 				"ST_Transform exception - unable to find the origin SRID.";
23663 			    sqlite3_result_error (context, msg, -1);
23664 			    return;
23665 			}
23666 		      if (proj_string_2 == NULL)
23667 			{
23668 			    msg =
23669 				"ST_Transform exception - unable to find the destination SRID.";
23670 			    sqlite3_result_error (context, msg, -1);
23671 			    return;
23672 			}
23673 #else /* supporting old PROJ.4 */
23674 		      sqlite3_result_null (context);
23675 		      return;
23676 #endif
23677 		  }
23678 	    }
23679 
23680 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23681 	  if (cache != NULL)
23682 	    {
23683 		gaiaResetProjErrorMsg_r (cache);
23684 		result =
23685 		    gaiaTransformEx_r (cache, geo, proj_string_1, proj_string_2,
23686 				       proj_bbox);
23687 	    }
23688 	  else
23689 	      result =
23690 		  gaiaTransformEx (geo, proj_string_1, proj_string_2,
23691 				   proj_bbox);
23692 	  if (result == NULL)
23693 	    {
23694 		msg2 =
23695 		    sqlite3_mprintf
23696 		    ("ST_Transform exception - PROJ reports \"%s\".",
23697 		     gaiaGetProjErrorMsg_r (cache));
23698 		sqlite3_result_error (context, msg2, -1);
23699 		sqlite3_free (msg2);
23700 		if (proj_from != NULL)
23701 		    free (proj_from);
23702 		if (proj_to != NULL)
23703 		    free (proj_to);
23704 		gaiaFreeGeomColl (geo);
23705 		return;
23706 	    }
23707 #else /* supporting old PROJ.4 */
23708 	  if (cache != NULL)
23709 	      result =
23710 		  gaiaTransform_r (cache, geo, proj_string_1, proj_string_2);
23711 	  else
23712 	      result = gaiaTransform (geo, proj_string_1, proj_string_2);
23713 #endif
23714 	  if (proj_from != NULL)
23715 	      free (proj_from);
23716 	  if (proj_to != NULL)
23717 	      free (proj_to);
23718 	  if (!result)
23719 	      sqlite3_result_null (context);
23720 	  else
23721 	    {
23722 		/* builds the BLOB geometry to be returned */
23723 		int len;
23724 		unsigned char *p_result = NULL;
23725 		result->Srid = srid_to;
23726 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23727 					    gpkg_mode, tiny_point);
23728 		sqlite3_result_blob (context, p_result, len, free);
23729 		gaiaFreeGeomColl (result);
23730 	    }
23731       }
23732     gaiaFreeGeomColl (geo);
23733 }
23734 
23735 static void
fnct_TransformXY(sqlite3_context * context,int argc,sqlite3_value ** argv)23736 fnct_TransformXY (sqlite3_context * context, int argc, sqlite3_value ** argv)
23737 {
23738 /* SQL function:
23739 / TransformXY(BLOBencoded geometry, srid)
23740 /
23741 / returns a new geometry that is the original one received, but
23742 / transformed / translated to the new SRID [coordinates translation
23743 / is applied]
23744 /
23745 / NOTE: this is a special "flavor" of ST_Transform()
23746 /       just X and Y coordinates will be transformed,
23747 /       Z and M values (if eventually present) will be
23748 /       left untouched.
23749 /       Mainly intended as a workaround possibily useful
23750 /       when facing partially broken PROJ.4 definitions.
23751 /
23752 / or NULL if any error is encountered
23753 */
23754     unsigned char *p_blob;
23755     int n_bytes;
23756     gaiaGeomCollPtr geo = NULL;
23757     gaiaGeomCollPtr result;
23758     int srid_from;
23759     int srid_to;
23760     char *proj_from = NULL;
23761     char *proj_to = NULL;
23762     void *data = sqlite3_user_data (context);
23763     sqlite3 *sqlite = sqlite3_context_db_handle (context);
23764     int gpkg_amphibious = 0;
23765     int gpkg_mode = 0;
23766     int tiny_point = 0;
23767     struct splite_internal_cache *cache = sqlite3_user_data (context);
23768     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23769     if (cache != NULL)
23770       {
23771 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23772 	  gpkg_mode = cache->gpkg_mode;
23773 	  tiny_point = cache->tinyPointEnabled;
23774       }
23775     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23776       {
23777 	  sqlite3_result_null (context);
23778 	  return;
23779       }
23780     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23781 	srid_to = sqlite3_value_int (argv[1]);
23782     else
23783       {
23784 	  sqlite3_result_null (context);
23785 	  return;
23786       }
23787     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23788     n_bytes = sqlite3_value_bytes (argv[0]);
23789     geo =
23790 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23791 				     gpkg_amphibious);
23792     if (!geo)
23793 	sqlite3_result_null (context);
23794     else
23795       {
23796 	  srid_from = geo->Srid;
23797 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23798 	  getProjAuthNameSrid (sqlite, srid_from, &proj_from);
23799 	  getProjAuthNameSrid (sqlite, srid_to, &proj_to);
23800 #else /* supporting old PROJ.4 */
23801 	  getProjParams (sqlite, srid_from, &proj_from);
23802 	  getProjParams (sqlite, srid_to, &proj_to);
23803 #endif
23804 	  if (proj_to == NULL || proj_from == NULL)
23805 	    {
23806 		if (proj_from)
23807 		    free (proj_from);
23808 		if (proj_to)
23809 		    free (proj_to);
23810 		gaiaFreeGeomColl (geo);
23811 		sqlite3_result_null (context);
23812 		return;
23813 	    }
23814 	  if (data != NULL)
23815 	      result = gaiaTransformXY_r (data, geo, proj_from, proj_to);
23816 	  else
23817 	      result = gaiaTransformXY (geo, proj_from, proj_to);
23818 	  free (proj_from);
23819 	  free (proj_to);
23820 	  if (!result)
23821 	      sqlite3_result_null (context);
23822 	  else
23823 	    {
23824 		/* builds the BLOB geometry to be returned */
23825 		int len;
23826 		unsigned char *p_result = NULL;
23827 		result->Srid = srid_to;
23828 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23829 					    gpkg_mode, tiny_point);
23830 		sqlite3_result_blob (context, p_result, len, free);
23831 		gaiaFreeGeomColl (result);
23832 	    }
23833       }
23834     gaiaFreeGeomColl (geo);
23835 }
23836 
23837 static void
fnct_TransformXYZ(sqlite3_context * context,int argc,sqlite3_value ** argv)23838 fnct_TransformXYZ (sqlite3_context * context, int argc, sqlite3_value ** argv)
23839 {
23840 /* SQL function:
23841 / TransformXYZ(BLOBencoded geometry, srid)
23842 /
23843 / returns a new geometry that is the original one received, but
23844 / transformed / translated to the new SRID [coordinates translation
23845 / is applied]
23846 /
23847 / NOTE: this is a special "flavor" of ST_Transform()
23848 /       just X, Y and Z coordinates will be transformed,
23849 /       M values (if eventually present) will be
23850 /       left untouched.
23851 /       Mainly intended as a workaround possibily useful
23852 /       when handling 4D geometries having M-values not
23853 /		corresponding to Time.
23854 /
23855 / or NULL if any error is encountered
23856 */
23857     unsigned char *p_blob;
23858     int n_bytes;
23859     gaiaGeomCollPtr geo = NULL;
23860     gaiaGeomCollPtr result;
23861     int srid_from;
23862     int srid_to;
23863     char *proj_from = NULL;
23864     char *proj_to = NULL;
23865     void *data = sqlite3_user_data (context);
23866     sqlite3 *sqlite = sqlite3_context_db_handle (context);
23867     int gpkg_amphibious = 0;
23868     int gpkg_mode = 0;
23869     int tiny_point = 0;
23870     struct splite_internal_cache *cache = sqlite3_user_data (context);
23871     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23872     if (cache != NULL)
23873       {
23874 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
23875 	  gpkg_mode = cache->gpkg_mode;
23876 	  tiny_point = cache->tinyPointEnabled;
23877       }
23878     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
23879       {
23880 	  sqlite3_result_null (context);
23881 	  return;
23882       }
23883     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
23884 	srid_to = sqlite3_value_int (argv[1]);
23885     else
23886       {
23887 	  sqlite3_result_null (context);
23888 	  return;
23889       }
23890     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
23891     n_bytes = sqlite3_value_bytes (argv[0]);
23892     geo =
23893 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
23894 				     gpkg_amphibious);
23895     if (!geo)
23896 	sqlite3_result_null (context);
23897     else
23898       {
23899 	  srid_from = geo->Srid;
23900 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
23901 	  getProjAuthNameSrid (sqlite, srid_from, &proj_from);
23902 	  getProjAuthNameSrid (sqlite, srid_to, &proj_to);
23903 #else /* supporting old PROJ.4 */
23904 	  getProjParams (sqlite, srid_from, &proj_from);
23905 	  getProjParams (sqlite, srid_to, &proj_to);
23906 #endif
23907 	  if (proj_to == NULL || proj_from == NULL)
23908 	    {
23909 		if (proj_from)
23910 		    free (proj_from);
23911 		if (proj_to)
23912 		    free (proj_to);
23913 		gaiaFreeGeomColl (geo);
23914 		sqlite3_result_null (context);
23915 		return;
23916 	    }
23917 	  if (data != NULL)
23918 	      result = gaiaTransformXYZ_r (data, geo, proj_from, proj_to);
23919 	  else
23920 	      result = gaiaTransformXYZ (geo, proj_from, proj_to);
23921 	  free (proj_from);
23922 	  free (proj_to);
23923 	  if (!result)
23924 	      sqlite3_result_null (context);
23925 	  else
23926 	    {
23927 		/* builds the BLOB geometry to be returned */
23928 		int len;
23929 		unsigned char *p_result = NULL;
23930 		result->Srid = srid_to;
23931 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
23932 					    gpkg_mode, tiny_point);
23933 		sqlite3_result_blob (context, p_result, len, free);
23934 		gaiaFreeGeomColl (result);
23935 	    }
23936       }
23937     gaiaFreeGeomColl (geo);
23938 }
23939 
23940 #ifdef PROJ_NEW			/* only if PROJ.6 is supported */
23941 static void
fnct_PROJ_GetLastErrorMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)23942 fnct_PROJ_GetLastErrorMsg (sqlite3_context * context, int argc,
23943 			   sqlite3_value ** argv)
23944 {
23945 /* SQL function:
23946 / PROJ_GetLastErrorMsg()
23947 /
23948 / return the most recent PROJ error message (if any)
23949 / return NULL on any other case
23950 */
23951     const char *msg;
23952     void *data = sqlite3_user_data (context);
23953     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23954     if (data != NULL)
23955 	msg = gaiaGetProjErrorMsg_r (data);
23956     else
23957 	msg = NULL;
23958     if (msg == NULL)
23959 	sqlite3_result_null (context);
23960     else
23961 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
23962 }
23963 
23964 static void
fnct_PROJ_GetDatabasePath(sqlite3_context * context,int argc,sqlite3_value ** argv)23965 fnct_PROJ_GetDatabasePath (sqlite3_context * context, int argc,
23966 			   sqlite3_value ** argv)
23967 {
23968 /* SQL function:
23969 / PROJ_GetDatabasePath()
23970 /
23971 / return the currently set PATH leading to the private PROJ.6 database
23972 / return NULL on any other case
23973 */
23974     const char *path;
23975     void *data = sqlite3_user_data (context);
23976     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23977     path = gaiaGetProjDatabasePath (data);
23978     if (path == NULL)
23979 	sqlite3_result_null (context);
23980     else
23981 	sqlite3_result_text (context, path, strlen (path), SQLITE_STATIC);
23982 }
23983 
23984 static void
fnct_PROJ_SetDatabasePath(sqlite3_context * context,int argc,sqlite3_value ** argv)23985 fnct_PROJ_SetDatabasePath (sqlite3_context * context, int argc,
23986 			   sqlite3_value ** argv)
23987 {
23988 /* SQL function:
23989 / PROJ_SetDatabasePath(path TEXT)
23990 /
23991 / sets the PATH leading to the private PROJ.6 database
23992 / return the new path on success
23993 / or NULL on any other case
23994 */
23995     const char *path;
23996     void *data = sqlite3_user_data (context);
23997     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
23998     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
23999       {
24000 	  sqlite3_result_null (context);
24001 	  return;
24002       }
24003     else
24004 	path = (const char *) sqlite3_value_text (argv[0]);
24005     path = gaiaSetProjDatabasePath (data, path);
24006     if (path == NULL)
24007 	sqlite3_result_null (context);
24008     else
24009 	sqlite3_result_text (context, path, strlen (path), SQLITE_STATIC);
24010 }
24011 
24012 static void
fnct_PROJ_AsProjString(sqlite3_context * context,int argc,sqlite3_value ** argv)24013 fnct_PROJ_AsProjString (sqlite3_context * context, int argc,
24014 			sqlite3_value ** argv)
24015 {
24016 /* SQL function:
24017 / PROJ_AsProjString(auth_name TEXT, auth_srid INTEGER)
24018 /
24019 / return the representation of some CRS as a proj-string
24020 / or NULL on error or invalid arguments
24021 */
24022     const char *auth_name = "EPSG";
24023     int auth_srid;
24024     char *proj_string = NULL;
24025     void *data = sqlite3_user_data (context);
24026     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24027     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
24028 	;
24029     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
24030 	auth_name = (const char *) sqlite3_value_text (argv[0]);
24031     else
24032       {
24033 	  sqlite3_result_null (context);
24034 	  return;
24035       }
24036     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
24037 	auth_srid = sqlite3_value_int (argv[1]);
24038     else
24039       {
24040 	  sqlite3_result_null (context);
24041 	  return;
24042       }
24043     proj_string = gaiaGetProjString (data, auth_name, auth_srid);
24044     if (proj_string == NULL)
24045 	sqlite3_result_null (context);
24046     else
24047 	sqlite3_result_text (context, proj_string, strlen (proj_string), free);
24048 }
24049 
24050 static void
fnct_PROJ_AsWKT(sqlite3_context * context,int argc,sqlite3_value ** argv)24051 fnct_PROJ_AsWKT (sqlite3_context * context, int argc, sqlite3_value ** argv)
24052 {
24053 /* SQL function:
24054 / PROJ_AsWKT(auth_name TEXT, auth_srid INTEGER)
24055 / PROJ_AsWKT(auth_name TEXT, auth_srid INTEGER, style TEXT)
24056 / PROJ_AsWKT(auth_name TEXT, auth_srid INTEGER, style TEXT, indented BOOLEAN)
24057 / PROJ_AsWKT(auth_name TEXT, auth_srid INTEGER, style TEXT,
24058 /            indented BOOLEAN, indentation INTEGER)
24059 /
24060 / return the WKT representation of some CRS
24061 / or NULL on error or invalid arguments
24062 */
24063     const char *auth_name = "EPSG";
24064     int auth_srid;
24065     int style = GAIA_PROJ_WKT_ISO_2018;
24066     int indented = 1;
24067     int indentation = 4;
24068     char *wkt_expr = NULL;
24069     void *data = sqlite3_user_data (context);
24070     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24071     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
24072 	;
24073     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
24074 	auth_name = (const char *) sqlite3_value_text (argv[0]);
24075     else
24076       {
24077 	  sqlite3_result_null (context);
24078 	  return;
24079       }
24080     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
24081 	auth_srid = sqlite3_value_int (argv[1]);
24082     else
24083       {
24084 	  sqlite3_result_null (context);
24085 	  return;
24086       }
24087     if (argc >= 3)
24088       {
24089 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
24090 	    {
24091 		const char *wkt = (const char *) sqlite3_value_text (argv[2]);
24092 		if (strcasecmp (wkt, "ISO-2015") == 0)
24093 		    style = GAIA_PROJ_WKT_ISO_2015;
24094 		if (strcasecmp (wkt, "GDAL") == 0)
24095 		    style = GAIA_PROJ_WKT_GDAL;
24096 		if (strcasecmp (wkt, "ESRI") == 0)
24097 		    style = GAIA_PROJ_WKT_ESRI;
24098 		else
24099 		    style = GAIA_PROJ_WKT_ISO_2018;
24100 	    }
24101 	  else
24102 	    {
24103 		sqlite3_result_null (context);
24104 		return;
24105 	    }
24106       }
24107     if (argc >= 4)
24108       {
24109 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
24110 	      indented = sqlite3_value_int (argv[3]);
24111 	  else
24112 	    {
24113 		sqlite3_result_null (context);
24114 		return;
24115 	    }
24116       }
24117     if (argc >= 5)
24118       {
24119 	  if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
24120 	      indentation = sqlite3_value_int (argv[4]);
24121 	  else
24122 	    {
24123 		sqlite3_result_null (context);
24124 		return;
24125 	    }
24126       }
24127     wkt_expr =
24128 	gaiaGetProjWKT (data, auth_name, auth_srid, style, indented,
24129 			indentation);
24130     if (wkt_expr == NULL)
24131 	sqlite3_result_null (context);
24132     else
24133 	sqlite3_result_text (context, wkt_expr, strlen (wkt_expr), free);
24134 }
24135 
24136 static void
fnct_PROJ_GuessSridFromWKT(sqlite3_context * context,int argc,sqlite3_value ** argv)24137 fnct_PROJ_GuessSridFromWKT (sqlite3_context * context, int argc,
24138 			    sqlite3_value ** argv)
24139 {
24140 /* SQL function:
24141 / PROJ_GuessSridFromWKT(wkt TEXT)
24142 /
24143 / return the SRID corresponding to a given WKT expression
24144 / -1 if not matching SRID exists
24145 / or NULL on error or invalid arguments
24146 */
24147     const char *wkt;
24148     int srid;
24149     sqlite3 *sqlite = sqlite3_context_db_handle (context);
24150     void *data = sqlite3_user_data (context);
24151     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24152     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
24153 	wkt = (const char *) sqlite3_value_text (argv[0]);
24154     else
24155       {
24156 	  sqlite3_result_null (context);
24157 	  return;
24158       }
24159     if (!gaiaGuessSridFromWKT (sqlite, data, wkt, &srid))
24160 	sqlite3_result_int (context, -1);
24161     else
24162 	sqlite3_result_int (context, srid);
24163 }
24164 
24165 static void
fnct_PROJ_GuessSridFromSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)24166 fnct_PROJ_GuessSridFromSHP (sqlite3_context * context, int argc,
24167 			    sqlite3_value ** argv)
24168 {
24169 /* SQL function:
24170 / PROJ_GuessSridFromSHP(filename TEXT)
24171 /
24172 / return the SRID corresponding to a given Shapefile
24173 / -1 if not matching SRID exists
24174 / or NULL on error or invalid arguments
24175 */
24176     const char *basepath;
24177     char *path;
24178     char *wkt = NULL;
24179     int srid;
24180     FILE *in;
24181     sqlite3 *sqlite = sqlite3_context_db_handle (context);
24182     void *data = sqlite3_user_data (context);
24183     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24184     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
24185 	basepath = (const char *) sqlite3_value_text (argv[0]);
24186     else
24187       {
24188 	  sqlite3_result_null (context);
24189 	  return;
24190       }
24191 /* loocking for an eventual .PRJ file */
24192     path = sqlite3_mprintf ("%s.prj", basepath);
24193 #ifdef _WIN32
24194     in = gaia_win_fopen (path, "rb");
24195 #else
24196     in = fopen (path, "rb");
24197 #endif
24198     if (in != NULL)
24199       {
24200 	  /* reading the WKT expression from the PRJ file */
24201 	  if (fseek (in, 0, SEEK_END) != -1)
24202 	    {
24203 		int rd;
24204 		int len = ftell (in);
24205 		rewind (in);
24206 		wkt = malloc (len + 1);
24207 		rd = fread (wkt, 1, len, in);
24208 		if (len != rd)
24209 		  {
24210 		      free (wkt);
24211 		      wkt = NULL;
24212 		  }
24213 		*(wkt + len) = '\0';
24214 	    }
24215 	  fclose (in);
24216       }
24217     sqlite3_free (path);
24218     if (wkt == NULL)
24219       {
24220 	  sqlite3_result_null (context);
24221 	  return;
24222       }
24223     if (!gaiaGuessSridFromWKT (sqlite, data, wkt, &srid))
24224 	sqlite3_result_int (context, -1);
24225     else
24226 	sqlite3_result_int (context, srid);
24227     free (wkt);
24228 }
24229 
24230 #ifdef ENABLE_MINIZIP		/* only id MINIZIP is enabled */
24231 static void
fnct_PROJ_GuessSridFromZipSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)24232 fnct_PROJ_GuessSridFromZipSHP (sqlite3_context * context, int argc,
24233 			       sqlite3_value ** argv)
24234 {
24235 /* SQL function:
24236 / PROJ_GuessSridFromZipSHP(zip_path TEXT, filename TEXT)
24237 /
24238 / return the SRID corresponding to a given Shapefile
24239 / -1 if not matching SRID exists
24240 / or NULL on error or invalid arguments
24241 */
24242     const char *zip_path;
24243     const char *basepath;
24244     char *wkt = NULL;
24245     int srid;
24246     sqlite3 *sqlite = sqlite3_context_db_handle (context);
24247     void *data = sqlite3_user_data (context);
24248     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24249     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
24250 	zip_path = (const char *) sqlite3_value_text (argv[0]);
24251     else
24252       {
24253 	  sqlite3_result_null (context);
24254 	  return;
24255       }
24256     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
24257 	basepath = (const char *) sqlite3_value_text (argv[1]);
24258     else
24259       {
24260 	  sqlite3_result_null (context);
24261 	  return;
24262       }
24263 /* loocking for an eventual .PRJ file */
24264     wkt = gaiaReadWktFromZipShp (zip_path, basepath);
24265     if (wkt == NULL)
24266       {
24267 	  sqlite3_result_null (context);
24268 	  return;
24269       }
24270     if (!gaiaGuessSridFromWKT (sqlite, data, wkt, &srid))
24271 	sqlite3_result_int (context, -1);
24272     else
24273 	sqlite3_result_int (context, srid);
24274     free (wkt);
24275 }
24276 #endif /* end MINIZIP */
24277 
24278 #endif /* end PROJ_NEW */
24279 
24280 #endif /* end including PROJ.4 */
24281 
24282 #ifndef OMIT_GEOS		/* including GEOS */
24283 
24284 static void
fnct_GEOS_GetLastWarningMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)24285 fnct_GEOS_GetLastWarningMsg (sqlite3_context * context, int argc,
24286 			     sqlite3_value ** argv)
24287 {
24288 /* SQL function:
24289 / GEOS_GetLastWarningMsg()
24290 /
24291 / return the most recent GEOS warning message (if any)
24292 / return NULL on any other case
24293 */
24294     const char *msg;
24295     void *data = sqlite3_user_data (context);
24296     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24297     if (data != NULL)
24298 	msg = gaiaGetGeosWarningMsg_r (data);
24299     else
24300 	msg = gaiaGetGeosWarningMsg ();
24301     if (msg == NULL)
24302 	sqlite3_result_null (context);
24303     else
24304 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
24305 }
24306 
24307 static void
fnct_GEOS_GetLastErrorMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)24308 fnct_GEOS_GetLastErrorMsg (sqlite3_context * context, int argc,
24309 			   sqlite3_value ** argv)
24310 {
24311 /* SQL function:
24312 / GEOS_GetLastErrorMsg()
24313 /
24314 / return the most recent GEOS error message (if any)
24315 / return NULL on any other case
24316 */
24317     const char *msg;
24318     void *data = sqlite3_user_data (context);
24319     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24320     if (data != NULL)
24321 	msg = gaiaGetGeosErrorMsg_r (data);
24322     else
24323 	msg = gaiaGetGeosErrorMsg ();
24324     if (msg == NULL)
24325 	sqlite3_result_null (context);
24326     else
24327 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
24328 }
24329 
24330 static void
fnct_GEOS_GetLastAuxErrorMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)24331 fnct_GEOS_GetLastAuxErrorMsg (sqlite3_context * context, int argc,
24332 			      sqlite3_value ** argv)
24333 {
24334 /* SQL function:
24335 / GEOS_GetLastAuxErrorMsg()
24336 /
24337 / return the most recent GEOS error message (if any)
24338 / return NULL on any other case
24339 */
24340     const char *msg;
24341     void *data = sqlite3_user_data (context);
24342     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24343     if (data != NULL)
24344 	msg = gaiaGetGeosAuxErrorMsg_r (data);
24345     else
24346 	msg = gaiaGetGeosAuxErrorMsg ();
24347     if (msg == NULL)
24348 	sqlite3_result_null (context);
24349     else
24350 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
24351 }
24352 
24353 static void
fnct_GEOS_GetCriticalPointFromMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)24354 fnct_GEOS_GetCriticalPointFromMsg (sqlite3_context * context, int argc,
24355 				   sqlite3_value ** argv)
24356 {
24357 /* SQL function:
24358 / GEOS_GetCriticalPointFromMsg()
24359 /
24360 / return a Point Geometry by (possibly) parsing the most recent GEOS error/warning message
24361 / return NULL on any other case
24362 */
24363     int srid = -1;
24364     gaiaGeomCollPtr geom;
24365     void *data = sqlite3_user_data (context);
24366     int gpkg_mode = 0;
24367     int tiny_point = 0;
24368     struct splite_internal_cache *cache = sqlite3_user_data (context);
24369     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24370     if (cache != NULL)
24371       {
24372 	  gpkg_mode = cache->gpkg_mode;
24373 	  tiny_point = cache->tinyPointEnabled;
24374       }
24375     if (argc == 1)
24376       {
24377 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
24378 	    {
24379 		sqlite3_result_null (context);
24380 		return;
24381 	    }
24382 	  srid = sqlite3_value_int (argv[0]);
24383       }
24384     if (data != NULL)
24385 	geom = gaiaCriticalPointFromGEOSmsg_r (data);
24386     else
24387 	geom = gaiaCriticalPointFromGEOSmsg ();
24388     if (geom == NULL)
24389 	sqlite3_result_null (context);
24390     else
24391       {
24392 	  unsigned char *blob;
24393 	  int len;
24394 	  geom->Srid = srid;
24395 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &blob, &len, gpkg_mode, tiny_point);
24396 	  gaiaFreeGeomColl (geom);
24397 	  sqlite3_result_blob (context, blob, len, free);
24398       }
24399 }
24400 
24401 static void
fnct_IsValidReason(sqlite3_context * context,int argc,sqlite3_value ** argv)24402 fnct_IsValidReason (sqlite3_context * context, int argc, sqlite3_value ** argv)
24403 {
24404 /* SQL function:
24405 / IsValidReason(geom [ , esri_flag] )
24406 / ST_IsValidReason(geom [ , esri_flag] )
24407 /
24408 / return a TEXT string stating if a Geometry is valid
24409 / and if not valid, a reason why
24410 / return NULL on any other case
24411 */
24412     unsigned char *p_blob;
24413     int n_bytes;
24414     int len;
24415     gaiaGeomCollPtr geom;
24416     int esri_flag = 0;
24417     char *str;
24418     void *data = sqlite3_user_data (context);
24419     int gpkg_amphibious = 0;
24420     int gpkg_mode = 0;
24421     struct splite_internal_cache *cache = sqlite3_user_data (context);
24422     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24423     if (cache != NULL)
24424       {
24425 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24426 	  gpkg_mode = cache->gpkg_mode;
24427       }
24428     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24429       {
24430 	  sqlite3_result_null (context);
24431 	  return;
24432       }
24433     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24434     n_bytes = sqlite3_value_bytes (argv[0]);
24435     if (argc >= 2)
24436       {
24437 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
24438 	    {
24439 		sqlite3_result_null (context);
24440 		return;
24441 	    }
24442 	  esri_flag = sqlite3_value_int (argv[1]);
24443       }
24444     geom =
24445 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24446 				     gpkg_amphibious);
24447     if (esri_flag)
24448       {
24449 	  gaiaGeomCollPtr detail;
24450 	  if (data != NULL)
24451 	      detail = gaiaIsValidDetailEx_r (data, geom, esri_flag);
24452 	  else
24453 	      detail = gaiaIsValidDetailEx (geom, esri_flag);
24454 	  if (detail == NULL)
24455 	    {
24456 		/* performing extra checks */
24457 		if (data != NULL)
24458 		  {
24459 		      if (gaiaIsToxic_r (data, geom))
24460 			  sqlite3_result_text (context,
24461 					       "Invalid: Toxic Geometry ... too few points",
24462 					       -1, SQLITE_TRANSIENT);
24463 		      else if (gaiaIsNotClosedGeomColl_r (data, geom))
24464 			  sqlite3_result_text (context,
24465 					       "Invalid: Unclosed Rings were detected",
24466 					       -1, SQLITE_TRANSIENT);
24467 		      else
24468 			  sqlite3_result_text (context, "Valid Geometry", -1,
24469 					       SQLITE_TRANSIENT);
24470 		  }
24471 		else
24472 		  {
24473 		      if (gaiaIsToxic (geom))
24474 			  sqlite3_result_text (context,
24475 					       "Invalid: Toxic Geometry ... too few points",
24476 					       -1, SQLITE_TRANSIENT);
24477 		      else if (gaiaIsNotClosedGeomColl (geom))
24478 			  sqlite3_result_text (context,
24479 					       "Invalid: Unclosed Rings were detected",
24480 					       -1, SQLITE_TRANSIENT);
24481 		      else
24482 			  sqlite3_result_text (context, "Valid Geometry", -1,
24483 					       SQLITE_TRANSIENT);
24484 		  }
24485 		goto end;
24486 	    }
24487 	  else
24488 	      gaiaFreeGeomColl (detail);
24489       }
24490     if (data != NULL)
24491 	str = gaiaIsValidReason_r (data, geom);
24492     else
24493 	str = gaiaIsValidReason (geom);
24494     if (str == NULL)
24495 	sqlite3_result_null (context);
24496     else
24497       {
24498 	  len = strlen (str);
24499 	  sqlite3_result_text (context, str, len, free);
24500       }
24501   end:
24502     if (geom != NULL)
24503 	gaiaFreeGeomColl (geom);
24504 }
24505 
24506 static void
fnct_IsValidDetail(sqlite3_context * context,int argc,sqlite3_value ** argv)24507 fnct_IsValidDetail (sqlite3_context * context, int argc, sqlite3_value ** argv)
24508 {
24509 /* SQL function:
24510 / IsValidDetail(geom [ , esri_flag] )
24511 / ST_IsValidDetail(geom [ , esri_flag] )
24512 /
24513 / return a Geometry detail causing a Geometry to be invalid
24514 / return NULL on any other case
24515 */
24516     unsigned char *p_blob;
24517     int n_bytes;
24518     int len;
24519     gaiaGeomCollPtr geom;
24520     gaiaGeomCollPtr detail;
24521     int esri_flag = 0;
24522     unsigned char *p_result = NULL;
24523     void *data = sqlite3_user_data (context);
24524     int gpkg_amphibious = 0;
24525     int gpkg_mode = 0;
24526     int tiny_point = 0;
24527     struct splite_internal_cache *cache = sqlite3_user_data (context);
24528     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24529     if (cache != NULL)
24530       {
24531 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24532 	  gpkg_mode = cache->gpkg_mode;
24533 	  tiny_point = cache->tinyPointEnabled;
24534       }
24535     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24536       {
24537 	  sqlite3_result_null (context);
24538 	  return;
24539       }
24540     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24541     n_bytes = sqlite3_value_bytes (argv[0]);
24542     if (argc >= 2)
24543       {
24544 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
24545 	    {
24546 		sqlite3_result_null (context);
24547 		return;
24548 	    }
24549 	  esri_flag = sqlite3_value_int (argv[1]);
24550       }
24551     geom =
24552 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24553 				     gpkg_amphibious);
24554     if (data != NULL)
24555 	detail = gaiaIsValidDetailEx_r (data, geom, esri_flag);
24556     else
24557 	detail = gaiaIsValidDetailEx (geom, esri_flag);
24558     if (detail == NULL)
24559 	sqlite3_result_null (context);
24560     else
24561       {
24562 	  detail->Srid = geom->Srid;
24563 	  gaiaToSpatiaLiteBlobWkbEx2 (detail, &p_result, &len, gpkg_mode,
24564 				      tiny_point);
24565 	  sqlite3_result_blob (context, p_result, len, free);
24566       }
24567     if (geom != NULL)
24568 	gaiaFreeGeomColl (geom);
24569     if (detail != NULL)
24570 	gaiaFreeGeomColl (detail);
24571 }
24572 
24573 static void
fnct_Boundary(sqlite3_context * context,int argc,sqlite3_value ** argv)24574 fnct_Boundary (sqlite3_context * context, int argc, sqlite3_value ** argv)
24575 {
24576 /* SQL function:
24577 / Boundary(BLOB encoded geometry)
24578 /
24579 / returns the combinatorial boundary for current geometry
24580 / or NULL if any error is encountered
24581 */
24582     unsigned char *p_blob;
24583     int n_bytes;
24584     int len;
24585     unsigned char *p_result = NULL;
24586     gaiaGeomCollPtr geo = NULL;
24587     gaiaGeomCollPtr boundary;
24588     int gpkg_amphibious = 0;
24589     int gpkg_mode = 0;
24590     int tiny_point = 0;
24591     struct splite_internal_cache *cache = sqlite3_user_data (context);
24592     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24593     if (cache != NULL)
24594       {
24595 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24596 	  gpkg_mode = cache->gpkg_mode;
24597 	  tiny_point = cache->tinyPointEnabled;
24598       }
24599     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24600       {
24601 	  sqlite3_result_null (context);
24602 	  return;
24603       }
24604     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24605     n_bytes = sqlite3_value_bytes (argv[0]);
24606     geo =
24607 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24608 				     gpkg_amphibious);
24609     if (!geo)
24610 	sqlite3_result_null (context);
24611     else
24612       {
24613 	  if (gaiaIsEmpty (geo))
24614 	      sqlite3_result_null (context);
24615 	  else
24616 	    {
24617 		void *data = sqlite3_user_data (context);
24618 		if (data != NULL)
24619 		    boundary = gaiaBoundary_r (data, geo);
24620 		else
24621 		    boundary = gaiaBoundary (geo);
24622 		if (!boundary)
24623 		    sqlite3_result_null (context);
24624 		else
24625 		  {
24626 		      gaiaToSpatiaLiteBlobWkbEx2 (boundary, &p_result, &len,
24627 						  gpkg_mode, tiny_point);
24628 		      gaiaFreeGeomColl (boundary);
24629 		      sqlite3_result_blob (context, p_result, len, free);
24630 		  }
24631 	    }
24632       }
24633     gaiaFreeGeomColl (geo);
24634 }
24635 
24636 static void
fnct_IsClosed(sqlite3_context * context,int argc,sqlite3_value ** argv)24637 fnct_IsClosed (sqlite3_context * context, int argc, sqlite3_value ** argv)
24638 {
24639 /* SQL function:
24640 / IsClosed(BLOB encoded LINESTRING or MULTILINESTRING geometry)
24641 /
24642 / returns:
24643 / 1 if this LINESTRING is closed [or if this is a MULTILINESTRING and every LINESTRINGs are closed]
24644 / 0 otherwise
24645 / or -1 if any error is encountered
24646 */
24647     unsigned char *p_blob;
24648     int n_bytes;
24649     gaiaGeomCollPtr geo = NULL;
24650     int gpkg_amphibious = 0;
24651     int gpkg_mode = 0;
24652     struct splite_internal_cache *cache = sqlite3_user_data (context);
24653     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24654     if (cache != NULL)
24655       {
24656 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24657 	  gpkg_mode = cache->gpkg_mode;
24658       }
24659     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24660       {
24661 	  sqlite3_result_int (context, -1);
24662 	  return;
24663       }
24664     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24665     n_bytes = sqlite3_value_bytes (argv[0]);
24666     geo =
24667 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24668 				     gpkg_amphibious);
24669     if (!geo)
24670 	sqlite3_result_int (context, -1);
24671     else
24672       {
24673 	  sqlite3_result_int (context, gaiaIsClosedGeom (geo));
24674       }
24675     gaiaFreeGeomColl (geo);
24676 }
24677 
24678 static void
fnct_IsSimple(sqlite3_context * context,int argc,sqlite3_value ** argv)24679 fnct_IsSimple (sqlite3_context * context, int argc, sqlite3_value ** argv)
24680 {
24681 /* SQL function:
24682 / IsSimple(BLOB encoded GEOMETRY)
24683 /
24684 / returns:
24685 / 1 if this GEOMETRY is simple
24686 / 0 otherwise
24687 / or -1 if any error is encountered
24688 */
24689     unsigned char *p_blob;
24690     int n_bytes;
24691     int ret;
24692     gaiaGeomCollPtr geo = NULL;
24693     int gpkg_amphibious = 0;
24694     int gpkg_mode = 0;
24695     struct splite_internal_cache *cache = sqlite3_user_data (context);
24696     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24697     if (cache != NULL)
24698       {
24699 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24700 	  gpkg_mode = cache->gpkg_mode;
24701       }
24702     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24703       {
24704 	  sqlite3_result_int (context, -1);
24705 	  return;
24706       }
24707     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24708     n_bytes = sqlite3_value_bytes (argv[0]);
24709     geo =
24710 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24711 				     gpkg_amphibious);
24712     if (!geo)
24713 	sqlite3_result_int (context, -1);
24714     else
24715       {
24716 	  void *data = sqlite3_user_data (context);
24717 	  if (data != NULL)
24718 	      ret = gaiaIsSimple_r (data, geo);
24719 	  else
24720 	      ret = gaiaIsSimple (geo);
24721 	  if (ret < 0)
24722 	      sqlite3_result_int (context, -1);
24723 	  else
24724 	      sqlite3_result_int (context, ret);
24725       }
24726     gaiaFreeGeomColl (geo);
24727 }
24728 
24729 static void
fnct_IsRing(sqlite3_context * context,int argc,sqlite3_value ** argv)24730 fnct_IsRing (sqlite3_context * context, int argc, sqlite3_value ** argv)
24731 {
24732 /* SQL function:
24733 / IsRing(BLOB encoded LINESTRING geometry)
24734 /
24735 / returns:
24736 / 1 if this LINESTRING is a valid RING
24737 / 0 otherwise
24738 / or -1 if any error is encountered
24739 */
24740     unsigned char *p_blob;
24741     int n_bytes;
24742     int ret;
24743     gaiaGeomCollPtr geo = NULL;
24744     gaiaLinestringPtr line;
24745     int gpkg_amphibious = 0;
24746     int gpkg_mode = 0;
24747     struct splite_internal_cache *cache = sqlite3_user_data (context);
24748     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24749     if (cache != NULL)
24750       {
24751 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24752 	  gpkg_mode = cache->gpkg_mode;
24753       }
24754     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24755       {
24756 	  sqlite3_result_int (context, -1);
24757 	  return;
24758       }
24759     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24760     n_bytes = sqlite3_value_bytes (argv[0]);
24761     geo =
24762 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24763 				     gpkg_amphibious);
24764     if (!geo)
24765 	sqlite3_result_int (context, -1);
24766     else
24767       {
24768 	  line = simpleLinestring (geo);
24769 	  if (line == NULL)
24770 	      sqlite3_result_int (context, -1);
24771 	  else
24772 	    {
24773 		void *data = sqlite3_user_data (context);
24774 		if (data != NULL)
24775 		    ret = gaiaIsRing_r (data, line);
24776 		else
24777 		    ret = gaiaIsRing (line);
24778 		sqlite3_result_int (context, ret);
24779 	    }
24780       }
24781     gaiaFreeGeomColl (geo);
24782 }
24783 
24784 static void
fnct_IsValid(sqlite3_context * context,int argc,sqlite3_value ** argv)24785 fnct_IsValid (sqlite3_context * context, int argc, sqlite3_value ** argv)
24786 {
24787 /* SQL function:
24788 / IsValid(BLOB encoded GEOMETRY [ , BOOLEAN esri_flag] )
24789 /
24790 / returns:
24791 / 1 if this GEOMETRY is a valid one
24792 / 0 otherwise
24793 / or -1 if any error is encountered
24794 */
24795     unsigned char *p_blob;
24796     int n_bytes;
24797     int ret;
24798     gaiaGeomCollPtr geo = NULL;
24799     int esri_flag = 0;
24800     int gpkg_amphibious = 0;
24801     int gpkg_mode = 0;
24802     struct splite_internal_cache *cache = sqlite3_user_data (context);
24803     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24804     if (cache != NULL)
24805       {
24806 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24807 	  gpkg_mode = cache->gpkg_mode;
24808       }
24809     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24810       {
24811 	  sqlite3_result_int (context, -1);
24812 	  return;
24813       }
24814     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24815     n_bytes = sqlite3_value_bytes (argv[0]);
24816     if (argc >= 2)
24817       {
24818 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
24819 	    {
24820 		sqlite3_result_null (context);
24821 		return;
24822 	    }
24823 	  esri_flag = sqlite3_value_int (argv[1]);
24824       }
24825     geo =
24826 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24827 				     gpkg_amphibious);
24828     if (!geo)
24829 	sqlite3_result_int (context, -1);
24830     else
24831       {
24832 	  void *data = sqlite3_user_data (context);
24833 	  if (esri_flag)
24834 	    {
24835 		gaiaGeomCollPtr detail;
24836 		if (data != NULL)
24837 		    detail = gaiaIsValidDetailEx_r (data, geo, esri_flag);
24838 		else
24839 		    detail = gaiaIsValidDetailEx (geo, esri_flag);
24840 		if (detail == NULL)
24841 		  {
24842 		      /* extra checks */
24843 		      int extra = 0;
24844 		      if (data != NULL)
24845 			{
24846 			    if (gaiaIsToxic_r (data, geo))
24847 				extra = 1;
24848 			    if (gaiaIsNotClosedGeomColl_r (data, geo))
24849 				extra = 1;
24850 			}
24851 		      else
24852 			{
24853 			    if (gaiaIsToxic (geo))
24854 				extra = 1;
24855 			    if (gaiaIsNotClosedGeomColl (geo))
24856 				extra = 1;
24857 			}
24858 		      if (extra)
24859 			  sqlite3_result_int (context, 0);
24860 		      else
24861 			  sqlite3_result_int (context, 1);
24862 		  }
24863 		else
24864 		  {
24865 		      gaiaFreeGeomColl (detail);
24866 		      sqlite3_result_int (context, 0);
24867 		  }
24868 		goto end;
24869 	    }
24870 	  if (data != NULL)
24871 	      ret = gaiaIsValid_r (data, geo);
24872 	  else
24873 	      ret = gaiaIsValid (geo);
24874 	  if (ret < 0)
24875 	      sqlite3_result_int (context, -1);
24876 	  else
24877 	      sqlite3_result_int (context, ret);
24878       }
24879   end:
24880     gaiaFreeGeomColl (geo);
24881 }
24882 
24883 static void
length_common(const void * p_cache,sqlite3_context * context,int argc,sqlite3_value ** argv,int is_perimeter)24884 length_common (const void *p_cache, sqlite3_context * context, int argc,
24885 	       sqlite3_value ** argv, int is_perimeter)
24886 {
24887 /* common implementation supporting both ST_Length and ST_Perimeter */
24888     unsigned char *p_blob;
24889     int n_bytes;
24890     double length = 0.0;
24891     int ret;
24892     int use_ellipsoid = -1;
24893     double a;
24894     double b;
24895     double rf;
24896     gaiaGeomCollPtr geo = NULL;
24897     sqlite3 *sqlite = sqlite3_context_db_handle (context);
24898     int gpkg_amphibious = 0;
24899     int gpkg_mode = 0;
24900     struct splite_internal_cache *cache = sqlite3_user_data (context);
24901     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
24902     if (cache != NULL)
24903       {
24904 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
24905 	  gpkg_mode = cache->gpkg_mode;
24906       }
24907     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
24908       {
24909 	  sqlite3_result_null (context);
24910 	  return;
24911       }
24912     if (argc == 2)
24913       {
24914 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
24915 	    {
24916 		sqlite3_result_null (context);
24917 		return;
24918 	    }
24919 	  use_ellipsoid = sqlite3_value_int (argv[1]);
24920 	  if (use_ellipsoid != 0)
24921 	      use_ellipsoid = 1;
24922       }
24923     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
24924     n_bytes = sqlite3_value_bytes (argv[0]);
24925     geo =
24926 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
24927 				     gpkg_amphibious);
24928     if (!geo)
24929 	sqlite3_result_null (context);
24930     else
24931       {
24932 	  if (use_ellipsoid >= 0)
24933 	    {
24934 		/* attempting to identify the corresponding ellipsoid */
24935 		if (getEllipsoidParams (sqlite, geo->Srid, &a, &b, &rf))
24936 		  {
24937 		      double l;
24938 		      int ib;
24939 		      gaiaLinestringPtr line;
24940 		      gaiaPolygonPtr polyg;
24941 		      gaiaRingPtr ring;
24942 		      if (use_ellipsoid)
24943 			{
24944 			    /* measuring on the Ellipsoid */
24945 			    if (!is_perimeter)
24946 			      {
24947 				  line = geo->FirstLinestring;
24948 				  while (line)
24949 				    {
24950 					/* Linestrings */
24951 					l = gaiaGeodesicTotalLength (a,
24952 								     b,
24953 								     rf,
24954 								     line->
24955 								     DimensionModel,
24956 								     line->Coords,
24957 								     line->Points);
24958 					if (l < 0.0)
24959 					  {
24960 					      length = -1.0;
24961 					      break;
24962 					  }
24963 					length += l;
24964 					line = line->Next;
24965 				    }
24966 			      }
24967 			    if (length >= 0)
24968 			      {
24969 				  if (is_perimeter)
24970 				    {
24971 					/* Polygons */
24972 					polyg = geo->FirstPolygon;
24973 					while (polyg)
24974 					  {
24975 					      /* exterior Ring */
24976 					      ring = polyg->Exterior;
24977 					      l = gaiaGeodesicTotalLength (a,
24978 									   b,
24979 									   rf,
24980 									   ring->DimensionModel,
24981 									   ring->Coords,
24982 									   ring->Points);
24983 					      if (l < 0.0)
24984 						{
24985 						    length = -1.0;
24986 						    break;
24987 						}
24988 					      length += l;
24989 					      for (ib = 0;
24990 						   ib <
24991 						   polyg->NumInteriors; ib++)
24992 						{
24993 						    /* interior Rings */
24994 						    ring =
24995 							polyg->Interiors + ib;
24996 						    l = gaiaGeodesicTotalLength
24997 							(a, b, rf,
24998 							 ring->DimensionModel,
24999 							 ring->Coords,
25000 							 ring->Points);
25001 						    if (l < 0.0)
25002 						      {
25003 							  length = -1.0;
25004 							  break;
25005 						      }
25006 						    length += l;
25007 						}
25008 					      if (length < 0.0)
25009 						  break;
25010 					      polyg = polyg->Next;
25011 					  }
25012 				    }
25013 			      }
25014 			}
25015 		      else
25016 			{
25017 			    /* measuring on the Great Circle */
25018 			    if (!is_perimeter)
25019 			      {
25020 				  line = geo->FirstLinestring;
25021 				  while (line)
25022 				    {
25023 					/* Linestrings */
25024 					length +=
25025 					    gaiaGreatCircleTotalLength
25026 					    (a, b, line->DimensionModel,
25027 					     line->Coords, line->Points);
25028 					line = line->Next;
25029 				    }
25030 			      }
25031 			    if (length >= 0)
25032 			      {
25033 				  if (is_perimeter)
25034 				    {
25035 					/* Polygons */
25036 					polyg = geo->FirstPolygon;
25037 					while (polyg)
25038 					  {
25039 					      /* exterior Ring */
25040 					      ring = polyg->Exterior;
25041 					      length +=
25042 						  gaiaGreatCircleTotalLength
25043 						  (a, b,
25044 						   ring->DimensionModel,
25045 						   ring->Coords, ring->Points);
25046 					      for (ib = 0;
25047 						   ib < polyg->NumInteriors;
25048 						   ib++)
25049 						{
25050 						    /* interior Rings */
25051 						    ring =
25052 							polyg->Interiors + ib;
25053 						    length +=
25054 							gaiaGreatCircleTotalLength
25055 							(a, b,
25056 							 ring->DimensionModel,
25057 							 ring->Coords,
25058 							 ring->Points);
25059 						}
25060 					      polyg = polyg->Next;
25061 					  }
25062 				    }
25063 			      }
25064 			}
25065 		      if (length < 0.0)
25066 			{
25067 			    /* invalid distance */
25068 			    sqlite3_result_null (context);
25069 			}
25070 		      else
25071 			  sqlite3_result_double (context, length);
25072 		  }
25073 		else
25074 		    sqlite3_result_null (context);
25075 		goto stop;
25076 	    }
25077 	  else if (p_cache != NULL)
25078 	      ret =
25079 		  gaiaGeomCollLengthOrPerimeter_r (p_cache, geo, is_perimeter,
25080 						   &length);
25081 	  else
25082 	      ret = gaiaGeomCollLengthOrPerimeter (geo, is_perimeter, &length);
25083 	  if (!ret)
25084 	      sqlite3_result_null (context);
25085 	  else
25086 	      sqlite3_result_double (context, length);
25087       }
25088   stop:
25089     gaiaFreeGeomColl (geo);
25090 }
25091 
25092 static void
fnct_Length(sqlite3_context * context,int argc,sqlite3_value ** argv)25093 fnct_Length (sqlite3_context * context, int argc, sqlite3_value ** argv)
25094 {
25095 /* SQL function:
25096 / ST_Length(BLOB encoded GEOMETRYCOLLECTION)
25097 / ST_Length(BLOB encoded GEOMETRYCOLLECTION, Boolean use_ellipsoid)
25098 /
25099 / returns  the total length for current geometry
25100 / or NULL if any error is encountered
25101 /
25102 / Please note: starting since 4.0.0 this function will ignore
25103 / any Polygon (only Linestrings will be considered)
25104 /
25105 */
25106     void *data = sqlite3_user_data (context);
25107     length_common (data, context, argc, argv, 0);
25108 }
25109 
25110 static void
fnct_Perimeter(sqlite3_context * context,int argc,sqlite3_value ** argv)25111 fnct_Perimeter (sqlite3_context * context, int argc, sqlite3_value ** argv)
25112 {
25113 /* SQL function:
25114 / ST_Perimeter(BLOB encoded GEOMETRYCOLLECTION)
25115 / ST_Perimeter(BLOB encoded GEOMETRYCOLLECTION, Boolean use_ellipsoid)
25116 /
25117 / returns  the total perimeter length for current geometry
25118 / or NULL if any error is encountered
25119 /
25120 / Please note: starting since 4.0.0 this function will ignore
25121 / any Linestring (only Polygons will be considered)
25122 /
25123 */
25124     void *data = sqlite3_user_data (context);
25125     length_common (data, context, argc, argv, 1);
25126 }
25127 
25128 static void
linestring_segment_length_common(sqlite3_context * context,int argc,sqlite3_value ** argv,int mode)25129 linestring_segment_length_common (sqlite3_context * context, int argc,
25130 				  sqlite3_value ** argv, int mode)
25131 {
25132 /* common implementation supporting LinestringXxxSegmentLenght */
25133     unsigned char *p_blob;
25134     int n_bytes;
25135     int ignore_repeated_vertices = 1;
25136     int iv;
25137     double x;
25138     double y;
25139     double z;
25140     double m;
25141     double last_x;
25142     double last_y;
25143     double min = DBL_MAX;
25144     double max = 0.0;
25145     double tot = 0.0;
25146     int n = 0;
25147     gaiaLinestringPtr ln;
25148     gaiaGeomCollPtr geo = NULL;
25149     int gpkg_amphibious = 0;
25150     int gpkg_mode = 0;
25151     struct splite_internal_cache *cache = sqlite3_user_data (context);
25152     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25153     if (cache != NULL)
25154       {
25155 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25156 	  gpkg_mode = cache->gpkg_mode;
25157       }
25158     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25159       {
25160 	  sqlite3_result_null (context);
25161 	  return;
25162       }
25163     if (argc == 2)
25164       {
25165 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25166 	    {
25167 		sqlite3_result_null (context);
25168 		return;
25169 	    }
25170 	  ignore_repeated_vertices = sqlite3_value_int (argv[1]);
25171       }
25172     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25173     n_bytes = sqlite3_value_bytes (argv[0]);
25174     geo =
25175 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25176 				     gpkg_amphibious);
25177     if (!geo)
25178       {
25179 	  sqlite3_result_null (context);
25180 	  return;
25181       }
25182     if (!is_single_linestring (geo))
25183       {
25184 	  gaiaFreeGeomColl (geo);
25185 	  sqlite3_result_null (context);
25186 	  return;
25187       }
25188 
25189     ln = geo->FirstLinestring;
25190     for (iv = 0; iv < ln->Points; iv++)
25191       {
25192 	  if (geo->DimensionModel == GAIA_XY_Z)
25193 	    {
25194 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
25195 	    }
25196 	  else if (geo->DimensionModel == GAIA_XY_M)
25197 	    {
25198 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
25199 	    }
25200 	  else if (geo->DimensionModel == GAIA_XY_Z_M)
25201 	    {
25202 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
25203 	    }
25204 	  else
25205 	    {
25206 		gaiaGetPoint (ln->Coords, iv, &x, &y);
25207 	    }
25208 	  if (iv > 0)
25209 	    {
25210 		int ok = 1;
25211 		if (ignore_repeated_vertices)
25212 		  {
25213 		      if (last_x == x && last_y == y)
25214 			  ok = 0;
25215 		  }
25216 		if (ok)
25217 		  {
25218 		      double l =
25219 			  sqrt (((last_x - x) * (last_x - x)) +
25220 				((last_y - y) * (last_y - y)));
25221 		      if (l < min)
25222 			  min = l;
25223 		      if (l > max)
25224 			  max = l;
25225 		      tot += l;
25226 		      n++;
25227 		  }
25228 	    }
25229 	  last_x = x;
25230 	  last_y = y;
25231       }
25232     if (mode == LINESTRING_MIN_SEGMENT_LENGTH)
25233 	sqlite3_result_double (context, min);
25234     else if (mode == LINESTRING_MAX_SEGMENT_LENGTH)
25235 	sqlite3_result_double (context, max);
25236     else
25237 	sqlite3_result_double (context, tot / (double) n);
25238 }
25239 
25240 static void
fnct_LinestringMinSegmentLength(sqlite3_context * context,int argc,sqlite3_value ** argv)25241 fnct_LinestringMinSegmentLength (sqlite3_context * context, int argc,
25242 				 sqlite3_value ** argv)
25243 {
25244 /* SQL function:
25245 / ST_LinestringMinSegmentLength(BLOB encoded LINESTRING)
25246 / ST_LinestringMinSegmentLength(BLOB encoded LINESTRING, BOOL ignore_repeated_vertices)
25247 /
25248 / returns the length of the shortest segment in the Linestring
25249 / or NULL if any error is encountered
25250 /
25251 */
25252     linestring_segment_length_common (context, argc, argv,
25253 				      LINESTRING_MIN_SEGMENT_LENGTH);
25254 }
25255 
25256 static void
fnct_LinestringMaxSegmentLength(sqlite3_context * context,int argc,sqlite3_value ** argv)25257 fnct_LinestringMaxSegmentLength (sqlite3_context * context, int argc,
25258 				 sqlite3_value ** argv)
25259 {
25260 /* SQL function:
25261 / ST_LinsetringMaxSegmentLength(BLOB encoded LINESTRING)
25262 /
25263 / returns the length of the longest segment in the Linestring
25264 / or NULL if any error is encountered
25265 /
25266 */
25267     linestring_segment_length_common (context, argc, argv,
25268 				      LINESTRING_MAX_SEGMENT_LENGTH);
25269 }
25270 
25271 static void
fnct_LinestringAvgSegmentLength(sqlite3_context * context,int argc,sqlite3_value ** argv)25272 fnct_LinestringAvgSegmentLength (sqlite3_context * context, int argc,
25273 				 sqlite3_value ** argv)
25274 {
25275 /* SQL function:
25276 / ST_LinestringMaxSegmentLength(BLOB encoded LINESTRING)
25277 /
25278 / returns the average segment length in the Linsetring
25279 / or NULL if any error is encountered
25280 /
25281 */
25282     linestring_segment_length_common (context, argc, argv,
25283 				      LINESTRING_AVG_SEGMENT_LENGTH);
25284 }
25285 
25286 static void
fnct_CurvosityIndex(sqlite3_context * context,int argc,sqlite3_value ** argv)25287 fnct_CurvosityIndex (sqlite3_context * context, int argc, sqlite3_value ** argv)
25288 {
25289 /* SQL function:
25290 / ST_CurvosityIndex(BLOB encoded LINESTRING)
25291 /    or
25292 / ST_CurvosityIndex(BLOB encoded LINESTRING, points INTEGER)
25293 /
25294 / returns the CurvosityIndex of some Linestring
25295 / or NULL if any error is encountered
25296 /
25297 */
25298     unsigned char *p_blob;
25299     int n_bytes;
25300     int extra_points = 0;
25301     double index;
25302     gaiaLinestringPtr ln;
25303     gaiaGeomCollPtr geo = NULL;
25304     int gpkg_amphibious = 0;
25305     int gpkg_mode = 0;
25306     struct splite_internal_cache *cache = sqlite3_user_data (context);
25307     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25308     if (cache != NULL)
25309       {
25310 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25311 	  gpkg_mode = cache->gpkg_mode;
25312       }
25313     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25314       {
25315 	  sqlite3_result_null (context);
25316 	  return;
25317       }
25318     if (argc == 2)
25319       {
25320 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25321 	    {
25322 		sqlite3_result_null (context);
25323 		return;
25324 	    }
25325 	  extra_points = sqlite3_value_int (argv[1]);
25326       }
25327     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25328     n_bytes = sqlite3_value_bytes (argv[0]);
25329     geo =
25330 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25331 				     gpkg_amphibious);
25332     if (!geo)
25333       {
25334 	  sqlite3_result_null (context);
25335 	  return;
25336       }
25337     if (!is_single_linestring (geo))
25338       {
25339 	  gaiaFreeGeomColl (geo);
25340 	  sqlite3_result_null (context);
25341 	  return;
25342       }
25343 
25344     ln = geo->FirstLinestring;
25345     index = gaiaCurvosityIndex (cache, ln, extra_points);
25346     sqlite3_result_double (context, index);
25347 }
25348 
25349 static void
fnct_UphillHeight(sqlite3_context * context,int argc,sqlite3_value ** argv)25350 fnct_UphillHeight (sqlite3_context * context, int argc, sqlite3_value ** argv)
25351 {
25352 /* SQL function:
25353 / ST_UphillHeight(BLOB encoded LINESTRING)
25354 /
25355 / returns the cumulative Uphill Height of some 3D Linestring
25356 / or NULL if any error is encountered
25357 /
25358 */
25359     unsigned char *p_blob;
25360     int n_bytes;
25361     double up;
25362     double down;
25363     gaiaLinestringPtr ln;
25364     gaiaGeomCollPtr geo = NULL;
25365     int gpkg_amphibious = 0;
25366     int gpkg_mode = 0;
25367     struct splite_internal_cache *cache = sqlite3_user_data (context);
25368     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25369     if (cache != NULL)
25370       {
25371 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25372 	  gpkg_mode = cache->gpkg_mode;
25373       }
25374     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25375       {
25376 	  sqlite3_result_null (context);
25377 	  return;
25378       }
25379     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25380     n_bytes = sqlite3_value_bytes (argv[0]);
25381     geo =
25382 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25383 				     gpkg_amphibious);
25384     if (!geo)
25385       {
25386 	  sqlite3_result_null (context);
25387 	  return;
25388       }
25389     if (!is_single_linestring (geo))
25390       {
25391 	  gaiaFreeGeomColl (geo);
25392 	  sqlite3_result_null (context);
25393 	  return;
25394       }
25395 
25396     ln = geo->FirstLinestring;
25397     gaiaUpDownHeight (ln, &up, &down);
25398     sqlite3_result_double (context, up);
25399 }
25400 
25401 static void
fnct_DownhillHeight(sqlite3_context * context,int argc,sqlite3_value ** argv)25402 fnct_DownhillHeight (sqlite3_context * context, int argc, sqlite3_value ** argv)
25403 {
25404 /* SQL function:
25405 / ST_DownhillHeight(BLOB encoded LINESTRING)
25406 /
25407 / returns the cumulative Downhill Height of some 3D Linestring
25408 / or NULL if any error is encountered
25409 /
25410 */
25411     unsigned char *p_blob;
25412     int n_bytes;
25413     double up;
25414     double down;
25415     gaiaLinestringPtr ln;
25416     gaiaGeomCollPtr geo = NULL;
25417     int gpkg_amphibious = 0;
25418     int gpkg_mode = 0;
25419     struct splite_internal_cache *cache = sqlite3_user_data (context);
25420     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25421     if (cache != NULL)
25422       {
25423 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25424 	  gpkg_mode = cache->gpkg_mode;
25425       }
25426     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25427       {
25428 	  sqlite3_result_null (context);
25429 	  return;
25430       }
25431     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25432     n_bytes = sqlite3_value_bytes (argv[0]);
25433     geo =
25434 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25435 				     gpkg_amphibious);
25436     if (!geo)
25437       {
25438 	  sqlite3_result_null (context);
25439 	  return;
25440       }
25441     if (!is_single_linestring (geo))
25442       {
25443 	  gaiaFreeGeomColl (geo);
25444 	  sqlite3_result_null (context);
25445 	  return;
25446       }
25447 
25448     ln = geo->FirstLinestring;
25449     gaiaUpDownHeight (ln, &up, &down);
25450     sqlite3_result_double (context, down);
25451 }
25452 
25453 static void
fnct_UpDownHeight(sqlite3_context * context,int argc,sqlite3_value ** argv)25454 fnct_UpDownHeight (sqlite3_context * context, int argc, sqlite3_value ** argv)
25455 {
25456 /* SQL function:
25457 / ST_UpDownHeight(BLOB encoded LINESTRING)
25458 /
25459 / returns the cumulative UpDown Height of some 3D Linestring
25460 / or NULL if any error is encountered
25461 /
25462 */
25463     unsigned char *p_blob;
25464     int n_bytes;
25465     double up;
25466     double down;
25467     gaiaLinestringPtr ln;
25468     gaiaGeomCollPtr geo = NULL;
25469     int gpkg_amphibious = 0;
25470     int gpkg_mode = 0;
25471     struct splite_internal_cache *cache = sqlite3_user_data (context);
25472     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25473     if (cache != NULL)
25474       {
25475 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25476 	  gpkg_mode = cache->gpkg_mode;
25477       }
25478     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25479       {
25480 	  sqlite3_result_null (context);
25481 	  return;
25482       }
25483     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25484     n_bytes = sqlite3_value_bytes (argv[0]);
25485     geo =
25486 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25487 				     gpkg_amphibious);
25488     if (!geo)
25489       {
25490 	  sqlite3_result_null (context);
25491 	  return;
25492       }
25493     if (!is_single_linestring (geo))
25494       {
25495 	  gaiaFreeGeomColl (geo);
25496 	  sqlite3_result_null (context);
25497 	  return;
25498       }
25499 
25500     ln = geo->FirstLinestring;
25501     gaiaUpDownHeight (ln, &up, &down);
25502     sqlite3_result_double (context, up + down);
25503 }
25504 
25505 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
25506 
25507 static void
fnct_3dLength(sqlite3_context * context,int argc,sqlite3_value ** argv)25508 fnct_3dLength (sqlite3_context * context, int argc, sqlite3_value ** argv)
25509 {
25510 /* SQL function:
25511 / ST_3dLength(BLOB encoded GEOMETRYCOLLECTION)
25512 /
25513 / returns  the total 2D or 3D length for current geometry
25514 / accordingly to the Geometry dimensions
25515 / returns NULL if any error is encountered
25516 /
25517 / Please note: this function will ignore
25518 / any Polygon (only Linestrings will be considered)
25519 /
25520 */
25521     unsigned char *p_blob;
25522     int n_bytes;
25523     double length = 0.0;
25524     int ret;
25525     gaiaGeomCollPtr geo = NULL;
25526     int gpkg_amphibious = 0;
25527     int gpkg_mode = 0;
25528     struct splite_internal_cache *cache = sqlite3_user_data (context);
25529     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25530     if (cache != NULL)
25531       {
25532 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25533 	  gpkg_mode = cache->gpkg_mode;
25534       }
25535     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25536       {
25537 	  sqlite3_result_null (context);
25538 	  return;
25539       }
25540     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25541     n_bytes = sqlite3_value_bytes (argv[0]);
25542     geo =
25543 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25544 				     gpkg_amphibious);
25545     if (!geo)
25546 	sqlite3_result_null (context);
25547     else
25548       {
25549 	  ret = gaia3dLength (cache, geo, &length);
25550 	  if (!ret)
25551 	      sqlite3_result_null (context);
25552 	  else
25553 	      sqlite3_result_double (context, length);
25554       }
25555     gaiaFreeGeomColl (geo);
25556 }
25557 
25558 static void
fnct_FromTWKB(sqlite3_context * context,int argc,sqlite3_value ** argv)25559 fnct_FromTWKB (sqlite3_context * context, int argc, sqlite3_value ** argv)
25560 {
25561 /* SQL function:
25562 / GeomFromTWKB(TWKB encoded geometry)
25563 /   or
25564 / GeomFromTWKB(TWKB encoded geometry, INT srid)
25565 /
25566 / returns the current geometry by parsing a TWKB encoded string
25567 / or NULL if any error is encountered
25568 */
25569     int len;
25570     unsigned char *p_result = NULL;
25571     const unsigned char *twkb;
25572     int twkb_size;
25573     int srid = -1;
25574     gaiaGeomCollPtr geo = NULL;
25575     int gpkg_mode = 0;
25576     int tiny_point = 0;
25577     struct splite_internal_cache *cache = sqlite3_user_data (context);
25578     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25579     if (cache != NULL)
25580       {
25581 	  gpkg_mode = cache->gpkg_mode;
25582 	  tiny_point = cache->tinyPointEnabled;
25583       }
25584     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25585       {
25586 	  sqlite3_result_null (context);
25587 	  return;
25588       }
25589     else
25590       {
25591 	  twkb = sqlite3_value_blob (argv[0]);
25592 	  twkb_size = sqlite3_value_bytes (argv[0]);
25593       }
25594     if (argc >= 2)
25595       {
25596 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25597 	    {
25598 		sqlite3_result_null (context);
25599 		return;
25600 	    }
25601 	  srid = sqlite3_value_int (argv[1]);
25602 	  if (srid < 0)
25603 	      srid = -1;
25604       }
25605     geo = gaiaFromTWKB (cache, twkb, twkb_size, srid);
25606     if (geo == NULL)
25607       {
25608 	  sqlite3_result_null (context);
25609 	  return;
25610       }
25611     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &len, gpkg_mode, tiny_point);
25612     gaiaFreeGeomColl (geo);
25613     sqlite3_result_blob (context, p_result, len, free);
25614 }
25615 
25616 static void
fnct_ToTWKB(sqlite3_context * context,int argc,sqlite3_value ** argv)25617 fnct_ToTWKB (sqlite3_context * context, int argc, sqlite3_value ** argv)
25618 {
25619 /* SQL function:
25620 / AsTWKB(BLOB encoded geometry)
25621 /   or
25622 / AsTWKB(BLOB encoded geometry, INT precision_xy)
25623 /   or
25624 / AsTWKB(BLOB encoded geometry, INT precision_xy, INT precision_z)
25625 /   or
25626 / AsTWKB(BLOB encoded geometry, INT precision_xy, INT precision_z,
25627 /        INT precision_m)
25628 /   or
25629 / AsTWKB(BLOB encoded geometry, INT precision_xy, INT precision_z,
25630 /        INT precision_m, INT with_size)
25631 /   or
25632 / AsTWKB(BLOB encoded geometry, INT precision_xy, INT precision_z,
25633 /        INT precision_m, INT with_size, INT with_bbox)
25634 /
25635 / returns a text string corresponding to compressed TWKB notation
25636 / or NULL if any error is encountered
25637 */
25638     unsigned char *p_blob;
25639     int n_bytes;
25640     int value;
25641     unsigned char precision_xy = 0;
25642     unsigned char precision_z = 0;
25643     unsigned char precision_m = 0;
25644     int with_size = 0;
25645     int with_bbox = 0;
25646     int ret;
25647     gaiaGeomCollPtr geo = NULL;
25648     int gpkg_amphibious = 0;
25649     int gpkg_mode = 0;
25650     struct splite_internal_cache *cache = sqlite3_user_data (context);
25651     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25652     if (cache != NULL)
25653       {
25654 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25655 	  gpkg_mode = cache->gpkg_mode;
25656       }
25657     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25658       {
25659 	  sqlite3_result_null (context);
25660 	  return;
25661       }
25662     else
25663       {
25664 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25665 	  n_bytes = sqlite3_value_bytes (argv[0]);
25666       }
25667     if (argc >= 2)
25668       {
25669 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25670 	    {
25671 		sqlite3_result_null (context);
25672 		return;
25673 	    }
25674 	  value = sqlite3_value_int (argv[1]);
25675 	  if (value < 0)
25676 	      precision_xy = 0;
25677 	  else if (value > 20)
25678 	      precision_xy = 20;
25679 	  else
25680 	      precision_xy = value;
25681       }
25682     if (argc >= 3)
25683       {
25684 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
25685 	    {
25686 		sqlite3_result_null (context);
25687 		return;
25688 	    }
25689 	  value = sqlite3_value_int (argv[2]);
25690 	  if (value < 0)
25691 	      precision_z = 0;
25692 	  else if (value > 20)
25693 	      precision_z = 20;
25694 	  else
25695 	      precision_z = value;
25696       }
25697     if (argc >= 4)
25698       {
25699 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
25700 	    {
25701 		sqlite3_result_null (context);
25702 		return;
25703 	    }
25704 	  value = sqlite3_value_int (argv[3]);
25705 	  if (value < 0)
25706 	      precision_m = 0;
25707 	  else if (value > 20)
25708 	      precision_m = 20;
25709 	  else
25710 	      precision_m = value;
25711       }
25712     if (argc >= 5)
25713       {
25714 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
25715 	    {
25716 		sqlite3_result_null (context);
25717 		return;
25718 	    }
25719 	  with_size = sqlite3_value_int (argv[4]);
25720 	  if (with_size != 0)
25721 	      with_size = 1;
25722       }
25723     if (argc >= 6)
25724       {
25725 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
25726 	    {
25727 		sqlite3_result_null (context);
25728 		return;
25729 	    }
25730 	  with_bbox = sqlite3_value_int (argv[5]);
25731 	  if (with_bbox != 0)
25732 	      with_bbox = 1;
25733       }
25734     geo =
25735 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25736 				     gpkg_amphibious);
25737     if (!geo)
25738 	sqlite3_result_null (context);
25739     else
25740       {
25741 	  unsigned char *twkb;
25742 	  int size_twkb;
25743 	  ret =
25744 	      gaiaToTWKB (cache, geo, precision_xy, precision_z, precision_m,
25745 			  with_size, with_bbox, &twkb, &size_twkb);
25746 	  if (!ret)
25747 	      sqlite3_result_null (context);
25748 	  else
25749 	      sqlite3_result_blob (context, twkb, size_twkb, free);
25750       }
25751     gaiaFreeGeomColl (geo);
25752 }
25753 
25754 static void
fnct_AsEncodedPolyline(sqlite3_context * context,int argc,sqlite3_value ** argv)25755 fnct_AsEncodedPolyline (sqlite3_context * context, int argc,
25756 			sqlite3_value ** argv)
25757 {
25758 /* SQL function:
25759 / ST_AsEncodedPolyline(BLOB encoded geometry)
25760 /   or
25761 / ST_AsEncodedPolyline(BLOB encoded geometry, INT precision)
25762 /
25763 / returns a text string corresponding to GoogleMaps encoded Polyline
25764 / or NULL if any error is encountered
25765 */
25766     unsigned char *p_blob;
25767     int n_bytes;
25768     int value;
25769     unsigned char precision = 5;
25770     int ret;
25771     gaiaGeomCollPtr geo = NULL;
25772     int gpkg_amphibious = 0;
25773     int gpkg_mode = 0;
25774     struct splite_internal_cache *cache = sqlite3_user_data (context);
25775     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25776     sqlite3 *sqlite = sqlite3_context_db_handle (context);
25777     if (cache != NULL)
25778       {
25779 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25780 	  gpkg_mode = cache->gpkg_mode;
25781       }
25782     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25783       {
25784 	  sqlite3_result_null (context);
25785 	  return;
25786       }
25787     else
25788       {
25789 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25790 	  n_bytes = sqlite3_value_bytes (argv[0]);
25791       }
25792     if (argc >= 2)
25793       {
25794 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25795 	    {
25796 		sqlite3_result_null (context);
25797 		return;
25798 	    }
25799 	  value = sqlite3_value_int (argv[1]);
25800 	  if (value < 0)
25801 	      precision = 0;
25802 	  else if (value > 20)
25803 	      precision = 20;
25804 	  else
25805 	      precision = value;
25806       }
25807     geo =
25808 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25809 				     gpkg_amphibious);
25810     if (!geo)
25811 	sqlite3_result_null (context);
25812     else
25813       {
25814 	  int invalid = 0;
25815 	  int geographic = 0;
25816 	  char *encoded;
25817 	  int size_encoded;
25818 	  if (geo->FirstPoint == NULL && geo->FirstPolygon == NULL
25819 	      && geo->FirstLinestring != NULL
25820 	      && geo->FirstLinestring == geo->LastLinestring)
25821 	      ;
25822 	  else
25823 	      invalid = 1;
25824 	  if (!srid_is_geographic (sqlite, geo->Srid, &geographic))
25825 	      invalid = 1;
25826 	  if (!geographic)
25827 	      invalid = 1;
25828 	  if (invalid)
25829 	    {
25830 		gaiaFreeGeomColl (geo);
25831 		sqlite3_result_null (context);
25832 		return;
25833 	    }
25834 	  ret =
25835 	      gaiaAsEncodedPolyLine (cache, geo, precision, &encoded,
25836 				     &size_encoded);
25837 	  if (!ret)
25838 	      sqlite3_result_null (context);
25839 	  else
25840 	      sqlite3_result_text (context, encoded, size_encoded, free);
25841       }
25842     gaiaFreeGeomColl (geo);
25843 }
25844 
25845 static void
fnct_LineFromEncodedPolyline(sqlite3_context * context,int argc,sqlite3_value ** argv)25846 fnct_LineFromEncodedPolyline (sqlite3_context * context, int argc,
25847 			      sqlite3_value ** argv)
25848 {
25849 /* SQL function:
25850 / ST_LineFromEncodedPolyline(TEXT encoded geometry)
25851 /   or
25852 / ST_LineFromEncodedPolyline(TEXT encoded geometry, INT precision)
25853 /
25854 / returns a Linestring Geometry from a text string corresponding to
25855 / GoogleMaps encoded Polyline
25856 / or NULL if any error is encountered
25857 */
25858     unsigned char *p_result = NULL;
25859     int size;
25860     const char *encoded;
25861     gaiaGeomCollPtr geo = NULL;
25862     int value;
25863     unsigned char precision = 5;
25864     int gpkg_mode = 0;
25865     struct splite_internal_cache *cache = sqlite3_user_data (context);
25866     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25867     if (cache != NULL)
25868 	gpkg_mode = cache->gpkg_mode;
25869     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
25870       {
25871 	  sqlite3_result_null (context);
25872 	  return;
25873       }
25874     else
25875 	encoded = (const char *) sqlite3_value_text (argv[0]);
25876     if (argc >= 2)
25877       {
25878 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25879 	    {
25880 		sqlite3_result_null (context);
25881 		return;
25882 	    }
25883 	  value = sqlite3_value_int (argv[1]);
25884 	  if (value < 0)
25885 	      precision = 0;
25886 	  else if (value > 20)
25887 	      precision = 20;
25888 	  else
25889 	      precision = value;
25890       }
25891     geo = gaiaLineFromEncodedPolyline (cache, encoded, precision);
25892     if (geo == NULL)
25893       {
25894 	  sqlite3_result_null (context);
25895 	  return;
25896       }
25897     gaiaToSpatiaLiteBlobWkbEx2 (geo, &p_result, &size, gpkg_mode, 0);
25898     gaiaFreeGeomColl (geo);
25899     sqlite3_result_blob (context, p_result, size, free);
25900 }
25901 
25902 #endif /* end RTTOPO conditional */
25903 
25904 static void
fnct_Area(sqlite3_context * context,int argc,sqlite3_value ** argv)25905 fnct_Area (sqlite3_context * context, int argc, sqlite3_value ** argv)
25906 {
25907 /* SQL function:
25908 / Area(BLOB encoded GEOMETRYCOLLECTION)
25909 /
25910 / returns the total area for current geometry
25911 / or NULL if any error is encountered
25912 */
25913     unsigned char *p_blob;
25914     int n_bytes;
25915     double area = 0.0;
25916     int ret;
25917     int use_ellipsoid = -1;
25918 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
25919     double a;
25920     double b;
25921     double rf;
25922     sqlite3 *sqlite = sqlite3_context_db_handle (context);
25923 #endif /* end RTTOPO conditional */
25924     gaiaGeomCollPtr geo = NULL;
25925     int gpkg_amphibious = 0;
25926     int gpkg_mode = 0;
25927     struct splite_internal_cache *cache = sqlite3_user_data (context);
25928     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
25929     if (cache != NULL)
25930       {
25931 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
25932 	  gpkg_mode = cache->gpkg_mode;
25933       }
25934     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
25935       {
25936 	  sqlite3_result_null (context);
25937 	  return;
25938       }
25939     if (argc == 2)
25940       {
25941 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
25942 	    {
25943 		sqlite3_result_null (context);
25944 		return;
25945 	    }
25946 	  use_ellipsoid = sqlite3_value_int (argv[1]);
25947 	  if (use_ellipsoid != 0)
25948 	      use_ellipsoid = 1;
25949       }
25950     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
25951     n_bytes = sqlite3_value_bytes (argv[0]);
25952     geo =
25953 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
25954 				     gpkg_amphibious);
25955     if (!geo)
25956 	sqlite3_result_null (context);
25957     else
25958       {
25959 	  if (use_ellipsoid >= 0)
25960 	    {
25961 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
25962 		/* attempting to identify the corresponding ellipsoid */
25963 		if (getEllipsoidParams (sqlite, geo->Srid, &a, &b, &rf))
25964 		    ret =
25965 			gaiaGeodesicArea (cache, geo, a, b, use_ellipsoid,
25966 					  &area);
25967 		else
25968 		    ret = 0;
25969 #else
25970 		ret = 0;
25971 #endif /* end RTTOPO conditional */
25972 	    }
25973 	  else
25974 	    {
25975 		void *data = sqlite3_user_data (context);
25976 		if (data != NULL)
25977 		    ret = gaiaGeomCollArea_r (data, geo, &area);
25978 		else
25979 		    ret = gaiaGeomCollArea (geo, &area);
25980 	    }
25981 	  if (!ret)
25982 	      sqlite3_result_null (context);
25983 	  else
25984 	      sqlite3_result_double (context, area);
25985       }
25986     gaiaFreeGeomColl (geo);
25987 }
25988 
25989 static gaiaGeomCollPtr
circularity_polygon(int srid,int dims,gaiaPolygonPtr pg)25990 circularity_polygon (int srid, int dims, gaiaPolygonPtr pg)
25991 {
25992 /* building an individual Polygon for Circularity */
25993     gaiaGeomCollPtr geom = NULL;
25994     gaiaPolygonPtr pg2;
25995     gaiaRingPtr i_rng;
25996     gaiaRingPtr o_rng;
25997     if (dims == GAIA_XY_Z)
25998 	geom = gaiaAllocGeomCollXYZ ();
25999     else if (dims == GAIA_XY_M)
26000 	geom = gaiaAllocGeomCollXYM ();
26001     else if (dims == GAIA_XY_Z_M)
26002 	geom = gaiaAllocGeomCollXYZM ();
26003     else
26004 	geom = gaiaAllocGeomColl ();
26005     geom->Srid = srid;
26006     i_rng = pg->Exterior;
26007     pg2 = gaiaAddPolygonToGeomColl (geom, i_rng->Points, 0);
26008     o_rng = pg2->Exterior;
26009     /* copying points (only EXTERIOR RING) */
26010     gaiaCopyRingCoords (o_rng, i_rng);
26011     return geom;
26012 }
26013 
26014 static void
fnct_Circularity(sqlite3_context * context,int argc,sqlite3_value ** argv)26015 fnct_Circularity (sqlite3_context * context, int argc, sqlite3_value ** argv)
26016 {
26017 /* SQL function:
26018 / Circularity(BLOB encoded GEOMETRYCOLLECTION)
26019 /
26020 / returns the Circularity Index for current geometry
26021 / or NULL if any error is encountered
26022 */
26023     unsigned char *p_blob;
26024     int n_bytes;
26025     double pi = 3.14159265358979323846;
26026     double area = 0.0;
26027     double perimeter = 0.0;
26028     double sum_area = 0.0;
26029     double sum_perimeter = 0.0;
26030     int nlns = 0;
26031     int npgs = 0;
26032     int ret;
26033     int use_ellipsoid = -1;
26034 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
26035     double a;
26036     double b;
26037     double rf;
26038     sqlite3 *sqlite = sqlite3_context_db_handle (context);
26039 #endif /* end RTTOPO conditional */
26040     gaiaGeomCollPtr geo = NULL;
26041     gaiaLinestringPtr ln;
26042     gaiaPolygonPtr pg;
26043     int gpkg_amphibious = 0;
26044     int gpkg_mode = 0;
26045     struct splite_internal_cache *cache = sqlite3_user_data (context);
26046     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26047     if (cache != NULL)
26048       {
26049 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26050 	  gpkg_mode = cache->gpkg_mode;
26051       }
26052     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26053       {
26054 	  sqlite3_result_null (context);
26055 	  return;
26056       }
26057     if (argc == 2)
26058       {
26059 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
26060 	    {
26061 		sqlite3_result_null (context);
26062 		return;
26063 	    }
26064 	  use_ellipsoid = sqlite3_value_int (argv[1]);
26065 	  if (use_ellipsoid != 0)
26066 	      use_ellipsoid = 1;
26067       }
26068     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26069     n_bytes = sqlite3_value_bytes (argv[0]);
26070     geo =
26071 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26072 				     gpkg_amphibious);
26073     if (!geo)
26074 	sqlite3_result_null (context);
26075     else
26076       {
26077 	  void *data = sqlite3_user_data (context);
26078 	  if (use_ellipsoid >= 0)
26079 	    {
26080 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
26081 		/* attempting to identify the corresponding ellipsoid */
26082 		if (getEllipsoidParams (sqlite, geo->Srid, &a, &b, &rf))
26083 		    ret = 1;
26084 		else
26085 		    ret = 0;
26086 #else
26087 		ret = 0;
26088 #endif /* end RTTOPO conditional */
26089 		if (!ret)
26090 		  {
26091 		      sqlite3_result_null (context);
26092 		      goto end;
26093 		  }
26094 	    }
26095 	  ln = geo->FirstLinestring;
26096 	  while (ln != NULL)
26097 	    {
26098 		nlns++;
26099 		ln = ln->Next;
26100 	    }
26101 
26102 	  pg = geo->FirstPolygon;
26103 	  while (pg != NULL)
26104 	    {
26105 		/* looping on individual polygons */
26106 		gaiaGeomCollPtr geo2 =
26107 		    circularity_polygon (geo->Srid, geo->DimensionModel, pg);
26108 		if (use_ellipsoid >= 0)
26109 		  {
26110 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
26111 		      /* attempting to identify the corresponding ellipsoid */
26112 		      ret =
26113 			  gaiaGeodesicArea (cache, geo2, a, b, use_ellipsoid,
26114 					    &area);
26115 #else
26116 		      ret = 0;
26117 #endif /* end RTTOPO conditional */
26118 		  }
26119 		else
26120 		  {
26121 		      if (data != NULL)
26122 			  ret = gaiaGeomCollArea_r (data, geo2, &area);
26123 		      else
26124 			  ret = gaiaGeomCollArea (geo2, &area);
26125 		  }
26126 		if (ret)
26127 		  {
26128 		      sum_area += area;
26129 		      npgs++;
26130 		  }
26131 		else
26132 		  {
26133 		      gaiaFreeGeomColl (geo2);
26134 		      npgs = 0;
26135 		      break;
26136 		  }
26137 
26138 		if (use_ellipsoid >= 0)
26139 		  {
26140 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
26141 		      perimeter = gaiaGeodesicTotalLength (a, b, rf,
26142 							   pg->
26143 							   Exterior->DimensionModel,
26144 							   pg->Exterior->Coords,
26145 							   pg->
26146 							   Exterior->Points);
26147 		      if (perimeter < 0.0)
26148 			  ret = 0;
26149 		      else
26150 			  ret = 1;
26151 #else
26152 		      ret = 0;
26153 #endif /* end RTTOPO conditional */
26154 		  }
26155 		else
26156 		  {
26157 		      if (data != NULL)
26158 			  ret =
26159 			      gaiaGeomCollLengthOrPerimeter_r (data, geo2, 1,
26160 							       &perimeter);
26161 		      else
26162 			  ret =
26163 			      gaiaGeomCollLengthOrPerimeter (geo2, 1,
26164 							     &perimeter);
26165 		  }
26166 		if (ret)
26167 		    sum_perimeter += perimeter;
26168 		else
26169 		  {
26170 		      gaiaFreeGeomColl (geo2);
26171 		      npgs = 0;
26172 		      break;
26173 		  }
26174 		gaiaFreeGeomColl (geo2);
26175 		pg = pg->Next;
26176 	    }
26177 	  if (!npgs)
26178 	    {
26179 		if (nlns)
26180 		    sqlite3_result_double (context, 0.0);
26181 		else
26182 		    sqlite3_result_null (context);
26183 	    }
26184 	  else
26185 	    {
26186 		double index =
26187 		    (4.0 * pi * sum_area) / (sum_perimeter * sum_perimeter);
26188 		sqlite3_result_double (context, index);
26189 	    }
26190       }
26191   end:
26192     gaiaFreeGeomColl (geo);
26193 }
26194 
26195 static void
fnct_Centroid(sqlite3_context * context,int argc,sqlite3_value ** argv)26196 fnct_Centroid (sqlite3_context * context, int argc, sqlite3_value ** argv)
26197 {
26198 /* SQL function:
26199 / Centroid(BLOBencoded POLYGON or MULTIPOLYGON geometry)
26200 /
26201 / returns a POINT representing the centroid for current POLYGON / MULTIPOLYGON geometry
26202 / or NULL if any error is encountered
26203 */
26204     unsigned char *p_blob;
26205     int n_bytes;
26206     int len;
26207     int ret;
26208     double x;
26209     double y;
26210     unsigned char *p_result = NULL;
26211     gaiaGeomCollPtr geo = NULL;
26212     gaiaGeomCollPtr result;
26213     int gpkg_amphibious = 0;
26214     int gpkg_mode = 0;
26215     int tiny_point = 0;
26216     struct splite_internal_cache *cache = sqlite3_user_data (context);
26217     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26218     if (cache != NULL)
26219       {
26220 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26221 	  gpkg_mode = cache->gpkg_mode;
26222 	  tiny_point = cache->tinyPointEnabled;
26223       }
26224     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26225       {
26226 	  sqlite3_result_null (context);
26227 	  return;
26228       }
26229     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26230     n_bytes = sqlite3_value_bytes (argv[0]);
26231     geo =
26232 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26233 				     gpkg_amphibious);
26234     if (!geo)
26235 	sqlite3_result_null (context);
26236     else
26237       {
26238 	  if (gaiaIsEmpty (geo))
26239 	      sqlite3_result_null (context);
26240 	  else
26241 	    {
26242 		void *data = sqlite3_user_data (context);
26243 		if (data != NULL)
26244 		    ret = gaiaGeomCollCentroid_r (data, geo, &x, &y);
26245 		else
26246 		    ret = gaiaGeomCollCentroid (geo, &x, &y);
26247 		if (!ret)
26248 		    sqlite3_result_null (context);
26249 		else
26250 		  {
26251 		      result = gaiaAllocGeomColl ();
26252 		      result->Srid = geo->Srid;
26253 		      gaiaAddPointToGeomColl (result, x, y);
26254 		      gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26255 						  gpkg_mode, tiny_point);
26256 		      gaiaFreeGeomColl (result);
26257 		      sqlite3_result_blob (context, p_result, len, free);
26258 		  }
26259 	    }
26260       }
26261     gaiaFreeGeomColl (geo);
26262 }
26263 
26264 static void
fnct_PointOnSurface(sqlite3_context * context,int argc,sqlite3_value ** argv)26265 fnct_PointOnSurface (sqlite3_context * context, int argc, sqlite3_value ** argv)
26266 {
26267 /* SQL function:
26268 / PointOnSurface(BLOBencoded POLYGON or MULTIPOLYGON geometry)
26269 /
26270 / returns a POINT guaranteed to lie on the Surface
26271 / or NULL if any error is encountered
26272 */
26273     unsigned char *p_blob;
26274     int n_bytes;
26275     int len;
26276     double x;
26277     double y;
26278     unsigned char *p_result = NULL;
26279     gaiaGeomCollPtr geo = NULL;
26280     gaiaGeomCollPtr result;
26281     int gpkg_amphibious = 0;
26282     int gpkg_mode = 0;
26283     int tiny_point = 0;
26284     struct splite_internal_cache *cache = sqlite3_user_data (context);
26285     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26286     if (cache != NULL)
26287       {
26288 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26289 	  gpkg_mode = cache->gpkg_mode;
26290 	  tiny_point = cache->tinyPointEnabled;
26291       }
26292     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26293       {
26294 	  sqlite3_result_null (context);
26295 	  return;
26296       }
26297     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26298     n_bytes = sqlite3_value_bytes (argv[0]);
26299     geo =
26300 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26301 				     gpkg_amphibious);
26302     if (!geo)
26303 	sqlite3_result_null (context);
26304     else
26305       {
26306 	  void *data = sqlite3_user_data (context);
26307 	  int posret;
26308 	  if (data != NULL)
26309 	      posret = gaiaGetPointOnSurface_r (data, geo, &x, &y);
26310 	  else
26311 	      posret = gaiaGetPointOnSurface (geo, &x, &y);
26312 	  if (!posret)
26313 	      sqlite3_result_null (context);
26314 	  else
26315 	    {
26316 		if (geo->DimensionModel == GAIA_XY_Z)
26317 		  {
26318 		      result = gaiaAllocGeomCollXYZ ();
26319 		      gaiaAddPointToGeomCollXYZ (result, x, y, 0.0);
26320 		  }
26321 		else if (geo->DimensionModel == GAIA_XY_M)
26322 		  {
26323 		      result = gaiaAllocGeomCollXYM ();
26324 		      gaiaAddPointToGeomCollXYM (result, x, y, 0.0);
26325 		  }
26326 		else if (geo->DimensionModel == GAIA_XY_Z_M)
26327 		  {
26328 		      result = gaiaAllocGeomCollXYZM ();
26329 		      gaiaAddPointToGeomCollXYZM (result, x, y, 0.0, 0.0);
26330 		  }
26331 		else
26332 		  {
26333 		      result = gaiaAllocGeomColl ();
26334 		      gaiaAddPointToGeomColl (result, x, y);
26335 		  }
26336 		result->Srid = geo->Srid;
26337 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26338 					    gpkg_mode, tiny_point);
26339 		gaiaFreeGeomColl (result);
26340 		sqlite3_result_blob (context, p_result, len, free);
26341 	    }
26342       }
26343     gaiaFreeGeomColl (geo);
26344 }
26345 
26346 static void
fnct_Simplify(sqlite3_context * context,int argc,sqlite3_value ** argv)26347 fnct_Simplify (sqlite3_context * context, int argc, sqlite3_value ** argv)
26348 {
26349 /* SQL function:
26350 / Simplify(BLOBencoded geometry, tolerance)
26351 /
26352 / returns a new geometry that is a caricature of the original one received, but simplified using the Douglas-Peuker algorihtm
26353 / or NULL if any error is encountered
26354 */
26355     unsigned char *p_blob;
26356     int n_bytes;
26357     gaiaGeomCollPtr geo = NULL;
26358     gaiaGeomCollPtr result;
26359     int int_value;
26360     double tolerance;
26361     int gpkg_amphibious = 0;
26362     int gpkg_mode = 0;
26363     int tiny_point = 0;
26364     struct splite_internal_cache *cache = sqlite3_user_data (context);
26365     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26366     if (cache != NULL)
26367       {
26368 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26369 	  gpkg_mode = cache->gpkg_mode;
26370 	  tiny_point = cache->tinyPointEnabled;
26371       }
26372     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26373       {
26374 	  sqlite3_result_null (context);
26375 	  return;
26376       }
26377     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
26378 	tolerance = sqlite3_value_double (argv[1]);
26379     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
26380       {
26381 	  int_value = sqlite3_value_int (argv[1]);
26382 	  tolerance = int_value;
26383       }
26384     else
26385       {
26386 	  sqlite3_result_null (context);
26387 	  return;
26388       }
26389     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26390     n_bytes = sqlite3_value_bytes (argv[0]);
26391     geo =
26392 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26393 				     gpkg_amphibious);
26394     if (!geo)
26395 	sqlite3_result_null (context);
26396     else
26397       {
26398 	  void *data = sqlite3_user_data (context);
26399 	  if (data != NULL)
26400 	      result = gaiaGeomCollSimplify_r (data, geo, tolerance);
26401 	  else
26402 	      result = gaiaGeomCollSimplify (geo, tolerance);
26403 	  if (!result)
26404 	      sqlite3_result_null (context);
26405 	  else
26406 	    {
26407 		/* builds the BLOB geometry to be returned */
26408 		int len;
26409 		unsigned char *p_result = NULL;
26410 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26411 					    gpkg_mode, tiny_point);
26412 		sqlite3_result_blob (context, p_result, len, free);
26413 		gaiaFreeGeomColl (result);
26414 	    }
26415       }
26416     gaiaFreeGeomColl (geo);
26417 }
26418 
26419 static void
fnct_SimplifyPreserveTopology(sqlite3_context * context,int argc,sqlite3_value ** argv)26420 fnct_SimplifyPreserveTopology (sqlite3_context * context, int argc,
26421 			       sqlite3_value ** argv)
26422 {
26423 /* SQL function:
26424 / SimplifyPreserveTopology(BLOBencoded geometry, tolerance)
26425 /
26426 / returns a new geometry that is a caricature of the original one received, but simplified using the Douglas-Peuker algorihtm [preserving topology]
26427 / or NULL if any error is encountered
26428 */
26429     unsigned char *p_blob;
26430     int n_bytes;
26431     gaiaGeomCollPtr geo = NULL;
26432     gaiaGeomCollPtr result;
26433     int int_value;
26434     double tolerance;
26435     int gpkg_amphibious = 0;
26436     int gpkg_mode = 0;
26437     int tiny_point = 0;
26438     struct splite_internal_cache *cache = sqlite3_user_data (context);
26439     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26440     if (cache != NULL)
26441       {
26442 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26443 	  gpkg_mode = cache->gpkg_mode;
26444 	  tiny_point = cache->tinyPointEnabled;
26445       }
26446     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26447       {
26448 	  sqlite3_result_null (context);
26449 	  return;
26450       }
26451     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
26452 	tolerance = sqlite3_value_double (argv[1]);
26453     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
26454       {
26455 	  int_value = sqlite3_value_int (argv[1]);
26456 	  tolerance = int_value;
26457       }
26458     else
26459       {
26460 	  sqlite3_result_null (context);
26461 	  return;
26462       }
26463     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26464     n_bytes = sqlite3_value_bytes (argv[0]);
26465     geo =
26466 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26467 				     gpkg_amphibious);
26468     if (!geo)
26469 	sqlite3_result_null (context);
26470     else
26471       {
26472 	  void *data = sqlite3_user_data (context);
26473 	  if (data != NULL)
26474 	      result =
26475 		  gaiaGeomCollSimplifyPreserveTopology_r (data, geo, tolerance);
26476 	  else
26477 	      result = gaiaGeomCollSimplifyPreserveTopology (geo, tolerance);
26478 	  if (!result)
26479 	      sqlite3_result_null (context);
26480 	  else
26481 	    {
26482 		/* builds the BLOB geometry to be returned */
26483 		int len;
26484 		unsigned char *p_result = NULL;
26485 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26486 					    gpkg_mode, tiny_point);
26487 		sqlite3_result_blob (context, p_result, len, free);
26488 		gaiaFreeGeomColl (result);
26489 	    }
26490       }
26491     gaiaFreeGeomColl (geo);
26492 }
26493 
26494 static void
fnct_ConvexHull(sqlite3_context * context,int argc,sqlite3_value ** argv)26495 fnct_ConvexHull (sqlite3_context * context, int argc, sqlite3_value ** argv)
26496 {
26497 /* SQL function:
26498 / ConvexHull(BLOBencoded geometry)
26499 /
26500 / returns a new geometry representing the CONVEX HULL for current geometry
26501 / or NULL if any error is encountered
26502 */
26503     unsigned char *p_blob;
26504     int n_bytes;
26505     int len;
26506     unsigned char *p_result = NULL;
26507     gaiaGeomCollPtr geo = NULL;
26508     gaiaGeomCollPtr result;
26509     int gpkg_amphibious = 0;
26510     int gpkg_mode = 0;
26511     int tiny_point = 0;
26512     struct splite_internal_cache *cache = sqlite3_user_data (context);
26513     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26514     if (cache != NULL)
26515       {
26516 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26517 	  gpkg_mode = cache->gpkg_mode;
26518 	  tiny_point = cache->tinyPointEnabled;
26519       }
26520     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26521       {
26522 	  sqlite3_result_null (context);
26523 	  return;
26524       }
26525     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26526     n_bytes = sqlite3_value_bytes (argv[0]);
26527     geo =
26528 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26529 				     gpkg_amphibious);
26530     if (!geo)
26531 	sqlite3_result_null (context);
26532     else
26533       {
26534 	  void *data = sqlite3_user_data (context);
26535 	  if (data != NULL)
26536 	      result = gaiaConvexHull_r (data, geo);
26537 	  else
26538 	      result = gaiaConvexHull (geo);
26539 	  if (!result)
26540 	      sqlite3_result_null (context);
26541 	  else
26542 	    {
26543 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26544 					    gpkg_mode, tiny_point);
26545 		sqlite3_result_blob (context, p_result, len, free);
26546 		gaiaFreeGeomColl (result);
26547 	    }
26548       }
26549     gaiaFreeGeomColl (geo);
26550 }
26551 
26552 static void
fnct_Buffer(sqlite3_context * context,int argc,sqlite3_value ** argv)26553 fnct_Buffer (sqlite3_context * context, int argc, sqlite3_value ** argv)
26554 {
26555 /* SQL function:
26556 / Buffer(BLOBencoded geometry, radius)
26557 / Buffer(BLOBencoded geometry, radius, quadrantsegments)
26558 /
26559 / returns a new geometry representing the BUFFER for current geometry
26560 / or NULL if any error is encountered
26561 */
26562     unsigned char *p_blob;
26563     int n_bytes;
26564     gaiaGeomCollPtr geo = NULL;
26565     gaiaGeomCollPtr result;
26566     double radius;
26567     int int_value;
26568     int quadrantsegments = -1;
26569     int gpkg_amphibious = 0;
26570     int gpkg_mode = 0;
26571     int tiny_point = 0;
26572     struct splite_internal_cache *cache = sqlite3_user_data (context);
26573     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26574     if (cache != NULL)
26575       {
26576 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26577 	  gpkg_mode = cache->gpkg_mode;
26578 	  tiny_point = cache->tinyPointEnabled;
26579       }
26580     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26581       {
26582 	  sqlite3_result_null (context);
26583 	  return;
26584       }
26585     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
26586 	radius = sqlite3_value_double (argv[1]);
26587     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
26588       {
26589 	  int_value = sqlite3_value_int (argv[1]);
26590 	  radius = int_value;
26591       }
26592     else
26593       {
26594 	  sqlite3_result_null (context);
26595 	  return;
26596       }
26597     if (argc == 3)
26598       {
26599 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
26600 	    {
26601 		sqlite3_result_null (context);
26602 		return;
26603 	    }
26604 	  quadrantsegments = sqlite3_value_int (argv[2]);
26605 	  if (quadrantsegments <= 0)
26606 	      quadrantsegments = 1;
26607       }
26608     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26609     n_bytes = sqlite3_value_bytes (argv[0]);
26610     geo =
26611 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26612 				     gpkg_amphibious);
26613     if (!geo)
26614 	sqlite3_result_null (context);
26615     else
26616       {
26617 	  void *data = sqlite3_user_data (context);
26618 	  if (data != NULL)
26619 	      result =
26620 		  gaiaGeomCollBuffer_r (data, geo, radius, quadrantsegments);
26621 	  else
26622 	    {
26623 		if (quadrantsegments <= 0)
26624 		    quadrantsegments = 30;
26625 		result = gaiaGeomCollBuffer (geo, radius, quadrantsegments);
26626 	    }
26627 	  if (!result)
26628 	      sqlite3_result_null (context);
26629 	  else
26630 	    {
26631 		/* builds the BLOB geometry to be returned */
26632 		int len;
26633 		unsigned char *p_result = NULL;
26634 		result->Srid = geo->Srid;
26635 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26636 					    gpkg_mode, tiny_point);
26637 		sqlite3_result_blob (context, p_result, len, free);
26638 		gaiaFreeGeomColl (result);
26639 	    }
26640       }
26641     gaiaFreeGeomColl (geo);
26642 }
26643 
26644 static void
fnct_Intersection(sqlite3_context * context,int argc,sqlite3_value ** argv)26645 fnct_Intersection (sqlite3_context * context, int argc, sqlite3_value ** argv)
26646 {
26647 /* SQL function:
26648 / Intersection(BLOBencoded geom1, BLOBencoded geom2)
26649 /
26650 / returns a new geometry representing the INTERSECTION of both geometries
26651 / or NULL if any error is encountered
26652 */
26653     unsigned char *p_blob;
26654     int n_bytes;
26655     gaiaGeomCollPtr geo1 = NULL;
26656     gaiaGeomCollPtr geo2 = NULL;
26657     gaiaGeomCollPtr result;
26658     int gpkg_amphibious = 0;
26659     int gpkg_mode = 0;
26660     int tiny_point = 0;
26661     struct splite_internal_cache *cache = sqlite3_user_data (context);
26662     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26663     if (cache != NULL)
26664       {
26665 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26666 	  gpkg_mode = cache->gpkg_mode;
26667 	  tiny_point = cache->tinyPointEnabled;
26668       }
26669     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26670       {
26671 	  sqlite3_result_null (context);
26672 	  return;
26673       }
26674     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
26675       {
26676 	  sqlite3_result_null (context);
26677 	  return;
26678       }
26679     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26680     n_bytes = sqlite3_value_bytes (argv[0]);
26681     geo1 =
26682 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26683 				     gpkg_amphibious);
26684     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
26685     n_bytes = sqlite3_value_bytes (argv[1]);
26686     geo2 =
26687 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26688 				     gpkg_amphibious);
26689     if (!geo1 || !geo2)
26690 	sqlite3_result_null (context);
26691     else
26692       {
26693 	  void *data = sqlite3_user_data (context);
26694 	  if (data != NULL)
26695 	      result = gaiaGeometryIntersection_r (data, geo1, geo2);
26696 	  else
26697 	      result = gaiaGeometryIntersection (geo1, geo2);
26698 	  if (!result)
26699 	      sqlite3_result_null (context);
26700 	  else if (gaiaIsEmpty (result))
26701 	    {
26702 		gaiaFreeGeomColl (result);
26703 		sqlite3_result_null (context);
26704 	    }
26705 	  else
26706 	    {
26707 		/* builds the BLOB geometry to be returned */
26708 		int len;
26709 		unsigned char *p_result = NULL;
26710 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26711 					    gpkg_mode, tiny_point);
26712 		sqlite3_result_blob (context, p_result, len, free);
26713 		gaiaFreeGeomColl (result);
26714 	    }
26715       }
26716     gaiaFreeGeomColl (geo1);
26717     gaiaFreeGeomColl (geo2);
26718 }
26719 
26720 static int
gaia_union_polygs(gaiaGeomCollPtr geom)26721 gaia_union_polygs (gaiaGeomCollPtr geom)
26722 {
26723 /* testing if this geometry simply contains Polygons */
26724     int pts = 0;
26725     int lns = 0;
26726     int pgs = 0;
26727     gaiaPointPtr pt;
26728     gaiaLinestringPtr ln;
26729     gaiaPolygonPtr pg;
26730     pt = geom->FirstPoint;
26731     while (pt)
26732       {
26733 	  pts++;
26734 	  pt = pt->Next;
26735       }
26736     ln = geom->FirstLinestring;
26737     while (ln)
26738       {
26739 	  lns++;
26740 	  ln = ln->Next;
26741       }
26742     pg = geom->FirstPolygon;
26743     while (pg)
26744       {
26745 	  pgs++;
26746 	  pg = pg->Next;
26747       }
26748     if (pts || lns)
26749 	return 0;
26750     if (!pgs)
26751 	return 0;
26752     return 1;
26753 }
26754 
26755 static void
fnct_Union_step(sqlite3_context * context,int argc,sqlite3_value ** argv)26756 fnct_Union_step (sqlite3_context * context, int argc, sqlite3_value ** argv)
26757 {
26758 /* SQL function:
26759 / Union(BLOBencoded geom)
26760 /
26761 / aggregate function - STEP
26762 /
26763 */
26764     struct gaia_geom_chain *chain;
26765     struct gaia_geom_chain_item *item;
26766     unsigned char *p_blob;
26767     int n_bytes;
26768     gaiaGeomCollPtr geom;
26769     struct gaia_geom_chain **p;
26770     int gpkg_amphibious = 0;
26771     int gpkg_mode = 0;
26772     struct splite_internal_cache *cache = sqlite3_user_data (context);
26773     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26774     if (cache != NULL)
26775       {
26776 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26777 	  gpkg_mode = cache->gpkg_mode;
26778       }
26779     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26780       {
26781 	  sqlite3_result_null (context);
26782 	  return;
26783       }
26784     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26785     n_bytes = sqlite3_value_bytes (argv[0]);
26786     geom =
26787 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26788 				     gpkg_amphibious);
26789     if (!geom)
26790 	return;
26791     p = sqlite3_aggregate_context (context, sizeof (struct gaia_geom_chain **));
26792     if (!(*p))
26793       {
26794 	  /* this is the first row */
26795 	  chain = malloc (sizeof (struct gaia_geom_chain));
26796 	  *p = chain;
26797 	  item = malloc (sizeof (struct gaia_geom_chain_item));
26798 	  item->geom = geom;
26799 	  item->next = NULL;
26800 	  chain->all_polygs = gaia_union_polygs (geom);
26801 	  chain->first = item;
26802 	  chain->last = item;
26803       }
26804     else
26805       {
26806 	  /* subsequent rows */
26807 	  chain = *p;
26808 	  item = malloc (sizeof (struct gaia_geom_chain_item));
26809 	  item->geom = geom;
26810 	  item->next = NULL;
26811 	  if (!gaia_union_polygs (geom))
26812 	      chain->all_polygs = 0;
26813 	  chain->last->next = item;
26814 	  chain->last = item;
26815       }
26816 }
26817 
26818 static void
gaia_free_geom_chain(struct gaia_geom_chain * chain)26819 gaia_free_geom_chain (struct gaia_geom_chain *chain)
26820 {
26821     struct gaia_geom_chain_item *p = chain->first;
26822     struct gaia_geom_chain_item *pn;
26823     while (p)
26824       {
26825 	  pn = p->next;
26826 	  gaiaFreeGeomColl (p->geom);
26827 	  free (p);
26828 	  p = pn;
26829       }
26830     free (chain);
26831 }
26832 
26833 static void
fnct_Union_final(sqlite3_context * context)26834 fnct_Union_final (sqlite3_context * context)
26835 {
26836 /* SQL function:
26837 / Union(BLOBencoded geom)
26838 /
26839 / aggregate function - FINAL
26840 /
26841 */
26842     gaiaGeomCollPtr tmp;
26843     struct gaia_geom_chain *chain;
26844     struct gaia_geom_chain_item *item;
26845     gaiaGeomCollPtr aggregate = NULL;
26846     gaiaGeomCollPtr result;
26847     void *data = sqlite3_user_data (context);
26848     struct gaia_geom_chain **p = sqlite3_aggregate_context (context, 0);
26849     int gpkg_mode = 0;
26850     int tiny_point = 0;
26851     struct splite_internal_cache *cache = sqlite3_user_data (context);
26852     if (cache != NULL)
26853       {
26854 	  gpkg_mode = cache->gpkg_mode;
26855 	  tiny_point = cache->tinyPointEnabled;
26856       }
26857     if (!p)
26858       {
26859 	  sqlite3_result_null (context);
26860 	  return;
26861       }
26862     chain = *p;
26863 
26864 /* applying UnaryUnion */
26865     item = chain->first;
26866     while (item)
26867       {
26868 	  gaiaGeomCollPtr geom = item->geom;
26869 	  if (item == chain->first)
26870 	    {
26871 		/* initializing the aggregate geometry */
26872 		aggregate = geom;
26873 		item->geom = NULL;
26874 		item = item->next;
26875 		continue;
26876 	    }
26877 	  if (data != NULL)
26878 	      tmp = gaiaMergeGeometries_r (data, aggregate, geom);
26879 	  else
26880 	      tmp = gaiaMergeGeometries (aggregate, geom);
26881 	  gaiaFreeGeomColl (geom);
26882 	  item->geom = NULL;
26883 	  aggregate = tmp;
26884 	  item = item->next;
26885       }
26886     if (data != NULL)
26887 	result = gaiaUnaryUnion_r (data, aggregate);
26888     else
26889 	result = gaiaUnaryUnion (aggregate);
26890     gaiaFreeGeomColl (aggregate);
26891     gaia_free_geom_chain (chain);
26892 
26893     if (result == NULL)
26894 	sqlite3_result_null (context);
26895     else if (gaiaIsEmpty (result))
26896 	sqlite3_result_null (context);
26897     else
26898       {
26899 	  /* builds the BLOB geometry to be returned */
26900 	  int len;
26901 	  unsigned char *p_result = NULL;
26902 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
26903 				      tiny_point);
26904 	  sqlite3_result_blob (context, p_result, len, free);
26905       }
26906     gaiaFreeGeomColl (result);
26907 }
26908 
26909 static void
fnct_Union(sqlite3_context * context,int argc,sqlite3_value ** argv)26910 fnct_Union (sqlite3_context * context, int argc, sqlite3_value ** argv)
26911 {
26912 /* SQL function:
26913 / Union(BLOBencoded geom1, BLOBencoded geom2)
26914 /
26915 / returns a new geometry representing the UNION of both geometries
26916 / or NULL if any error is encountered
26917 */
26918     unsigned char *p_blob;
26919     int n_bytes;
26920     gaiaGeomCollPtr geo1 = NULL;
26921     gaiaGeomCollPtr geo2 = NULL;
26922     gaiaGeomCollPtr result;
26923     int gpkg_amphibious = 0;
26924     int gpkg_mode = 0;
26925     int tiny_point = 0;
26926     struct splite_internal_cache *cache = sqlite3_user_data (context);
26927     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
26928     if (cache != NULL)
26929       {
26930 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
26931 	  gpkg_mode = cache->gpkg_mode;
26932 	  tiny_point = cache->tinyPointEnabled;
26933       }
26934     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
26935       {
26936 	  sqlite3_result_null (context);
26937 	  return;
26938       }
26939     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
26940       {
26941 	  sqlite3_result_null (context);
26942 	  return;
26943       }
26944     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
26945     n_bytes = sqlite3_value_bytes (argv[0]);
26946     geo1 =
26947 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26948 				     gpkg_amphibious);
26949     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
26950     n_bytes = sqlite3_value_bytes (argv[1]);
26951     geo2 =
26952 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
26953 				     gpkg_amphibious);
26954     if (!geo1 || !geo2)
26955 	sqlite3_result_null (context);
26956     else
26957       {
26958 	  void *data = sqlite3_user_data (context);
26959 	  if (data != NULL)
26960 	      result = gaiaGeometryUnion_r (data, geo1, geo2);
26961 	  else
26962 	      result = gaiaGeometryUnion (geo1, geo2);
26963 	  if (!result)
26964 	      sqlite3_result_null (context);
26965 	  else if (gaiaIsEmpty (result))
26966 	    {
26967 		gaiaFreeGeomColl (result);
26968 		sqlite3_result_null (context);
26969 	    }
26970 	  else
26971 	    {
26972 		/* builds the BLOB geometry to be returned */
26973 		int len;
26974 		unsigned char *p_result = NULL;
26975 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
26976 					    gpkg_mode, tiny_point);
26977 		sqlite3_result_blob (context, p_result, len, free);
26978 		gaiaFreeGeomColl (result);
26979 	    }
26980       }
26981     gaiaFreeGeomColl (geo1);
26982     gaiaFreeGeomColl (geo2);
26983 }
26984 
26985 static void
fnct_Difference(sqlite3_context * context,int argc,sqlite3_value ** argv)26986 fnct_Difference (sqlite3_context * context, int argc, sqlite3_value ** argv)
26987 {
26988 /* SQL function:
26989 / Difference(BLOBencoded geom1, BLOBencoded geom2)
26990 /
26991 / returns a new geometry representing the DIFFERENCE of both geometries
26992 / or NULL if any error is encountered
26993 */
26994     unsigned char *p_blob;
26995     int n_bytes;
26996     gaiaGeomCollPtr geo1 = NULL;
26997     gaiaGeomCollPtr geo2 = NULL;
26998     gaiaGeomCollPtr result;
26999     int gpkg_amphibious = 0;
27000     int gpkg_mode = 0;
27001     int tiny_point = 0;
27002     struct splite_internal_cache *cache = sqlite3_user_data (context);
27003     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27004     if (cache != NULL)
27005       {
27006 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27007 	  gpkg_mode = cache->gpkg_mode;
27008 	  tiny_point = cache->tinyPointEnabled;
27009       }
27010     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27011       {
27012 	  sqlite3_result_null (context);
27013 	  return;
27014       }
27015     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27016       {
27017 	  sqlite3_result_null (context);
27018 	  return;
27019       }
27020     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
27021     n_bytes = sqlite3_value_bytes (argv[0]);
27022     geo1 =
27023 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27024 				     gpkg_amphibious);
27025     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
27026     n_bytes = sqlite3_value_bytes (argv[1]);
27027     geo2 =
27028 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27029 				     gpkg_amphibious);
27030     if (!geo1 || !geo2)
27031 	sqlite3_result_null (context);
27032     else
27033       {
27034 	  void *data = sqlite3_user_data (context);
27035 	  if (data != NULL)
27036 	      result = gaiaGeometryDifference_r (data, geo1, geo2);
27037 	  else
27038 	      result = gaiaGeometryDifference (geo1, geo2);
27039 	  if (!result)
27040 	      sqlite3_result_null (context);
27041 	  else if (gaiaIsEmpty (result))
27042 	    {
27043 		gaiaFreeGeomColl (result);
27044 		sqlite3_result_null (context);
27045 	    }
27046 	  else
27047 	    {
27048 		/* builds the BLOB geometry to be returned */
27049 		int len;
27050 		unsigned char *p_result = NULL;
27051 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
27052 					    gpkg_mode, tiny_point);
27053 		sqlite3_result_blob (context, p_result, len, free);
27054 		gaiaFreeGeomColl (result);
27055 	    }
27056       }
27057     gaiaFreeGeomColl (geo1);
27058     gaiaFreeGeomColl (geo2);
27059 }
27060 
27061 static void
fnct_SymDifference(sqlite3_context * context,int argc,sqlite3_value ** argv)27062 fnct_SymDifference (sqlite3_context * context, int argc, sqlite3_value ** argv)
27063 {
27064 /* SQL function:
27065 / SymDifference(BLOBencoded geom1, BLOBencoded geom2)
27066 /
27067 / returns a new geometry representing the SYMMETRIC DIFFERENCE of both geometries
27068 / or NULL if any error is encountered
27069 */
27070     unsigned char *p_blob;
27071     int n_bytes;
27072     gaiaGeomCollPtr geo1 = NULL;
27073     gaiaGeomCollPtr geo2 = NULL;
27074     gaiaGeomCollPtr result;
27075     int gpkg_amphibious = 0;
27076     int gpkg_mode = 0;
27077     int tiny_point = 0;
27078     struct splite_internal_cache *cache = sqlite3_user_data (context);
27079     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27080     if (cache != NULL)
27081       {
27082 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27083 	  gpkg_mode = cache->gpkg_mode;
27084 	  tiny_point = cache->tinyPointEnabled;
27085       }
27086     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27087       {
27088 	  sqlite3_result_null (context);
27089 	  return;
27090       }
27091     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27092       {
27093 	  sqlite3_result_null (context);
27094 	  return;
27095       }
27096     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
27097     n_bytes = sqlite3_value_bytes (argv[0]);
27098     geo1 =
27099 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27100 				     gpkg_amphibious);
27101     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
27102     n_bytes = sqlite3_value_bytes (argv[1]);
27103     geo2 =
27104 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27105 				     gpkg_amphibious);
27106     if (!geo1 || !geo2)
27107 	sqlite3_result_null (context);
27108     else
27109       {
27110 	  void *data = sqlite3_user_data (context);
27111 	  if (data != NULL)
27112 	      result = gaiaGeometrySymDifference_r (data, geo1, geo2);
27113 	  else
27114 	      result = gaiaGeometrySymDifference (geo1, geo2);
27115 	  if (!result)
27116 	      sqlite3_result_null (context);
27117 	  else if (gaiaIsEmpty (result))
27118 	    {
27119 		gaiaFreeGeomColl (result);
27120 		sqlite3_result_null (context);
27121 	    }
27122 	  else
27123 	    {
27124 		/* builds the BLOB geometry to be returned */
27125 		int len;
27126 		unsigned char *p_result = NULL;
27127 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
27128 					    gpkg_mode, tiny_point);
27129 		sqlite3_result_blob (context, p_result, len, free);
27130 		gaiaFreeGeomColl (result);
27131 	    }
27132       }
27133     gaiaFreeGeomColl (geo1);
27134     gaiaFreeGeomColl (geo2);
27135 }
27136 
27137 static void
fnct_Equals(sqlite3_context * context,int argc,sqlite3_value ** argv)27138 fnct_Equals (sqlite3_context * context, int argc, sqlite3_value ** argv)
27139 {
27140 /* SQL function:
27141 / Equals(BLOBencoded geom1, BLOBencoded geom2)
27142 /
27143 / returns:
27144 / 1 if the two geometries are "spatially equal"
27145 / 0 otherwise
27146 / or -1 if any error is encountered
27147 */
27148     unsigned char *p_blob;
27149     int n_bytes;
27150     gaiaGeomCollPtr geo1 = NULL;
27151     gaiaGeomCollPtr geo2 = NULL;
27152     int ret;
27153     int gpkg_amphibious = 0;
27154     int gpkg_mode = 0;
27155     struct splite_internal_cache *cache = sqlite3_user_data (context);
27156     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27157     if (cache != NULL)
27158       {
27159 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27160 	  gpkg_mode = cache->gpkg_mode;
27161       }
27162     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27163       {
27164 	  sqlite3_result_int (context, -1);
27165 	  return;
27166       }
27167     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27168       {
27169 	  sqlite3_result_int (context, -1);
27170 	  return;
27171       }
27172     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
27173     n_bytes = sqlite3_value_bytes (argv[0]);
27174     geo1 =
27175 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27176 				     gpkg_amphibious);
27177     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
27178     n_bytes = sqlite3_value_bytes (argv[1]);
27179     geo2 =
27180 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27181 				     gpkg_amphibious);
27182     if (!geo1 || !geo2)
27183 	sqlite3_result_int (context, -1);
27184     else
27185       {
27186 	  void *data = sqlite3_user_data (context);
27187 	  if (data != NULL)
27188 	      ret = gaiaGeomCollEquals_r (data, geo1, geo2);
27189 	  else
27190 	      ret = gaiaGeomCollEquals (geo1, geo2);
27191 	  sqlite3_result_int (context, ret);
27192       }
27193     gaiaFreeGeomColl (geo1);
27194     gaiaFreeGeomColl (geo2);
27195 }
27196 
27197 static void
fnct_Intersects(sqlite3_context * context,int argc,sqlite3_value ** argv)27198 fnct_Intersects (sqlite3_context * context, int argc, sqlite3_value ** argv)
27199 {
27200 /* SQL function:
27201 / Intersects(BLOBencoded geom1, BLOBencoded geom2)
27202 /
27203 / returns:
27204 / 1 if the two geometries do "spatially intersects"
27205 / 0 otherwise
27206 / or -1 if any error is encountered
27207 */
27208     unsigned char *blob1;
27209     unsigned char *blob2;
27210     int bytes1;
27211     int bytes2;
27212     gaiaGeomCollPtr geo1 = NULL;
27213     gaiaGeomCollPtr geo2 = NULL;
27214     int ret;
27215     int gpkg_amphibious = 0;
27216     int gpkg_mode = 0;
27217     struct splite_internal_cache *cache = sqlite3_user_data (context);
27218     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27219     if (cache != NULL)
27220       {
27221 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27222 	  gpkg_mode = cache->gpkg_mode;
27223       }
27224     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27225       {
27226 	  sqlite3_result_int (context, -1);
27227 	  return;
27228       }
27229     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27230       {
27231 	  sqlite3_result_int (context, -1);
27232 	  return;
27233       }
27234     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27235     bytes1 = sqlite3_value_bytes (argv[0]);
27236     geo1 =
27237 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27238     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27239     bytes2 = sqlite3_value_bytes (argv[1]);
27240     geo2 =
27241 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27242     if (!geo1 || !geo2)
27243 	sqlite3_result_int (context, -1);
27244     else
27245       {
27246 	  void *data = sqlite3_user_data (context);
27247 	  if (data != NULL)
27248 	      ret = gaiaGeomCollPreparedIntersects (data,
27249 						    geo1, blob1, bytes1, geo2,
27250 						    blob2, bytes2);
27251 	  else
27252 	      ret = gaiaGeomCollIntersects (geo1, geo2);
27253 	  sqlite3_result_int (context, ret);
27254       }
27255     gaiaFreeGeomColl (geo1);
27256     gaiaFreeGeomColl (geo2);
27257 }
27258 
27259 static void
fnct_Disjoint(sqlite3_context * context,int argc,sqlite3_value ** argv)27260 fnct_Disjoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
27261 {
27262 /* SQL function:
27263 / Disjoint(BLOBencoded geom1, BLOBencoded geom2)
27264 /
27265 / returns:
27266 / 1 if the two geometries are "spatially disjoint"
27267 / 0 otherwise
27268 / or -1 if any error is encountered
27269 */
27270     unsigned char *blob1;
27271     unsigned char *blob2;
27272     int bytes1;
27273     int bytes2;
27274     gaiaGeomCollPtr geo1 = NULL;
27275     gaiaGeomCollPtr geo2 = NULL;
27276     int ret;
27277     int gpkg_amphibious = 0;
27278     int gpkg_mode = 0;
27279     struct splite_internal_cache *cache = sqlite3_user_data (context);
27280     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27281     if (cache != NULL)
27282       {
27283 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27284 	  gpkg_mode = cache->gpkg_mode;
27285       }
27286     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27287       {
27288 	  sqlite3_result_int (context, -1);
27289 	  return;
27290       }
27291     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27292       {
27293 	  sqlite3_result_int (context, -1);
27294 	  return;
27295       }
27296     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27297     bytes1 = sqlite3_value_bytes (argv[0]);
27298     geo1 =
27299 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27300     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27301     bytes2 = sqlite3_value_bytes (argv[1]);
27302     geo2 =
27303 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27304     if (!geo1 || !geo2)
27305 	sqlite3_result_int (context, -1);
27306     else
27307       {
27308 	  void *data = sqlite3_user_data (context);
27309 	  if (data != NULL)
27310 	      ret = gaiaGeomCollPreparedDisjoint (data,
27311 						  geo1, blob1, bytes1, geo2,
27312 						  blob2, bytes2);
27313 	  else
27314 	      ret = gaiaGeomCollDisjoint (geo1, geo2);
27315 	  sqlite3_result_int (context, ret);
27316       }
27317     gaiaFreeGeomColl (geo1);
27318     gaiaFreeGeomColl (geo2);
27319 }
27320 
27321 static void
fnct_Overlaps(sqlite3_context * context,int argc,sqlite3_value ** argv)27322 fnct_Overlaps (sqlite3_context * context, int argc, sqlite3_value ** argv)
27323 {
27324 /* SQL function:
27325 / Overlaps(BLOBencoded geom1, BLOBencoded geom2)
27326 /
27327 / returns:
27328 / 1 if the two geometries do "spatially overlaps"
27329 / 0 otherwise
27330 / or -1 if any error is encountered
27331 */
27332     unsigned char *blob1;
27333     unsigned char *blob2;
27334     int bytes1;
27335     int bytes2;
27336     gaiaGeomCollPtr geo1 = NULL;
27337     gaiaGeomCollPtr geo2 = NULL;
27338     int ret;
27339     int gpkg_amphibious = 0;
27340     int gpkg_mode = 0;
27341     struct splite_internal_cache *cache = sqlite3_user_data (context);
27342     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27343     if (cache != NULL)
27344       {
27345 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27346 	  gpkg_mode = cache->gpkg_mode;
27347       }
27348     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27349       {
27350 	  sqlite3_result_int (context, -1);
27351 	  return;
27352       }
27353     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27354       {
27355 	  sqlite3_result_int (context, -1);
27356 	  return;
27357       }
27358     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27359     bytes1 = sqlite3_value_bytes (argv[0]);
27360     geo1 =
27361 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27362     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27363     bytes2 = sqlite3_value_bytes (argv[1]);
27364     geo2 =
27365 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27366     if (!geo1 || !geo2)
27367 	sqlite3_result_int (context, -1);
27368     else
27369       {
27370 	  void *data = sqlite3_user_data (context);
27371 	  if (data != NULL)
27372 	      ret = gaiaGeomCollPreparedOverlaps (data,
27373 						  geo1, blob1, bytes1, geo2,
27374 						  blob2, bytes2);
27375 	  else
27376 	      ret = gaiaGeomCollOverlaps (geo1, geo2);
27377 	  sqlite3_result_int (context, ret);
27378       }
27379     gaiaFreeGeomColl (geo1);
27380     gaiaFreeGeomColl (geo2);
27381 }
27382 
27383 static void
fnct_Crosses(sqlite3_context * context,int argc,sqlite3_value ** argv)27384 fnct_Crosses (sqlite3_context * context, int argc, sqlite3_value ** argv)
27385 {
27386 /* SQL function:
27387 / Crosses(BLOBencoded geom1, BLOBencoded geom2)
27388 /
27389 / returns:
27390 / 1 if the two geometries do "spatially crosses"
27391 / 0 otherwise
27392 / or -1 if any error is encountered
27393 */
27394     unsigned char *blob1;
27395     unsigned char *blob2;
27396     int bytes1;
27397     int bytes2;
27398     gaiaGeomCollPtr geo1 = NULL;
27399     gaiaGeomCollPtr geo2 = NULL;
27400     int ret;
27401     int gpkg_amphibious = 0;
27402     int gpkg_mode = 0;
27403     struct splite_internal_cache *cache = sqlite3_user_data (context);
27404     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27405     if (cache != NULL)
27406       {
27407 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27408 	  gpkg_mode = cache->gpkg_mode;
27409       }
27410     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27411       {
27412 	  sqlite3_result_int (context, -1);
27413 	  return;
27414       }
27415     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27416       {
27417 	  sqlite3_result_int (context, -1);
27418 	  return;
27419       }
27420     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27421     bytes1 = sqlite3_value_bytes (argv[0]);
27422     geo1 =
27423 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27424     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27425     bytes2 = sqlite3_value_bytes (argv[1]);
27426     geo2 =
27427 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27428     if (!geo1 || !geo2)
27429 	sqlite3_result_int (context, -1);
27430     else
27431       {
27432 	  void *data = sqlite3_user_data (context);
27433 	  if (data != NULL)
27434 	      ret = gaiaGeomCollPreparedCrosses (data,
27435 						 geo1, blob1, bytes1, geo2,
27436 						 blob2, bytes2);
27437 	  else
27438 	      ret = gaiaGeomCollCrosses (geo1, geo2);
27439 	  sqlite3_result_int (context, ret);
27440       }
27441     gaiaFreeGeomColl (geo1);
27442     gaiaFreeGeomColl (geo2);
27443 }
27444 
27445 static void
fnct_Touches(sqlite3_context * context,int argc,sqlite3_value ** argv)27446 fnct_Touches (sqlite3_context * context, int argc, sqlite3_value ** argv)
27447 {
27448 /* SQL function:
27449 / Touches(BLOBencoded geom1, BLOBencoded geom2)
27450 /
27451 / returns:
27452 / 1 if the two geometries do "spatially touches"
27453 / 0 otherwise
27454 / or -1 if any error is encountered
27455 */
27456     unsigned char *blob1;
27457     unsigned char *blob2;
27458     int bytes1;
27459     int bytes2;
27460     gaiaGeomCollPtr geo1 = NULL;
27461     gaiaGeomCollPtr geo2 = NULL;
27462     int ret;
27463     int gpkg_amphibious = 0;
27464     int gpkg_mode = 0;
27465     struct splite_internal_cache *cache = sqlite3_user_data (context);
27466     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27467     if (cache != NULL)
27468       {
27469 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27470 	  gpkg_mode = cache->gpkg_mode;
27471       }
27472     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27473       {
27474 	  sqlite3_result_int (context, -1);
27475 	  return;
27476       }
27477     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27478       {
27479 	  sqlite3_result_int (context, -1);
27480 	  return;
27481       }
27482     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27483     bytes1 = sqlite3_value_bytes (argv[0]);
27484     geo1 =
27485 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27486     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27487     bytes2 = sqlite3_value_bytes (argv[1]);
27488     geo2 =
27489 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27490     if (!geo1 || !geo2)
27491 	sqlite3_result_int (context, -1);
27492     else
27493       {
27494 	  void *data = sqlite3_user_data (context);
27495 	  if (data != NULL)
27496 	      ret = gaiaGeomCollPreparedTouches (data,
27497 						 geo1, blob1, bytes1, geo2,
27498 						 blob2, bytes2);
27499 	  else
27500 	      ret = gaiaGeomCollTouches (geo1, geo2);
27501 	  sqlite3_result_int (context, ret);
27502       }
27503     gaiaFreeGeomColl (geo1);
27504     gaiaFreeGeomColl (geo2);
27505 }
27506 
27507 static void
fnct_Within(sqlite3_context * context,int argc,sqlite3_value ** argv)27508 fnct_Within (sqlite3_context * context, int argc, sqlite3_value ** argv)
27509 {
27510 /* SQL function:
27511 / Within(BLOBencoded geom1, BLOBencoded geom2)
27512 /
27513 / returns:
27514 / 1 if GEOM-1 is completely contained within GEOM-2
27515 / 0 otherwise
27516 / or -1 if any error is encountered
27517 */
27518     unsigned char *blob1;
27519     unsigned char *blob2;
27520     int bytes1;
27521     int bytes2;
27522     gaiaGeomCollPtr geo1 = NULL;
27523     gaiaGeomCollPtr geo2 = NULL;
27524     int ret;
27525     int gpkg_amphibious = 0;
27526     int gpkg_mode = 0;
27527     struct splite_internal_cache *cache = sqlite3_user_data (context);
27528     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27529     if (cache != NULL)
27530       {
27531 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27532 	  gpkg_mode = cache->gpkg_mode;
27533       }
27534     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27535       {
27536 	  sqlite3_result_int (context, -1);
27537 	  return;
27538       }
27539     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27540       {
27541 	  sqlite3_result_int (context, -1);
27542 	  return;
27543       }
27544     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27545     bytes1 = sqlite3_value_bytes (argv[0]);
27546     geo1 =
27547 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27548     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27549     bytes2 = sqlite3_value_bytes (argv[1]);
27550     geo2 =
27551 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27552     if (!geo1 || !geo2)
27553 	sqlite3_result_int (context, -1);
27554     else
27555       {
27556 	  void *data = sqlite3_user_data (context);
27557 	  if (data != NULL)
27558 	      ret = gaiaGeomCollPreparedWithin (data, geo1,
27559 						blob1, bytes1, geo2, blob2,
27560 						bytes2);
27561 	  else
27562 	      ret = gaiaGeomCollWithin (geo1, geo2);
27563 	  sqlite3_result_int (context, ret);
27564       }
27565     gaiaFreeGeomColl (geo1);
27566     gaiaFreeGeomColl (geo2);
27567 }
27568 
27569 static void
fnct_Contains(sqlite3_context * context,int argc,sqlite3_value ** argv)27570 fnct_Contains (sqlite3_context * context, int argc, sqlite3_value ** argv)
27571 {
27572 /* SQL function:
27573 / Contains(BLOBencoded geom1, BLOBencoded geom2)
27574 /
27575 / returns:
27576 / 1 if GEOM-1 completely contains GEOM-2
27577 / 0 otherwise
27578 / or -1 if any error is encountered
27579 */
27580     unsigned char *blob1;
27581     unsigned char *blob2;
27582     int bytes1;
27583     int bytes2;
27584     gaiaGeomCollPtr geo1 = NULL;
27585     gaiaGeomCollPtr geo2 = NULL;
27586     int ret;
27587     int gpkg_amphibious = 0;
27588     int gpkg_mode = 0;
27589     struct splite_internal_cache *cache = sqlite3_user_data (context);
27590     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27591     if (cache != NULL)
27592       {
27593 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27594 	  gpkg_mode = cache->gpkg_mode;
27595       }
27596     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27597       {
27598 	  sqlite3_result_int (context, -1);
27599 	  return;
27600       }
27601     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27602       {
27603 	  sqlite3_result_int (context, -1);
27604 	  return;
27605       }
27606     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
27607     bytes1 = sqlite3_value_bytes (argv[0]);
27608     geo1 =
27609 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
27610     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
27611     bytes2 = sqlite3_value_bytes (argv[1]);
27612     geo2 =
27613 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
27614     if (!geo1 || !geo2)
27615 	sqlite3_result_int (context, -1);
27616     else
27617       {
27618 	  void *data = sqlite3_user_data (context);
27619 	  if (data != NULL)
27620 	      ret = gaiaGeomCollPreparedContains (data,
27621 						  geo1, blob1, bytes1, geo2,
27622 						  blob2, bytes2);
27623 	  else
27624 	      ret = gaiaGeomCollContains (geo1, geo2);
27625 	  sqlite3_result_int (context, ret);
27626       }
27627     gaiaFreeGeomColl (geo1);
27628     gaiaFreeGeomColl (geo2);
27629 }
27630 
27631 static void
fnct_Relate(sqlite3_context * context,int argc,sqlite3_value ** argv)27632 fnct_Relate (sqlite3_context * context, int argc, sqlite3_value ** argv)
27633 {
27634 /* SQL function:
27635 / Relate(BLOBencoded geom1, BLOBencoded geom2, string pattern)
27636 /
27637 / returns:
27638 / 1 if GEOM-1 and GEOM-2 have a spatial relationship as specified by the patternMatrix
27639 / 0 otherwise
27640 / or -1 if any error is encountered
27641 /
27642 / or alternatively:
27643 /
27644 / Relate(BLOBencoded geom1, BLOBencoded geom2)
27645 / Relate(BLOBencoded geom1, BLOBencoded geom2, int bnr)
27646 /
27647 / returns:
27648 / an intersection matrix [DE-9IM]
27649 / NULL if any error is encountered
27650 */
27651     unsigned char *p_blob;
27652     int n_bytes;
27653     gaiaGeomCollPtr geo1 = NULL;
27654     gaiaGeomCollPtr geo2 = NULL;
27655     int ret;
27656     const char *pattern = NULL;
27657     int bnr = 1;
27658     char *matrix;
27659     int gpkg_amphibious = 0;
27660     int gpkg_mode = 0;
27661     struct splite_internal_cache *cache = sqlite3_user_data (context);
27662     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27663     if (cache != NULL)
27664       {
27665 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27666 	  gpkg_mode = cache->gpkg_mode;
27667       }
27668     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27669       {
27670 	  if (argc < 3)
27671 	      sqlite3_result_null (context);
27672 	  else
27673 	    {
27674 		if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
27675 		    sqlite3_result_null (context);
27676 		else
27677 		    sqlite3_result_int (context, -1);
27678 	    }
27679 	  return;
27680       }
27681     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27682       {
27683 	  if (argc < 3)
27684 	      sqlite3_result_null (context);
27685 	  else
27686 	    {
27687 		if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
27688 		    sqlite3_result_null (context);
27689 		else
27690 		    sqlite3_result_int (context, -1);
27691 	    }
27692 	  return;
27693       }
27694     if (argc >= 3)
27695       {
27696 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
27697 	      pattern = (const char *) sqlite3_value_text (argv[2]);
27698 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
27699 	      bnr = sqlite3_value_int (argv[2]);
27700 	  else
27701 	    {
27702 		sqlite3_result_null (context);
27703 		return;
27704 	    }
27705       }
27706     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
27707     n_bytes = sqlite3_value_bytes (argv[0]);
27708     geo1 =
27709 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27710 				     gpkg_amphibious);
27711     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
27712     n_bytes = sqlite3_value_bytes (argv[1]);
27713     geo2 =
27714 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27715 				     gpkg_amphibious);
27716     if (!geo1 || !geo2)
27717       {
27718 	  if (pattern == NULL)
27719 	      sqlite3_result_null (context);
27720 	  else
27721 	      sqlite3_result_int (context, -1);
27722       }
27723     else
27724       {
27725 	  void *data = sqlite3_user_data (context);
27726 	  if (pattern != NULL)
27727 	    {
27728 		/* evaluating the given intersection matrix pattern */
27729 		if (data != NULL)
27730 		    ret = gaiaGeomCollRelate_r (data, geo1, geo2, pattern);
27731 		else
27732 		    ret = gaiaGeomCollRelate (geo1, geo2, pattern);
27733 		sqlite3_result_int (context, ret);
27734 	    }
27735 	  else
27736 	    {
27737 		/* returning an intersection matrix */
27738 		if (data != NULL)
27739 		    matrix =
27740 			gaiaGeomCollRelateBoundaryNodeRule_r (data, geo1,
27741 							      geo2, bnr);
27742 		else
27743 		    matrix =
27744 			gaiaGeomCollRelateBoundaryNodeRule (geo1, geo2, bnr);
27745 		if (matrix == NULL)
27746 		    sqlite3_result_null (context);
27747 		else
27748 		    sqlite3_result_text (context, matrix, strlen (matrix),
27749 					 free);
27750 	    }
27751       }
27752     if (geo1 != NULL)
27753 	gaiaFreeGeomColl (geo1);
27754     if (geo2 != NULL)
27755 	gaiaFreeGeomColl (geo2);
27756 }
27757 
27758 static void
fnct_RelateMatch(sqlite3_context * context,int argc,sqlite3_value ** argv)27759 fnct_RelateMatch (sqlite3_context * context, int argc, sqlite3_value ** argv)
27760 {
27761 /* SQL function:
27762 / ST_RelateMatch(string matrix, string pattern)
27763 /
27764 / returns:
27765 / 1 if the intersection matrix satisfies the intersection pattern
27766 / 0 otherwise
27767 / or -1 if any error is encountered
27768 */
27769     int ret;
27770     const char *matrix;
27771     const char *pattern;
27772     void *data = sqlite3_user_data (context);
27773     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27774     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
27775       {
27776 	  sqlite3_result_int (context, -1);
27777 	  return;
27778       }
27779     else
27780 	matrix = (char *) sqlite3_value_text (argv[0]);
27781     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
27782       {
27783 	  sqlite3_result_int (context, -1);
27784 	  return;
27785       }
27786     else
27787 	pattern = (char *) sqlite3_value_text (argv[1]);
27788     if (data != NULL)
27789 	ret = gaiaIntersectionMatrixPatternMatch_r (data, matrix, pattern);
27790     else
27791 	ret = gaiaIntersectionMatrixPatternMatch (matrix, pattern);
27792     sqlite3_result_int (context, ret);
27793 }
27794 
27795 static void
fnct_Distance(sqlite3_context * context,int argc,sqlite3_value ** argv)27796 fnct_Distance (sqlite3_context * context, int argc, sqlite3_value ** argv)
27797 {
27798 /* SQL function:
27799 / Distance(BLOBencoded geom1, BLOBencoded geom2)
27800 / Distance(BLOBencoded geom1, BLOBencoded geom2, Boolen use_ellipsoid)
27801 /
27802 / returns the distance between GEOM-1 and GEOM-2
27803 */
27804     unsigned char *p_blob;
27805     int n_bytes;
27806     gaiaGeomCollPtr geo1 = NULL;
27807     gaiaGeomCollPtr geo2 = NULL;
27808     double dist;
27809     int use_ellipsoid = -1;
27810     double a;
27811     double b;
27812     double rf;
27813     int ret;
27814     sqlite3 *sqlite = sqlite3_context_db_handle (context);
27815     void *data = sqlite3_user_data (context);
27816     int gpkg_amphibious = 0;
27817     int gpkg_mode = 0;
27818     struct splite_internal_cache *cache = sqlite3_user_data (context);
27819     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
27820     if (cache != NULL)
27821       {
27822 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
27823 	  gpkg_mode = cache->gpkg_mode;
27824       }
27825     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
27826       {
27827 	  sqlite3_result_null (context);
27828 	  return;
27829       }
27830     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
27831       {
27832 	  sqlite3_result_null (context);
27833 	  return;
27834       }
27835     if (argc == 3)
27836       {
27837 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
27838 	    {
27839 		sqlite3_result_null (context);
27840 		return;
27841 	    }
27842 	  use_ellipsoid = sqlite3_value_int (argv[2]);
27843 	  if (use_ellipsoid != 0)
27844 	      use_ellipsoid = 1;
27845       }
27846     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
27847     n_bytes = sqlite3_value_bytes (argv[0]);
27848     geo1 =
27849 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27850 				     gpkg_amphibious);
27851     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
27852     n_bytes = sqlite3_value_bytes (argv[1]);
27853     geo2 =
27854 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
27855 				     gpkg_amphibious);
27856     if (!geo1 || !geo2)
27857 	sqlite3_result_null (context);
27858     else
27859       {
27860 	  if (use_ellipsoid >= 0)
27861 	    {
27862 		/* checking first if an intersection exists */
27863 		if (data != NULL)
27864 		    ret = gaiaGeomCollIntersects_r (data, geo1, geo2);
27865 		else
27866 		    ret = gaiaGeomCollIntersects (geo1, geo2);
27867 		if (ret)
27868 		  {
27869 		      /* if an intersection exists the distance is always ZERO */
27870 		      sqlite3_result_double (context, 0.0);
27871 		      goto stop;
27872 		  }
27873 
27874 		/* attempting to identify the corresponding ellipsoid */
27875 		if (getEllipsoidParams (sqlite, geo1->Srid, &a, &b, &rf))
27876 		  {
27877 		      gaiaGeomCollPtr shortest;
27878 		      if (data != NULL)
27879 			  shortest = gaiaShortestLine_r (data, geo1, geo2);
27880 		      else
27881 			  shortest = gaiaShortestLine (geo1, geo2);
27882 		      if (shortest == NULL)
27883 			  sqlite3_result_null (context);
27884 		      else if (shortest->FirstLinestring == NULL)
27885 			{
27886 			    gaiaFreeGeomColl (shortest);
27887 			    sqlite3_result_null (context);
27888 			}
27889 		      else
27890 			{
27891 			    /* computes the metric distance */
27892 			    double x0;
27893 			    double y0;
27894 			    double x1;
27895 			    double y1;
27896 			    double z;
27897 			    double m;
27898 			    gaiaLinestringPtr ln = shortest->FirstLinestring;
27899 			    dist = -1.0;
27900 			    if (ln->Points == 2)
27901 			      {
27902 				  if (ln->DimensionModel == GAIA_XY_Z)
27903 				    {
27904 					gaiaGetPointXYZ (ln->Coords, 0,
27905 							 &x0, &y0, &z);
27906 				    }
27907 				  else if (ln->DimensionModel == GAIA_XY_M)
27908 				    {
27909 					gaiaGetPointXYM (ln->Coords, 0,
27910 							 &x0, &y0, &m);
27911 				    }
27912 				  else if (ln->DimensionModel == GAIA_XY_Z_M)
27913 				    {
27914 					gaiaGetPointXYZM (ln->Coords, 0,
27915 							  &x0, &y0, &z, &m);
27916 				    }
27917 				  else
27918 				    {
27919 					gaiaGetPoint (ln->Coords, 0, &x0, &y0);
27920 				    }
27921 				  if (ln->DimensionModel == GAIA_XY_Z)
27922 				    {
27923 					gaiaGetPointXYZ (ln->Coords, 1,
27924 							 &x1, &y1, &z);
27925 				    }
27926 				  else if (ln->DimensionModel == GAIA_XY_M)
27927 				    {
27928 					gaiaGetPointXYM (ln->Coords, 1,
27929 							 &x1, &y1, &m);
27930 				    }
27931 				  else if (ln->DimensionModel == GAIA_XY_Z_M)
27932 				    {
27933 					gaiaGetPointXYZM (ln->Coords, 1,
27934 							  &x1, &y1, &z, &m);
27935 				    }
27936 				  else
27937 				    {
27938 					gaiaGetPoint (ln->Coords, 1, &x1, &y1);
27939 				    }
27940 				  if (use_ellipsoid)
27941 				      dist =
27942 					  gaiaGeodesicDistance (a, b,
27943 								rf, y0,
27944 								x0, y1, x1);
27945 				  else
27946 				    {
27947 					a = 6378137.0;
27948 					rf = 298.257223563;
27949 					b = (a * (1.0 - (1.0 / rf)));
27950 					dist =
27951 					    gaiaGreatCircleDistance (a,
27952 								     b,
27953 								     y0,
27954 								     x0,
27955 								     y1, x1);
27956 				    }
27957 				  if (dist < 0.0)
27958 				    {
27959 					/* invalid distance */
27960 					sqlite3_result_null (context);
27961 				    }
27962 				  else
27963 				      sqlite3_result_double (context, dist);
27964 			      }
27965 			    else
27966 				sqlite3_result_null (context);
27967 			    gaiaFreeGeomColl (shortest);
27968 			}
27969 		  }
27970 		else
27971 		    sqlite3_result_null (context);
27972 		goto stop;
27973 	    }
27974 	  else
27975 	    {
27976 		if (data != NULL)
27977 		    ret = gaiaGeomCollDistance_r (data, geo1, geo2, &dist);
27978 		else
27979 		    ret = gaiaGeomCollDistance (geo1, geo2, &dist);
27980 		if (!ret)
27981 		    sqlite3_result_null (context);
27982 		else
27983 		    sqlite3_result_double (context, dist);
27984 	    }
27985       }
27986   stop:
27987     gaiaFreeGeomColl (geo1);
27988     gaiaFreeGeomColl (geo2);
27989 }
27990 
27991 static void
fnct_PtDistWithin(sqlite3_context * context,int argc,sqlite3_value ** argv)27992 fnct_PtDistWithin (sqlite3_context * context, int argc, sqlite3_value ** argv)
27993 {
27994 /* SQL function:
27995 / PtDistWithin(BLOBencoded geom1, BLOBencoded geom2, double dist
27996 / [, boolen use_spheroid])
27997 /
27998 / returns TRUE if the distance between GEOM-1 and GEOM-2
27999 / is less or equal to dist
28000 /
28001 / - if both geom1 and geom2 are in the 4326 (WGS84) SRID,
28002 /   (and does actually contains a single POINT each one)
28003 /   dist is assumed to be measured in Meters
28004 / - in this case the optional arg use_spheroid is
28005 /   checked to determine if geodesic distance has to be
28006 /   computed on the sphere (quickest) or on the spheroid
28007 /   default: use_spheroid = FALSE
28008 /
28009 / in any other case the "plain" distance is evaluated
28010 */
28011     unsigned char *p_blob;
28012     int n_bytes;
28013     gaiaGeomCollPtr geo1 = NULL;
28014     gaiaGeomCollPtr geo2 = NULL;
28015     gaiaPointPtr pt;
28016     gaiaLinestringPtr ln;
28017     gaiaPolygonPtr pg;
28018     double ref_dist;
28019     int use_spheroid = 0;
28020     double x0 = 0.0;
28021     double y0 = 0.0;
28022     double x1 = 0.0;
28023     double y1 = 0.0;
28024     int pt0 = 0;
28025     int ln0 = 0;
28026     int pg0 = 0;
28027     int pt1 = 0;
28028     int ln1 = 0;
28029     int pg1 = 0;
28030     double dist;
28031     double a;
28032     double b;
28033     double rf;
28034     int ret;
28035     void *data = sqlite3_user_data (context);
28036     int gpkg_amphibious = 0;
28037     int gpkg_mode = 0;
28038     struct splite_internal_cache *cache = sqlite3_user_data (context);
28039     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28040     if (cache != NULL)
28041       {
28042 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28043 	  gpkg_mode = cache->gpkg_mode;
28044       }
28045     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28046       {
28047 	  sqlite3_result_null (context);
28048 	  return;
28049       }
28050     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
28051       {
28052 	  sqlite3_result_null (context);
28053 	  return;
28054       }
28055     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER
28056 	|| sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
28057 	;
28058     else
28059       {
28060 	  sqlite3_result_null (context);
28061 	  return;
28062       }
28063     if (argc == 4)
28064       {
28065 	  /* optional use_spheroid arg */
28066 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
28067 	    {
28068 		sqlite3_result_null (context);
28069 		return;
28070 	    }
28071       }
28072     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28073     n_bytes = sqlite3_value_bytes (argv[0]);
28074     geo1 =
28075 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28076 				     gpkg_amphibious);
28077     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
28078     n_bytes = sqlite3_value_bytes (argv[1]);
28079     geo2 =
28080 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28081 				     gpkg_amphibious);
28082     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
28083       {
28084 	  int dst = sqlite3_value_int (argv[2]);
28085 	  ref_dist = dst;
28086       }
28087     else
28088 	ref_dist = sqlite3_value_double (argv[2]);
28089     if (argc == 4)
28090 	use_spheroid = sqlite3_value_int (argv[3]);
28091     if (!geo1 || !geo2)
28092 	sqlite3_result_null (context);
28093     else
28094       {
28095 	  if (geo1->Srid == 4326 && geo2->Srid == 4326)
28096 	    {
28097 		/* checking for single points */
28098 		pt = geo1->FirstPoint;
28099 		while (pt)
28100 		  {
28101 		      x0 = pt->X;
28102 		      y0 = pt->Y;
28103 		      pt0++;
28104 		      pt = pt->Next;
28105 		  }
28106 		ln = geo1->FirstLinestring;
28107 		while (ln)
28108 		  {
28109 		      ln0++;
28110 		      ln = ln->Next;
28111 		  }
28112 		pg = geo1->FirstPolygon;
28113 		while (pg)
28114 		  {
28115 		      pg0++;
28116 		      pg = pg->Next;
28117 		  }
28118 		pt = geo2->FirstPoint;
28119 		while (pt)
28120 		  {
28121 		      x1 = pt->X;
28122 		      y1 = pt->Y;
28123 		      pt1++;
28124 		      pt = pt->Next;
28125 		  }
28126 		ln = geo2->FirstLinestring;
28127 		while (ln)
28128 		  {
28129 		      ln1++;
28130 		      ln = ln->Next;
28131 		  }
28132 		pg = geo2->FirstPolygon;
28133 		while (pg)
28134 		  {
28135 		      pg1++;
28136 		      pg = pg->Next;
28137 		  }
28138 		if (pt0 == 1 && pt1 == 1 && ln0 == 0 && ln1 == 0 && pg0 == 0
28139 		    && pg1 == 0)
28140 		  {
28141 		      /* using geodesic distance */
28142 		      a = 6378137.0;
28143 		      rf = 298.257223563;
28144 		      b = (a * (1.0 - (1.0 / rf)));
28145 		      if (use_spheroid)
28146 			{
28147 			    dist =
28148 				gaiaGeodesicDistance (a, b, rf, y0, x0, y1, x1);
28149 			    if (dist <= ref_dist)
28150 				sqlite3_result_int (context, 1);
28151 			    else
28152 				sqlite3_result_int (context, 0);
28153 			}
28154 		      else
28155 			{
28156 			    dist =
28157 				gaiaGreatCircleDistance (a, b, y0, x0, y1, x1);
28158 			    if (dist <= ref_dist)
28159 				sqlite3_result_int (context, 1);
28160 			    else
28161 				sqlite3_result_int (context, 0);
28162 			}
28163 		      goto stop;
28164 		  }
28165 	    }
28166 /* defaulting to flat distance */
28167 	  if (data != NULL)
28168 	      ret = gaiaGeomCollDistance_r (data, geo1, geo2, &dist);
28169 	  else
28170 	      ret = gaiaGeomCollDistance (geo1, geo2, &dist);
28171 	  if (!ret)
28172 	      sqlite3_result_null (context);
28173 	  if (dist <= ref_dist)
28174 	      sqlite3_result_int (context, 1);
28175 	  else
28176 	      sqlite3_result_int (context, 0);
28177       }
28178   stop:
28179     gaiaFreeGeomColl (geo1);
28180     gaiaFreeGeomColl (geo2);
28181 }
28182 
28183 SPATIALITE_PRIVATE void
geos_error(const char * fmt,...)28184 geos_error (const char *fmt, ...)
28185 {
28186 /* reporting some GEOS error */
28187     va_list ap;
28188     char *msg;
28189     va_start (ap, fmt);
28190     msg = sqlite3_vmprintf (fmt, ap);
28191     va_end (ap);
28192     if (msg)
28193       {
28194 	  spatialite_e ("GEOS error: %s\n", msg);
28195 	  gaiaSetGeosErrorMsg (msg);
28196 	  sqlite3_free (msg);
28197       }
28198     else
28199 	gaiaSetGeosErrorMsg (NULL);
28200 }
28201 
28202 SPATIALITE_PRIVATE void
geos_warning(const char * fmt,...)28203 geos_warning (const char *fmt, ...)
28204 {
28205 /* reporting some GEOS warning */
28206     va_list ap;
28207     char *msg;
28208     va_start (ap, fmt);
28209     msg = sqlite3_vmprintf (fmt, ap);
28210     va_end (ap);
28211     if (msg)
28212       {
28213 	  spatialite_e ("GEOS warning: %s\n", msg);
28214 	  gaiaSetGeosWarningMsg (msg);
28215 	  sqlite3_free (msg);
28216       }
28217     else
28218 	gaiaSetGeosWarningMsg (NULL);
28219 }
28220 
28221 static void
fnct_aux_polygonize(sqlite3_context * context,gaiaGeomCollPtr geom_org,int force_multipolygon,int allow_multipolygon)28222 fnct_aux_polygonize (sqlite3_context * context, gaiaGeomCollPtr geom_org,
28223 		     int force_multipolygon, int allow_multipolygon)
28224 {
28225 /* a  common function performing any kind of polygonization op */
28226     gaiaGeomCollPtr geom_new = NULL;
28227     int len;
28228     unsigned char *p_result = NULL;
28229     gaiaPolygonPtr pg;
28230     int pgs = 0;
28231     void *data = sqlite3_user_data (context);
28232     int gpkg_mode = 0;
28233     int tiny_point = 0;
28234     struct splite_internal_cache *cache = sqlite3_user_data (context);
28235     if (cache != NULL)
28236       {
28237 	  gpkg_mode = cache->gpkg_mode;
28238 	  tiny_point = cache->tinyPointEnabled;
28239       }
28240     if (!geom_org)
28241 	goto invalid;
28242     if (data != NULL)
28243 	geom_new = gaiaPolygonize_r (data, geom_org, force_multipolygon);
28244     else
28245 	geom_new = gaiaPolygonize (geom_org, force_multipolygon);
28246     if (!geom_new)
28247 	goto invalid;
28248     gaiaFreeGeomColl (geom_org);
28249     pg = geom_new->FirstPolygon;
28250     while (pg)
28251       {
28252 	  pgs++;
28253 	  pg = pg->Next;
28254       }
28255     if (pgs > 1 && allow_multipolygon == 0)
28256       {
28257 	  /* invalid: a POLYGON is expected !!! */
28258 	  gaiaFreeGeomColl (geom_new);
28259 	  sqlite3_result_null (context);
28260 	  return;
28261       }
28262     gaiaToSpatiaLiteBlobWkbEx2 (geom_new, &p_result, &len, gpkg_mode,
28263 				tiny_point);
28264     gaiaFreeGeomColl (geom_new);
28265     sqlite3_result_blob (context, p_result, len, free);
28266     return;
28267   invalid:
28268     if (geom_org)
28269 	gaiaFreeGeomColl (geom_org);
28270     sqlite3_result_null (context);
28271 }
28272 
28273 /*
28274 / the following functions performs initial argument checking,
28275 / and then readdressing the request to fnct_aux_polygonize()
28276 / for actual processing
28277 */
28278 
28279 static void
fnct_BdPolyFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)28280 fnct_BdPolyFromText1 (sqlite3_context * context, int argc,
28281 		      sqlite3_value ** argv)
28282 {
28283 /* SQL function:
28284 / BdPolyFromText(WKT encoded MULTILINESTRING)
28285 /
28286 / returns the current geometry [POLYGON] by parsing a WKT encoded MULTILINESTRING
28287 / or NULL if any error is encountered
28288 /
28289 */
28290     const unsigned char *text;
28291     gaiaGeomCollPtr geo = NULL;
28292     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28293     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
28294       {
28295 	  sqlite3_result_null (context);
28296 	  return;
28297       }
28298     text = sqlite3_value_text (argv[0]);
28299     geo = gaiaParseWkt (text, -1);
28300     if (geo == NULL)
28301       {
28302 	  sqlite3_result_null (context);
28303 	  return;
28304       }
28305     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28306       {
28307 	  gaiaFreeGeomColl (geo);
28308 	  sqlite3_result_null (context);
28309 	  return;
28310       }
28311     geo->Srid = 0;
28312     fnct_aux_polygonize (context, geo, 0, 0);
28313     return;
28314 }
28315 
28316 static void
fnct_BdPolyFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)28317 fnct_BdPolyFromText2 (sqlite3_context * context, int argc,
28318 		      sqlite3_value ** argv)
28319 {
28320 /* SQL function:
28321 / BdPolyFromText(WKT encoded MULTILINESTRING, SRID)
28322 /
28323 / returns the current geometry [POLYGON] by parsing a WKT encoded MULTILINESTRING
28324 / or NULL if any error is encountered
28325 /
28326 */
28327     const unsigned char *text;
28328     gaiaGeomCollPtr geo = NULL;
28329     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28330     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
28331       {
28332 	  sqlite3_result_null (context);
28333 	  return;
28334       }
28335     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
28336       {
28337 	  sqlite3_result_null (context);
28338 	  return;
28339       }
28340     text = sqlite3_value_text (argv[0]);
28341     geo = gaiaParseWkt (text, -1);
28342     if (geo == NULL)
28343       {
28344 	  sqlite3_result_null (context);
28345 	  return;
28346       }
28347     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28348       {
28349 	  gaiaFreeGeomColl (geo);
28350 	  sqlite3_result_null (context);
28351 	  return;
28352       }
28353     geo->Srid = sqlite3_value_int (argv[1]);
28354     fnct_aux_polygonize (context, geo, 0, 0);
28355     return;
28356 }
28357 
28358 static void
fnct_BdMPolyFromText1(sqlite3_context * context,int argc,sqlite3_value ** argv)28359 fnct_BdMPolyFromText1 (sqlite3_context * context, int argc,
28360 		       sqlite3_value ** argv)
28361 {
28362 /* SQL function:
28363 / BdMPolyFromText(WKT encoded MULTILINESTRING)
28364 /
28365 / returns the current geometry [MULTIPOLYGON] by parsing a WKT encoded MULTILINESTRING
28366 / or NULL if any error is encountered
28367 /
28368 */
28369     const unsigned char *text;
28370     gaiaGeomCollPtr geo = NULL;
28371     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28372     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
28373       {
28374 	  sqlite3_result_null (context);
28375 	  return;
28376       }
28377     text = sqlite3_value_text (argv[0]);
28378     geo = gaiaParseWkt (text, -1);
28379     if (geo == NULL)
28380       {
28381 	  sqlite3_result_null (context);
28382 	  return;
28383       }
28384     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28385       {
28386 	  gaiaFreeGeomColl (geo);
28387 	  sqlite3_result_null (context);
28388 	  return;
28389       }
28390     geo->Srid = 0;
28391     fnct_aux_polygonize (context, geo, 1, 1);
28392     return;
28393 }
28394 
28395 static void
fnct_BdMPolyFromText2(sqlite3_context * context,int argc,sqlite3_value ** argv)28396 fnct_BdMPolyFromText2 (sqlite3_context * context, int argc,
28397 		       sqlite3_value ** argv)
28398 {
28399 /* SQL function:
28400 / BdMPolyFromText(WKT encoded MULTILINESTRING, SRID)
28401 /
28402 / returns the current geometry [MULTIPOLYGON] by parsing a WKT encoded MULTILINESTRING
28403 / or NULL if any error is encountered
28404 /
28405 */
28406     const unsigned char *text;
28407     gaiaGeomCollPtr geo = NULL;
28408     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28409     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
28410       {
28411 	  sqlite3_result_null (context);
28412 	  return;
28413       }
28414     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
28415       {
28416 	  sqlite3_result_null (context);
28417 	  return;
28418       }
28419     text = sqlite3_value_text (argv[0]);
28420     geo = gaiaParseWkt (text, -1);
28421     if (geo == NULL)
28422       {
28423 	  sqlite3_result_null (context);
28424 	  return;
28425       }
28426     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28427       {
28428 	  gaiaFreeGeomColl (geo);
28429 	  sqlite3_result_null (context);
28430 	  return;
28431       }
28432     geo->Srid = sqlite3_value_int (argv[1]);
28433     fnct_aux_polygonize (context, geo, 1, 1);
28434     return;
28435 }
28436 
28437 static void
fnct_BdPolyFromWKB1(sqlite3_context * context,int argc,sqlite3_value ** argv)28438 fnct_BdPolyFromWKB1 (sqlite3_context * context, int argc, sqlite3_value ** argv)
28439 {
28440 /* SQL function:
28441 / BdPolyFromWKB(WKB encoded MULTILINESTRING)
28442 /
28443 / returns the current geometry [POLYGON] by parsing a WKB encoded MULTILINESTRING
28444 / or NULL if any error is encountered
28445 /
28446 */
28447     int n_bytes;
28448     const unsigned char *wkb;
28449     gaiaGeomCollPtr geo = NULL;
28450     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28451     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28452       {
28453 	  sqlite3_result_null (context);
28454 	  return;
28455       }
28456     wkb = sqlite3_value_blob (argv[0]);
28457     n_bytes = sqlite3_value_bytes (argv[0]);
28458     if (!check_wkb (wkb, n_bytes, -1))
28459 	return;
28460     geo = gaiaFromWkb (wkb, n_bytes);
28461     if (geo == NULL)
28462       {
28463 	  sqlite3_result_null (context);
28464 	  return;
28465       }
28466     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28467       {
28468 	  gaiaFreeGeomColl (geo);
28469 	  sqlite3_result_null (context);
28470 	  return;
28471       }
28472     geo->Srid = 0;
28473     fnct_aux_polygonize (context, geo, 0, 0);
28474     return;
28475 }
28476 
28477 static void
fnct_BdPolyFromWKB2(sqlite3_context * context,int argc,sqlite3_value ** argv)28478 fnct_BdPolyFromWKB2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
28479 {
28480 /* SQL function:
28481 / BdPolyFromWKB(WKB encoded MULTILINESTRING)
28482 /
28483 / returns the current geometry [POLYGON] by parsing a WKB encoded MULTILINESTRING
28484 / or NULL if any error is encountered
28485 /
28486 */
28487     int n_bytes;
28488     const unsigned char *wkb;
28489     gaiaGeomCollPtr geo = NULL;
28490     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28491     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28492       {
28493 	  sqlite3_result_null (context);
28494 	  return;
28495       }
28496     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
28497       {
28498 	  sqlite3_result_null (context);
28499 	  return;
28500       }
28501     wkb = sqlite3_value_blob (argv[0]);
28502     n_bytes = sqlite3_value_bytes (argv[0]);
28503     if (!check_wkb (wkb, n_bytes, -1))
28504 	return;
28505     geo = gaiaFromWkb (wkb, n_bytes);
28506     if (geo == NULL)
28507       {
28508 	  sqlite3_result_null (context);
28509 	  return;
28510       }
28511     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28512       {
28513 	  gaiaFreeGeomColl (geo);
28514 	  sqlite3_result_null (context);
28515 	  return;
28516       }
28517     geo->Srid = sqlite3_value_int (argv[1]);
28518     fnct_aux_polygonize (context, geo, 0, 0);
28519     return;
28520 }
28521 
28522 static void
fnct_BdMPolyFromWKB1(sqlite3_context * context,int argc,sqlite3_value ** argv)28523 fnct_BdMPolyFromWKB1 (sqlite3_context * context, int argc,
28524 		      sqlite3_value ** argv)
28525 {
28526 /* SQL function:
28527 / BdMPolyFromWKB(WKB encoded MULTILINESTRING)
28528 /
28529 / returns the current geometry [MULTIPOLYGON] by parsing a WKB encoded MULTILINESTRING
28530 / or NULL if any error is encountered
28531 /
28532 */
28533     int n_bytes;
28534     const unsigned char *wkb;
28535     gaiaGeomCollPtr geo = NULL;
28536     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28537     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28538       {
28539 	  sqlite3_result_null (context);
28540 	  return;
28541       }
28542     wkb = sqlite3_value_blob (argv[0]);
28543     n_bytes = sqlite3_value_bytes (argv[0]);
28544     if (!check_wkb (wkb, n_bytes, -1))
28545 	return;
28546     geo = gaiaFromWkb (wkb, n_bytes);
28547     if (geo == NULL)
28548       {
28549 	  sqlite3_result_null (context);
28550 	  return;
28551       }
28552     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28553       {
28554 	  gaiaFreeGeomColl (geo);
28555 	  sqlite3_result_null (context);
28556 	  return;
28557       }
28558     geo->Srid = 0;
28559     fnct_aux_polygonize (context, geo, 1, 1);
28560     return;
28561 }
28562 
28563 static void
fnct_BdMPolyFromWKB2(sqlite3_context * context,int argc,sqlite3_value ** argv)28564 fnct_BdMPolyFromWKB2 (sqlite3_context * context, int argc,
28565 		      sqlite3_value ** argv)
28566 {
28567 /* SQL function:
28568 / BdMPolyFromWKB(WKB encoded MULTILINESTRING)
28569 /
28570 / returns the current geometry [MULTIPOLYGON] by parsing a WKB encoded MULTILINESTRING
28571 / or NULL if any error is encountered
28572 /
28573 */
28574     int n_bytes;
28575     const unsigned char *wkb;
28576     gaiaGeomCollPtr geo = NULL;
28577     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28578     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28579       {
28580 	  sqlite3_result_null (context);
28581 	  return;
28582       }
28583     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
28584       {
28585 	  sqlite3_result_null (context);
28586 	  return;
28587       }
28588     wkb = sqlite3_value_blob (argv[0]);
28589     n_bytes = sqlite3_value_bytes (argv[0]);
28590     if (!check_wkb (wkb, n_bytes, -1))
28591 	return;
28592     geo = gaiaFromWkb (wkb, n_bytes);
28593     if (geo == NULL)
28594       {
28595 	  sqlite3_result_null (context);
28596 	  return;
28597       }
28598     if (geo->DeclaredType != GAIA_MULTILINESTRING)
28599       {
28600 	  gaiaFreeGeomColl (geo);
28601 	  sqlite3_result_null (context);
28602 	  return;
28603       }
28604     geo->Srid = sqlite3_value_int (argv[1]);
28605     fnct_aux_polygonize (context, geo, 1, 1);
28606     return;
28607 }
28608 
28609 static void
fnct_OffsetCurve(sqlite3_context * context,int argc,sqlite3_value ** argv)28610 fnct_OffsetCurve (sqlite3_context * context, int argc, sqlite3_value ** argv)
28611 {
28612 /* SQL function:
28613 / OffsetCurve(BLOBencoded geometry, DOUBLE radius)
28614 /
28615 / returns a new geometry representing the OFFSET-CURVE for current geometry
28616 / [a LINESTRING is expected]
28617 / or NULL if any error is encountered
28618 /
28619 / negative radius: right-side / positive radius: left-side
28620 */
28621     unsigned char *p_blob;
28622     int n_bytes;
28623     gaiaGeomCollPtr geo = NULL;
28624     gaiaGeomCollPtr result;
28625     double radius;
28626     int int_value;
28627     int gpkg_amphibious = 0;
28628     int gpkg_mode = 0;
28629     int tiny_point = 0;
28630     struct splite_internal_cache *cache = sqlite3_user_data (context);
28631     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28632     if (cache != NULL)
28633       {
28634 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28635 	  gpkg_mode = cache->gpkg_mode;
28636 	  tiny_point = cache->tinyPointEnabled;
28637       }
28638     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28639       {
28640 	  sqlite3_result_null (context);
28641 	  return;
28642       }
28643     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
28644 	radius = sqlite3_value_double (argv[1]);
28645     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
28646       {
28647 	  int_value = sqlite3_value_int (argv[1]);
28648 	  radius = int_value;
28649       }
28650     else
28651       {
28652 	  sqlite3_result_null (context);
28653 	  return;
28654       }
28655     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28656     n_bytes = sqlite3_value_bytes (argv[0]);
28657     geo =
28658 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28659 				     gpkg_amphibious);
28660     if (!geo)
28661 	sqlite3_result_null (context);
28662     else
28663       {
28664 	  void *data = sqlite3_user_data (context);
28665 	  if (data != NULL)
28666 	      result = gaiaOffsetCurve_r (data, geo, radius, 16, 0);
28667 	  else
28668 	      result = gaiaOffsetCurve (geo, radius, 16, 0);
28669 	  if (!result)
28670 	      sqlite3_result_null (context);
28671 	  else
28672 	    {
28673 		/* builds the BLOB geometry to be returned */
28674 		int len;
28675 		unsigned char *p_result = NULL;
28676 		result->Srid = geo->Srid;
28677 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
28678 					    gpkg_mode, tiny_point);
28679 		sqlite3_result_blob (context, p_result, len, free);
28680 		gaiaFreeGeomColl (result);
28681 	    }
28682       }
28683     gaiaFreeGeomColl (geo);
28684 }
28685 
28686 static void
fnct_SingleSidedBuffer(sqlite3_context * context,int argc,sqlite3_value ** argv)28687 fnct_SingleSidedBuffer (sqlite3_context * context, int argc,
28688 			sqlite3_value ** argv)
28689 {
28690 /* SQL function:
28691 / SingleSidedBuffer(BLOBencoded geometry, radius, left-or-right-side)
28692 /
28693 / returns a new geometry representing the SingleSided BUFFER
28694 / for current geometry [a LINESTRING is expected]
28695 / or NULL if any error is encountered
28696 */
28697     unsigned char *p_blob;
28698     int n_bytes;
28699     gaiaGeomCollPtr geo = NULL;
28700     gaiaGeomCollPtr result;
28701     double radius;
28702     int int_value;
28703     int left_right;
28704     int gpkg_amphibious = 0;
28705     int gpkg_mode = 0;
28706     int tiny_point = 0;
28707     struct splite_internal_cache *cache = sqlite3_user_data (context);
28708     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28709     if (cache != NULL)
28710       {
28711 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28712 	  gpkg_mode = cache->gpkg_mode;
28713 	  tiny_point = cache->tinyPointEnabled;
28714       }
28715     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28716       {
28717 	  sqlite3_result_null (context);
28718 	  return;
28719       }
28720     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
28721 	radius = sqlite3_value_double (argv[1]);
28722     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
28723       {
28724 	  int_value = sqlite3_value_int (argv[1]);
28725 	  radius = int_value;
28726       }
28727     else
28728       {
28729 	  sqlite3_result_null (context);
28730 	  return;
28731       }
28732     if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
28733 	left_right = sqlite3_value_int (argv[2]);
28734     else
28735       {
28736 	  sqlite3_result_null (context);
28737 	  return;
28738       }
28739     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28740     n_bytes = sqlite3_value_bytes (argv[0]);
28741     geo =
28742 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28743 				     gpkg_amphibious);
28744     if (!geo)
28745 	sqlite3_result_null (context);
28746     else
28747       {
28748 	  void *data = sqlite3_user_data (context);
28749 	  if (data != NULL)
28750 	      result =
28751 		  gaiaSingleSidedBuffer_r (data, geo, radius, -1, left_right);
28752 	  else
28753 	      result = gaiaSingleSidedBuffer (geo, radius, 16, left_right);
28754 	  if (!result)
28755 	      sqlite3_result_null (context);
28756 	  else
28757 	    {
28758 		/* builds the BLOB geometry to be returned */
28759 		int len;
28760 		unsigned char *p_result = NULL;
28761 		result->Srid = geo->Srid;
28762 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
28763 					    gpkg_mode, tiny_point);
28764 		sqlite3_result_blob (context, p_result, len, free);
28765 		gaiaFreeGeomColl (result);
28766 	    }
28767       }
28768     gaiaFreeGeomColl (geo);
28769 }
28770 
28771 static void
fnct_HausdorffDistance(sqlite3_context * context,int argc,sqlite3_value ** argv)28772 fnct_HausdorffDistance (sqlite3_context * context, int argc,
28773 			sqlite3_value ** argv)
28774 {
28775 /* SQL function:
28776 / HausdorffDistance(BLOBencoded geom1, BLOBencoded geom2)
28777 /
28778 / returns the discrete Hausdorff distance between GEOM-1 and GEOM-2
28779 */
28780     unsigned char *p_blob;
28781     int n_bytes;
28782     gaiaGeomCollPtr geo1 = NULL;
28783     gaiaGeomCollPtr geo2 = NULL;
28784     double dist;
28785     int ret;
28786     int gpkg_amphibious = 0;
28787     int gpkg_mode = 0;
28788     struct splite_internal_cache *cache = sqlite3_user_data (context);
28789     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28790     if (cache != NULL)
28791       {
28792 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28793 	  gpkg_mode = cache->gpkg_mode;
28794       }
28795     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28796       {
28797 	  sqlite3_result_null (context);
28798 	  return;
28799       }
28800     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
28801       {
28802 	  sqlite3_result_null (context);
28803 	  return;
28804       }
28805     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28806     n_bytes = sqlite3_value_bytes (argv[0]);
28807     geo1 =
28808 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28809 				     gpkg_amphibious);
28810     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
28811     n_bytes = sqlite3_value_bytes (argv[1]);
28812     geo2 =
28813 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28814 				     gpkg_amphibious);
28815     if (!geo1 || !geo2)
28816 	sqlite3_result_null (context);
28817     else
28818       {
28819 	  void *data = sqlite3_user_data (context);
28820 	  if (data != NULL)
28821 	      ret = gaiaHausdorffDistance_r (data, geo1, geo2, &dist);
28822 	  else
28823 	      ret = gaiaHausdorffDistance (geo1, geo2, &dist);
28824 	  if (!ret)
28825 	      sqlite3_result_null (context);
28826 	  sqlite3_result_double (context, dist);
28827       }
28828     gaiaFreeGeomColl (geo1);
28829     gaiaFreeGeomColl (geo2);
28830 }
28831 
28832 #ifdef GEOS_370			/* only if GEOS_370 support is available */
28833 
28834 static void
fnct_HausdorffDistanceDensify(sqlite3_context * context,int argc,sqlite3_value ** argv)28835 fnct_HausdorffDistanceDensify (sqlite3_context * context, int argc,
28836 			       sqlite3_value ** argv)
28837 {
28838 /* SQL function:
28839 / HausdorffDistance(BLOBencoded geom1, BLOBencoded geom2, double densify_fract)
28840 /
28841 / returns the discrete Hausdorff distance between GEOM-1 and GEOM-2
28842 */
28843     unsigned char *p_blob;
28844     int n_bytes;
28845     gaiaGeomCollPtr geo1 = NULL;
28846     gaiaGeomCollPtr geo2 = NULL;
28847     double densify_fract;
28848     double dist;
28849     int ret;
28850     int gpkg_amphibious = 0;
28851     int gpkg_mode = 0;
28852     struct splite_internal_cache *cache = sqlite3_user_data (context);
28853     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28854     if (cache != NULL)
28855       {
28856 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28857 	  gpkg_mode = cache->gpkg_mode;
28858       }
28859     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28860       {
28861 	  sqlite3_result_null (context);
28862 	  return;
28863       }
28864     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
28865       {
28866 	  sqlite3_result_null (context);
28867 	  return;
28868       }
28869     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
28870       {
28871 	  densify_fract = sqlite3_value_double (argv[2]);
28872 	  if (densify_fract > 0.0 && densify_fract < 1.0)
28873 	      ;
28874 	  else
28875 	    {
28876 		sqlite3_result_null (context);
28877 		return;
28878 	    }
28879       }
28880     else
28881       {
28882 	  sqlite3_result_null (context);
28883 	  return;
28884       }
28885     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28886     n_bytes = sqlite3_value_bytes (argv[0]);
28887     geo1 =
28888 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28889 				     gpkg_amphibious);
28890     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
28891     n_bytes = sqlite3_value_bytes (argv[1]);
28892     geo2 =
28893 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28894 				     gpkg_amphibious);
28895     if (!geo1 || !geo2)
28896 	sqlite3_result_null (context);
28897     else
28898       {
28899 	  void *data = sqlite3_user_data (context);
28900 	  if (data != NULL)
28901 	      ret =
28902 		  gaiaHausdorffDistanceDensify_r (data, geo1, geo2,
28903 						  densify_fract, &dist);
28904 	  else
28905 	      ret =
28906 		  gaiaHausdorffDistanceDensify (geo1, geo2, densify_fract,
28907 						&dist);
28908 	  if (!ret)
28909 	      sqlite3_result_null (context);
28910 	  sqlite3_result_double (context, dist);
28911       }
28912     gaiaFreeGeomColl (geo1);
28913     gaiaFreeGeomColl (geo2);
28914 }
28915 
28916 static void
fnct_FrechetDistance(sqlite3_context * context,int argc,sqlite3_value ** argv)28917 fnct_FrechetDistance (sqlite3_context * context, int argc,
28918 		      sqlite3_value ** argv)
28919 {
28920 /* SQL function:
28921 / FrechetDistance(BLOBencoded geom1, BLOBencoded geom2)
28922 /
28923 / returns the discrete Frechet distance between GEOM-1 and GEOM-2
28924 */
28925     unsigned char *p_blob;
28926     int n_bytes;
28927     gaiaGeomCollPtr geo1 = NULL;
28928     gaiaGeomCollPtr geo2 = NULL;
28929     double dist;
28930     int ret;
28931     int gpkg_amphibious = 0;
28932     int gpkg_mode = 0;
28933     struct splite_internal_cache *cache = sqlite3_user_data (context);
28934     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28935     if (cache != NULL)
28936       {
28937 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
28938 	  gpkg_mode = cache->gpkg_mode;
28939       }
28940     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
28941       {
28942 	  sqlite3_result_null (context);
28943 	  return;
28944       }
28945     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
28946       {
28947 	  sqlite3_result_null (context);
28948 	  return;
28949       }
28950     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
28951     n_bytes = sqlite3_value_bytes (argv[0]);
28952     geo1 =
28953 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28954 				     gpkg_amphibious);
28955     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
28956     n_bytes = sqlite3_value_bytes (argv[1]);
28957     geo2 =
28958 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
28959 				     gpkg_amphibious);
28960     if (!geo1 || !geo2)
28961 	sqlite3_result_null (context);
28962     else
28963       {
28964 	  void *data = sqlite3_user_data (context);
28965 	  if (data != NULL)
28966 	      ret = gaiaFrechetDistance_r (data, geo1, geo2, &dist);
28967 	  else
28968 	      ret = gaiaFrechetDistance (geo1, geo2, &dist);
28969 	  if (!ret)
28970 	      sqlite3_result_null (context);
28971 	  sqlite3_result_double (context, dist);
28972       }
28973     gaiaFreeGeomColl (geo1);
28974     gaiaFreeGeomColl (geo2);
28975 }
28976 
28977 static void
fnct_FrechetDistanceDensify(sqlite3_context * context,int argc,sqlite3_value ** argv)28978 fnct_FrechetDistanceDensify (sqlite3_context * context, int argc,
28979 			     sqlite3_value ** argv)
28980 {
28981 /* SQL function:
28982 / FrechetDistance(BLOBencoded geom1, BLOBencoded geom2, double densify_fract)
28983 /
28984 / returns the discrete Frechet distance between GEOM-1 and GEOM-2
28985 */
28986     unsigned char *p_blob;
28987     int n_bytes;
28988     gaiaGeomCollPtr geo1 = NULL;
28989     gaiaGeomCollPtr geo2 = NULL;
28990     double densify_fract;
28991     double dist;
28992     int ret;
28993     int gpkg_amphibious = 0;
28994     int gpkg_mode = 0;
28995     struct splite_internal_cache *cache = sqlite3_user_data (context);
28996     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
28997     if (cache != NULL)
28998       {
28999 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29000 	  gpkg_mode = cache->gpkg_mode;
29001       }
29002     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29003       {
29004 	  sqlite3_result_null (context);
29005 	  return;
29006       }
29007     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29008       {
29009 	  sqlite3_result_null (context);
29010 	  return;
29011       }
29012     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
29013       {
29014 	  densify_fract = sqlite3_value_double (argv[2]);
29015 	  if (densify_fract > 0.0 && densify_fract < 1.0)
29016 	      ;
29017 	  else
29018 	    {
29019 		sqlite3_result_null (context);
29020 		return;
29021 	    }
29022       }
29023     else
29024       {
29025 	  sqlite3_result_null (context);
29026 	  return;
29027       }
29028     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29029     n_bytes = sqlite3_value_bytes (argv[0]);
29030     geo1 =
29031 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29032 				     gpkg_amphibious);
29033     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29034     n_bytes = sqlite3_value_bytes (argv[1]);
29035     geo2 =
29036 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29037 				     gpkg_amphibious);
29038     if (!geo1 || !geo2)
29039 	sqlite3_result_null (context);
29040     else
29041       {
29042 	  void *data = sqlite3_user_data (context);
29043 	  if (data != NULL)
29044 	      ret =
29045 		  gaiaFrechetDistanceDensify_r (data, geo1, geo2, densify_fract,
29046 						&dist);
29047 	  else
29048 	      ret =
29049 		  gaiaFrechetDistanceDensify (geo1, geo2, densify_fract, &dist);
29050 	  if (!ret)
29051 	      sqlite3_result_null (context);
29052 	  sqlite3_result_double (context, dist);
29053       }
29054     gaiaFreeGeomColl (geo1);
29055     gaiaFreeGeomColl (geo2);
29056 }
29057 
29058 #endif /* end GEOS_370 conditional */
29059 
29060 static void
fnct_SharedPaths(sqlite3_context * context,int argc,sqlite3_value ** argv)29061 fnct_SharedPaths (sqlite3_context * context, int argc, sqlite3_value ** argv)
29062 {
29063 /* SQL function:
29064 / SharedPaths(BLOBencoded geometry1, BLOBencoded geometry2)
29065 /
29066 / returns a new geometry representing common (shared) Edges
29067 / [two LINESTRINGs/MULTILINESTRINGs are expected]
29068 / or NULL if any error is encountered
29069 */
29070     unsigned char *p_blob;
29071     int n_bytes;
29072     gaiaGeomCollPtr geo1 = NULL;
29073     gaiaGeomCollPtr geo2 = NULL;
29074     gaiaGeomCollPtr result;
29075     int gpkg_amphibious = 0;
29076     int gpkg_mode = 0;
29077     int tiny_point = 0;
29078     struct splite_internal_cache *cache = sqlite3_user_data (context);
29079     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29080     if (cache != NULL)
29081       {
29082 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29083 	  gpkg_mode = cache->gpkg_mode;
29084 	  tiny_point = cache->tinyPointEnabled;
29085       }
29086     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29087       {
29088 	  sqlite3_result_null (context);
29089 	  return;
29090       }
29091     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29092       {
29093 	  sqlite3_result_null (context);
29094 	  return;
29095       }
29096     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29097     n_bytes = sqlite3_value_bytes (argv[0]);
29098     geo1 =
29099 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29100 				     gpkg_amphibious);
29101     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29102     n_bytes = sqlite3_value_bytes (argv[1]);
29103     geo2 =
29104 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29105 				     gpkg_amphibious);
29106     if (geo1 == NULL || geo2 == NULL)
29107 	sqlite3_result_null (context);
29108     else
29109       {
29110 	  void *data = sqlite3_user_data (context);
29111 	  if (data != NULL)
29112 	      result = gaiaSharedPaths_r (data, geo1, geo2);
29113 	  else
29114 	      result = gaiaSharedPaths (geo1, geo2);
29115 	  if (!result)
29116 	      sqlite3_result_null (context);
29117 	  else
29118 	    {
29119 		/* builds the BLOB geometry to be returned */
29120 		int len;
29121 		unsigned char *p_result = NULL;
29122 		result->Srid = geo1->Srid;
29123 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29124 					    gpkg_mode, tiny_point);
29125 		sqlite3_result_blob (context, p_result, len, free);
29126 		gaiaFreeGeomColl (result);
29127 	    }
29128       }
29129     gaiaFreeGeomColl (geo1);
29130     gaiaFreeGeomColl (geo2);
29131 }
29132 
29133 static void
fnct_Covers(sqlite3_context * context,int argc,sqlite3_value ** argv)29134 fnct_Covers (sqlite3_context * context, int argc, sqlite3_value ** argv)
29135 {
29136 /* SQL function:
29137 / Covers(BLOBencoded geom1, BLOBencoded geom2)
29138 /
29139 / returns:
29140 / 1 if GEOM-1 "spatially covers" GEOM-2
29141 / 0 otherwise
29142 / or -1 if any error is encountered
29143 */
29144     unsigned char *blob1;
29145     unsigned char *blob2;
29146     int bytes1;
29147     int bytes2;
29148     gaiaGeomCollPtr geo1 = NULL;
29149     gaiaGeomCollPtr geo2 = NULL;
29150     int ret;
29151     int gpkg_amphibious = 0;
29152     int gpkg_mode = 0;
29153     struct splite_internal_cache *cache = sqlite3_user_data (context);
29154     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29155     if (cache != NULL)
29156       {
29157 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29158 	  gpkg_mode = cache->gpkg_mode;
29159       }
29160     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29161       {
29162 	  sqlite3_result_int (context, -1);
29163 	  return;
29164       }
29165     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29166       {
29167 	  sqlite3_result_int (context, -1);
29168 	  return;
29169       }
29170     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
29171     bytes1 = sqlite3_value_bytes (argv[0]);
29172     geo1 =
29173 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
29174     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
29175     bytes2 = sqlite3_value_bytes (argv[1]);
29176     geo2 =
29177 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
29178     if (!geo1 || !geo2)
29179 	sqlite3_result_int (context, -1);
29180     else
29181       {
29182 	  void *data = sqlite3_user_data (context);
29183 	  if (data != NULL)
29184 	      ret = gaiaGeomCollPreparedCovers (data, geo1,
29185 						blob1, bytes1, geo2, blob2,
29186 						bytes2);
29187 	  else
29188 	      ret = gaiaGeomCollCovers (geo1, geo2);
29189 	  sqlite3_result_int (context, ret);
29190       }
29191     gaiaFreeGeomColl (geo1);
29192     gaiaFreeGeomColl (geo2);
29193 }
29194 
29195 static void
fnct_CoveredBy(sqlite3_context * context,int argc,sqlite3_value ** argv)29196 fnct_CoveredBy (sqlite3_context * context, int argc, sqlite3_value ** argv)
29197 {
29198 /* SQL function:
29199 / CoveredBy(BLOBencoded geom1, BLOBencoded geom2)
29200 /
29201 / returns:
29202 / 1 if GEOM-1 is "spatially covered by" GEOM-2
29203 / 0 otherwise
29204 / or -1 if any error is encountered
29205 */
29206     unsigned char *blob1;
29207     unsigned char *blob2;
29208     int bytes1;
29209     int bytes2;
29210     gaiaGeomCollPtr geo1 = NULL;
29211     gaiaGeomCollPtr geo2 = NULL;
29212     int ret;
29213     int gpkg_amphibious = 0;
29214     int gpkg_mode = 0;
29215     struct splite_internal_cache *cache = sqlite3_user_data (context);
29216     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29217     if (cache != NULL)
29218       {
29219 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29220 	  gpkg_mode = cache->gpkg_mode;
29221       }
29222     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29223       {
29224 	  sqlite3_result_int (context, -1);
29225 	  return;
29226       }
29227     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29228       {
29229 	  sqlite3_result_int (context, -1);
29230 	  return;
29231       }
29232     blob1 = (unsigned char *) sqlite3_value_blob (argv[0]);
29233     bytes1 = sqlite3_value_bytes (argv[0]);
29234     geo1 =
29235 	gaiaFromSpatiaLiteBlobWkbEx (blob1, bytes1, gpkg_mode, gpkg_amphibious);
29236     blob2 = (unsigned char *) sqlite3_value_blob (argv[1]);
29237     bytes2 = sqlite3_value_bytes (argv[1]);
29238     geo2 =
29239 	gaiaFromSpatiaLiteBlobWkbEx (blob2, bytes2, gpkg_mode, gpkg_amphibious);
29240     if (!geo1 || !geo2)
29241 	sqlite3_result_int (context, -1);
29242     else
29243       {
29244 	  void *data = sqlite3_user_data (context);
29245 	  if (data != NULL)
29246 	      ret = gaiaGeomCollPreparedCoveredBy (data,
29247 						   geo1, blob1, bytes1, geo2,
29248 						   blob2, bytes2);
29249 	  else
29250 	      ret = gaiaGeomCollCoveredBy (geo1, geo2);
29251 	  sqlite3_result_int (context, ret);
29252       }
29253     gaiaFreeGeomColl (geo1);
29254     gaiaFreeGeomColl (geo2);
29255 }
29256 
29257 static void
fnct_LineInterpolatePoint(sqlite3_context * context,int argc,sqlite3_value ** argv)29258 fnct_LineInterpolatePoint (sqlite3_context * context, int argc,
29259 			   sqlite3_value ** argv)
29260 {
29261 /* SQL function:
29262 / LineInterpolatePoint(BLOBencoded geometry1, double fraction)
29263 /
29264 / returns a new geometry representing a point interpolated along a line
29265 / [a LINESTRING is expected / fraction ranging from 0.0 to 1.0]
29266 / or NULL if any error is encountered
29267 */
29268     unsigned char *p_blob;
29269     int n_bytes;
29270     int int_value;
29271     double fraction;
29272     gaiaGeomCollPtr geo = NULL;
29273     gaiaGeomCollPtr result;
29274     int gpkg_amphibious = 0;
29275     int gpkg_mode = 0;
29276     int tiny_point = 0;
29277     struct splite_internal_cache *cache = sqlite3_user_data (context);
29278     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29279     if (cache != NULL)
29280       {
29281 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29282 	  gpkg_mode = cache->gpkg_mode;
29283 	  tiny_point = cache->tinyPointEnabled;
29284       }
29285     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29286       {
29287 	  sqlite3_result_null (context);
29288 	  return;
29289       }
29290     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
29291 	fraction = sqlite3_value_double (argv[1]);
29292     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
29293       {
29294 	  int_value = sqlite3_value_int (argv[1]);
29295 	  fraction = int_value;
29296       }
29297     else
29298       {
29299 	  sqlite3_result_null (context);
29300 	  return;
29301       }
29302     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29303     n_bytes = sqlite3_value_bytes (argv[0]);
29304     geo =
29305 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29306 				     gpkg_amphibious);
29307     if (geo == NULL)
29308 	sqlite3_result_null (context);
29309     else
29310       {
29311 	  void *data = sqlite3_user_data (context);
29312 	  if (data != NULL)
29313 	      result = gaiaLineInterpolatePoint_r (data, geo, fraction);
29314 	  else
29315 	      result = gaiaLineInterpolatePoint (geo, fraction);
29316 	  if (!result)
29317 	      sqlite3_result_null (context);
29318 	  else
29319 	    {
29320 		/* builds the BLOB geometry to be returned */
29321 		int len;
29322 		unsigned char *p_result = NULL;
29323 		result->Srid = geo->Srid;
29324 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29325 					    gpkg_mode, tiny_point);
29326 		sqlite3_result_blob (context, p_result, len, free);
29327 		gaiaFreeGeomColl (result);
29328 	    }
29329       }
29330     gaiaFreeGeomColl (geo);
29331 }
29332 
29333 static void
fnct_LineInterpolateEquidistantPoints(sqlite3_context * context,int argc,sqlite3_value ** argv)29334 fnct_LineInterpolateEquidistantPoints (sqlite3_context * context, int argc,
29335 				       sqlite3_value ** argv)
29336 {
29337 /* SQL function:
29338 / LineInterpolateEquidistantPointS(BLOBencoded geometry1, double distance)
29339 /
29340 / returns a new geometry representing a point interpolated along a line
29341 / [a LINESTRING is expected / fraction ranging from 0.0 to 1.0]
29342 / or NULL if any error is encountered
29343 */
29344     unsigned char *p_blob;
29345     int n_bytes;
29346     int int_value;
29347     double distance;
29348     gaiaGeomCollPtr geo = NULL;
29349     gaiaGeomCollPtr result;
29350     int gpkg_amphibious = 0;
29351     int gpkg_mode = 0;
29352     int tiny_point = 0;
29353     struct splite_internal_cache *cache = sqlite3_user_data (context);
29354     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29355     if (cache != NULL)
29356       {
29357 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29358 	  gpkg_mode = cache->gpkg_mode;
29359 	  tiny_point = cache->tinyPointEnabled;
29360       }
29361     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29362       {
29363 	  sqlite3_result_null (context);
29364 	  return;
29365       }
29366     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
29367 	distance = sqlite3_value_double (argv[1]);
29368     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
29369       {
29370 	  int_value = sqlite3_value_int (argv[1]);
29371 	  distance = int_value;
29372       }
29373     else
29374       {
29375 	  sqlite3_result_null (context);
29376 	  return;
29377       }
29378     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29379     n_bytes = sqlite3_value_bytes (argv[0]);
29380     geo =
29381 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29382 				     gpkg_amphibious);
29383     if (geo == NULL)
29384 	sqlite3_result_null (context);
29385     else
29386       {
29387 	  void *data = sqlite3_user_data (context);
29388 	  if (data != NULL)
29389 	      result =
29390 		  gaiaLineInterpolateEquidistantPoints_r (data, geo, distance);
29391 	  else
29392 	      result = gaiaLineInterpolateEquidistantPoints (geo, distance);
29393 	  if (!result)
29394 	      sqlite3_result_null (context);
29395 	  else
29396 	    {
29397 		/* builds the BLOB geometry to be returned */
29398 		int len;
29399 		unsigned char *p_result = NULL;
29400 		result->Srid = geo->Srid;
29401 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29402 					    gpkg_mode, tiny_point);
29403 		sqlite3_result_blob (context, p_result, len, free);
29404 		gaiaFreeGeomColl (result);
29405 	    }
29406       }
29407     gaiaFreeGeomColl (geo);
29408 }
29409 
29410 static void
fnct_LineLocatePoint(sqlite3_context * context,int argc,sqlite3_value ** argv)29411 fnct_LineLocatePoint (sqlite3_context * context, int argc,
29412 		      sqlite3_value ** argv)
29413 {
29414 /* SQL function:
29415 / LineLocatePoint(BLOBencoded geometry1, BLOBencoded geometry2)
29416 /
29417 / return a number (between 0.0 and 1.0) representing the location
29418 / of the closest point on LineString to the given Point, as a fraction
29419 / of total 2d line length
29420 /
29421 / - geom1 is expected to represent some LINESTRING
29422 / - geom2 is expected to represent some POINT
29423 */
29424     unsigned char *p_blob;
29425     int n_bytes;
29426     double fraction;
29427     gaiaGeomCollPtr geo1 = NULL;
29428     gaiaGeomCollPtr geo2 = NULL;
29429     int gpkg_amphibious = 0;
29430     int gpkg_mode = 0;
29431     struct splite_internal_cache *cache = sqlite3_user_data (context);
29432     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29433     if (cache != NULL)
29434       {
29435 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29436 	  gpkg_mode = cache->gpkg_mode;
29437       }
29438     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29439       {
29440 	  sqlite3_result_null (context);
29441 	  return;
29442       }
29443     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29444       {
29445 	  sqlite3_result_null (context);
29446 	  return;
29447       }
29448     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29449     n_bytes = sqlite3_value_bytes (argv[0]);
29450     geo1 =
29451 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29452 				     gpkg_amphibious);
29453     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29454     n_bytes = sqlite3_value_bytes (argv[1]);
29455     geo2 =
29456 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29457 				     gpkg_amphibious);
29458     if (geo1 == NULL || geo2 == NULL)
29459 	sqlite3_result_null (context);
29460     else
29461       {
29462 	  void *data = sqlite3_user_data (context);
29463 	  if (data != NULL)
29464 	      fraction = gaiaLineLocatePoint_r (data, geo1, geo2);
29465 	  else
29466 	      fraction = gaiaLineLocatePoint (geo1, geo2);
29467 	  if (fraction >= 0.0 && fraction <= 1.0)
29468 	      sqlite3_result_double (context, fraction);
29469 	  else
29470 	      sqlite3_result_null (context);
29471       }
29472     gaiaFreeGeomColl (geo1);
29473     gaiaFreeGeomColl (geo2);
29474 }
29475 
29476 static void
fnct_LineSubstring(sqlite3_context * context,int argc,sqlite3_value ** argv)29477 fnct_LineSubstring (sqlite3_context * context, int argc, sqlite3_value ** argv)
29478 {
29479 /* SQL function:
29480 / LineSubstring(BLOBencoded geometry1, double start_fraction, double end_fraction)
29481 /
29482 / Return a Linestring being a substring of the input one starting and ending at
29483 / the given fractions of total 2d length [fractions ranging from 0.0 to 1.0]
29484 / or NULL if any error is encountered
29485 */
29486     unsigned char *p_blob;
29487     int n_bytes;
29488     int int_value;
29489     double fraction1;
29490     double fraction2;
29491     gaiaGeomCollPtr geo = NULL;
29492     gaiaGeomCollPtr result;
29493     int gpkg_amphibious = 0;
29494     int gpkg_mode = 0;
29495     int tiny_point = 0;
29496     struct splite_internal_cache *cache = sqlite3_user_data (context);
29497     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29498     if (cache != NULL)
29499       {
29500 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29501 	  gpkg_mode = cache->gpkg_mode;
29502 	  tiny_point = cache->tinyPointEnabled;
29503       }
29504     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29505       {
29506 	  sqlite3_result_null (context);
29507 	  return;
29508       }
29509     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
29510 	fraction1 = sqlite3_value_double (argv[1]);
29511     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
29512       {
29513 	  int_value = sqlite3_value_int (argv[1]);
29514 	  fraction1 = int_value;
29515       }
29516     else
29517       {
29518 	  sqlite3_result_null (context);
29519 	  return;
29520       }
29521     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
29522 	fraction2 = sqlite3_value_double (argv[2]);
29523     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
29524       {
29525 	  int_value = sqlite3_value_int (argv[2]);
29526 	  fraction2 = int_value;
29527       }
29528     else
29529       {
29530 	  sqlite3_result_null (context);
29531 	  return;
29532       }
29533     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29534     n_bytes = sqlite3_value_bytes (argv[0]);
29535     geo =
29536 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29537 				     gpkg_amphibious);
29538     if (geo == NULL)
29539 	sqlite3_result_null (context);
29540     else
29541       {
29542 	  void *data = sqlite3_user_data (context);
29543 	  if (data != NULL)
29544 	      result = gaiaLineSubstring_r (data, geo, fraction1, fraction2);
29545 	  else
29546 	      result = gaiaLineSubstring (geo, fraction1, fraction2);
29547 	  if (!result)
29548 	      sqlite3_result_null (context);
29549 	  else
29550 	    {
29551 		/* builds the BLOB geometry to be returned */
29552 		int len;
29553 		unsigned char *p_result = NULL;
29554 		result->Srid = geo->Srid;
29555 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29556 					    gpkg_mode, tiny_point);
29557 		sqlite3_result_blob (context, p_result, len, free);
29558 		gaiaFreeGeomColl (result);
29559 	    }
29560       }
29561     gaiaFreeGeomColl (geo);
29562 }
29563 
29564 static void
fnct_ClosestPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)29565 fnct_ClosestPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
29566 {
29567 /* SQL function:
29568 / ClosestPoint(BLOBencoded geometry1, BLOBencoded geometry2)
29569 /
29570 / Returns the Point on geom1 that is closest to geom2
29571 / NULL is returned for invalid arguments (or if distance is ZERO)
29572 */
29573     unsigned char *p_blob;
29574     int n_bytes;
29575     gaiaGeomCollPtr geo1 = NULL;
29576     gaiaGeomCollPtr geo2 = NULL;
29577     gaiaGeomCollPtr result;
29578     int gpkg_amphibious = 0;
29579     int gpkg_mode = 0;
29580     int tiny_point = 0;
29581     struct splite_internal_cache *cache = sqlite3_user_data (context);
29582     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29583     if (cache != NULL)
29584       {
29585 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29586 	  gpkg_mode = cache->gpkg_mode;
29587 	  tiny_point = cache->tinyPointEnabled;
29588       }
29589     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29590       {
29591 	  sqlite3_result_null (context);
29592 	  return;
29593       }
29594     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29595       {
29596 	  sqlite3_result_null (context);
29597 	  return;
29598       }
29599     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29600     n_bytes = sqlite3_value_bytes (argv[0]);
29601     geo1 =
29602 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29603 				     gpkg_amphibious);
29604     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29605     n_bytes = sqlite3_value_bytes (argv[1]);
29606     geo2 =
29607 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29608 				     gpkg_amphibious);
29609     if (geo1 == NULL || geo2 == NULL)
29610 	sqlite3_result_null (context);
29611     else
29612       {
29613 	  void *data = sqlite3_user_data (context);
29614 	  if (data != NULL)
29615 	      result = gaiaShortestLine_r (data, geo1, geo2);
29616 	  else
29617 	      result = gaiaShortestLine (geo1, geo2);
29618 	  if (result == NULL)
29619 	      sqlite3_result_null (context);
29620 	  else if (result->FirstLinestring == NULL)
29621 	    {
29622 		gaiaFreeGeomColl (result);
29623 		sqlite3_result_null (context);
29624 	    }
29625 	  else
29626 	    {
29627 		/* builds the BLOB geometry to be returned */
29628 		double x;
29629 		double y;
29630 		double z;
29631 		double m;
29632 		int len;
29633 		unsigned char *p_result = NULL;
29634 		gaiaGeomCollPtr pt = NULL;
29635 		gaiaLinestringPtr ln = result->FirstLinestring;
29636 		if (ln->DimensionModel == GAIA_XY_Z)
29637 		    pt = gaiaAllocGeomCollXYZ ();
29638 		else if (ln->DimensionModel == GAIA_XY_M)
29639 		    pt = gaiaAllocGeomCollXYM ();
29640 		else if (ln->DimensionModel == GAIA_XY_Z_M)
29641 		    pt = gaiaAllocGeomCollXYZM ();
29642 		else
29643 		    pt = gaiaAllocGeomColl ();
29644 		if (ln->DimensionModel == GAIA_XY_Z)
29645 		  {
29646 		      gaiaGetPointXYZ (ln->Coords, 0, &x, &y, &z);
29647 		      gaiaAddPointToGeomCollXYZ (pt, x, y, z);
29648 		  }
29649 		else if (ln->DimensionModel == GAIA_XY_M)
29650 		  {
29651 		      gaiaGetPointXYM (ln->Coords, 0, &x, &y, &m);
29652 		      gaiaAddPointToGeomCollXYM (pt, x, y, m);
29653 		  }
29654 		else if (ln->DimensionModel == GAIA_XY_Z_M)
29655 		  {
29656 		      gaiaGetPointXYZM (ln->Coords, 0, &x, &y, &z, &m);
29657 		      gaiaAddPointToGeomCollXYZM (pt, x, y, z, m);
29658 		  }
29659 		else
29660 		  {
29661 		      gaiaGetPoint (ln->Coords, 0, &x, &y);
29662 		      gaiaAddPointToGeomColl (pt, x, y);
29663 		  }
29664 		pt->Srid = geo1->Srid;
29665 		gaiaToSpatiaLiteBlobWkbEx2 (pt, &p_result, &len, gpkg_mode,
29666 					    tiny_point);
29667 		sqlite3_result_blob (context, p_result, len, free);
29668 		gaiaFreeGeomColl (result);
29669 		gaiaFreeGeomColl (pt);
29670 	    }
29671       }
29672     gaiaFreeGeomColl (geo1);
29673     gaiaFreeGeomColl (geo2);
29674 }
29675 
29676 static void
fnct_ShortestLine(sqlite3_context * context,int argc,sqlite3_value ** argv)29677 fnct_ShortestLine (sqlite3_context * context, int argc, sqlite3_value ** argv)
29678 {
29679 /* SQL function:
29680 / ShortestLine(BLOBencoded geometry1, BLOBencoded geometry2)
29681 /
29682 / Returns the shortest line between two geometries
29683 / NULL is returned for invalid arguments (or if distance is ZERO)
29684 */
29685     unsigned char *p_blob;
29686     int n_bytes;
29687     gaiaGeomCollPtr geo1 = NULL;
29688     gaiaGeomCollPtr geo2 = NULL;
29689     gaiaGeomCollPtr result;
29690     int gpkg_amphibious = 0;
29691     int gpkg_mode = 0;
29692     int tiny_point = 0;
29693     struct splite_internal_cache *cache = sqlite3_user_data (context);
29694     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29695     if (cache != NULL)
29696       {
29697 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29698 	  gpkg_mode = cache->gpkg_mode;
29699 	  tiny_point = cache->tinyPointEnabled;
29700       }
29701     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29702       {
29703 	  sqlite3_result_null (context);
29704 	  return;
29705       }
29706     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29707       {
29708 	  sqlite3_result_null (context);
29709 	  return;
29710       }
29711     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29712     n_bytes = sqlite3_value_bytes (argv[0]);
29713     geo1 =
29714 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29715 				     gpkg_amphibious);
29716     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29717     n_bytes = sqlite3_value_bytes (argv[1]);
29718     geo2 =
29719 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29720 				     gpkg_amphibious);
29721     if (geo1 == NULL || geo2 == NULL)
29722 	sqlite3_result_null (context);
29723     else
29724       {
29725 	  void *data = sqlite3_user_data (context);
29726 	  if (data != NULL)
29727 	      result = gaiaShortestLine_r (data, geo1, geo2);
29728 	  else
29729 	      result = gaiaShortestLine (geo1, geo2);
29730 	  sqlite3_result_null (context);
29731 	  if (!result)
29732 	      sqlite3_result_null (context);
29733 	  else
29734 	    {
29735 		/* builds the BLOB geometry to be returned */
29736 		int len;
29737 		unsigned char *p_result = NULL;
29738 		result->Srid = geo1->Srid;
29739 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29740 					    gpkg_mode, tiny_point);
29741 		sqlite3_result_blob (context, p_result, len, free);
29742 		gaiaFreeGeomColl (result);
29743 	    }
29744       }
29745     gaiaFreeGeomColl (geo1);
29746     gaiaFreeGeomColl (geo2);
29747 }
29748 
29749 static void
fnct_Snap(sqlite3_context * context,int argc,sqlite3_value ** argv)29750 fnct_Snap (sqlite3_context * context, int argc, sqlite3_value ** argv)
29751 {
29752 /* SQL function:
29753 / Snap(BLOBencoded geometry1, BLOBencoded geometry2, double tolerance)
29754 /
29755 / Returns a new Geometry corresponding to geom1 snapped to geom2
29756 / and using the given tolerance
29757 / NULL is returned for invalid arguments (or if distance is ZERO)
29758 */
29759     unsigned char *p_blob;
29760     int n_bytes;
29761     int int_value;
29762     double tolerance;
29763     gaiaGeomCollPtr geo1 = NULL;
29764     gaiaGeomCollPtr geo2 = NULL;
29765     gaiaGeomCollPtr result;
29766     int gpkg_amphibious = 0;
29767     int gpkg_mode = 0;
29768     int tiny_point = 0;
29769     struct splite_internal_cache *cache = sqlite3_user_data (context);
29770     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29771     if (cache != NULL)
29772       {
29773 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29774 	  gpkg_mode = cache->gpkg_mode;
29775 	  tiny_point = cache->tinyPointEnabled;
29776       }
29777     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29778       {
29779 	  sqlite3_result_null (context);
29780 	  return;
29781       }
29782     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
29783       {
29784 	  sqlite3_result_null (context);
29785 	  return;
29786       }
29787     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
29788 	tolerance = sqlite3_value_double (argv[2]);
29789     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
29790       {
29791 	  int_value = sqlite3_value_int (argv[2]);
29792 	  tolerance = int_value;
29793       }
29794     else
29795       {
29796 	  sqlite3_result_null (context);
29797 	  return;
29798       }
29799     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29800     n_bytes = sqlite3_value_bytes (argv[0]);
29801     geo1 =
29802 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29803 				     gpkg_amphibious);
29804     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
29805     n_bytes = sqlite3_value_bytes (argv[1]);
29806     geo2 =
29807 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29808 				     gpkg_amphibious);
29809     if (geo1 == NULL || geo2 == NULL)
29810 	sqlite3_result_null (context);
29811     else
29812       {
29813 	  void *data = sqlite3_user_data (context);
29814 	  if (data != NULL)
29815 	      result = gaiaSnap_r (data, geo1, geo2, tolerance);
29816 	  else
29817 	      result = gaiaSnap (geo1, geo2, tolerance);
29818 	  if (result == NULL)
29819 	      sqlite3_result_null (context);
29820 	  else
29821 	    {
29822 		/* builds the BLOB geometry to be returned */
29823 		int len;
29824 		unsigned char *p_result = NULL;
29825 		result->Srid = geo1->Srid;
29826 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29827 					    gpkg_mode, tiny_point);
29828 		sqlite3_result_blob (context, p_result, len, free);
29829 		gaiaFreeGeomColl (result);
29830 	    }
29831       }
29832     gaiaFreeGeomColl (geo1);
29833     gaiaFreeGeomColl (geo2);
29834 }
29835 
29836 static void
fnct_LineMerge(sqlite3_context * context,int argc,sqlite3_value ** argv)29837 fnct_LineMerge (sqlite3_context * context, int argc, sqlite3_value ** argv)
29838 {
29839 /* SQL function:
29840 / LineMerge(BLOBencoded geometry)
29841 /
29842 / Assuming that Geometry represents a set of sparse Linestrings,
29843 / this function will attempt to reassemble a single line
29844 / (or a set of lines)
29845 / NULL is returned for invalid arguments
29846 */
29847     unsigned char *p_blob;
29848     int n_bytes;
29849     gaiaGeomCollPtr geo = NULL;
29850     gaiaGeomCollPtr result;
29851     int gpkg_amphibious = 0;
29852     int gpkg_mode = 0;
29853     int tiny_point = 0;
29854     struct splite_internal_cache *cache = sqlite3_user_data (context);
29855     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29856     if (cache != NULL)
29857       {
29858 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29859 	  gpkg_mode = cache->gpkg_mode;
29860 	  tiny_point = cache->tinyPointEnabled;
29861       }
29862     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29863       {
29864 	  sqlite3_result_null (context);
29865 	  return;
29866       }
29867     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29868     n_bytes = sqlite3_value_bytes (argv[0]);
29869     geo =
29870 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29871 				     gpkg_amphibious);
29872     if (geo == NULL)
29873 	sqlite3_result_null (context);
29874     else
29875       {
29876 	  void *data = sqlite3_user_data (context);
29877 	  if (data != NULL)
29878 	      result = gaiaLineMerge_r (data, geo);
29879 	  else
29880 	      result = gaiaLineMerge (geo);
29881 	  if (result == NULL)
29882 	      sqlite3_result_null (context);
29883 	  else
29884 	    {
29885 		/* builds the BLOB geometry to be returned */
29886 		int len;
29887 		unsigned char *p_result = NULL;
29888 		result->Srid = geo->Srid;
29889 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29890 					    gpkg_mode, tiny_point);
29891 		sqlite3_result_blob (context, p_result, len, free);
29892 		gaiaFreeGeomColl (result);
29893 	    }
29894       }
29895     gaiaFreeGeomColl (geo);
29896 }
29897 
29898 static void
fnct_UnaryUnion(sqlite3_context * context,int argc,sqlite3_value ** argv)29899 fnct_UnaryUnion (sqlite3_context * context, int argc, sqlite3_value ** argv)
29900 {
29901 /* SQL function:
29902 / UnaryUnion(BLOBencoded geometry)
29903 /
29904 / exactly like Union, but using a single Collection
29905 / NULL is returned for invalid arguments
29906 */
29907     unsigned char *p_blob;
29908     int n_bytes;
29909     gaiaGeomCollPtr geo = NULL;
29910     gaiaGeomCollPtr result;
29911     int gpkg_amphibious = 0;
29912     int gpkg_mode = 0;
29913     int tiny_point = 0;
29914     struct splite_internal_cache *cache = sqlite3_user_data (context);
29915     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29916     if (cache != NULL)
29917       {
29918 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29919 	  gpkg_mode = cache->gpkg_mode;
29920 	  tiny_point = cache->tinyPointEnabled;
29921       }
29922     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
29923       {
29924 	  sqlite3_result_null (context);
29925 	  return;
29926       }
29927     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
29928     n_bytes = sqlite3_value_bytes (argv[0]);
29929     geo =
29930 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
29931 				     gpkg_amphibious);
29932     if (geo == NULL)
29933 	sqlite3_result_null (context);
29934     else
29935       {
29936 	  void *data = sqlite3_user_data (context);
29937 	  if (data != NULL)
29938 	      result = gaiaUnaryUnion_r (data, geo);
29939 	  else
29940 	      result = gaiaUnaryUnion (geo);
29941 	  if (result == NULL)
29942 	      sqlite3_result_null (context);
29943 	  else
29944 	    {
29945 		/* builds the BLOB geometry to be returned */
29946 		int len;
29947 		unsigned char *p_result = NULL;
29948 		result->Srid = geo->Srid;
29949 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
29950 					    gpkg_mode, tiny_point);
29951 		sqlite3_result_blob (context, p_result, len, free);
29952 		gaiaFreeGeomColl (result);
29953 	    }
29954       }
29955     gaiaFreeGeomColl (geo);
29956 }
29957 
29958 static void
fnct_SquareGrid(sqlite3_context * context,int argc,sqlite3_value ** argv)29959 fnct_SquareGrid (sqlite3_context * context, int argc, sqlite3_value ** argv)
29960 {
29961 /* SQL function:
29962 / ST_SquareGrid(BLOBencoded geom, double size)
29963 / ST_SquareGrid(BLOBencoded geom, double size, int mode)
29964 / ST_SquareGrid(BLOBencoded geom, double size, int mode, BLOBencoded origin)
29965 /
29966 / mode interpretation:
29967 / ==============================================
29968 / positive = a MULTILINESTRING will be returned
29969 /        0 = a MULTIPOLYGON will be returned
29970 / negative = a MULTIPOINT will be returned
29971 / ==============================================
29972 /
29973 / Builds a regular grid (Square cells) covering the geom.
29974 / each cell has the edges's length as defined by the size argument
29975 / an arbitrary origin is supported (0,0 is assumed by default)
29976 / return NULL if any error is encountered
29977 */
29978     unsigned char *p_blob;
29979     int n_bytes;
29980     int int_value;
29981     double origin_x = 0.0;
29982     double origin_y = 0.0;
29983     double size;
29984     int mode = 0;
29985     gaiaGeomCollPtr geo = NULL;
29986     gaiaGeomCollPtr point = NULL;
29987     gaiaGeomCollPtr result = NULL;
29988     int gpkg_amphibious = 0;
29989     int gpkg_mode = 0;
29990     int tiny_point = 0;
29991     struct splite_internal_cache *cache = sqlite3_user_data (context);
29992     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
29993     if (cache != NULL)
29994       {
29995 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
29996 	  gpkg_mode = cache->gpkg_mode;
29997 	  tiny_point = cache->tinyPointEnabled;
29998       }
29999     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30000       {
30001 	  sqlite3_result_null (context);
30002 	  return;
30003       }
30004     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
30005       {
30006 	  int_value = sqlite3_value_int (argv[1]);
30007 	  size = int_value;
30008       }
30009     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
30010       {
30011 	  size = sqlite3_value_double (argv[1]);
30012       }
30013     else
30014       {
30015 	  sqlite3_result_null (context);
30016 	  return;
30017       }
30018     if (size <= 0.0)
30019       {
30020 	  /* negative side size */
30021 	  sqlite3_result_null (context);
30022 	  return;
30023       }
30024     if (argc >= 3)
30025       {
30026 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
30027 	      mode = sqlite3_value_int (argv[2]);
30028 	  else
30029 	    {
30030 		sqlite3_result_null (context);
30031 		return;
30032 	    }
30033       }
30034     if (argc == 4)
30035       {
30036 	  if (sqlite3_value_type (argv[3]) != SQLITE_BLOB)
30037 	    {
30038 		sqlite3_result_null (context);
30039 		return;
30040 	    }
30041 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[3]);
30042 	  n_bytes = sqlite3_value_bytes (argv[3]);
30043 	  point =
30044 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30045 					   gpkg_amphibious);
30046 	  if (!point)
30047 	    {
30048 		sqlite3_result_null (context);
30049 		return;
30050 	    }
30051 	  if (point->FirstLinestring != NULL)
30052 	      goto no_point;
30053 	  if (point->FirstPolygon != NULL)
30054 	      goto no_point;
30055 	  if (point->FirstPoint != NULL)
30056 	    {
30057 		if (point->FirstPoint == point->LastPoint)
30058 		  {
30059 		      origin_x = point->FirstPoint->X;
30060 		      origin_y = point->FirstPoint->Y;
30061 		      gaiaFreeGeomColl (point);
30062 		  }
30063 		else
30064 		    goto no_point;
30065 	    }
30066 	  else
30067 	      goto no_point;
30068 
30069       }
30070     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30071     n_bytes = sqlite3_value_bytes (argv[0]);
30072     geo =
30073 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30074 				     gpkg_amphibious);
30075     if (!geo)
30076 	sqlite3_result_null (context);
30077     else
30078       {
30079 	  void *data = sqlite3_user_data (context);
30080 	  if (geo->FirstPoint != NULL)
30081 	      goto no_polygon;
30082 	  if (geo->FirstLinestring != NULL)
30083 	      goto no_polygon;
30084 	  if (geo->FirstPolygon == NULL)
30085 	      goto no_polygon;
30086 	  if (data != NULL)
30087 	      result =
30088 		  gaiaSquareGrid_r (data, geo, origin_x, origin_y, size, mode);
30089 	  else
30090 	      result = gaiaSquareGrid (geo, origin_x, origin_y, size, mode);
30091 	  if (result == NULL)
30092 	      sqlite3_result_null (context);
30093 	  else
30094 	    {
30095 		/* builds the BLOB geometry to be returned */
30096 		int len;
30097 		unsigned char *p_result = NULL;
30098 		result->Srid = geo->Srid;
30099 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
30100 					    gpkg_mode, tiny_point);
30101 		sqlite3_result_blob (context, p_result, len, free);
30102 		gaiaFreeGeomColl (result);
30103 	    }
30104       }
30105     gaiaFreeGeomColl (geo);
30106     return;
30107 
30108   no_point:
30109     gaiaFreeGeomColl (point);
30110     sqlite3_result_null (context);
30111     return;
30112 
30113   no_polygon:
30114     gaiaFreeGeomColl (geo);
30115     sqlite3_result_null (context);
30116     return;
30117 }
30118 
30119 static void
fnct_TriangularGrid(sqlite3_context * context,int argc,sqlite3_value ** argv)30120 fnct_TriangularGrid (sqlite3_context * context, int argc, sqlite3_value ** argv)
30121 {
30122 /* SQL function:
30123 / ST_TriangularGrid(BLOBencoded geom, double size)
30124 / ST_TriangularGrid(BLOBencoded geom, double size, int mode)
30125 / ST_TriangularGrid(BLOBencoded geom, double size, int mode, BLOBencoded origin)
30126 /
30127 / mode interpretation:
30128 / ==============================================
30129 / positive = a MULTILINESTRING will be returned
30130 /        0 = a MULTIPOLYGON will be returned
30131 / negative = a MULTIPOINT will be returned
30132 / ==============================================
30133 /
30134 / Builds a regular grid (Triangular cells) covering the geom.
30135 / each cell has the edge's length as defined by the size argument
30136 / an arbitrary origin is supported (0,0 is assumed by default)
30137 / return NULL if any error is encountered
30138 */
30139     unsigned char *p_blob;
30140     int n_bytes;
30141     int int_value;
30142     double origin_x = 0.0;
30143     double origin_y = 0.0;
30144     double size;
30145     int mode = 0;
30146     gaiaGeomCollPtr geo = NULL;
30147     gaiaGeomCollPtr point = NULL;
30148     gaiaGeomCollPtr result = NULL;
30149     int gpkg_amphibious = 0;
30150     int gpkg_mode = 0;
30151     int tiny_point = 0;
30152     struct splite_internal_cache *cache = sqlite3_user_data (context);
30153     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30154     if (cache != NULL)
30155       {
30156 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30157 	  gpkg_mode = cache->gpkg_mode;
30158 	  tiny_point = cache->tinyPointEnabled;
30159       }
30160     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30161       {
30162 	  sqlite3_result_null (context);
30163 	  return;
30164       }
30165     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
30166       {
30167 	  int_value = sqlite3_value_int (argv[1]);
30168 	  size = int_value;
30169       }
30170     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
30171       {
30172 	  size = sqlite3_value_double (argv[1]);
30173       }
30174     else
30175       {
30176 	  sqlite3_result_null (context);
30177 	  return;
30178       }
30179     if (size <= 0.0)
30180       {
30181 	  /* negative side size */
30182 	  sqlite3_result_null (context);
30183 	  return;
30184       }
30185     if (argc >= 3)
30186       {
30187 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
30188 	      mode = sqlite3_value_int (argv[2]);
30189 	  else
30190 	    {
30191 		sqlite3_result_null (context);
30192 		return;
30193 	    }
30194       }
30195     if (argc == 4)
30196       {
30197 	  if (sqlite3_value_type (argv[3]) != SQLITE_BLOB)
30198 	    {
30199 		sqlite3_result_null (context);
30200 		return;
30201 	    }
30202 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[3]);
30203 	  n_bytes = sqlite3_value_bytes (argv[3]);
30204 	  point =
30205 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30206 					   gpkg_amphibious);
30207 	  if (!point)
30208 	    {
30209 		sqlite3_result_null (context);
30210 		return;
30211 	    }
30212 	  if (point->FirstLinestring != NULL)
30213 	      goto no_point;
30214 	  if (point->FirstPolygon != NULL)
30215 	      goto no_point;
30216 	  if (point->FirstPoint != NULL)
30217 	    {
30218 		if (point->FirstPoint == point->LastPoint)
30219 		  {
30220 		      origin_x = point->FirstPoint->X;
30221 		      origin_y = point->FirstPoint->Y;
30222 		      gaiaFreeGeomColl (point);
30223 		  }
30224 		else
30225 		    goto no_point;
30226 	    }
30227 	  else
30228 	      goto no_point;
30229 
30230       }
30231     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30232     n_bytes = sqlite3_value_bytes (argv[0]);
30233     geo =
30234 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30235 				     gpkg_amphibious);
30236     if (!geo)
30237 	sqlite3_result_null (context);
30238     else
30239       {
30240 	  void *data = sqlite3_user_data (context);
30241 	  if (geo->FirstPoint != NULL)
30242 	      goto no_polygon;
30243 	  if (geo->FirstLinestring != NULL)
30244 	      goto no_polygon;
30245 	  if (geo->FirstPolygon == NULL)
30246 	      goto no_polygon;
30247 	  if (data != NULL)
30248 	      result =
30249 		  gaiaTriangularGrid_r (data, geo, origin_x, origin_y, size,
30250 					mode);
30251 	  else
30252 	      result = gaiaTriangularGrid (geo, origin_x, origin_y, size, mode);
30253 	  if (result == NULL)
30254 	      sqlite3_result_null (context);
30255 	  else
30256 	    {
30257 		/* builds the BLOB geometry to be returned */
30258 		int len;
30259 		unsigned char *p_result = NULL;
30260 		result->Srid = geo->Srid;
30261 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
30262 					    gpkg_mode, tiny_point);
30263 		sqlite3_result_blob (context, p_result, len, free);
30264 		gaiaFreeGeomColl (result);
30265 	    }
30266       }
30267     gaiaFreeGeomColl (geo);
30268     return;
30269 
30270   no_point:
30271     gaiaFreeGeomColl (point);
30272     sqlite3_result_null (context);
30273     return;
30274 
30275   no_polygon:
30276     gaiaFreeGeomColl (geo);
30277     sqlite3_result_null (context);
30278     return;
30279 }
30280 
30281 static void
fnct_HexagonalGrid(sqlite3_context * context,int argc,sqlite3_value ** argv)30282 fnct_HexagonalGrid (sqlite3_context * context, int argc, sqlite3_value ** argv)
30283 {
30284 /* SQL function:
30285 / ST_HexagonalGrid(BLOBencoded geom, double size)
30286 / ST_HexagonalGrid(BLOBencoded geom, double size, int mode)
30287 / ST_HexagonalGrid(BLOBencoded geom, double size, int mode, BLOBencoded origin)
30288 /
30289 / mode interpretation:
30290 / ==============================================
30291 / positive = a MULTILINESTRING will be returned
30292 /        0 = a MULTIPOLYGON will be returned
30293 / negative = a MULTIPOINT will be returned
30294 / ==============================================
30295 /
30296 / Builds a regular grid (Hexagonal cells) covering the geom.
30297 / each cell has the edges's length as defined by the size argument
30298 / an arbitrary origin is supported (0,0 is assumed by default)
30299 / return NULL if any error is encountered
30300 */
30301     unsigned char *p_blob;
30302     int n_bytes;
30303     int int_value;
30304     double origin_x = 0.0;
30305     double origin_y = 0.0;
30306     double size;
30307     int mode = 0;
30308     gaiaGeomCollPtr geo = NULL;
30309     gaiaGeomCollPtr point = NULL;
30310     gaiaGeomCollPtr result = NULL;
30311     int gpkg_amphibious = 0;
30312     int gpkg_mode = 0;
30313     int tiny_point = 0;
30314     struct splite_internal_cache *cache = sqlite3_user_data (context);
30315     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30316     if (cache != NULL)
30317       {
30318 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30319 	  gpkg_mode = cache->gpkg_mode;
30320 	  tiny_point = cache->tinyPointEnabled;
30321       }
30322     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30323       {
30324 	  sqlite3_result_null (context);
30325 	  return;
30326       }
30327     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
30328       {
30329 	  int_value = sqlite3_value_int (argv[1]);
30330 	  size = int_value;
30331       }
30332     else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
30333       {
30334 	  size = sqlite3_value_double (argv[1]);
30335       }
30336     else
30337       {
30338 	  sqlite3_result_null (context);
30339 	  return;
30340       }
30341     if (size <= 0.0)
30342       {
30343 	  /* negative side size */
30344 	  sqlite3_result_null (context);
30345 	  return;
30346       }
30347     if (argc >= 3)
30348       {
30349 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
30350 	      mode = sqlite3_value_int (argv[2]);
30351 	  else
30352 	    {
30353 		sqlite3_result_null (context);
30354 		return;
30355 	    }
30356       }
30357     if (argc == 4)
30358       {
30359 	  if (sqlite3_value_type (argv[3]) != SQLITE_BLOB)
30360 	    {
30361 		sqlite3_result_null (context);
30362 		return;
30363 	    }
30364 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[3]);
30365 	  n_bytes = sqlite3_value_bytes (argv[3]);
30366 	  point =
30367 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30368 					   gpkg_amphibious);
30369 	  if (!point)
30370 	    {
30371 		sqlite3_result_null (context);
30372 		return;
30373 	    }
30374 	  if (point->FirstLinestring != NULL)
30375 	      goto no_point;
30376 	  if (point->FirstPolygon != NULL)
30377 	      goto no_point;
30378 	  if (point->FirstPoint != NULL)
30379 	    {
30380 		if (point->FirstPoint == point->LastPoint)
30381 		  {
30382 		      origin_x = point->FirstPoint->X;
30383 		      origin_y = point->FirstPoint->Y;
30384 		      gaiaFreeGeomColl (point);
30385 		  }
30386 		else
30387 		    goto no_point;
30388 	    }
30389 	  else
30390 	      goto no_point;
30391 
30392       }
30393     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30394     n_bytes = sqlite3_value_bytes (argv[0]);
30395     geo =
30396 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30397 				     gpkg_amphibious);
30398     if (!geo)
30399 	sqlite3_result_null (context);
30400     else
30401       {
30402 	  void *data = sqlite3_user_data (context);
30403 	  if (geo->FirstPoint != NULL)
30404 	      goto no_polygon;
30405 	  if (geo->FirstLinestring != NULL)
30406 	      goto no_polygon;
30407 	  if (geo->FirstPolygon == NULL)
30408 	      goto no_polygon;
30409 	  if (data != NULL)
30410 	      result =
30411 		  gaiaHexagonalGrid_r (data, geo, origin_x, origin_y, size,
30412 				       mode);
30413 	  else
30414 	      result = gaiaHexagonalGrid (geo, origin_x, origin_y, size, mode);
30415 	  if (result == NULL)
30416 	      sqlite3_result_null (context);
30417 	  else
30418 	    {
30419 		/* builds the BLOB geometry to be returned */
30420 		int len;
30421 		unsigned char *p_result = NULL;
30422 		result->Srid = geo->Srid;
30423 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
30424 					    gpkg_mode, tiny_point);
30425 		sqlite3_result_blob (context, p_result, len, free);
30426 		gaiaFreeGeomColl (result);
30427 	    }
30428       }
30429     gaiaFreeGeomColl (geo);
30430     return;
30431 
30432   no_point:
30433     gaiaFreeGeomColl (point);
30434     sqlite3_result_null (context);
30435     return;
30436 
30437   no_polygon:
30438     gaiaFreeGeomColl (geo);
30439     sqlite3_result_null (context);
30440     return;
30441 }
30442 
30443 static void
fnct_LinesCutAtNodes(sqlite3_context * context,int argc,sqlite3_value ** argv)30444 fnct_LinesCutAtNodes (sqlite3_context * context, int argc,
30445 		      sqlite3_value ** argv)
30446 {
30447 /* SQL function:
30448 / LinesCutAtNodes(BLOBencoded geometry1, BLOBencoded geometry2)
30449 /
30450 / Assuming that Geometry-1 represents a set of arbitray Linestrings,
30451 / and that Geometry-2 represents of arbitrary Points, this function
30452 / will then attempt to cut lines accordingly to given nodes.
30453 / NULL is returned for invalid arguments
30454 */
30455     unsigned char *p_blob;
30456     int n_bytes;
30457     gaiaGeomCollPtr geom1 = NULL;
30458     gaiaGeomCollPtr geom2 = NULL;
30459     gaiaGeomCollPtr result;
30460     int gpkg_amphibious = 0;
30461     int gpkg_mode = 0;
30462     int tiny_point = 0;
30463     struct splite_internal_cache *cache = sqlite3_user_data (context);
30464     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30465     if (cache != NULL)
30466       {
30467 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30468 	  gpkg_mode = cache->gpkg_mode;
30469 	  tiny_point = cache->tinyPointEnabled;
30470       }
30471     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30472       {
30473 	  sqlite3_result_null (context);
30474 	  return;
30475       }
30476     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
30477       {
30478 	  sqlite3_result_null (context);
30479 	  return;
30480       }
30481     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30482     n_bytes = sqlite3_value_bytes (argv[0]);
30483     geom1 =
30484 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30485 				     gpkg_amphibious);
30486     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
30487     n_bytes = sqlite3_value_bytes (argv[1]);
30488     geom2 =
30489 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30490 				     gpkg_amphibious);
30491     if (geom1 == NULL || geom2 == NULL)
30492       {
30493 	  if (geom1)
30494 	      gaiaFreeGeomColl (geom1);
30495 	  if (geom2)
30496 	      gaiaFreeGeomColl (geom2);
30497 	  sqlite3_result_null (context);
30498 	  return;
30499       }
30500     result = gaiaLinesCutAtNodes (geom1, geom2);
30501     if (result == NULL)
30502       {
30503 	  sqlite3_result_null (context);
30504       }
30505     else
30506       {
30507 	  /* builds the BLOB geometry to be returned */
30508 	  int len;
30509 	  unsigned char *p_result = NULL;
30510 	  result->Srid = geom1->Srid;
30511 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
30512 				      tiny_point);
30513 	  sqlite3_result_blob (context, p_result, len, free);
30514 	  gaiaFreeGeomColl (result);
30515       }
30516     gaiaFreeGeomColl (geom1);
30517     gaiaFreeGeomColl (geom2);
30518 }
30519 
30520 static int
cmp_pt_coords(const void * p1,const void * p2)30521 cmp_pt_coords (const void *p1, const void *p2)
30522 {
30523 /* compares two nodes  by ID [for QSORT] */
30524     gaiaPointPtr pt1 = *((gaiaPointPtr *) p1);
30525     gaiaPointPtr pt2 = *((gaiaPointPtr *) p2);
30526     if (pt1->X == pt2->X && pt1->Y == pt2->Y && pt1->Z == pt2->Z)
30527 	return 0;
30528     if (pt1->X > pt2->X)
30529 	return 1;
30530     if (pt1->X == pt2->X && pt1->Y > pt2->Y)
30531 	return 1;
30532     if (pt1->X == pt2->X && pt1->Y == pt2->Y && pt1->Z > pt2->Z)
30533 	return 1;
30534     return -1;
30535 }
30536 
30537 static gaiaGeomCollPtr
auxPolygNodes(gaiaGeomCollPtr geom)30538 auxPolygNodes (gaiaGeomCollPtr geom)
30539 {
30540 /* attempting to identify Ring-Nodes */
30541     gaiaGeomCollPtr result = NULL;
30542     gaiaPolygonPtr pg;
30543     gaiaRingPtr rng;
30544     gaiaPointPtr pt;
30545     gaiaPointPtr prev_pt;
30546     gaiaPointPtr *sorted = NULL;
30547     int count = 0;
30548     int iv;
30549     int ib;
30550     double x;
30551     double y;
30552     double z;
30553     double m;
30554 
30555 /* inserting all Points into a Dynamic Line */
30556     gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
30557     pg = geom->FirstPolygon;
30558     while (pg)
30559       {
30560 	  rng = pg->Exterior;
30561 	  /* CAVEAT: first point needs to be skipped (closed ring) */
30562 	  for (iv = 1; iv < rng->Points; iv++)
30563 	    {
30564 		/* exterior ring */
30565 		if (geom->DimensionModel == GAIA_XY_Z)
30566 		  {
30567 		      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
30568 		      gaiaAppendPointZToDynamicLine (dyn, x, y, z);
30569 		  }
30570 		else if (geom->DimensionModel == GAIA_XY_M)
30571 		  {
30572 		      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
30573 		      gaiaAppendPointMToDynamicLine (dyn, x, y, m);
30574 		  }
30575 		else if (geom->DimensionModel == GAIA_XY_Z_M)
30576 		  {
30577 		      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
30578 		      gaiaAppendPointZMToDynamicLine (dyn, x, y, z, m);
30579 		  }
30580 		else
30581 		  {
30582 		      gaiaGetPoint (rng->Coords, iv, &x, &y);
30583 		      gaiaAppendPointToDynamicLine (dyn, x, y);
30584 		  }
30585 	    }
30586 
30587 	  for (ib = 0; ib < pg->NumInteriors; ib++)
30588 	    {
30589 		rng = pg->Interiors + ib;
30590 		/* CAVEAT: first point needs to be skipped (closed ring) */
30591 		for (iv = 1; iv < rng->Points; iv++)
30592 		  {
30593 		      /* interior ring */
30594 		      if (geom->DimensionModel == GAIA_XY_Z)
30595 			{
30596 			    gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
30597 			    gaiaAppendPointZToDynamicLine (dyn, x, y, z);
30598 			}
30599 		      else if (geom->DimensionModel == GAIA_XY_M)
30600 			{
30601 			    gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
30602 			    gaiaAppendPointMToDynamicLine (dyn, x, y, m);
30603 			}
30604 		      else if (geom->DimensionModel == GAIA_XY_Z_M)
30605 			{
30606 			    gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
30607 			    gaiaAppendPointZMToDynamicLine (dyn, x, y, z, m);
30608 			}
30609 		      else
30610 			{
30611 			    gaiaGetPoint (rng->Coords, iv, &x, &y);
30612 			    gaiaAppendPointToDynamicLine (dyn, x, y);
30613 			}
30614 		  }
30615 	    }
30616 	  pg = pg->Next;
30617       }
30618 
30619     pt = dyn->First;
30620     while (pt)
30621       {
30622 	  /* counting how many points */
30623 	  count++;
30624 	  pt = pt->Next;
30625       }
30626     if (count == 0)
30627       {
30628 	  gaiaFreeDynamicLine (dyn);
30629 	  return NULL;
30630       }
30631 
30632 /* allocating and initializing an array of pointers */
30633     sorted = malloc (sizeof (gaiaPointPtr) * count);
30634     iv = 0;
30635     pt = dyn->First;
30636     while (pt)
30637       {
30638 	  *(sorted + iv++) = pt;
30639 	  pt = pt->Next;
30640       }
30641 
30642 /* sorting points by coords */
30643     qsort (sorted, count, sizeof (gaiaPointPtr), cmp_pt_coords);
30644 
30645     if (geom->DimensionModel == GAIA_XY_Z)
30646 	result = gaiaAllocGeomCollXYZ ();
30647     else if (geom->DimensionModel == GAIA_XY_M)
30648 	result = gaiaAllocGeomCollXYM ();
30649     else if (geom->DimensionModel == GAIA_XY_Z_M)
30650 	result = gaiaAllocGeomCollXYZM ();
30651     else
30652 	result = gaiaAllocGeomColl ();
30653     result->Srid = geom->Srid;
30654 
30655 /* identifying nodes */
30656     prev_pt = NULL;
30657     for (iv = 0; iv < count; iv++)
30658       {
30659 	  pt = *(sorted + iv);
30660 	  if (prev_pt != NULL)
30661 	    {
30662 		if (prev_pt->X == pt->X && prev_pt->Y == pt->Y
30663 		    && prev_pt->Z == pt->Z)
30664 		  {
30665 		      if (result->LastPoint != NULL)
30666 			{
30667 			    if (result->LastPoint->X == pt->X
30668 				&& result->LastPoint->Y == pt->Y
30669 				&& result->LastPoint->Z == pt->Z)
30670 				continue;
30671 			}
30672 		      /* Node found */
30673 		      if (result->DimensionModel == GAIA_XY_Z)
30674 			  gaiaAddPointToGeomCollXYZ (result, pt->X, pt->Y,
30675 						     pt->Z);
30676 		      else if (result->DimensionModel == GAIA_XY_M)
30677 			  gaiaAddPointToGeomCollXYM (result, pt->X, pt->Y,
30678 						     pt->M);
30679 		      else if (result->DimensionModel == GAIA_XY_Z_M)
30680 			  gaiaAddPointToGeomCollXYZM (result, pt->X,
30681 						      pt->Y, pt->Z, pt->M);
30682 		      else
30683 			  gaiaAddPointToGeomColl (result, pt->X, pt->Y);
30684 		  }
30685 	    }
30686 	  prev_pt = pt;
30687       }
30688 
30689     if (result->FirstPoint == NULL)
30690       {
30691 	  gaiaFreeGeomColl (result);
30692 	  result = NULL;
30693       }
30694     free (sorted);
30695     gaiaFreeDynamicLine (dyn);
30696     return result;
30697 }
30698 
30699 static void
fnct_RingsCutAtNodes(sqlite3_context * context,int argc,sqlite3_value ** argv)30700 fnct_RingsCutAtNodes (sqlite3_context * context, int argc,
30701 		      sqlite3_value ** argv)
30702 {
30703 /* SQL function:
30704 / RingsCutAtNodes(BLOBencoded geometry)
30705 /
30706 / This function will attempt to return a collection of lines
30707 / representing Polygon/Rings: the input geometry is expected
30708 / to be a Polygon or MultiPolygon.
30709 / Each Ring will be cut accordingly to any identified "node"
30710 / i.e. self-intersections or intersections between two Rings.
30711 /
30712 / NULL is returned for invalid arguments
30713 */
30714     int pts = 0;
30715     int lns = 0;
30716     int pgs = 0;
30717     unsigned char *p_blob;
30718     int n_bytes;
30719     gaiaPointPtr pt;
30720     gaiaLinestringPtr ln;
30721     gaiaPolygonPtr pg;
30722     gaiaGeomCollPtr geom = NULL;
30723     gaiaGeomCollPtr geom1 = NULL;
30724     gaiaGeomCollPtr geom2 = NULL;
30725     gaiaGeomCollPtr result;
30726     int gpkg_amphibious = 0;
30727     int gpkg_mode = 0;
30728     int tiny_point = 0;
30729     struct splite_internal_cache *cache = sqlite3_user_data (context);
30730     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30731     if (cache != NULL)
30732       {
30733 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30734 	  gpkg_mode = cache->gpkg_mode;
30735 	  tiny_point = cache->tinyPointEnabled;
30736       }
30737     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30738       {
30739 	  sqlite3_result_null (context);
30740 	  return;
30741       }
30742     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30743     n_bytes = sqlite3_value_bytes (argv[0]);
30744     geom =
30745 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30746 				     gpkg_amphibious);
30747     if (geom == NULL)
30748       {
30749 	  sqlite3_result_null (context);
30750 	  return;
30751       }
30752 
30753 /* checking if Geometry is a Polygon or MultiPolyhon */
30754     pt = geom->FirstPoint;
30755     while (pt)
30756       {
30757 	  pts++;
30758 	  pt = pt->Next;
30759       }
30760     ln = geom->FirstLinestring;
30761     while (ln)
30762       {
30763 	  lns++;
30764 	  ln = ln->Next;
30765       }
30766     pg = geom->FirstPolygon;
30767     while (pg)
30768       {
30769 	  pgs++;
30770 	  pg = pg->Next;
30771       }
30772     if (pts > 0 || lns > 0 || pgs == 0)
30773       {
30774 	  /* not Polygon/MultiPolygon */
30775 	  gaiaFreeGeomColl (geom);
30776 	  sqlite3_result_null (context);
30777 	  return;
30778       }
30779 
30780 /* transforming Rings into Linestrings */
30781     geom1 = gaiaLinearize (geom, 1);
30782     if (geom1 == NULL)
30783       {
30784 	  gaiaFreeGeomColl (geom);
30785 	  sqlite3_result_null (context);
30786 	  return;
30787       }
30788 
30789 /* identifying the Nodes */
30790     geom2 = auxPolygNodes (geom);
30791     if (geom2 == NULL)
30792       {
30793 	  /* there is no need to cut any Ring [no Nodes] */
30794 	  int len;
30795 	  unsigned char *p_result = NULL;
30796 	  geom1->Srid = geom->Srid;
30797 	  gaiaToSpatiaLiteBlobWkbEx2 (geom1, &p_result, &len, gpkg_mode,
30798 				      tiny_point);
30799 	  sqlite3_result_blob (context, p_result, len, free);
30800 	  gaiaFreeGeomColl (geom);
30801 	  gaiaFreeGeomColl (geom1);
30802 	  return;
30803       }
30804 
30805 /* attempting to cut Rings */
30806     result = gaiaLinesCutAtNodes (geom1, geom2);
30807     if (result == NULL)
30808 	sqlite3_result_null (context);
30809     else
30810       {
30811 	  /* builds the BLOB geometry to be returned */
30812 	  int len;
30813 	  unsigned char *p_result = NULL;
30814 	  result->Srid = geom->Srid;
30815 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len, gpkg_mode,
30816 				      tiny_point);
30817 	  sqlite3_result_blob (context, p_result, len, free);
30818 	  gaiaFreeGeomColl (result);
30819       }
30820     gaiaFreeGeomColl (geom);
30821     gaiaFreeGeomColl (geom1);
30822     gaiaFreeGeomColl (geom2);
30823 }
30824 
30825 #ifdef GEOS_ADVANCED		/* GEOS advanced features - 3.4.0 */
30826 
30827 static void
fnct_DelaunayTriangulation(sqlite3_context * context,int argc,sqlite3_value ** argv)30828 fnct_DelaunayTriangulation (sqlite3_context * context, int argc,
30829 			    sqlite3_value ** argv)
30830 {
30831 /* SQL function:
30832 / DelaunayTriangulation(BLOBencoded geometry)
30833 / DelaunayTriangulation(BLOBencoded geometry, boolean onlyEdges)
30834 / DelaunayTriangulation(BLOBencoded geometry, boolean onlyEdges, double tolerance)
30835 /
30836 / Attempts to build a Delaunay Triangulation using all points/vertices
30837 / found in the input geometry.
30838 / NULL is returned for invalid arguments
30839 */
30840     unsigned char *p_blob;
30841     int n_bytes;
30842     gaiaGeomCollPtr geo = NULL;
30843     gaiaGeomCollPtr result;
30844     int int_value;
30845     double tolerance = 0.0;
30846     int only_edges = 0;
30847     int gpkg_amphibious = 0;
30848     int gpkg_mode = 0;
30849     int tiny_point = 0;
30850     struct splite_internal_cache *cache = sqlite3_user_data (context);
30851     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30852     if (cache != NULL)
30853       {
30854 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30855 	  gpkg_mode = cache->gpkg_mode;
30856 	  tiny_point = cache->tinyPointEnabled;
30857       }
30858     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30859       {
30860 	  sqlite3_result_null (context);
30861 	  return;
30862       }
30863     if (argc >= 2)
30864       {
30865 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
30866 	      only_edges = sqlite3_value_int (argv[1]);
30867 	  else
30868 	    {
30869 		sqlite3_result_null (context);
30870 		return;
30871 	    }
30872       }
30873     if (argc == 3)
30874       {
30875 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
30876 	      tolerance = sqlite3_value_double (argv[2]);
30877 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
30878 	    {
30879 		int_value = sqlite3_value_int (argv[2]);
30880 		tolerance = int_value;
30881 	    }
30882 	  else
30883 	    {
30884 		sqlite3_result_null (context);
30885 		return;
30886 	    }
30887       }
30888     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
30889     n_bytes = sqlite3_value_bytes (argv[0]);
30890     geo =
30891 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
30892 				     gpkg_amphibious);
30893     if (geo == NULL)
30894 	sqlite3_result_null (context);
30895     else
30896       {
30897 	  void *data = sqlite3_user_data (context);
30898 	  if (data != NULL)
30899 	      result =
30900 		  gaiaDelaunayTriangulation_r (data, geo, tolerance,
30901 					       only_edges);
30902 	  else
30903 	      result = gaiaDelaunayTriangulation (geo, tolerance, only_edges);
30904 	  if (result == NULL)
30905 	      sqlite3_result_null (context);
30906 	  else
30907 	    {
30908 		/* builds the BLOB geometry to be returned */
30909 		int len;
30910 		unsigned char *p_result = NULL;
30911 		result->Srid = geo->Srid;
30912 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
30913 					    gpkg_mode, tiny_point);
30914 		sqlite3_result_blob (context, p_result, len, free);
30915 		gaiaFreeGeomColl (result);
30916 	    }
30917       }
30918     gaiaFreeGeomColl (geo);
30919 }
30920 
30921 static void
fnct_VoronojDiagram(sqlite3_context * context,int argc,sqlite3_value ** argv)30922 fnct_VoronojDiagram (sqlite3_context * context, int argc, sqlite3_value ** argv)
30923 {
30924 /* SQL function:
30925 / VoronojDiagram(BLOBencoded geometry)
30926 / VoronojDiagram(BLOBencoded geometry, boolean onlyEdges)
30927 / VoronojDiagram(BLOBencoded geometry, boolean onlyEdges,
30928 /        double extra_frame_size)
30929 / VoronojDiagram(BLOBencoded geometry, boolean onlyEdges,
30930 /        double extra_frame_size, double tolerance)
30931 /
30932 / Attempts to build a Voronoj Diagram using all points/vertices
30933 / found in the input geometry.
30934 / NULL is returned for invalid arguments
30935 */
30936     unsigned char *p_blob;
30937     int n_bytes;
30938     gaiaGeomCollPtr geo = NULL;
30939     gaiaGeomCollPtr result;
30940     int int_value;
30941     double tolerance = 0.0;
30942     double extra_frame_size = -1.0;
30943     int only_edges = 0;
30944     int gpkg_amphibious = 0;
30945     int gpkg_mode = 0;
30946     int tiny_point = 0;
30947     struct splite_internal_cache *cache = sqlite3_user_data (context);
30948     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
30949     if (cache != NULL)
30950       {
30951 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
30952 	  gpkg_mode = cache->gpkg_mode;
30953 	  tiny_point = cache->tinyPointEnabled;
30954       }
30955     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
30956       {
30957 	  sqlite3_result_null (context);
30958 	  return;
30959       }
30960     if (argc >= 2)
30961       {
30962 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
30963 	      only_edges = sqlite3_value_int (argv[1]);
30964 	  else
30965 	    {
30966 		sqlite3_result_null (context);
30967 		return;
30968 	    }
30969       }
30970     if (argc >= 3)
30971       {
30972 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
30973 	      extra_frame_size = sqlite3_value_double (argv[2]);
30974 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
30975 	    {
30976 		int_value = sqlite3_value_int (argv[2]);
30977 		extra_frame_size = int_value;
30978 	    }
30979 	  else
30980 	    {
30981 		sqlite3_result_null (context);
30982 		return;
30983 	    }
30984       }
30985     if (argc == 4)
30986       {
30987 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
30988 	      tolerance = sqlite3_value_double (argv[3]);
30989 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
30990 	    {
30991 		int_value = sqlite3_value_int (argv[3]);
30992 		tolerance = int_value;
30993 	    }
30994 	  else
30995 	    {
30996 		sqlite3_result_null (context);
30997 		return;
30998 	    }
30999       }
31000     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31001     n_bytes = sqlite3_value_bytes (argv[0]);
31002     geo =
31003 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31004 				     gpkg_amphibious);
31005     if (geo == NULL)
31006 	sqlite3_result_null (context);
31007     else
31008       {
31009 	  void *data = sqlite3_user_data (context);
31010 	  if (data != NULL)
31011 	      result =
31012 		  gaiaVoronojDiagram_r (data, geo, extra_frame_size,
31013 					tolerance, only_edges);
31014 	  else
31015 	      result =
31016 		  gaiaVoronojDiagram (geo, extra_frame_size, tolerance,
31017 				      only_edges);
31018 	  if (result == NULL)
31019 	      sqlite3_result_null (context);
31020 	  else
31021 	    {
31022 		/* builds the BLOB geometry to be returned */
31023 		int len;
31024 		unsigned char *p_result = NULL;
31025 		result->Srid = geo->Srid;
31026 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31027 					    gpkg_mode, tiny_point);
31028 		sqlite3_result_blob (context, p_result, len, free);
31029 		gaiaFreeGeomColl (result);
31030 	    }
31031       }
31032     gaiaFreeGeomColl (geo);
31033 }
31034 
31035 static void
fnct_ConcaveHull(sqlite3_context * context,int argc,sqlite3_value ** argv)31036 fnct_ConcaveHull (sqlite3_context * context, int argc, sqlite3_value ** argv)
31037 {
31038 /* SQL function:
31039 / ConcaveHull(BLOBencoded geometry)
31040 / ConcaveHull(BLOBencoded geometry, double factor)
31041 / ConcaveHull(BLOBencoded geometry, double factor, boolean allow_holes)
31042 / ConcaveHull(BLOBencoded geometry, double factor,
31043 /        boolean allow_holes, double tolerance)
31044 /
31045 / Attempts to build a ConcaveHull using all points/vertices
31046 / found in the input geometry.
31047 / NULL is returned for invalid arguments
31048 */
31049     unsigned char *p_blob;
31050     int n_bytes;
31051     gaiaGeomCollPtr geo = NULL;
31052     gaiaGeomCollPtr result;
31053     int int_value;
31054     double tolerance = 0.0;
31055     double factor = 3.0;
31056     int allow_holes = 0;
31057     int gpkg_amphibious = 0;
31058     int gpkg_mode = 0;
31059     int tiny_point = 0;
31060     struct splite_internal_cache *cache = sqlite3_user_data (context);
31061     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31062     if (cache != NULL)
31063       {
31064 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31065 	  gpkg_mode = cache->gpkg_mode;
31066 	  tiny_point = cache->tinyPointEnabled;
31067       }
31068     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31069       {
31070 	  sqlite3_result_null (context);
31071 	  return;
31072       }
31073     if (argc >= 2)
31074       {
31075 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
31076 	      factor = sqlite3_value_double (argv[1]);
31077 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
31078 	    {
31079 		int_value = sqlite3_value_int (argv[1]);
31080 		factor = int_value;
31081 	    }
31082 	  else
31083 	    {
31084 		sqlite3_result_null (context);
31085 		return;
31086 	    }
31087       }
31088     if (argc >= 3)
31089       {
31090 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
31091 	      allow_holes = sqlite3_value_int (argv[2]);
31092 	  else
31093 	    {
31094 		sqlite3_result_null (context);
31095 		return;
31096 	    }
31097       }
31098     if (argc == 4)
31099       {
31100 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
31101 	      tolerance = sqlite3_value_double (argv[3]);
31102 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
31103 	    {
31104 		int_value = sqlite3_value_int (argv[3]);
31105 		tolerance = int_value;
31106 	    }
31107 	  else
31108 	    {
31109 		sqlite3_result_null (context);
31110 		return;
31111 	    }
31112       }
31113     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31114     n_bytes = sqlite3_value_bytes (argv[0]);
31115     geo =
31116 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31117 				     gpkg_amphibious);
31118     if (geo == NULL)
31119 	sqlite3_result_null (context);
31120     else
31121       {
31122 	  void *data = sqlite3_user_data (context);
31123 	  if (data != NULL)
31124 	      result =
31125 		  gaiaConcaveHull_r (data, geo, factor, tolerance, allow_holes);
31126 	  else
31127 	      result = gaiaConcaveHull (geo, factor, tolerance, allow_holes);
31128 	  if (result == NULL)
31129 	      sqlite3_result_null (context);
31130 	  else
31131 	    {
31132 		/* builds the BLOB geometry to be returned */
31133 		int len;
31134 		unsigned char *p_result = NULL;
31135 		result->Srid = geo->Srid;
31136 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31137 					    gpkg_mode, tiny_point);
31138 		sqlite3_result_blob (context, p_result, len, free);
31139 		gaiaFreeGeomColl (result);
31140 	    }
31141       }
31142     gaiaFreeGeomColl (geo);
31143 }
31144 
31145 #endif /* end GEOS advanced features */
31146 
31147 #ifdef ENABLE_RTTOPO		/* enabling RTTOPO support */
31148 
31149 static void
fnct_RTTOPO_GetLastWarningMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)31150 fnct_RTTOPO_GetLastWarningMsg (sqlite3_context * context, int argc,
31151 			       sqlite3_value ** argv)
31152 {
31153 /* SQL function:
31154 / RTTOPO_GetLastWarningMsg()
31155 /
31156 / return the most recent RTTOPO warning message (if any)
31157 / return NULL on any other case
31158 */
31159     const char *msg;
31160     struct splite_internal_cache *cache = sqlite3_user_data (context);
31161     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31162     msg = gaiaGetRtTopoWarningMsg (cache);
31163     if (msg == NULL)
31164 	sqlite3_result_null (context);
31165     else
31166 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
31167 }
31168 
31169 static void
fnct_RTTOPO_GetLastErrorMsg(sqlite3_context * context,int argc,sqlite3_value ** argv)31170 fnct_RTTOPO_GetLastErrorMsg (sqlite3_context * context, int argc,
31171 			     sqlite3_value ** argv)
31172 {
31173 /* SQL function:
31174 / RTTOPO_GetLastErrorMsg()
31175 /
31176 / return the most recent RTEOM error message (if any)
31177 / return NULL on any other case
31178 */
31179     const char *msg;
31180     struct splite_internal_cache *cache = sqlite3_user_data (context);
31181     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31182     msg = gaiaGetRtTopoErrorMsg (cache);
31183     if (msg == NULL)
31184 	sqlite3_result_null (context);
31185     else
31186 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
31187 }
31188 
31189 static void
fnct_MakeValid(sqlite3_context * context,int argc,sqlite3_value ** argv)31190 fnct_MakeValid (sqlite3_context * context, int argc, sqlite3_value ** argv)
31191 {
31192 /* SQL function:
31193 / MakeValid(BLOBencoded geometry)
31194 /
31195 / Attempts to make an invalid geometry valid without loosing vertices.
31196 / NULL is returned for invalid arguments
31197 */
31198     unsigned char *p_blob;
31199     int n_bytes;
31200     gaiaGeomCollPtr geo = NULL;
31201     gaiaGeomCollPtr result;
31202     int gpkg_amphibious = 0;
31203     int gpkg_mode = 0;
31204     int tiny_point = 0;
31205     struct splite_internal_cache *cache = sqlite3_user_data (context);
31206     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31207     if (cache != NULL)
31208       {
31209 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31210 	  gpkg_mode = cache->gpkg_mode;
31211 	  tiny_point = cache->tinyPointEnabled;
31212       }
31213     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31214       {
31215 	  sqlite3_result_null (context);
31216 	  return;
31217       }
31218     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31219     n_bytes = sqlite3_value_bytes (argv[0]);
31220     geo =
31221 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31222 				     gpkg_amphibious);
31223     if (geo == NULL)
31224 	sqlite3_result_null (context);
31225     else
31226       {
31227 	  result = gaiaMakeValid (cache, geo);
31228 	  if (result == NULL)
31229 	    {
31230 		char *msg;
31231 		const char *lw_err = gaiaGetRtTopoErrorMsg (cache);
31232 		if (lw_err)
31233 		    msg = sqlite3_mprintf
31234 			("MakeValid error - RTTOPO reports: %s\n", lw_err);
31235 		else
31236 		    msg = sqlite3_mprintf
31237 			("MakeValid error - RTTOPO reports: Unknown Reason\n");
31238 		sqlite3_result_error (context, msg, strlen (msg));
31239 		sqlite3_free (msg);
31240 	    }
31241 	  else
31242 	    {
31243 		/* builds the BLOB geometry to be returned */
31244 		int len;
31245 		unsigned char *p_result = NULL;
31246 		result->Srid = geo->Srid;
31247 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31248 					    gpkg_mode, tiny_point);
31249 		sqlite3_result_blob (context, p_result, len, free);
31250 		gaiaFreeGeomColl (result);
31251 	    }
31252       }
31253     gaiaFreeGeomColl (geo);
31254 }
31255 
31256 static void
fnct_MakeValidDiscarded(sqlite3_context * context,int argc,sqlite3_value ** argv)31257 fnct_MakeValidDiscarded (sqlite3_context * context, int argc,
31258 			 sqlite3_value ** argv)
31259 {
31260 /* SQL function:
31261 / MakeValidDiscarded(BLOBencoded geometry)
31262 /
31263 / Strictly related to MakeValid(); useful to collect any offending item
31264 / discarded during the validation process.
31265 / NULL is returned for invalid arguments (or if no discarded items are found)
31266 */
31267     unsigned char *p_blob;
31268     int n_bytes;
31269     gaiaGeomCollPtr geo = NULL;
31270     gaiaGeomCollPtr result;
31271     int gpkg_amphibious = 0;
31272     int gpkg_mode = 0;
31273     int tiny_point = 0;
31274     struct splite_internal_cache *cache = sqlite3_user_data (context);
31275     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31276     if (cache != NULL)
31277       {
31278 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31279 	  gpkg_mode = cache->gpkg_mode;
31280 	  tiny_point = cache->tinyPointEnabled;
31281       }
31282     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31283       {
31284 	  sqlite3_result_null (context);
31285 	  return;
31286       }
31287     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31288     n_bytes = sqlite3_value_bytes (argv[0]);
31289     geo =
31290 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31291 				     gpkg_amphibious);
31292     if (geo == NULL)
31293 	sqlite3_result_null (context);
31294     else
31295       {
31296 	  result = gaiaMakeValidDiscarded (cache, geo);
31297 	  if (result == NULL)
31298 	      sqlite3_result_null (context);
31299 	  else
31300 	    {
31301 		/* builds the BLOB geometry to be returned */
31302 		int len;
31303 		unsigned char *p_result = NULL;
31304 		result->Srid = geo->Srid;
31305 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31306 					    gpkg_mode, tiny_point);
31307 		sqlite3_result_blob (context, p_result, len, free);
31308 		gaiaFreeGeomColl (result);
31309 	    }
31310       }
31311     gaiaFreeGeomColl (geo);
31312 }
31313 
31314 static void
fnct_Segmentize(sqlite3_context * context,int argc,sqlite3_value ** argv)31315 fnct_Segmentize (sqlite3_context * context, int argc, sqlite3_value ** argv)
31316 {
31317 /* SQL function:
31318 / Segmentize(BLOBencoded geometry, double dist)
31319 /
31320 / Ensure every segment is at most 'dist' long
31321 / NULL is returned for invalid arguments
31322 */
31323     unsigned char *p_blob;
31324     int n_bytes;
31325     int int_value;
31326     double dist;
31327     gaiaGeomCollPtr geo = NULL;
31328     gaiaGeomCollPtr result;
31329     int gpkg_amphibious = 0;
31330     int gpkg_mode = 0;
31331     int tiny_point = 0;
31332     struct splite_internal_cache *cache = sqlite3_user_data (context);
31333     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31334     if (cache != NULL)
31335       {
31336 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31337 	  gpkg_mode = cache->gpkg_mode;
31338 	  tiny_point = cache->tinyPointEnabled;
31339       }
31340     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31341       {
31342 	  sqlite3_result_null (context);
31343 	  return;
31344       }
31345     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
31346 	dist = sqlite3_value_double (argv[1]);
31347     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
31348       {
31349 	  int_value = sqlite3_value_int (argv[1]);
31350 	  dist = int_value;
31351       }
31352     else
31353       {
31354 	  sqlite3_result_null (context);
31355 	  return;
31356       }
31357     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31358     n_bytes = sqlite3_value_bytes (argv[0]);
31359     geo =
31360 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31361 				     gpkg_amphibious);
31362     if (geo == NULL)
31363 	sqlite3_result_null (context);
31364     else
31365       {
31366 	  result = gaiaSegmentize (cache, geo, dist);
31367 	  if (result == NULL)
31368 	      sqlite3_result_null (context);
31369 	  else
31370 	    {
31371 		/* builds the BLOB geometry to be returned */
31372 		int len;
31373 		unsigned char *p_result = NULL;
31374 		result->Srid = geo->Srid;
31375 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31376 					    gpkg_mode, tiny_point);
31377 		sqlite3_result_blob (context, p_result, len, free);
31378 		gaiaFreeGeomColl (result);
31379 	    }
31380       }
31381     gaiaFreeGeomColl (geo);
31382 }
31383 
31384 static int
is_line(gaiaGeomCollPtr geom)31385 is_line (gaiaGeomCollPtr geom)
31386 {
31387 /* checking for a Linestring or MultiLinestring */
31388     if (geom->FirstPoint != NULL || geom->FirstPolygon != NULL)
31389 	return 0;
31390     if (geom->FirstLinestring != NULL)
31391 	return 1;
31392     return 0;
31393 }
31394 
31395 static int
is_point_blade(gaiaGeomCollPtr geom)31396 is_point_blade (gaiaGeomCollPtr geom)
31397 {
31398 /* checking for a Point or MultiPoint */
31399     if (geom->FirstLinestring != NULL || geom->FirstPolygon != NULL)
31400 	return 0;
31401     if (geom->FirstPoint != NULL)
31402 	return 1;
31403     return 0;
31404 }
31405 
31406 static void
fnct_SnapAndSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)31407 fnct_SnapAndSplit (sqlite3_context * context, int argc, sqlite3_value ** argv)
31408 {
31409 /* SQL function:
31410 / SnapAndSplit(BLOBencoded geometry1, BLOBencoded geometry2, double tolerance)
31411 /
31412 / - geometry1 is expected to be a LINESTRING or MULTILINESTRING
31413 / - geometry2 is expected to be a MULTIPOINT
31414 / - in a first pass geometry1 will be snapped against geometry2
31415 / - then the intermediate result of Snap will be Split using
31416 /   geometry2 as the cutting blade.
31417 / .-
31418 / Returns a new Geometry of the MULTILINESTRING type
31419 / NULL is returned for invalid arguments
31420 */
31421     unsigned char *p_blob;
31422     int n_bytes;
31423     int int_value;
31424     double tolerance;
31425     gaiaGeomCollPtr geo1 = NULL;
31426     gaiaGeomCollPtr geo2 = NULL;
31427     gaiaGeomCollPtr result_snap;
31428     gaiaGeomCollPtr result_split;
31429     int gpkg_amphibious = 0;
31430     int gpkg_mode = 0;
31431     int tiny_point = 0;
31432     struct splite_internal_cache *cache = sqlite3_user_data (context);
31433     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31434     if (cache != NULL)
31435       {
31436 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31437 	  gpkg_mode = cache->gpkg_mode;
31438 	  tiny_point = cache->tinyPointEnabled;
31439       }
31440     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31441       {
31442 	  sqlite3_result_null (context);
31443 	  return;
31444       }
31445     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
31446       {
31447 	  sqlite3_result_null (context);
31448 	  return;
31449       }
31450     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
31451 	tolerance = sqlite3_value_double (argv[2]);
31452     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
31453       {
31454 	  int_value = sqlite3_value_int (argv[2]);
31455 	  tolerance = int_value;
31456       }
31457     else
31458       {
31459 	  sqlite3_result_null (context);
31460 	  return;
31461       }
31462     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31463     n_bytes = sqlite3_value_bytes (argv[0]);
31464     geo1 =
31465 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31466 				     gpkg_amphibious);
31467     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
31468     n_bytes = sqlite3_value_bytes (argv[1]);
31469     geo2 =
31470 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31471 				     gpkg_amphibious);
31472     if (geo1 == NULL || geo2 == NULL)
31473 	sqlite3_result_null (context);
31474     else if (is_line (geo1) == 0)
31475 	sqlite3_result_null (context);
31476     else if (is_point_blade (geo2) == 0)
31477 	sqlite3_result_null (context);
31478     else
31479       {
31480 	  void *data = sqlite3_user_data (context);
31481 	  if (data != NULL)
31482 	      result_snap = gaiaSnap_r (data, geo1, geo2, tolerance);
31483 	  else
31484 	      result_snap = gaiaSnap (geo1, geo2, tolerance);
31485 	  if (result_snap == NULL)
31486 	      sqlite3_result_null (context);
31487 	  else
31488 	    {
31489 		result_split = gaiaSplit (cache, result_snap, geo2);
31490 		gaiaFreeGeomColl (result_snap);
31491 		if (result_split == NULL)
31492 		    sqlite3_result_null (context);
31493 		else
31494 		  {
31495 		      /* builds the BLOB geometry to be returned */
31496 		      int len;
31497 		      unsigned char *p_result = NULL;
31498 		      result_split->Srid = geo1->Srid;
31499 		      gaiaToSpatiaLiteBlobWkbEx2 (result_split, &p_result, &len,
31500 						  gpkg_mode, tiny_point);
31501 		      sqlite3_result_blob (context, p_result, len, free);
31502 		      gaiaFreeGeomColl (result_split);
31503 		  }
31504 	    }
31505       }
31506     gaiaFreeGeomColl (geo1);
31507     gaiaFreeGeomColl (geo2);
31508 }
31509 
31510 static void
fnct_Split(sqlite3_context * context,int argc,sqlite3_value ** argv)31511 fnct_Split (sqlite3_context * context, int argc, sqlite3_value ** argv)
31512 {
31513 /* SQL function:
31514 / Split(BLOBencoded input, BLOBencoded blade)
31515 /
31516 / Returns a collection of geometries resulting by splitting a geometry
31517 / NULL is returned for invalid arguments
31518 */
31519     unsigned char *p_blob;
31520     int n_bytes;
31521     gaiaGeomCollPtr input = NULL;
31522     gaiaGeomCollPtr blade = NULL;
31523     gaiaGeomCollPtr result;
31524     int gpkg_amphibious = 0;
31525     int gpkg_mode = 0;
31526     int tiny_point = 0;
31527     struct splite_internal_cache *cache = sqlite3_user_data (context);
31528     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31529     if (cache != NULL)
31530       {
31531 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31532 	  gpkg_mode = cache->gpkg_mode;
31533 	  tiny_point = cache->tinyPointEnabled;
31534       }
31535     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31536       {
31537 	  sqlite3_result_null (context);
31538 	  return;
31539       }
31540     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
31541       {
31542 	  sqlite3_result_null (context);
31543 	  return;
31544       }
31545     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31546     n_bytes = sqlite3_value_bytes (argv[0]);
31547     input =
31548 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31549 				     gpkg_amphibious);
31550     if (input == NULL)
31551       {
31552 	  sqlite3_result_null (context);
31553 	  return;
31554       }
31555     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
31556     n_bytes = sqlite3_value_bytes (argv[1]);
31557     blade =
31558 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31559 				     gpkg_amphibious);
31560     if (blade == NULL)
31561       {
31562 	  gaiaFreeGeomColl (input);
31563 	  sqlite3_result_null (context);
31564 	  return;
31565       }
31566     else
31567       {
31568 	  result = gaiaSplit (cache, input, blade);
31569 	  if (result == NULL)
31570 	      sqlite3_result_null (context);
31571 	  else
31572 	    {
31573 		/* builds the BLOB geometry to be returned */
31574 		int len;
31575 		unsigned char *p_result = NULL;
31576 		result->Srid = input->Srid;
31577 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31578 					    gpkg_mode, tiny_point);
31579 		sqlite3_result_blob (context, p_result, len, free);
31580 		gaiaFreeGeomColl (result);
31581 	    }
31582       }
31583     gaiaFreeGeomColl (input);
31584     gaiaFreeGeomColl (blade);
31585 }
31586 
31587 static void
fnct_SplitLeft(sqlite3_context * context,int argc,sqlite3_value ** argv)31588 fnct_SplitLeft (sqlite3_context * context, int argc, sqlite3_value ** argv)
31589 {
31590 /* SQL function:
31591 / SplitLeft(BLOBencoded input, BLOBencoded blade)
31592 /
31593 / Returns a collection of geometries resulting by splitting a geometry [left half]
31594 / NULL is returned for invalid arguments
31595 */
31596     unsigned char *p_blob;
31597     int n_bytes;
31598     gaiaGeomCollPtr input = NULL;
31599     gaiaGeomCollPtr blade = NULL;
31600     gaiaGeomCollPtr result;
31601     int gpkg_amphibious = 0;
31602     int gpkg_mode = 0;
31603     int tiny_point = 0;
31604     struct splite_internal_cache *cache = sqlite3_user_data (context);
31605     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31606     if (cache != NULL)
31607       {
31608 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31609 	  gpkg_mode = cache->gpkg_mode;
31610 	  tiny_point = cache->tinyPointEnabled;
31611       }
31612     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31613       {
31614 	  sqlite3_result_null (context);
31615 	  return;
31616       }
31617     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
31618       {
31619 	  sqlite3_result_null (context);
31620 	  return;
31621       }
31622     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31623     n_bytes = sqlite3_value_bytes (argv[0]);
31624     input =
31625 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31626 				     gpkg_amphibious);
31627     if (input == NULL)
31628       {
31629 	  sqlite3_result_null (context);
31630 	  return;
31631       }
31632     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
31633     n_bytes = sqlite3_value_bytes (argv[1]);
31634     blade =
31635 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31636 				     gpkg_amphibious);
31637     if (blade == NULL)
31638       {
31639 	  gaiaFreeGeomColl (input);
31640 	  sqlite3_result_null (context);
31641 	  return;
31642       }
31643     else
31644       {
31645 	  result = gaiaSplitLeft (cache, input, blade);
31646 	  if (result == NULL)
31647 	      sqlite3_result_null (context);
31648 	  else
31649 	    {
31650 		/* builds the BLOB geometry to be returned */
31651 		int len;
31652 		unsigned char *p_result = NULL;
31653 		result->Srid = input->Srid;
31654 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31655 					    gpkg_mode, tiny_point);
31656 		sqlite3_result_blob (context, p_result, len, free);
31657 		gaiaFreeGeomColl (result);
31658 	    }
31659       }
31660     gaiaFreeGeomColl (input);
31661     gaiaFreeGeomColl (blade);
31662 }
31663 
31664 static void
fnct_SplitRight(sqlite3_context * context,int argc,sqlite3_value ** argv)31665 fnct_SplitRight (sqlite3_context * context, int argc, sqlite3_value ** argv)
31666 {
31667 /* SQL function:
31668 / SplitRight(BLOBencoded input, BLOBencoded blade)
31669 /
31670 / Returns a collection of geometries resulting by splitting a geometry [right half]
31671 / NULL is returned for invalid arguments
31672 */
31673     unsigned char *p_blob;
31674     int n_bytes;
31675     gaiaGeomCollPtr input = NULL;
31676     gaiaGeomCollPtr blade = NULL;
31677     gaiaGeomCollPtr result;
31678     int gpkg_amphibious = 0;
31679     int gpkg_mode = 0;
31680     int tiny_point = 0;
31681     struct splite_internal_cache *cache = sqlite3_user_data (context);
31682     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31683     if (cache != NULL)
31684       {
31685 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31686 	  gpkg_mode = cache->gpkg_mode;
31687 	  tiny_point = cache->tinyPointEnabled;
31688       }
31689     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31690       {
31691 	  sqlite3_result_null (context);
31692 	  return;
31693       }
31694     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
31695       {
31696 	  sqlite3_result_null (context);
31697 	  return;
31698       }
31699     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31700     n_bytes = sqlite3_value_bytes (argv[0]);
31701     input =
31702 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31703 				     gpkg_amphibious);
31704     if (input == NULL)
31705       {
31706 	  sqlite3_result_null (context);
31707 	  return;
31708       }
31709     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
31710     n_bytes = sqlite3_value_bytes (argv[1]);
31711     blade =
31712 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31713 				     gpkg_amphibious);
31714     if (blade == NULL)
31715       {
31716 	  gaiaFreeGeomColl (input);
31717 	  sqlite3_result_null (context);
31718 	  return;
31719       }
31720     else
31721       {
31722 	  result = gaiaSplitRight (cache, input, blade);
31723 	  if (result == NULL)
31724 	      sqlite3_result_null (context);
31725 	  else
31726 	    {
31727 		/* builds the BLOB geometry to be returned */
31728 		int len;
31729 		unsigned char *p_result = NULL;
31730 		result->Srid = input->Srid;
31731 		gaiaToSpatiaLiteBlobWkbEx2 (result, &p_result, &len,
31732 					    gpkg_mode, tiny_point);
31733 		sqlite3_result_blob (context, p_result, len, free);
31734 		gaiaFreeGeomColl (result);
31735 	    }
31736       }
31737     gaiaFreeGeomColl (input);
31738     gaiaFreeGeomColl (blade);
31739 }
31740 
31741 static int
getXYSinglePoint(gaiaGeomCollPtr geom,double * x,double * y)31742 getXYSinglePoint (gaiaGeomCollPtr geom, double *x, double *y)
31743 {
31744 /* check if this geometry is a simple Point (returning 2D coords) */
31745     double z;
31746     double m;
31747     return getXYZMSinglePoint (geom, x, y, &z, &m);
31748 }
31749 
31750 static void
fnct_Azimuth(sqlite3_context * context,int argc,sqlite3_value ** argv)31751 fnct_Azimuth (sqlite3_context * context, int argc, sqlite3_value ** argv)
31752 {
31753 /* SQL function:
31754 / Azimuth(BLOBencoded pointA, BLOBencoded pointB)
31755 /
31756 / Returns the angle in radians from the horizontal of the vector
31757 / defined by pointA and pointB.
31758 / Angle is computed clockwise from down-to-up: on the clock:
31759 / 12=0; 3=PI/2; 6=PI; 9=3PI/2.
31760 / NULL is returned for invalid arguments
31761 */
31762     unsigned char *p_blob;
31763     int n_bytes;
31764     gaiaGeomCollPtr geom;
31765     double x1;
31766     double y1;
31767     double x2;
31768     double y2;
31769     double a;
31770     double b;
31771     double rf;
31772     double azimuth;
31773     int srid;
31774     sqlite3 *sqlite = sqlite3_context_db_handle (context);
31775     int gpkg_amphibious = 0;
31776     int gpkg_mode = 0;
31777     struct splite_internal_cache *cache = sqlite3_user_data (context);
31778     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31779     if (cache != NULL)
31780       {
31781 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31782 	  gpkg_mode = cache->gpkg_mode;
31783       }
31784     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31785       {
31786 	  sqlite3_result_null (context);
31787 	  return;
31788       }
31789     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
31790       {
31791 	  sqlite3_result_null (context);
31792 	  return;
31793       }
31794 
31795 /* retrieving and validating the first point */
31796     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31797     n_bytes = sqlite3_value_bytes (argv[0]);
31798     geom =
31799 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31800 				     gpkg_amphibious);
31801     if (geom == NULL)
31802       {
31803 	  sqlite3_result_null (context);
31804 	  return;
31805       }
31806     if (!getXYSinglePoint (geom, &x1, &y1))
31807       {
31808 	  gaiaFreeGeomColl (geom);
31809 	  sqlite3_result_null (context);
31810 	  return;
31811       }
31812     srid = geom->Srid;
31813     gaiaFreeGeomColl (geom);
31814 
31815 /* retrieving and validating the second point */
31816     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
31817     n_bytes = sqlite3_value_bytes (argv[1]);
31818     geom =
31819 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31820 				     gpkg_amphibious);
31821     if (geom == NULL)
31822       {
31823 	  sqlite3_result_null (context);
31824 	  return;
31825       }
31826     if (!getXYSinglePoint (geom, &x2, &y2))
31827       {
31828 	  gaiaFreeGeomColl (geom);
31829 	  sqlite3_result_null (context);
31830 	  return;
31831       }
31832     gaiaFreeGeomColl (geom);
31833 
31834     if (getEllipsoidParams (sqlite, srid, &a, &b, &rf))
31835       {
31836 	  if (gaiaEllipsoidAzimuth (cache, x1, y1, x2, y2, a, b, &azimuth))
31837 	      sqlite3_result_double (context, azimuth);
31838 	  else
31839 	      sqlite3_result_null (context);
31840 	  return;
31841       }
31842 
31843     if (gaiaAzimuth (cache, x1, y1, x2, y2, &azimuth))
31844 	sqlite3_result_double (context, azimuth);
31845     else
31846 	sqlite3_result_null (context);
31847 }
31848 
31849 static void
fnct_Project(sqlite3_context * context,int argc,sqlite3_value ** argv)31850 fnct_Project (sqlite3_context * context, int argc, sqlite3_value ** argv)
31851 {
31852 /* SQL function:
31853 / Project(BLOBencoded point, distance Double, bearing Double)
31854 /
31855 / Returns a new Point projected from a start point given a
31856 / distance and a bearing.
31857 / - Point is expected to be Long/Lat
31858 / - Distance is in meters
31859 / - Bearing is in radians; on the clock:
31860 /   12=0; 3=PI/2; 6=PI; 9=3PI/2.
31861 / NULL is returned for invalid arguments
31862 */
31863     unsigned char *p_blob;
31864     int n_bytes;
31865     gaiaGeomCollPtr geom;
31866     double x1;
31867     double y1;
31868     double x2;
31869     double y2;
31870     int ival;
31871     double distance;
31872     double azimuth;
31873     double a;
31874     double b;
31875     double rf;
31876     int srid;
31877     sqlite3 *sqlite = sqlite3_context_db_handle (context);
31878     int gpkg_amphibious = 0;
31879     int gpkg_mode = 0;
31880     int tiny_point = 0;
31881     struct splite_internal_cache *cache = sqlite3_user_data (context);
31882     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31883     if (cache != NULL)
31884       {
31885 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31886 	  gpkg_mode = cache->gpkg_mode;
31887 	  tiny_point = cache->tinyPointEnabled;
31888       }
31889     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31890       {
31891 	  sqlite3_result_null (context);
31892 	  return;
31893       }
31894     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
31895 	distance = sqlite3_value_double (argv[1]);
31896     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
31897       {
31898 	  ival = sqlite3_value_int (argv[1]);
31899 	  distance = ival;
31900       }
31901     else
31902       {
31903 	  sqlite3_result_null (context);
31904 	  return;
31905       }
31906     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
31907 	azimuth = sqlite3_value_double (argv[2]);
31908     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
31909       {
31910 	  ival = sqlite3_value_int (argv[2]);
31911 	  azimuth = ival;
31912       }
31913     else
31914       {
31915 	  sqlite3_result_null (context);
31916 	  return;
31917       }
31918 
31919 /* retrieving and validating the start point */
31920     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
31921     n_bytes = sqlite3_value_bytes (argv[0]);
31922     geom =
31923 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
31924 				     gpkg_amphibious);
31925     if (geom == NULL)
31926       {
31927 	  sqlite3_result_null (context);
31928 	  return;
31929       }
31930     if (!getXYSinglePoint (geom, &x1, &y1))
31931       {
31932 	  gaiaFreeGeomColl (geom);
31933 	  sqlite3_result_null (context);
31934 	  return;
31935       }
31936     srid = geom->Srid;
31937     gaiaFreeGeomColl (geom);
31938     if (!getEllipsoidParams (sqlite, srid, &a, &b, &rf))
31939       {
31940 	  sqlite3_result_null (context);
31941 	  return;
31942       }
31943     if (distance == 0.0)
31944       {
31945 	  /* returning the Start Point */
31946 	  gaiaMakePointEx (tiny_point, x1, y1, srid, &p_blob, &n_bytes);
31947 	  if (!p_blob)
31948 	      sqlite3_result_null (context);
31949 	  else
31950 	      sqlite3_result_blob (context, p_blob, n_bytes, free);
31951 	  return;
31952       }
31953 
31954     if (gaiaProjectedPoint (cache, x1, y1, a, b, distance, azimuth, &x2, &y2))
31955       {
31956 	  gaiaMakePointEx (tiny_point, x2, y2, srid, &p_blob, &n_bytes);
31957 	  if (!p_blob)
31958 	      sqlite3_result_null (context);
31959 	  else
31960 	      sqlite3_result_blob (context, p_blob, n_bytes, free);
31961       }
31962     else
31963 	sqlite3_result_null (context);
31964 }
31965 
31966 static void
fnct_GeoHash(sqlite3_context * context,int argc,sqlite3_value ** argv)31967 fnct_GeoHash (sqlite3_context * context, int argc, sqlite3_value ** argv)
31968 {
31969 /* SQL function:
31970 / GeoHash(BLOBencoded geom)
31971 / GeoHash(BLOBencoded geom, Integer precision)
31972 /
31973 / Returns a GeoHash representation for input geometry
31974 / (expected to be in longitude/latitude coords)
31975 / NULL is returned for invalid arguments
31976 */
31977     unsigned char *p_blob;
31978     int n_bytes;
31979     gaiaGeomCollPtr geom;
31980     int precision = 0;
31981     char *geo_hash;
31982     int gpkg_amphibious = 0;
31983     int gpkg_mode = 0;
31984     struct splite_internal_cache *cache = sqlite3_user_data (context);
31985     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
31986     if (cache != NULL)
31987       {
31988 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
31989 	  gpkg_mode = cache->gpkg_mode;
31990       }
31991     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
31992       {
31993 	  sqlite3_result_null (context);
31994 	  return;
31995       }
31996     if (argc == 2)
31997       {
31998 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
31999 	      precision = sqlite3_value_int (argv[1]);
32000 	  else
32001 	    {
32002 		sqlite3_result_null (context);
32003 		return;
32004 	    }
32005       }
32006 
32007     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32008     n_bytes = sqlite3_value_bytes (argv[0]);
32009     geom =
32010 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32011 				     gpkg_amphibious);
32012     if (geom == NULL)
32013       {
32014 	  sqlite3_result_null (context);
32015 	  return;
32016       }
32017     geo_hash = gaiaGeoHash (cache, geom, precision);
32018     if (geo_hash != NULL)
32019       {
32020 	  int len = strlen (geo_hash);
32021 	  sqlite3_result_text (context, geo_hash, len, free);
32022       }
32023     else
32024 	sqlite3_result_null (context);
32025     gaiaFreeGeomColl (geom);
32026 }
32027 
32028 static char *
get_srs_by_srid(sqlite3 * sqlite,int srid,int longsrs)32029 get_srs_by_srid (sqlite3 * sqlite, int srid, int longsrs)
32030 {
32031 /* retrieves the short- or long- srs reference for the given srid */
32032     char sql[1024];
32033     int ret;
32034     const char *name;
32035     int i;
32036     char **results;
32037     int rows;
32038     int columns;
32039     int len;
32040     char *srs = NULL;
32041 
32042     if (longsrs)
32043 	sprintf (sql,
32044 		 "SELECT 'urn:ogc:def:crs:' || auth_name || '::' || auth_srid "
32045 		 "FROM spatial_ref_sys WHERE srid = %d", srid);
32046     else
32047 	sprintf (sql, "SELECT auth_name || ':' || auth_srid "
32048 		 "FROM spatial_ref_sys WHERE srid = %d", srid);
32049     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
32050     if (ret != SQLITE_OK)
32051 	return NULL;
32052     if (rows < 1)
32053 	;
32054     else
32055       {
32056 	  for (i = 1; i <= rows; i++)
32057 	    {
32058 		name = results[(i * columns) + 0];
32059 		len = strlen (name);
32060 		srs = malloc (len + 1);
32061 		strcpy (srs, name);
32062 	    }
32063       }
32064     sqlite3_free_table (results);
32065     return srs;
32066 }
32067 
32068 static void
fnct_AsX3D(sqlite3_context * context,int argc,sqlite3_value ** argv)32069 fnct_AsX3D (sqlite3_context * context, int argc, sqlite3_value ** argv)
32070 {
32071 /* SQL function:
32072 / AsX3D(BLOBencoded geom)
32073 / AsX3D(BLOBencoded geom, Integer precision)
32074 / AsX3D(BLOBencoded geom, Integer precision, Integer options)
32075 / AsX3D(BLOBencoded geom, Integer precision, Integer options, Text refid)
32076 /
32077 / Returns an X3D representation for input geometry
32078 / NULL is returned for invalid arguments
32079 */
32080     unsigned char *p_blob;
32081     int n_bytes;
32082     gaiaGeomCollPtr geom;
32083     int precision = 15;
32084     int options = 0;
32085     const char *refid = "";
32086     char *srs = NULL;
32087     char *x3d;
32088     sqlite3 *sqlite = sqlite3_context_db_handle (context);
32089     int gpkg_amphibious = 0;
32090     int gpkg_mode = 0;
32091     struct splite_internal_cache *cache = sqlite3_user_data (context);
32092     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32093     if (cache != NULL)
32094       {
32095 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32096 	  gpkg_mode = cache->gpkg_mode;
32097       }
32098     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32099       {
32100 	  sqlite3_result_null (context);
32101 	  return;
32102       }
32103     if (argc >= 2)
32104       {
32105 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
32106 	      precision = sqlite3_value_int (argv[1]);
32107 	  else
32108 	    {
32109 		sqlite3_result_null (context);
32110 		return;
32111 	    }
32112       }
32113     if (argc >= 3)
32114       {
32115 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
32116 	      options = sqlite3_value_int (argv[2]);
32117 	  else
32118 	    {
32119 		sqlite3_result_null (context);
32120 		return;
32121 	    }
32122       }
32123     if (argc == 4)
32124       {
32125 	  if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
32126 	      refid = (const char *) sqlite3_value_text (argv[3]);
32127 	  else
32128 	    {
32129 		sqlite3_result_null (context);
32130 		return;
32131 	    }
32132       }
32133 
32134     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32135     n_bytes = sqlite3_value_bytes (argv[0]);
32136     geom =
32137 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32138 				     gpkg_amphibious);
32139     if (geom == NULL)
32140       {
32141 	  sqlite3_result_null (context);
32142 	  return;
32143       }
32144     if (geom->Srid > 0)
32145       {
32146 	  int longshort = 0;
32147 	  if (options & 1)
32148 	      longshort = 1;
32149 	  srs = get_srs_by_srid (sqlite, geom->Srid, longshort);
32150       }
32151     x3d = gaiaAsX3D (cache, geom, srs, precision, options, refid);
32152     if (x3d != NULL)
32153       {
32154 	  int len = strlen (x3d);
32155 	  sqlite3_result_text (context, x3d, len, free);
32156       }
32157     else
32158 	sqlite3_result_null (context);
32159     gaiaFreeGeomColl (geom);
32160     if (srs)
32161 	free (srs);
32162 }
32163 
32164 static void
fnct_3DDistance(sqlite3_context * context,int argc,sqlite3_value ** argv)32165 fnct_3DDistance (sqlite3_context * context, int argc, sqlite3_value ** argv)
32166 {
32167 /* SQL function:
32168 / 3DDistance(BLOBencoded geom1, BLOBencoded geom2)
32169 /
32170 / returns the 3D distance between GEOM-1 and GEOM-2
32171 */
32172     unsigned char *p_blob;
32173     int n_bytes;
32174     gaiaGeomCollPtr geo1 = NULL;
32175     gaiaGeomCollPtr geo2 = NULL;
32176     double dist;
32177     int ret;
32178     int gpkg_amphibious = 0;
32179     int gpkg_mode = 0;
32180     struct splite_internal_cache *cache = sqlite3_user_data (context);
32181     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32182     if (cache != NULL)
32183       {
32184 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32185 	  gpkg_mode = cache->gpkg_mode;
32186       }
32187     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32188       {
32189 	  sqlite3_result_null (context);
32190 	  return;
32191       }
32192     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
32193       {
32194 	  sqlite3_result_null (context);
32195 	  return;
32196       }
32197     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32198     n_bytes = sqlite3_value_bytes (argv[0]);
32199     geo1 =
32200 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32201 				     gpkg_amphibious);
32202     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
32203     n_bytes = sqlite3_value_bytes (argv[1]);
32204     geo2 =
32205 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32206 				     gpkg_amphibious);
32207     if (!geo1 || !geo2)
32208 	sqlite3_result_null (context);
32209     else
32210       {
32211 	  ret = gaia3DDistance (cache, geo1, geo2, &dist);
32212 	  if (!ret)
32213 	      sqlite3_result_null (context);
32214 	  else
32215 	      sqlite3_result_double (context, dist);
32216       }
32217     gaiaFreeGeomColl (geo1);
32218     gaiaFreeGeomColl (geo2);
32219 }
32220 
32221 static void
fnct_MaxDistance(sqlite3_context * context,int argc,sqlite3_value ** argv)32222 fnct_MaxDistance (sqlite3_context * context, int argc, sqlite3_value ** argv)
32223 {
32224 /* SQL function:
32225 / MaxDistance(BLOBencoded geom1, BLOBencoded geom2)
32226 /
32227 / returns the max 2D distance between GEOM-1 and GEOM-2
32228 */
32229     unsigned char *p_blob;
32230     int n_bytes;
32231     gaiaGeomCollPtr geo1 = NULL;
32232     gaiaGeomCollPtr geo2 = NULL;
32233     double dist;
32234     int ret;
32235     int gpkg_amphibious = 0;
32236     int gpkg_mode = 0;
32237     struct splite_internal_cache *cache = sqlite3_user_data (context);
32238     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32239     if (cache != NULL)
32240       {
32241 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32242 	  gpkg_mode = cache->gpkg_mode;
32243       }
32244     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32245       {
32246 	  sqlite3_result_null (context);
32247 	  return;
32248       }
32249     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
32250       {
32251 	  sqlite3_result_null (context);
32252 	  return;
32253       }
32254     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32255     n_bytes = sqlite3_value_bytes (argv[0]);
32256     geo1 =
32257 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32258 				     gpkg_amphibious);
32259     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
32260     n_bytes = sqlite3_value_bytes (argv[1]);
32261     geo2 =
32262 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32263 				     gpkg_amphibious);
32264     if (!geo1 || !geo2)
32265 	sqlite3_result_null (context);
32266     else
32267       {
32268 	  ret = gaiaMaxDistance (cache, geo1, geo2, &dist);
32269 	  if (!ret)
32270 	      sqlite3_result_null (context);
32271 	  else
32272 	      sqlite3_result_double (context, dist);
32273       }
32274     gaiaFreeGeomColl (geo1);
32275     gaiaFreeGeomColl (geo2);
32276 }
32277 
32278 static void
fnct_3DMaxDistance(sqlite3_context * context,int argc,sqlite3_value ** argv)32279 fnct_3DMaxDistance (sqlite3_context * context, int argc, sqlite3_value ** argv)
32280 {
32281 /* SQL function:
32282 / 3DMaxDistance(BLOBencoded geom1, BLOBencoded geom2)
32283 /
32284 / returns the max 3D distance between GEOM-1 and GEOM-2
32285 */
32286     unsigned char *p_blob;
32287     int n_bytes;
32288     gaiaGeomCollPtr geo1 = NULL;
32289     gaiaGeomCollPtr geo2 = NULL;
32290     double dist;
32291     int ret;
32292     int gpkg_amphibious = 0;
32293     int gpkg_mode = 0;
32294     struct splite_internal_cache *cache = sqlite3_user_data (context);
32295     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32296     if (cache != NULL)
32297       {
32298 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32299 	  gpkg_mode = cache->gpkg_mode;
32300       }
32301     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32302       {
32303 	  sqlite3_result_null (context);
32304 	  return;
32305       }
32306     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
32307       {
32308 	  sqlite3_result_null (context);
32309 	  return;
32310       }
32311     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32312     n_bytes = sqlite3_value_bytes (argv[0]);
32313     geo1 =
32314 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32315 				     gpkg_amphibious);
32316     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
32317     n_bytes = sqlite3_value_bytes (argv[1]);
32318     geo2 =
32319 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32320 				     gpkg_amphibious);
32321     if (!geo1 || !geo2)
32322 	sqlite3_result_null (context);
32323     else
32324       {
32325 	  ret = gaia3DMaxDistance (cache, geo1, geo2, &dist);
32326 	  if (!ret)
32327 	      sqlite3_result_null (context);
32328 	  else
32329 	      sqlite3_result_double (context, dist);
32330       }
32331     gaiaFreeGeomColl (geo1);
32332     gaiaFreeGeomColl (geo2);
32333 }
32334 
32335 static void
fnct_Node(sqlite3_context * context,int argc,sqlite3_value ** argv)32336 fnct_Node (sqlite3_context * context, int argc, sqlite3_value ** argv)
32337 {
32338 /* SQL function:
32339 / ST_Node(BLOBencoded linestring(s))
32340 /
32341 / Returns a new new (Multi)Linestring by re-noding the input linestring(s)
32342 / NULL is returned for invalid arguments
32343 */
32344     unsigned char *p_blob;
32345     int n_bytes;
32346     gaiaGeomCollPtr input;
32347     gaiaGeomCollPtr result;
32348     int gpkg_amphibious = 0;
32349     int gpkg_mode = 0;
32350     int tiny_point = 0;
32351     struct splite_internal_cache *cache = sqlite3_user_data (context);
32352     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32353     if (cache != NULL)
32354       {
32355 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32356 	  gpkg_mode = cache->gpkg_mode;
32357 	  tiny_point = cache->tinyPointEnabled;
32358       }
32359     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32360       {
32361 	  sqlite3_result_null (context);
32362 	  return;
32363       }
32364 
32365 /* retrieving the input geometry */
32366     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32367     n_bytes = sqlite3_value_bytes (argv[0]);
32368     input =
32369 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32370 				     gpkg_amphibious);
32371     if (input == NULL)
32372       {
32373 	  sqlite3_result_null (context);
32374 	  return;
32375       }
32376 
32377     result = gaiaNodeLines (cache, input);
32378     if (result != NULL)
32379       {
32380 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_blob, &n_bytes, gpkg_mode,
32381 				      tiny_point);
32382 	  sqlite3_result_blob (context, p_blob, n_bytes, free);
32383 	  gaiaFreeGeomColl (result);
32384       }
32385     else
32386 	sqlite3_result_null (context);
32387     gaiaFreeGeomColl (input);
32388 }
32389 
32390 static int
check_all_linestrings(gaiaGeomCollPtr in)32391 check_all_linestrings (gaiaGeomCollPtr in)
32392 {
32393 /* check id this is a collection of Linestrings */
32394     int pts = 0;
32395     int lns = 0;
32396     int pgs = 0;
32397     gaiaPointPtr pt;
32398     gaiaLinestringPtr ln;
32399     gaiaPolygonPtr pg;
32400 
32401     if (in == NULL)
32402 	return 0;
32403 /* checking if we have any POINT */
32404     pt = in->FirstPoint;
32405     while (pt)
32406       {
32407 	  pts++;
32408 	  pt = pt->Next;
32409       }
32410     if (pts > 0)
32411 	return 0;
32412 /* checking if we have any POLYGON */
32413     pg = in->FirstPolygon;
32414     while (pg)
32415       {
32416 	  pgs++;
32417 	  pg = pg->Next;
32418       }
32419     if (pgs > 0)
32420 	return 0;
32421 /* checking if we have any LINESTRING */
32422     ln = in->FirstLinestring;
32423     while (ln)
32424       {
32425 	  lns++;
32426 	  ln = ln->Next;
32427       }
32428     if (lns == 0)
32429 	return 0;
32430     return 1;
32431 }
32432 
32433 static gaiaGeomCollPtr
get_nodes(gaiaGeomCollPtr in)32434 get_nodes (gaiaGeomCollPtr in)
32435 {
32436 /* extracts all Nodes (Linestring extermities) */
32437     int iv;
32438     double x;
32439     double y;
32440     double m;
32441     double z;
32442     gaiaLinestringPtr ln;
32443     gaiaGeomCollPtr out;
32444 
32445     if (in == NULL)
32446 	return NULL;
32447 
32448     if (in->DimensionModel == GAIA_XY_M)
32449 	out = gaiaAllocGeomCollXYM ();
32450     else if (in->DimensionModel == GAIA_XY_Z)
32451 	out = gaiaAllocGeomCollXYZ ();
32452     else if (in->DimensionModel == GAIA_XY_Z_M)
32453 	out = gaiaAllocGeomCollXYZM ();
32454     else
32455 	out = gaiaAllocGeomColl ();
32456     out->Srid = in->Srid;
32457 
32458     ln = in->FirstLinestring;
32459     while (ln)
32460       {
32461 	  /* saving the extreme points - Start */
32462 	  if (ln->DimensionModel == GAIA_XY_Z)
32463 	    {
32464 		gaiaGetPointXYZ (ln->Coords, 0, &x, &y, &z);
32465 		gaiaAddPointToGeomCollXYZ (out, x, y, z);
32466 	    }
32467 	  else if (ln->DimensionModel == GAIA_XY_M)
32468 	    {
32469 		gaiaGetPointXYM (ln->Coords, 0, &x, &y, &m);
32470 		gaiaAddPointToGeomCollXYM (out, x, y, m);
32471 	    }
32472 	  else if (ln->DimensionModel == GAIA_XY_Z_M)
32473 	    {
32474 		gaiaGetPointXYZM (ln->Coords, 0, &x, &y, &z, &m);
32475 		gaiaAddPointToGeomCollXYZM (out, x, y, z, m);
32476 	    }
32477 	  else
32478 	    {
32479 		gaiaGetPoint (ln->Coords, 0, &x, &y);
32480 		gaiaAddPointToGeomColl (out, x, y);
32481 	    }
32482 	  /* saving the extreme points - End */
32483 	  iv = ln->Points - 1;
32484 	  if (ln->DimensionModel == GAIA_XY_Z)
32485 	    {
32486 		gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
32487 		gaiaAddPointToGeomCollXYZ (out, x, y, z);
32488 	    }
32489 	  else if (ln->DimensionModel == GAIA_XY_M)
32490 	    {
32491 		gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
32492 		gaiaAddPointToGeomCollXYM (out, x, y, m);
32493 	    }
32494 	  else if (ln->DimensionModel == GAIA_XY_Z_M)
32495 	    {
32496 		gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
32497 		gaiaAddPointToGeomCollXYZM (out, x, y, z, m);
32498 	    }
32499 	  else
32500 	    {
32501 		gaiaGetPoint (ln->Coords, iv, &x, &y);
32502 		gaiaAddPointToGeomColl (out, x, y);
32503 	    }
32504 	  ln = ln->Next;
32505       }
32506 
32507     return out;
32508 }
32509 
32510 static int
point_is_defined(gaiaPointPtr in,gaiaGeomCollPtr geom)32511 point_is_defined (gaiaPointPtr in, gaiaGeomCollPtr geom)
32512 {
32513 /* checking if a Point is already defined */
32514     gaiaPointPtr pt = geom->FirstPoint;
32515     while (pt)
32516       {
32517 	  if (geom->DimensionModel == GAIA_XY_Z)
32518 	    {
32519 		if (pt->X == in->X && pt->Y == in->Y && pt->Z == in->Z)
32520 		    return 1;
32521 	    }
32522 	  else if (geom->DimensionModel == GAIA_XY_M)
32523 	    {
32524 		if (pt->X == in->X && pt->Y == in->Y && pt->M == in->M)
32525 		    return 1;
32526 	    }
32527 	  else if (geom->DimensionModel == GAIA_XY_Z_M)
32528 	    {
32529 		if (pt->X == in->X && pt->Y == in->Y && pt->Z == in->Z
32530 		    && pt->M == in->M)
32531 		    return 1;
32532 	    }
32533 	  else
32534 	    {
32535 		if (pt->X == in->X && pt->Y == in->Y)
32536 		    return 1;
32537 	    }
32538 	  pt = pt->Next;
32539       }
32540     return 0;
32541 }
32542 
32543 static gaiaGeomCollPtr
get_self_intersections(gaiaGeomCollPtr in_old,gaiaGeomCollPtr in_new)32544 get_self_intersections (gaiaGeomCollPtr in_old, gaiaGeomCollPtr in_new)
32545 {
32546 /* extracting the self-intersection points */
32547     gaiaPointPtr pt;
32548     gaiaGeomCollPtr out;
32549 
32550     if (in_old->DimensionModel == GAIA_XY_M)
32551 	out = gaiaAllocGeomCollXYM ();
32552     else if (in_old->DimensionModel == GAIA_XY_Z)
32553 	out = gaiaAllocGeomCollXYZ ();
32554     else if (in_old->DimensionModel == GAIA_XY_Z_M)
32555 	out = gaiaAllocGeomCollXYZM ();
32556     else
32557 	out = gaiaAllocGeomColl ();
32558     out->Srid = in_old->Srid;
32559 
32560     pt = in_new->FirstPoint;
32561     while (pt)
32562       {
32563 	  int ok1 = point_is_defined (pt, in_old);
32564 	  int ok2 = point_is_defined (pt, out);
32565 	  if (!ok1 && !ok2)
32566 	    {
32567 		/* inserting a Point into the result collection */
32568 		if (out->DimensionModel == GAIA_XY_Z)
32569 		    gaiaAddPointToGeomCollXYZ (out, pt->X, pt->Y, pt->Z);
32570 		else if (out->DimensionModel == GAIA_XY_M)
32571 		    gaiaAddPointToGeomCollXYM (out, pt->X, pt->Y, pt->M);
32572 		else if (out->DimensionModel == GAIA_XY_Z_M)
32573 		    gaiaAddPointToGeomCollXYZM (out, pt->X, pt->Y, pt->Z,
32574 						pt->M);
32575 		else
32576 		    gaiaAddPointToGeomColl (out, pt->X, pt->Y);
32577 	    }
32578 	  pt = pt->Next;
32579       }
32580 
32581     if (out->FirstPoint == NULL)
32582       {
32583 	  /* no self-intersections were found */
32584 	  gaiaFreeGeomColl (out);
32585 	  return NULL;
32586       }
32587 
32588     return out;
32589 }
32590 
32591 static void
fnct_SelfIntersections(sqlite3_context * context,int argc,sqlite3_value ** argv)32592 fnct_SelfIntersections (sqlite3_context * context, int argc,
32593 			sqlite3_value ** argv)
32594 {
32595 /* SQL function:
32596 / ST_SelfIntersections(BLOBencoded linestring(s))
32597 /
32598 / Returns a MultiPoint Geometry representing any self-intersection
32599 / found within the input geometry [linestring(s)]
32600 / NULL is returned for invalid arguments, or when no self-intersections
32601 / were found
32602 */
32603     unsigned char *p_blob;
32604     int n_bytes;
32605     gaiaGeomCollPtr input;
32606     gaiaGeomCollPtr noded;
32607     gaiaGeomCollPtr result;
32608     gaiaGeomCollPtr nodes_in;
32609     gaiaGeomCollPtr nodes_out;
32610     int gpkg_amphibious = 0;
32611     int gpkg_mode = 0;
32612     int tiny_point = 0;
32613     struct splite_internal_cache *cache = sqlite3_user_data (context);
32614     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32615     if (cache != NULL)
32616       {
32617 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32618 	  gpkg_mode = cache->gpkg_mode;
32619 	  tiny_point = cache->tinyPointEnabled;
32620       }
32621     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32622       {
32623 	  sqlite3_result_null (context);
32624 	  return;
32625       }
32626 
32627 /* retrieving the input geometry */
32628     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32629     n_bytes = sqlite3_value_bytes (argv[0]);
32630     input =
32631 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32632 				     gpkg_amphibious);
32633     if (input == NULL)
32634       {
32635 	  sqlite3_result_null (context);
32636 	  return;
32637       }
32638 
32639 /* checking the input (Linestrings only) */
32640     if (!check_all_linestrings (input))
32641       {
32642 	  gaiaFreeGeomColl (input);
32643 	  sqlite3_result_null (context);
32644 	  return;
32645       }
32646 /* extracting all input nodes */
32647     nodes_in = get_nodes (input);
32648 
32649     noded = gaiaNodeLines (cache, input);
32650     gaiaFreeGeomColl (input);
32651 /* extracting all output nodes */
32652     nodes_out = get_nodes (noded);
32653     gaiaFreeGeomColl (noded);
32654 
32655 /* identifying the intersections */
32656     result = get_self_intersections (nodes_in, nodes_out);
32657     gaiaFreeGeomColl (nodes_in);
32658     gaiaFreeGeomColl (nodes_out);
32659     if (result != NULL)
32660       {
32661 	  result->DeclaredType = GAIA_MULTIPOINT;
32662 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_blob, &n_bytes, gpkg_mode,
32663 				      tiny_point);
32664 	  sqlite3_result_blob (context, p_blob, n_bytes, free);
32665 	  gaiaFreeGeomColl (result);
32666       }
32667     else
32668 	sqlite3_result_null (context);
32669 }
32670 
32671 static void
fnct_Subdivide(sqlite3_context * context,int argc,sqlite3_value ** argv)32672 fnct_Subdivide (sqlite3_context * context, int argc, sqlite3_value ** argv)
32673 {
32674 /* SQL function:
32675 / ST_Subdivide(BLOBencoded geom)
32676 /    or
32677 / ST_Subdivide(BLOBencoded geom, int max_vertices)
32678 /
32679 / Divides geometry into parts until a part can be represented using no
32680 / more than max_vertices.
32681 / NULL is returned for invalid arguments
32682 */
32683     unsigned char *p_blob;
32684     int n_bytes;
32685     gaiaGeomCollPtr input;
32686     gaiaGeomCollPtr result;
32687     int max_vertices = 128;
32688     int gpkg_amphibious = 0;
32689     int gpkg_mode = 0;
32690     int tiny_point = 0;
32691     struct splite_internal_cache *cache = sqlite3_user_data (context);
32692     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32693     if (cache != NULL)
32694       {
32695 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32696 	  gpkg_mode = cache->gpkg_mode;
32697 	  tiny_point = cache->tinyPointEnabled;
32698       }
32699     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
32700       {
32701 	  sqlite3_result_null (context);
32702 	  return;
32703       }
32704     if (argc >= 2)
32705       {
32706 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
32707 	    {
32708 		sqlite3_result_null (context);
32709 		return;
32710 	    }
32711 	  max_vertices = sqlite3_value_int (argv[1]);
32712       }
32713 
32714 /* retrieving the input geometry */
32715     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32716     n_bytes = sqlite3_value_bytes (argv[0]);
32717     input =
32718 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
32719 				     gpkg_amphibious);
32720     if (input == NULL)
32721       {
32722 	  sqlite3_result_null (context);
32723 	  goto end;
32724       }
32725 
32726 /* subdiving the input geometry */
32727     result = gaiaSubdivide (cache, input, max_vertices);
32728     if (result != NULL)
32729       {
32730 	  gaiaToSpatiaLiteBlobWkbEx2 (result, &p_blob, &n_bytes, gpkg_mode,
32731 				      tiny_point);
32732 	  sqlite3_result_blob (context, p_blob, n_bytes, free);
32733 	  gaiaFreeGeomColl (result);
32734       }
32735     else
32736 	sqlite3_result_null (context);
32737   end:
32738     gaiaFreeGeomColl (input);
32739 }
32740 
32741 #endif /* end RTTOPO support */
32742 
32743 
32744 static void
fnct_Cutter(sqlite3_context * context,int argc,sqlite3_value ** argv)32745 fnct_Cutter (sqlite3_context * context, int argc, sqlite3_value ** argv)
32746 {
32747 /* SQL function:
32748 / ST_Cutter(TEXT in_db_prefix, TEXT input_table, TEXT input_geom,
32749 /              TEXT blade_db_prefix, TEXT blade_table, TEXT blade_geom,
32750 /              TEXT output_table)
32751 / ST_Cutter(TEXT in_db_prefix, TEXT input_table, TEXT input_geom,
32752 /              TEXT blade_db_prefix, TEXT blade_table, TEXT blade_geom,
32753 /              TEXT output_table, INT transaction)
32754 / ST_Cutter(TEXT in_db_prefix, TEXT input_table, TEXT input_geom,
32755 /              TEXT blade_db_prefix, TEXT blade_table, TEXT blade_geom,
32756 /              TEXT output_table, INT transaction, INT ram_temp_store)
32757 /
32758 / the "input" table-geometry is expected to be declared as POINT,
32759 / LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING or MULTIPOLYGON
32760 / and can be of any 2D or 3D dimension
32761 /
32762 / the "blade" table-geometry is expected to be declared as POLYGON
32763 / or MULTIPOLYGON, and will always be casted to a pure(X,Y) dimension
32764 /
32765 / the "output" table *must* not exists, and will be automatically
32766 / created within the MAIN database.
32767 /
32768 / in_db_prefix and/or blade_db_prefix can eventually be NULL, and
32769 / in this case the MAIN db will be assumed
32770 /
32771 / input_geom and/or blade_geom can eventually be NULL, and in this
32772 / case the geometry column name will be automatically determined.
32773 / anyway when a table defines two or more Geometries declaring a
32774 / NULL geometry name will cause a failure.
32775 /
32776 ///////////////////////////////////////////////////////////////////
32777 /
32778 / will precisely cut the input dataset against polygonal blade(s)
32779 / and will consequently create and populate an output dataset
32780 /
32781 /
32782 / returns 1 on success
32783 / 0 on failure, -1 on invalid arguments
32784 */
32785     sqlite3 *sqlite;
32786     int ret = 0;
32787     const char *in_db_prefix = NULL;
32788     const char *input_table = NULL;
32789     const char *input_geom = NULL;
32790     const char *blade_db_prefix = NULL;
32791     const char *blade_table = NULL;
32792     const char *blade_geom = NULL;
32793     const char *output_table = NULL;
32794     int transaction = 0;
32795     int ram_tmp_store = 0;
32796     char **message = NULL;
32797     struct splite_internal_cache *cache = sqlite3_user_data (context);
32798     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32799     if (cache != NULL)
32800 	message = &(cache->cutterMessage);
32801 
32802     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
32803 	;
32804     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
32805 	in_db_prefix = (const char *) sqlite3_value_text (argv[0]);
32806     else
32807       {
32808 	  sqlite3_result_int (context, -1);
32809 	  return;
32810       }
32811     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
32812 	input_table = (const char *) sqlite3_value_text (argv[1]);
32813     else
32814       {
32815 	  sqlite3_result_int (context, -1);
32816 	  return;
32817       }
32818     if (sqlite3_value_type (argv[2]) == SQLITE_NULL)
32819 	;
32820     else if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
32821 	input_geom = (const char *) sqlite3_value_text (argv[2]);
32822     else
32823       {
32824 	  sqlite3_result_int (context, -1);
32825 	  return;
32826       }
32827     if (sqlite3_value_type (argv[3]) == SQLITE_NULL)
32828 	;
32829     else if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
32830 	blade_db_prefix = (const char *) sqlite3_value_text (argv[3]);
32831     else
32832       {
32833 	  sqlite3_result_int (context, -1);
32834 	  return;
32835       }
32836     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
32837 	blade_table = (const char *) sqlite3_value_text (argv[4]);
32838     else
32839       {
32840 	  sqlite3_result_int (context, -1);
32841 	  return;
32842       }
32843     if (sqlite3_value_type (argv[5]) == SQLITE_NULL)
32844 	;
32845     else if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
32846 	blade_geom = (const char *) sqlite3_value_text (argv[5]);
32847     else
32848       {
32849 	  sqlite3_result_int (context, -1);
32850 	  return;
32851       }
32852     if (sqlite3_value_type (argv[6]) == SQLITE_TEXT)
32853 	output_table = (const char *) sqlite3_value_text (argv[6]);
32854     else
32855       {
32856 	  sqlite3_result_int (context, -1);
32857 	  return;
32858       }
32859     if (argc >= 8)
32860       {
32861 	  if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
32862 	      transaction = sqlite3_value_int (argv[7]);
32863 	  else
32864 	    {
32865 		sqlite3_result_int (context, -1);
32866 		return;
32867 	    }
32868       }
32869     if (argc == 9)
32870       {
32871 	  if (sqlite3_value_type (argv[8]) == SQLITE_INTEGER)
32872 	      ram_tmp_store = sqlite3_value_int (argv[8]);
32873 	  else
32874 	    {
32875 		sqlite3_result_int (context, -1);
32876 		return;
32877 	    }
32878       }
32879 
32880     sqlite = sqlite3_context_db_handle (context);
32881     ret =
32882 	gaiaCutter (sqlite, cache, in_db_prefix, input_table, input_geom,
32883 		    blade_db_prefix, blade_table, blade_geom, output_table,
32884 		    transaction, ram_tmp_store, message);
32885 
32886     sqlite3_result_int (context, ret);
32887 }
32888 
32889 static void
fnct_GetCutterMessage(sqlite3_context * context,int argc,sqlite3_value ** argv)32890 fnct_GetCutterMessage (sqlite3_context * context, int argc,
32891 		       sqlite3_value ** argv)
32892 {
32893 /* SQL function:
32894 / GetCutterMessage( void )
32895 /
32896 / will return the last diagnostic message from Cutter
32897 / NULL if there is no pending message
32898 */
32899     char *message = NULL;
32900     struct splite_internal_cache *cache = sqlite3_user_data (context);
32901     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32902     if (cache != NULL)
32903 	message = cache->cutterMessage;
32904 
32905     if (message == NULL)
32906 	sqlite3_result_null (context);
32907     else
32908 	sqlite3_result_text (context, message, strlen (message), SQLITE_STATIC);
32909 }
32910 
32911 static void
fnct_DrapeLine(sqlite3_context * context,int argc,sqlite3_value ** argv)32912 fnct_DrapeLine (sqlite3_context * context, int argc, sqlite3_value ** argv)
32913 {
32914 /* SQL function:
32915 / ST_DrapeLine( line-1 Linestring, line-2 Linestring )
32916 /    or
32917 / ST_DrapeLine( line-1 Linestring, line-2 Linestring, tolerance Double )
32918 /
32919 / will drape line-1 over line-2 returning a new linestring
32920 / NULL on invalid arguments or if any error is encountered
32921 */
32922     unsigned char *blob;
32923     int bytes;
32924     gaiaGeomCollPtr geom1 = NULL;
32925     gaiaGeomCollPtr geom2 = NULL;
32926     gaiaGeomCollPtr geom3 = NULL;
32927     double tolerance = 0.0;
32928     sqlite3 *db_handle = sqlite3_context_db_handle (context);
32929     int gpkg_amphibious = 0;
32930     int gpkg_mode = 0;
32931     struct splite_internal_cache *cache = sqlite3_user_data (context);
32932     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
32933     if (cache != NULL)
32934       {
32935 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
32936 	  gpkg_mode = cache->gpkg_mode;
32937       }
32938 
32939     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
32940       {
32941 	  blob = (unsigned char *) sqlite3_value_blob (argv[0]);
32942 	  bytes = sqlite3_value_bytes (argv[0]);
32943 	  geom1 =
32944 	      gaiaFromSpatiaLiteBlobWkbEx (blob, bytes, gpkg_mode,
32945 					   gpkg_amphibious);
32946       }
32947     else
32948 	goto error;
32949     if (sqlite3_value_type (argv[1]) == SQLITE_BLOB)
32950       {
32951 	  blob = (unsigned char *) sqlite3_value_blob (argv[1]);
32952 	  bytes = sqlite3_value_bytes (argv[1]);
32953 	  geom2 =
32954 	      gaiaFromSpatiaLiteBlobWkbEx (blob, bytes, gpkg_mode,
32955 					   gpkg_amphibious);
32956       }
32957     else
32958 	goto error;
32959     if (argc >= 3)
32960       {
32961 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
32962 	    {
32963 		int val = sqlite3_value_int (argv[2]);
32964 		tolerance = val;
32965 	    }
32966 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
32967 	      tolerance = sqlite3_value_double (argv[2]);
32968 	  else
32969 	      goto error;
32970       }
32971 
32972 /* checking the arguments for validity */
32973     if (geom1 == NULL || geom2 == NULL)
32974 	goto error;
32975     if (geom1->Srid != geom2->Srid)
32976 	goto error;
32977     if (geom1->DimensionModel == GAIA_XY || geom1->DimensionModel == GAIA_XY_M)
32978 	;
32979     else
32980 	goto error;
32981     if (geom2->DimensionModel == GAIA_XY_Z
32982 	|| geom2->DimensionModel == GAIA_XY_Z_M)
32983 	;
32984     else
32985 	goto error;
32986     if (!gaia_do_check_linestring (geom1))
32987 	goto error;
32988     if (!gaia_do_check_linestring (geom2))
32989 	goto error;
32990     if (tolerance < 0.0)
32991 	goto error;
32992 
32993     geom3 = gaiaDrapeLine (db_handle, geom1, geom2, tolerance);
32994     if (geom3 == NULL)
32995 	goto error;
32996 
32997     gaiaToSpatiaLiteBlobWkb (geom3, &blob, &bytes);
32998     sqlite3_result_blob (context, blob, bytes, free);
32999     gaiaFreeGeomColl (geom1);
33000     gaiaFreeGeomColl (geom2);
33001     gaiaFreeGeomColl (geom3);
33002     return;
33003 
33004   error:
33005     if (geom1 != NULL)
33006 	gaiaFreeGeomColl (geom1);
33007     if (geom2 != NULL)
33008 	gaiaFreeGeomColl (geom2);
33009     if (geom3 != NULL)
33010 	gaiaFreeGeomColl (geom3);
33011     sqlite3_result_null (context);
33012 }
33013 
33014 static void
fnct_DrapeLineExceptions(sqlite3_context * context,int argc,sqlite3_value ** argv)33015 fnct_DrapeLineExceptions (sqlite3_context * context, int argc,
33016 			  sqlite3_value ** argv)
33017 {
33018 /* SQL function:
33019 / ST_DrapeLineExceptions( line-1 Linestring, line-2 Linestring )
33020 /    or
33021 / ST_DrapeLineExceptions( line-1 Linestring, line-2 Linestring,
33022 /                         tolerance  Double )
33023 /    or
33024 / ST_DrapeLineExceptions( line-1 Linestring, line-2 Linestring,
33025 /                         tolerance  Double, interpolated Integer )
33026 /
33027 / will drape line-1 over line-2 returning a MultiPoint containing
33028 / all Points from line-1 not correctly draped.
33029 / NULL on invalid arguments or if any error is encountered or
33030 / if all Point are correctly draped.
33031 */
33032     unsigned char *blob;
33033     int bytes;
33034     gaiaGeomCollPtr geom1 = NULL;
33035     gaiaGeomCollPtr geom2 = NULL;
33036     gaiaGeomCollPtr geom3 = NULL;
33037     double tolerance = 0.0;
33038     int interpolated = 1;
33039     sqlite3 *db_handle = sqlite3_context_db_handle (context);
33040     int gpkg_amphibious = 0;
33041     int gpkg_mode = 0;
33042     struct splite_internal_cache *cache = sqlite3_user_data (context);
33043     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33044     if (cache != NULL)
33045       {
33046 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
33047 	  gpkg_mode = cache->gpkg_mode;
33048       }
33049 
33050     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
33051       {
33052 	  blob = (unsigned char *) sqlite3_value_blob (argv[0]);
33053 	  bytes = sqlite3_value_bytes (argv[0]);
33054 	  geom1 =
33055 	      gaiaFromSpatiaLiteBlobWkbEx (blob, bytes, gpkg_mode,
33056 					   gpkg_amphibious);
33057       }
33058     else
33059 	goto error;
33060     if (sqlite3_value_type (argv[1]) == SQLITE_BLOB)
33061       {
33062 	  blob = (unsigned char *) sqlite3_value_blob (argv[1]);
33063 	  bytes = sqlite3_value_bytes (argv[1]);
33064 	  geom2 =
33065 	      gaiaFromSpatiaLiteBlobWkbEx (blob, bytes, gpkg_mode,
33066 					   gpkg_amphibious);
33067       }
33068     else
33069 	goto error;
33070     if (argc >= 3)
33071       {
33072 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
33073 	    {
33074 		int val = sqlite3_value_int (argv[2]);
33075 		tolerance = val;
33076 	    }
33077 	  else if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
33078 	      tolerance = sqlite3_value_double (argv[2]);
33079 	  else
33080 	      goto error;
33081       }
33082     if (argc >= 4)
33083       {
33084 	  if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
33085 	      interpolated = sqlite3_value_int (argv[3]);
33086 	  else
33087 	      goto error;
33088       }
33089 
33090 /* checking the arguments for validity */
33091     if (geom1 == NULL || geom2 == NULL)
33092 	goto error;
33093     if (geom1->Srid != geom2->Srid)
33094 	goto error;
33095     if (geom1->DimensionModel == GAIA_XY || geom1->DimensionModel == GAIA_XY_M)
33096 	;
33097     else
33098 	goto error;
33099     if (geom2->DimensionModel == GAIA_XY_Z
33100 	|| geom2->DimensionModel == GAIA_XY_Z_M)
33101 	;
33102     else
33103 	goto error;
33104     if (!gaia_do_check_linestring (geom1))
33105 	goto error;
33106     if (!gaia_do_check_linestring (geom2))
33107 	goto error;
33108     if (tolerance < 0.0)
33109 	goto error;
33110 
33111     geom3 =
33112 	gaiaDrapeLineExceptions (db_handle, geom1, geom2, tolerance,
33113 				 interpolated);
33114     if (geom3 == NULL)
33115 	goto error;
33116 
33117     gaiaToSpatiaLiteBlobWkb (geom3, &blob, &bytes);
33118     sqlite3_result_blob (context, blob, bytes, free);
33119     gaiaFreeGeomColl (geom1);
33120     gaiaFreeGeomColl (geom2);
33121     gaiaFreeGeomColl (geom3);
33122     return;
33123 
33124   error:
33125     if (geom1 != NULL)
33126 	gaiaFreeGeomColl (geom1);
33127     if (geom2 != NULL)
33128 	gaiaFreeGeomColl (geom2);
33129     if (geom3 != NULL)
33130 	gaiaFreeGeomColl (geom3);
33131     sqlite3_result_null (context);
33132 }
33133 
33134 #endif /* end including GEOS */
33135 
33136 static int
text2double(const unsigned char * str,double * val)33137 text2double (const unsigned char *str, double *val)
33138 {
33139 /* checks for a valid number, eventually returning a DOUBLE */
33140     int err = 0;
33141     int sign = 0;
33142     int decimal = 0;
33143     int exp = 0;
33144     int expsign = 0;
33145     const unsigned char *p = str;
33146     while (*p != '\0')
33147       {
33148 	  switch (*p)
33149 	    {
33150 	    case '0':
33151 	    case '1':
33152 	    case '2':
33153 	    case '3':
33154 	    case '4':
33155 	    case '5':
33156 	    case '6':
33157 	    case '7':
33158 	    case '8':
33159 	    case '9':
33160 		break;
33161 	    case '-':
33162 	    case '+':
33163 		if (!exp)
33164 		    sign++;
33165 		else
33166 		    expsign++;
33167 		break;
33168 	    case '.':
33169 		decimal++;
33170 		break;
33171 	    case 'e':
33172 	    case 'E':
33173 		exp++;
33174 		break;
33175 	    default:
33176 		err = 1;
33177 		break;
33178 	    };
33179 	  p++;
33180       }
33181     if (sign > 1 || expsign > 1 || decimal > 1 || (exp == 0 && expsign > 0))
33182 	err = 1;
33183     if (err)
33184 	return 0;
33185     *val = atof ((const char *) str);
33186     return 1;
33187 }
33188 
33189 static int
is_integer(const unsigned char * value)33190 is_integer (const unsigned char *value)
33191 {
33192 /* checking if a text string is an Integer Number */
33193     const unsigned char *p = value;
33194     while (*p != '\0')
33195       {
33196 	  /* skipping any leading whitespace */
33197 	  if (*p == ' ')
33198 	    {
33199 		p++;
33200 		continue;
33201 	    }
33202 	  break;
33203       }
33204     if (*p == '\0')
33205 	return 0;
33206     if (*p == '-' || *p == '+')
33207 	p++;			/* skipping an eventual sign */
33208     if (*p == '\0')
33209 	return 0;
33210     while (*p != '\0')
33211       {
33212 	  if (*p >= '0' && *p <= '9')
33213 	    {
33214 		p++;
33215 		continue;
33216 	    }
33217 	  return 0;
33218       }
33219     return 1;
33220 }
33221 
33222 static int
is_decimal_number(const unsigned char * value)33223 is_decimal_number (const unsigned char *value)
33224 {
33225 /* checking if a text string is a Decimal Number */
33226     const unsigned char *p = value;
33227     while (*p != '\0')
33228       {
33229 	  /* skipping any leading whitespace */
33230 	  if (*p == ' ')
33231 	    {
33232 		p++;
33233 		continue;
33234 	    }
33235 	  break;
33236       }
33237     if (*p == '\0')
33238 	return 0;
33239     if (*p == '-' || *p == '+')
33240 	p++;			/* skipping an eventual sign */
33241     if (*p == '\0')
33242 	return 0;
33243     while (*p != '\0')
33244       {
33245 	  /* integer part */
33246 	  if (*p == '.')
33247 	    {
33248 		p++;
33249 		break;
33250 	    }
33251 	  if (*p >= '0' && *p <= '9')
33252 	    {
33253 		p++;
33254 		continue;
33255 	    }
33256 	  return 0;
33257       }
33258     if (*p == '\0')
33259 	return 0;
33260     while (*p != '\0')
33261       {
33262 	  /* fractional part */
33263 	  if (*p == 'e' || *p == 'E')
33264 	      break;
33265 	  if (*p >= '0' && *p <= '9')
33266 	    {
33267 		p++;
33268 		continue;
33269 	    }
33270 	  return 0;
33271       }
33272     if (*p == '\0')
33273 	return 1;		/* valid decimal number without exponent */
33274 
33275 /* checking the exponent */
33276     if (*p == 'e' || *p == 'E')
33277 	p++;			/* skipping an eventual exponent marker */
33278     else
33279 	return 0;
33280     if (*p == '\0')
33281 	return 0;
33282     if (*p == '-' || *p == '+')
33283 	p++;			/* skipping an eventual exponent sign */
33284     if (*p == '\0')
33285 	return 0;
33286     while (*p != '\0')
33287       {
33288 	  /* exponent */
33289 	  if (*p >= '0' && *p <= '9')
33290 	    {
33291 		p++;
33292 		continue;
33293 	    }
33294 	  return 0;
33295       }
33296     return 1;
33297 }
33298 
33299 static void
fnct_IsInteger(sqlite3_context * context,int argc,sqlite3_value ** argv)33300 fnct_IsInteger (sqlite3_context * context, int argc, sqlite3_value ** argv)
33301 {
33302 /* SQL function:
33303 / IsInteger(TEXT value)
33304 /
33305 / returns 1 if yes, 0 if  not and -1 on any non-text value
33306 */
33307     int ret;
33308     const unsigned char *value;
33309     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33310     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33311 	value = sqlite3_value_text (argv[0]);
33312     else
33313       {
33314 	  sqlite3_result_int (context, -1);
33315 	  return;
33316       }
33317     ret = is_integer (value);
33318     sqlite3_result_int (context, ret);
33319 }
33320 
33321 static void
fnct_IsDecimalNumber(sqlite3_context * context,int argc,sqlite3_value ** argv)33322 fnct_IsDecimalNumber (sqlite3_context * context, int argc,
33323 		      sqlite3_value ** argv)
33324 {
33325 /* SQL function:
33326 / IsDecimalNumber(TEXT value)
33327 /
33328 / returns 1 if yes, 0 if  not and -1 on any non-text value
33329 */
33330     int ret;
33331     const unsigned char *value;
33332     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33333     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33334 	value = sqlite3_value_text (argv[0]);
33335     else
33336       {
33337 	  sqlite3_result_int (context, -1);
33338 	  return;
33339       }
33340     ret = is_decimal_number (value);
33341     sqlite3_result_int (context, ret);
33342 }
33343 
33344 static void
fnct_IsNumber(sqlite3_context * context,int argc,sqlite3_value ** argv)33345 fnct_IsNumber (sqlite3_context * context, int argc, sqlite3_value ** argv)
33346 {
33347 /* SQL function:
33348 / IsNumber(TEXT value)
33349 /
33350 / returns 1 if yes, 0 if  not and -1 on any non-text value
33351 */
33352     int ret;
33353     const unsigned char *value;
33354     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33355     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33356 	value = sqlite3_value_text (argv[0]);
33357     else
33358       {
33359 	  sqlite3_result_int (context, -1);
33360 	  return;
33361       }
33362     ret = is_integer (value);
33363     if (ret)
33364       {
33365 	  sqlite3_result_int (context, 1);
33366 	  return;
33367       }
33368     ret = is_decimal_number (value);
33369     sqlite3_result_int (context, ret);
33370 }
33371 
33372 static void
fnct_CastToInteger(sqlite3_context * context,int argc,sqlite3_value ** argv)33373 fnct_CastToInteger (sqlite3_context * context, int argc, sqlite3_value ** argv)
33374 {
33375 /* SQL function:
33376 / CastToInteger(generic value)
33377 /
33378 / returns an INTEGER value [if conversion is possible]
33379 / or NULL in any other case
33380 */
33381     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33382     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
33383       {
33384 	  sqlite3_int64 val = sqlite3_value_int64 (argv[0]);
33385 	  sqlite3_result_int64 (context, val);
33386 	  return;
33387       }
33388     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
33389       {
33390 	  sqlite3_int64 val;
33391 	  double dval = sqlite3_value_double (argv[0]);
33392 	  double diff = dval - floor (dval);
33393 	  val = (sqlite3_int64) sqlite3_value_double (argv[0]);
33394 	  if (diff >= 0.5)
33395 	      val++;
33396 	  sqlite3_result_int64 (context, val);
33397 	  return;
33398       }
33399     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33400       {
33401 	  const unsigned char *txt = sqlite3_value_text (argv[0]);
33402 	  double dval;
33403 	  if (text2double (txt, &dval))
33404 	    {
33405 		sqlite3_int64 val;
33406 		double dval = sqlite3_value_double (argv[0]);
33407 		double diff = dval - floor (dval);
33408 		val = (sqlite3_int64) sqlite3_value_double (argv[0]);
33409 		if (diff >= 0.5)
33410 		    val++;
33411 		sqlite3_result_int64 (context, val);
33412 		return;
33413 	    }
33414       }
33415     sqlite3_result_null (context);
33416 }
33417 
33418 static void
fnct_CastToDouble(sqlite3_context * context,int argc,sqlite3_value ** argv)33419 fnct_CastToDouble (sqlite3_context * context, int argc, sqlite3_value ** argv)
33420 {
33421 /* SQL function:
33422 / CastToDouble(generic value)
33423 /
33424 / returns a DOUBLE value [if conversion is possible]
33425 / or NULL in any other case
33426 */
33427     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33428     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
33429       {
33430 	  double val = (double) sqlite3_value_int64 (argv[0]);
33431 	  sqlite3_result_double (context, val);
33432 	  return;
33433       }
33434     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
33435       {
33436 	  double val = sqlite3_value_double (argv[0]);
33437 	  sqlite3_result_double (context, val);
33438 	  return;
33439       }
33440     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33441       {
33442 	  const unsigned char *txt = sqlite3_value_text (argv[0]);
33443 	  double val;
33444 	  if (text2double (txt, &val))
33445 	    {
33446 		sqlite3_result_double (context, val);
33447 		return;
33448 	    }
33449       }
33450     sqlite3_result_null (context);
33451 }
33452 
33453 static void
fnct_CastToText(sqlite3_context * context,int argc,sqlite3_value ** argv)33454 fnct_CastToText (sqlite3_context * context, int argc, sqlite3_value ** argv)
33455 {
33456 /* SQL function:
33457 / CastToText(generic value)
33458 / CastToText(generic value, Integer left-aligned-length)
33459 /
33460 / returns a TEXT value [if conversion is possible]
33461 / or NULL in any other case
33462 */
33463     char *txt;
33464     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33465     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
33466       {
33467 	  char format[32];
33468 	  const char *fmt = "%lld";
33469 	  sqlite3_int64 val;
33470 	  if (argc == 2)
33471 	    {
33472 		int length;
33473 		if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
33474 		  {
33475 		      sqlite3_result_null (context);
33476 		      return;
33477 		  }
33478 		length = sqlite3_value_int (argv[1]);
33479 		if (length > 0)
33480 		  {
33481 		      sprintf (format, "%%0%dlld", length);
33482 		      fmt = format;
33483 		  }
33484 	    }
33485 	  val = sqlite3_value_int64 (argv[0]);
33486 	  txt = sqlite3_mprintf (fmt, val);
33487 	  sqlite3_result_text (context, txt, strlen (txt), sqlite3_free);
33488 	  return;
33489       }
33490     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
33491       {
33492 	  int i;
33493 	  int len;
33494 	  double val = sqlite3_value_double (argv[0]);
33495 	  char format[32];
33496 	  const char *fmt = "%1.18f";
33497 	  if (argc == 2)
33498 	    {
33499 		int length;
33500 		if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
33501 		  {
33502 		      sqlite3_result_null (context);
33503 		      return;
33504 		  }
33505 		length = sqlite3_value_int (argv[1]);
33506 		if (length > 0)
33507 		  {
33508 		      sprintf (format, "%%0%d.18f", length + 19);
33509 		      fmt = format;
33510 		  }
33511 	    }
33512 	  txt = sqlite3_mprintf (fmt, val);
33513 	  len = strlen (txt);
33514 	  for (i = len - 1; i > 0; i--)
33515 	    {
33516 		/* suppressing meaningless trailing zeroes */
33517 		if (txt[i] >= '1' && txt[i] <= '9')
33518 		    break;
33519 		if (txt[i] == '.')
33520 		  {
33521 		      txt[i + 1] = '0';
33522 		      break;
33523 		  }
33524 		if (txt[i] == '0')
33525 		    txt[i] = '\0';
33526 	    }
33527 	  sqlite3_result_text (context, txt, strlen (txt), sqlite3_free);
33528 	  return;
33529       }
33530     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33531       {
33532 	  int n_bytes;
33533 	  txt = (char *) sqlite3_value_text (argv[0]);
33534 	  n_bytes = sqlite3_value_bytes (argv[0]);
33535 	  sqlite3_result_text (context, txt, n_bytes, SQLITE_TRANSIENT);
33536 	  return;
33537       }
33538     sqlite3_result_null (context);
33539 }
33540 
33541 static int
parseHexByte(unsigned char hi,unsigned char lo,unsigned char * val)33542 parseHexByte (unsigned char hi, unsigned char lo, unsigned char *val)
33543 {
33544 /* converting a byte for its Hex representation */
33545     unsigned char x;
33546     switch (hi)
33547       {
33548       case '0':
33549 	  x = 0;
33550 	  break;
33551       case '1':
33552 	  x = 16;
33553 	  break;
33554       case '2':
33555 	  x = 16 * 2;
33556 	  break;
33557       case '3':
33558 	  x = 16 * 3;
33559 	  break;
33560       case '4':
33561 	  x = 16 * 4;
33562 	  break;
33563       case '5':
33564 	  x = 16 * 5;
33565 	  break;
33566       case '6':
33567 	  x = 16 * 6;
33568 	  break;
33569       case '7':
33570 	  x = 16 * 7;
33571 	  break;
33572       case '8':
33573 	  x = 16 * 8;
33574 	  break;
33575       case '9':
33576 	  x = 16 * 9;
33577 	  break;
33578       case 'a':
33579       case 'A':
33580 	  x = 16 * 10;
33581 	  break;
33582       case 'b':
33583       case 'B':
33584 	  x = 16 * 11;
33585 	  break;
33586       case 'c':
33587       case 'C':
33588 	  x = 16 * 12;
33589 	  break;
33590       case 'd':
33591       case 'D':
33592 	  x = 16 * 13;
33593 	  break;
33594       case 'e':
33595       case 'E':
33596 	  x = 16 * 14;
33597 	  break;
33598       case 'f':
33599       case 'F':
33600 	  x = 16 * 15;
33601 	  break;
33602       default:
33603 	  return 0;
33604       };
33605     switch (lo)
33606       {
33607       case '0':
33608 	  x += 0;
33609 	  break;
33610       case '1':
33611 	  x += 1;
33612 	  break;
33613       case '2':
33614 	  x += 2;
33615 	  break;
33616       case '3':
33617 	  x += 3;
33618 	  break;
33619       case '4':
33620 	  x += 4;
33621 	  break;
33622       case '5':
33623 	  x += 5;
33624 	  break;
33625       case '6':
33626 	  x += 6;
33627 	  break;
33628       case '7':
33629 	  x += 7;
33630 	  break;
33631       case '8':
33632 	  x += 8;
33633 	  break;
33634       case '9':
33635 	  x += 9;
33636 	  break;
33637       case 'a':
33638       case 'A':
33639 	  x += 10;
33640 	  break;
33641       case 'b':
33642       case 'B':
33643 	  x += 11;
33644 	  break;
33645       case 'c':
33646       case 'C':
33647 	  x += 12;
33648 	  break;
33649       case 'd':
33650       case 'D':
33651 	  x += 13;
33652 	  break;
33653       case 'e':
33654       case 'E':
33655 	  x += 14;
33656 	  break;
33657       case 'f':
33658       case 'F':
33659 	  x += 15;
33660 	  break;
33661       default:
33662 	  return 0;
33663       };
33664     *val = x;
33665     return 1;
33666 }
33667 
33668 static int
parseHexString(const unsigned char * in,int in_len,unsigned char ** out,int * out_len)33669 parseHexString (const unsigned char *in, int in_len, unsigned char **out,
33670 		int *out_len)
33671 {
33672 /* parsing an Hexadecimal string */
33673     unsigned char *buf;
33674     unsigned char *p_out;
33675     unsigned char byteval;
33676     int i;
33677     int len;
33678     *out = NULL;
33679     *out_len = 0;
33680     if (in == NULL)
33681 	return 0;
33682     len = in_len / 2;
33683     if (len * 2 != in_len)	/* # digits is an odd number */
33684 	return 0;
33685     buf = malloc (len);
33686     p_out = buf;
33687     for (i = 0; i < in_len; i += 2)
33688       {
33689 	  if (!parseHexByte (in[i], in[i + 1], &byteval))
33690 	      goto error;
33691 	  *p_out++ = byteval;
33692       }
33693     *out = buf;
33694     *out_len = len;
33695     return 1;
33696   error:
33697     free (buf);
33698     return 0;
33699 }
33700 
33701 static void
fnct_CastToBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)33702 fnct_CastToBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
33703 {
33704 /* SQL function:
33705 / CastToBlob(generic value)
33706 /   or
33707 / CastToBlob(generic value, boolen hex_input)
33708 /
33709 / returns a BLOB value [if conversion is possible]
33710 / or NULL in any other case
33711 */
33712     const unsigned char *p_blob;
33713     int n_bytes;
33714     int is_hex = 0;
33715     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33716     if (argc == 2)
33717       {
33718 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
33719 	    {
33720 		sqlite3_result_null (context);
33721 		return;
33722 	    }
33723 	  is_hex = sqlite3_value_int (argv[1]);
33724       }
33725     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
33726       {
33727 	  p_blob = sqlite3_value_blob (argv[0]);
33728 	  n_bytes = sqlite3_value_bytes (argv[0]);
33729 	  if (is_hex)
33730 	    {
33731 		/* attempting to convert Hexadecimal input */
33732 		unsigned char *blob;
33733 		int bytes;
33734 		if (!parseHexString (p_blob, n_bytes, &blob, &bytes))
33735 		  {
33736 		      sqlite3_result_null (context);
33737 		      return;
33738 		  }
33739 		sqlite3_result_blob (context, blob, bytes, free);
33740 		return;
33741 	    }
33742 	  sqlite3_result_blob (context, p_blob, n_bytes, SQLITE_TRANSIENT);
33743 	  return;
33744       }
33745     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33746       {
33747 	  p_blob = sqlite3_value_text (argv[0]);
33748 	  n_bytes = sqlite3_value_bytes (argv[0]);
33749 	  if (is_hex)
33750 	    {
33751 		/* attempting to convert Hexadecimal input */
33752 		unsigned char *blob;
33753 		int bytes;
33754 		if (!parseHexString (p_blob, n_bytes, &blob, &bytes))
33755 		  {
33756 		      sqlite3_result_null (context);
33757 		      return;
33758 		  }
33759 		sqlite3_result_blob (context, blob, bytes, free);
33760 		return;
33761 	    }
33762 	  sqlite3_result_blob (context, p_blob, n_bytes, SQLITE_TRANSIENT);
33763 	  return;
33764       }
33765     sqlite3_result_null (context);
33766 }
33767 
33768 static void
fnct_ForceAsNull(sqlite3_context * context,int argc,sqlite3_value ** argv)33769 fnct_ForceAsNull (sqlite3_context * context, int argc, sqlite3_value ** argv)
33770 {
33771 /* SQL function:
33772 / ForceAsNull(generic val1, generic val2)
33773 /
33774 / returns a NULL value if val1 and val2 are equal
33775 / (and exactly of the same type)
33776 / return val1 in any other case
33777 */
33778     int type1;
33779     int type2;
33780     const unsigned char *p_blob;
33781     int n_bytes;
33782     const unsigned char *p_blob2;
33783     int n_bytes2;
33784     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33785     type1 = sqlite3_value_type (argv[0]);
33786     type2 = sqlite3_value_type (argv[1]);
33787     if (type1 == type2)
33788       {
33789 	  switch (type1)
33790 	    {
33791 	    case SQLITE_INTEGER:
33792 		if (sqlite3_value_int64 (argv[0]) ==
33793 		    sqlite3_value_int64 (argv[1]))
33794 		  {
33795 		      sqlite3_result_null (context);
33796 		      return;
33797 		  }
33798 		break;
33799 	    case SQLITE_FLOAT:
33800 		if (sqlite3_value_double (argv[0]) ==
33801 		    sqlite3_value_double (argv[1]))
33802 		  {
33803 		      sqlite3_result_null (context);
33804 		      return;
33805 		  }
33806 		break;
33807 	    case SQLITE_TEXT:
33808 		p_blob = sqlite3_value_text (argv[0]);
33809 		n_bytes = sqlite3_value_bytes (argv[0]);
33810 		p_blob2 = sqlite3_value_text (argv[1]);
33811 		n_bytes2 = sqlite3_value_bytes (argv[1]);
33812 		if (n_bytes == n_bytes2)
33813 		  {
33814 		      if (strcasecmp
33815 			  ((const char *) p_blob, (const char *) p_blob2) == 0)
33816 			{
33817 			    sqlite3_result_null (context);
33818 			    return;
33819 			}
33820 		  }
33821 		break;
33822 	    case SQLITE_BLOB:
33823 		p_blob = sqlite3_value_blob (argv[0]);
33824 		n_bytes = sqlite3_value_bytes (argv[0]);
33825 		p_blob2 = sqlite3_value_blob (argv[1]);
33826 		n_bytes2 = sqlite3_value_bytes (argv[1]);
33827 		if (n_bytes == n_bytes2)
33828 		  {
33829 		      if (memcmp (p_blob, p_blob2, n_bytes) == 0)
33830 			{
33831 			    sqlite3_result_null (context);
33832 			    return;
33833 			}
33834 		  }
33835 		break;
33836 	    case SQLITE_NULL:
33837 		sqlite3_result_null (context);
33838 		return;
33839 	    };
33840       }
33841 /* returning the first argument */
33842     switch (type1)
33843       {
33844       case SQLITE_INTEGER:
33845 	  sqlite3_result_int64 (context, sqlite3_value_int64 (argv[0]));
33846 	  break;
33847       case SQLITE_FLOAT:
33848 	  sqlite3_result_double (context, sqlite3_value_double (argv[0]));
33849 	  break;
33850       case SQLITE_TEXT:
33851 	  p_blob = sqlite3_value_text (argv[0]);
33852 	  n_bytes = sqlite3_value_bytes (argv[0]);
33853 	  sqlite3_result_text (context, (const char *) p_blob, n_bytes,
33854 			       SQLITE_TRANSIENT);
33855 	  break;
33856       case SQLITE_BLOB:
33857 	  p_blob = sqlite3_value_blob (argv[0]);
33858 	  n_bytes = sqlite3_value_bytes (argv[0]);
33859 	  sqlite3_result_blob (context, p_blob, n_bytes, SQLITE_TRANSIENT);
33860 	  break;
33861       default:
33862 	  sqlite3_result_null (context);
33863 	  break;
33864       };
33865 }
33866 
33867 static void
fnct_CreateUUID(sqlite3_context * context,int argc,sqlite3_value ** argv)33868 fnct_CreateUUID (sqlite3_context * context, int argc, sqlite3_value ** argv)
33869 {
33870 /* SQL function:
33871 / CreateUUID()
33872 /
33873 / returns a TEXT value containing an UUID
33874 / [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx]
33875 */
33876     unsigned char rnd[16];
33877     char uuid[64];
33878     char *p = uuid;
33879     int i;
33880     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33881     sqlite3_randomness (16, rnd);
33882     for (i = 0; i < 16; i++)
33883       {
33884 	  if (i == 4 || i == 6 || i == 8 || i == 10)
33885 	      *p++ = '-';
33886 	  sprintf (p, "%02x", rnd[i]);
33887 	  p += 2;
33888       }
33889     *p = '\0';
33890     uuid[14] = '4';
33891     uuid[19] = '8';
33892     sqlite3_result_text (context, uuid, strlen (uuid), SQLITE_TRANSIENT);
33893 }
33894 
33895 static void
fnct_MD5Checksum(sqlite3_context * context,int argc,sqlite3_value ** argv)33896 fnct_MD5Checksum (sqlite3_context * context, int argc, sqlite3_value ** argv)
33897 {
33898 /* SQL function:
33899 / MD5Checksum(blob)
33900 /
33901 / returns a TEXT value containing an hex MD5 checksum
33902 / [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
33903 /      or
33904 / NULL on invalid arguments
33905 */
33906     void *md5;
33907     char *checksum;
33908     const unsigned char *blob;
33909     int blob_len;
33910     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33911 
33912     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
33913       {
33914 	  blob = sqlite3_value_blob (argv[0]);
33915 	  blob_len = sqlite3_value_bytes (argv[0]);
33916       }
33917     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33918       {
33919 	  blob = sqlite3_value_text (argv[0]);
33920 	  blob_len = sqlite3_value_bytes (argv[0]);
33921       }
33922     else
33923       {
33924 	  sqlite3_result_null (context);
33925 	  return;
33926       }
33927 /* creating an MD5 object */
33928     md5 = gaiaCreateMD5Checksum ();
33929 /* evaluating the BLOB */
33930     gaiaUpdateMD5Checksum (md5, blob, blob_len);
33931     checksum = gaiaFinalizeMD5Checksum (md5);
33932     gaiaFreeMD5Checksum (md5);
33933     if (checksum == NULL)
33934 	sqlite3_result_null (context);
33935     else
33936 	sqlite3_result_text (context, checksum, strlen (checksum), free);
33937 }
33938 
33939 static void
fnct_MD5TotalChecksum_step(sqlite3_context * context,int argc,sqlite3_value ** argv)33940 fnct_MD5TotalChecksum_step (sqlite3_context * context, int argc,
33941 			    sqlite3_value ** argv)
33942 {
33943 /* SQL function:
33944 / MD5TotalChecksum(BLOB)
33945 /
33946 / aggregate function - STEP
33947 /
33948 */
33949     void **p;
33950     void *md5;
33951     const unsigned char *blob;
33952     int blob_len;
33953     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
33954 
33955     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
33956       {
33957 	  blob = sqlite3_value_blob (argv[0]);
33958 	  blob_len = sqlite3_value_bytes (argv[0]);
33959       }
33960     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
33961       {
33962 	  blob = sqlite3_value_text (argv[0]);
33963 	  blob_len = sqlite3_value_bytes (argv[0]);
33964       }
33965     else
33966       {
33967 	  sqlite3_result_null (context);
33968 	  return;
33969       }
33970     p = sqlite3_aggregate_context (context, sizeof (void *));
33971     if (!(*p))
33972       {
33973 	  /* this is the first row - creating an MD5 object */
33974 	  md5 = gaiaCreateMD5Checksum ();
33975 	  gaiaUpdateMD5Checksum (md5, blob, blob_len);
33976 	  *p = md5;
33977       }
33978     else
33979       {
33980 	  /* subsequent rows */
33981 	  md5 = *p;
33982 	  gaiaUpdateMD5Checksum (md5, blob, blob_len);
33983       }
33984 }
33985 
33986 static void
fnct_MD5TotalChecksum_final(sqlite3_context * context)33987 fnct_MD5TotalChecksum_final (sqlite3_context * context)
33988 {
33989 /* SQL function:
33990 / MD5TotalChecksum(BLOB)
33991 /
33992 / aggregate function - FINAL
33993 /
33994 */
33995     void **p;
33996     void *md5;
33997     char *checksum;
33998     p = sqlite3_aggregate_context (context, 0);
33999     if (!(*p))
34000       {
34001 	  sqlite3_result_null (context);
34002 	  return;
34003       }
34004     md5 = *p;
34005     checksum = gaiaFinalizeMD5Checksum (md5);
34006     gaiaFreeMD5Checksum (md5);
34007     if (checksum == NULL)
34008 	sqlite3_result_null (context);
34009     else
34010 	sqlite3_result_text (context, checksum, strlen (checksum), free);
34011 }
34012 
34013 #if OMIT_ICONV == 0		/* ICONV is absolutely required */
34014 
34015 static void
fnct_ExportGeoJSON(sqlite3_context * context,int argc,sqlite3_value ** argv)34016 fnct_ExportGeoJSON (sqlite3_context * context, int argc, sqlite3_value ** argv)
34017 {
34018 /* SQL function:
34019 / ExportGeoJSON(TEXT table, TEXT geom_column, TEXT filename)
34020 / ExportGeoJSON(TEXT table, TEXT geom_column, TEXT filename,
34021 /               TEXT format)
34022 / ExportGeoJSON(TEXT table, TEXT geom_column, TEXT filename,
34023 /               TEXT format, INT precision)
34024 /
34025 / returns:
34026 / the number of exported rows
34027 / NULL on invalid arguments
34028 */
34029     int ret;
34030     char *table;
34031     char *geom_col;
34032     char *path;
34033     int format = 0;
34034     int precision = 8;
34035     char *fmt = NULL;
34036     int rows;
34037     sqlite3 *db_handle = sqlite3_context_db_handle (context);
34038     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34039     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
34040       {
34041 	  sqlite3_result_null (context);
34042 	  return;
34043       }
34044     table = (char *) sqlite3_value_text (argv[0]);
34045     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
34046       {
34047 	  sqlite3_result_null (context);
34048 	  return;
34049       }
34050     geom_col = (char *) sqlite3_value_text (argv[1]);
34051     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
34052       {
34053 	  sqlite3_result_null (context);
34054 	  return;
34055       }
34056     path = (char *) sqlite3_value_text (argv[2]);
34057     if (argc > 3)
34058       {
34059 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
34060 	    {
34061 		sqlite3_result_null (context);
34062 		return;
34063 	    }
34064 	  else
34065 	    {
34066 		fmt = (char *) sqlite3_value_text (argv[3]);
34067 		if (strcasecmp (fmt, "none") == 0)
34068 		    format = 0;
34069 		else if (strcasecmp (fmt, "MBR") == 0)
34070 		    format = 1;
34071 		else if (strcasecmp (fmt, "withShortCRS") == 0)
34072 		    format = 2;
34073 		else if (strcasecmp (fmt, "MBRwithShortCRS") == 0)
34074 		    format = 3;
34075 		else if (strcasecmp (fmt, "withLongCRS") == 0)
34076 		    format = 4;
34077 		else if (strcasecmp (fmt, "MBRwithLongCRS") == 0)
34078 		    format = 5;
34079 		else
34080 		  {
34081 		      sqlite3_result_null (context);
34082 		      return;
34083 		  }
34084 	    }
34085       }
34086     if (argc > 4)
34087       {
34088 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
34089 	    {
34090 		sqlite3_result_null (context);
34091 		return;
34092 	    }
34093 	  else
34094 	      precision = sqlite3_value_int (argv[4]);
34095       }
34096 
34097     ret =
34098 	dump_geojson_ex (db_handle, table, geom_col, path, precision, format,
34099 			 &rows);
34100 
34101     if (rows < 0 || !ret)
34102 	sqlite3_result_null (context);
34103     else
34104 	sqlite3_result_int (context, rows);
34105 }
34106 
34107 static void
fnct_ExportGeoJSON2(sqlite3_context * context,int argc,sqlite3_value ** argv)34108 fnct_ExportGeoJSON2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
34109 {
34110 /* SQL function:
34111 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename)
34112 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename,
34113 /                INT precision)
34114 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename,
34115 /                INT precision, INT lon_lat)
34116 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename,
34117 /                INT precision, INT lon_lat, INT M_coords)
34118 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename,
34119 /                INT precision, INT lon_lat, INT M_coords,
34120 /                INT indented)
34121 / ExportGeoJSON2(TEXT table, TEXT geom_column, TEXT filename,
34122 /                INT precision, INT lon_lat, INT M_coords,
34123 /                INT indented, TEXT colname_case)
34124 /
34125 / returns:
34126 / the number of exported rows
34127 / NULL on invalid arguments
34128 */
34129     int ret;
34130     char *table;
34131     char *geom_col;
34132     char *path;
34133     int precision = 8;
34134     int lon_lat = 1;
34135     int m_coords = 0;
34136     int indented = 1;
34137     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
34138     int rows;
34139     char *errmsg = NULL;
34140     sqlite3 *db_handle = sqlite3_context_db_handle (context);
34141     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34142     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
34143       {
34144 	  sqlite3_result_null (context);
34145 	  return;
34146       }
34147     table = (char *) sqlite3_value_text (argv[0]);
34148     if (sqlite3_value_type (argv[1]) == SQLITE_NULL)
34149 	geom_col = NULL;
34150     else
34151       {
34152 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
34153 	    {
34154 		sqlite3_result_null (context);
34155 		return;
34156 	    }
34157 	  geom_col = (char *) sqlite3_value_text (argv[1]);
34158       }
34159     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
34160       {
34161 	  sqlite3_result_null (context);
34162 	  return;
34163       }
34164     path = (char *) sqlite3_value_text (argv[2]);
34165     if (argc > 3)
34166       {
34167 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
34168 	    {
34169 		sqlite3_result_null (context);
34170 		return;
34171 	    }
34172 	  precision = sqlite3_value_int (argv[3]);
34173       }
34174     if (argc > 4)
34175       {
34176 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
34177 	    {
34178 		sqlite3_result_null (context);
34179 		return;
34180 	    }
34181 	  lon_lat = sqlite3_value_int (argv[4]);
34182       }
34183     if (argc > 5)
34184       {
34185 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
34186 	    {
34187 		sqlite3_result_null (context);
34188 		return;
34189 	    }
34190 	  m_coords = sqlite3_value_int (argv[5]);
34191       }
34192     if (argc > 6)
34193       {
34194 	  if (sqlite3_value_type (argv[6]) != SQLITE_INTEGER)
34195 	    {
34196 		sqlite3_result_null (context);
34197 		return;
34198 	    }
34199 	  indented = sqlite3_value_int (argv[6]);
34200       }
34201     if (argc > 7)
34202       {
34203 	  if (sqlite3_value_type (argv[7]) != SQLITE_TEXT)
34204 	    {
34205 		sqlite3_result_null (context);
34206 		return;
34207 	    }
34208 	  else
34209 	    {
34210 		const char *val = (char *) sqlite3_value_text (argv[7]);
34211 		if (strcasecmp (val, "UPPER") == 0
34212 		    || strcasecmp (val, "UPPERCASE") == 0)
34213 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
34214 		else if (strcasecmp (val, "SAME") == 0
34215 			 || strcasecmp (val, "SAMECASE") == 0)
34216 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
34217 		else
34218 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
34219 	    }
34220       }
34221 
34222     ret =
34223 	dump_geojson2 (db_handle, table, geom_col, path, precision, lon_lat,
34224 		       m_coords, indented, colname_case, &rows, &errmsg);
34225     if (errmsg != NULL)
34226       {
34227 	  spatialite_e ("%s", errmsg);
34228 	  sqlite3_free (errmsg);
34229       }
34230 
34231     if (rows < 0 || !ret)
34232 	sqlite3_result_null (context);
34233     else
34234 	sqlite3_result_int (context, rows);
34235 }
34236 
34237 static void
fnct_ImportGeoJSON(sqlite3_context * context,int argc,sqlite3_value ** argv)34238 fnct_ImportGeoJSON (sqlite3_context * context, int argc, sqlite3_value ** argv)
34239 {
34240 /* SQL function:
34241 / ImportGeoJSON(TEXT filename, TEXT table)
34242 / ImportGeoJSON(TEXT filename, TEXT table, TEXT geom_column)
34243 / ImportGeoJSON(TEXT filename, TEXT table, TEXT geom_column,
34244 /               INT spatial_index)
34245 / ImportGeoJSON(TEXT filename, TEXT table, TEXT geom_column,
34246 /               INT spatial_index, INT srid)
34247 / ImportGeoJSON(TEXT filename, TEXT table, TEXT geom_column,
34248 /               INT spatial_index, INT srid, TEXT colname_case)
34249 /
34250 / returns:
34251 / the number of imported rows
34252 / NULL on invalid arguments
34253 */
34254     int ret;
34255     char *table;
34256     char *geom_col = "geometry";
34257     char *path;
34258     int spatial_index = 0;
34259     int srid = 4326;
34260     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
34261     int rows;
34262     char *errmsg = NULL;
34263     sqlite3 *db_handle = sqlite3_context_db_handle (context);
34264     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34265     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
34266       {
34267 	  sqlite3_result_null (context);
34268 	  return;
34269       }
34270     path = (char *) sqlite3_value_text (argv[0]);
34271     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
34272       {
34273 	  sqlite3_result_null (context);
34274 	  return;
34275       }
34276     table = (char *) sqlite3_value_text (argv[1]);
34277     if (argc > 2)
34278       {
34279 	  if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
34280 	    {
34281 		sqlite3_result_null (context);
34282 		return;
34283 	    }
34284 	  geom_col = (char *) sqlite3_value_text (argv[2]);
34285       }
34286     if (argc > 3)
34287       {
34288 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
34289 	    {
34290 		sqlite3_result_null (context);
34291 		return;
34292 	    }
34293 	  spatial_index = sqlite3_value_int (argv[3]);
34294       }
34295     if (argc > 4)
34296       {
34297 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
34298 	    {
34299 		sqlite3_result_null (context);
34300 		return;
34301 	    }
34302 	  srid = sqlite3_value_int (argv[4]);
34303       }
34304     if (argc > 5)
34305       {
34306 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
34307 	    {
34308 		sqlite3_result_null (context);
34309 		return;
34310 	    }
34311 	  else
34312 	    {
34313 		const char *val = (char *) sqlite3_value_text (argv[5]);
34314 		if (strcasecmp (val, "UPPER") == 0
34315 		    || strcasecmp (val, "UPPERCASE") == 0)
34316 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
34317 		else if (strcasecmp (val, "SAME") == 0
34318 			 || strcasecmp (val, "SAMECASE") == 0)
34319 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
34320 		else
34321 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
34322 	    }
34323       }
34324 
34325     ret =
34326 	load_geojson (db_handle, path, table, geom_col, spatial_index, srid,
34327 		      colname_case, &rows, &errmsg);
34328     if (errmsg != NULL)
34329       {
34330 	  spatialite_e ("%s", errmsg);
34331 	  sqlite3_free (errmsg);
34332       }
34333 
34334     if (rows < 0 || !ret)
34335 	sqlite3_result_null (context);
34336     else
34337 	sqlite3_result_int (context, rows);
34338 }
34339 
34340 static void
fnct_EncodeURL(sqlite3_context * context,int argc,sqlite3_value ** argv)34341 fnct_EncodeURL (sqlite3_context * context, int argc, sqlite3_value ** argv)
34342 {
34343 /* SQL function:
34344 / EncodeURL(text url)
34345 /   or
34346 / EncodeURL(text url, text out_charset)
34347 /
34348 / returns a TEXT value containing the percent-encoded URL
34349 /      or
34350 / NULL on invalid arguments
34351 */
34352     const char *url;
34353     const char *out_charset = "UTF-8";
34354     char *encoded;
34355     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34356 
34357     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34358 	url = (const char *) sqlite3_value_text (argv[0]);
34359     else
34360       {
34361 	  sqlite3_result_null (context);
34362 	  return;
34363       }
34364     if (argc > 1)
34365       {
34366 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
34367 	      out_charset = (const char *) sqlite3_value_text (argv[1]);
34368 	  else
34369 	    {
34370 		sqlite3_result_null (context);
34371 		return;
34372 	    }
34373       }
34374 /* encoding the URL */
34375     encoded = gaiaEncodeURL (url, out_charset);
34376     if (encoded == NULL)
34377 	sqlite3_result_null (context);
34378     else
34379 	sqlite3_result_text (context, encoded, strlen (encoded), free);
34380 }
34381 
34382 static void
fnct_DecodeURL(sqlite3_context * context,int argc,sqlite3_value ** argv)34383 fnct_DecodeURL (sqlite3_context * context, int argc, sqlite3_value ** argv)
34384 {
34385 /* SQL function:
34386 / DecodeURL(text)
34387 /   or
34388 / DecodeURL(text url, text in_charset)
34389 /
34390 / returns a TEXT value containing the URL cleaned from percent-encoding
34391 /      or
34392 / NULL on invalid arguments
34393 */
34394     char *url;
34395     const char *encoded;
34396     const char *in_charset = "UTF-8";
34397     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34398 
34399     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34400 	encoded = (const char *) sqlite3_value_text (argv[0]);
34401     else
34402       {
34403 	  sqlite3_result_null (context);
34404 	  return;
34405       }
34406     if (argc > 1)
34407       {
34408 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
34409 	      in_charset = (const char *) sqlite3_value_text (argv[1]);
34410 	  else
34411 	    {
34412 		sqlite3_result_null (context);
34413 		return;
34414 	    }
34415       }
34416 /* decoding the URL */
34417     url = gaiaDecodeURL (encoded, in_charset);
34418     if (url == NULL)
34419 	sqlite3_result_null (context);
34420     else
34421 	sqlite3_result_text (context, url, strlen (url), free);
34422 }
34423 
34424 #ifdef ENABLE_MINIZIP		/* only id MINIZIP is enabled */
34425 
34426 static void
fnct_Zipfile_NumSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)34427 fnct_Zipfile_NumSHP (sqlite3_context * context, int argc, sqlite3_value ** argv)
34428 {
34429 /* SQL function:
34430 / Zipfile_NumSHP(zip_path TEXT)
34431 /
34432 / return the total number of Shapefiles contained within a given Zipfile
34433 / 0 if not Shapefile exists
34434 / or NULL on error or invalid arguments
34435 */
34436     const char *zip_path;
34437     int count;
34438     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34439     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34440 	zip_path = (const char *) sqlite3_value_text (argv[0]);
34441     else
34442       {
34443 	  sqlite3_result_null (context);
34444 	  return;
34445       }
34446 /* searching for Shapefiles */
34447     if (!gaiaZipfileNumSHP (zip_path, &count))
34448       {
34449 	  sqlite3_result_null (context);
34450 	  return;
34451       }
34452     sqlite3_result_int (context, count);
34453 }
34454 
34455 static void
fnct_Zipfile_ShpN(sqlite3_context * context,int argc,sqlite3_value ** argv)34456 fnct_Zipfile_ShpN (sqlite3_context * context, int argc, sqlite3_value ** argv)
34457 {
34458 /* SQL function:
34459 / Zipfile_ShpN(zip_path TEXT, idx INTEGER)
34460 /
34461 / return the name of the Nth Shapefile from within a Zipfile
34462 / or NULL on error or invalid arguments
34463 */
34464     const char *zip_path;
34465     int idx;
34466     char *basename;
34467     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34468     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34469 	zip_path = (const char *) sqlite3_value_text (argv[0]);
34470     else
34471       {
34472 	  sqlite3_result_null (context);
34473 	  return;
34474       }
34475     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
34476 	idx = sqlite3_value_int (argv[1]);
34477     else
34478       {
34479 	  sqlite3_result_null (context);
34480 	  return;
34481       }
34482 /* searching the Nth Shapefile */
34483     basename = gaiaZipfileShpN (zip_path, idx);
34484     if (basename == NULL)
34485       {
34486 	  sqlite3_result_null (context);
34487 	  return;
34488       }
34489     sqlite3_result_text (context, basename, strlen (basename), free);
34490 }
34491 
34492 static void
fnct_Zipfile_NumDBF(sqlite3_context * context,int argc,sqlite3_value ** argv)34493 fnct_Zipfile_NumDBF (sqlite3_context * context, int argc, sqlite3_value ** argv)
34494 {
34495 /* SQL function:
34496 / Zipfile_NumDBF(zip_path TEXT)
34497 /
34498 / return the total number of DBF files contained within a given Zipfile
34499 / 0 if not DBF file exists
34500 / or NULL on error or invalid arguments
34501 */
34502     const char *zip_path;
34503     int count;
34504     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34505     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34506 	zip_path = (const char *) sqlite3_value_text (argv[0]);
34507     else
34508       {
34509 	  sqlite3_result_null (context);
34510 	  return;
34511       }
34512 /* searching for DBF files */
34513     if (!gaiaZipfileNumDBF (zip_path, &count))
34514       {
34515 	  sqlite3_result_null (context);
34516 	  return;
34517       }
34518     sqlite3_result_int (context, count);
34519 }
34520 
34521 static void
fnct_Zipfile_DbfN(sqlite3_context * context,int argc,sqlite3_value ** argv)34522 fnct_Zipfile_DbfN (sqlite3_context * context, int argc, sqlite3_value ** argv)
34523 {
34524 /* SQL function:
34525 / Zipfile_DbfN(zip_path TEXT, idx INTEGER)
34526 /
34527 / return the name of the Nth DBF file from within a Zipfile
34528 / or NULL on error or invalid arguments
34529 */
34530     const char *zip_path;
34531     int idx;
34532     char *filename;
34533     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34534     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34535 	zip_path = (const char *) sqlite3_value_text (argv[0]);
34536     else
34537       {
34538 	  sqlite3_result_null (context);
34539 	  return;
34540       }
34541     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
34542 	idx = sqlite3_value_int (argv[1]);
34543     else
34544       {
34545 	  sqlite3_result_null (context);
34546 	  return;
34547       }
34548 /* searching the Nth DBF file */
34549     filename = gaiaZipfileDbfN (zip_path, idx);
34550     if (filename == NULL)
34551       {
34552 	  sqlite3_result_null (context);
34553 	  return;
34554       }
34555     sqlite3_result_text (context, filename, strlen (filename), free);
34556 }
34557 
34558 #endif /* end MINIZIP */
34559 
34560 #endif /* ICONV enabled/disabled */
34561 
34562 static void
fnct_DirNameFromPath(sqlite3_context * context,int argc,sqlite3_value ** argv)34563 fnct_DirNameFromPath (sqlite3_context * context, int argc,
34564 		      sqlite3_value ** argv)
34565 {
34566 /* SQL function:
34567 / DirNameFromPath(text)
34568 /
34569 / returns a TEXT value containing the Directory Name from a Path
34570 /      or
34571 / NULL on invalid arguments
34572 */
34573     char *dir;
34574     const char *path;
34575     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34576 
34577     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34578 	path = (const char *) sqlite3_value_text (argv[0]);
34579     else
34580       {
34581 	  sqlite3_result_null (context);
34582 	  return;
34583       }
34584 /* breaking the Path */
34585     dir = gaiaDirNameFromPath (path);
34586     if (dir == NULL)
34587 	sqlite3_result_null (context);
34588     else
34589 	sqlite3_result_text (context, dir, strlen (dir), free);
34590 }
34591 
34592 static void
fnct_FullFileNameFromPath(sqlite3_context * context,int argc,sqlite3_value ** argv)34593 fnct_FullFileNameFromPath (sqlite3_context * context, int argc,
34594 			   sqlite3_value ** argv)
34595 {
34596 /* SQL function:
34597 / FullFileNameFromPath(text)
34598 /
34599 / returns a TEXT value containing the Full FileName (including extension)
34600 / from a Path
34601 /      or
34602 / NULL on invalid arguments
34603 */
34604     char *name;
34605     const char *path;
34606     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34607 
34608     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34609 	path = (const char *) sqlite3_value_text (argv[0]);
34610     else
34611       {
34612 	  sqlite3_result_null (context);
34613 	  return;
34614       }
34615 /* breaking the Path */
34616     name = gaiaFullFileNameFromPath (path);
34617     if (name == NULL)
34618 	sqlite3_result_null (context);
34619     else
34620 	sqlite3_result_text (context, name, strlen (name), free);
34621 }
34622 
34623 static void
fnct_FileNameFromPath(sqlite3_context * context,int argc,sqlite3_value ** argv)34624 fnct_FileNameFromPath (sqlite3_context * context, int argc,
34625 		       sqlite3_value ** argv)
34626 {
34627 /* SQL function:
34628 / FileNameFromPath(text)
34629 /
34630 / returns a TEXT value containing the FileName (excluding extension)
34631 / from a Path
34632 /      or
34633 / NULL on invalid arguments
34634 */
34635     char *name;
34636     const char *path;
34637     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34638 
34639     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34640 	path = (const char *) sqlite3_value_text (argv[0]);
34641     else
34642       {
34643 	  sqlite3_result_null (context);
34644 	  return;
34645       }
34646 /* breaking the Path */
34647     name = gaiaFileNameFromPath (path);
34648     if (name == NULL)
34649 	sqlite3_result_null (context);
34650     else
34651 	sqlite3_result_text (context, name, strlen (name), free);
34652 }
34653 
34654 static void
fnct_FileExtFromPath(sqlite3_context * context,int argc,sqlite3_value ** argv)34655 fnct_FileExtFromPath (sqlite3_context * context, int argc,
34656 		      sqlite3_value ** argv)
34657 {
34658 /* SQL function:
34659 / FileExtFromPath(text)
34660 /
34661 / returns a TEXT value containing the Extension (if any) from a Path
34662 /      or
34663 / NULL on invalid arguments
34664 */
34665     char *ext;
34666     const char *path;
34667     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34668 
34669     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34670 	path = (const char *) sqlite3_value_text (argv[0]);
34671     else
34672       {
34673 	  sqlite3_result_null (context);
34674 	  return;
34675       }
34676 /* breaking the Path */
34677     ext = gaiaFileExtFromPath (path);
34678     if (ext == NULL)
34679 	sqlite3_result_null (context);
34680     else
34681 	sqlite3_result_text (context, ext, strlen (ext), free);
34682 }
34683 
34684 static void
fnct_RemoveExtraSpaces(sqlite3_context * context,int argc,sqlite3_value ** argv)34685 fnct_RemoveExtraSpaces (sqlite3_context * context, int argc,
34686 			sqlite3_value ** argv)
34687 {
34688 /* SQL function:
34689 / RemoveExtraSpaces(TEXT string)
34690 /
34691 / returns a TEXT value containing no repeated whitespaces
34692 /      or
34693 / NULL on invalid arguments
34694 */
34695     const char *dirty;
34696     char *clean;
34697     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34698 
34699     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34700 	dirty = (const char *) sqlite3_value_text (argv[0]);
34701     else
34702       {
34703 	  sqlite3_result_null (context);
34704 	  return;
34705       }
34706 /* removing whitespaces from the string */
34707     clean = gaiaRemoveExtraSpaces (dirty);
34708     if (clean == NULL)
34709 	sqlite3_result_null (context);
34710     else
34711 	sqlite3_result_text (context, clean, strlen (clean), free);
34712 }
34713 
34714 static void
fnct_make_string_list_step(sqlite3_context * context,int argc,sqlite3_value ** argv)34715 fnct_make_string_list_step (sqlite3_context * context, int argc,
34716 			    sqlite3_value ** argv)
34717 {
34718 /* SQL function:
34719 / MakeStringList(X)
34720 / MakeStringList(X, separator)
34721 /
34722 / aggregate function - STEP
34723 /
34724 */
34725     struct string_list_str *p;
34726     char buf[1024];
34727     const char *str = buf;
34728     char separator = ',';
34729     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34730     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
34731 	str = (const char *) sqlite3_value_text (argv[0]);
34732     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34733 #if defined(_WIN32) && !defined(__MINGW32__)
34734 	sprintf (buf, "%I64d", sqlite3_value_int64 (argv[0]));
34735 #else
34736 	sprintf (buf, "%lld", sqlite3_value_int64 (argv[0]));
34737 #endif
34738     else
34739 	strcpy (buf, "ILLEGAL_VALUE");
34740     if (argc >= 2)
34741       {
34742 	  if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
34743 	    {
34744 		const char *sep = (const char *) sqlite3_value_text (argv[1]);
34745 		separator = *sep;
34746 	    }
34747 	  else
34748 	      return;
34749       }
34750     p = sqlite3_aggregate_context (context, sizeof (struct string_list_str));
34751     if (p->separator == '\0' && p->string == NULL)
34752       {
34753 	  /* first item */
34754 	  p->separator = separator;
34755 	  if (separator == '\0')
34756 	      separator = ',';
34757 	  p->string = sqlite3_mprintf ("%s", str);
34758       }
34759     else
34760       {
34761 	  char *oldstr = p->string;
34762 	  p->string = sqlite3_mprintf ("%s%c%s", oldstr, p->separator, str);
34763 	  sqlite3_free (oldstr);
34764       }
34765 }
34766 
34767 static void
fnct_make_string_list_final(sqlite3_context * context)34768 fnct_make_string_list_final (sqlite3_context * context)
34769 {
34770 /* SQL function:
34771 / MakeStringList(X)
34772 / MakeStringList(X, separator)
34773 / aggregate function -  FINAL
34774 /
34775 */
34776     struct string_list_str *p = sqlite3_aggregate_context (context, 0);
34777     if (!p)
34778       {
34779 	  sqlite3_result_null (context);
34780 	  return;
34781       }
34782     sqlite3_result_text (context, p->string, -1, sqlite3_free);
34783 }
34784 
34785 
34786 #ifndef OMIT_MATHSQL		/* supporting SQL math functions */
34787 
34788 static int
testInvalidFP(double x)34789 testInvalidFP (double x)
34790 {
34791 /* testing if this one is an invalid Floating Point */
34792 #ifdef _WIN32
34793     if (_fpclass (x) == _FPCLASS_NN || _fpclass (x) == _FPCLASS_PN ||
34794 	_fpclass (x) == _FPCLASS_NZ || _fpclass (x) == _FPCLASS_PZ)
34795 	;
34796     else
34797 	return 1;
34798 #else
34799     if (fpclassify (x) == FP_NORMAL || fpclassify (x) == FP_ZERO)
34800 	;
34801     else
34802 	return 1;
34803 #endif
34804     return 0;
34805 }
34806 
34807 static void
fnct_math_acos(sqlite3_context * context,int argc,sqlite3_value ** argv)34808 fnct_math_acos (sqlite3_context * context, int argc, sqlite3_value ** argv)
34809 {
34810 /* SQL function:
34811 / acos(double X)
34812 /
34813 / Returns the arc cosine of X, that is, the value whose cosine is X
34814 / or NULL if any error is encountered
34815 */
34816     int int_value;
34817     double x;
34818     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34819     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34820       {
34821 	  x = acos (sqlite3_value_double (argv[0]));
34822 	  if (testInvalidFP (x))
34823 	      sqlite3_result_null (context);
34824 	  else
34825 	      sqlite3_result_double (context, x);
34826       }
34827     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34828       {
34829 	  int_value = sqlite3_value_int (argv[0]);
34830 	  x = int_value;
34831 	  x = acos (x);
34832 	  if (testInvalidFP (x))
34833 	      sqlite3_result_null (context);
34834 	  else
34835 	      sqlite3_result_double (context, x);
34836       }
34837     else
34838 	sqlite3_result_null (context);
34839 }
34840 
34841 static void
fnct_math_asin(sqlite3_context * context,int argc,sqlite3_value ** argv)34842 fnct_math_asin (sqlite3_context * context, int argc, sqlite3_value ** argv)
34843 {
34844 /* SQL function:
34845 / asin(double X)
34846 /
34847 / Returns the arc sine of X, that is, the value whose sine is X
34848 / or NULL if any error is encountered
34849 */
34850     int int_value;
34851     double x;
34852     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34853     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34854       {
34855 	  x = asin (sqlite3_value_double (argv[0]));
34856 	  if (testInvalidFP (x))
34857 	      sqlite3_result_null (context);
34858 	  else
34859 	      sqlite3_result_double (context, x);
34860       }
34861     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34862       {
34863 	  int_value = sqlite3_value_int (argv[0]);
34864 	  x = int_value;
34865 	  x = asin (x);
34866 	  if (testInvalidFP (x))
34867 	      sqlite3_result_null (context);
34868 	  else
34869 	      sqlite3_result_double (context, x);
34870       }
34871     else
34872 	sqlite3_result_null (context);
34873 }
34874 
34875 static void
fnct_math_atan(sqlite3_context * context,int argc,sqlite3_value ** argv)34876 fnct_math_atan (sqlite3_context * context, int argc, sqlite3_value ** argv)
34877 {
34878 /* SQL function:
34879 / atan(double X)
34880 /
34881 / Returns the arc tangent of X, that is, the value whose tangent is X
34882 / or NULL if any error is encountered
34883 */
34884     int int_value;
34885     double x;
34886     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34887     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34888       {
34889 	  x = atan (sqlite3_value_double (argv[0]));
34890 	  sqlite3_result_double (context, x);
34891       }
34892     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34893       {
34894 	  int_value = sqlite3_value_int (argv[0]);
34895 	  x = int_value;
34896 	  x = atan (x);
34897 	  sqlite3_result_double (context, x);
34898       }
34899     else
34900 	sqlite3_result_null (context);
34901 }
34902 
34903 static void
fnct_math_atan2(sqlite3_context * context,int argc,sqlite3_value ** argv)34904 fnct_math_atan2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
34905 {
34906 /* SQL function:
34907 / atan2(double Y, double X)
34908 /
34909 / Returns  the principal value of the arc tangent of Y/X, using
34910 / the signs of the two arguments to determine the quadrant of
34911 / the result.
34912 / or NULL if any error is encountered
34913 */
34914     int int_value;
34915     double x = 0.0;
34916     double y = 0.0;
34917     double t;
34918     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34919     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34920 	y = sqlite3_value_double (argv[0]);
34921     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34922       {
34923 	  int_value = sqlite3_value_int (argv[0]);
34924 	  y = int_value;
34925       }
34926     else
34927       {
34928 	  sqlite3_result_null (context);
34929 	  return;
34930       }
34931     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
34932 	x = sqlite3_value_double (argv[1]);
34933     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
34934       {
34935 	  int_value = sqlite3_value_int (argv[1]);
34936 	  x = int_value;
34937       }
34938     else
34939       {
34940 	  sqlite3_result_null (context);
34941 	  return;
34942       }
34943     t = atan2 (y, x);
34944     sqlite3_result_double (context, t);
34945 }
34946 
34947 static void
fnct_math_ceil(sqlite3_context * context,int argc,sqlite3_value ** argv)34948 fnct_math_ceil (sqlite3_context * context, int argc, sqlite3_value ** argv)
34949 {
34950 /* SQL function:
34951 / ceil(double X)
34952 /
34953 / Returns the smallest integer value not less than X
34954 / or NULL if any error is encountered
34955 */
34956     int int_value;
34957     double x;
34958     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34959     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34960       {
34961 	  x = ceil (sqlite3_value_double (argv[0]));
34962 	  sqlite3_result_double (context, x);
34963       }
34964     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34965       {
34966 	  int_value = sqlite3_value_int (argv[0]);
34967 	  x = int_value;
34968 	  x = ceil (x);
34969 	  sqlite3_result_double (context, x);
34970       }
34971     else
34972 	sqlite3_result_null (context);
34973 }
34974 
34975 static void
fnct_math_cos(sqlite3_context * context,int argc,sqlite3_value ** argv)34976 fnct_math_cos (sqlite3_context * context, int argc, sqlite3_value ** argv)
34977 {
34978 /* SQL function:
34979 / cos(double X)
34980 /
34981 / Returns the cosine of X, where X is given in radians
34982 / or NULL if any error is encountered
34983 */
34984     int int_value;
34985     double x;
34986     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
34987     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
34988       {
34989 	  x = cos (sqlite3_value_double (argv[0]));
34990 	  sqlite3_result_double (context, x);
34991       }
34992     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
34993       {
34994 	  int_value = sqlite3_value_int (argv[0]);
34995 	  x = int_value;
34996 	  x = cos (x);
34997 	  sqlite3_result_double (context, x);
34998       }
34999     else
35000 	sqlite3_result_null (context);
35001 }
35002 
35003 static void
fnct_math_cot(sqlite3_context * context,int argc,sqlite3_value ** argv)35004 fnct_math_cot (sqlite3_context * context, int argc, sqlite3_value ** argv)
35005 {
35006 /* SQL function:
35007 / cot(double X)
35008 /
35009 / Returns the cotangent of X
35010 / or NULL if any error is encountered
35011 */
35012     int int_value;
35013     double x;
35014     double tang;
35015     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35016     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35017 	x = sqlite3_value_double (argv[0]);
35018     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35019       {
35020 	  int_value = sqlite3_value_int (argv[0]);
35021 	  x = int_value;
35022       }
35023     else
35024       {
35025 	  sqlite3_result_null (context);
35026 	  return;
35027       }
35028     tang = tan (x);
35029     if (tang == 0.0)
35030       {
35031 	  sqlite3_result_null (context);
35032 	  return;
35033       }
35034     x = 1.0 / tang;
35035     sqlite3_result_double (context, x);
35036 }
35037 
35038 static void
fnct_math_degrees(sqlite3_context * context,int argc,sqlite3_value ** argv)35039 fnct_math_degrees (sqlite3_context * context, int argc, sqlite3_value ** argv)
35040 {
35041 /* SQL function:
35042 / degrees(double X)
35043 /
35044 / Returns the argument X, converted from radians to degrees
35045 / or NULL if any error is encountered
35046 */
35047     int int_value;
35048     double x;
35049     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35050     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35051 	x = sqlite3_value_double (argv[0]);
35052     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35053       {
35054 	  int_value = sqlite3_value_int (argv[0]);
35055 	  x = int_value;
35056       }
35057     else
35058       {
35059 	  sqlite3_result_null (context);
35060 	  return;
35061       }
35062     x = x * 57.29577951308232;
35063     sqlite3_result_double (context, x);
35064 }
35065 
35066 static void
fnct_math_exp(sqlite3_context * context,int argc,sqlite3_value ** argv)35067 fnct_math_exp (sqlite3_context * context, int argc, sqlite3_value ** argv)
35068 {
35069 /* SQL function:
35070 / exp(double X)
35071 /
35072 / Returns the value of e (the base of natural logarithms) raised to the power of X
35073 / or NULL if any error is encountered
35074 */
35075     int int_value;
35076     double x;
35077     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35078     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35079       {
35080 	  x = exp (sqlite3_value_double (argv[0]));
35081 	  sqlite3_result_double (context, x);
35082       }
35083     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35084       {
35085 	  int_value = sqlite3_value_int (argv[0]);
35086 	  x = int_value;
35087 	  x = exp (x);
35088 	  sqlite3_result_double (context, x);
35089       }
35090     else
35091 	sqlite3_result_null (context);
35092 }
35093 
35094 static void
fnct_math_floor(sqlite3_context * context,int argc,sqlite3_value ** argv)35095 fnct_math_floor (sqlite3_context * context, int argc, sqlite3_value ** argv)
35096 {
35097 /* SQL function:
35098 / floor(double X)
35099 /
35100 / Returns the largest integer value not greater than X
35101 / or NULL if any error is encountered
35102 */
35103     int int_value;
35104     double x;
35105     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35106     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35107       {
35108 	  x = floor (sqlite3_value_double (argv[0]));
35109 	  sqlite3_result_double (context, x);
35110       }
35111     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35112       {
35113 	  int_value = sqlite3_value_int (argv[0]);
35114 	  x = int_value;
35115 	  x = floor (x);
35116 	  sqlite3_result_double (context, x);
35117       }
35118     else
35119 	sqlite3_result_null (context);
35120 }
35121 
35122 static void
fnct_math_logn(sqlite3_context * context,int argc,sqlite3_value ** argv)35123 fnct_math_logn (sqlite3_context * context, int argc, sqlite3_value ** argv)
35124 {
35125 /* SQL function:
35126 / log(double X)
35127 /
35128 / Returns the natural logarithm of X; that is, the base-e logarithm of X
35129 / or NULL if any error is encountered
35130 */
35131     int int_value;
35132     double x;
35133     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35134     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35135       {
35136 	  x = log (sqlite3_value_double (argv[0]));
35137 	  if (testInvalidFP (x))
35138 	      sqlite3_result_null (context);
35139 	  else
35140 	      sqlite3_result_double (context, x);
35141       }
35142     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35143       {
35144 	  int_value = sqlite3_value_int (argv[0]);
35145 	  x = int_value;
35146 	  x = log (x);
35147 	  if (testInvalidFP (x))
35148 	      sqlite3_result_null (context);
35149 	  else
35150 	      sqlite3_result_double (context, x);
35151       }
35152     else
35153 	sqlite3_result_null (context);
35154 }
35155 
35156 static void
fnct_math_logn2(sqlite3_context * context,int argc,sqlite3_value ** argv)35157 fnct_math_logn2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
35158 {
35159 /* SQL function:
35160 / log(double X, double B)
35161 /
35162 / Returns the logarithm of X to the base B
35163 / or NULL if any error is encountered
35164 */
35165     int int_value;
35166     double x = 0.0;
35167     double b = 1.0;
35168     double log1;
35169     double log2;
35170     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35171     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35172 	x = sqlite3_value_double (argv[0]);
35173     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35174       {
35175 	  int_value = sqlite3_value_int (argv[0]);
35176 	  x = int_value;
35177       }
35178     else
35179       {
35180 	  sqlite3_result_null (context);
35181 	  return;
35182       }
35183     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
35184 	b = sqlite3_value_double (argv[1]);
35185     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
35186       {
35187 	  int_value = sqlite3_value_int (argv[1]);
35188 	  b = int_value;
35189       }
35190     else
35191       {
35192 	  sqlite3_result_null (context);
35193 	  return;
35194       }
35195     if (x <= 0.0 || b <= 1.0)
35196       {
35197 	  sqlite3_result_null (context);
35198 	  return;
35199       }
35200     log1 = log (x);
35201     if (testInvalidFP (log1))
35202       {
35203 	  sqlite3_result_null (context);
35204 	  return;
35205       }
35206     log2 = log (b);
35207     if (testInvalidFP (log2))
35208       {
35209 	  sqlite3_result_null (context);
35210 	  return;
35211       }
35212     sqlite3_result_double (context, log1 / log2);
35213 }
35214 
35215 static void
fnct_math_log_2(sqlite3_context * context,int argc,sqlite3_value ** argv)35216 fnct_math_log_2 (sqlite3_context * context, int argc, sqlite3_value ** argv)
35217 {
35218 /* SQL function:
35219 / log2(double X)
35220 /
35221 / Returns the base-2 logarithm of X
35222 / or NULL if any error is encountered
35223 */
35224     int int_value;
35225     double x;
35226     double log1;
35227     double log2;
35228     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35229     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35230 	x = sqlite3_value_double (argv[0]);
35231     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35232       {
35233 	  int_value = sqlite3_value_int (argv[0]);
35234 	  x = int_value;
35235       }
35236     else
35237       {
35238 	  sqlite3_result_null (context);
35239 	  return;
35240       }
35241     log1 = log (x);
35242     if (testInvalidFP (log1))
35243       {
35244 	  sqlite3_result_null (context);
35245 	  return;
35246       }
35247     log2 = log (2.0);
35248     sqlite3_result_double (context, log1 / log2);
35249 }
35250 
35251 static void
fnct_math_log_10(sqlite3_context * context,int argc,sqlite3_value ** argv)35252 fnct_math_log_10 (sqlite3_context * context, int argc, sqlite3_value ** argv)
35253 {
35254 /* SQL function:
35255 / log10(double X)
35256 /
35257 / Returns the base-10 logarithm of X
35258 / or NULL if any error is encountered
35259 */
35260     int int_value;
35261     double x;
35262     double log1;
35263     double log2;
35264     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35265     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35266 	x = sqlite3_value_double (argv[0]);
35267     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35268       {
35269 	  int_value = sqlite3_value_int (argv[0]);
35270 	  x = int_value;
35271       }
35272     else
35273       {
35274 	  sqlite3_result_null (context);
35275 	  return;
35276       }
35277     log1 = log (x);
35278     if (testInvalidFP (log1))
35279       {
35280 	  sqlite3_result_null (context);
35281 	  return;
35282       }
35283     log2 = log (10.0);
35284     sqlite3_result_double (context, log1 / log2);
35285 }
35286 
35287 static void
fnct_math_pi(sqlite3_context * context,int argc,sqlite3_value ** argv)35288 fnct_math_pi (sqlite3_context * context, int argc, sqlite3_value ** argv)
35289 {
35290 /* SQL function:
35291 / pi(void)
35292 /
35293 / Returns the value of (pi)
35294 */
35295     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35296     sqlite3_result_double (context, 3.14159265358979323846);
35297 }
35298 
35299 static void
fnct_math_pow(sqlite3_context * context,int argc,sqlite3_value ** argv)35300 fnct_math_pow (sqlite3_context * context, int argc, sqlite3_value ** argv)
35301 {
35302 /* SQL function:
35303 / pow(double X, double Y)
35304 /
35305 / Returns the value of X raised to the power of Y.
35306 / or NULL if any error is encountered
35307 */
35308     int int_value;
35309     double x;
35310     double y;
35311     double p;
35312     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35313     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35314 	x = sqlite3_value_double (argv[0]);
35315     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35316       {
35317 	  int_value = sqlite3_value_int (argv[0]);
35318 	  x = int_value;
35319       }
35320     else
35321       {
35322 	  sqlite3_result_null (context);
35323 	  return;
35324       }
35325     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
35326 	y = sqlite3_value_double (argv[1]);
35327     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
35328       {
35329 	  int_value = sqlite3_value_int (argv[1]);
35330 	  y = int_value;
35331       }
35332     else
35333       {
35334 	  sqlite3_result_null (context);
35335 	  return;
35336       }
35337     p = pow (x, y);
35338     if (testInvalidFP (p))
35339 	sqlite3_result_null (context);
35340     else
35341 	sqlite3_result_double (context, p);
35342 }
35343 
35344 static void
fnct_math_stddev_step(sqlite3_context * context,int argc,sqlite3_value ** argv)35345 fnct_math_stddev_step (sqlite3_context * context, int argc,
35346 		       sqlite3_value ** argv)
35347 {
35348 /* SQL function:
35349 / stddev_pop(double X)
35350 / stddev_samp(double X)
35351 / var_pop(double X)
35352 / var_samp(double X)
35353 /
35354 / aggregate function - STEP
35355 /
35356 */
35357     struct stddev_str *p;
35358     int int_value;
35359     double x;
35360     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35361     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35362 	x = sqlite3_value_double (argv[0]);
35363     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35364       {
35365 	  int_value = sqlite3_value_int (argv[0]);
35366 	  x = int_value;
35367       }
35368     else
35369 	return;
35370     p = sqlite3_aggregate_context (context, sizeof (struct stddev_str));
35371     if (!(p->cleaned))
35372       {
35373 	  p->cleaned = 1;
35374 	  p->mean = x;
35375 	  p->quot = 0.0;
35376 	  p->count = 0.0;
35377       }
35378     p->count += 1.0;
35379     p->quot =
35380 	p->quot +
35381 	(((p->count - 1.0) * ((x - p->mean) * (x - p->mean))) / p->count);
35382     p->mean = p->mean + ((x - p->mean) / p->count);
35383 }
35384 
35385 static void
fnct_math_stddev_pop_final(sqlite3_context * context)35386 fnct_math_stddev_pop_final (sqlite3_context * context)
35387 {
35388 /* SQL function:
35389 / stddev_pop(double X)
35390 / aggregate function -  FINAL
35391 /
35392 */
35393     double x;
35394     struct stddev_str *p = sqlite3_aggregate_context (context, 0);
35395     if (!p)
35396       {
35397 	  sqlite3_result_null (context);
35398 	  return;
35399       }
35400     x = sqrt (p->quot / p->count);
35401     sqlite3_result_double (context, x);
35402 }
35403 
35404 static void
fnct_math_stddev_samp_final(sqlite3_context * context)35405 fnct_math_stddev_samp_final (sqlite3_context * context)
35406 {
35407 /* SQL function:
35408 / stddev_samp(double X)
35409 / aggregate function -  FINAL
35410 /
35411 */
35412     double x;
35413     struct stddev_str *p = sqlite3_aggregate_context (context, 0);
35414     if (!p)
35415       {
35416 	  sqlite3_result_null (context);
35417 	  return;
35418       }
35419     x = sqrt (p->quot / (p->count - 1.0));
35420     sqlite3_result_double (context, x);
35421 }
35422 
35423 static void
fnct_math_var_pop_final(sqlite3_context * context)35424 fnct_math_var_pop_final (sqlite3_context * context)
35425 {
35426 /* SQL function:
35427 / var_pop(double X)
35428 / aggregate function -  FINAL
35429 /
35430 */
35431     double x;
35432     struct stddev_str *p = sqlite3_aggregate_context (context, 0);
35433     if (!p)
35434       {
35435 	  sqlite3_result_null (context);
35436 	  return;
35437       }
35438     x = p->quot / p->count;
35439     sqlite3_result_double (context, x);
35440 }
35441 
35442 static void
fnct_math_var_samp_final(sqlite3_context * context)35443 fnct_math_var_samp_final (sqlite3_context * context)
35444 {
35445 /* SQL function:
35446 / var_samp(double X)
35447 / aggregate function -  FINAL
35448 /
35449 */
35450     double x;
35451     struct stddev_str *p = sqlite3_aggregate_context (context, 0);
35452     if (!p)
35453       {
35454 	  sqlite3_result_null (context);
35455 	  return;
35456       }
35457     x = p->quot / (p->count - 1.0);
35458     sqlite3_result_double (context, x);
35459 }
35460 
35461 static void
fnct_math_radians(sqlite3_context * context,int argc,sqlite3_value ** argv)35462 fnct_math_radians (sqlite3_context * context, int argc, sqlite3_value ** argv)
35463 {
35464 /* SQL function:
35465 / radians(double X)
35466 /
35467 / Returns the argument X, converted from degrees to radians
35468 / or NULL if any error is encountered
35469 */
35470     int int_value;
35471     double x;
35472     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35473     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35474 	x = sqlite3_value_double (argv[0]);
35475     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35476       {
35477 	  int_value = sqlite3_value_int (argv[0]);
35478 	  x = int_value;
35479       }
35480     else
35481       {
35482 	  sqlite3_result_null (context);
35483 	  return;
35484       }
35485     x = x * .0174532925199432958;
35486     sqlite3_result_double (context, x);
35487 }
35488 
35489 static void
fnct_math_sign(sqlite3_context * context,int argc,sqlite3_value ** argv)35490 fnct_math_sign (sqlite3_context * context, int argc, sqlite3_value ** argv)
35491 {
35492 /* SQL function:
35493 / sign(double X)
35494 /
35495 / Returns the sign of the argument as -1, 0, or 1, depending on whether X is negative, zero, or positive
35496 / or NULL if any error is encountered
35497 */
35498     int int_value;
35499     double x;
35500     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35501     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35502 	x = sqlite3_value_double (argv[0]);
35503     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35504       {
35505 	  int_value = sqlite3_value_int (argv[0]);
35506 	  x = int_value;
35507       }
35508     else
35509       {
35510 	  sqlite3_result_null (context);
35511 	  return;
35512       }
35513     if (x > 0.0)
35514 	sqlite3_result_double (context, 1.0);
35515     else if (x < 0.0)
35516 	sqlite3_result_double (context, -1.0);
35517     else
35518 	sqlite3_result_double (context, 0.0);
35519 }
35520 
35521 static void
fnct_math_sin(sqlite3_context * context,int argc,sqlite3_value ** argv)35522 fnct_math_sin (sqlite3_context * context, int argc, sqlite3_value ** argv)
35523 {
35524 /* SQL function:
35525 / sin(double X)
35526 /
35527 / Returns the sine of X, where X is given in radians
35528 / or NULL if any error is encountered
35529 */
35530     int int_value;
35531     double x;
35532     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35533     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35534       {
35535 	  x = sin (sqlite3_value_double (argv[0]));
35536 	  sqlite3_result_double (context, x);
35537       }
35538     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35539       {
35540 	  int_value = sqlite3_value_int (argv[0]);
35541 	  x = int_value;
35542 	  x = sin (x);
35543 	  sqlite3_result_double (context, x);
35544       }
35545     else
35546 	sqlite3_result_null (context);
35547 }
35548 
35549 static void
fnct_math_sqrt(sqlite3_context * context,int argc,sqlite3_value ** argv)35550 fnct_math_sqrt (sqlite3_context * context, int argc, sqlite3_value ** argv)
35551 {
35552 /* SQL function:
35553 / sqrt(double X)
35554 /
35555 / Returns the square root of a non-negative number X
35556 / or NULL if any error is encountered
35557 */
35558     int int_value;
35559     double x;
35560     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35561     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35562       {
35563 	  x = sqrt (sqlite3_value_double (argv[0]));
35564 	  if (testInvalidFP (x))
35565 	      sqlite3_result_null (context);
35566 	  else
35567 	      sqlite3_result_double (context, x);
35568       }
35569     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35570       {
35571 	  int_value = sqlite3_value_int (argv[0]);
35572 	  x = int_value;
35573 	  x = sqrt (x);
35574 	  if (testInvalidFP (x))
35575 	      sqlite3_result_null (context);
35576 	  else
35577 	      sqlite3_result_double (context, x);
35578       }
35579     else
35580 	sqlite3_result_null (context);
35581 }
35582 
35583 static void
fnct_math_tan(sqlite3_context * context,int argc,sqlite3_value ** argv)35584 fnct_math_tan (sqlite3_context * context, int argc, sqlite3_value ** argv)
35585 {
35586 /* SQL function:
35587 / tan(double X)
35588 /
35589 / Returns the tangent of X, where X is given in radians
35590 / or NULL if any error is encountered
35591 */
35592     int int_value;
35593     double x;
35594     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35595     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
35596       {
35597 	  x = tan (sqlite3_value_double (argv[0]));
35598 	  sqlite3_result_double (context, x);
35599       }
35600     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
35601       {
35602 	  int_value = sqlite3_value_int (argv[0]);
35603 	  x = int_value;
35604 	  x = tan (x);
35605 	  sqlite3_result_double (context, x);
35606       }
35607     else
35608 	sqlite3_result_null (context);
35609 }
35610 
35611 #endif /* end supporting SQL math functions */
35612 
35613 static void
fnct_GeomFromExifGpsBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35614 fnct_GeomFromExifGpsBlob (sqlite3_context * context, int argc,
35615 			  sqlite3_value ** argv)
35616 {
35617 /* SQL function:
35618 / GeomFromExifGpsBlob(BLOB encoded image)
35619 /
35620 / returns:
35621 / a POINT geometry
35622 / or NULL if any error is encountered
35623 */
35624     unsigned char *p_blob;
35625     int n_bytes;
35626     gaiaGeomCollPtr geom;
35627     unsigned char *geoblob;
35628     int geosize;
35629     double longitude;
35630     double latitude;
35631     int gpkg_mode = 0;
35632     int tiny_point = 0;
35633     struct splite_internal_cache *cache = sqlite3_user_data (context);
35634     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35635     if (cache != NULL)
35636       {
35637 	  gpkg_mode = cache->gpkg_mode;
35638 	  tiny_point = cache->tinyPointEnabled;
35639       }
35640     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
35641       {
35642 	  sqlite3_result_null (context);
35643 	  return;
35644       }
35645     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
35646     n_bytes = sqlite3_value_bytes (argv[0]);
35647     if (gaiaGetGpsCoords (p_blob, n_bytes, &longitude, &latitude))
35648       {
35649 	  geom = gaiaAllocGeomColl ();
35650 	  geom->Srid = 4326;
35651 	  gaiaAddPointToGeomColl (geom, longitude, latitude);
35652 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &geoblob, &geosize, gpkg_mode,
35653 				      tiny_point);
35654 	  gaiaFreeGeomColl (geom);
35655 	  sqlite3_result_blob (context, geoblob, geosize, free);
35656       }
35657     else
35658 	sqlite3_result_null (context);
35659 }
35660 
35661 static char *
guess_mime_type(const unsigned char * p_blob,int n_bytes)35662 guess_mime_type (const unsigned char *p_blob, int n_bytes)
35663 {
35664 /* guessing the mime-type corresponding to some BLOB */
35665     int blob_type;
35666     const char *mime = NULL;
35667     int len;
35668     char *string = NULL;
35669     blob_type = gaiaGuessBlobType (p_blob, n_bytes);
35670     switch (blob_type)
35671       {
35672       case GAIA_ZIP_BLOB:
35673 	  mime = "application/zip";
35674 	  break;
35675       case GAIA_PDF_BLOB:
35676 	  mime = "application/pdf";
35677 	  break;
35678       case GAIA_TIFF_BLOB:
35679 	  mime = "image/tiff";
35680 	  break;
35681       case GAIA_GIF_BLOB:
35682 	  mime = "image/gif";
35683 	  break;
35684       case GAIA_PNG_BLOB:
35685 	  mime = "image/png";
35686 	  break;
35687       case GAIA_JP2_BLOB:
35688 	  mime = "image/jp2";
35689 	  break;
35690       case GAIA_JPEG_BLOB:
35691       case GAIA_EXIF_BLOB:
35692       case GAIA_EXIF_GPS_BLOB:
35693 	  mime = "image/jpeg";
35694 	  break;
35695 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
35696       case GAIA_XML_BLOB:
35697 	  mime = "application/xml";
35698 	  if (gaiaIsSvgXmlBlob (p_blob, n_bytes))
35699 	      mime = "image/svg+xml";
35700 	  break;
35701 #endif /* end including LIBXML2 */
35702       };
35703     if (mime != NULL)
35704       {
35705 	  len = strlen (mime);
35706 	  string = malloc (len + 1);
35707 	  strcpy (string, mime);
35708       }
35709     return string;
35710 }
35711 
35712 static void
fnct_GetMimeType(sqlite3_context * context,int argc,sqlite3_value ** argv)35713 fnct_GetMimeType (sqlite3_context * context, int argc, sqlite3_value ** argv)
35714 {
35715 /* SQL function:
35716 / GetMimeType(BLOB)
35717 /
35718 / returns:
35719 / the Mime-Type corresponding to the BLOB
35720 / or NULL if any error is encountered or no valid mime is defined
35721 */
35722     unsigned char *p_blob;
35723     int n_bytes;
35724     char *mime = NULL;
35725     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35726     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
35727       {
35728 	  sqlite3_result_null (context);
35729 	  return;
35730       }
35731     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
35732     n_bytes = sqlite3_value_bytes (argv[0]);
35733     mime = guess_mime_type (p_blob, n_bytes);
35734     if (mime == NULL)
35735 	sqlite3_result_null (context);
35736     else
35737 	sqlite3_result_text (context, mime, strlen (mime), free);
35738 }
35739 
35740 static void
blob_guess(sqlite3_context * context,int argc,sqlite3_value ** argv,int request)35741 blob_guess (sqlite3_context * context, int argc, sqlite3_value ** argv,
35742 	    int request)
35743 {
35744 /* SQL function:
35745 / IsGifBlob(BLOB encoded image)
35746 / IsPngBlob, IsJpegBlob, IsExifBlob, IsExifGpsBlob, IsTiffBlob,
35747 / IsZipBlob, IsPdfBlob, IsJP2Blob, IsGeometryBlob,
35748 / IsCompressedGeometryBlob, IsTinyPointBlob
35749 /
35750 / returns:
35751 / 1 if the required BLOB_TYPE is TRUE
35752 / 0 otherwise
35753 / or -1 if any error is encountered
35754 */
35755     unsigned char *p_blob;
35756     int n_bytes;
35757     int blob_type;
35758     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35759     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
35760       {
35761 	  sqlite3_result_int (context, -1);
35762 	  return;
35763       }
35764     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
35765     n_bytes = sqlite3_value_bytes (argv[0]);
35766     blob_type = gaiaGuessBlobType (p_blob, n_bytes);
35767     if (request == GAIA_GEOMETRY_BLOB)
35768       {
35769 	  if (blob_type == GAIA_GEOMETRY_BLOB)
35770 	      sqlite3_result_int (context, 1);
35771 	  else
35772 	      sqlite3_result_int (context, 0);
35773 	  return;
35774       }
35775     if (request == GAIA_COMPRESSED_GEOMETRY_BLOB)
35776       {
35777 	  if (blob_type == GAIA_COMPRESSED_GEOMETRY_BLOB)
35778 	      sqlite3_result_int (context, 1);
35779 	  else
35780 	      sqlite3_result_int (context, 0);
35781 	  return;
35782       }
35783     if (request == GAIA_TINYPOINT_BLOB)
35784       {
35785 	  if (blob_type == GAIA_TINYPOINT_BLOB)
35786 	      sqlite3_result_int (context, 1);
35787 	  else
35788 	      sqlite3_result_int (context, 0);
35789 	  return;
35790       }
35791     if (request == GAIA_ZIP_BLOB)
35792       {
35793 	  if (blob_type == GAIA_ZIP_BLOB)
35794 	      sqlite3_result_int (context, 1);
35795 	  else
35796 	      sqlite3_result_int (context, 0);
35797 	  return;
35798       }
35799     if (request == GAIA_PDF_BLOB)
35800       {
35801 	  if (blob_type == GAIA_PDF_BLOB)
35802 	      sqlite3_result_int (context, 1);
35803 	  else
35804 	      sqlite3_result_int (context, 0);
35805 	  return;
35806       }
35807     if (request == GAIA_TIFF_BLOB)
35808       {
35809 	  if (blob_type == GAIA_TIFF_BLOB)
35810 	      sqlite3_result_int (context, 1);
35811 	  else
35812 	      sqlite3_result_int (context, 0);
35813 	  return;
35814       }
35815     if (request == GAIA_GIF_BLOB)
35816       {
35817 	  if (blob_type == GAIA_GIF_BLOB)
35818 	      sqlite3_result_int (context, 1);
35819 	  else
35820 	      sqlite3_result_int (context, 0);
35821 	  return;
35822       }
35823     if (request == GAIA_PNG_BLOB)
35824       {
35825 	  if (blob_type == GAIA_PNG_BLOB)
35826 	      sqlite3_result_int (context, 1);
35827 	  else
35828 	      sqlite3_result_int (context, 0);
35829 	  return;
35830       }
35831     if (request == GAIA_JPEG_BLOB)
35832       {
35833 	  if (blob_type == GAIA_JPEG_BLOB || blob_type == GAIA_EXIF_BLOB
35834 	      || blob_type == GAIA_EXIF_GPS_BLOB)
35835 	      sqlite3_result_int (context, 1);
35836 	  else
35837 	      sqlite3_result_int (context, 0);
35838 	  return;
35839       }
35840     if (request == GAIA_EXIF_BLOB)
35841       {
35842 	  if (blob_type == GAIA_EXIF_BLOB || blob_type == GAIA_EXIF_GPS_BLOB)
35843 	    {
35844 		sqlite3_result_int (context, 1);
35845 	    }
35846 	  else
35847 	      sqlite3_result_int (context, 0);
35848 	  return;
35849       }
35850     if (request == GAIA_EXIF_GPS_BLOB)
35851       {
35852 	  if (blob_type == GAIA_EXIF_GPS_BLOB)
35853 	    {
35854 		sqlite3_result_int (context, 1);
35855 	    }
35856 	  else
35857 	      sqlite3_result_int (context, 0);
35858 	  return;
35859       }
35860     if (request == GAIA_WEBP_BLOB)
35861       {
35862 	  if (blob_type == GAIA_WEBP_BLOB)
35863 	      sqlite3_result_int (context, 1);
35864 	  else
35865 	      sqlite3_result_int (context, 0);
35866 	  return;
35867       }
35868     if (request == GAIA_JP2_BLOB)
35869       {
35870 	  if (blob_type == GAIA_JP2_BLOB)
35871 	      sqlite3_result_int (context, 1);
35872 	  else
35873 	      sqlite3_result_int (context, 0);
35874 	  return;
35875       }
35876     sqlite3_result_int (context, -1);
35877 }
35878 
35879 /*
35880 / the following functions simply readdress the blob_guess()
35881 / setting the appropriate request mode
35882 */
35883 
35884 static void
fnct_IsGeometryBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35885 fnct_IsGeometryBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35886 {
35887     blob_guess (context, argc, argv, GAIA_GEOMETRY_BLOB);
35888 }
35889 
35890 static void
fnct_IsCompressedGeometryBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35891 fnct_IsCompressedGeometryBlob (sqlite3_context * context, int argc,
35892 			       sqlite3_value ** argv)
35893 {
35894     blob_guess (context, argc, argv, GAIA_COMPRESSED_GEOMETRY_BLOB);
35895 }
35896 
35897 static void
fnct_IsTinyPointBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35898 fnct_IsTinyPointBlob (sqlite3_context * context, int argc,
35899 		      sqlite3_value ** argv)
35900 {
35901     blob_guess (context, argc, argv, GAIA_TINYPOINT_BLOB);
35902 }
35903 
35904 static void
fnct_IsZipBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35905 fnct_IsZipBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35906 {
35907     blob_guess (context, argc, argv, GAIA_ZIP_BLOB);
35908 }
35909 
35910 static void
fnct_IsPdfBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35911 fnct_IsPdfBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35912 {
35913     blob_guess (context, argc, argv, GAIA_PDF_BLOB);
35914 }
35915 
35916 static void
fnct_IsTiffBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35917 fnct_IsTiffBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35918 {
35919     blob_guess (context, argc, argv, GAIA_TIFF_BLOB);
35920 }
35921 
35922 static void
fnct_IsGifBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35923 fnct_IsGifBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35924 {
35925     blob_guess (context, argc, argv, GAIA_GIF_BLOB);
35926 }
35927 
35928 static void
fnct_IsPngBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35929 fnct_IsPngBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35930 {
35931     blob_guess (context, argc, argv, GAIA_PNG_BLOB);
35932 }
35933 
35934 static void
fnct_IsJpegBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35935 fnct_IsJpegBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35936 {
35937     blob_guess (context, argc, argv, GAIA_JPEG_BLOB);
35938 }
35939 
35940 static void
fnct_IsExifBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35941 fnct_IsExifBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35942 {
35943     blob_guess (context, argc, argv, GAIA_EXIF_BLOB);
35944 }
35945 
35946 static void
fnct_IsExifGpsBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35947 fnct_IsExifGpsBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35948 {
35949     blob_guess (context, argc, argv, GAIA_EXIF_GPS_BLOB);
35950 }
35951 
35952 static void
fnct_IsWebPBlob(sqlite3_context * context,int argc,sqlite3_value ** argv)35953 fnct_IsWebPBlob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35954 {
35955     blob_guess (context, argc, argv, GAIA_WEBP_BLOB);
35956 }
35957 
35958 static void
fnct_IsJP2Blob(sqlite3_context * context,int argc,sqlite3_value ** argv)35959 fnct_IsJP2Blob (sqlite3_context * context, int argc, sqlite3_value ** argv)
35960 {
35961     blob_guess (context, argc, argv, GAIA_JP2_BLOB);
35962 }
35963 
35964 static void
fnct_BlobFromFile(sqlite3_context * context,int argc,sqlite3_value ** argv)35965 fnct_BlobFromFile (sqlite3_context * context, int argc, sqlite3_value ** argv)
35966 {
35967 /* SQL function:
35968 / BlobFromFile(TEXT filepath)
35969 /
35970 / returns:
35971 / some BLOB on success
35972 / or NULL on failure
35973 */
35974     unsigned char *p_blob;
35975     int n_bytes;
35976     int max_blob;
35977     int rd;
35978     sqlite3 *sqlite = sqlite3_context_db_handle (context);
35979     const char *path = NULL;
35980     FILE *in = NULL;
35981     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
35982     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
35983 	path = (const char *) sqlite3_value_text (argv[0]);
35984     if (path == NULL)
35985       {
35986 	  sqlite3_result_null (context);
35987 	  return;
35988       }
35989     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
35990     n_bytes = sqlite3_value_bytes (argv[0]);
35991 #ifdef _WIN32
35992     in = gaia_win_fopen (path, "rb");
35993 #else
35994     in = fopen (path, "rb");
35995 #endif
35996     if (in == NULL)
35997       {
35998 	  sqlite3_result_null (context);
35999 	  return;
36000       }
36001     else
36002       {
36003 	  /* querying the file length */
36004 	  if (fseek (in, 0, SEEK_END) < 0)
36005 	    {
36006 		sqlite3_result_null (context);
36007 		fclose (in);
36008 		return;
36009 	    }
36010 	  n_bytes = ftell (in);
36011 	  max_blob = sqlite3_limit (sqlite, SQLITE_LIMIT_LENGTH, -1);
36012 	  if (n_bytes > max_blob)
36013 	    {
36014 		/* too big; cannot be stored into a BLOB */
36015 		sqlite3_result_null (context);
36016 		fclose (in);
36017 		return;
36018 	    }
36019 	  rewind (in);
36020 	  p_blob = malloc (n_bytes);
36021 	  /* attempting to load the BLOB from the file */
36022 	  rd = fread (p_blob, 1, n_bytes, in);
36023 	  fclose (in);
36024 	  if (rd != n_bytes)
36025 	    {
36026 		/* read error */
36027 		free (p_blob);
36028 		sqlite3_result_null (context);
36029 		return;
36030 	    }
36031 	  sqlite3_result_blob (context, p_blob, n_bytes, free);
36032       }
36033 }
36034 
36035 static void
fnct_BlobToFile(sqlite3_context * context,int argc,sqlite3_value ** argv)36036 fnct_BlobToFile (sqlite3_context * context, int argc, sqlite3_value ** argv)
36037 {
36038 /* SQL function:
36039 / BlobToFile(BLOB payload, TEXT filepath)
36040 /
36041 / returns:
36042 / 1 on success
36043 / or 0 on failure
36044 */
36045     unsigned char *p_blob;
36046     int n_bytes;
36047     const char *path = NULL;
36048     FILE *out = NULL;
36049     int ret = 1;
36050     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36051     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
36052       {
36053 	  sqlite3_result_int (context, 0);
36054 	  return;
36055       }
36056     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
36057 	path = (const char *) sqlite3_value_text (argv[1]);
36058     if (path == NULL)
36059       {
36060 	  sqlite3_result_int (context, 0);
36061 	  return;
36062       }
36063     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
36064     n_bytes = sqlite3_value_bytes (argv[0]);
36065 #ifdef _WIN32
36066     out = gaia_win_fopen (path, "wb");
36067 #else
36068     out = fopen (path, "wb");
36069 #endif
36070     if (out == NULL)
36071 	ret = 0;
36072     else
36073       {
36074 	  /* exporting the BLOB into the file */
36075 	  int wr = fwrite (p_blob, 1, n_bytes, out);
36076 	  if (wr != n_bytes)
36077 	      ret = 0;
36078 	  fclose (out);
36079       }
36080     sqlite3_result_int (context, ret);
36081 }
36082 
36083 #ifndef OMIT_GEOS		/* only if GEOS is enabled */
36084 
36085 static int
load_dxf(sqlite3 * db_handle,struct splite_internal_cache * cache,char * filename,int srid,int append,int force_dims,int mode,int special_rings,char * prefix,char * layer_name)36086 load_dxf (sqlite3 * db_handle, struct splite_internal_cache *cache,
36087 	  char *filename, int srid, int append, int force_dims, int mode,
36088 	  int special_rings, char *prefix, char *layer_name)
36089 {
36090 /* scanning a Directory and processing all DXF files */
36091     int ret;
36092     gaiaDxfParserPtr dxf = NULL;
36093 
36094 /* creating a DXF parser */
36095     dxf = gaiaCreateDxfParser (srid, force_dims, prefix, layer_name,
36096 			       special_rings);
36097     if (dxf == NULL)
36098       {
36099 	  ret = 0;
36100 	  goto stop_dxf;
36101       }
36102 /* attempting to parse the DXF input file */
36103     if (gaiaParseDxfFile_r (cache, dxf, filename))
36104       {
36105 	  /* loading into the DB */
36106 	  if (!gaiaLoadFromDxfParser (db_handle, dxf, mode, append))
36107 	    {
36108 		ret = 0;
36109 		spatialite_e ("DB error while loading: %s\n", filename);
36110 	    }
36111       }
36112     else
36113       {
36114 	  ret = 0;
36115 	  spatialite_e ("Unable to parse: %s\n", filename);
36116 	  goto stop_dxf;
36117       }
36118     spatialite_e ("\n*** DXF file successfully loaded\n");
36119     ret = 1;
36120 
36121   stop_dxf:
36122     /* destroying the DXF parser */
36123     gaiaDestroyDxfParser (dxf);
36124     return ret;
36125 }
36126 
36127 static void
fnct_ImportDXF(sqlite3_context * context,int argc,sqlite3_value ** argv)36128 fnct_ImportDXF (sqlite3_context * context, int argc, sqlite3_value ** argv)
36129 {
36130 /* SQL function:
36131 / ImportDXF(TEXT filename)
36132 /     or
36133 / InportDXF(TEXT filename, INT srid, INT append, TEXT dims,
36134 /           TEXT mode, TEXT special_rings, TEXT table_prefix,
36135 /           TEXT layer_name)
36136 /
36137 / returns:
36138 / 1 on success
36139 / or 0 on failure
36140 / NULL on invalid arguments
36141 */
36142     int ret;
36143     char *filename;
36144     int srid = -1;
36145     int append = 0;
36146     int special_rings = GAIA_DXF_RING_NONE;
36147     int mode = GAIA_DXF_IMPORT_BY_LAYER;
36148     int force_dims = GAIA_DXF_AUTO_2D_3D;
36149     char *prefix = NULL;
36150     char *layer_name = NULL;
36151     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36152     struct splite_internal_cache *cache = sqlite3_user_data (context);
36153     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36154     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36155       {
36156 	  sqlite3_result_null (context);
36157 	  return;
36158       }
36159     filename = (char *) sqlite3_value_text (argv[0]);
36160     if (argc > 7)
36161       {
36162 	  const char *value;
36163 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
36164 	    {
36165 		sqlite3_result_null (context);
36166 		return;
36167 	    }
36168 	  srid = sqlite3_value_int (argv[1]);
36169 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
36170 	    {
36171 		sqlite3_result_null (context);
36172 		return;
36173 	    }
36174 	  append = sqlite3_value_int (argv[2]);
36175 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
36176 	    {
36177 		sqlite3_result_null (context);
36178 		return;
36179 	    }
36180 	  value = (const char *) sqlite3_value_text (argv[3]);
36181 	  if (strcasecmp (value, "2D") == 0)
36182 	      force_dims = GAIA_DXF_FORCE_2D;
36183 	  else if (strcasecmp (value, "3D") == 0)
36184 	      force_dims = GAIA_DXF_FORCE_3D;
36185 	  else if (strcasecmp (value, "AUTO") == 0)
36186 	      force_dims = GAIA_DXF_AUTO_2D_3D;
36187 	  else
36188 	    {
36189 		sqlite3_result_null (context);
36190 		return;
36191 	    }
36192 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
36193 	    {
36194 		sqlite3_result_null (context);
36195 		return;
36196 	    }
36197 	  value = (const char *) sqlite3_value_text (argv[4]);
36198 	  if (strcasecmp (value, "MIXED") == 0)
36199 	      mode = GAIA_DXF_IMPORT_MIXED;
36200 	  else if (strcasecmp (value, "DISTINCT") == 0)
36201 	      mode = GAIA_DXF_IMPORT_BY_LAYER;
36202 	  else
36203 	    {
36204 		sqlite3_result_null (context);
36205 		return;
36206 	    }
36207 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
36208 	    {
36209 		sqlite3_result_null (context);
36210 		return;
36211 	    }
36212 	  value = (const char *) sqlite3_value_text (argv[5]);
36213 	  if (strcasecmp (value, "LINKED") == 0)
36214 	      special_rings = GAIA_DXF_RING_LINKED;
36215 	  else if (strcasecmp (value, "UNLINKED") == 0)
36216 	      special_rings = GAIA_DXF_RING_UNLINKED;
36217 	  else if (strcasecmp (value, "NONE") == 0)
36218 	      special_rings = GAIA_DXF_RING_NONE;
36219 	  else
36220 	    {
36221 		sqlite3_result_null (context);
36222 		return;
36223 	    }
36224 	  if (sqlite3_value_type (argv[6]) == SQLITE_TEXT)
36225 	      prefix = (char *) sqlite3_value_text (argv[6]);
36226 	  else if (sqlite3_value_type (argv[6]) != SQLITE_NULL)
36227 	    {
36228 		sqlite3_result_null (context);
36229 		return;
36230 	    }
36231 	  if (sqlite3_value_type (argv[7]) == SQLITE_TEXT)
36232 	      layer_name = (char *) sqlite3_value_text (argv[7]);
36233 	  else if (sqlite3_value_type (argv[7]) != SQLITE_NULL)
36234 	    {
36235 		sqlite3_result_null (context);
36236 		return;
36237 	    }
36238       }
36239 
36240     ret =
36241 	load_dxf (db_handle, cache, filename, srid, append, force_dims, mode,
36242 		  special_rings, prefix, layer_name);
36243     sqlite3_result_int (context, ret);
36244 }
36245 
36246 static int
is_dxf_file(const char * filename)36247 is_dxf_file (const char *filename)
36248 {
36249 /* testing if a FileName ends with the expected suffix */
36250     int len = strlen (filename);
36251     int off = len - 4;
36252     if (off >= 1)
36253       {
36254 	  if (strcasecmp (filename + off, ".dxf") == 0)
36255 	      return 1;
36256       }
36257     return 0;
36258 }
36259 
36260 static int
scan_dxf_dir(sqlite3 * db_handle,struct splite_internal_cache * cache,char * dir_path,int srid,int append,int force_dims,int mode,int special_rings,char * prefix,char * layer_name)36261 scan_dxf_dir (sqlite3 * db_handle, struct splite_internal_cache *cache,
36262 	      char *dir_path, int srid, int append, int force_dims, int mode,
36263 	      int special_rings, char *prefix, char *layer_name)
36264 {
36265 /* scanning a Directory and processing all DXF files */
36266     int cnt = 0;
36267     char *filepath;
36268 #if defined(_WIN32) && !defined(__MINGW32__)
36269 /* Visual Studio .NET */
36270     struct _finddata_t c_file;
36271     intptr_t hFile;
36272     if (_chdir (dir_path) < 0)
36273 	return 0;
36274     if ((hFile = _findfirst ("*.*", &c_file)) == -1L)
36275 	;
36276     else
36277       {
36278 	  while (1)
36279 	    {
36280 		if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
36281 		    || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
36282 		  {
36283 		      if (is_dxf_file (c_file.name))
36284 			{
36285 			    filepath =
36286 				sqlite3_mprintf ("%s/%s", dir_path,
36287 						 c_file.name);
36288 			    cnt +=
36289 				load_dxf (db_handle, cache, filepath, srid,
36290 					  append, force_dims, mode,
36291 					  special_rings, prefix, layer_name);
36292 			    sqlite3_free (filepath);
36293 			}
36294 		  }
36295 		if (_findnext (hFile, &c_file) != 0)
36296 		    break;
36297 	    };
36298 	  _findclose (hFile);
36299       }
36300 #else
36301 /* not Visual Studio .NET */
36302     struct dirent *entry;
36303     DIR *dir = opendir (dir_path);
36304     if (!dir)
36305 	return 0;
36306     while (1)
36307       {
36308 	  /* scanning dir-entries */
36309 	  entry = readdir (dir);
36310 	  if (!entry)
36311 	      break;
36312 	  if (is_dxf_file (entry->d_name))
36313 	    {
36314 		filepath = sqlite3_mprintf ("%s/%s", dir_path, entry->d_name);
36315 		cnt +=
36316 		    load_dxf (db_handle, cache, filepath, srid, append,
36317 			      force_dims, mode, special_rings, prefix,
36318 			      layer_name);
36319 		sqlite3_free (filepath);
36320 	    }
36321       }
36322     closedir (dir);
36323 #endif
36324     return cnt;
36325 }
36326 
36327 static void
fnct_ImportDXFfromDir(sqlite3_context * context,int argc,sqlite3_value ** argv)36328 fnct_ImportDXFfromDir (sqlite3_context * context, int argc,
36329 		       sqlite3_value ** argv)
36330 {
36331 /* SQL function:
36332 / ImportDXFfromDir(TEXT dir_path)
36333 /     or
36334 / InportDXFfromDir(TEXT dir_path, INT srid, INT append, TEXT dims,
36335 /                  TEXT mode, TEXT special_rings, TEXT table_prefix,
36336 /                  TEXT layer_name)
36337 /
36338 / returns:
36339 / 1 on success
36340 / or 0 on failure
36341 / NULL on invalid arguments
36342 */
36343     int ret;
36344     char *dir_path;
36345     int srid = -1;
36346     int append = 0;
36347     int special_rings = GAIA_DXF_RING_NONE;
36348     int mode = GAIA_DXF_IMPORT_BY_LAYER;
36349     int force_dims = GAIA_DXF_AUTO_2D_3D;
36350     char *prefix = NULL;
36351     char *layer_name = NULL;
36352     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36353     struct splite_internal_cache *cache = sqlite3_user_data (context);
36354     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36355     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36356       {
36357 	  sqlite3_result_null (context);
36358 	  return;
36359       }
36360     dir_path = (char *) sqlite3_value_text (argv[0]);
36361     if (argc > 7)
36362       {
36363 	  const char *value;
36364 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
36365 	    {
36366 		sqlite3_result_null (context);
36367 		return;
36368 	    }
36369 	  srid = sqlite3_value_int (argv[1]);
36370 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
36371 	    {
36372 		sqlite3_result_null (context);
36373 		return;
36374 	    }
36375 	  append = sqlite3_value_int (argv[2]);
36376 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
36377 	    {
36378 		sqlite3_result_null (context);
36379 		return;
36380 	    }
36381 	  value = (const char *) sqlite3_value_text (argv[3]);
36382 	  if (strcasecmp (value, "2D") == 0)
36383 	      force_dims = GAIA_DXF_FORCE_2D;
36384 	  else if (strcasecmp (value, "3D") == 0)
36385 	      force_dims = GAIA_DXF_FORCE_3D;
36386 	  else if (strcasecmp (value, "AUTO") == 0)
36387 	      force_dims = GAIA_DXF_AUTO_2D_3D;
36388 	  else
36389 	    {
36390 		sqlite3_result_null (context);
36391 		return;
36392 	    }
36393 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
36394 	    {
36395 		sqlite3_result_null (context);
36396 		return;
36397 	    }
36398 	  value = (const char *) sqlite3_value_text (argv[4]);
36399 	  if (strcasecmp (value, "MIXED") == 0)
36400 	      mode = GAIA_DXF_IMPORT_MIXED;
36401 	  else if (strcasecmp (value, "DISTINCT") == 0)
36402 	      mode = GAIA_DXF_IMPORT_BY_LAYER;
36403 	  else
36404 	    {
36405 		sqlite3_result_null (context);
36406 		return;
36407 	    }
36408 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
36409 	    {
36410 		sqlite3_result_null (context);
36411 		return;
36412 	    }
36413 	  value = (const char *) sqlite3_value_text (argv[5]);
36414 	  if (strcasecmp (value, "LINKED") == 0)
36415 	      special_rings = GAIA_DXF_RING_LINKED;
36416 	  else if (strcasecmp (value, "UNLINKED") == 0)
36417 	      special_rings = GAIA_DXF_RING_UNLINKED;
36418 	  else if (strcasecmp (value, "NONE") == 0)
36419 	      special_rings = GAIA_DXF_RING_NONE;
36420 	  else
36421 	    {
36422 		sqlite3_result_null (context);
36423 		return;
36424 	    }
36425 	  if (sqlite3_value_type (argv[6]) == SQLITE_TEXT)
36426 	      prefix = (char *) sqlite3_value_text (argv[6]);
36427 	  else if (sqlite3_value_type (argv[6]) != SQLITE_NULL)
36428 	    {
36429 		sqlite3_result_null (context);
36430 		return;
36431 	    }
36432 	  if (sqlite3_value_type (argv[7]) == SQLITE_TEXT)
36433 	      layer_name = (char *) sqlite3_value_text (argv[7]);
36434 	  else if (sqlite3_value_type (argv[7]) != SQLITE_NULL)
36435 	    {
36436 		sqlite3_result_null (context);
36437 		return;
36438 	    }
36439       }
36440 
36441     ret =
36442 	scan_dxf_dir (db_handle, cache, dir_path, srid, append, force_dims,
36443 		      mode, special_rings, prefix, layer_name);
36444     sqlite3_result_int (context, ret);
36445 }
36446 
36447 #endif /* end GEOS conditional */
36448 
36449 static void
fnct_ExportDXF(sqlite3_context * context,int argc,sqlite3_value ** argv)36450 fnct_ExportDXF (sqlite3_context * context, int argc, sqlite3_value ** argv)
36451 {
36452 /* SQL function:
36453 / ExportDXF(TEXT out_dir, TEXT filename, TEXT sql_query, TEXT layer_col_name,
36454 /           TEXT geom_col_name, TEXT label_col_name, TEXT text_height_col_name,
36455 /           TEXT text_rotation_col_name, BLOB geom_filter)
36456 /     or
36457 / ExportDXF(TEXT out_dir, TEXT filename, TEXT sql_query, TEXT layer_col_name,
36458 /           TEXT geom_col_name, TEXT label_col_name, TEXT text_height_col_name,
36459 /           TEXT text_rotation_col_name, BLOB geom_filter, INT precision)
36460 /
36461 / returns:
36462 / 1 on success
36463 / or 0 on failure
36464 */
36465     unsigned char *p_blob;
36466     int n_bytes;
36467     char *path;
36468     const char *dir_path = NULL;
36469     const char *filename = NULL;
36470     FILE *out = NULL;
36471     const char *sql_query = NULL;
36472     const char *layer_col_name = NULL;
36473     const char *geom_col_name = NULL;
36474     const char *label_col_name = NULL;
36475     const char *text_height_col_name = NULL;
36476     const char *text_rotation_col_name = NULL;
36477     gaiaGeomCollPtr geom = NULL;
36478     int precision = 3;
36479     int ret = 1;
36480     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36481     int gpkg_amphibious = 0;
36482     int gpkg_mode = 0;
36483     struct splite_internal_cache *cache = sqlite3_user_data (context);
36484     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36485     if (cache != NULL)
36486       {
36487 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
36488 	  gpkg_mode = cache->gpkg_mode;
36489       }
36490     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
36491 	dir_path = (const char *) sqlite3_value_text (argv[0]);
36492     if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
36493 	filename = (const char *) sqlite3_value_text (argv[1]);
36494     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
36495 	sql_query = (const char *) sqlite3_value_text (argv[2]);
36496     if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
36497 	layer_col_name = (const char *) sqlite3_value_text (argv[3]);
36498     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
36499 	geom_col_name = (const char *) sqlite3_value_text (argv[4]);
36500     if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
36501 	label_col_name = (const char *) sqlite3_value_text (argv[5]);
36502     if (sqlite3_value_type (argv[6]) == SQLITE_TEXT)
36503 	text_height_col_name = (const char *) sqlite3_value_text (argv[6]);
36504     if (sqlite3_value_type (argv[7]) == SQLITE_TEXT)
36505 	text_rotation_col_name = (const char *) sqlite3_value_text (argv[7]);
36506     if (sqlite3_value_type (argv[8]) == SQLITE_BLOB)
36507       {
36508 	  p_blob = (unsigned char *) sqlite3_value_blob (argv[8]);
36509 	  n_bytes = sqlite3_value_bytes (argv[8]);
36510 	  geom =
36511 	      gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
36512 					   gpkg_amphibious);
36513       }
36514     if (argc == 10)
36515       {
36516 	  if (sqlite3_value_type (argv[9]) == SQLITE_INTEGER)
36517 	      precision = sqlite3_value_int (argv[9]);
36518       }
36519     if (dir_path == NULL || filename == NULL || sql_query == NULL
36520 	|| layer_col_name == NULL || geom_col_name == NULL)
36521       {
36522 	  sqlite3_result_int (context, 0);
36523 	  if (geom != NULL)
36524 	      gaiaFreeGeomColl (geom);
36525 	  return;
36526       }
36527 
36528     path = sqlite3_mprintf ("%s/%s.dxf", dir_path, filename);
36529 #ifdef _WIN32
36530     out = gaia_win_fopen (path, "wb");
36531 #else
36532     out = fopen (path, "wb");
36533 #endif
36534     if (out == NULL)
36535       {
36536 	  ret = 0;
36537 	  spatialite_e ("ExportDXF error - unable to create \"%s\"\n", path);
36538       }
36539     else
36540       {
36541 	  /* exporting the DXF */
36542 	  gaiaDxfWriter dxf;
36543 	  gaiaDxfWriterInit (&dxf, out, precision, GAIA_DXF_V12);
36544 	  ret = gaiaExportDxf (&dxf, db_handle, sql_query, layer_col_name,
36545 			       geom_col_name, label_col_name,
36546 			       text_height_col_name, text_rotation_col_name,
36547 			       geom);
36548 	  if (ret > 0)
36549 	      ret = 1;
36550 	  fclose (out);
36551       }
36552     sqlite3_result_int (context, ret);
36553     if (geom != NULL)
36554 	gaiaFreeGeomColl (geom);
36555     sqlite3_free (path);
36556 }
36557 
36558 static void
fnct_CheckDuplicateRows(sqlite3_context * context,int argc,sqlite3_value ** argv)36559 fnct_CheckDuplicateRows (sqlite3_context * context, int argc,
36560 			 sqlite3_value ** argv)
36561 {
36562 /* SQL function:
36563 / CheckDuplicateRows(TEXT table)
36564 /
36565 / returns:
36566 / the number of duplicate rows found
36567 / NULL on invalid arguments
36568 */
36569     char *table;
36570     int rows;
36571     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36572     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36573     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36574       {
36575 	  sqlite3_result_null (context);
36576 	  return;
36577       }
36578     table = (char *) sqlite3_value_text (argv[0]);
36579 
36580     check_duplicated_rows (db_handle, table, &rows);
36581 
36582     if (rows < 0)
36583 	sqlite3_result_null (context);
36584     else
36585 	sqlite3_result_int (context, rows);
36586 }
36587 
36588 static void
fnct_RemoveDuplicateRows(sqlite3_context * context,int argc,sqlite3_value ** argv)36589 fnct_RemoveDuplicateRows (sqlite3_context * context, int argc,
36590 			  sqlite3_value ** argv)
36591 {
36592 /* SQL function:
36593 / RemoveDuplicateRows(TEXT table)
36594 / RemoveDuplicateRows(TEXT table, BOOL transaction)
36595 /
36596 / returns:
36597 / the number of duplicate rows removed
36598 / NULL on invalid arguments
36599 */
36600     char *table;
36601     int transaction = 1;
36602     int rows;
36603     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36604     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36605     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36606       {
36607 	  sqlite3_result_null (context);
36608 	  return;
36609       }
36610     table = (char *) sqlite3_value_text (argv[0]);
36611     if (argc == 2)
36612       {
36613 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
36614 	    {
36615 		sqlite3_result_null (context);
36616 		return;
36617 	    }
36618 	  transaction = sqlite3_value_int (argv[1]);
36619       }
36620 
36621     remove_duplicated_rows_ex2 (db_handle, table, &rows, transaction);
36622 
36623     if (rows < 0)
36624 	sqlite3_result_null (context);
36625     else
36626 	sqlite3_result_int (context, rows);
36627 }
36628 
36629 static void
fnct_ElementaryGeometries(sqlite3_context * context,int argc,sqlite3_value ** argv)36630 fnct_ElementaryGeometries (sqlite3_context * context, int argc,
36631 			   sqlite3_value ** argv)
36632 {
36633 /* SQL function:
36634 / ElementaryGeometries(TEXT input_table, TEXT geo_column, TEXT out_table,
36635 /                      TEXT out_pk, TEXT out_multi_id)
36636 / ElementaryGeometries(TEXT input_table, TEXT geo_column, TEXT out_table,
36637 /                      TEXT out_pk, TEXT out_multi_id, BOOL transaction)
36638 / ElementaryGeometries(TEXT input_table, TEXT geo_column, TEXT out_table,
36639 /                      TEXT out_pk, TEXT out_multi_id, BOOL transaction,
36640 /                     ... text option1 ..., ... text option2 ..., text option10)
36641 /
36642 / returns:
36643 / the number of inserted rows
36644 / NULL on invalid arguments
36645 */
36646     char *in_table;
36647     char *geo_column;
36648     char *out_table;
36649     char *out_pk;
36650     char *out_multi_id;
36651     const void *options = NULL;
36652     int rows;
36653     int transaction = 1;
36654     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36655     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36656     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36657       {
36658 	  sqlite3_result_null (context);
36659 	  return;
36660       }
36661     in_table = (char *) sqlite3_value_text (argv[0]);
36662     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
36663       {
36664 	  sqlite3_result_null (context);
36665 	  return;
36666       }
36667     geo_column = (char *) sqlite3_value_text (argv[1]);
36668     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
36669       {
36670 	  sqlite3_result_null (context);
36671 	  return;
36672       }
36673     out_table = (char *) sqlite3_value_text (argv[2]);
36674     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
36675       {
36676 	  sqlite3_result_null (context);
36677 	  return;
36678       }
36679     out_pk = (char *) sqlite3_value_text (argv[3]);
36680     if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
36681       {
36682 	  sqlite3_result_null (context);
36683 	  return;
36684       }
36685     out_multi_id = (char *) sqlite3_value_text (argv[4]);
36686     if (argc >= 6)
36687       {
36688 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
36689 	    {
36690 		sqlite3_result_null (context);
36691 		return;
36692 	    }
36693 	  transaction = sqlite3_value_int (argv[5]);
36694       }
36695 
36696 /* additional options */
36697     if (argc > 6 && sqlite3_value_type (argv[6]) != SQLITE_TEXT)
36698       {
36699 	  spatialite_e
36700 	      ("ElementaryGeometries() error: argument 7 is not of the String or TEXT type\n");
36701 	  sqlite3_result_null (context);
36702 	  return;
36703       }
36704     if (argc > 7 && sqlite3_value_type (argv[7]) != SQLITE_TEXT)
36705       {
36706 	  spatialite_e
36707 	      ("ElementaryGeometries() error: argument 8 is not of the String or TEXT type\n");
36708 	  sqlite3_result_null (context);
36709 	  return;
36710       }
36711     if (argc > 8 && sqlite3_value_type (argv[8]) != SQLITE_TEXT)
36712       {
36713 	  spatialite_e
36714 	      ("ElementaryGeometries() error: argument 9 is not of the String or TEXT type\n");
36715 	  sqlite3_result_null (context);
36716 	  return;
36717       }
36718     if (argc > 9 && sqlite3_value_type (argv[9]) != SQLITE_TEXT)
36719       {
36720 	  spatialite_e
36721 	      ("ElementaryGeometries() error: argument 10 is not of the String or TEXT type\n");
36722 	  sqlite3_result_null (context);
36723 	  return;
36724       }
36725     if (argc > 10 && sqlite3_value_type (argv[10]) != SQLITE_TEXT)
36726       {
36727 	  spatialite_e
36728 	      ("ElementaryGeometries() error: argument 11 is not of the String or TEXT type\n");
36729 	  sqlite3_result_null (context);
36730 	  return;
36731       }
36732     if (argc > 11 && sqlite3_value_type (argv[11]) != SQLITE_TEXT)
36733       {
36734 	  spatialite_e
36735 	      ("ElementaryGeometries() error: argument 12 is not of the String or TEXT type\n");
36736 	  sqlite3_result_null (context);
36737 	  return;
36738       }
36739     if (argc > 12 && sqlite3_value_type (argv[12]) != SQLITE_TEXT)
36740       {
36741 	  spatialite_e
36742 	      ("ElementaryGeometries() error: argument 13 is not of the String or TEXT type\n");
36743 	  sqlite3_result_null (context);
36744 	  return;
36745       }
36746     if (argc > 13 && sqlite3_value_type (argv[13]) != SQLITE_TEXT)
36747       {
36748 	  spatialite_e
36749 	      ("ElementaryGeometries() error: argument 14 is not of the String or TEXT type\n");
36750 	  sqlite3_result_null (context);
36751 	  return;
36752       }
36753     if (argc > 14 && sqlite3_value_type (argv[14]) != SQLITE_TEXT)
36754       {
36755 	  spatialite_e
36756 	      ("ElementaryGeometries() error: argument 15 is not of the String or TEXT type\n");
36757 	  sqlite3_result_null (context);
36758 	  return;
36759       }
36760     if (argc > 15 && sqlite3_value_type (argv[15]) != SQLITE_TEXT)
36761       {
36762 	  spatialite_e
36763 	      ("ElementaryGeometries() error: argument 16 is not of the String or TEXT type\n");
36764 	  sqlite3_result_null (context);
36765 	  return;
36766       }
36767 
36768     options = gaiaElemGeomOptionsCreate ();
36769     if (options == NULL)
36770       {
36771 	  sqlite3_result_null (context);
36772 	  return;
36773       }
36774 
36775 /* additional options */
36776     if (argc > 6)
36777 	gaiaElemGeomOptionsAdd (options,
36778 				(const char *) sqlite3_value_text (argv[6]));
36779     if (argc > 7)
36780 	gaiaElemGeomOptionsAdd (options,
36781 				(const char *) sqlite3_value_text (argv[7]));
36782     if (argc > 8)
36783 	gaiaElemGeomOptionsAdd (options,
36784 				(const char *) sqlite3_value_text (argv[8]));
36785     if (argc > 9)
36786 	gaiaElemGeomOptionsAdd (options,
36787 				(const char *) sqlite3_value_text (argv[9]));
36788     if (argc > 10)
36789 	gaiaElemGeomOptionsAdd (options,
36790 				(const char *) sqlite3_value_text (argv[10]));
36791     if (argc > 11)
36792 	gaiaElemGeomOptionsAdd (options,
36793 				(const char *) sqlite3_value_text (argv[11]));
36794     if (argc > 12)
36795 	gaiaElemGeomOptionsAdd (options,
36796 				(const char *) sqlite3_value_text (argv[12]));
36797     if (argc > 13)
36798 	gaiaElemGeomOptionsAdd (options,
36799 				(const char *) sqlite3_value_text (argv[13]));
36800     if (argc > 14)
36801 	gaiaElemGeomOptionsAdd (options,
36802 				(const char *) sqlite3_value_text (argv[14]));
36803     if (argc > 15)
36804 	gaiaElemGeomOptionsAdd (options,
36805 				(const char *) sqlite3_value_text (argv[15]));
36806 
36807     elementary_geometries_ex3 (db_handle, in_table, geo_column, out_table,
36808 			       out_pk, out_multi_id, options, &rows,
36809 			       transaction);
36810 
36811     gaiaElemGeomOptionsDestroy (options);
36812     if (rows <= 0)
36813 	sqlite3_result_null (context);
36814     else
36815 	sqlite3_result_int (context, rows);
36816 }
36817 
36818 static void
fnct_DropGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)36819 fnct_DropGeoTable (sqlite3_context * context, int argc, sqlite3_value ** argv)
36820 {
36821 /*
36822 /
36823 / DEPRECATED !!!! please use DropTable() as a full replacement !!!!
36824 /
36825 / SQL function:
36826 / DropGeoTable(TEXT table)
36827 / DropGeoTable(TEXT table, BOOL transaction)
36828 / DropGeoTable(TEXT db_prefix, TEXT table)
36829 / DropGeoTable(TEXT db_prefix, TEXT table, BOOL transaction)
36830 /
36831 / returns:
36832 / 1 on success, 0 on failure
36833 / NULL on invalid arguments
36834 */
36835     char *db_prefix = "main";
36836     char *table = NULL;
36837     int transaction = 1;
36838     int ret;
36839     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36840     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36841     if (argc == 1)
36842       {
36843 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
36844 	    {
36845 		sqlite3_result_null (context);
36846 		return;
36847 	    }
36848 	  table = (char *) sqlite3_value_text (argv[0]);
36849       }
36850     else if (argc >= 2)
36851       {
36852 	  if (sqlite3_value_type (argv[0]) == SQLITE_TEXT
36853 	      && sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
36854 	    {
36855 		table = (char *) sqlite3_value_text (argv[0]);
36856 		transaction = sqlite3_value_int (argv[1]);
36857 	    }
36858 	  else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT
36859 		   && sqlite3_value_type (argv[1]) == SQLITE_TEXT)
36860 	    {
36861 		db_prefix = (char *) sqlite3_value_text (argv[0]);
36862 		table = (char *) sqlite3_value_text (argv[1]);
36863 	    }
36864 	  else
36865 	    {
36866 		sqlite3_result_null (context);
36867 		return;
36868 	    }
36869       }
36870     if (argc == 3)
36871       {
36872 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
36873 	    {
36874 		sqlite3_result_null (context);
36875 		return;
36876 	    }
36877 	  transaction = sqlite3_value_int (argv[2]);
36878       }
36879 
36880     ret = gaiaDropTableEx3 (db_handle, db_prefix, table, transaction, NULL);
36881     sqlite3_result_int (context, ret);
36882 }
36883 
36884 static void
fnct_DropTable(sqlite3_context * context,int argc,sqlite3_value ** argv)36885 fnct_DropTable (sqlite3_context * context, int argc, sqlite3_value ** argv)
36886 {
36887 /* SQL function:
36888 / DropTable(TEXT db_prefix, TEXT table)
36889 / DropTable(TEXT db_prefix, TEXT table, BOOL permissive)
36890 /
36891 / returns:
36892 / 1 on success
36893 / an Exception on failure.
36894 */
36895     char *db_prefix = NULL;
36896     char *table = NULL;
36897     int permissive = 0;
36898     const char *arg_name;
36899     char *err;
36900     char *msg;
36901     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36902     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36903     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
36904 	&& sqlite3_value_type (argv[0]) != SQLITE_NULL)
36905       {
36906 	  arg_name = "1st arg";
36907 	  goto invalid_args;
36908       }
36909     db_prefix = (char *) sqlite3_value_text (argv[0]);
36910     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
36911       {
36912 	  arg_name = "2nd arg";
36913 	  goto invalid_args;
36914       }
36915     table = (char *) sqlite3_value_text (argv[1]);
36916     if (argc >= 3)
36917       {
36918 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
36919 	    {
36920 		arg_name = "3rd arg";
36921 		goto invalid_args;
36922 	    }
36923 	  permissive = sqlite3_value_int (argv[2]);
36924       }
36925 
36926     if (!gaiaDropTable5 (db_handle, db_prefix, table, &err))
36927       {
36928 	  if (permissive)
36929 	    {
36930 		sqlite3_free (err);
36931 		sqlite3_result_int (context, 0);
36932 		return;
36933 	    }
36934 	  msg = sqlite3_mprintf ("DropTable exception - %s.", err);
36935 	  sqlite3_result_error (context, msg, -1);
36936 	  sqlite3_free (msg);
36937 	  sqlite3_free (err);
36938 	  return;
36939       }
36940     sqlite3_result_int (context, 1);
36941     return;
36942 
36943   invalid_args:
36944     msg =
36945 	sqlite3_mprintf ("DropTable exception - invalid argument (%s).",
36946 			 arg_name);
36947     sqlite3_result_error (context, msg, -1);
36948     sqlite3_free (msg);
36949     return;
36950 }
36951 
36952 static void
fnct_RenameTable(sqlite3_context * context,int argc,sqlite3_value ** argv)36953 fnct_RenameTable (sqlite3_context * context, int argc, sqlite3_value ** argv)
36954 {
36955 /* SQL function:
36956 / RenameTable(TEXT db_prefix, TEXT old_name, TEXT new_name)
36957 / RenameTable(TEXT db_prefix, TEXT old_name, TEXT new_name, BOOL permissive)
36958 /
36959 / returns:
36960 / 1 on success
36961 / an Exception on failure.
36962 */
36963     const char *db_prefix = NULL;
36964     const char *old_name = NULL;
36965     const char *new_name = NULL;
36966     const char *arg_name;
36967     int permissive = 0;
36968     char *err;
36969     char *msg;
36970     sqlite3 *db_handle = sqlite3_context_db_handle (context);
36971     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
36972     if (sqlite3_libversion_number () < 3025000)
36973 	goto obsolete_sqlite;
36974     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
36975 	&& sqlite3_value_type (argv[0]) != SQLITE_NULL)
36976       {
36977 	  arg_name = "1st arg";
36978 	  goto invalid_args;
36979       }
36980     db_prefix = (char *) sqlite3_value_text (argv[0]);
36981     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
36982       {
36983 	  arg_name = "2nd arg";
36984 	  goto invalid_args;
36985       }
36986     old_name = (char *) sqlite3_value_text (argv[1]);
36987     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
36988       {
36989 	  arg_name = "3rd arg";
36990 	  goto invalid_args;
36991       }
36992     new_name = (char *) sqlite3_value_text (argv[2]);
36993     if (argc >= 4)
36994       {
36995 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
36996 	    {
36997 		arg_name = "4th arg";
36998 		goto invalid_args;
36999 	    }
37000 	  permissive = sqlite3_value_int (argv[3]);
37001       }
37002     if (!gaiaRenameTable (db_handle, db_prefix, old_name, new_name, &err))
37003       {
37004 	  if (permissive)
37005 	    {
37006 		sqlite3_free (err);
37007 		sqlite3_result_int (context, 0);
37008 		return;
37009 	    }
37010 	  msg = sqlite3_mprintf ("RenameTable exception - %s.", err);
37011 	  sqlite3_result_error (context, msg, -1);
37012 	  sqlite3_free (msg);
37013 	  sqlite3_free (err);
37014 	  return;
37015       }
37016     sqlite3_result_int (context, 1);
37017     return;
37018 
37019   invalid_args:
37020     msg =
37021 	sqlite3_mprintf ("RenameTable exception - invalid argument (%s).",
37022 			 arg_name);
37023     sqlite3_result_error (context, msg, -1);
37024     sqlite3_free (msg);
37025     return;
37026 
37027   obsolete_sqlite:
37028     msg =
37029 	sqlite3_mprintf
37030 	("RenameTable exception - libsqlite 3.25 or later is strictly required.");
37031     sqlite3_result_error (context, msg, -1);
37032     sqlite3_free (msg);
37033     return;
37034 }
37035 
37036 static void
fnct_RenameColumn(sqlite3_context * context,int argc,sqlite3_value ** argv)37037 fnct_RenameColumn (sqlite3_context * context, int argc, sqlite3_value ** argv)
37038 {
37039 /* SQL function:
37040 / RenameColumn(TEXT db_prefix, TEXT table, TEXT old_name, TEXT new_name)
37041 / RenameColumn(TEXT db_prefix, TEXT table, TEXT old_name, TEXT new_name, BOOL permissive)
37042 /
37043 / returns:
37044 / 1 on success
37045 / an Exception on failure.
37046 */
37047     const char *db_prefix = NULL;
37048     const char *table = NULL;
37049     const char *old_name = NULL;
37050     const char *new_name = NULL;
37051     const char *arg_name;
37052     int permissive = 0;
37053     char *err;
37054     char *msg;
37055     sqlite3 *db_handle = sqlite3_context_db_handle (context);
37056     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37057     if (sqlite3_libversion_number () < 3025000)
37058 	goto obsolete_sqlite;
37059     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
37060 	&& sqlite3_value_type (argv[0]) != SQLITE_NULL)
37061       {
37062 	  arg_name = "1st arg";
37063 	  goto invalid_args;
37064       }
37065     db_prefix = (char *) sqlite3_value_text (argv[0]);
37066     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
37067       {
37068 	  arg_name = "2nd arg";
37069 	  goto invalid_args;
37070       }
37071     table = (char *) sqlite3_value_text (argv[1]);
37072     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
37073       {
37074 	  arg_name = "3rd arg";
37075 	  goto invalid_args;
37076       }
37077     old_name = (char *) sqlite3_value_text (argv[2]);
37078     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
37079       {
37080 	  arg_name = "4th arg";
37081 	  goto invalid_args;
37082       }
37083     new_name = (char *) sqlite3_value_text (argv[3]);
37084     if (argc >= 5)
37085       {
37086 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
37087 	    {
37088 		arg_name = "5th arg";
37089 		goto invalid_args;
37090 	    }
37091 	  permissive = sqlite3_value_int (argv[4]);
37092       }
37093     if (!gaiaRenameColumn
37094 	(db_handle, db_prefix, table, old_name, new_name, &err))
37095       {
37096 	  if (permissive)
37097 	    {
37098 		sqlite3_free (err);
37099 		sqlite3_result_int (context, 0);
37100 		return;
37101 	    }
37102 	  msg = sqlite3_mprintf ("RenameColumn exception - %s.", err);
37103 	  sqlite3_result_error (context, msg, -1);
37104 	  sqlite3_free (msg);
37105 	  sqlite3_free (err);
37106 	  return;
37107       }
37108     sqlite3_result_int (context, 1);
37109     return;
37110 
37111   invalid_args:
37112     msg =
37113 	sqlite3_mprintf ("RenameColumn exception - invalid argument (%s).",
37114 			 arg_name);
37115     sqlite3_result_error (context, msg, -1);
37116     sqlite3_free (msg);
37117     return;
37118 
37119   obsolete_sqlite:
37120     msg =
37121 	sqlite3_mprintf
37122 	("RenameColumn exception - libsqlite 3.25 or later is strictly required.");
37123     sqlite3_result_error (context, msg, -1);
37124     sqlite3_free (msg);
37125     return;
37126 }
37127 
37128 static void
fnct_sp_get_last_error(sqlite3_context * context,int argc,sqlite3_value ** argv)37129 fnct_sp_get_last_error (sqlite3_context * context, int argc,
37130 			sqlite3_value ** argv)
37131 {
37132 /* SQL function:
37133 / SqlProc_GetLastError()
37134 /
37135 / return the most recent SQL Procedures error message (if any)
37136 / return NULL on any other case
37137 */
37138     const char *msg = NULL;
37139     void *data = sqlite3_user_data (context);
37140     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37141     if (data != NULL)
37142 	msg = gaia_sql_proc_get_last_error (data);
37143     if (msg == NULL)
37144 	sqlite3_result_null (context);
37145     else
37146 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
37147 }
37148 
37149 static void
fnct_sp_set_logfile(sqlite3_context * context,int argc,sqlite3_value ** argv)37150 fnct_sp_set_logfile (sqlite3_context * context, int argc, sqlite3_value ** argv)
37151 {
37152 /* SQL function:
37153 / SqlProc_SetLogfile(TEXT logfile_path)
37154 / SqlProc_SetLogfile(TEXT logfile_path, INT append)
37155 /
37156 / returns:
37157 / 1 on success
37158 / raises an exception on invalid argument or unaccessible file
37159 */
37160     const char *filepath = NULL;
37161     int append = 0;
37162     char *msg;
37163     struct splite_internal_cache *cache = sqlite3_user_data (context);
37164     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37165     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
37166 	filepath = (const char *) sqlite3_value_text (argv[0]);
37167     else if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
37168 	;
37169     else
37170 	goto invalid_filepath;
37171     if (argc >= 2)
37172       {
37173 	  if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
37174 	      append = sqlite3_value_int (argv[1]);
37175 	  else
37176 	      goto invalid_append;
37177       }
37178     if (gaia_sql_proc_logfile (cache, filepath, append))
37179 	sqlite3_result_int (context, 1);
37180     else
37181 	goto file_error;
37182     return;
37183 
37184   invalid_filepath:
37185     msg = "SqlProc exception - illegal File Path argument.";
37186     sqlite3_result_error (context, msg, -1);
37187     return;
37188 
37189   invalid_append:
37190     msg = "SqlProc exception - illegal Append Mode argument.";
37191     sqlite3_result_error (context, msg, -1);
37192     return;
37193 
37194   file_error:
37195     msg =
37196 	sqlite3_mprintf
37197 	("SqlProc exception - unable to open \"%s\" for writing.", filepath);
37198     sqlite3_result_error (context, msg, -1);
37199     sqlite3_free (msg);
37200     return;
37201 }
37202 
37203 static void
fnct_sp_get_logfile(sqlite3_context * context,int argc,sqlite3_value ** argv)37204 fnct_sp_get_logfile (sqlite3_context * context, int argc, sqlite3_value ** argv)
37205 {
37206 /* SQL function:
37207 / SqlProc_GetLogfile(void)
37208 /
37209 / returns:
37210 / the path of the currently set Logfile
37211 / NULL if no current Logfile is defined
37212 */
37213     struct splite_internal_cache *cache = sqlite3_user_data (context);
37214     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37215     if (cache == NULL)
37216 	sqlite3_result_null (context);
37217     else
37218       {
37219 	  const char *path = cache->SqlProcLogfile;
37220 	  if (path == NULL)
37221 	      sqlite3_result_null (context);
37222 	  else
37223 	      sqlite3_result_text (context, path, strlen (path), SQLITE_STATIC);
37224       }
37225 }
37226 
37227 static void
fnct_sp_from_text(sqlite3_context * context,int argc,sqlite3_value ** argv)37228 fnct_sp_from_text (sqlite3_context * context, int argc, sqlite3_value ** argv)
37229 {
37230 /* SQL function:
37231 / SqlProc_FromText(TEXT sql-script)
37232 / SqlProc_FromText(TEXT sql-script, TEXT charset)
37233 /
37234 / returns:
37235 / a SQL Procedure BLOB object
37236 / raises an exception on invalid arguments
37237 */
37238     const char *sql;
37239     const char *charset = "UTF-8";
37240     unsigned char *blob = NULL;
37241     int blob_sz = 0;
37242     const char *msg;
37243     struct splite_internal_cache *cache = sqlite3_user_data (context);
37244     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37245     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
37246 	goto invalid_sql_body;
37247     sql = (const char *) sqlite3_value_text (argv[0]);
37248     if (argc >= 2)
37249       {
37250 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
37251 	      goto invalid_charset;
37252 	  charset = (const char *) sqlite3_value_text (argv[1]);
37253       }
37254     if (gaia_sql_proc_parse (cache, sql, charset, &blob, &blob_sz))
37255 	sqlite3_result_blob (context, blob, blob_sz, free);
37256     else
37257       {
37258 	  if (blob != NULL)
37259 	      free (blob);
37260 	  goto parse_error;
37261       }
37262     return;
37263 
37264   invalid_sql_body:
37265     msg = "SqlProc exception - illegal SQL Body argument.";
37266     sqlite3_result_error (context, msg, -1);
37267     return;
37268 
37269   invalid_charset:
37270     msg = "SqlProc exception - illegal Charset Encodind argument.";
37271     sqlite3_result_error (context, msg, -1);
37272     return;
37273 
37274   parse_error:
37275     msg = "SqlProc exception - invalid SQL Body.";
37276     sqlite3_result_error (context, msg, -1);
37277     return;
37278 }
37279 
37280 static void
fnct_sp_from_file(sqlite3_context * context,int argc,sqlite3_value ** argv)37281 fnct_sp_from_file (sqlite3_context * context, int argc, sqlite3_value ** argv)
37282 {
37283 /* SQL function:
37284 / SqlProc_FromFile(TEXT filepath)
37285 / SqlProc_FromFile(TEXT filepath, TEXT charset)
37286 /
37287 / returns:
37288 / a SQL Procedure BLOB object
37289 / raises an exception on invalid arguments
37290 */
37291     const char *filepath;
37292     const char *charset = "UTF-8";
37293     unsigned char *blob = NULL;
37294     int blob_sz = 0;
37295     const char *msg;
37296     struct splite_internal_cache *cache = sqlite3_user_data (context);
37297     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37298     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
37299 	goto invalid_filepath;
37300     filepath = (const char *) sqlite3_value_text (argv[0]);
37301     if (argc >= 2)
37302       {
37303 	  if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
37304 	      goto invalid_charset;
37305 	  charset = (const char *) sqlite3_value_text (argv[1]);
37306       }
37307     if (gaia_sql_proc_import (cache, filepath, charset, &blob, &blob_sz))
37308 	sqlite3_result_blob (context, blob, blob_sz, free);
37309     else
37310       {
37311 	  if (blob != NULL)
37312 	      free (blob);
37313 	  goto read_error;
37314       }
37315     return;
37316 
37317   invalid_filepath:
37318     msg = "SqlProc exception - illegal File Path argument.";
37319     sqlite3_result_error (context, msg, -1);
37320     return;
37321 
37322   invalid_charset:
37323     msg = "SqlProc exception - illegal Charset Encodind argument.";
37324     sqlite3_result_error (context, msg, -1);
37325     return;
37326 
37327   read_error:
37328     msg = "SqlProc exception - unable to parse the external File.";
37329     sqlite3_result_error (context, msg, -1);
37330     return;
37331 }
37332 
37333 static void
fnct_sp_is_valid(sqlite3_context * context,int argc,sqlite3_value ** argv)37334 fnct_sp_is_valid (sqlite3_context * context, int argc, sqlite3_value ** argv)
37335 {
37336 /* SQL function:
37337 / SqlProc_IsValid(BLOB)
37338 /
37339 / returns:
37340 / 1 if the argument really is a valid SQL Procedure Object
37341 / 0 if not
37342 */
37343     const unsigned char *blob;
37344     int blob_sz = 0;
37345     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37346     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37347       {
37348 	  sqlite3_result_int (context, 0);
37349 	  return;
37350       }
37351     blob = sqlite3_value_blob (argv[0]);
37352     blob_sz = sqlite3_value_bytes (argv[0]);
37353     if (gaia_sql_proc_is_valid (blob, blob_sz))
37354 	sqlite3_result_int (context, 1);
37355     else
37356 	sqlite3_result_int (context, 0);
37357     return;
37358 }
37359 
37360 static void
fnct_sp_var_count(sqlite3_context * context,int argc,sqlite3_value ** argv)37361 fnct_sp_var_count (sqlite3_context * context, int argc, sqlite3_value ** argv)
37362 {
37363 /* SQL function:
37364 / SqlProc_NumVariables(BLOB)
37365 /
37366 / returns:
37367 / the total count of Variables from a SQL Procedure Object
37368 / raises an exception on invalid argument
37369 */
37370     const unsigned char *blob;
37371     int blob_sz = 0;
37372     int count;
37373     const char *msg;
37374     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37375     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37376 	goto invalid_argument;
37377     blob = sqlite3_value_blob (argv[0]);
37378     blob_sz = sqlite3_value_bytes (argv[0]);
37379     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37380 	goto not_an_sql_proc;
37381     count = gaia_sql_proc_var_count (blob, blob_sz);
37382     sqlite3_result_int (context, count);
37383     return;
37384 
37385   invalid_argument:
37386     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37387     sqlite3_result_error (context, msg, -1);
37388     return;
37389 
37390   not_an_sql_proc:
37391     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37392     sqlite3_result_error (context, msg, -1);
37393     return;
37394 }
37395 
37396 static void
fnct_sp_variable(sqlite3_context * context,int argc,sqlite3_value ** argv)37397 fnct_sp_variable (sqlite3_context * context, int argc, sqlite3_value ** argv)
37398 {
37399 /* SQL function:
37400 / SqlProc_VariableN(BLOB, INTEGER index)
37401 /
37402 / returns:
37403 / the Name of the Nth Variable from a SQL Procedure Object
37404 / raises an exception on invalid arguments
37405 */
37406     const unsigned char *blob;
37407     int blob_sz = 0;
37408     int count;
37409     int index;
37410     const char *varname;
37411     char *msg;
37412     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37413     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37414 	goto invalid_blob_argument;
37415     if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
37416 	goto invalid_int_argument;
37417     blob = sqlite3_value_blob (argv[0]);
37418     blob_sz = sqlite3_value_bytes (argv[0]);
37419     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37420 	goto not_an_sql_proc;
37421     index = sqlite3_value_int (argv[1]);
37422     count = gaia_sql_proc_var_count (blob, blob_sz);
37423     if (index < 0 || index >= count)
37424 	goto illegal_index;
37425     varname = gaia_sql_proc_variable (blob, blob_sz, index);
37426     if (varname == NULL)
37427 	sqlite3_result_null (context);
37428     else
37429 	sqlite3_result_text (context, varname, strlen (varname), free);
37430     return;
37431 
37432   invalid_blob_argument:
37433     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37434     sqlite3_result_error (context, msg, -1);
37435     return;
37436 
37437   invalid_int_argument:
37438     msg = "SqlProc exception - illegal Index arg [not an INTEGER].";
37439     sqlite3_result_error (context, msg, -1);
37440     return;
37441 
37442   not_an_sql_proc:
37443     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37444     sqlite3_result_error (context, msg, -1);
37445     return;
37446 
37447   illegal_index:
37448     msg =
37449 	sqlite3_mprintf
37450 	("SqlProc exception - illegal Index (expected to be between 0 and %d).",
37451 	 count - 1);
37452     sqlite3_result_error (context, msg, -1);
37453     sqlite3_free (msg);
37454     return;
37455 }
37456 
37457 static void
fnct_sp_all_variables(sqlite3_context * context,int argc,sqlite3_value ** argv)37458 fnct_sp_all_variables (sqlite3_context * context, int argc,
37459 		       sqlite3_value ** argv)
37460 {
37461 /* SQL function:
37462 / SqlProc_AllVariables(BLOB)
37463 /
37464 / returns:
37465 / a space separated list of Variable Names from a SQL Procedure Object
37466 / raises an exception on invalid arguments
37467 */
37468     const unsigned char *blob;
37469     int blob_sz = 0;
37470     const char *varlist;
37471     const char *msg;
37472     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37473     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37474 	goto invalid_argument;
37475     blob = sqlite3_value_blob (argv[0]);
37476     blob_sz = sqlite3_value_bytes (argv[0]);
37477     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37478 	goto not_an_sql_proc;
37479     varlist = gaia_sql_proc_all_variables (blob, blob_sz);
37480     if (varlist == NULL)
37481 	sqlite3_result_null (context);
37482     else
37483 	sqlite3_result_text (context, varlist, strlen (varlist), sqlite3_free);
37484     return;
37485 
37486   invalid_argument:
37487     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37488     sqlite3_result_error (context, msg, -1);
37489     return;
37490 
37491   not_an_sql_proc:
37492     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37493     sqlite3_result_error (context, msg, -1);
37494     return;
37495 }
37496 
37497 static int
is_decorated_variable_name(const char * name)37498 is_decorated_variable_name (const char *name)
37499 {
37500 /* testing for an already decorated Variable Name */
37501     char mark_start = *name;
37502     char mark_stop = *(name + strlen (name) - 1);
37503     if (mark_start == mark_stop && (mark_start == '@' || mark_start == '$'))
37504 	return 1;
37505     return 0;
37506 }
37507 
37508 static char *
do_encode_blob_value(const unsigned char * blob,int blob_sz)37509 do_encode_blob_value (const unsigned char *blob, int blob_sz)
37510 {
37511 /* encoding a BLOB value as an Hex String */
37512     char *value = sqlite3_malloc ((blob_sz * 2) + 4);
37513     char *p_out = value;
37514     int i;
37515 
37516     *p_out++ = 'x';
37517     *p_out++ = '\'';
37518     for (i = 0; i < blob_sz; i++)
37519       {
37520 	  unsigned char byte = *(blob + i);
37521 	  unsigned char hi = byte / 16;
37522 	  unsigned char lo = byte - (hi * 16);
37523 	  switch (hi)
37524 	    {
37525 	    case 0:
37526 		*p_out++ = '0';
37527 		break;
37528 	    case 1:
37529 		*p_out++ = '1';
37530 		break;
37531 	    case 2:
37532 		*p_out++ = '2';
37533 		break;
37534 	    case 3:
37535 		*p_out++ = '3';
37536 		break;
37537 	    case 4:
37538 		*p_out++ = '4';
37539 		break;
37540 	    case 5:
37541 		*p_out++ = '5';
37542 		break;
37543 	    case 6:
37544 		*p_out++ = '6';
37545 		break;
37546 	    case 7:
37547 		*p_out++ = '7';
37548 		break;
37549 	    case 8:
37550 		*p_out++ = '8';
37551 		break;
37552 	    case 9:
37553 		*p_out++ = '9';
37554 		break;
37555 	    case 10:
37556 		*p_out++ = 'A';
37557 		break;
37558 	    case 11:
37559 		*p_out++ = 'B';
37560 		break;
37561 	    case 12:
37562 		*p_out++ = 'C';
37563 		break;
37564 	    case 13:
37565 		*p_out++ = 'D';
37566 		break;
37567 	    case 14:
37568 		*p_out++ = 'E';
37569 		break;
37570 	    case 15:
37571 		*p_out++ = 'F';
37572 		break;
37573 	    };
37574 	  switch (lo)
37575 	    {
37576 	    case 0:
37577 		*p_out++ = '0';
37578 		break;
37579 	    case 1:
37580 		*p_out++ = '1';
37581 		break;
37582 	    case 2:
37583 		*p_out++ = '2';
37584 		break;
37585 	    case 3:
37586 		*p_out++ = '3';
37587 		break;
37588 	    case 4:
37589 		*p_out++ = '4';
37590 		break;
37591 	    case 5:
37592 		*p_out++ = '5';
37593 		break;
37594 	    case 6:
37595 		*p_out++ = '6';
37596 		break;
37597 	    case 7:
37598 		*p_out++ = '7';
37599 		break;
37600 	    case 8:
37601 		*p_out++ = '8';
37602 		break;
37603 	    case 9:
37604 		*p_out++ = '9';
37605 		break;
37606 	    case 10:
37607 		*p_out++ = 'A';
37608 		break;
37609 	    case 11:
37610 		*p_out++ = 'B';
37611 		break;
37612 	    case 12:
37613 		*p_out++ = 'C';
37614 		break;
37615 	    case 13:
37616 		*p_out++ = 'D';
37617 		break;
37618 	    case 14:
37619 		*p_out++ = 'E';
37620 		break;
37621 	    case 15:
37622 		*p_out++ = 'F';
37623 		break;
37624 	    };
37625       }
37626     *p_out++ = '\'';
37627     *p_out = '\0';
37628     return value;
37629 }
37630 
37631 static void
fnct_sp_var_arg(sqlite3_context * context,int argc,sqlite3_value ** argv)37632 fnct_sp_var_arg (sqlite3_context * context, int argc, sqlite3_value ** argv)
37633 {
37634 /* SQL function:
37635 / SqlProc_VarValue(TEXT var-name, NULL)
37636 / SqlProc_VarValue(TEXT var-name, INT value)
37637 / SqlProc_VarValue(TEXT var-name, DOUBLE value)
37638 / SqlProc_VarValue(TEXT var-name, TEXT value)
37639 / SqlProc_VarValue(TEXT var-name, BLOB value)
37640 /
37641 / returns:
37642 / an SQL Procedure Argument - Variable with Value
37643 / raises an exception on invalid arguments
37644 */
37645     const char *var_name;
37646     const unsigned char *blob;
37647     int blob_sz;
37648     char *var_arg;
37649     const char *msg;
37650     char *value;
37651     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37652     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
37653 	goto invalid_argument;
37654     var_name = (const char *) sqlite3_value_text (argv[0]);
37655     switch (sqlite3_value_type (argv[1]))
37656       {
37657       case SQLITE_NULL:
37658 	  value = sqlite3_mprintf ("%s", "NULL");
37659 	  break;
37660       case SQLITE_INTEGER:
37661 #if defined(_WIN32) && !defined(__MINGW32__)
37662 	  value = sqlite3_mprintf ("%I64d", sqlite3_value_int64 (argv[1]));
37663 #else
37664 	  value = sqlite3_mprintf ("%lld", sqlite3_value_int64 (argv[1]));
37665 #endif
37666 	  break;
37667       case SQLITE_FLOAT:
37668 	  value = sqlite3_mprintf ("%1.10f", sqlite3_value_double (argv[1]));
37669 	  break;
37670       case SQLITE_TEXT:
37671 	  value = sqlite3_mprintf ("%s", sqlite3_value_text (argv[1]));
37672 	  break;
37673       case SQLITE_BLOB:
37674       default:
37675 	  blob = sqlite3_value_blob (argv[1]);
37676 	  blob_sz = sqlite3_value_bytes (argv[1]);
37677 	  value = do_encode_blob_value (blob, blob_sz);
37678 	  break;
37679       };
37680 
37681     if (is_decorated_variable_name (var_name))
37682 	var_arg = sqlite3_mprintf ("%s=%s", var_name, value);
37683     else
37684 	var_arg = sqlite3_mprintf ("@%s@=%s", var_name, value);
37685     sqlite3_result_text (context, var_arg, strlen (var_arg), sqlite3_free);
37686     sqlite3_free (value);
37687     return;
37688 
37689   invalid_argument:
37690     msg = "SqlProc exception - illegal Name arg [not TEXT].";
37691     sqlite3_result_error (context, msg, -1);
37692     return;
37693 }
37694 
37695 static void
fnct_sp_is_valid_var(sqlite3_context * context,int argc,sqlite3_value ** argv)37696 fnct_sp_is_valid_var (sqlite3_context * context, int argc,
37697 		      sqlite3_value ** argv)
37698 {
37699 /* SQL function:
37700 / SqlProc_IsValidVarValue(TEXT)
37701 /
37702 / returns:
37703 / 1 if the argument really is a valid SQL Variable with Value
37704 / 0 if not
37705 */
37706     const char *str;
37707     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37708     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
37709       {
37710 	  sqlite3_result_int (context, 0);
37711 	  return;
37712       }
37713     str = (const char *) sqlite3_value_text (argv[0]);
37714     if (gaia_sql_proc_is_valid_var_value (str))
37715 	sqlite3_result_int (context, 1);
37716     else
37717 	sqlite3_result_int (context, 0);
37718     return;
37719 }
37720 
37721 static void
fnct_sp_raw_sql(sqlite3_context * context,int argc,sqlite3_value ** argv)37722 fnct_sp_raw_sql (sqlite3_context * context, int argc, sqlite3_value ** argv)
37723 {
37724 /* SQL function:
37725 / SqlProc_RawSQL(BLOB)
37726 /
37727 / returns:
37728 / the raw SQL body from a SQL Procedure Object
37729 / raises an exception on invalid arguments
37730 */
37731     const unsigned char *blob;
37732     int blob_sz = 0;
37733     const char *sql;
37734     const char *msg;
37735     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37736     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37737 	goto invalid_argument;
37738     blob = sqlite3_value_blob (argv[0]);
37739     blob_sz = sqlite3_value_bytes (argv[0]);
37740     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37741 	goto not_an_sql_proc;
37742     sql = gaia_sql_proc_raw_sql (blob, blob_sz);
37743     if (sql == NULL)
37744 	sqlite3_result_null (context);
37745     else
37746 	sqlite3_result_text (context, sql, strlen (sql), free);
37747     return;
37748 
37749   invalid_argument:
37750     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37751     sqlite3_result_error (context, msg, -1);
37752     return;
37753 
37754   not_an_sql_proc:
37755     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37756     sqlite3_result_error (context, msg, -1);
37757     return;
37758 }
37759 
37760 static SqlProc_VarListPtr
get_sql_proc_variables(const void * cache,int argc,sqlite3_value ** argv)37761 get_sql_proc_variables (const void *cache, int argc, sqlite3_value ** argv)
37762 {
37763 /* common implementation: creating an SQL Procedure Variables List */
37764     int i;
37765     const char *text;
37766     SqlProc_VarListPtr list = gaia_sql_proc_create_variables ();
37767     for (i = 1; i < argc; i++)
37768       {
37769 	  if (sqlite3_value_type (argv[i]) != SQLITE_TEXT)
37770 	    {
37771 		char *errmsg =
37772 		    sqlite3_mprintf
37773 		    ("Variable Argument #%d is not of the TEXT type.\n",
37774 		     i - 1);
37775 		gaia_sql_proc_set_error (cache, errmsg);
37776 		sqlite3_free (errmsg);
37777 		list->Error = 1;
37778 		goto end;
37779 	    }
37780 	  text = (const char *) sqlite3_value_text (argv[i]);
37781 	  if (!gaia_sql_proc_add_variable (list, text))
37782 	    {
37783 		char *errmsg =
37784 		    sqlite3_mprintf ("Illegal Variable Argument #%d: %s\n",
37785 				     i - 1, text);
37786 		gaia_sql_proc_set_error (cache, errmsg);
37787 		sqlite3_free (errmsg);
37788 		list->Error = 1;
37789 		goto end;
37790 	    }
37791       }
37792   end:
37793     return list;
37794 }
37795 
37796 static void
fnct_sp_cooked_sql(sqlite3_context * context,int argc,sqlite3_value ** argv)37797 fnct_sp_cooked_sql (sqlite3_context * context, int argc, sqlite3_value ** argv)
37798 {
37799 /* SQL function:
37800 / SqlProc_CookedSQL(BLOB [, arg1 TEXT, arg2 TEXT, ... argN TEXT] )
37801 /
37802 / returns:
37803 / the cooked SQL body from a SQL Procedure Object
37804 / raises an exception on invalid arguments
37805 */
37806     const unsigned char *blob;
37807     int blob_sz = 0;
37808     char *sql;
37809     const char *msg;
37810     SqlProc_VarListPtr variables = NULL;
37811     sqlite3 *sqlite = sqlite3_context_db_handle (context);
37812     struct splite_internal_cache *cache = sqlite3_user_data (context);
37813     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37814     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37815 	goto invalid_blob_argument;
37816     blob = sqlite3_value_blob (argv[0]);
37817     blob_sz = sqlite3_value_bytes (argv[0]);
37818     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37819 	goto not_an_sql_proc;
37820 
37821 /* retrieving the List of Variables with Values */
37822     variables = get_sql_proc_variables (cache, argc, argv);
37823     if (variables == NULL)
37824 	goto err_variables;
37825     if (variables->Error)
37826 	goto illegal_variables;
37827 
37828 /* replacing Variables */
37829     if (!gaia_sql_proc_cooked_sql
37830 	(sqlite, cache, blob, blob_sz, variables, &sql))
37831 	goto cooking_error;
37832     if (sql == NULL)
37833       {
37834 	  sqlite3_result_null (context);
37835 	  goto done;
37836       }
37837     sqlite3_result_text (context, sql, strlen (sql), free);
37838 
37839   done:
37840     gaia_sql_proc_destroy_variables (variables);
37841     return;
37842 
37843   invalid_blob_argument:
37844     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37845     sqlite3_result_error (context, msg, -1);
37846     return;
37847 
37848   not_an_sql_proc:
37849     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37850     sqlite3_result_error (context, msg, -1);
37851     return;
37852 
37853   err_variables:
37854     if (variables != NULL)
37855 	gaia_sql_proc_destroy_variables (variables);
37856     msg = "SqlProc exception - unable to get a List of Variables with Values.";
37857     sqlite3_result_error (context, msg, -1);
37858     return;
37859 
37860   illegal_variables:
37861     if (variables != NULL)
37862 	gaia_sql_proc_destroy_variables (variables);
37863     msg =
37864 	"SqlProc exception - the List of Variables with Values contains illegal items.";
37865     sqlite3_result_error (context, msg, -1);
37866     return;
37867 
37868   cooking_error:
37869     if (variables != NULL)
37870 	gaia_sql_proc_destroy_variables (variables);
37871     msg = "SqlProc exception - unable to create a Cooked SQL Body.";
37872     sqlite3_result_error (context, msg, -1);
37873     return;
37874 }
37875 
37876 static void
fnct_sp_execute(sqlite3_context * context,int argc,sqlite3_value ** argv)37877 fnct_sp_execute (sqlite3_context * context, int argc, sqlite3_value ** argv)
37878 {
37879 /* SQL function:
37880 / SqlProc_Execute(BLOB [, arg1 TEXT, arg2 TEXT, ... argN TEXT] )
37881 /
37882 / returns:
37883 / the arbitrary valure set by SqlProc_Return() on succes
37884 / raises an exception on invalid arguments or errors
37885 */
37886     const unsigned char *blob;
37887     int blob_sz = 0;
37888     char *sql;
37889     const char *msg;
37890     SqlProc_VarListPtr variables = NULL;
37891     sqlite3 *sqlite = sqlite3_context_db_handle (context);
37892     struct splite_internal_cache *cache = sqlite3_user_data (context);
37893     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
37894     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
37895 	goto invalid_blob_argument;
37896     blob = sqlite3_value_blob (argv[0]);
37897     blob_sz = sqlite3_value_bytes (argv[0]);
37898     if (!gaia_sql_proc_is_valid (blob, blob_sz))
37899 	goto not_an_sql_proc;
37900 
37901 /* retrieving the List of Variables with Values */
37902     variables = get_sql_proc_variables (cache, argc, argv);
37903     if (variables == NULL)
37904 	goto err_variables;
37905     if (variables->Error)
37906 	goto illegal_variables;
37907 
37908 /* replacing Variables */
37909     if (!gaia_sql_proc_cooked_sql
37910 	(sqlite, cache, blob, blob_sz, variables, &sql))
37911 	goto cooking_error;
37912 
37913 /* executing the SQL Procedure */
37914     if (!gaia_sql_proc_execute (sqlite, cache, sql))
37915 	goto sql_error;
37916     if (cache != NULL)
37917       {
37918 	  if (cache->SqlProcRetValue == NULL)
37919 	      sqlite3_result_null (context);
37920 	  else
37921 	    {
37922 		/* setting the Return Value declared from SqlProc_Return() */
37923 		struct gaia_variant_value *retval = cache->SqlProcRetValue;
37924 		switch (retval->dataType)
37925 		  {
37926 		  case SQLITE_INTEGER:
37927 		      sqlite3_result_int64 (context, retval->intValue);
37928 		      break;
37929 		  case SQLITE_FLOAT:
37930 		      sqlite3_result_double (context, retval->dblValue);
37931 		      break;
37932 		  case SQLITE_TEXT:
37933 		      sqlite3_result_text (context, retval->textValue,
37934 					   retval->size, SQLITE_STATIC);
37935 		      break;
37936 		  case SQLITE_BLOB:
37937 		      sqlite3_result_blob (context, retval->blobValue,
37938 					   retval->size, SQLITE_STATIC);
37939 		      break;
37940 		  case SQLITE_NULL:
37941 		  default:
37942 		      sqlite3_result_null (context);
37943 		      break;
37944 
37945 		  };
37946 	    }
37947       }
37948     else
37949 	sqlite3_result_null (context);
37950     if (sql != NULL)
37951 	free (sql);
37952     gaia_sql_proc_destroy_variables (variables);
37953     return;
37954 
37955   invalid_blob_argument:
37956     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
37957     sqlite3_result_error (context, msg, -1);
37958     return;
37959 
37960   not_an_sql_proc:
37961     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
37962     sqlite3_result_error (context, msg, -1);
37963     return;
37964 
37965   err_variables:
37966     msg = "SqlProc exception - unable to get a List of Variables with Values.";
37967     sqlite3_result_error (context, msg, -1);
37968     return;
37969 
37970   illegal_variables:
37971     if (variables != NULL)
37972 	gaia_sql_proc_destroy_variables (variables);
37973     msg =
37974 	"SqlProc exception - the List of Variables with Values contains illegal items.";
37975     sqlite3_result_error (context, msg, -1);
37976     return;
37977 
37978   cooking_error:
37979     if (variables != NULL)
37980 	gaia_sql_proc_destroy_variables (variables);
37981     msg = "SqlProc exception - unable to create a Cooked SQL Body.";
37982     sqlite3_result_error (context, msg, -1);
37983     return;
37984 
37985   sql_error:
37986     if (variables != NULL)
37987 	gaia_sql_proc_destroy_variables (variables);
37988     if (sql != NULL)
37989 	free (sql);
37990     msg = "SqlProc exception - a fatal SQL error was encountered.";
37991     sqlite3_result_error (context, msg, -1);
37992     return;
37993 }
37994 
37995 static void
fnct_sp_execute_loop(sqlite3_context * context,int argc,sqlite3_value ** argv)37996 fnct_sp_execute_loop (sqlite3_context * context, int argc,
37997 		      sqlite3_value ** argv)
37998 {
37999 /* SQL function:
38000 / SqlProc_ExecuteLoop(BLOB [, arg1 TEXT, arg2 TEXT, ... argN TEXT] )
38001 /
38002 / returns:
38003 / 1 on succes
38004 / raises an exception on invalid arguments or errors
38005 */
38006     const unsigned char *blob;
38007     int blob_sz = 0;
38008     char *sql;
38009     const char *msg;
38010     SqlProc_VarListPtr variables = NULL;
38011     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38012     struct splite_internal_cache *cache = sqlite3_user_data (context);
38013     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38014 
38015     while (1)
38016       {
38017 	  /* never ending loop */
38018 	  if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
38019 	      goto invalid_blob_argument;
38020 	  blob = sqlite3_value_blob (argv[0]);
38021 	  blob_sz = sqlite3_value_bytes (argv[0]);
38022 	  if (!gaia_sql_proc_is_valid (blob, blob_sz))
38023 	      goto not_an_sql_proc;
38024 
38025 	  /* retrieving the List of Variables with Values */
38026 	  variables = get_sql_proc_variables (cache, argc, argv);
38027 	  if (variables == NULL)
38028 	      goto err_variables;
38029 	  if (variables->Error)
38030 	      goto illegal_variables;
38031 
38032 	  /* replacing Variables */
38033 	  if (!gaia_sql_proc_cooked_sql
38034 	      (sqlite, cache, blob, blob_sz, variables, &sql))
38035 	      goto cooking_error;
38036 
38037 	  /* executing the SQL Procedure */
38038 	  if (!gaia_sql_proc_execute (sqlite, cache, sql))
38039 	      goto sql_error;
38040 	  if (cache != NULL)
38041 	    {
38042 		if (cache->SqlProcRetValue == NULL)
38043 		    break;	/* stopping the loop */
38044 		else
38045 		  {
38046 		      /* retrieving the Return Value declared from SqlProc_Return() */
38047 		      struct gaia_variant_value *retval =
38048 			  cache->SqlProcRetValue;
38049 		      if (retval->dataType == SQLITE_INTEGER)
38050 			{
38051 			    if (retval->intValue <= 0)
38052 				break;	/* stopping the loop */
38053 			}
38054 		  }
38055 	    }
38056 	  if (sql != NULL)
38057 	      free (sql);
38058 	  gaia_sql_proc_destroy_variables (variables);
38059       }
38060 
38061     sqlite3_result_int (context, 1);
38062     if (sql != NULL)
38063 	free (sql);
38064     gaia_sql_proc_destroy_variables (variables);
38065     return;
38066 
38067   invalid_blob_argument:
38068     msg = "SqlProc exception - illegal SQL Procedure arg [not a BLOB].";
38069     sqlite3_result_error (context, msg, -1);
38070     return;
38071 
38072   not_an_sql_proc:
38073     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
38074     sqlite3_result_error (context, msg, -1);
38075     return;
38076 
38077   err_variables:
38078     msg = "SqlProc exception - unable to get a List of Variables with Values.";
38079     sqlite3_result_error (context, msg, -1);
38080     return;
38081 
38082   illegal_variables:
38083     if (variables != NULL)
38084 	gaia_sql_proc_destroy_variables (variables);
38085     msg =
38086 	"SqlProc exception - the List of Variables with Values contains illegal items.";
38087     sqlite3_result_error (context, msg, -1);
38088     return;
38089 
38090   cooking_error:
38091     if (variables != NULL)
38092 	gaia_sql_proc_destroy_variables (variables);
38093     msg = "SqlProc exception - unable to create a Cooked SQL Body.";
38094     sqlite3_result_error (context, msg, -1);
38095     return;
38096 
38097   sql_error:
38098     if (variables != NULL)
38099 	gaia_sql_proc_destroy_variables (variables);
38100     if (sql != NULL)
38101 	free (sql);
38102     msg = "SqlProc exception - a fatal SQL error was encountered.";
38103     sqlite3_result_error (context, msg, -1);
38104     return;
38105 }
38106 
38107 static void
fnct_sp_return(sqlite3_context * context,int argc,sqlite3_value ** argv)38108 fnct_sp_return (sqlite3_context * context, int argc, sqlite3_value ** argv)
38109 {
38110 /* SQL function:
38111 / SqlProc_Return( NULL )
38112 / SqlProc_Return( value INTEGER )
38113 / SqlProc_Return( value DOUBLE )
38114 / SqlProc_Return( value TEXT )
38115 / SqlProc_Return( value BLOB )
38116 / StoredProc_Return( NULL )
38117 / StoredProc_Return( value INTEGER )
38118 / StoredProc_Return( value DOUBLE )
38119 / StoredProc_Return( value TEXT )
38120 / StoredProc_Return( value BLOB )
38121 /
38122 / returns:
38123 / 1 on succes
38124 / raises an exception on invalid arguments or errors
38125 */
38126     const char *txt;
38127     const unsigned char *blob;
38128     int size;
38129     const char *msg;
38130     struct splite_internal_cache *cache = sqlite3_user_data (context);
38131     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38132     if (cache == NULL)
38133 	goto no_cache;
38134 
38135 /* registrering an EXIT request */
38136     cache->SqlProcContinue = 0;
38137 
38138 /* registrering a Return Value */
38139     switch (sqlite3_value_type (argv[0]))
38140       {
38141       case SQLITE_INTEGER:
38142 	  gaia_set_variant_int64 (cache->SqlProcRetValue,
38143 				  sqlite3_value_int64 (argv[0]));
38144 	  break;
38145       case SQLITE_FLOAT:
38146 	  gaia_set_variant_double (cache->SqlProcRetValue,
38147 				   sqlite3_value_double (argv[0]));
38148 	  break;
38149       case SQLITE_TEXT:
38150 	  txt = (const char *) sqlite3_value_text (argv[0]);
38151 	  size = sqlite3_value_bytes (argv[0]);
38152 	  if (!gaia_set_variant_text (cache->SqlProcRetValue, txt, size))
38153 	      goto insuff_memory;
38154 	  break;
38155       case SQLITE_BLOB:
38156 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
38157 	  size = sqlite3_value_bytes (argv[0]);
38158 	  if (!gaia_set_variant_blob (cache->SqlProcRetValue, blob, size))
38159 	      goto insuff_memory;
38160 	  break;
38161       case SQLITE_NULL:
38162       default:
38163 	  gaia_set_variant_null (cache->SqlProcRetValue);
38164 	  break;
38165       };
38166     sqlite3_result_int (context, 1);
38167     return;
38168 
38169   no_cache:
38170     msg = "SqlProc_Return exception - unable to find a Connection Cache.";
38171     sqlite3_result_error (context, msg, -1);
38172     return;
38173 
38174   insuff_memory:
38175     msg = "SqlProc_Return exception - Insuficient Memory.";
38176     sqlite3_result_error (context, msg, -1);
38177     return;
38178 }
38179 
38180 static void
fnct_sp_create_tables(sqlite3_context * context,int argc,sqlite3_value ** argv)38181 fnct_sp_create_tables (sqlite3_context * context, int argc,
38182 		       sqlite3_value ** argv)
38183 {
38184 /* SQL function:
38185 / StoredProc_CreateTables()
38186 /
38187 / will attempt to create the Stored Procedures tables if not
38188 / already existing
38189 /
38190 / returns:
38191 / 1 on success, 0 on failure
38192 */
38193     int ret;
38194     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38195     void *data = sqlite3_user_data (context);
38196     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38197     ret = gaia_stored_proc_create_tables (sqlite, data);
38198     sqlite3_result_int (context, ret);
38199 }
38200 
38201 static void
fnct_sp_register(sqlite3_context * context,int argc,sqlite3_value ** argv)38202 fnct_sp_register (sqlite3_context * context, int argc, sqlite3_value ** argv)
38203 {
38204 /* SQL function:
38205 / StoredProc_Register(name TEXT, title TEXT, sql_body BLOB)
38206 /
38207 / returns:
38208 / 1 on success, 0 on failure
38209 / raises an exception on invalid arguments
38210 */
38211     const char *name;
38212     const char *title;
38213     const unsigned char *blob;
38214     int blob_sz = 0;
38215     const char *msg;
38216     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38217     struct splite_internal_cache *cache = sqlite3_user_data (context);
38218     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38219     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38220 	goto invalid_argument_1;
38221     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
38222 	goto invalid_argument_2;
38223     if (sqlite3_value_type (argv[2]) != SQLITE_BLOB)
38224 	goto invalid_argument_3;
38225     name = (const char *) sqlite3_value_text (argv[0]);
38226     title = (const char *) sqlite3_value_text (argv[1]);
38227     blob = sqlite3_value_blob (argv[2]);
38228     blob_sz = sqlite3_value_bytes (argv[2]);
38229     if (!gaia_sql_proc_is_valid (blob, blob_sz))
38230 	goto not_an_sql_proc;
38231     if (gaia_stored_proc_store (sqlite, cache, name, title, blob, blob_sz))
38232 	sqlite3_result_int (context, 1);
38233     else
38234 	sqlite3_result_int (context, 0);
38235     return;
38236 
38237   invalid_argument_1:
38238     msg =
38239 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38240     sqlite3_result_error (context, msg, -1);
38241     return;
38242 
38243   invalid_argument_2:
38244     msg =
38245 	"StoredProc exception - illegal Stored Procedure Title [not a TEXT string].";
38246     sqlite3_result_error (context, msg, -1);
38247     return;
38248 
38249   invalid_argument_3:
38250     msg = "StoredProc exception - illegal Stored Procedure Body [not a BLOB].";
38251     sqlite3_result_error (context, msg, -1);
38252     return;
38253 
38254   not_an_sql_proc:
38255     msg = "StoredProc exception - invalid SQL Procedure BLOB.";
38256     sqlite3_result_error (context, msg, -1);
38257     return;
38258 }
38259 
38260 static void
fnct_sp_get(sqlite3_context * context,int argc,sqlite3_value ** argv)38261 fnct_sp_get (sqlite3_context * context, int argc, sqlite3_value ** argv)
38262 {
38263 /* SQL function:
38264 / StoredProc_Get(name TEXT)
38265 /
38266 / returns:
38267 / a SQL Procedure BLOB Object
38268 / raises an exception on invalid arguments
38269 */
38270     const char *name;
38271     unsigned char *blob;
38272     int blob_sz = 0;
38273     const char *msg;
38274     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38275     struct splite_internal_cache *cache = sqlite3_user_data (context);
38276     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38277     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38278 	goto invalid_argument;
38279     name = (const char *) sqlite3_value_text (argv[0]);
38280     if (gaia_stored_proc_fetch (sqlite, cache, name, &blob, &blob_sz))
38281 	sqlite3_result_blob (context, blob, blob_sz, free);
38282     else
38283 	sqlite3_result_null (context);
38284     return;
38285 
38286   invalid_argument:
38287     msg =
38288 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38289     sqlite3_result_error (context, msg, -1);
38290     return;
38291 }
38292 
38293 static void
fnct_sp_delete(sqlite3_context * context,int argc,sqlite3_value ** argv)38294 fnct_sp_delete (sqlite3_context * context, int argc, sqlite3_value ** argv)
38295 {
38296 /* SQL function:
38297 / StoredProc_Delete(name TEXT)
38298 /
38299 / returns:
38300 / 1 on success, 0 on failure
38301 / raises an exception on invalid arguments
38302 */
38303     const char *name;
38304     const char *msg;
38305     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38306     struct splite_internal_cache *cache = sqlite3_user_data (context);
38307     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38308     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38309 	goto invalid_argument;
38310     name = (const char *) sqlite3_value_text (argv[0]);
38311     if (gaia_stored_proc_delete (sqlite, cache, name))
38312 	sqlite3_result_int (context, 1);
38313     else
38314 	sqlite3_result_int (context, 0);
38315     return;
38316 
38317   invalid_argument:
38318     msg =
38319 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38320     sqlite3_result_error (context, msg, -1);
38321     return;
38322 }
38323 
38324 static void
fnct_sp_update_title(sqlite3_context * context,int argc,sqlite3_value ** argv)38325 fnct_sp_update_title (sqlite3_context * context, int argc,
38326 		      sqlite3_value ** argv)
38327 {
38328 /* SQL function:
38329 / StoredProc_UpdateTitle(name TEXT, title TEXT)
38330 /
38331 / returns:
38332 / 1 on success, 0 on failure
38333 / raises an exception on invalid arguments
38334 */
38335     const char *name;
38336     const char *title;
38337     const char *msg;
38338     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38339     struct splite_internal_cache *cache = sqlite3_user_data (context);
38340     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38341     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38342 	goto invalid_argument_1;
38343     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
38344 	goto invalid_argument_2;
38345     name = (const char *) sqlite3_value_text (argv[0]);
38346     title = (const char *) sqlite3_value_text (argv[1]);
38347     if (gaia_stored_proc_update_title (sqlite, cache, name, title))
38348 	sqlite3_result_int (context, 1);
38349     else
38350 	sqlite3_result_int (context, 0);
38351     return;
38352 
38353   invalid_argument_1:
38354     msg =
38355 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38356     sqlite3_result_error (context, msg, -1);
38357     return;
38358 
38359   invalid_argument_2:
38360     msg =
38361 	"StoredProc exception - illegal Stored Procedure Title [not a TEXT string].";
38362     sqlite3_result_error (context, msg, -1);
38363     return;
38364 }
38365 
38366 static void
fnct_sp_update_sql(sqlite3_context * context,int argc,sqlite3_value ** argv)38367 fnct_sp_update_sql (sqlite3_context * context, int argc, sqlite3_value ** argv)
38368 {
38369 /* SQL function:
38370 / StoredProc_UpdateSqlBody(name TEXT, sql BLOB)
38371 /
38372 / returns:
38373 / 1 on success, 0 on failure
38374 / raises an exception on invalid arguments
38375 */
38376     const char *name;
38377     const unsigned char *blob;
38378     int blob_sz = 0;
38379     const char *msg;
38380     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38381     struct splite_internal_cache *cache = sqlite3_user_data (context);
38382     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38383     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38384 	goto invalid_argument_1;
38385     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
38386 	goto invalid_argument_2;
38387     name = (const char *) sqlite3_value_text (argv[0]);
38388     blob = sqlite3_value_blob (argv[1]);
38389     blob_sz = sqlite3_value_bytes (argv[1]);
38390     if (!gaia_sql_proc_is_valid (blob, blob_sz))
38391 	goto not_an_sql_proc;
38392     if (gaia_stored_proc_update_sql (sqlite, cache, name, blob, blob_sz))
38393 	sqlite3_result_int (context, 1);
38394     else
38395 	sqlite3_result_int (context, 0);
38396     return;
38397 
38398   invalid_argument_1:
38399     msg =
38400 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38401     sqlite3_result_error (context, msg, -1);
38402     return;
38403 
38404   invalid_argument_2:
38405     msg = "StoredProc exception - illegal Stored Procedure Body [not a BLOB].";
38406     sqlite3_result_error (context, msg, -1);
38407     return;
38408 
38409   not_an_sql_proc:
38410     msg = "StoredProc exception - invalid SQL Procedure BLOB.";
38411     sqlite3_result_error (context, msg, -1);
38412     return;
38413 }
38414 
38415 static void
fnct_sp_stored_execute(sqlite3_context * context,int argc,sqlite3_value ** argv)38416 fnct_sp_stored_execute (sqlite3_context * context, int argc,
38417 			sqlite3_value ** argv)
38418 {
38419 /* SQL function:
38420 / StoredProc_Execute(TEXT [, arg1 TEXT, arg2 TEXT, ... argN TEXT] )
38421 /
38422 / returns:
38423 / the arbitrary value set by StoredProcedue_Return() on succes
38424 / raises an exception on invalid arguments or errors
38425 */
38426     const char *name;
38427     unsigned char *blob;
38428     int blob_sz = 0;
38429     char *sql;
38430     const char *msg;
38431     char *message;
38432     SqlProc_VarListPtr variables = NULL;
38433     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38434     struct splite_internal_cache *cache = sqlite3_user_data (context);
38435     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38436     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38437 	goto invalid_name_argument;
38438     name = (const char *) sqlite3_value_text (argv[0]);
38439     if (!gaia_stored_proc_fetch (sqlite, cache, name, &blob, &blob_sz))
38440 	goto invalid_stored_procedure;
38441     if (!gaia_sql_proc_is_valid (blob, blob_sz))
38442 	goto not_an_sql_proc;
38443 
38444 /* retrieving the List of Variables with Values */
38445     variables = get_sql_proc_variables (cache, argc, argv);
38446     if (variables == NULL)
38447 	goto err_variables;
38448     if (variables->Error)
38449 	goto illegal_variables;
38450 
38451 /* replacing Variables */
38452     if (!gaia_sql_proc_cooked_sql
38453 	(sqlite, cache, blob, blob_sz, variables, &sql))
38454 	goto cooking_error;
38455     free (blob);
38456 
38457 /* executing the SQL Procedure */
38458     if (!gaia_sql_proc_execute (sqlite, cache, sql))
38459 	goto sql_error;
38460     if (cache != NULL)
38461       {
38462 	  if (cache->SqlProcRetValue == NULL)
38463 	      sqlite3_result_null (context);
38464 	  else
38465 	    {
38466 		/* setting the Return Value declared from StoredProc_Return() */
38467 		struct gaia_variant_value *retval = cache->SqlProcRetValue;
38468 		switch (retval->dataType)
38469 		  {
38470 		  case SQLITE_INTEGER:
38471 		      sqlite3_result_int64 (context, retval->intValue);
38472 		      break;
38473 		  case SQLITE_FLOAT:
38474 		      sqlite3_result_double (context, retval->dblValue);
38475 		      break;
38476 		  case SQLITE_TEXT:
38477 		      sqlite3_result_text (context, retval->textValue,
38478 					   retval->size, SQLITE_STATIC);
38479 		      break;
38480 		  case SQLITE_BLOB:
38481 		      sqlite3_result_blob (context, retval->blobValue,
38482 					   retval->size, SQLITE_STATIC);
38483 		      break;
38484 		  case SQLITE_NULL:
38485 		  default:
38486 		      sqlite3_result_null (context);
38487 		      break;
38488 
38489 		  };
38490 	    }
38491       }
38492     else
38493 	sqlite3_result_null (context);
38494     if (sql != NULL)
38495 	free (sql);
38496     gaia_sql_proc_destroy_variables (variables);
38497     return;
38498 
38499   invalid_name_argument:
38500     msg =
38501 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38502     sqlite3_result_error (context, msg, -1);
38503     return;
38504 
38505   invalid_stored_procedure:
38506     message =
38507 	sqlite3_mprintf
38508 	("StoredProc exception - unable to retrieve a Stored Procedure named \"%s\".",
38509 	 name);
38510     sqlite3_result_error (context, message, -1);
38511     sqlite3_free (message);
38512     return;
38513 
38514   not_an_sql_proc:
38515     free (blob);
38516     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
38517     sqlite3_result_error (context, msg, -1);
38518     return;
38519 
38520   err_variables:
38521     free (blob);
38522     msg = "SqlProc exception - unable to get a List of Variables with Values.";
38523     sqlite3_result_error (context, msg, -1);
38524     return;
38525 
38526   illegal_variables:
38527     free (blob);
38528     gaia_sql_proc_destroy_variables (variables);
38529     msg =
38530 	"SqlProc exception - the List of Variables with Values contains illegal items.";
38531     sqlite3_result_error (context, msg, -1);
38532     return;
38533 
38534   cooking_error:
38535     gaia_sql_proc_destroy_variables (variables);
38536     free (blob);
38537     msg = "SqlProc exception - unable to create a Cooked SQL Body.";
38538     sqlite3_result_error (context, msg, -1);
38539     return;
38540 
38541   sql_error:
38542     if (sql != NULL)
38543 	free (sql);
38544     gaia_sql_proc_destroy_variables (variables);
38545     msg = "SqlProc exception - a fatal SQL error was encountered.";
38546     sqlite3_result_error (context, msg, -1);
38547     return;
38548 }
38549 
38550 static void
fnct_sp_stored_execute_loop(sqlite3_context * context,int argc,sqlite3_value ** argv)38551 fnct_sp_stored_execute_loop (sqlite3_context * context, int argc,
38552 			     sqlite3_value ** argv)
38553 {
38554 /* SQL function:
38555 / StoredProc_ExecuteLoop(TEXT [, arg1 TEXT, arg2 TEXT, ... argN TEXT] )
38556 /
38557 / returns:
38558 / 1 on succes
38559 / raises an exception on invalid arguments or errors
38560 */
38561     const char *name;
38562     unsigned char *blob;
38563     int blob_sz = 0;
38564     char *sql;
38565     const char *msg;
38566     char *message;
38567     SqlProc_VarListPtr variables = NULL;
38568     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38569     struct splite_internal_cache *cache = sqlite3_user_data (context);
38570     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38571 
38572     while (1)
38573       {
38574 	  /* never ending loop */
38575 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38576 	      goto invalid_name_argument;
38577 	  name = (const char *) sqlite3_value_text (argv[0]);
38578 	  if (!gaia_stored_proc_fetch (sqlite, cache, name, &blob, &blob_sz))
38579 	      goto invalid_stored_procedure;
38580 	  if (!gaia_sql_proc_is_valid (blob, blob_sz))
38581 	      goto not_an_sql_proc;
38582 
38583 	  /* retrieving the List of Variables with Values */
38584 	  variables = get_sql_proc_variables (cache, argc, argv);
38585 	  if (variables == NULL)
38586 	      goto err_variables;
38587 	  if (variables->Error)
38588 	      goto illegal_variables;
38589 
38590 	  /* replacing Variables */
38591 	  if (!gaia_sql_proc_cooked_sql
38592 	      (sqlite, cache, blob, blob_sz, variables, &sql))
38593 	      goto cooking_error;
38594 	  free (blob);
38595 
38596 	  /* executing the SQL Procedure */
38597 	  if (!gaia_sql_proc_execute (sqlite, cache, sql))
38598 	      goto sql_error;
38599 	  if (cache != NULL)
38600 	    {
38601 		if (cache->SqlProcRetValue == NULL)
38602 		    break;	/* stopping the loop */
38603 		else
38604 		  {
38605 		      /* retrieving the Return Value declared from SqlProc_Return() */
38606 		      struct gaia_variant_value *retval =
38607 			  cache->SqlProcRetValue;
38608 		      if (retval->dataType == SQLITE_INTEGER)
38609 			{
38610 			    if (retval->intValue <= 0)
38611 				break;	/* stopping the loop */
38612 			}
38613 		  }
38614 	    }
38615 	  if (sql != NULL)
38616 	      free (sql);
38617 	  gaia_sql_proc_destroy_variables (variables);
38618       }
38619 
38620     sqlite3_result_int (context, 1);
38621     if (sql != NULL)
38622 	free (sql);
38623     gaia_sql_proc_destroy_variables (variables);
38624     return;
38625 
38626   invalid_name_argument:
38627     msg =
38628 	"StoredProc exception - illegal Stored Procedure Name [not a TEXT string].";
38629     sqlite3_result_error (context, msg, -1);
38630     return;
38631 
38632   invalid_stored_procedure:
38633     message =
38634 	sqlite3_mprintf
38635 	("StoredProc exception - unable to retrieve a Stored Procedure named \"%s\".",
38636 	 name);
38637     sqlite3_result_error (context, message, -1);
38638     sqlite3_free (message);
38639     return;
38640 
38641   not_an_sql_proc:
38642     free (blob);
38643     msg = "SqlProc exception - invalid SQL Procedure BLOB.";
38644     sqlite3_result_error (context, msg, -1);
38645     return;
38646 
38647   err_variables:
38648     free (blob);
38649     msg = "SqlProc exception - unable to get a List of Variables with Values.";
38650     sqlite3_result_error (context, msg, -1);
38651     return;
38652 
38653   illegal_variables:
38654     free (blob);
38655     gaia_sql_proc_destroy_variables (variables);
38656     msg =
38657 	"SqlProc exception - the List of Variables with Values contains illegal items.";
38658     sqlite3_result_error (context, msg, -1);
38659     return;
38660 
38661   cooking_error:
38662     gaia_sql_proc_destroy_variables (variables);
38663     free (blob);
38664     msg = "SqlProc exception - unable to create a Cooked SQL Body.";
38665     sqlite3_result_error (context, msg, -1);
38666     return;
38667 
38668   sql_error:
38669     if (sql != NULL)
38670 	free (sql);
38671     gaia_sql_proc_destroy_variables (variables);
38672     msg = "SqlProc exception - a fatal SQL error was encountered.";
38673     sqlite3_result_error (context, msg, -1);
38674     return;
38675 }
38676 
38677 static void
fnct_sp_var_register(sqlite3_context * context,int argc,sqlite3_value ** argv)38678 fnct_sp_var_register (sqlite3_context * context, int argc,
38679 		      sqlite3_value ** argv)
38680 {
38681 /* SQL function:
38682 / StoredVar_Register(name TEXT, title TEXT, value NULL)
38683 / StoredVar_Register(name TEXT, title TEXT, value INT)
38684 / StoredVar_Register(name TEXT, title TEXT, value DOUBLE)
38685 / StoredVar_Register(name TEXT, title TEXT, value TEXT)
38686 / StoredVar_Register(name TEXT, title TEXT, value BLOB)
38687 /
38688 / returns:
38689 / 1 on success, 0 on failure
38690 / raises an exception on invalid arguments
38691 */
38692     const char *name;
38693     const char *title;
38694     const unsigned char *blob;
38695     int blob_sz;
38696     char *value = NULL;
38697     const char *msg;
38698     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38699     struct splite_internal_cache *cache = sqlite3_user_data (context);
38700     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38701     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38702 	goto invalid_argument_1;
38703     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
38704 	goto invalid_argument_2;
38705     name = (const char *) sqlite3_value_text (argv[0]);
38706     title = (const char *) sqlite3_value_text (argv[1]);
38707     switch (sqlite3_value_type (argv[2]))
38708       {
38709       case SQLITE_NULL:
38710 	  value = sqlite3_mprintf ("%s", "NULL");
38711 	  break;
38712       case SQLITE_INTEGER:
38713 	  value = sqlite3_mprintf ("%d", sqlite3_value_int (argv[2]));
38714 	  break;
38715       case SQLITE_FLOAT:
38716 	  value = sqlite3_mprintf ("%1.10f", sqlite3_value_double (argv[2]));
38717 	  break;
38718       case SQLITE_TEXT:
38719 	  value = sqlite3_mprintf ("%s", sqlite3_value_text (argv[2]));
38720 	  break;
38721       case SQLITE_BLOB:
38722       default:
38723 	  blob = sqlite3_value_blob (argv[2]);
38724 	  blob_sz = sqlite3_value_bytes (argv[2]);
38725 	  value = do_encode_blob_value (blob, blob_sz);
38726 	  break;
38727       };
38728     if (gaia_stored_var_store (sqlite, cache, name, title, value))
38729 	sqlite3_result_int (context, 1);
38730     else
38731 	sqlite3_result_int (context, 0);
38732     if (value != NULL)
38733 	sqlite3_free (value);
38734     return;
38735 
38736   invalid_argument_1:
38737     msg =
38738 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38739     sqlite3_result_error (context, msg, -1);
38740     return;
38741 
38742   invalid_argument_2:
38743     msg =
38744 	"StoredVar exception - illegal Stored Variable Title [not a TEXT string].";
38745     sqlite3_result_error (context, msg, -1);
38746     return;
38747 }
38748 
38749 static void
fnct_sp_var_get(sqlite3_context * context,int argc,sqlite3_value ** argv)38750 fnct_sp_var_get (sqlite3_context * context, int argc, sqlite3_value ** argv)
38751 {
38752 /* SQL function:
38753 / StoredVar_Get(name TEXT)
38754 /
38755 / returns:
38756 / a Variable with Value string
38757 / raises an exception on invalid arguments
38758 */
38759     const char *name;
38760     char *value;
38761     const char *msg;
38762     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38763     struct splite_internal_cache *cache = sqlite3_user_data (context);
38764     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38765     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38766 	goto invalid_argument;
38767     name = (const char *) sqlite3_value_text (argv[0]);
38768     if (!gaia_stored_var_fetch (sqlite, cache, name, 1, &value))
38769 	sqlite3_result_null (context);
38770     else
38771 	sqlite3_result_text (context, value, strlen (value), free);
38772     return;
38773 
38774   invalid_argument:
38775     msg =
38776 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38777     sqlite3_result_error (context, msg, -1);
38778     return;
38779 }
38780 
38781 static void
fnct_sp_var_get_value(sqlite3_context * context,int argc,sqlite3_value ** argv)38782 fnct_sp_var_get_value (sqlite3_context * context, int argc,
38783 		       sqlite3_value ** argv)
38784 {
38785 /* SQL function:
38786 / StoredVar_GetValue(name TEXT)
38787 /
38788 / returns:
38789 / a Variable with Value string
38790 / raises an exception on invalid arguments
38791 */
38792     const char *name;
38793     char *value;
38794     const char *msg;
38795     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38796     struct splite_internal_cache *cache = sqlite3_user_data (context);
38797     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38798     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38799 	goto invalid_argument;
38800     name = (const char *) sqlite3_value_text (argv[0]);
38801     if (!gaia_stored_var_fetch (sqlite, cache, name, 0, &value))
38802 	sqlite3_result_null (context);
38803     else
38804 	sqlite3_result_text (context, value, strlen (value), free);
38805     return;
38806 
38807   invalid_argument:
38808     msg =
38809 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38810     sqlite3_result_error (context, msg, -1);
38811     return;
38812 }
38813 
38814 static void
fnct_sp_var_delete(sqlite3_context * context,int argc,sqlite3_value ** argv)38815 fnct_sp_var_delete (sqlite3_context * context, int argc, sqlite3_value ** argv)
38816 {
38817 /* SQL function:
38818 / StoredVar_Delete(name TEXT)
38819 /
38820 / returns:
38821 / 1 on success, 0 on failure
38822 / raises an exception on invalid arguments
38823 */
38824     const char *name;
38825     const char *msg;
38826     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38827     struct splite_internal_cache *cache = sqlite3_user_data (context);
38828     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38829     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38830 	goto invalid_argument;
38831     name = (const char *) sqlite3_value_text (argv[0]);
38832     if (gaia_stored_var_delete (sqlite, cache, name))
38833 	sqlite3_result_int (context, 1);
38834     else
38835 	sqlite3_result_int (context, 0);
38836     return;
38837 
38838   invalid_argument:
38839     msg =
38840 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38841     sqlite3_result_error (context, msg, -1);
38842     return;
38843 }
38844 
38845 static void
fnct_sp_var_update_title(sqlite3_context * context,int argc,sqlite3_value ** argv)38846 fnct_sp_var_update_title (sqlite3_context * context, int argc,
38847 			  sqlite3_value ** argv)
38848 {
38849 /* SQL function:
38850 / StoredVar_UpdateTitle(name TEXT, title TEXT)
38851 /
38852 / returns:
38853 / 1 on success, 0 on failure
38854 / raises an exception on invalid arguments
38855 */
38856     const char *name;
38857     const char *title;
38858     const char *msg;
38859     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38860     struct splite_internal_cache *cache = sqlite3_user_data (context);
38861     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38862     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38863 	goto invalid_argument_1;
38864     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
38865 	goto invalid_argument_2;
38866     name = (const char *) sqlite3_value_text (argv[0]);
38867     title = (const char *) sqlite3_value_text (argv[1]);
38868     if (gaia_stored_var_update_title (sqlite, cache, name, title))
38869 	sqlite3_result_int (context, 1);
38870     else
38871 	sqlite3_result_int (context, 0);
38872     return;
38873 
38874   invalid_argument_1:
38875     msg =
38876 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38877     sqlite3_result_error (context, msg, -1);
38878     return;
38879 
38880   invalid_argument_2:
38881     msg =
38882 	"StoredVar exception - illegal Stored Variable Title [not a TEXT string].";
38883     sqlite3_result_error (context, msg, -1);
38884     return;
38885 }
38886 
38887 static void
fnct_sp_var_update_value(sqlite3_context * context,int argc,sqlite3_value ** argv)38888 fnct_sp_var_update_value (sqlite3_context * context, int argc,
38889 			  sqlite3_value ** argv)
38890 {
38891 /* SQL function:
38892 / StoredVar_UpdateValue(name TEXT, value NULL)
38893 / StoredVar_UpdateValue(name TEXT, value INT)
38894 / StoredVar_UpdateValue(name TEXT, value DOUBLE)
38895 / StoredVar_UpdateValue(name TEXT, value TEXT)
38896 / StoredVar_UpdateValue(name TEXT, value BLOB)
38897 /
38898 / returns:
38899 / 1 on success, 0 on failure
38900 / raises an exception on invalid arguments
38901 */
38902     const char *name;
38903     const unsigned char *blob;
38904     int blob_sz;
38905     char *value = NULL;
38906     const char *msg;
38907     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38908     struct splite_internal_cache *cache = sqlite3_user_data (context);
38909     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38910     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
38911 	goto invalid_argument_1;
38912     name = (const char *) sqlite3_value_text (argv[0]);
38913     switch (sqlite3_value_type (argv[1]))
38914       {
38915       case SQLITE_NULL:
38916 	  value = sqlite3_mprintf ("%s", "NULL");
38917 	  break;
38918       case SQLITE_INTEGER:
38919 #if defined(_WIN32) && !defined(__MINGW32__)
38920 	  value = sqlite3_mprintf ("%I64d", sqlite3_value_int64 (argv[1]));
38921 #else
38922 	  value = sqlite3_mprintf ("%lld", sqlite3_value_int64 (argv[1]));
38923 #endif
38924 	  break;
38925       case SQLITE_FLOAT:
38926 	  value = sqlite3_mprintf ("%1.10f", sqlite3_value_double (argv[1]));
38927 	  break;
38928       case SQLITE_TEXT:
38929 	  value = sqlite3_mprintf ("%s", sqlite3_value_text (argv[1]));
38930 	  break;
38931       case SQLITE_BLOB:
38932       default:
38933 	  blob = sqlite3_value_blob (argv[1]);
38934 	  blob_sz = sqlite3_value_bytes (argv[1]);
38935 	  value = do_encode_blob_value (blob, blob_sz);
38936 	  break;
38937       };
38938     if (gaia_stored_var_update_value (sqlite, cache, name, value))
38939 	sqlite3_result_int (context, 1);
38940     else
38941 	sqlite3_result_int (context, 0);
38942     if (value != NULL)
38943 	sqlite3_free (value);
38944     return;
38945 
38946   invalid_argument_1:
38947     msg =
38948 	"StoredVar exception - illegal Stored Variable Name [not a TEXT string].";
38949     sqlite3_result_error (context, msg, -1);
38950     return;
38951 }
38952 
38953 static void
fnct_create_routing_nodes(sqlite3_context * context,int argc,sqlite3_value ** argv)38954 fnct_create_routing_nodes (sqlite3_context * context, int argc,
38955 			   sqlite3_value ** argv)
38956 {
38957 /* SQL function:
38958 / CreateRoutingNodes(db-prefix TEXT, input-table TEXT , geom-column TEXT,
38959 /                    node-from-column TEXT , node-to-column TEXT )
38960 /
38961 / returns:
38962 / 1 on succes
38963 / raises an exception on invalid arguments or errors
38964 */
38965     const char *db_prefix;
38966     const char *input_table;
38967     const char *geom_column;
38968     const char *from_column;
38969     const char *to_column;
38970     const char *msg;
38971     sqlite3 *sqlite = sqlite3_context_db_handle (context);
38972     struct splite_internal_cache *cache = sqlite3_user_data (context);
38973     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
38974     if (sqlite3_value_type (argv[0]) == SQLITE_NULL)
38975 	db_prefix = NULL;
38976     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
38977 	db_prefix = (const char *) sqlite3_value_text (argv[0]);
38978     else
38979 	goto invalid_argument_1;
38980     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
38981 	goto invalid_argument_2;
38982     else
38983 	input_table = (const char *) sqlite3_value_text (argv[1]);
38984     if (sqlite3_value_type (argv[2]) == SQLITE_NULL)
38985 	geom_column = NULL;
38986     else if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
38987 	geom_column = (const char *) sqlite3_value_text (argv[2]);
38988     else
38989 	goto invalid_argument_3;
38990     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
38991 	goto invalid_argument_4;
38992     from_column = (const char *) sqlite3_value_text (argv[3]);
38993     if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
38994 	goto invalid_argument_5;
38995     to_column = (const char *) sqlite3_value_text (argv[4]);
38996     if (gaia_create_routing_nodes
38997 	(sqlite, cache, db_prefix, input_table, geom_column, from_column,
38998 	 to_column))
38999 	sqlite3_result_int (context, 1);
39000     else
39001       {
39002 	  /* there was an error, raising an Exception */
39003 	  char *msg_err;
39004 	  msg = gaia_create_routing_get_last_error (cache);
39005 	  if (msg == NULL)
39006 	      msg_err =
39007 		  sqlite3_mprintf
39008 		  ("CreateRoutingNodes exception - Unknown reason");
39009 	  else
39010 	      msg_err =
39011 		  sqlite3_mprintf ("CreateRoutingNodes exception - %s", msg);
39012 	  sqlite3_result_error (context, msg_err, -1);
39013 	  sqlite3_free (msg_err);
39014       }
39015     return;
39016 
39017   invalid_argument_1:
39018     msg =
39019 	"CreateRoutingNodes exception - illegal DB-prefix [not a TEXT string].";
39020     sqlite3_result_error (context, msg, -1);
39021     return;
39022 
39023   invalid_argument_2:
39024     msg =
39025 	"CreateRoutingNodes exception - illegal Spatial-Table Name [not a TEXT string].";
39026     sqlite3_result_error (context, msg, -1);
39027     return;
39028 
39029   invalid_argument_3:
39030     msg =
39031 	"CreateRoutingNodes exception - illegal Geometry Column Name [not a TEXT string].";
39032     sqlite3_result_error (context, msg, -1);
39033     return;
39034 
39035   invalid_argument_4:
39036     msg =
39037 	"CreateRoutingNodes exception - illegal FromNode Column Name [not a TEXT string].";
39038     sqlite3_result_error (context, msg, -1);
39039     return;
39040 
39041   invalid_argument_5:
39042     msg =
39043 	"CreateRoutingNodes exception - illegal ToNode Column Name [not a TEXT string].";
39044     sqlite3_result_error (context, msg, -1);
39045     return;
39046 }
39047 
39048 static void
fnct_create_routing(sqlite3_context * context,int argc,sqlite3_value ** argv)39049 fnct_create_routing (sqlite3_context * context, int argc, sqlite3_value ** argv)
39050 {
39051 /* SQL function:
39052 / CreateRouting(routing-data-table TEXT , virtual-routing-table TEXT ,
39053 /               input-table TEXT , from-column TEXT , to-column TEXT ,
39054 /               geom-column TEXT , cost-column TEXT )
39055 / CreateRouting(routing-data-table TEXT , virtual-routing-table TEXT ,
39056 /               input-table TEXT , from-column TEXT , to-column TEXT ,
39057 /               geom-column TEXT , cost-column TEXT , name-column TEXT ,
39058 /               a-star-enabled BOOLEAN , bidirectional BOOLEAN )
39059 / CreateRouting(routing-data-table TEXT , virtual-routing-table TEXT ,
39060 /               input-table TEXT , from-column TEXT , to-column TEXT ,
39061 /               geom-column TEXT , cost-column TEXT , name-column TEXT ,
39062 /               a-star-enabled BOOLEAN , bidirectional BOOLEAN ,
39063 /               oneway-from TEXT , oneway-to TEXT )
39064 / CreateRouting(routing-data-table TEXT , virtual-routing-table TEXT ,
39065 /               input-table TEXT , from-column TEXT , to-column TEXT ,
39066 /               geom-column TEXT , cost-column TEXT , name-column TEXT ,
39067 /               a-star-enabled BOOLEAN , bidirectional BOOLEAN ,
39068 /               oneway-from TEXT , oneway-to TEXT , overwrite BOOLEAN )
39069 /
39070 / returns:
39071 / 1 on succes
39072 / raises an exception on invalid arguments or errors
39073 */
39074     const char *routing_data_table;
39075     const char *virtual_routing_table;
39076     const char *input_table;
39077     const char *from_column;
39078     const char *to_column;
39079     const char *geom_column;
39080     const char *cost_column;
39081     const char *name_column;
39082     int a_star_enabled = 1;
39083     int bidirectional = 1;
39084     const char *oneway_from = NULL;
39085     const char *oneway_to = NULL;
39086     int overwrite = 0;
39087     const char *msg;
39088     sqlite3 *sqlite = sqlite3_context_db_handle (context);
39089     struct splite_internal_cache *cache = sqlite3_user_data (context);
39090     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39091     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39092 	goto invalid_argument_1;
39093     routing_data_table = (const char *) sqlite3_value_text (argv[0]);
39094     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39095 	goto invalid_argument_2;
39096     virtual_routing_table = (const char *) sqlite3_value_text (argv[1]);
39097     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39098 	goto invalid_argument_3;
39099     input_table = (const char *) sqlite3_value_text (argv[2]);
39100     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
39101 	goto invalid_argument_4;
39102     from_column = (const char *) sqlite3_value_text (argv[3]);
39103     if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
39104 	goto invalid_argument_5;
39105     to_column = (const char *) sqlite3_value_text (argv[4]);
39106     if (sqlite3_value_type (argv[5]) == SQLITE_NULL)
39107 	geom_column = NULL;
39108     else if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
39109 	geom_column = (const char *) sqlite3_value_text (argv[5]);
39110     else
39111 	goto invalid_argument_6;
39112     if (sqlite3_value_type (argv[6]) == SQLITE_NULL)
39113 	cost_column = NULL;
39114     else if (sqlite3_value_type (argv[6]) == SQLITE_TEXT)
39115 	cost_column = (const char *) sqlite3_value_text (argv[6]);
39116     else
39117 	goto invalid_argument_7;
39118     if (argc >= 10)
39119       {
39120 	  if (sqlite3_value_type (argv[7]) == SQLITE_NULL)
39121 	      name_column = NULL;
39122 	  else if (sqlite3_value_type (argv[7]) == SQLITE_TEXT)
39123 	      name_column = (const char *) sqlite3_value_text (argv[7]);
39124 	  else
39125 	      goto invalid_argument_8;
39126 	  if (sqlite3_value_type (argv[8]) != SQLITE_INTEGER)
39127 	      goto invalid_argument_9;
39128 	  a_star_enabled = sqlite3_value_int (argv[8]);
39129 	  if (sqlite3_value_type (argv[9]) != SQLITE_INTEGER)
39130 	      goto invalid_argument_10;
39131 	  bidirectional = sqlite3_value_int (argv[9]);
39132       }
39133     if (argc >= 12)
39134       {
39135 	  if (sqlite3_value_type (argv[10]) == SQLITE_NULL)
39136 	      oneway_from = NULL;
39137 	  else if (sqlite3_value_type (argv[10]) == SQLITE_TEXT)
39138 	      oneway_from = (const char *) sqlite3_value_text (argv[10]);
39139 	  else
39140 	      goto invalid_argument_11;
39141 	  if (sqlite3_value_type (argv[11]) == SQLITE_NULL)
39142 	      oneway_to = NULL;
39143 	  else if (sqlite3_value_type (argv[11]) == SQLITE_TEXT)
39144 	      oneway_to = (const char *) sqlite3_value_text (argv[11]);
39145 	  else
39146 	      goto invalid_argument_12;
39147       }
39148     if (argc >= 13)
39149       {
39150 	  if (sqlite3_value_type (argv[12]) != SQLITE_INTEGER)
39151 	      goto invalid_argument_13;
39152 	  overwrite = sqlite3_value_int (argv[12]);
39153       }
39154     if (gaia_create_routing
39155 	(sqlite, cache, routing_data_table, virtual_routing_table,
39156 	 input_table, from_column, to_column, geom_column, cost_column,
39157 	 name_column, a_star_enabled, bidirectional, oneway_from, oneway_to,
39158 	 overwrite))
39159 	sqlite3_result_int (context, 1);
39160     else
39161       {
39162 	  /* there was an error, raising an Exception */
39163 	  char *msg_err;
39164 	  msg = gaia_create_routing_get_last_error (cache);
39165 	  if (msg == NULL)
39166 	      msg_err =
39167 		  sqlite3_mprintf ("CreateRouting exception - Unknown reason");
39168 	  else
39169 	      msg_err = sqlite3_mprintf ("CreateRouting exception - %s", msg);
39170 	  sqlite3_result_error (context, msg_err, -1);
39171 	  sqlite3_free (msg_err);
39172       }
39173     return;
39174 
39175   invalid_argument_1:
39176     msg =
39177 	"CreateRouting exception - illegal Routing-Data Table Name [not a TEXT string].";
39178     sqlite3_result_error (context, msg, -1);
39179     return;
39180 
39181   invalid_argument_2:
39182     msg =
39183 	"CreateRouting exception - illegal VirtualRouting-Table Name [not a TEXT string].";
39184     sqlite3_result_error (context, msg, -1);
39185     return;
39186 
39187   invalid_argument_3:
39188     msg =
39189 	"CreateRouting exception - illegal Input-Table Name [not a TEXT string].";
39190     sqlite3_result_error (context, msg, -1);
39191     return;
39192 
39193   invalid_argument_4:
39194     msg =
39195 	"CreateRouting exception - illegal FromNode Column Name [not a TEXT string].";
39196     sqlite3_result_error (context, msg, -1);
39197     return;
39198 
39199   invalid_argument_5:
39200     msg =
39201 	"CreateRouting exception - illegal ToNode Column Name [not a TEXT string].";
39202     sqlite3_result_error (context, msg, -1);
39203     return;
39204 
39205   invalid_argument_6:
39206     msg =
39207 	"CreateRouting exception - illegal Geometry Column Name [not a TEXT string].";
39208     sqlite3_result_error (context, msg, -1);
39209     return;
39210 
39211   invalid_argument_7:
39212     msg =
39213 	"CreateRouting exception - illegal Cost Column Name [not a TEXT string].";
39214     sqlite3_result_error (context, msg, -1);
39215     return;
39216 
39217   invalid_argument_8:
39218     msg =
39219 	"CreateRouting exception - illegal RoadName Column Name [not a TEXT string].";
39220     sqlite3_result_error (context, msg, -1);
39221     return;
39222 
39223   invalid_argument_9:
39224     msg =
39225 	"CreateRouting exception - illegal A* Enabled option [not an INTEGER].";
39226     sqlite3_result_error (context, msg, -1);
39227     return;
39228 
39229   invalid_argument_10:
39230     msg =
39231 	"CreateRouting exception - illegal Bidirectional option [not an INTEGER].";
39232     sqlite3_result_error (context, msg, -1);
39233     return;
39234 
39235   invalid_argument_11:
39236     msg =
39237 	"CreateRouting exception - illegal OnewayFromTo Column Name [not a TEXT string].";
39238     sqlite3_result_error (context, msg, -1);
39239     return;
39240 
39241   invalid_argument_12:
39242     msg =
39243 	"CreateRouting exception - illegal OnewayToFrom Column Name [not a TEXT string].";
39244     sqlite3_result_error (context, msg, -1);
39245     return;
39246 
39247   invalid_argument_13:
39248     msg =
39249 	"CreateRouting exception - illegal OverWrite option [not an INTEGER].";
39250     sqlite3_result_error (context, msg, -1);
39251     return;
39252 }
39253 
39254 static void
fnct_create_routing_get_last_error(sqlite3_context * context,int argc,sqlite3_value ** argv)39255 fnct_create_routing_get_last_error (sqlite3_context * context, int argc,
39256 				    sqlite3_value ** argv)
39257 {
39258 /* SQL function:
39259 / CreateRouting_GetLastError()
39260 /
39261 / returns:
39262 / the most recent error message raised by CreateRouting
39263 / or NULL if no such message is available
39264 */
39265     const char *err_msg;
39266     struct splite_internal_cache *cache = sqlite3_user_data (context);
39267     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39268     if (cache == NULL)
39269       {
39270 	  sqlite3_result_null (context);
39271 	  return;
39272       }
39273 
39274     err_msg = gaia_create_routing_get_last_error (cache);
39275     if (err_msg == NULL)
39276 	sqlite3_result_null (context);
39277     else
39278 	sqlite3_result_text (context, err_msg, strlen (err_msg), SQLITE_STATIC);
39279 }
39280 
39281 #ifndef OMIT_FREEXL		/* FREEXL is enabled */
39282 static void
fnct_ImportXLS(sqlite3_context * context,int argc,sqlite3_value ** argv)39283 fnct_ImportXLS (sqlite3_context * context, int argc, sqlite3_value ** argv)
39284 {
39285 /* SQL function:
39286 / ImportXLS(TEXT filename, TEXT table)
39287 / ImportXLS(TEXT filename, TEXT table, INT worksheet_index)
39288 / ImportXLS(TEXT filename, TEXT table, INT worksheet_index,
39289 /          INT first_line_titles)
39290 /
39291 / returns:
39292 / the number of inserted rows
39293 / NULL on invalid arguments
39294 */
39295     const char *filename;
39296     const char *table;
39297     int widx;
39298     unsigned int worksheet_index = 0;
39299     int first_line_titles = 0;
39300     int ret;
39301     unsigned int rows;
39302     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39303     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39304     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39305       {
39306 	  sqlite3_result_null (context);
39307 	  return;
39308       }
39309     filename = (const char *) sqlite3_value_text (argv[0]);
39310     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39311       {
39312 	  sqlite3_result_null (context);
39313 	  return;
39314       }
39315     table = (const char *) sqlite3_value_text (argv[1]);
39316     if (argc > 2)
39317       {
39318 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
39319 	    {
39320 		sqlite3_result_null (context);
39321 		return;
39322 	    }
39323 	  widx = sqlite3_value_int (argv[2]);
39324 	  if (widx < 0)
39325 	    {
39326 		sqlite3_result_null (context);
39327 		return;
39328 	    }
39329 	  worksheet_index = widx;
39330       }
39331     if (argc > 3)
39332       {
39333 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
39334 	    {
39335 		sqlite3_result_null (context);
39336 		return;
39337 	    }
39338 	  first_line_titles = sqlite3_value_int (argv[3]);
39339       }
39340 
39341     ret =
39342 	load_XL (db_handle, filename, table, worksheet_index,
39343 		 first_line_titles, &rows, NULL);
39344 
39345     if (!ret)
39346 	sqlite3_result_null (context);
39347     else
39348 	sqlite3_result_int (context, rows);
39349 }
39350 #endif /* end FREEXL support */
39351 
39352 #ifndef OMIT_ICONV		/* ICONV is supported */
39353 static void
fnct_ImportDBF(sqlite3_context * context,int argc,sqlite3_value ** argv)39354 fnct_ImportDBF (sqlite3_context * context, int argc, sqlite3_value ** argv)
39355 {
39356 /* SQL function:
39357 / ImportDBF(TEXT filename, TEXT table, TEXT charset)
39358 / ImportDBF(TEXT filename, TEXT table, TEXT charset, TEXT pk_column)
39359 / ImportDBF(TEXT filename, TEXT table, TEXT charset, TEXT pk_column,
39360 /           INTEGER text_dates)
39361 / ImportDBF(TEXT filename, TEXT table, TEXT charset, TEXT pk_column,
39362 /           INTEGER text_dates, INTEGER colname_case)
39363 /
39364 / returns:
39365 / the number of inserted rows
39366 / NULL on invalid arguments
39367 */
39368     int ret;
39369     char *table;
39370     char *path;
39371     char *charset;
39372     char *pk_column = NULL;
39373     int text_dates = 0;
39374     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39375     int rows;
39376     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39377     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39378     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39379       {
39380 	  sqlite3_result_null (context);
39381 	  return;
39382       }
39383     path = (char *) sqlite3_value_text (argv[0]);
39384     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39385       {
39386 	  sqlite3_result_null (context);
39387 	  return;
39388       }
39389     table = (char *) sqlite3_value_text (argv[1]);
39390     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39391       {
39392 	  sqlite3_result_null (context);
39393 	  return;
39394       }
39395     charset = (char *) sqlite3_value_text (argv[2]);
39396     if (argc > 3)
39397       {
39398 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
39399 	    {
39400 		sqlite3_result_null (context);
39401 		return;
39402 	    }
39403 	  else
39404 	      pk_column = (char *) sqlite3_value_text (argv[3]);
39405       }
39406     if (argc > 4)
39407       {
39408 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
39409 	    {
39410 		sqlite3_result_null (context);
39411 		return;
39412 	    }
39413 	  else
39414 	      text_dates = sqlite3_value_int (argv[4]);
39415       }
39416     if (argc > 5)
39417       {
39418 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
39419 	    {
39420 		sqlite3_result_null (context);
39421 		return;
39422 	    }
39423 	  else
39424 	    {
39425 		const char *val = (char *) sqlite3_value_text (argv[5]);
39426 		if (strcasecmp (val, "UPPER") == 0
39427 		    || strcasecmp (val, "UPPERCASE") == 0)
39428 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
39429 		else if (strcasecmp (val, "SAME") == 0
39430 			 || strcasecmp (val, "SAMECASE") == 0)
39431 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
39432 		else
39433 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39434 	    }
39435       }
39436 
39437     ret =
39438 	load_dbf_ex3 (db_handle, path, table, pk_column, charset, 1,
39439 		      text_dates, &rows, colname_case, NULL);
39440 
39441     if (rows < 0 || !ret)
39442 	sqlite3_result_null (context);
39443     else
39444 	sqlite3_result_int (context, rows);
39445 }
39446 
39447 static void
fnct_ExportDBF(sqlite3_context * context,int argc,sqlite3_value ** argv)39448 fnct_ExportDBF (sqlite3_context * context, int argc, sqlite3_value ** argv)
39449 {
39450 /* SQL function:
39451 / ExportDBF(TEXT table, TEXT filename, TEXT charset)
39452 / ExportDBF(TEXT table, TEXT filename, TEXT charset, TEXT colname_case)
39453 /
39454 / returns:
39455 / the number of exported rows
39456 / NULL on invalid arguments
39457 */
39458     int ret;
39459     char *table;
39460     char *path;
39461     char *charset;
39462     int rows;
39463     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39464     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39465     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39466     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39467       {
39468 	  sqlite3_result_null (context);
39469 	  return;
39470       }
39471     table = (char *) sqlite3_value_text (argv[0]);
39472     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39473       {
39474 	  sqlite3_result_null (context);
39475 	  return;
39476       }
39477     path = (char *) sqlite3_value_text (argv[1]);
39478     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39479       {
39480 	  sqlite3_result_null (context);
39481 	  return;
39482       }
39483     charset = (char *) sqlite3_value_text (argv[2]);
39484     if (argc > 3)
39485       {
39486 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
39487 	    {
39488 		sqlite3_result_null (context);
39489 		return;
39490 	    }
39491 	  else
39492 	    {
39493 		const char *val = (char *) sqlite3_value_text (argv[3]);
39494 		if (strcasecmp (val, "UPPER") == 0
39495 		    || strcasecmp (val, "UPPERCASE") == 0)
39496 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
39497 		else if (strcasecmp (val, "SAME") == 0
39498 			 || strcasecmp (val, "SAMECASE") == 0)
39499 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
39500 		else
39501 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39502 	    }
39503       }
39504 
39505     ret =
39506 	dump_dbf_ex2 (db_handle, table, path, charset, &rows, colname_case,
39507 		      NULL);
39508 
39509     if (rows <= 0 || !ret)
39510 	sqlite3_result_null (context);
39511     else
39512 	sqlite3_result_int (context, rows);
39513 }
39514 
39515 static void
fnct_ImportSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)39516 fnct_ImportSHP (sqlite3_context * context, int argc, sqlite3_value ** argv)
39517 {
39518 /* SQL function:
39519 / ImportSHP(TEXT filename, TEXT table, TEXT charset)
39520 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid)
39521 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39522 /           TEXT geom_column)
39523 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39524 /           TEXT geom_column, TEXT pk_column)
39525 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39526 /           TEXT geom_column, TEXT pk_column, TEXT geom_type)
39527 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39528 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39529 /           INT coerce2d)
39530 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39531 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39532 /           INT coerce2d, INT compressed)
39533 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39534 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39535 /           INT coerce2d, INT compressed, INT spatial_index)
39536 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39537 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39538 /           INT coerce2d, INT compressed, INT spatial_index,
39539 /           INT text_dates)
39540 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39541 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39542 /           INT coerce2d, INT compressed, INT spatial_index,
39543 /           INT text_dates, TEXT colname_case)
39544 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39545 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39546 /           INT coerce2d, INT compressed, INT spatial_index,
39547 /           INT text_dates, TEXT colname_case, INT update_statistics)
39548 / ImportSHP(TEXT filename, TEXT table, TEXT charset, INT srid,
39549 /           TEXT geom_column, TEXT pk_column, TEXT geom_type,
39550 /           INT coerce2d, INT compressed, INT spatial_index,
39551 /           INT text_dates, TEXT colname_case, INT update_statistics,
39552 /           INT verbose)
39553 /
39554 / returns:
39555 / the number of imported rows
39556 / NULL on invalid arguments
39557 */
39558     int ret;
39559     char *table;
39560     char *path;
39561     char *charset;
39562     int srid = -1;
39563     int coerce2d = 0;
39564     int compressed = 0;
39565     int spatial_index = 0;
39566     int text_dates = 0;
39567     int update_statistics = 1;
39568     int verbose = 1;
39569     char *pk_column = NULL;
39570     char *geo_column = NULL;
39571     char *geom_type = NULL;
39572     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39573     int rows;
39574     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39575     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39576     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39577       {
39578 	  sqlite3_result_null (context);
39579 	  return;
39580       }
39581     path = (char *) sqlite3_value_text (argv[0]);
39582     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39583       {
39584 	  sqlite3_result_null (context);
39585 	  return;
39586       }
39587     table = (char *) sqlite3_value_text (argv[1]);
39588     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39589       {
39590 	  sqlite3_result_null (context);
39591 	  return;
39592       }
39593     charset = (char *) sqlite3_value_text (argv[2]);
39594     if (argc > 3)
39595       {
39596 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
39597 	    {
39598 		sqlite3_result_null (context);
39599 		return;
39600 	    }
39601 	  else
39602 	      srid = sqlite3_value_int (argv[3]);
39603       }
39604     if (argc > 4)
39605       {
39606 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
39607 	    {
39608 		sqlite3_result_null (context);
39609 		return;
39610 	    }
39611 	  else
39612 	      geo_column = (char *) sqlite3_value_text (argv[4]);
39613       }
39614     if (argc > 5)
39615       {
39616 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
39617 	    {
39618 		sqlite3_result_null (context);
39619 		return;
39620 	    }
39621 	  else
39622 	      pk_column = (char *) sqlite3_value_text (argv[5]);
39623       }
39624     if (argc > 6)
39625       {
39626 	  if (sqlite3_value_type (argv[6]) != SQLITE_TEXT)
39627 	    {
39628 		sqlite3_result_null (context);
39629 		return;
39630 	    }
39631 	  else
39632 	      geom_type = (char *) sqlite3_value_text (argv[6]);
39633       }
39634     if (argc > 7)
39635       {
39636 	  if (sqlite3_value_type (argv[7]) != SQLITE_INTEGER)
39637 	    {
39638 		sqlite3_result_null (context);
39639 		return;
39640 	    }
39641 	  else
39642 	      coerce2d = sqlite3_value_int (argv[7]);
39643       }
39644     if (argc > 8)
39645       {
39646 	  if (sqlite3_value_type (argv[8]) != SQLITE_INTEGER)
39647 	    {
39648 		sqlite3_result_null (context);
39649 		return;
39650 	    }
39651 	  else
39652 	      compressed = sqlite3_value_int (argv[8]);
39653       }
39654     if (argc > 9)
39655       {
39656 	  if (sqlite3_value_type (argv[9]) != SQLITE_INTEGER)
39657 	    {
39658 		sqlite3_result_null (context);
39659 		return;
39660 	    }
39661 	  else
39662 	      spatial_index = sqlite3_value_int (argv[9]);
39663       }
39664     if (argc > 10)
39665       {
39666 	  if (sqlite3_value_type (argv[10]) != SQLITE_INTEGER)
39667 	    {
39668 		sqlite3_result_null (context);
39669 		return;
39670 	    }
39671 	  else
39672 	      text_dates = sqlite3_value_int (argv[10]);
39673       }
39674     if (argc > 11)
39675       {
39676 	  if (sqlite3_value_type (argv[11]) != SQLITE_TEXT)
39677 	    {
39678 		sqlite3_result_null (context);
39679 		return;
39680 	    }
39681 	  else
39682 	    {
39683 		const char *val = (char *) sqlite3_value_text (argv[11]);
39684 		if (strcasecmp (val, "UPPER") == 0
39685 		    || strcasecmp (val, "UPPERCASE") == 0)
39686 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
39687 		else if (strcasecmp (val, "SAME") == 0
39688 			 || strcasecmp (val, "SAMECASE") == 0)
39689 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
39690 		else
39691 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39692 	    }
39693       }
39694     if (argc > 12)
39695       {
39696 	  if (sqlite3_value_type (argv[12]) != SQLITE_INTEGER)
39697 	    {
39698 		sqlite3_result_null (context);
39699 		return;
39700 	    }
39701 	  else
39702 	      update_statistics = sqlite3_value_int (argv[12]);
39703       }
39704     if (argc > 13)
39705       {
39706 	  if (sqlite3_value_type (argv[13]) != SQLITE_INTEGER)
39707 	    {
39708 		sqlite3_result_null (context);
39709 		return;
39710 	    }
39711 	  else
39712 	      verbose = sqlite3_value_int (argv[13]);
39713       }
39714 
39715     ret =
39716 	load_shapefile_ex3 (db_handle, path, table, charset, srid, geo_column,
39717 			    geom_type, pk_column, coerce2d, compressed,
39718 			    verbose, spatial_index, text_dates, &rows,
39719 			    colname_case, NULL);
39720 
39721     if (rows < 0 || !ret)
39722 	sqlite3_result_null (context);
39723     else
39724       {
39725 	  if (update_statistics)
39726 	      update_layer_statistics (db_handle, table, NULL);
39727 	  sqlite3_result_int (context, rows);
39728       }
39729 }
39730 
39731 #ifdef ENABLE_MINIZIP		/* only if MINIZIP is enabled */
39732 
39733 static void
fnct_ImportZipDBF(sqlite3_context * context,int argc,sqlite3_value ** argv)39734 fnct_ImportZipDBF (sqlite3_context * context, int argc, sqlite3_value ** argv)
39735 {
39736 /* SQL function:
39737 / ImportZipDBF(TEXT zip_path, TEXT filename, TEXT table, TEXT charset)
39738 / ImportZipDBF(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39739 /              TEXT pk_column)
39740 / ImportZipDBF(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39741 /              TEXT pk_column, INTEGER text_dates)
39742 / ImportZipDBF(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39743 /              TEXT pk_column, INTEGER text_dates, INTEGER colname_case)
39744 /
39745 / returns:
39746 / the number of inserted rows
39747 / NULL on invalid arguments
39748 */
39749     int ret;
39750     char *zip_path;
39751     char *table;
39752     char *path;
39753     char *charset;
39754     char *pk_column = NULL;
39755     int text_dates = 0;
39756     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39757     int rows = 0;
39758     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39759     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39760     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39761       {
39762 	  sqlite3_result_null (context);
39763 	  return;
39764       }
39765     zip_path = (char *) sqlite3_value_text (argv[0]);
39766     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39767       {
39768 	  sqlite3_result_null (context);
39769 	  return;
39770       }
39771     path = (char *) sqlite3_value_text (argv[1]);
39772     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39773       {
39774 	  sqlite3_result_null (context);
39775 	  return;
39776       }
39777     table = (char *) sqlite3_value_text (argv[2]);
39778     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
39779       {
39780 	  sqlite3_result_null (context);
39781 	  return;
39782       }
39783     charset = (char *) sqlite3_value_text (argv[3]);
39784     if (argc > 4)
39785       {
39786 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
39787 	    {
39788 		sqlite3_result_null (context);
39789 		return;
39790 	    }
39791 	  else
39792 	      pk_column = (char *) sqlite3_value_text (argv[4]);
39793       }
39794     if (argc > 5)
39795       {
39796 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
39797 	    {
39798 		sqlite3_result_null (context);
39799 		return;
39800 	    }
39801 	  else
39802 	      text_dates = sqlite3_value_int (argv[5]);
39803       }
39804     if (argc > 6)
39805       {
39806 	  if (sqlite3_value_type (argv[6]) != SQLITE_TEXT)
39807 	    {
39808 		sqlite3_result_null (context);
39809 		return;
39810 	    }
39811 	  else
39812 	    {
39813 		const char *val = (char *) sqlite3_value_text (argv[6]);
39814 		if (strcasecmp (val, "UPPER") == 0
39815 		    || strcasecmp (val, "UPPERCASE") == 0)
39816 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
39817 		else if (strcasecmp (val, "SAME") == 0
39818 			 || strcasecmp (val, "SAMECASE") == 0)
39819 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
39820 		else
39821 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39822 	    }
39823       }
39824 
39825     ret =
39826 	load_zip_dbf (db_handle, zip_path, path, table, pk_column, charset, 1,
39827 		      text_dates, &rows, colname_case, NULL);
39828 
39829     if (rows < 0 || !ret)
39830 	sqlite3_result_null (context);
39831     else
39832 	sqlite3_result_int (context, rows);
39833 }
39834 
39835 static void
fnct_ImportZipSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)39836 fnct_ImportZipSHP (sqlite3_context * context, int argc, sqlite3_value ** argv)
39837 {
39838 /* SQL function:
39839 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset)
39840 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39841 /              INT srid)
39842 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39843 /              INT srid, TEXT geom_column)
39844 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39845 /              INT srid, TEXT geom_column, TEXT pk_column)
39846 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39847 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type)
39848 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39849 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39850 /              INT coerce2d)
39851 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39852 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39853 /              INT coerce2d, INT compressed)
39854 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39855 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39856 /              INT coerce2d, INT compressed, INT spatial_index)
39857 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39858 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39859 /              INT coerce2d, INT compressed, INT spatial_index,
39860 /              INT text_dates)
39861 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39862 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39863 /              INT coerce2d, INT compressed, INT spatial_index,
39864 /              INT text_dates, TEXT colname_case)
39865 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39866 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39867 /              INT coerce2d, INT compressed, INT spatial_index,
39868 /              INT text_dates, TEXT colname_case, INT update_statistics)
39869 / ImportZipSHP(TEXT zip_path, TEXT filename, TEXT table, TEXT charset,
39870 /              INT srid, TEXT geom_column, TEXT pk_column, TEXT geom_type,
39871 /              INT coerce2d, INT compressed, INT spatial_index,
39872 /              INT text_dates, TEXT colname_case, INT update_statistics,
39873 /              INT verbose)
39874 /
39875 / returns:
39876 / the number of imported rows
39877 / NULL on invalid arguments
39878 */
39879     int ret;
39880     char *zip_path;
39881     char *table;
39882     char *path;
39883     char *charset;
39884     int srid = -1;
39885     int coerce2d = 0;
39886     int compressed = 0;
39887     int spatial_index = 0;
39888     int text_dates = 0;
39889     int update_statistics = 1;
39890     int verbose = 1;
39891     char *pk_column = NULL;
39892     char *geo_column = NULL;
39893     char *geom_type = NULL;
39894     int colname_case = GAIA_DBF_COLNAME_LOWERCASE;
39895     int rows = 0;
39896     sqlite3 *db_handle = sqlite3_context_db_handle (context);
39897     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
39898     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
39899       {
39900 	  sqlite3_result_null (context);
39901 	  return;
39902       }
39903     zip_path = (char *) sqlite3_value_text (argv[0]);
39904     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
39905       {
39906 	  sqlite3_result_null (context);
39907 	  return;
39908       }
39909     path = (char *) sqlite3_value_text (argv[1]);
39910     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
39911       {
39912 	  sqlite3_result_null (context);
39913 	  return;
39914       }
39915     table = (char *) sqlite3_value_text (argv[2]);
39916     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
39917       {
39918 	  sqlite3_result_null (context);
39919 	  return;
39920       }
39921     charset = (char *) sqlite3_value_text (argv[3]);
39922     if (argc > 4)
39923       {
39924 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
39925 	    {
39926 		sqlite3_result_null (context);
39927 		return;
39928 	    }
39929 	  else
39930 	      srid = sqlite3_value_int (argv[4]);
39931       }
39932     if (argc > 5)
39933       {
39934 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
39935 	    {
39936 		sqlite3_result_null (context);
39937 		return;
39938 	    }
39939 	  else
39940 	      geo_column = (char *) sqlite3_value_text (argv[5]);
39941       }
39942     if (argc > 6)
39943       {
39944 	  if (sqlite3_value_type (argv[6]) != SQLITE_TEXT)
39945 	    {
39946 		sqlite3_result_null (context);
39947 		return;
39948 	    }
39949 	  else
39950 	      pk_column = (char *) sqlite3_value_text (argv[6]);
39951       }
39952     if (argc > 7)
39953       {
39954 	  if (sqlite3_value_type (argv[7]) != SQLITE_TEXT)
39955 	    {
39956 		sqlite3_result_null (context);
39957 		return;
39958 	    }
39959 	  else
39960 	      geom_type = (char *) sqlite3_value_text (argv[7]);
39961       }
39962     if (argc > 8)
39963       {
39964 	  if (sqlite3_value_type (argv[8]) != SQLITE_INTEGER)
39965 	    {
39966 		sqlite3_result_null (context);
39967 		return;
39968 	    }
39969 	  else
39970 	      coerce2d = sqlite3_value_int (argv[8]);
39971       }
39972     if (argc > 9)
39973       {
39974 	  if (sqlite3_value_type (argv[9]) != SQLITE_INTEGER)
39975 	    {
39976 		sqlite3_result_null (context);
39977 		return;
39978 	    }
39979 	  else
39980 	      compressed = sqlite3_value_int (argv[9]);
39981       }
39982     if (argc > 10)
39983       {
39984 	  if (sqlite3_value_type (argv[10]) != SQLITE_INTEGER)
39985 	    {
39986 		sqlite3_result_null (context);
39987 		return;
39988 	    }
39989 	  else
39990 	      spatial_index = sqlite3_value_int (argv[10]);
39991       }
39992     if (argc > 11)
39993       {
39994 	  if (sqlite3_value_type (argv[11]) != SQLITE_INTEGER)
39995 	    {
39996 		sqlite3_result_null (context);
39997 		return;
39998 	    }
39999 	  else
40000 	      text_dates = sqlite3_value_int (argv[11]);
40001       }
40002     if (argc > 12)
40003       {
40004 	  if (sqlite3_value_type (argv[12]) != SQLITE_TEXT)
40005 	    {
40006 		sqlite3_result_null (context);
40007 		return;
40008 	    }
40009 	  else
40010 	    {
40011 		const char *val = (char *) sqlite3_value_text (argv[12]);
40012 		if (strcasecmp (val, "UPPER") == 0
40013 		    || strcasecmp (val, "UPPERCASE") == 0)
40014 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
40015 		else if (strcasecmp (val, "SAME") == 0
40016 			 || strcasecmp (val, "SAMECASE") == 0)
40017 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
40018 		else
40019 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
40020 	    }
40021       }
40022     if (argc > 13)
40023       {
40024 	  if (sqlite3_value_type (argv[13]) != SQLITE_INTEGER)
40025 	    {
40026 		sqlite3_result_null (context);
40027 		return;
40028 	    }
40029 	  else
40030 	      update_statistics = sqlite3_value_int (argv[13]);
40031       }
40032     if (argc > 14)
40033       {
40034 	  if (sqlite3_value_type (argv[14]) != SQLITE_INTEGER)
40035 	    {
40036 		sqlite3_result_null (context);
40037 		return;
40038 	    }
40039 	  else
40040 	      verbose = sqlite3_value_int (argv[14]);
40041       }
40042 
40043     ret =
40044 	load_zip_shapefile (db_handle, zip_path, path, table, charset, srid,
40045 			    geo_column, geom_type, pk_column, coerce2d,
40046 			    compressed, verbose, spatial_index, text_dates,
40047 			    &rows, colname_case, NULL);
40048 
40049     if (rows < 0 || !ret)
40050 	sqlite3_result_null (context);
40051     else
40052       {
40053 	  if (update_statistics)
40054 	      update_layer_statistics (db_handle, table, NULL);
40055 	  sqlite3_result_int (context, rows);
40056       }
40057 }
40058 
40059 #endif /* end enabling ImportZipSHP */
40060 
40061 static void
fnct_ExportSHP(sqlite3_context * context,int argc,sqlite3_value ** argv)40062 fnct_ExportSHP (sqlite3_context * context, int argc, sqlite3_value ** argv)
40063 {
40064 /* SQL function:
40065 / ExportSHP(TEXT table, TEXT geom_column, TEXT filename, TEXT charset)
40066 / ExportSHP(TEXT table, TEXT geom_column, TEXT filename, TEXT charset,
40067 /           TEXT geom_type)
40068 / ExportSHP(TEXT table, TEXT geom_column, TEXT filename, TEXT charset,
40069 /           TEXT geom_type, TEXT colname_case)
40070 /
40071 / returns:
40072 / the number of exported rows
40073 / NULL on invalid arguments
40074 */
40075     int ret;
40076     char *table;
40077     char *column;
40078     char *path;
40079     char *charset;
40080     char *geom_type = NULL;
40081     int colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
40082     int rows;
40083     sqlite3 *db_handle = sqlite3_context_db_handle (context);
40084 #ifdef PROJ_NEW			/* only if new PROJ.6 is supported */
40085     struct splite_internal_cache *cache = sqlite3_user_data (context);
40086 #endif
40087     void *proj_ctx = NULL;
40088     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40089     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
40090       {
40091 	  sqlite3_result_null (context);
40092 	  return;
40093       }
40094     table = (char *) sqlite3_value_text (argv[0]);
40095     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
40096       {
40097 	  sqlite3_result_null (context);
40098 	  return;
40099       }
40100     column = (char *) sqlite3_value_text (argv[1]);
40101     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
40102       {
40103 	  sqlite3_result_null (context);
40104 	  return;
40105       }
40106     path = (char *) sqlite3_value_text (argv[2]);
40107     if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
40108       {
40109 	  sqlite3_result_null (context);
40110 	  return;
40111       }
40112     charset = (char *) sqlite3_value_text (argv[3]);
40113     if (argc > 4)
40114       {
40115 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
40116 	    {
40117 		sqlite3_result_null (context);
40118 		return;
40119 	    }
40120 	  else
40121 	      geom_type = (char *) sqlite3_value_text (argv[4]);
40122       }
40123     if (argc > 5)
40124       {
40125 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
40126 	    {
40127 		sqlite3_result_null (context);
40128 		return;
40129 	    }
40130 	  else
40131 	    {
40132 		const char *val = (char *) sqlite3_value_text (argv[5]);
40133 		if (strcasecmp (val, "UPPER") == 0
40134 		    || strcasecmp (val, "UPPERCASE") == 0)
40135 		    colname_case = GAIA_DBF_COLNAME_UPPERCASE;
40136 		else if (strcasecmp (val, "SAME") == 0
40137 			 || strcasecmp (val, "SAMECASE") == 0)
40138 		    colname_case = GAIA_DBF_COLNAME_CASE_IGNORE;
40139 		else
40140 		    colname_case = GAIA_DBF_COLNAME_LOWERCASE;
40141 	    }
40142       }
40143 
40144 #ifdef PROJ_NEW			/* only if new PROJ.6 is supported */
40145     if (cache != NULL)
40146 	proj_ctx = cache->PROJ_handle;
40147 #endif
40148     ret =
40149 	dump_shapefile_ex2 (db_handle, proj_ctx, table, column, path, charset,
40150 			    geom_type, 1, &rows, colname_case, NULL);
40151 
40152     if (rows < 0 || !ret)
40153 	sqlite3_result_null (context);
40154     else
40155 	sqlite3_result_int (context, rows);
40156 }
40157 
40158 static void
fnct_ExportKML(sqlite3_context * context,int argc,sqlite3_value ** argv)40159 fnct_ExportKML (sqlite3_context * context, int argc, sqlite3_value ** argv)
40160 {
40161 /* SQL function:
40162 / ExportKML(TEXT table, TEXT geom_column, TEXT filename)
40163 / ExportKML(TEXT table, TEXT geom_column, TEXT filename, INT precision)
40164 / ExportKML(TEXT table, TEXT geom_column, TEXT filename, INT precision,
40165 /           TEXT name_column)
40166 / ExportKML(TEXT table, TEXT geom_column, TEXT filename, INT precision,
40167 /           TEXT name_column, TEXT description_column)
40168 /
40169 / returns:
40170 / the number of exported rows
40171 / NULL on invalid arguments
40172 */
40173     int ret;
40174     char *table;
40175     char *geom_col;
40176     char *path;
40177     int precision = 8;
40178     char *name_col = NULL;
40179     char *descr_col = NULL;
40180     int rows;
40181     sqlite3 *db_handle = sqlite3_context_db_handle (context);
40182     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40183     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
40184       {
40185 	  sqlite3_result_null (context);
40186 	  return;
40187       }
40188     table = (char *) sqlite3_value_text (argv[0]);
40189     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
40190       {
40191 	  sqlite3_result_null (context);
40192 	  return;
40193       }
40194     geom_col = (char *) sqlite3_value_text (argv[1]);
40195     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
40196       {
40197 	  sqlite3_result_null (context);
40198 	  return;
40199       }
40200     path = (char *) sqlite3_value_text (argv[2]);
40201     if (argc > 3)
40202       {
40203 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
40204 	    {
40205 		sqlite3_result_null (context);
40206 		return;
40207 	    }
40208 	  else
40209 	      precision = sqlite3_value_int (argv[3]);
40210       }
40211     if (argc > 4)
40212       {
40213 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
40214 	    {
40215 		sqlite3_result_null (context);
40216 		return;
40217 	    }
40218 	  else
40219 	      name_col = (char *) sqlite3_value_text (argv[4]);
40220       }
40221     if (argc > 5)
40222       {
40223 	  if (sqlite3_value_type (argv[5]) != SQLITE_TEXT)
40224 	    {
40225 		sqlite3_result_null (context);
40226 		return;
40227 	    }
40228 	  else
40229 	      descr_col = (char *) sqlite3_value_text (argv[5]);
40230       }
40231 
40232     ret =
40233 	dump_kml_ex (db_handle, table, geom_col, path, name_col, descr_col,
40234 		     precision, &rows);
40235 
40236     if (rows < 0 || !ret)
40237 	sqlite3_result_null (context);
40238     else
40239 	sqlite3_result_int (context, rows);
40240 }
40241 
40242 #endif /* end ICONV supported */
40243 
40244 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
40245 static void
wfs_page_done(int features,void * ptr)40246 wfs_page_done (int features, void *ptr)
40247 {
40248 /* WFS progress handler callback */
40249     if (ptr == NULL)
40250 	ptr = NULL;		/* silencing stupid compiler warnings */
40251     if (isatty (1))
40252 	spatialite_e ("WFS Features loaded since now: %d\r", features);
40253 }
40254 
40255 static void
fnct_ImportWFS(sqlite3_context * context,int argc,sqlite3_value ** argv)40256 fnct_ImportWFS (sqlite3_context * context, int argc, sqlite3_value ** argv)
40257 {
40258 /* SQL function:
40259 / ImportWFS(TEXT filename_or_url, TEXT layer_name, TEXT table)
40260 / ImportWFS(TEXT filename_or_url, TEXT layer_name, TEXT table,
40261 /           TEXT pk_column)
40262 / ImportWFS(TEXT filename_or_url, TEXT layer_name, TEXT table,
40263 /           TEXT pk_column, INT swap_axes)
40264 / ImportWFS(TEXT filename_or_url, TEXT layer_name, TEXT table,
40265 /           TEXT pk_column, INT swap_axes, INT page_size)
40266 / ImportWFS(TEXT filename_or_url, TEXT layer_name, TEXT table,
40267 /           TEXT pk_column, INT swap_axes, INT page_size,
40268 /           INT spatial_index)
40269 /
40270 / returns:
40271 / the number of imported rows
40272 / NULL on invalid arguments
40273 */
40274     int ret;
40275     char *path_or_url;
40276     char *layer_name;
40277     char *table;
40278     int swap_axes = 0;
40279     int spatial_index = 0;
40280     int page_size = -1;
40281     char *pk_column = NULL;
40282     int rows;
40283     sqlite3 *db_handle = sqlite3_context_db_handle (context);
40284     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40285     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
40286       {
40287 	  sqlite3_result_null (context);
40288 	  return;
40289       }
40290     path_or_url = (char *) sqlite3_value_text (argv[0]);
40291     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
40292       {
40293 	  sqlite3_result_null (context);
40294 	  return;
40295       }
40296     layer_name = (char *) sqlite3_value_text (argv[1]);
40297     if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
40298       {
40299 	  sqlite3_result_null (context);
40300 	  return;
40301       }
40302     table = (char *) sqlite3_value_text (argv[2]);
40303     if (argc > 3)
40304       {
40305 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
40306 	    {
40307 		sqlite3_result_null (context);
40308 		return;
40309 	    }
40310 	  else
40311 	      pk_column = (char *) sqlite3_value_text (argv[3]);
40312       }
40313     if (argc > 4)
40314       {
40315 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
40316 	    {
40317 		sqlite3_result_null (context);
40318 		return;
40319 	    }
40320 	  else
40321 	      swap_axes = sqlite3_value_int (argv[4]);
40322       }
40323     if (argc > 5)
40324       {
40325 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
40326 	    {
40327 		sqlite3_result_null (context);
40328 		return;
40329 	    }
40330 	  else
40331 	      page_size = sqlite3_value_int (argv[5]);
40332       }
40333     if (argc > 6)
40334       {
40335 	  if (sqlite3_value_type (argv[6]) != SQLITE_INTEGER)
40336 	    {
40337 		sqlite3_result_null (context);
40338 		return;
40339 	    }
40340 	  else
40341 	      spatial_index = sqlite3_value_int (argv[6]);
40342       }
40343 
40344     ret =
40345 	load_from_wfs_paged (db_handle, path_or_url, NULL, layer_name,
40346 			     swap_axes, table, pk_column, spatial_index,
40347 			     page_size, &rows, NULL, wfs_page_done, NULL);
40348 
40349     if (rows < 0 || !ret)
40350 	sqlite3_result_null (context);
40351     else
40352 	sqlite3_result_int (context, rows);
40353 }
40354 #endif /* end including LIBXML2 */
40355 
40356 static int
is_word_delimiter(const char x,int post)40357 is_word_delimiter (const char x, int post)
40358 {
40359 /* testing for a SQL word delimiter */
40360     if (x == ' ' || x == '\t' || x == '\n' || x == '\r' || x == '(')
40361 	return 1;
40362     if (post && x == '(')
40363 	return 1;
40364     if (!post && x == ',')
40365 	return 1;
40366     return 0;
40367 }
40368 
40369 static int
do_check_eval(const char * str)40370 do_check_eval (const char *str)
40371 {
40372 /* testing if a Trigger attempts calling the dangerous Eval() function */
40373 
40374     int contains_eval = 0;
40375     const char *start = str;
40376     const char *ptr;
40377     while (1)
40378       {
40379 	  char pre;
40380 	  char post;
40381 	  ptr = strstr (start, "eval");
40382 	  if (ptr == NULL)
40383 	      break;
40384 	  if (ptr > str)
40385 	      pre = *(ptr - 1);
40386 	  else
40387 	      pre = ' ';
40388 	  post = *(ptr + 4);
40389 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40390 	      contains_eval = 1;
40391 	  start = ptr + 4;
40392       }
40393     return contains_eval;
40394 }
40395 
40396 static int
do_check_blob_from_file(const char * str)40397 do_check_blob_from_file (const char *str)
40398 {
40399 /* testing if a Trigger attempts calling the dangerous BlobFromFile() function */
40400 
40401     int contains_blob_from_file = 0;
40402     const char *start = str;
40403     const char *ptr;
40404     while (1)
40405       {
40406 	  char pre;
40407 	  char post;
40408 	  ptr = strstr (start, "blobfromfile");
40409 	  if (ptr == NULL)
40410 	      break;
40411 	  if (ptr > str)
40412 	      pre = *(ptr - 1);
40413 	  else
40414 	      pre = ' ';
40415 	  post = *(ptr + 12);
40416 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40417 	      contains_blob_from_file = 1;
40418 	  start = ptr + 12;
40419       }
40420     return contains_blob_from_file;
40421 }
40422 
40423 static int
do_check_blob_to_file(const char * str)40424 do_check_blob_to_file (const char *str)
40425 {
40426 /* testing if a Trigger attempts calling the dangerous BlobToFile() function */
40427 
40428     int contains_blob_to_file = 0;
40429     const char *start = str;
40430     const char *ptr;
40431     while (1)
40432       {
40433 	  char pre;
40434 	  char post;
40435 	  ptr = strstr (start, "blobtofile");
40436 	  if (ptr == NULL)
40437 	      break;
40438 	  if (ptr > str)
40439 	      pre = *(ptr - 1);
40440 	  else
40441 	      pre = ' ';
40442 	  post = *(ptr + 10);
40443 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40444 	      contains_blob_to_file = 1;
40445 	  start = ptr + 10;
40446       }
40447     return contains_blob_to_file;
40448 }
40449 
40450 static int
do_check_load_xml(const char * str)40451 do_check_load_xml (const char *str)
40452 {
40453 /* testing if a Trigger attempts calling the dangerous XB_LoadXml() function */
40454 
40455     int contains_load_xml = 0;
40456     const char *start = str;
40457     const char *ptr;
40458     while (1)
40459       {
40460 	  char pre;
40461 	  char post;
40462 	  ptr = strstr (start, "xb_loadxml");
40463 	  if (ptr == NULL)
40464 	      break;
40465 	  if (ptr > str)
40466 	      pre = *(ptr - 1);
40467 	  else
40468 	      pre = ' ';
40469 	  post = *(ptr + 10);
40470 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40471 	      contains_load_xml = 1;
40472 	  start = ptr + 10;
40473       }
40474     return contains_load_xml;
40475 }
40476 
40477 static int
do_check_store_xml(const char * str)40478 do_check_store_xml (const char *str)
40479 {
40480 /* testing if a Trigger attempts calling the dangerous XB_StoreXml() function */
40481 
40482     int contains_store_xml = 0;
40483     const char *start = str;
40484     const char *ptr;
40485     while (1)
40486       {
40487 	  char pre;
40488 	  char post;
40489 	  ptr = strstr (start, "xb_storexml");
40490 	  if (ptr == NULL)
40491 	      break;
40492 	  if (ptr > str)
40493 	      pre = *(ptr - 1);
40494 	  else
40495 	      pre = ' ';
40496 	  post = *(ptr + 11);
40497 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40498 	      contains_store_xml = 1;
40499 	  start = ptr + 11;
40500       }
40501     return contains_store_xml;
40502 }
40503 
40504 static int
do_check_export_geo_json(const char * str)40505 do_check_export_geo_json (const char *str)
40506 {
40507 /* testing if a Trigger attempts calling the dangerous ExportGeoJSON() function */
40508 
40509     int contains_export_geo_json = 0;
40510     const char *start = str;
40511     const char *ptr;
40512     while (1)
40513       {
40514 	  char pre;
40515 	  char post;
40516 	  ptr = strstr (start, "exportgeojson");
40517 	  if (ptr == NULL)
40518 	      break;
40519 	  if (ptr > str)
40520 	      pre = *(ptr - 1);
40521 	  else
40522 	      pre = ' ';
40523 	  post = *(ptr + 13);
40524 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40525 	      contains_export_geo_json = 1;
40526 	  start = ptr + 13;
40527       }
40528     return contains_export_geo_json;
40529 }
40530 
40531 static int
do_check_impexp(const char * str,const char * ref)40532 do_check_impexp (const char *str, const char *ref)
40533 {
40534 /*
40535 / testing if a Trigger attempts calling one of the dangerous ExportDXF(),
40536 / ImportDXF(), ExportDBF(), ImportDBF(),  ExportSHP(), ExportSHP(),
40537 / ExportGeoJSON(), ImportGeoJSON2(), ExportKML(), ImportWFS() or
40538 / ImportXLS() functions */
40539 
40540     int contains_impexp = 0;
40541     const char *start = str;
40542     const char *ptr;
40543     while (1)
40544       {
40545 	  char pre;
40546 	  char post;
40547 	  ptr = strstr (start, ref);
40548 	  if (ptr == NULL)
40549 	      break;
40550 	  if (ptr > str)
40551 	      pre = *(ptr - 1);
40552 	  else
40553 	      pre = ' ';
40554 	  post = *(ptr + 9);
40555 	  if (is_word_delimiter (pre, 0) && is_word_delimiter (post, 1))
40556 	      contains_impexp = 1;
40557 	  start = ptr + 9;
40558       }
40559     return contains_impexp;
40560 }
40561 
40562 static void
fnct_CountUnsafeTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)40563 fnct_CountUnsafeTriggers (sqlite3_context * context, int argc,
40564 			  sqlite3_value ** argv)
40565 {
40566 /* SQL function:
40567 / CountUnsafeTriggers()
40568 /
40569 / returns:
40570 / the total count of *unsafe* triggers found
40571 / 0 if no dubious trigger has been identified
40572 */
40573     int ret;
40574     int i;
40575     char **results;
40576     int rows;
40577     int columns;
40578     const char *sql;
40579     sqlite3 *sqlite = sqlite3_context_db_handle (context);
40580     int count = 0;
40581     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40582 
40583 /* checking all Triggers */
40584     sql = "SELECT Lower(sql) FROM sqlite_master WHERE "
40585 	"type IN ('trigger', 'view') AND (sql LIKE '%BlobFromFile%' "
40586 	"OR sql LIKE '%BlobToFile%' OR sql LIKE '%XB_LoadXML%' "
40587 	"OR sql LIKE '%XB_StoreXML%' OR sql LIKE '%ImportDXF%' "
40588 	"OR sql LIKE '%ExportDXF%' OR sql LIKE '%ImportDBF%' "
40589 	"OR sql LIKE '%ExportDBF%' OR sql LIKE '%ImportSHP%' "
40590 	"OR sql LIKE '%ImportZipDBF%' OR sql LIKE '%ImportZipSHP%' "
40591 	"OR sql LIKE '%ExportSHP%' OR sql LIKE '%ExportKML%' "
40592 	"OR sql LIKE '%ExportGeoJSON%' OR (sql LIKE '%eval%' AND sql LIKE '%(%') "
40593 	"OR sql LIKE '%ExportGeoJSON2%' OR sql LIKE '%ImportGeoJSON%' "
40594 	"OR sql LIKE '%ImportWFS%' OR sql LIKE '%ImportXLS%')";
40595     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
40596     if (ret != SQLITE_OK)
40597 	goto unknown;
40598     if (rows < 1)
40599 	;
40600     else
40601       {
40602 	  for (i = 1; i <= rows; i++)
40603 	    {
40604 		int dangerous = 0;
40605 		if (do_check_blob_from_file (results[(i * columns) + 0]))
40606 		    dangerous = 1;
40607 		if (do_check_blob_to_file (results[(i * columns) + 0]))
40608 		    dangerous = 1;
40609 		if (do_check_load_xml (results[(i * columns) + 0]))
40610 		    dangerous = 1;
40611 		if (do_check_store_xml (results[(i * columns) + 0]))
40612 		    dangerous = 1;
40613 		if (do_check_export_geo_json (results[(i * columns) + 0]))
40614 		    dangerous = 1;
40615 		if (do_check_impexp (results[(i * columns) + 0], "importdxf"))
40616 		    dangerous = 1;
40617 		if (do_check_impexp (results[(i * columns) + 0], "exportdxf"))
40618 		    dangerous = 1;
40619 		if (do_check_impexp (results[(i * columns) + 0], "importdbf"))
40620 		    dangerous = 1;
40621 		if (do_check_impexp
40622 		    (results[(i * columns) + 0], "importzipdbf"))
40623 		    dangerous = 1;
40624 		if (do_check_impexp (results[(i * columns) + 0], "exportdbf"))
40625 		    dangerous = 1;
40626 		if (do_check_impexp (results[(i * columns) + 0], "importshp"))
40627 		    dangerous = 1;
40628 		if (do_check_impexp
40629 		    (results[(i * columns) + 0], "importzipshp"))
40630 		    dangerous = 1;
40631 		if (do_check_impexp (results[(i * columns) + 0], "exportshp"))
40632 		    dangerous = 1;
40633 		if (do_check_impexp
40634 		    (results[(i * columns) + 0], "importgeojson"))
40635 		    dangerous = 1;
40636 		if (do_check_impexp
40637 		    (results[(i * columns) + 0], "exportgeojson2"))
40638 		    dangerous = 1;
40639 		if (do_check_impexp (results[(i * columns) + 0], "exportkml"))
40640 		    dangerous = 1;
40641 		if (do_check_impexp (results[(i * columns) + 0], "importwfs"))
40642 		    dangerous = 1;
40643 		if (do_check_impexp (results[(i * columns) + 0], "importxls"))
40644 		    dangerous = 1;
40645 		if (do_check_eval (results[(i * columns) + 0]))
40646 		    dangerous = 1;
40647 		if (dangerous)
40648 		    count++;
40649 	    }
40650       }
40651     sqlite3_free_table (results);
40652   unknown:
40653     sqlite3_result_int (context, count);
40654 }
40655 
40656 static void
fnct_GeodesicLength(sqlite3_context * context,int argc,sqlite3_value ** argv)40657 fnct_GeodesicLength (sqlite3_context * context, int argc, sqlite3_value ** argv)
40658 {
40659 /* SQL function:
40660 / GeodesicLength(BLOB encoded GEOMETRYCOLLECTION)
40661 /
40662 / returns  the total Geodesic length for current geometry
40663 / or NULL if any error is encountered
40664 */
40665     unsigned char *p_blob;
40666     int n_bytes;
40667     double l;
40668     double length = 0.0;
40669     double a;
40670     double b;
40671     double rf;
40672     gaiaGeomCollPtr geo = NULL;
40673     gaiaLinestringPtr line;
40674     gaiaPolygonPtr polyg;
40675     gaiaRingPtr ring;
40676     int ib;
40677     sqlite3 *sqlite = sqlite3_context_db_handle (context);
40678     int gpkg_amphibious = 0;
40679     int gpkg_mode = 0;
40680     struct splite_internal_cache *cache = sqlite3_user_data (context);
40681     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40682     if (cache != NULL)
40683       {
40684 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
40685 	  gpkg_mode = cache->gpkg_mode;
40686       }
40687     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
40688       {
40689 	  sqlite3_result_null (context);
40690 	  return;
40691       }
40692     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
40693     n_bytes = sqlite3_value_bytes (argv[0]);
40694     geo =
40695 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40696 				     gpkg_amphibious);
40697     if (!geo)
40698 	sqlite3_result_null (context);
40699     else
40700       {
40701 	  if (getEllipsoidParams (sqlite, geo->Srid, &a, &b, &rf))
40702 	    {
40703 		line = geo->FirstLinestring;
40704 		while (line)
40705 		  {
40706 		      /* Linestrings */
40707 		      l = gaiaGeodesicTotalLength (a, b, rf,
40708 						   line->DimensionModel,
40709 						   line->Coords, line->Points);
40710 		      if (l < 0.0)
40711 			{
40712 			    length = -1.0;
40713 			    break;
40714 			}
40715 		      length += l;
40716 		      line = line->Next;
40717 		  }
40718 		if (length >= 0)
40719 		  {
40720 		      /* Polygons */
40721 		      polyg = geo->FirstPolygon;
40722 		      while (polyg)
40723 			{
40724 			    /* exterior Ring */
40725 			    ring = polyg->Exterior;
40726 			    l = gaiaGeodesicTotalLength (a, b, rf,
40727 							 ring->DimensionModel,
40728 							 ring->Coords,
40729 							 ring->Points);
40730 			    if (l < 0.0)
40731 			      {
40732 				  length = -1.0;
40733 				  break;
40734 			      }
40735 			    length += l;
40736 			    for (ib = 0; ib < polyg->NumInteriors; ib++)
40737 			      {
40738 				  /* interior Rings */
40739 				  ring = polyg->Interiors + ib;
40740 				  l = gaiaGeodesicTotalLength (a, b, rf,
40741 							       ring->DimensionModel,
40742 							       ring->Coords,
40743 							       ring->Points);
40744 				  if (l < 0.0)
40745 				    {
40746 					length = -1.0;
40747 					break;
40748 				    }
40749 				  length += l;
40750 			      }
40751 			    if (length < 0.0)
40752 				break;
40753 			    polyg = polyg->Next;
40754 			}
40755 		  }
40756 		if (length < 0.0)
40757 		    sqlite3_result_null (context);
40758 		else
40759 		    sqlite3_result_double (context, length);
40760 	    }
40761 	  else
40762 	      sqlite3_result_null (context);
40763 	  gaiaFreeGeomColl (geo);
40764       }
40765 }
40766 
40767 static void
fnct_GreatCircleLength(sqlite3_context * context,int argc,sqlite3_value ** argv)40768 fnct_GreatCircleLength (sqlite3_context * context, int argc,
40769 			sqlite3_value ** argv)
40770 {
40771 /* SQL function:
40772 / GreatCircleLength(BLOB encoded GEOMETRYCOLLECTION)
40773 /
40774 / returns  the total Great Circle length for current geometry
40775 / or NULL if any error is encountered
40776 */
40777     unsigned char *p_blob;
40778     int n_bytes;
40779     double length = 0.0;
40780     double a;
40781     double b;
40782     double rf;
40783     gaiaGeomCollPtr geo = NULL;
40784     gaiaLinestringPtr line;
40785     gaiaPolygonPtr polyg;
40786     gaiaRingPtr ring;
40787     int ib;
40788     sqlite3 *sqlite = sqlite3_context_db_handle (context);
40789     int gpkg_amphibious = 0;
40790     int gpkg_mode = 0;
40791     struct splite_internal_cache *cache = sqlite3_user_data (context);
40792     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40793     if (cache != NULL)
40794       {
40795 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
40796 	  gpkg_mode = cache->gpkg_mode;
40797       }
40798     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
40799       {
40800 	  sqlite3_result_null (context);
40801 	  return;
40802       }
40803     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
40804     n_bytes = sqlite3_value_bytes (argv[0]);
40805     geo =
40806 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40807 				     gpkg_amphibious);
40808     if (!geo)
40809 	sqlite3_result_null (context);
40810     else
40811       {
40812 	  if (getEllipsoidParams (sqlite, geo->Srid, &a, &b, &rf))
40813 	    {
40814 		line = geo->FirstLinestring;
40815 		while (line)
40816 		  {
40817 		      /* Linestrings */
40818 		      length +=
40819 			  gaiaGreatCircleTotalLength (a, b,
40820 						      line->DimensionModel,
40821 						      line->Coords,
40822 						      line->Points);
40823 		      line = line->Next;
40824 		  }
40825 		if (length >= 0)
40826 		  {
40827 		      /* Polygons */
40828 		      polyg = geo->FirstPolygon;
40829 		      while (polyg)
40830 			{
40831 			    /* exterior Ring */
40832 			    ring = polyg->Exterior;
40833 			    length +=
40834 				gaiaGreatCircleTotalLength (a, b,
40835 							    ring->DimensionModel,
40836 							    ring->Coords,
40837 							    ring->Points);
40838 			    for (ib = 0; ib < polyg->NumInteriors; ib++)
40839 			      {
40840 				  /* interior Rings */
40841 				  ring = polyg->Interiors + ib;
40842 				  length +=
40843 				      gaiaGreatCircleTotalLength (a, b,
40844 								  ring->DimensionModel,
40845 								  ring->Coords,
40846 								  ring->Points);
40847 			      }
40848 			    polyg = polyg->Next;
40849 			}
40850 		  }
40851 		sqlite3_result_double (context, length);
40852 	    }
40853 	  else
40854 	      sqlite3_result_null (context);
40855 	  gaiaFreeGeomColl (geo);
40856       }
40857 }
40858 
40859 static void
fnct_GeodesicArcLength(sqlite3_context * context,int argc,sqlite3_value ** argv)40860 fnct_GeodesicArcLength (sqlite3_context * context, int argc,
40861 			sqlite3_value ** argv)
40862 {
40863 /* SQL function:
40864 / GeodesicArcLength(geom1 Geometry, geom2 Geometry)
40865 / GeodesicArcLength(geom1 Geometry, geom2 Geometry, meters Integer)
40866 /
40867 / returns the Arc Length between points 1 and 2
40868 / or NULL if any error is encountered
40869 /
40870 / *******************************************************************
40871 / this SQL function was kindly contributed by Mark Johnson
40872 / <mj10777@googlemail.com>
40873 */
40874     unsigned char *p_blob;
40875     int n_bytes;
40876     gaiaGeomCollPtr geom1 = NULL;
40877     gaiaGeomCollPtr geom2 = NULL;
40878     int return_type = GAIA_GEODESIC_ARC_LENGTH_METERS;
40879     double retval;
40880     sqlite3 *sqlite = sqlite3_context_db_handle (context);
40881     int gpkg_amphibious = 0;
40882     int gpkg_mode = 0;
40883     struct splite_internal_cache *cache = sqlite3_user_data (context);
40884     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40885     if (cache != NULL)
40886       {
40887 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
40888 	  gpkg_mode = cache->gpkg_mode;
40889       }
40890     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
40891       {
40892 	  sqlite3_result_null (context);
40893 	  return;
40894       }
40895     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
40896       {
40897 	  sqlite3_result_null (context);
40898 	  return;
40899       }
40900     if (argc >= 3)
40901       {
40902 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
40903 	    {
40904 		sqlite3_result_null (context);
40905 		return;
40906 	    }
40907 	  if (sqlite3_value_int (argv[2]) == 0)
40908 	      return_type = GAIA_GEODESIC_ARC_LENGTH_DEGREES;
40909       }
40910     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
40911     n_bytes = sqlite3_value_bytes (argv[0]);
40912     geom1 =
40913 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40914 				     gpkg_amphibious);
40915     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
40916     n_bytes = sqlite3_value_bytes (argv[1]);
40917     geom2 =
40918 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40919 				     gpkg_amphibious);
40920 
40921     if (geom1 == NULL || geom2 == NULL)
40922 	sqlite3_result_null (context);
40923     else
40924       {
40925 	  if (gaiaGeodesicArcLength
40926 	      (sqlite, cache, geom1, geom2, return_type, &retval))
40927 	      sqlite3_result_double (context, retval);
40928 	  else
40929 	      sqlite3_result_null (context);
40930       }
40931     if (geom1 != NULL)
40932 	gaiaFreeGeomColl (geom1);
40933     if (geom2 != NULL)
40934 	gaiaFreeGeomColl (geom2);
40935 }
40936 
40937 static void
fnct_GeodesicChordLength(sqlite3_context * context,int argc,sqlite3_value ** argv)40938 fnct_GeodesicChordLength (sqlite3_context * context, int argc,
40939 			  sqlite3_value ** argv)
40940 {
40941 /* SQL function:
40942 / GeodesicChordLength(geom1 Geometry, geom2 Geometry)
40943 / GeodesicChordLength(geom1 Geometry, geom2 Geometry, meters Integer)
40944 /
40945 / returns the Chord Length between points 1 and 2
40946 / or NULL if any error is encountered
40947 /
40948 / *******************************************************************
40949 / this SQL function was kindly contributed by Mark Johnson
40950 / <mj10777@googlemail.com>
40951 */
40952     unsigned char *p_blob;
40953     int n_bytes;
40954     gaiaGeomCollPtr geom1 = NULL;
40955     gaiaGeomCollPtr geom2 = NULL;
40956     int return_type = GAIA_GEODESIC_CHORD_LENGTH_METERS;
40957     double retval;
40958     sqlite3 *sqlite = sqlite3_context_db_handle (context);
40959     int gpkg_amphibious = 0;
40960     int gpkg_mode = 0;
40961     struct splite_internal_cache *cache = sqlite3_user_data (context);
40962     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
40963     if (cache != NULL)
40964       {
40965 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
40966 	  gpkg_mode = cache->gpkg_mode;
40967       }
40968     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
40969       {
40970 	  sqlite3_result_null (context);
40971 	  return;
40972       }
40973     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
40974       {
40975 	  sqlite3_result_null (context);
40976 	  return;
40977       }
40978     if (argc >= 3)
40979       {
40980 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
40981 	    {
40982 		sqlite3_result_null (context);
40983 		return;
40984 	    }
40985 	  if (sqlite3_value_int (argv[2]) == 0)
40986 	      return_type = GAIA_GEODESIC_CHORD_LENGTH_DEGREES;
40987       }
40988     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
40989     n_bytes = sqlite3_value_bytes (argv[0]);
40990     geom1 =
40991 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40992 				     gpkg_amphibious);
40993     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
40994     n_bytes = sqlite3_value_bytes (argv[1]);
40995     geom2 =
40996 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
40997 				     gpkg_amphibious);
40998 
40999     if (!geom1 || !geom2)
41000 	sqlite3_result_null (context);
41001     else
41002       {
41003 	  if (gaiaGeodesicArcLength
41004 	      (sqlite, cache, geom1, geom2, return_type, &retval))
41005 	      sqlite3_result_double (context, retval);
41006 	  else
41007 	      sqlite3_result_null (context);
41008       }
41009     if (geom1 != NULL)
41010 	gaiaFreeGeomColl (geom1);
41011     if (geom2 != NULL)
41012 	gaiaFreeGeomColl (geom2);
41013 }
41014 
41015 static void
fnct_GeodesicCentralAngle(sqlite3_context * context,int argc,sqlite3_value ** argv)41016 fnct_GeodesicCentralAngle (sqlite3_context * context, int argc,
41017 			   sqlite3_value ** argv)
41018 {
41019 /* SQL function:
41020 / GeodesicCentralAngle(geom1 Geometry, geom2 Geometry)
41021 / GeodesicCentralAngle(geom1 Geometry, geom2 Geometry, radians Integer)
41022 /
41023 / returns the Central Angle for the Arc between points 1 and 2
41024 / or NULL if any error is encountered
41025 /
41026 / *******************************************************************
41027 / this SQL function was kindly contributed by Mark Johnson
41028 / <mj10777@googlemail.com>
41029 */
41030     unsigned char *p_blob;
41031     int n_bytes;
41032     gaiaGeomCollPtr geom1 = NULL;
41033     gaiaGeomCollPtr geom2 = NULL;
41034     int return_type = GAIA_GEODESIC_CENTRAL_ANGLE_RADIANS;
41035     double retval;
41036     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41037     int gpkg_amphibious = 0;
41038     int gpkg_mode = 0;
41039     struct splite_internal_cache *cache = sqlite3_user_data (context);
41040     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41041     if (cache != NULL)
41042       {
41043 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
41044 	  gpkg_mode = cache->gpkg_mode;
41045       }
41046     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
41047       {
41048 	  sqlite3_result_null (context);
41049 	  return;
41050       }
41051     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
41052       {
41053 	  sqlite3_result_null (context);
41054 	  return;
41055       }
41056     if (argc >= 3)
41057       {
41058 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
41059 	    {
41060 		sqlite3_result_null (context);
41061 		return;
41062 	    }
41063 	  if (sqlite3_value_int (argv[2]) == 0)
41064 	      return_type = GAIA_GEODESIC_CENTRAL_ANGLE_DEGREES;
41065       }
41066     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
41067     n_bytes = sqlite3_value_bytes (argv[0]);
41068     geom1 =
41069 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41070 				     gpkg_amphibious);
41071     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
41072     n_bytes = sqlite3_value_bytes (argv[1]);
41073     geom2 =
41074 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41075 				     gpkg_amphibious);
41076 
41077     if (!geom1 || !geom2)
41078 	sqlite3_result_null (context);
41079     else
41080       {
41081 	  if (gaiaGeodesicArcLength
41082 	      (sqlite, cache, geom1, geom2, return_type, &retval))
41083 	      sqlite3_result_double (context, retval);
41084 	  else
41085 	      sqlite3_result_null (context);
41086       }
41087     if (geom1 != NULL)
41088 	gaiaFreeGeomColl (geom1);
41089     if (geom2 != NULL)
41090 	gaiaFreeGeomColl (geom2);
41091 }
41092 
41093 static void
fnct_GeodesicArcArea(sqlite3_context * context,int argc,sqlite3_value ** argv)41094 fnct_GeodesicArcArea (sqlite3_context * context, int argc,
41095 		      sqlite3_value ** argv)
41096 {
41097 /* SQL function:
41098 / GeodesicArcArea(geom1 Geometry, geom2 Geometry)
41099 /
41100 / returns the Area (in sq. meters) for the Arc between points 1 and 2
41101 / or NULL if any error is encountered
41102 /
41103 / *******************************************************************
41104 / this SQL function was kindly contributed by Mark Johnson
41105 / <mj10777@googlemail.com>
41106 */
41107     unsigned char *p_blob;
41108     int n_bytes;
41109     gaiaGeomCollPtr geom1 = NULL;
41110     gaiaGeomCollPtr geom2 = NULL;
41111     double retval;
41112     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41113     int gpkg_amphibious = 0;
41114     int gpkg_mode = 0;
41115     struct splite_internal_cache *cache = sqlite3_user_data (context);
41116     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41117     if (cache != NULL)
41118       {
41119 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
41120 	  gpkg_mode = cache->gpkg_mode;
41121       }
41122     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
41123       {
41124 	  sqlite3_result_null (context);
41125 	  return;
41126       }
41127     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
41128       {
41129 	  sqlite3_result_null (context);
41130 	  return;
41131       }
41132     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
41133     n_bytes = sqlite3_value_bytes (argv[0]);
41134     geom1 =
41135 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41136 				     gpkg_amphibious);
41137     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
41138     n_bytes = sqlite3_value_bytes (argv[1]);
41139     geom2 =
41140 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41141 				     gpkg_amphibious);
41142 
41143     if (!geom1 || !geom2)
41144 	sqlite3_result_null (context);
41145     else
41146       {
41147 	  if (gaiaGeodesicArcLength
41148 	      (sqlite, cache, geom1, geom2, GAIA_GEODESIC_ARC_AREA_METERS,
41149 	       &retval))
41150 	      sqlite3_result_double (context, retval);
41151 	  else
41152 	      sqlite3_result_null (context);
41153       }
41154     if (geom1 != NULL)
41155 	gaiaFreeGeomColl (geom1);
41156     if (geom2 != NULL)
41157 	gaiaFreeGeomColl (geom2);
41158 }
41159 
41160 static void
fnct_GeodesicArcHeight(sqlite3_context * context,int argc,sqlite3_value ** argv)41161 fnct_GeodesicArcHeight (sqlite3_context * context, int argc,
41162 			sqlite3_value ** argv)
41163 {
41164 /* SQL function:
41165 / GeodesicArcHeight(geom1 Geometry, geom2 Geometry)
41166 /
41167 / returns the Height (in meters) for the Arc between points 1 and 2
41168 / or NULL if any error is encountered
41169 /
41170 / *******************************************************************
41171 / this SQL function was kindly contributed by Mark Johnson
41172 / <mj10777@googlemail.com>
41173 */
41174     unsigned char *p_blob;
41175     int n_bytes;
41176     gaiaGeomCollPtr geom1 = NULL;
41177     gaiaGeomCollPtr geom2 = NULL;
41178     double retval;
41179     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41180     int gpkg_amphibious = 0;
41181     int gpkg_mode = 0;
41182     struct splite_internal_cache *cache = sqlite3_user_data (context);
41183     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41184     if (cache != NULL)
41185       {
41186 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
41187 	  gpkg_mode = cache->gpkg_mode;
41188       }
41189     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
41190       {
41191 	  sqlite3_result_null (context);
41192 	  return;
41193       }
41194     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
41195       {
41196 	  sqlite3_result_null (context);
41197 	  return;
41198       }
41199     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
41200     n_bytes = sqlite3_value_bytes (argv[0]);
41201     geom1 =
41202 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41203 				     gpkg_amphibious);
41204     p_blob = (unsigned char *) sqlite3_value_blob (argv[1]);
41205     n_bytes = sqlite3_value_bytes (argv[1]);
41206     geom2 =
41207 	gaiaFromSpatiaLiteBlobWkbEx (p_blob, n_bytes, gpkg_mode,
41208 				     gpkg_amphibious);
41209 
41210     if (!geom1 || !geom2)
41211 	sqlite3_result_null (context);
41212     else
41213       {
41214 	  if (gaiaGeodesicArcLength
41215 	      (sqlite, cache, geom1, geom2, GAIA_GEODESIC_ARC_HEIGHT_METERS,
41216 	       &retval))
41217 	      sqlite3_result_double (context, retval);
41218 	  else
41219 	      sqlite3_result_null (context);
41220       }
41221     if (geom1 != NULL)
41222 	gaiaFreeGeomColl (geom1);
41223     if (geom2 != NULL)
41224 	gaiaFreeGeomColl (geom2);
41225 }
41226 
41227 static void
convertUnit(sqlite3_context * context,int argc,sqlite3_value ** argv,int unit_from,int unit_to)41228 convertUnit (sqlite3_context * context, int argc, sqlite3_value ** argv,
41229 	     int unit_from, int unit_to)
41230 {
41231 /* SQL functions:
41232 / CvtToKm(), CvtToDm(), CvtToCm(), CvtToMm(), CvtToKmi(), CvtToIn(), CvtToFt(),
41233 / CvtToYd(), CvtToMi(), CvtToFath(), CvtToCh(), CvtToLink(), CvtToUsIn(),
41234 / CvtToUsFt(), CvtToUsYd(), CvtToUsCh(), CvtToUsMi(), CvtToIndFt(),
41235 / CvtToIndYd(), CvtToIndCh(),
41236 / CvtFromKm(), CvtFromDm(), CvtFromCm(), CvtFromMm(), CvtFromKmi(),
41237 / CvtFromIn(), CvtFromFt(), CvtFromYd(), CvtFromMi(), CvtFromFath(),
41238 / CvtFromCh(), CvtFromLink(), CvtFromUsIn(), CvtFromUsFt(), CvtFromUsYd(),
41239 / CvtFromUsCh(), CvtFromUsMi(), CvtFromIndFt(), CvtFromIndYd(),
41240 / CvtFromIndCh()
41241 /
41242 / converts a Length from one unit to a different one
41243 / or NULL if any error is encountered
41244 */
41245     double cvt;
41246     double value;
41247     int int_value;
41248     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41249     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
41250 	value = sqlite3_value_double (argv[0]);
41251     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
41252       {
41253 	  int_value = sqlite3_value_int (argv[0]);
41254 	  value = int_value;
41255       }
41256     else
41257       {
41258 	  sqlite3_result_null (context);
41259 	  return;
41260       }
41261     if (!gaiaConvertLength (value, unit_from, unit_to, &cvt))
41262 	sqlite3_result_null (context);
41263     else
41264 	sqlite3_result_double (context, cvt);
41265 }
41266 
41267 static void
fnct_cvtToKm(sqlite3_context * context,int argc,sqlite3_value ** argv)41268 fnct_cvtToKm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41269 {
41270     convertUnit (context, argc, argv, GAIA_M, GAIA_KM);
41271 }
41272 
41273 static void
fnct_cvtToDm(sqlite3_context * context,int argc,sqlite3_value ** argv)41274 fnct_cvtToDm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41275 {
41276     convertUnit (context, argc, argv, GAIA_M, GAIA_DM);
41277 }
41278 
41279 static void
fnct_cvtToCm(sqlite3_context * context,int argc,sqlite3_value ** argv)41280 fnct_cvtToCm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41281 {
41282     convertUnit (context, argc, argv, GAIA_M, GAIA_CM);
41283 }
41284 
41285 static void
fnct_cvtToMm(sqlite3_context * context,int argc,sqlite3_value ** argv)41286 fnct_cvtToMm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41287 {
41288     convertUnit (context, argc, argv, GAIA_M, GAIA_MM);
41289 }
41290 
41291 static void
fnct_cvtToKmi(sqlite3_context * context,int argc,sqlite3_value ** argv)41292 fnct_cvtToKmi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41293 {
41294     convertUnit (context, argc, argv, GAIA_M, GAIA_KMI);
41295 }
41296 
41297 static void
fnct_cvtToIn(sqlite3_context * context,int argc,sqlite3_value ** argv)41298 fnct_cvtToIn (sqlite3_context * context, int argc, sqlite3_value ** argv)
41299 {
41300     convertUnit (context, argc, argv, GAIA_M, GAIA_IN);
41301 }
41302 
41303 static void
fnct_cvtToFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41304 fnct_cvtToFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41305 {
41306     convertUnit (context, argc, argv, GAIA_M, GAIA_FT);
41307 }
41308 
41309 static void
fnct_cvtToYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41310 fnct_cvtToYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41311 {
41312     convertUnit (context, argc, argv, GAIA_M, GAIA_YD);
41313 }
41314 
41315 static void
fnct_cvtToMi(sqlite3_context * context,int argc,sqlite3_value ** argv)41316 fnct_cvtToMi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41317 {
41318     convertUnit (context, argc, argv, GAIA_M, GAIA_MI);
41319 }
41320 
41321 static void
fnct_cvtToFath(sqlite3_context * context,int argc,sqlite3_value ** argv)41322 fnct_cvtToFath (sqlite3_context * context, int argc, sqlite3_value ** argv)
41323 {
41324     convertUnit (context, argc, argv, GAIA_M, GAIA_FATH);
41325 }
41326 
41327 static void
fnct_cvtToCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41328 fnct_cvtToCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41329 {
41330     convertUnit (context, argc, argv, GAIA_M, GAIA_CH);
41331 }
41332 
41333 static void
fnct_cvtToLink(sqlite3_context * context,int argc,sqlite3_value ** argv)41334 fnct_cvtToLink (sqlite3_context * context, int argc, sqlite3_value ** argv)
41335 {
41336     convertUnit (context, argc, argv, GAIA_M, GAIA_LINK);
41337 }
41338 
41339 static void
fnct_cvtToUsIn(sqlite3_context * context,int argc,sqlite3_value ** argv)41340 fnct_cvtToUsIn (sqlite3_context * context, int argc, sqlite3_value ** argv)
41341 {
41342     convertUnit (context, argc, argv, GAIA_M, GAIA_US_IN);
41343 }
41344 
41345 static void
fnct_cvtToUsFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41346 fnct_cvtToUsFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41347 {
41348     convertUnit (context, argc, argv, GAIA_M, GAIA_US_FT);
41349 }
41350 
41351 static void
fnct_cvtToUsYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41352 fnct_cvtToUsYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41353 {
41354     convertUnit (context, argc, argv, GAIA_M, GAIA_US_YD);
41355 }
41356 
41357 static void
fnct_cvtToUsCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41358 fnct_cvtToUsCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41359 {
41360     convertUnit (context, argc, argv, GAIA_M, GAIA_US_CH);
41361 }
41362 
41363 static void
fnct_cvtToUsMi(sqlite3_context * context,int argc,sqlite3_value ** argv)41364 fnct_cvtToUsMi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41365 {
41366     convertUnit (context, argc, argv, GAIA_M, GAIA_US_MI);
41367 }
41368 
41369 static void
fnct_cvtToIndFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41370 fnct_cvtToIndFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41371 {
41372     convertUnit (context, argc, argv, GAIA_M, GAIA_IND_FT);
41373 }
41374 
41375 static void
fnct_cvtToIndYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41376 fnct_cvtToIndYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41377 {
41378     convertUnit (context, argc, argv, GAIA_M, GAIA_IND_YD);
41379 }
41380 
41381 static void
fnct_cvtToIndCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41382 fnct_cvtToIndCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41383 {
41384     convertUnit (context, argc, argv, GAIA_M, GAIA_IND_CH);
41385 }
41386 
41387 static void
fnct_cvtFromKm(sqlite3_context * context,int argc,sqlite3_value ** argv)41388 fnct_cvtFromKm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41389 {
41390     convertUnit (context, argc, argv, GAIA_KM, GAIA_M);
41391 }
41392 
41393 static void
fnct_cvtFromDm(sqlite3_context * context,int argc,sqlite3_value ** argv)41394 fnct_cvtFromDm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41395 {
41396     convertUnit (context, argc, argv, GAIA_DM, GAIA_M);
41397 }
41398 
41399 static void
fnct_cvtFromCm(sqlite3_context * context,int argc,sqlite3_value ** argv)41400 fnct_cvtFromCm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41401 {
41402     convertUnit (context, argc, argv, GAIA_CM, GAIA_M);
41403 }
41404 
41405 static void
fnct_cvtFromMm(sqlite3_context * context,int argc,sqlite3_value ** argv)41406 fnct_cvtFromMm (sqlite3_context * context, int argc, sqlite3_value ** argv)
41407 {
41408     convertUnit (context, argc, argv, GAIA_MM, GAIA_M);
41409 }
41410 
41411 static void
fnct_cvtFromKmi(sqlite3_context * context,int argc,sqlite3_value ** argv)41412 fnct_cvtFromKmi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41413 {
41414     convertUnit (context, argc, argv, GAIA_KMI, GAIA_M);
41415 }
41416 
41417 static void
fnct_cvtFromIn(sqlite3_context * context,int argc,sqlite3_value ** argv)41418 fnct_cvtFromIn (sqlite3_context * context, int argc, sqlite3_value ** argv)
41419 {
41420     convertUnit (context, argc, argv, GAIA_IN, GAIA_M);
41421 }
41422 
41423 static void
fnct_cvtFromFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41424 fnct_cvtFromFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41425 {
41426     convertUnit (context, argc, argv, GAIA_FT, GAIA_M);
41427 }
41428 
41429 static void
fnct_cvtFromYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41430 fnct_cvtFromYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41431 {
41432     convertUnit (context, argc, argv, GAIA_YD, GAIA_M);
41433 }
41434 
41435 static void
fnct_cvtFromMi(sqlite3_context * context,int argc,sqlite3_value ** argv)41436 fnct_cvtFromMi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41437 {
41438     convertUnit (context, argc, argv, GAIA_MI, GAIA_M);
41439 }
41440 
41441 static void
fnct_cvtFromFath(sqlite3_context * context,int argc,sqlite3_value ** argv)41442 fnct_cvtFromFath (sqlite3_context * context, int argc, sqlite3_value ** argv)
41443 {
41444     convertUnit (context, argc, argv, GAIA_FATH, GAIA_M);
41445 }
41446 
41447 static void
fnct_cvtFromCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41448 fnct_cvtFromCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41449 {
41450     convertUnit (context, argc, argv, GAIA_CH, GAIA_M);
41451 }
41452 
41453 static void
fnct_cvtFromLink(sqlite3_context * context,int argc,sqlite3_value ** argv)41454 fnct_cvtFromLink (sqlite3_context * context, int argc, sqlite3_value ** argv)
41455 {
41456     convertUnit (context, argc, argv, GAIA_LINK, GAIA_M);
41457 }
41458 
41459 static void
fnct_cvtFromUsIn(sqlite3_context * context,int argc,sqlite3_value ** argv)41460 fnct_cvtFromUsIn (sqlite3_context * context, int argc, sqlite3_value ** argv)
41461 {
41462     convertUnit (context, argc, argv, GAIA_US_IN, GAIA_M);
41463 }
41464 
41465 static void
fnct_cvtFromUsFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41466 fnct_cvtFromUsFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41467 {
41468     convertUnit (context, argc, argv, GAIA_US_FT, GAIA_M);
41469 }
41470 
41471 static void
fnct_cvtFromUsYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41472 fnct_cvtFromUsYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41473 {
41474     convertUnit (context, argc, argv, GAIA_US_YD, GAIA_M);
41475 }
41476 
41477 static void
fnct_cvtFromUsCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41478 fnct_cvtFromUsCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41479 {
41480     convertUnit (context, argc, argv, GAIA_US_CH, GAIA_M);
41481 }
41482 
41483 static void
fnct_cvtFromUsMi(sqlite3_context * context,int argc,sqlite3_value ** argv)41484 fnct_cvtFromUsMi (sqlite3_context * context, int argc, sqlite3_value ** argv)
41485 {
41486     convertUnit (context, argc, argv, GAIA_US_MI, GAIA_M);
41487 }
41488 
41489 static void
fnct_cvtFromIndFt(sqlite3_context * context,int argc,sqlite3_value ** argv)41490 fnct_cvtFromIndFt (sqlite3_context * context, int argc, sqlite3_value ** argv)
41491 {
41492     convertUnit (context, argc, argv, GAIA_IND_FT, GAIA_M);
41493 }
41494 
41495 static void
fnct_cvtFromIndYd(sqlite3_context * context,int argc,sqlite3_value ** argv)41496 fnct_cvtFromIndYd (sqlite3_context * context, int argc, sqlite3_value ** argv)
41497 {
41498     convertUnit (context, argc, argv, GAIA_IND_YD, GAIA_M);
41499 }
41500 
41501 static void
fnct_cvtFromIndCh(sqlite3_context * context,int argc,sqlite3_value ** argv)41502 fnct_cvtFromIndCh (sqlite3_context * context, int argc, sqlite3_value ** argv)
41503 {
41504     convertUnit (context, argc, argv, GAIA_IND_CH, GAIA_M);
41505 }
41506 
41507 static void
fnct_longFromDMS(sqlite3_context * context,int argc,sqlite3_value ** argv)41508 fnct_longFromDMS (sqlite3_context * context, int argc, sqlite3_value ** argv)
41509 {
41510 /* SQL function:
41511 / LongitudeFromDMS ( dms_string )
41512 /
41513 / return the Longitude (in Decimal Degrees) from a DMS text expression
41514 / or NULL if any error is encountered
41515 */
41516     const char *dms;
41517     double longitude;
41518     double latitude;
41519     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41520     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
41521 	dms = (const char *) sqlite3_value_text (argv[0]);
41522     else
41523       {
41524 	  sqlite3_result_null (context);
41525 	  return;
41526       }
41527     if (!gaiaParseDMS (dms, &longitude, &latitude))
41528 	sqlite3_result_null (context);
41529     else
41530 	sqlite3_result_double (context, longitude);
41531 }
41532 
41533 static void
fnct_latFromDMS(sqlite3_context * context,int argc,sqlite3_value ** argv)41534 fnct_latFromDMS (sqlite3_context * context, int argc, sqlite3_value ** argv)
41535 {
41536 /* SQL function:
41537 / LatitudeFromDMS ( dms_string )
41538 /
41539 / return the Latitude (in Decimal Degrees) from a DMS text expression
41540 / or NULL if any error is encountered
41541 */
41542     const char *dms;
41543     double longitude;
41544     double latitude;
41545     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41546     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
41547 	dms = (const char *) sqlite3_value_text (argv[0]);
41548     else
41549       {
41550 	  sqlite3_result_null (context);
41551 	  return;
41552       }
41553     if (!gaiaParseDMS (dms, &longitude, &latitude))
41554 	sqlite3_result_null (context);
41555     else
41556 	sqlite3_result_double (context, latitude);
41557 }
41558 
41559 static void
fnct_toDMS(sqlite3_context * context,int argc,sqlite3_value ** argv)41560 fnct_toDMS (sqlite3_context * context, int argc, sqlite3_value ** argv)
41561 {
41562 /* SQL function:
41563 / LongLatToDMS ( longitude, latitude )
41564 /     or
41565 / LongLatToDMS ( longitude, latitude, decimal_digits )
41566 /
41567 / return a DMS text expression
41568 / or NULL if any error is encountered
41569 */
41570     double longitude;
41571     double latitude;
41572     int decimal_digits = 0;
41573     char *dms;
41574     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41575     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
41576 	longitude = sqlite3_value_double (argv[0]);
41577     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
41578       {
41579 	  int value = sqlite3_value_int (argv[0]);
41580 	  longitude = value;
41581       }
41582     else
41583       {
41584 	  sqlite3_result_null (context);
41585 	  return;
41586       }
41587     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
41588 	latitude = sqlite3_value_double (argv[1]);
41589     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
41590       {
41591 	  int value = sqlite3_value_int (argv[1]);
41592 	  latitude = value;
41593       }
41594     else
41595       {
41596 	  sqlite3_result_null (context);
41597 	  return;
41598       }
41599     if (argc >= 3)
41600       {
41601 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
41602 	    {
41603 		sqlite3_result_null (context);
41604 		return;
41605 	    }
41606 	  decimal_digits = sqlite3_value_int (argv[2]);
41607       }
41608     dms = gaiaConvertToDMSex (longitude, latitude, decimal_digits);
41609     if (dms == NULL)
41610 	sqlite3_result_null (context);
41611     else
41612 	sqlite3_result_text (context, dms, strlen (dms), free);
41613 }
41614 
41615 static void
fnct_sequence_currval(sqlite3_context * context,int argc,sqlite3_value ** argv)41616 fnct_sequence_currval (sqlite3_context * context, int argc,
41617 		       sqlite3_value ** argv)
41618 {
41619 /* SQL function:
41620 / sequence_currval ( seq_name TEXT )
41621 /
41622 / return the current value from some Sequence
41623 / or NULL if any error is encountered
41624 */
41625     const char *seq_name = NULL;
41626     gaiaSequencePtr seq;
41627     struct splite_internal_cache *cache = sqlite3_user_data (context);
41628     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41629     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
41630 	seq_name = (const char *) sqlite3_value_text (argv[0]);
41631     seq = gaiaFindSequence (cache, seq_name);
41632     if (seq == NULL)
41633 	sqlite3_result_null (context);
41634     else
41635 	sqlite3_result_int (context, seq->value);
41636 }
41637 
41638 static void
fnct_sequence_lastval(sqlite3_context * context,int argc,sqlite3_value ** argv)41639 fnct_sequence_lastval (sqlite3_context * context, int argc,
41640 		       sqlite3_value ** argv)
41641 {
41642 /* SQL function:
41643 / sequence_lastval ()
41644 /
41645 / return the last value returned by sequence_nextval()
41646 / or NULL if any error is encountered
41647 */
41648     int value;
41649     struct splite_internal_cache *cache = sqlite3_user_data (context);
41650     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41651     if (gaiaLastUsedSequence (cache, &value) == 0)
41652 	sqlite3_result_null (context);
41653     else
41654 	sqlite3_result_int (context, value);
41655 }
41656 
41657 static void
fnct_sequence_nextval(sqlite3_context * context,int argc,sqlite3_value ** argv)41658 fnct_sequence_nextval (sqlite3_context * context, int argc,
41659 		       sqlite3_value ** argv)
41660 {
41661 /* SQL function:
41662 / sequence_nextval ( seq_name TEXT )
41663 /
41664 / return the next value from some Sequence
41665 / or NULL if any error is encountered
41666 */
41667     const char *seq_name = NULL;
41668     gaiaSequencePtr seq;
41669     struct splite_internal_cache *cache = sqlite3_user_data (context);
41670     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41671     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
41672 	seq_name = (const char *) sqlite3_value_text (argv[0]);
41673     seq = gaiaFindSequence (cache, seq_name);
41674     if (seq == NULL)
41675       {
41676 	  seq = gaiaCreateSequence (cache, seq_name);
41677 	  if (seq == NULL)
41678 	      sqlite3_result_null (context);
41679 	  else
41680 	    {
41681 		gaiaSequenceNext (cache, seq);
41682 		sqlite3_result_int (context, seq->value);
41683 	    }
41684       }
41685     else
41686       {
41687 	  gaiaSequenceNext (cache, seq);
41688 	  sqlite3_result_int (context, seq->value);
41689       }
41690 }
41691 
41692 static void
fnct_sequence_setval(sqlite3_context * context,int argc,sqlite3_value ** argv)41693 fnct_sequence_setval (sqlite3_context * context, int argc,
41694 		      sqlite3_value ** argv)
41695 {
41696 /* SQL function:
41697 / sequence_setval ( seq_name TEXT , value INT )
41698 /
41699 / resets the next value for some Sequence and return the value itself
41700 / or NULL if any error is encountered
41701 */
41702     const char *seq_name = NULL;
41703     int value;
41704     gaiaSequencePtr seq;
41705     struct splite_internal_cache *cache = sqlite3_user_data (context);
41706     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41707     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
41708 	seq_name = (const char *) sqlite3_value_text (argv[0]);
41709     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
41710 	value = sqlite3_value_int (argv[1]);
41711     else
41712       {
41713 	  sqlite3_result_null (context);
41714 	  return;
41715       }
41716     seq = gaiaFindSequence (cache, seq_name);
41717     if (seq == NULL)
41718       {
41719 	  seq = gaiaCreateSequence (cache, seq_name);
41720 	  if (seq == NULL)
41721 	      sqlite3_result_null (context);
41722 	  else
41723 	    {
41724 		gaiaResetSequence (seq, value);
41725 		sqlite3_result_int (context, seq->value);
41726 	    }
41727       }
41728     else
41729       {
41730 	  gaiaResetSequence (seq, value);
41731 	  sqlite3_result_int (context, seq->value);
41732       }
41733 }
41734 
41735 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
41736 
41737 static void
fnct_CreateStylingTables(sqlite3_context * context,int argc,sqlite3_value ** argv)41738 fnct_CreateStylingTables (sqlite3_context * context, int argc,
41739 			  sqlite3_value ** argv)
41740 {
41741 /* SQL function:
41742 / CreateStylingTables()
41743 /  or
41744 / CreateStylingTables(bool relaxed)
41745 /  or
41746 / CreateStylingTables(bool relaxed, bool transaction)
41747 /
41748 / creates any SLD/SE related table
41749 / returns 1 on success
41750 / 0 on failure, -1 on invalid arguments
41751 */
41752     int relaxed = 0;
41753     int transaction = 0;
41754     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41755     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41756     if (argc >= 1)
41757       {
41758 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
41759 	    {
41760 		sqlite3_result_int (context, -1);
41761 		return;
41762 	    }
41763 	  relaxed = sqlite3_value_int (argv[0]);
41764       }
41765     if (argc >= 2)
41766       {
41767 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
41768 	    {
41769 		sqlite3_result_int (context, -1);
41770 		return;
41771 	    }
41772 	  transaction = sqlite3_value_int (argv[1]);
41773       }
41774 
41775     if (!createStylingTables_ex (sqlite, relaxed, transaction))
41776 	goto error;
41777     updateSpatiaLiteHistory (sqlite, "*** SE Styling ***", NULL,
41778 			     "Styling tables successfully created");
41779     sqlite3_result_int (context, 1);
41780     return;
41781 
41782   error:
41783     sqlite3_result_int (context, 0);
41784     return;
41785 }
41786 
41787 static void
fnct_ReCreateStylingTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)41788 fnct_ReCreateStylingTriggers (sqlite3_context * context, int argc,
41789 			      sqlite3_value ** argv)
41790 {
41791 /* SQL function:
41792 / ReCreateStylingTriggers()
41793 /  or
41794 / ReCreateStylingTriggers(bool relaxed)
41795 /  or
41796 / ReCreateStylingTriggers(bool relaxed, bool transaction)
41797 /
41798 / (re)creates any SLD/SE related trigger
41799 / returns 1 on success
41800 / 0 on failure, -1 on invalid arguments
41801 */
41802     int relaxed = 0;
41803     int transaction = 0;
41804     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41805     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41806     if (argc >= 1)
41807       {
41808 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
41809 	    {
41810 		sqlite3_result_int (context, -1);
41811 		return;
41812 	    }
41813 	  relaxed = sqlite3_value_int (argv[0]);
41814       }
41815     if (argc >= 2)
41816       {
41817 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
41818 	    {
41819 		sqlite3_result_int (context, -1);
41820 		return;
41821 	    }
41822 	  transaction = sqlite3_value_int (argv[1]);
41823       }
41824 
41825     if (!reCreateStylingTriggers (sqlite, relaxed, transaction))
41826 	goto error;
41827     updateSpatiaLiteHistory (sqlite, "*** SE Styling ***", NULL,
41828 			     "Styling triggers successfully (re)created");
41829     sqlite3_result_int (context, 1);
41830     return;
41831 
41832   error:
41833     sqlite3_result_int (context, 0);
41834     return;
41835 }
41836 
41837 static void
fnct_AutoRegisterStandardBrushes(sqlite3_context * context,int argc,sqlite3_value ** argv)41838 fnct_AutoRegisterStandardBrushes (sqlite3_context * context, int argc,
41839 				  sqlite3_value ** argv)
41840 {
41841 /* SQL function:
41842 / AutoRegisterStandardBrushes()
41843 /
41844 / insert all Standard Brushes
41845 / returns NULL
41846 */
41847     char *sql;
41848     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41849     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41850 /* standard HORZ brush */
41851     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41852 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41853 			   "http://www.utopia.gov/stdbrush_horz.png",
41854 			   "stdbrush_horz", "PNG icon: 16 X 16",
41855 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F052A0AA4776C2D0000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E6507000000114944415408D76360C006FEFF07216C00005FD003FD0222B80F0000000049454E44AE426082'",
41856 			   "stdbrush_horz.png");
41857     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41858     sqlite3_free (sql);
41859 /* standard VERT brush */
41860     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41861 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41862 			   "http://www.utopia.gov/stdbrush_vert.png",
41863 			   "stdbrush_vert", "PNG icon: 16 X 16",
41864 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F052C140822F6C80000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E65070000000E4944415408D763606C6020050100BDB80811166C49120000000049454E44AE426082'",
41865 			   "stdbrush_vert.png");
41866     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41867     sqlite3_free (sql);
41868 /* standard CROSS brush */
41869     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41870 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41871 			   "http://www.utopia.gov/stdbrush_cross.png",
41872 			   "stdbrush_cross", "PNG icon: 16 X 16",
41873 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F052B2111D0A42C0000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E6507000000134944415408D763606C60C044FFFF831036290005B60B0B55E3F2160000000049454E44AE426082'",
41874 			   "stdbrush_horz.png");
41875     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41876     sqlite3_free (sql);
41877 /* standard DIAG1 brush */
41878     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41879 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41880 			   "http://www.utopia.gov/stdbrush_diag1.png",
41881 			   "stdbrush_diag1", "PNG icon: 16 X 16",
41882 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F053A2AD5DB5EB40000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E6507000000284944415408D76338C0C8F08081A18081C18281418681818F81819D8181B98181F10003A644033300A53305FB13D67A660000000049454E44AE426082'",
41883 			   "stdbrush_diag1.png");
41884     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41885     sqlite3_free (sql);
41886 /* standard DIAG2 brush */
41887     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41888 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41889 			   "http://www.utopia.gov/stdbrush_diag2.png",
41890 			   "stdbrush_diag2", "PNG icon: 16 X 16",
41891 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F060413C95D73980000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E6507000000284944415408D76368606660606760E06360906160B0606028606078C0C0788081B9015398E10023007A0D05FB2ED2A2EB0000000049454E44AE426082'",
41892 			   "stdbrush_diag2.png");
41893     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41894     sqlite3_free (sql);
41895 /* standard CROSSDIAG brush */
41896     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41897 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41898 			   "http://www.utopia.gov/stdbrush_crossdiag.png",
41899 			   "stdbrush_crossdiag", "PNG icon: 16 X 16",
41900 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F060233A469F4D60000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E65070000002F4944415408D76338C0CCF0809DA1808FC1428641C68281AF8081FD0103F301100232805CA020500AA800A8EC003300EEB009F1542AF56B0000000049454E44AE426082'",
41901 			   "stdbrush_crossdiag.png");
41902     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41903     sqlite3_free (sql);
41904 // standard DOTS brush
41905     sql = sqlite3_mprintf ("INSERT OR IGNORE INTO main.SE_external_graphics "
41906 			   "(xlink_href, title, abstract, resource, file_name) VALUES (%Q, %Q, %Q, %s, %Q)",
41907 			   "http://www.utopia.gov/stdbrush_dots.png",
41908 			   "stdbrush_dots", "PNG icon: 16 X 16",
41909 			   "x'89504E470D0A1A0A0000000D4948445200000010000000100103000000253D6D2200000006504C5445000000000000A567B9CF0000000174524E530040E6D86600000001624B47440088051D48000000097048597300000B1300000B1301009A9C180000000774494D4507E2071F061A20A2CC2D510000001D69545874436F6D6D656E7400000000004372656174656420776974682047494D50642E65070000001F4944415408D76338C0CCD0C0C8800C181B18980F801090810C80CA0E30030079B00511EB64F1C50000000049454E44AE426082'",
41910 			   "stdbrush_dots.png");
41911     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
41912     sqlite3_free (sql);
41913     sqlite3_result_null (context);
41914 }
41915 
41916 static void
fnct_RegisterExternalGraphic(sqlite3_context * context,int argc,sqlite3_value ** argv)41917 fnct_RegisterExternalGraphic (sqlite3_context * context, int argc,
41918 			      sqlite3_value ** argv)
41919 {
41920 /* SQL function:
41921 / RegisterExternalGraphic(String xlink_href, BLOB resource)
41922 /  or
41923 / RegisterExternalGraphic(String xlink_href, BLOB resource, string title,
41924 /						  String abstract, String file_name)
41925 /
41926 / insert or updates an External Graphic
41927 / returns 1 on success
41928 / 0 on failure, -1 on invalid arguments
41929 */
41930     int ret;
41931     const char *xlink_href;
41932     const char *title = NULL;
41933     const char *abstract = NULL;
41934     const char *file_name = NULL;
41935     const unsigned char *p_blob;
41936     int n_bytes;
41937     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41938     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41939     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
41940       {
41941 	  sqlite3_result_int (context, -1);
41942 	  return;
41943       }
41944     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
41945       {
41946 	  sqlite3_result_int (context, -1);
41947 	  return;
41948       }
41949     if (argc == 5)
41950       {
41951 	  /* optional extra args */
41952 	  if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
41953 	    {
41954 		sqlite3_result_int (context, -1);
41955 		return;
41956 	    }
41957 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT)
41958 	    {
41959 		sqlite3_result_int (context, -1);
41960 		return;
41961 	    }
41962 	  if (sqlite3_value_type (argv[4]) != SQLITE_TEXT)
41963 	    {
41964 		sqlite3_result_int (context, -1);
41965 		return;
41966 	    }
41967       }
41968     xlink_href = (const char *) sqlite3_value_text (argv[0]);
41969     p_blob = sqlite3_value_blob (argv[1]);
41970     n_bytes = sqlite3_value_bytes (argv[1]);
41971     if (argc == 5)
41972       {
41973 	  title = (const char *) sqlite3_value_text (argv[2]);
41974 	  abstract = (const char *) sqlite3_value_text (argv[3]);
41975 	  file_name = (const char *) sqlite3_value_text (argv[4]);
41976       }
41977     ret = register_external_graphic (sqlite, xlink_href, p_blob, n_bytes,
41978 				     title, abstract, file_name);
41979     sqlite3_result_int (context, ret);
41980 }
41981 
41982 static void
fnct_UnregisterExternalGraphic(sqlite3_context * context,int argc,sqlite3_value ** argv)41983 fnct_UnregisterExternalGraphic (sqlite3_context * context, int argc,
41984 				sqlite3_value ** argv)
41985 {
41986 /* SQL function:
41987 / UnregisterExternalGraphic(String xlink_href)
41988 /
41989 / removes an External Graphic
41990 / returns 1 on success
41991 / 0 on failure, -1 on invalid arguments
41992 */
41993     int ret;
41994     const char *xlink_href;
41995     sqlite3 *sqlite = sqlite3_context_db_handle (context);
41996     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
41997     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
41998       {
41999 	  sqlite3_result_int (context, -1);
42000 	  return;
42001       }
42002     xlink_href = (const char *) sqlite3_value_text (argv[0]);
42003     ret = unregister_external_graphic (sqlite, xlink_href);
42004     sqlite3_result_int (context, ret);
42005 }
42006 
42007 static void
fnct_RegisterVectorCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42008 fnct_RegisterVectorCoverage (sqlite3_context * context, int argc,
42009 			     sqlite3_value ** argv)
42010 {
42011 /* SQL function:
42012 / RegisterVectorCoverage(Text coverage_name, Text f_table_name,
42013 /                        Text f_geometry_column)
42014 /   or
42015 / RegisterVectorCoverage(Text coverage_name, Text f_table_name,
42016 /                        Text f_geometry_column, Text title,
42017 /                        Text abstract)
42018 /   or
42019 / RegisterVectorCoverage(Text coverage_name, Text f_table_name,
42020 /                        Text f_geometry_column, Text title,
42021 /                        Text abstract, Bool is_queryable,
42022 /                        Bool is_editable)
42023 /
42024 / inserts a Vector Coverage
42025 / returns 1 on success
42026 / 0 on failure, -1 on invalid arguments
42027 */
42028     int ret;
42029     const char *coverage_name;
42030     const char *f_table_name;
42031     const char *f_geometry_column;
42032     const char *title = NULL;
42033     const char *abstract = NULL;
42034     int is_queryable = 0;
42035     int is_editable = 0;
42036     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42037     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42038     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42039 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
42040 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
42041       {
42042 	  sqlite3_result_int (context, -1);
42043 	  return;
42044       }
42045     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42046     f_table_name = (const char *) sqlite3_value_text (argv[1]);
42047     f_geometry_column = (const char *) sqlite3_value_text (argv[2]);
42048     if (argc >= 5)
42049       {
42050 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT
42051 	      || sqlite3_value_type (argv[4]) != SQLITE_TEXT)
42052 	    {
42053 		sqlite3_result_int (context, -1);
42054 		return;
42055 	    }
42056 	  title = (const char *) sqlite3_value_text (argv[3]);
42057 	  abstract = (const char *) sqlite3_value_text (argv[4]);
42058       }
42059     if (argc >= 7)
42060       {
42061 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER
42062 	      || sqlite3_value_type (argv[6]) != SQLITE_INTEGER)
42063 	    {
42064 		sqlite3_result_int (context, -1);
42065 		return;
42066 	    }
42067 	  is_queryable = sqlite3_value_int (argv[5]);
42068 	  is_editable = sqlite3_value_int (argv[6]);
42069       }
42070     ret =
42071 	register_vector_coverage (sqlite, coverage_name, f_table_name,
42072 				  f_geometry_column, title, abstract,
42073 				  is_queryable, is_editable);
42074     sqlite3_result_int (context, ret);
42075 }
42076 
42077 static void
fnct_RegisterSpatialViewCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42078 fnct_RegisterSpatialViewCoverage (sqlite3_context * context, int argc,
42079 				  sqlite3_value ** argv)
42080 {
42081 /* SQL function:
42082 / RegisterSpatialViewCoverage(Text coverage_name, Text view_name,
42083 /                             Text view_geometry)
42084 /   or
42085 / RegisterSpatialViewCoverage(Text coverage_name, Text view_name,
42086 /                             Text view_geometry, Text title,
42087 /                             Text abstract)
42088 /   or
42089 / RegisterSpatialViewCoverage(Text coverage_name, Text view_name,
42090 /                             Text view_geometry, Text title,
42091 /                             Text abstract, Bool is_queryable,
42092 /                             Bool is_editable)
42093 /
42094 / inserts a Vector Coverage based upon a Spatial View
42095 / returns 1 on success
42096 / 0 on failure, -1 on invalid arguments
42097 */
42098     int ret;
42099     const char *coverage_name;
42100     const char *view_name;
42101     const char *view_geometry;
42102     const char *title = NULL;
42103     const char *abstract = NULL;
42104     int is_queryable = 0;
42105     int is_editable = 0;
42106     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42107     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42108     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42109 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
42110 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
42111       {
42112 	  sqlite3_result_int (context, -1);
42113 	  return;
42114       }
42115     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42116     view_name = (const char *) sqlite3_value_text (argv[1]);
42117     view_geometry = (const char *) sqlite3_value_text (argv[2]);
42118     if (argc >= 5)
42119       {
42120 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT
42121 	      || sqlite3_value_type (argv[4]) != SQLITE_TEXT)
42122 	    {
42123 		sqlite3_result_int (context, -1);
42124 		return;
42125 	    }
42126 	  title = (const char *) sqlite3_value_text (argv[3]);
42127 	  abstract = (const char *) sqlite3_value_text (argv[4]);
42128       }
42129     if (argc >= 7)
42130       {
42131 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER
42132 	      || sqlite3_value_type (argv[6]) != SQLITE_INTEGER)
42133 	    {
42134 		sqlite3_result_int (context, -1);
42135 		return;
42136 	    }
42137 	  is_queryable = sqlite3_value_int (argv[5]);
42138 	  is_editable = sqlite3_value_int (argv[6]);
42139       }
42140     ret =
42141 	register_spatial_view_coverage (sqlite, coverage_name, view_name,
42142 					view_geometry, title, abstract,
42143 					is_queryable, is_editable);
42144     sqlite3_result_int (context, ret);
42145 }
42146 
42147 static void
fnct_RegisterVirtualTableCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42148 fnct_RegisterVirtualTableCoverage (sqlite3_context * context, int argc,
42149 				   sqlite3_value ** argv)
42150 {
42151 /* SQL function:
42152 / RegisterVirtualTableCoverage(Text coverage_name, Text virt_name,
42153 /                              Text virt_geometry)
42154 /   or
42155 / RegisterVirtualTableCoverage(Text coverage_name, Text virt_name,
42156 /                              Text virt_geometry, Text title,
42157 /                              Text abstract)
42158 /   or
42159 / RegisterVirtualTableCoverage(Text coverage_name, Text virt_name,
42160 /                              Text virt_geometry, Text title,
42161 /                              Text abstract, Bool is_queryable)
42162 /
42163 / note: both RegisterVirtualShapeCoverage() and
42164 / RegisterVirtualGeoJsonCoverage() are accepted
42165 / as valid alias names
42166 /
42167 / inserts a Vector Coverage based upon a VirtualTable
42168 / returns 1 on success
42169 / 0 on failure, -1 on invalid arguments
42170 */
42171     int ret;
42172     const char *coverage_name;
42173     const char *virt_name;
42174     const char *virt_geometry;
42175     const char *title = NULL;
42176     const char *abstract = NULL;
42177     int is_queryable = 0;
42178     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42179     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42180     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42181 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
42182 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
42183       {
42184 	  sqlite3_result_int (context, -1);
42185 	  return;
42186       }
42187     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42188     virt_name = (const char *) sqlite3_value_text (argv[1]);
42189     virt_geometry = (const char *) sqlite3_value_text (argv[2]);
42190     if (argc >= 5)
42191       {
42192 	  if (sqlite3_value_type (argv[3]) != SQLITE_TEXT
42193 	      || sqlite3_value_type (argv[4]) != SQLITE_TEXT)
42194 	    {
42195 		sqlite3_result_int (context, -1);
42196 		return;
42197 	    }
42198 	  title = (const char *) sqlite3_value_text (argv[3]);
42199 	  abstract = (const char *) sqlite3_value_text (argv[4]);
42200       }
42201     if (argc >= 6)
42202       {
42203 	  if (sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
42204 	    {
42205 		sqlite3_result_int (context, -1);
42206 		return;
42207 	    }
42208 	  is_queryable = sqlite3_value_int (argv[5]);
42209       }
42210     ret =
42211 	register_virtual_table_coverage (sqlite, coverage_name, virt_name,
42212 					 virt_geometry, title, abstract,
42213 					 is_queryable);
42214     sqlite3_result_int (context, ret);
42215 }
42216 
42217 static void
fnct_RegisterTopoGeoCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42218 fnct_RegisterTopoGeoCoverage (sqlite3_context * context, int argc,
42219 			      sqlite3_value ** argv)
42220 {
42221 /* SQL function:
42222 / RegisterTopoGeoCoverage(Text coverage_name, Text topogeo_name)
42223 /   or
42224 / RegisterTopoGeoCoverage(Text coverage_name, Text topogeo_name,
42225 /                         Text title, Text abstract)
42226 /   or
42227 / RegisterTopoGeoCoverage(Text coverage_name, Text topogeo_name,
42228 /                         Text title, Text abstract, Bool is_queryable,
42229 /                         Bool is_editable)
42230 /
42231 / inserts a Vector Coverage based on some Topology-Geometry
42232 / returns 1 on success
42233 / 0 on failure, -1 on invalid arguments
42234 */
42235     int ret;
42236     const char *coverage_name;
42237     const char *topogeo_name;
42238     const char *title = NULL;
42239     const char *abstract = NULL;
42240     int is_queryable = 0;
42241     int is_editable = 0;
42242     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42243     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42244     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42245 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
42246       {
42247 	  sqlite3_result_int (context, -1);
42248 	  return;
42249       }
42250     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42251     topogeo_name = (const char *) sqlite3_value_text (argv[1]);
42252     if (argc >= 4)
42253       {
42254 	  if (sqlite3_value_type (argv[2]) != SQLITE_TEXT
42255 	      || sqlite3_value_type (argv[3]) != SQLITE_TEXT)
42256 	    {
42257 		sqlite3_result_int (context, -1);
42258 		return;
42259 	    }
42260 	  title = (const char *) sqlite3_value_text (argv[2]);
42261 	  abstract = (const char *) sqlite3_value_text (argv[3]);
42262       }
42263     if (argc >= 6)
42264       {
42265 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER
42266 	      || sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
42267 	    {
42268 		sqlite3_result_int (context, -1);
42269 		return;
42270 	    }
42271 	  is_queryable = sqlite3_value_int (argv[4]);
42272 	  is_editable = sqlite3_value_int (argv[5]);
42273       }
42274     ret =
42275 	register_topogeo_coverage (sqlite, coverage_name, topogeo_name,
42276 				   title, abstract, is_queryable, is_editable);
42277     sqlite3_result_int (context, ret);
42278 }
42279 
42280 static void
fnct_RegisterTopoNetCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42281 fnct_RegisterTopoNetCoverage (sqlite3_context * context, int argc,
42282 			      sqlite3_value ** argv)
42283 {
42284 /* SQL function:
42285 / RegisterTopoNetCoverage(Text coverage_name, Text toponet_name)
42286 /   or
42287 / RegisterTopoNetCoverage(Text coverage_name, Text toponet_name,
42288 /                         Text title, Text abstract)
42289 /   or
42290 / RegisterTopoNetCoverage(Text coverage_name, Text toponet_name,
42291 /                         Text title, Text abstract, Bool is_queryable,
42292 /                         Bool is_editable)
42293 /
42294 / inserts a Vector Coverage based on some Topology-Network
42295 / returns 1 on success
42296 / 0 on failure, -1 on invalid arguments
42297 */
42298     int ret;
42299     const char *coverage_name;
42300     const char *toponet_name;
42301     const char *title = NULL;
42302     const char *abstract = NULL;
42303     int is_queryable = 0;
42304     int is_editable = 0;
42305     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42306     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42307     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42308 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
42309       {
42310 	  sqlite3_result_int (context, -1);
42311 	  return;
42312       }
42313     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42314     toponet_name = (const char *) sqlite3_value_text (argv[1]);
42315     if (argc >= 4)
42316       {
42317 	  if (sqlite3_value_type (argv[2]) != SQLITE_TEXT
42318 	      || sqlite3_value_type (argv[3]) != SQLITE_TEXT)
42319 	    {
42320 		sqlite3_result_int (context, -1);
42321 		return;
42322 	    }
42323 	  title = (const char *) sqlite3_value_text (argv[2]);
42324 	  abstract = (const char *) sqlite3_value_text (argv[3]);
42325       }
42326     if (argc >= 6)
42327       {
42328 	  if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER
42329 	      || sqlite3_value_type (argv[5]) != SQLITE_INTEGER)
42330 	    {
42331 		sqlite3_result_int (context, -1);
42332 		return;
42333 	    }
42334 	  is_queryable = sqlite3_value_int (argv[4]);
42335 	  is_editable = sqlite3_value_int (argv[5]);
42336       }
42337     ret =
42338 	register_toponet_coverage (sqlite, coverage_name, toponet_name,
42339 				   title, abstract, is_queryable, is_editable);
42340     sqlite3_result_int (context, ret);
42341 }
42342 
42343 static void
fnct_UnregisterVectorCoverage(sqlite3_context * context,int argc,sqlite3_value ** argv)42344 fnct_UnregisterVectorCoverage (sqlite3_context * context, int argc,
42345 			       sqlite3_value ** argv)
42346 {
42347 /* SQL function:
42348 / UnRegisterVectorCoverage(Text coverage_name)
42349 /
42350 / deletes a Vector Coverage
42351 / returns 1 on success
42352 / 0 on failure, -1 on invalid arguments
42353 */
42354     int ret;
42355     const char *coverage_name;
42356     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42357     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42358     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
42359       {
42360 	  sqlite3_result_int (context, -1);
42361 	  return;
42362       }
42363     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42364     ret = unregister_vector_coverage (sqlite, coverage_name);
42365     sqlite3_result_int (context, ret);
42366 }
42367 
42368 static void
fnct_SetVectorCoverageInfos(sqlite3_context * context,int argc,sqlite3_value ** argv)42369 fnct_SetVectorCoverageInfos (sqlite3_context * context, int argc,
42370 			     sqlite3_value ** argv)
42371 {
42372 /* SQL function:
42373 / SetVectorCoverageInfos(Text coverage_name, Text title,
42374 /                        Text abstract)
42375 /    or
42376 / SetVectorCoverageInfos(Text coverage_name, Text title,
42377 /                        Text abstract, Bool is_queryable,
42378 /                        Bool is_editable)
42379 /
42380 / updates the descriptive infos supporting a Vector Coverage
42381 / returns 1 on success
42382 / 0 on failure, -1 on invalid arguments
42383 */
42384     int ret;
42385     const char *coverage_name;
42386     const char *title = NULL;
42387     const char *abstract = NULL;
42388     int is_queryable = -1;
42389     int is_editable = -1;
42390     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42391     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42392     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42393 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT
42394 	|| sqlite3_value_type (argv[2]) != SQLITE_TEXT)
42395       {
42396 	  sqlite3_result_int (context, -1);
42397 	  return;
42398       }
42399     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42400     title = (const char *) sqlite3_value_text (argv[1]);
42401     abstract = (const char *) sqlite3_value_text (argv[2]);
42402     if (argc >= 5)
42403       {
42404 	  if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER
42405 	      || sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
42406 	    {
42407 		sqlite3_result_int (context, -1);
42408 		return;
42409 	    }
42410 	  is_queryable = sqlite3_value_int (argv[3]);
42411 	  is_editable = sqlite3_value_int (argv[4]);
42412       }
42413     ret =
42414 	set_vector_coverage_infos (sqlite, coverage_name, title, abstract,
42415 				   is_queryable, is_editable);
42416     sqlite3_result_int (context, ret);
42417 }
42418 
42419 static void
fnct_SetVectorCoverageCopyright(sqlite3_context * context,int argc,sqlite3_value ** argv)42420 fnct_SetVectorCoverageCopyright (sqlite3_context * context, int argc,
42421 				 sqlite3_value ** argv)
42422 {
42423 /* SQL function:
42424 / SetVectorCoverageCopyright(Text coverage_name, Text copyright)
42425 /    or
42426 / SetVectorCoverageCopyright(Text coverage_name, Text copyright,
42427 /                            Text license)
42428 /
42429 / updates copyright infos supporting a Vector Coverage
42430 / returns 1 on success
42431 / 0 on failure, -1 on invalid arguments
42432 */
42433     int ret;
42434     const char *coverage_name;
42435     const char *copyright = NULL;
42436     const char *license = NULL;
42437     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42438     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42439     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
42440       {
42441 	  sqlite3_result_int (context, -1);
42442 	  return;
42443       }
42444     if (sqlite3_value_type (argv[1]) == SQLITE_NULL)
42445 	;
42446     else if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
42447 	copyright = (const char *) sqlite3_value_text (argv[1]);
42448     else
42449       {
42450 	  sqlite3_result_int (context, -1);
42451 	  return;
42452       }
42453     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42454     if (argc >= 3)
42455       {
42456 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
42457 	      license = (const char *) sqlite3_value_text (argv[2]);
42458 	  else
42459 	    {
42460 		sqlite3_result_int (context, -1);
42461 		return;
42462 	    }
42463       }
42464     ret =
42465 	set_vector_coverage_copyright (sqlite, coverage_name, copyright,
42466 				       license);
42467     sqlite3_result_int (context, ret);
42468 }
42469 
42470 static void
fnct_RegisterVectorCoverageSrid(sqlite3_context * context,int argc,sqlite3_value ** argv)42471 fnct_RegisterVectorCoverageSrid (sqlite3_context * context, int argc,
42472 				 sqlite3_value ** argv)
42473 {
42474 /* SQL function:
42475 / RegisterVectorCoverageSrid(Text coverage_name, Integer srid)
42476 /
42477 / inserts a Vector Coverage alternative SRID
42478 / returns 1 on success
42479 / 0 on failure, -1 on invalid arguments
42480 */
42481     int ret;
42482     const char *coverage_name;
42483     int srid;
42484     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42485     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42486     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42487 	|| sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
42488       {
42489 	  sqlite3_result_int (context, -1);
42490 	  return;
42491       }
42492     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42493     srid = sqlite3_value_int (argv[1]);
42494     ret = register_vector_coverage_srid (sqlite, coverage_name, srid);
42495     sqlite3_result_int (context, ret);
42496 }
42497 
42498 static void
fnct_UnregisterVectorCoverageSrid(sqlite3_context * context,int argc,sqlite3_value ** argv)42499 fnct_UnregisterVectorCoverageSrid (sqlite3_context * context, int argc,
42500 				   sqlite3_value ** argv)
42501 {
42502 /* SQL function:
42503 / UnRegisterVectorCoverageSrid(Text coverage_name, Integer srid)
42504 /
42505 / deletes a Vector Coverage alternative SRID
42506 / returns 1 on success
42507 / 0 on failure, -1 on invalid arguments
42508 */
42509     int ret;
42510     const char *coverage_name;
42511     int srid;
42512     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42513     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42514     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42515 	|| sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
42516       {
42517 	  sqlite3_result_int (context, -1);
42518 	  return;
42519       }
42520     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42521     srid = sqlite3_value_int (argv[1]);
42522     ret = unregister_vector_coverage_srid (sqlite, coverage_name, srid);
42523     sqlite3_result_int (context, ret);
42524 }
42525 
42526 static void
fnct_RegisterVectorCoverageKeyword(sqlite3_context * context,int argc,sqlite3_value ** argv)42527 fnct_RegisterVectorCoverageKeyword (sqlite3_context * context, int argc,
42528 				    sqlite3_value ** argv)
42529 {
42530 /* SQL function:
42531 / RegisterVectorCoverageKeyword(Text coverage_name, Text keyword)
42532 /
42533 / inserts a Vector Coverage Keyword
42534 / returns 1 on success
42535 / 0 on failure, -1 on invalid arguments
42536 */
42537     int ret;
42538     const char *coverage_name;
42539     const char *keyword;
42540     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42541     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42542     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42543 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
42544       {
42545 	  sqlite3_result_int (context, -1);
42546 	  return;
42547       }
42548     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42549     keyword = (const char *) sqlite3_value_text (argv[1]);
42550     ret = register_vector_coverage_keyword (sqlite, coverage_name, keyword);
42551     sqlite3_result_int (context, ret);
42552 }
42553 
42554 static void
fnct_UnregisterVectorCoverageKeyword(sqlite3_context * context,int argc,sqlite3_value ** argv)42555 fnct_UnregisterVectorCoverageKeyword (sqlite3_context * context, int argc,
42556 				      sqlite3_value ** argv)
42557 {
42558 /* SQL function:
42559 / UnRegisterVectorCoverageSrid(Text coverage_name, Text keyword)
42560 /
42561 / deletes a Vector Coverage Keyword
42562 / returns 1 on success
42563 / 0 on failure, -1 on invalid arguments
42564 */
42565     int ret;
42566     const char *coverage_name;
42567     const char *keyword;
42568     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42569     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42570     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
42571 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
42572       {
42573 	  sqlite3_result_int (context, -1);
42574 	  return;
42575       }
42576     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42577     keyword = (const char *) sqlite3_value_text (argv[1]);
42578     ret = unregister_vector_coverage_keyword (sqlite, coverage_name, keyword);
42579     sqlite3_result_int (context, ret);
42580 }
42581 
42582 static void
fnct_UpdateVectorCoverageExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)42583 fnct_UpdateVectorCoverageExtent (sqlite3_context * context, int argc,
42584 				 sqlite3_value ** argv)
42585 {
42586 /* SQL function:
42587 / UpdateVectorCoverageExtent()
42588 /   or
42589 / UpdateVectorCoverageExtent(Integer transaction)
42590 /   or
42591 / UpdateVectorCoverageExtent(Text coverage_name)
42592 /   or
42593 / UpdateVectorCoverageExtent(Text coverage_name, int transaction)
42594 /
42595 / updates Vector Coverage Extents
42596 / returns 1 on success
42597 / 0 on failure, -1 on invalid arguments
42598 */
42599     int ret;
42600     const char *coverage_name = NULL;
42601     int transaction = 0;
42602     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42603     struct splite_internal_cache *cache = sqlite3_user_data (context);
42604     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42605     if (argc >= 1)
42606       {
42607 	  if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
42608 	      coverage_name = (const char *) sqlite3_value_text (argv[0]);
42609 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42610 	      transaction = sqlite3_value_int (argv[0]);
42611 	  else
42612 	    {
42613 		sqlite3_result_int (context, -1);
42614 		return;
42615 	    }
42616       }
42617     if (argc >= 2)
42618       {
42619 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
42620 	    {
42621 		sqlite3_result_int (context, -1);
42622 		return;
42623 	    }
42624 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
42625 	    {
42626 		sqlite3_result_int (context, -1);
42627 		return;
42628 	    }
42629 	  coverage_name = (const char *) sqlite3_value_text (argv[0]);
42630 	  transaction = sqlite3_value_int (argv[1]);
42631       }
42632     ret =
42633 	update_vector_coverage_extent (sqlite, cache, coverage_name,
42634 				       transaction);
42635     sqlite3_result_int (context, ret);
42636 }
42637 
42638 static void
fnct_RegisterMapConfiguration(sqlite3_context * context,int argc,sqlite3_value ** argv)42639 fnct_RegisterMapConfiguration (sqlite3_context * context, int argc,
42640 			       sqlite3_value ** argv)
42641 {
42642 /* SQL function:
42643 / RL2_RegisterMapConfiguration(BLOB style)
42644 /
42645 / inserts an RL2 Map Configuration
42646 / returns 1 on success
42647 / 0 on failure, -1 on invalid arguments
42648 */
42649     int ret;
42650     const unsigned char *p_blob;
42651     int n_bytes;
42652     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42653     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42654     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
42655       {
42656 	  sqlite3_result_int (context, -1);
42657 	  return;
42658       }
42659     p_blob = sqlite3_value_blob (argv[0]);
42660     n_bytes = sqlite3_value_bytes (argv[0]);
42661     ret = register_map_configuration (sqlite, p_blob, n_bytes);
42662     sqlite3_result_int (context, ret);
42663 }
42664 
42665 static void
fnct_UnRegisterMapConfiguration(sqlite3_context * context,int argc,sqlite3_value ** argv)42666 fnct_UnRegisterMapConfiguration (sqlite3_context * context, int argc,
42667 				 sqlite3_value ** argv)
42668 {
42669 /* SQL function:
42670 / UnRegisterMapConfiguration(Integer id )
42671 /   or
42672 / UnRegisterMapConfiguration(Text name )
42673 /
42674 / removes a Map Configuration definition
42675 / returns 1 on success
42676 / 0 on failure, -1 on invalid arguments
42677 */
42678     int ret;
42679     int id = -1;
42680     const char *name = NULL;
42681     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42682     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42683     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42684 	id = sqlite3_value_int (argv[0]);
42685     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
42686 	name = (const char *) sqlite3_value_text (argv[0]);
42687     else
42688       {
42689 	  sqlite3_result_int (context, -1);
42690 	  return;
42691       }
42692     ret = unregister_map_configuration (sqlite, id, name);
42693     sqlite3_result_int (context, ret);
42694 }
42695 
42696 static void
fnct_ReloadMapConfiguration(sqlite3_context * context,int argc,sqlite3_value ** argv)42697 fnct_ReloadMapConfiguration (sqlite3_context * context, int argc,
42698 			     sqlite3_value ** argv)
42699 {
42700 /* SQL function:
42701 / ReloadMapConfiguration(Integer id, BLOB style)
42702 /    or
42703 / ReloadMapConfiguration(Text name, BLOB style)
42704 /
42705 / updates a  Map Configuration definition
42706 / returns 1 on success
42707 / 0 on failure, -1 on invalid arguments
42708 */
42709     int ret;
42710     int id = -1;
42711     const char *name = NULL;
42712     const unsigned char *p_blob;
42713     int n_bytes;
42714     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42715     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42716     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42717 	id = sqlite3_value_int (argv[0]);
42718     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
42719 	name = (const char *) sqlite3_value_text (argv[0]);
42720     else
42721       {
42722 	  sqlite3_result_int (context, -1);
42723 	  return;
42724       }
42725     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
42726       {
42727 	  sqlite3_result_int (context, -1);
42728 	  return;
42729       }
42730     p_blob = sqlite3_value_blob (argv[1]);
42731     n_bytes = sqlite3_value_bytes (argv[1]);
42732     ret = reload_map_configuration (sqlite, id, name, p_blob, n_bytes);
42733     sqlite3_result_int (context, ret);
42734 }
42735 
42736 static void
fnct_NumMapConfigurations(sqlite3_context * context,int argc,sqlite3_value ** argv)42737 fnct_NumMapConfigurations (sqlite3_context * context, int argc,
42738 			   sqlite3_value ** argv)
42739 {
42740 /* SQL function:
42741 / RL2_NumMapConfigurations()
42742 /
42743 / returns the total number of registered MapConfigurations
42744 / >= 1 on success
42745 / 0 if no MapConfiguration is registered, -1 on error
42746 */
42747     int ret;
42748     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42749     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42750     ret = count_map_configurations (sqlite);
42751     sqlite3_result_int (context, ret);
42752 }
42753 
42754 static void
fnct_MapConfigurationNameN(sqlite3_context * context,int argc,sqlite3_value ** argv)42755 fnct_MapConfigurationNameN (sqlite3_context * context, int argc,
42756 			       sqlite3_value ** argv)
42757 {
42758 /* SQL function:
42759 / MapConfigurationNameN(Integer ind)
42760 /
42761 / returns the Name of the Nth  Map Configuration (first Index is ZERO)
42762 / NULL on failure or on invalid arguments
42763 */
42764     int ind = -1;
42765     char *name = NULL;
42766     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42767     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42768     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42769 	ind = sqlite3_value_int (argv[0]);
42770     else
42771       {
42772 	  sqlite3_result_null (context);
42773 	  return;
42774       }
42775     name = get_map_configuration_name (sqlite, ind);
42776     if (name == NULL)
42777 	sqlite3_result_null (context);
42778     else
42779 	sqlite3_result_text (context, name, strlen (name), free);
42780 }
42781 
42782 static void
fnct_MapConfigurationTitleN(sqlite3_context * context,int argc,sqlite3_value ** argv)42783 fnct_MapConfigurationTitleN (sqlite3_context * context, int argc,
42784 				sqlite3_value ** argv)
42785 {
42786 /* SQL function:
42787 / MapConfigurationTitleN(Integer ind)
42788 /
42789 / returns the Title of the Nth  Map Configuration (first Index is ZERO)
42790 / NULL on failure or on invalid arguments
42791 */
42792     int ind = -1;
42793     char *name = NULL;
42794     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42795     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42796     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42797 	ind = sqlite3_value_int (argv[0]);
42798     else
42799       {
42800 	  sqlite3_result_null (context);
42801 	  return;
42802       }
42803     name = get_map_configuration_title (sqlite, ind);
42804     if (name == NULL)
42805 	sqlite3_result_null (context);
42806     else
42807 	sqlite3_result_text (context, name, strlen (name), free);
42808 }
42809 
42810 static void
fnct_MapConfigurationAbstractN(sqlite3_context * context,int argc,sqlite3_value ** argv)42811 fnct_MapConfigurationAbstractN (sqlite3_context * context, int argc,
42812 				   sqlite3_value ** argv)
42813 {
42814 /* SQL function:
42815 / MapConfigurationAbstractN(Integer ind)
42816 /
42817 / returns the Name of the Nth  Map Configuration (first Index is ZERO)
42818 / NULL on failure or on invalid arguments
42819 */
42820     int ind = -1;
42821     char *name = NULL;
42822     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42823     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42824     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42825 	ind = sqlite3_value_int (argv[0]);
42826     else
42827       {
42828 	  sqlite3_result_null (context);
42829 	  return;
42830       }
42831     name = get_map_configuration_abstract (sqlite, ind);
42832     if (name == NULL)
42833 	sqlite3_result_null (context);
42834     else
42835 	sqlite3_result_text (context, name, strlen (name), free);
42836 }
42837 
42838 static void
fnct_RegisterVectorStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)42839 fnct_RegisterVectorStyle (sqlite3_context * context, int argc,
42840 			  sqlite3_value ** argv)
42841 {
42842 /* SQL function:
42843 / RegisterVectorStyle(BLOB style)
42844 /
42845 / inserts a Vector Style
42846 / returns 1 on success
42847 / 0 on failure, -1 on invalid arguments
42848 */
42849     int ret;
42850     const unsigned char *p_blob;
42851     int n_bytes;
42852     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42853     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42854     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
42855       {
42856 	  sqlite3_result_int (context, -1);
42857 	  return;
42858       }
42859     p_blob = sqlite3_value_blob (argv[0]);
42860     n_bytes = sqlite3_value_bytes (argv[0]);
42861     ret = register_vector_style (sqlite, p_blob, n_bytes);
42862     sqlite3_result_int (context, ret);
42863 }
42864 
42865 static void
fnct_UnRegisterVectorStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)42866 fnct_UnRegisterVectorStyle (sqlite3_context * context, int argc,
42867 			    sqlite3_value ** argv)
42868 {
42869 /* SQL function:
42870 / UnRegisterVectorStyle(Integer style_id [ , Integer removeAll] )
42871 /  or
42872 / UnRegisterVectorStyle(Text style_name [ , Integer removeAll] )
42873 /
42874 / removes a Vector Style definition
42875 / returns 1 on success
42876 / 0 on failure, -1 on invalid arguments
42877 */
42878     int ret;
42879     int style_id = -1;
42880     const char *style_name = NULL;
42881     int remove_all = 0;
42882     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42883     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42884     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42885 	style_id = sqlite3_value_int (argv[0]);
42886     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
42887 	style_name = (const char *) sqlite3_value_text (argv[0]);
42888     else
42889       {
42890 	  sqlite3_result_int (context, -1);
42891 	  return;
42892       }
42893     if (argc >= 2)
42894       {
42895 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
42896 	    {
42897 		sqlite3_result_int (context, -1);
42898 		return;
42899 	    }
42900 	  remove_all = sqlite3_value_int (argv[1]);
42901       }
42902     ret = unregister_vector_style (sqlite, style_id, style_name, remove_all);
42903     sqlite3_result_int (context, ret);
42904 }
42905 
42906 static void
fnct_ReloadVectorStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)42907 fnct_ReloadVectorStyle (sqlite3_context * context, int argc,
42908 			sqlite3_value ** argv)
42909 {
42910 /* SQL function:
42911 / ReloadVectorStyle(Integer style_id, BLOB style)
42912 /    or
42913 / ReloadVectorStyle(Text style_name, BLOB style)
42914 /
42915 / updates a Vector Style
42916 / returns 1 on success
42917 / 0 on failure, -1 on invalid arguments
42918 */
42919     int ret;
42920     int style_id = -1;
42921     const char *style_name = NULL;
42922     const unsigned char *p_blob;
42923     int n_bytes;
42924     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42925     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42926     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
42927 	style_id = sqlite3_value_int (argv[0]);
42928     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
42929 	style_name = (const char *) sqlite3_value_text (argv[0]);
42930     else
42931       {
42932 	  sqlite3_result_int (context, -1);
42933 	  return;
42934       }
42935     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
42936       {
42937 	  sqlite3_result_int (context, -1);
42938 	  return;
42939       }
42940     p_blob = sqlite3_value_blob (argv[1]);
42941     n_bytes = sqlite3_value_bytes (argv[1]);
42942     ret = reload_vector_style (sqlite, style_id, style_name, p_blob, n_bytes);
42943     sqlite3_result_int (context, ret);
42944 }
42945 
42946 static void
fnct_RegisterVectorStyledLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)42947 fnct_RegisterVectorStyledLayer (sqlite3_context * context, int argc,
42948 				sqlite3_value ** argv)
42949 {
42950 /* SQL function:
42951 / RegisterVectorStyledLayer(String coverage_name, Integer style_id)
42952 /  or
42953 / RegisterVectorStyledLayer(String coverage_name, Text style_name)
42954 /
42955 / inserts a Vector Styled Layer
42956 / returns 1 on success
42957 / 0 on failure, -1 on invalid arguments
42958 */
42959     int ret;
42960     const char *coverage_name;
42961     int style_id = -1;
42962     const char *style_name = NULL;
42963     sqlite3 *sqlite = sqlite3_context_db_handle (context);
42964     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
42965     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
42966       {
42967 	  sqlite3_result_int (context, -1);
42968 	  return;
42969       }
42970     coverage_name = (const char *) sqlite3_value_text (argv[0]);
42971     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
42972 	style_id = sqlite3_value_int (argv[1]);
42973     else if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
42974 	style_name = (const char *) sqlite3_value_text (argv[1]);
42975     else
42976       {
42977 	  sqlite3_result_int (context, -1);
42978 	  return;
42979       }
42980     ret = register_vector_styled_layer_ex (sqlite, coverage_name, style_id,
42981 					   style_name);
42982     sqlite3_result_int (context, ret);
42983 }
42984 
42985 static void
fnct_UnRegisterVectorStyledLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)42986 fnct_UnRegisterVectorStyledLayer (sqlite3_context * context, int argc,
42987 				  sqlite3_value ** argv)
42988 {
42989 /* SQL function:
42990 / UnRegisterVectorStyledLayer(String coverage_name,	Integer style_id)
42991 /  or
42992 / UnRegisterVectorStyledLayer(String coverage_name,	Text style_name)
42993 /
42994 / removes a Vector Styled Layer definition
42995 / returns 1 on success
42996 / 0 on failure, -1 on invalid arguments
42997 */
42998     int ret;
42999     const char *coverage_name;
43000     int style_id = -1;
43001     const char *style_name = NULL;
43002     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43003     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43004     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43005       {
43006 	  sqlite3_result_int (context, -1);
43007 	  return;
43008       }
43009     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43010     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
43011 	style_id = sqlite3_value_int (argv[1]);
43012     else if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
43013 	style_name = (const char *) sqlite3_value_text (argv[1]);
43014     else
43015       {
43016 	  sqlite3_result_int (context, -1);
43017 	  return;
43018       }
43019     ret = unregister_vector_styled_layer (sqlite, coverage_name, style_id,
43020 					  style_name);
43021     sqlite3_result_int (context, ret);
43022 }
43023 
43024 static void
fnct_RegisterRasterStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)43025 fnct_RegisterRasterStyle (sqlite3_context * context, int argc,
43026 			  sqlite3_value ** argv)
43027 {
43028 /* SQL function:
43029 / RegisterRasterStyle(BLOB style)
43030 /
43031 / inserts a Raster Style
43032 / returns 1 on success
43033 / 0 on failure, -1 on invalid arguments
43034 */
43035     int ret;
43036     const unsigned char *p_blob;
43037     int n_bytes;
43038     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43039     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43040     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43041       {
43042 	  sqlite3_result_int (context, -1);
43043 	  return;
43044       }
43045     p_blob = sqlite3_value_blob (argv[0]);
43046     n_bytes = sqlite3_value_bytes (argv[0]);
43047     ret = register_raster_style (sqlite, p_blob, n_bytes);
43048     sqlite3_result_int (context, ret);
43049 }
43050 
43051 static void
fnct_UnRegisterRasterStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)43052 fnct_UnRegisterRasterStyle (sqlite3_context * context, int argc,
43053 			    sqlite3_value ** argv)
43054 {
43055 /* SQL function:
43056 / UnRegisterRasterStyle(Integer style_id [ , Integer removeAll] )
43057 /   or
43058 / UnRegisterRasterStyledLayer(Text style_name [ , Integer removeAll] )
43059 /
43060 / removes a Raster Style definition
43061 / returns 1 on success
43062 / 0 on failure, -1 on invalid arguments
43063 */
43064     int ret;
43065     int style_id = -1;
43066     const char *style_name = NULL;
43067     int remove_all = 0;
43068     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43069     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43070     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
43071 	style_id = sqlite3_value_int (argv[0]);
43072     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
43073 	style_name = (const char *) sqlite3_value_text (argv[0]);
43074     else
43075       {
43076 	  sqlite3_result_int (context, -1);
43077 	  return;
43078       }
43079     if (argc >= 2)
43080       {
43081 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43082 	    {
43083 		sqlite3_result_int (context, -1);
43084 		return;
43085 	    }
43086 	  remove_all = sqlite3_value_int (argv[1]);
43087       }
43088     ret = unregister_raster_style (sqlite, style_id, style_name, remove_all);
43089     sqlite3_result_int (context, ret);
43090 }
43091 
43092 static void
fnct_ReloadRasterStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)43093 fnct_ReloadRasterStyle (sqlite3_context * context, int argc,
43094 			sqlite3_value ** argv)
43095 {
43096 /* SQL function:
43097 / ReloadRasterStyle(Integer style_id, BLOB style)
43098 /    or
43099 / ReloadRasterStyle(Text style_name, BLOB style)
43100 /
43101 / updates a Raster Style
43102 / returns 1 on success
43103 / 0 on failure, -1 on invalid arguments
43104 */
43105     int ret;
43106     int style_id = -1;
43107     const char *style_name = NULL;
43108     const unsigned char *p_blob;
43109     int n_bytes;
43110     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43111     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43112     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
43113 	style_id = sqlite3_value_int (argv[0]);
43114     else if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
43115 	style_name = (const char *) sqlite3_value_text (argv[0]);
43116     else
43117       {
43118 	  sqlite3_result_int (context, -1);
43119 	  return;
43120       }
43121     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
43122       {
43123 	  sqlite3_result_int (context, -1);
43124 	  return;
43125       }
43126     p_blob = sqlite3_value_blob (argv[1]);
43127     n_bytes = sqlite3_value_bytes (argv[1]);
43128     ret = reload_raster_style (sqlite, style_id, style_name, p_blob, n_bytes);
43129     sqlite3_result_int (context, ret);
43130 }
43131 
43132 static void
fnct_RegisterRasterStyledLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)43133 fnct_RegisterRasterStyledLayer (sqlite3_context * context, int argc,
43134 				sqlite3_value ** argv)
43135 {
43136 /* SQL function:
43137 / RegisterRasterStyledLayer(String coverage_name, Integer style_id)
43138 /   or
43139 / RegisterRasterStyledLayer(String coverage_name, Text style_name)
43140 /
43141 / inserts a Raster Styled Layer
43142 / returns 1 on success
43143 / 0 on failure, -1 on invalid arguments
43144 */
43145     int ret;
43146     const char *coverage_name;
43147     int style_id = -1;
43148     const char *style_name = NULL;
43149     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43150     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43151     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43152       {
43153 	  sqlite3_result_int (context, -1);
43154 	  return;
43155       }
43156     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43157     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
43158 	style_id = sqlite3_value_int (argv[1]);
43159     else if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
43160 	style_name = (const char *) sqlite3_value_text (argv[1]);
43161     else
43162       {
43163 	  sqlite3_result_int (context, -1);
43164 	  return;
43165       }
43166     ret =
43167 	register_raster_styled_layer_ex (sqlite, coverage_name, style_id,
43168 					 style_name);
43169     sqlite3_result_int (context, ret);
43170 }
43171 
43172 static void
fnct_UnRegisterRasterStyledLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)43173 fnct_UnRegisterRasterStyledLayer (sqlite3_context * context, int argc,
43174 				  sqlite3_value ** argv)
43175 {
43176 /* SQL function:
43177 / UnRegisterRasterStyledLayer(String coverage_name, Integer style_id)
43178 /   or
43179 / UnRegisterRasterStyledLayer(String coverage_name, Text style_name)
43180 /
43181 / removes a Raster Styled Layer definition
43182 / returns 1 on success
43183 / 0 on failure, -1 on invalid arguments
43184 */
43185     int ret;
43186     const char *coverage_name;
43187     int style_id = -1;
43188     const char *style_name = NULL;
43189     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43190     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43191     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43192       {
43193 	  sqlite3_result_int (context, -1);
43194 	  return;
43195       }
43196     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43197     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
43198 	style_id = sqlite3_value_int (argv[1]);
43199     else if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
43200 	style_name = (const char *) sqlite3_value_text (argv[1]);
43201     else
43202       {
43203 	  sqlite3_result_int (context, -1);
43204 	  return;
43205       }
43206     ret =
43207 	unregister_raster_styled_layer (sqlite, coverage_name, style_id,
43208 					style_name);
43209     sqlite3_result_int (context, ret);
43210 }
43211 
43212 static void
fnct_RegisterRasterCoverageSrid(sqlite3_context * context,int argc,sqlite3_value ** argv)43213 fnct_RegisterRasterCoverageSrid (sqlite3_context * context, int argc,
43214 				 sqlite3_value ** argv)
43215 {
43216 /* SQL function:
43217 / RegisterRasterCoverageSrid(Text coverage_name, Integer srid)
43218 /
43219 / inserts a Raster Coverage alternative SRID
43220 / returns 1 on success
43221 / 0 on failure, -1 on invalid arguments
43222 */
43223     int ret;
43224     const char *coverage_name;
43225     int srid;
43226     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43227     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43228     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
43229 	|| sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43230       {
43231 	  sqlite3_result_int (context, -1);
43232 	  return;
43233       }
43234     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43235     srid = sqlite3_value_int (argv[1]);
43236     ret = register_raster_coverage_srid (sqlite, coverage_name, srid);
43237     sqlite3_result_int (context, ret);
43238 }
43239 
43240 static void
fnct_UnregisterRasterCoverageSrid(sqlite3_context * context,int argc,sqlite3_value ** argv)43241 fnct_UnregisterRasterCoverageSrid (sqlite3_context * context, int argc,
43242 				   sqlite3_value ** argv)
43243 {
43244 /* SQL function:
43245 / UnRegisterRasterCoverageSrid(Text coverage_name, Integer srid)
43246 /
43247 / deletes a Raster Coverage alternative SRID
43248 / returns 1 on success
43249 / 0 on failure, -1 on invalid arguments
43250 */
43251     int ret;
43252     const char *coverage_name;
43253     int srid;
43254     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43255     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43256     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
43257 	|| sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43258       {
43259 	  sqlite3_result_int (context, -1);
43260 	  return;
43261       }
43262     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43263     srid = sqlite3_value_int (argv[1]);
43264     ret = unregister_raster_coverage_srid (sqlite, coverage_name, srid);
43265     sqlite3_result_int (context, ret);
43266 }
43267 
43268 static void
fnct_RegisterRasterCoverageKeyword(sqlite3_context * context,int argc,sqlite3_value ** argv)43269 fnct_RegisterRasterCoverageKeyword (sqlite3_context * context, int argc,
43270 				    sqlite3_value ** argv)
43271 {
43272 /* SQL function:
43273 / RegisterRasterCoverageKeyword(Text coverage_name, Text keyword)
43274 /
43275 / inserts a Raster Coverage Keyword
43276 / returns 1 on success
43277 / 0 on failure, -1 on invalid arguments
43278 */
43279     int ret;
43280     const char *coverage_name;
43281     const char *keyword;
43282     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43283     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43284     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
43285 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
43286       {
43287 	  sqlite3_result_int (context, -1);
43288 	  return;
43289       }
43290     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43291     keyword = (const char *) sqlite3_value_text (argv[1]);
43292     ret = register_raster_coverage_keyword (sqlite, coverage_name, keyword);
43293     sqlite3_result_int (context, ret);
43294 }
43295 
43296 static void
fnct_UnregisterRasterCoverageKeyword(sqlite3_context * context,int argc,sqlite3_value ** argv)43297 fnct_UnregisterRasterCoverageKeyword (sqlite3_context * context, int argc,
43298 				      sqlite3_value ** argv)
43299 {
43300 /* SQL function:
43301 / UnRegisterRasterCoverageKeyword(Text coverage_name, Text keyword)
43302 /
43303 / deletes a Raster Coverage Keyword
43304 / returns 1 on success
43305 / 0 on failure, -1 on invalid arguments
43306 */
43307     int ret;
43308     const char *coverage_name;
43309     const char *keyword;
43310     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43311     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43312     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT
43313 	|| sqlite3_value_type (argv[1]) != SQLITE_TEXT)
43314       {
43315 	  sqlite3_result_int (context, -1);
43316 	  return;
43317       }
43318     coverage_name = (const char *) sqlite3_value_text (argv[0]);
43319     keyword = (const char *) sqlite3_value_text (argv[1]);
43320     ret = unregister_raster_coverage_keyword (sqlite, coverage_name, keyword);
43321     sqlite3_result_int (context, ret);
43322 }
43323 
43324 static void
fnct_UpdateRasterCoverageExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)43325 fnct_UpdateRasterCoverageExtent (sqlite3_context * context, int argc,
43326 				 sqlite3_value ** argv)
43327 {
43328 /* SQL function:
43329 / UpdateRasterCoverageExtent()
43330 /   or
43331 / UpdateRasterCoverageExtent(Integer transaction)
43332 /   or
43333 / UpdateRasterCoverageExtent(Text coverage_name)
43334 /   or
43335 / UpdateRasterCoverageExtent(Text coverage_name, int transaction)
43336 /
43337 / updates Raster Coverage Extents
43338 / returns 1 on success
43339 / 0 on failure, -1 on invalid arguments
43340 */
43341     int ret;
43342     const char *coverage_name = NULL;
43343     int transaction = 0;
43344     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43345     struct splite_internal_cache *cache = sqlite3_user_data (context);
43346     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43347     if (argc >= 1)
43348       {
43349 	  if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
43350 	      coverage_name = (const char *) sqlite3_value_text (argv[0]);
43351 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
43352 	      transaction = sqlite3_value_int (argv[0]);
43353 	  else
43354 	    {
43355 		sqlite3_result_int (context, -1);
43356 		return;
43357 	    }
43358       }
43359     if (argc >= 2)
43360       {
43361 	  if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43362 	    {
43363 		sqlite3_result_int (context, -1);
43364 		return;
43365 	    }
43366 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43367 	    {
43368 		sqlite3_result_int (context, -1);
43369 		return;
43370 	    }
43371 	  coverage_name = (const char *) sqlite3_value_text (argv[0]);
43372 	  transaction = sqlite3_value_int (argv[1]);
43373       }
43374     ret =
43375 	update_raster_coverage_extent (sqlite, cache, coverage_name,
43376 				       transaction);
43377     sqlite3_result_int (context, ret);
43378 }
43379 
43380 
43381 static void
fnct_CreateIsoMetadataTables(sqlite3_context * context,int argc,sqlite3_value ** argv)43382 fnct_CreateIsoMetadataTables (sqlite3_context * context, int argc,
43383 			      sqlite3_value ** argv)
43384 {
43385 /* SQL function:
43386 / CreateIsoMetadataTables()
43387 /  or
43388 / CreateIsoMetadataTables(bool relaxed)
43389 /
43390 / creates any ISO Metadata related table
43391 / returns 1 on success
43392 / 0 on failure, -1 on invalid arguments
43393 */
43394     int relaxed = 0;
43395     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43396     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43397     if (argc == 1)
43398       {
43399 	  if (sqlite3_value_type (argv[0]) != SQLITE_INTEGER)
43400 	    {
43401 		sqlite3_result_int (context, -1);
43402 		return;
43403 	    }
43404 	  relaxed = sqlite3_value_int (argv[0]);
43405       }
43406 
43407     if (!createIsoMetadataTables (sqlite, relaxed))
43408 	goto error;
43409     updateSpatiaLiteHistory (sqlite, "*** ISO Metadata ***", NULL,
43410 			     "ISO Metadata tables successfully created");
43411     sqlite3_result_int (context, 1);
43412     return;
43413 
43414   error:
43415     sqlite3_result_int (context, 0);
43416     return;
43417 }
43418 
43419 static void
fnct_GetIsoMetadataId(sqlite3_context * context,int argc,sqlite3_value ** argv)43420 fnct_GetIsoMetadataId (sqlite3_context * context, int argc,
43421 		       sqlite3_value ** argv)
43422 {
43423 /* SQL function:
43424 / GetIsoMetadataId(String fileIdentifier)
43425 /
43426 / return the ID of the row corresponding to "fileIdentifier"
43427 / 0 on failure / -1 on invalid argument
43428 */
43429     const char *fileIdentifier;
43430     sqlite3_int64 id;
43431     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43432     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43433     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43434       {
43435 	  sqlite3_result_int (context, -1);
43436 	  return;
43437       }
43438     fileIdentifier = (const char *) sqlite3_value_text (argv[0]);
43439     if (!get_iso_metadata_id (sqlite, fileIdentifier, &id))
43440 	sqlite3_result_int (context, 0);
43441     else
43442 	sqlite3_result_int64 (context, id);
43443 }
43444 
43445 static void
fnct_RegisterIsoMetadata(sqlite3_context * context,int argc,sqlite3_value ** argv)43446 fnct_RegisterIsoMetadata (sqlite3_context * context, int argc,
43447 			  sqlite3_value ** argv)
43448 {
43449 /* SQL function:
43450 / RegisterIsoMetadata(String scope, BLOB metadata)
43451 /  or
43452 / RegisterIsoMetadata(String scope, BLOB metadata,
43453 /			Integer id)
43454 /  or
43455 / RegisterIsoMetadata(String scope, BLOB metadata,
43456 /			String fileIdentifier)
43457 /
43458 / insert or updates a Raster Styled Layer
43459 / returns 1 on success
43460 / 0 on failure, -1 on invalid arguments
43461 */
43462     int ret;
43463     const char *scope;
43464     const unsigned char *p_blob;
43465     int n_bytes;
43466     sqlite3_int64 id = -1;
43467     const char *fileIdentifier = NULL;
43468     sqlite3 *sqlite = sqlite3_context_db_handle (context);
43469     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43470     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43471       {
43472 	  sqlite3_result_int (context, -1);
43473 	  return;
43474       }
43475     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
43476       {
43477 	  sqlite3_result_int (context, -1);
43478 	  return;
43479       }
43480     if (argc == 3)
43481       {
43482 	  /* optional extra args */
43483 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER ||
43484 	      sqlite3_value_type (argv[2]) == SQLITE_TEXT)
43485 	      ;
43486 	  else
43487 	    {
43488 		sqlite3_result_int (context, -1);
43489 		return;
43490 	    }
43491       }
43492     scope = (const char *) sqlite3_value_text (argv[0]);
43493     p_blob = sqlite3_value_blob (argv[1]);
43494     n_bytes = sqlite3_value_bytes (argv[1]);
43495     if (argc == 3)
43496       {
43497 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
43498 	      id = sqlite3_value_int64 (argv[2]);
43499 	  if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
43500 	      fileIdentifier = (const char *) sqlite3_value_text (argv[2]);
43501       }
43502     ret = register_iso_metadata (sqlite, scope, p_blob, n_bytes, &id,
43503 				 fileIdentifier);
43504     sqlite3_result_int (context, ret);
43505 }
43506 
43507 static void
fnct_XB_Create(sqlite3_context * context,int argc,sqlite3_value ** argv)43508 fnct_XB_Create (sqlite3_context * context, int argc, sqlite3_value ** argv)
43509 {
43510 /* SQL function:
43511 / XB_Create(BLOB XMLdocument)
43512 / XB_Create(BLOB XMLdocument, bool compressed)
43513 / XB_Create(BLOB XMLdocument, bool compressed, text SchemaURI)
43514 / XB_Create(BLOB XMLdocument, bool compressed, int InternalSchemaURI)
43515 /
43516 / returns the current XmlBlob by parsing an XMLdocument
43517 / or NULL if any error is encountered
43518 /
43519 / - the XMLdocument should be "well formed"
43520 / - if *compressed* is TRUE (default) the XmlBlob would be zipped
43521 / - if *SchemaURI* in not NULL then only XMLdocuments successfully
43522 /   passing a formal Schema Validation will be accepted as valid
43523 / - if *InternalSchamaURI* is defined (any numeric value) then an
43524 /   attempt will be made in order to identify a SchemaURI defined
43525 /   internally within the XMLDocument itself.
43526 /   if such internal SchemaURI doesn't exists, or if the formal
43527 /   Schema Validation fails, NULL will be returned.
43528 */
43529     int len = 0;
43530     unsigned char *p_result = NULL;
43531     const unsigned char *xml;
43532     int xml_len;
43533     int compressed = 1;
43534     int use_internal_schema_uri = 0;
43535     const char *schemaURI = NULL;
43536     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43537     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43538       {
43539 	  sqlite3_result_null (context);
43540 	  return;
43541       }
43542     if (argc >= 2)
43543       {
43544 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43545 	    {
43546 		sqlite3_result_null (context);
43547 		return;
43548 	    }
43549       }
43550     if (argc == 3)
43551       {
43552 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
43553 	      use_internal_schema_uri = 1;
43554 	  else if (sqlite3_value_type (argv[2]) != SQLITE_TEXT)
43555 	    {
43556 		sqlite3_result_null (context);
43557 		return;
43558 	    }
43559       }
43560     xml = (const unsigned char *) sqlite3_value_blob (argv[0]);
43561     xml_len = sqlite3_value_bytes (argv[0]);
43562     if (argc >= 2)
43563 	compressed = sqlite3_value_int (argv[1]);
43564     if (use_internal_schema_uri)
43565       {
43566 	  /* using the SchemaURI internally defined within the XMLDocument */
43567 	  char *internalSchemaURI =
43568 	      gaiaXmlGetInternalSchemaURI (sqlite3_user_data (context), xml,
43569 					   xml_len);
43570 	  if (internalSchemaURI == NULL)
43571 	    {
43572 		/* unable to identify the SchemaURI */
43573 		p_result = NULL;
43574 	    }
43575 	  else
43576 	    {
43577 		/* ok, attempting to validate using the internal SchemaURI */
43578 		gaiaXmlToBlob (sqlite3_user_data (context), xml, xml_len,
43579 			       compressed, internalSchemaURI, &p_result,
43580 			       &len, NULL, NULL);
43581 		free (internalSchemaURI);
43582 	    }
43583       }
43584     else
43585       {
43586 	  if (argc == 3)
43587 	      schemaURI = (const char *) sqlite3_value_text (argv[2]);
43588 	  gaiaXmlToBlob (sqlite3_user_data (context), xml, xml_len,
43589 			 compressed, schemaURI, &p_result, &len, NULL, NULL);
43590       }
43591     if (p_result == NULL)
43592       {
43593 	  sqlite3_result_null (context);
43594 	  return;
43595       }
43596     sqlite3_result_blob (context, p_result, len, free);
43597 }
43598 
43599 static void
fnct_XB_LoadXML(sqlite3_context * context,int argc,sqlite3_value ** argv)43600 fnct_XB_LoadXML (sqlite3_context * context, int argc, sqlite3_value ** argv)
43601 {
43602 /* SQL function:
43603 / XB_LoadXML(text path-or-URL)
43604 /
43605 / returns a generic Text by parsing an XML Document
43606 / or NULL if any error is encountered
43607 /
43608 */
43609     const char *path_or_url;
43610     unsigned char *xml;
43611     int xml_len;
43612     int ret;
43613     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43614     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
43615       {
43616 	  sqlite3_result_null (context);
43617 	  return;
43618       }
43619     path_or_url = (const char *) sqlite3_value_text (argv[0]);
43620 
43621 /* acquiring the XML Document as a Blob */
43622     ret = gaiaXmlLoad
43623 	(sqlite3_user_data (context), path_or_url, &xml, &xml_len, NULL);
43624     if (!ret || xml == NULL)
43625       {
43626 	  sqlite3_result_null (context);
43627 	  return;
43628       }
43629 
43630     sqlite3_result_blob (context, xml, xml_len, free);
43631 }
43632 
43633 static void
fnct_XB_GetPayload(sqlite3_context * context,int argc,sqlite3_value ** argv)43634 fnct_XB_GetPayload (sqlite3_context * context, int argc, sqlite3_value ** argv)
43635 {
43636 /* SQL function:
43637 / XB_GetPayload(XmlBLOB)
43638 / XB_GetPayload(XmlBLOB, int format)
43639 /
43640 / returns the current XMLDocument (as BLOB) by parsing an XmlBLOB
43641 / or NULL if any error is encountered
43642 /
43643 / the returned buffer will be always null-terminated
43644 */
43645     const unsigned char *p_blob;
43646     int n_bytes;
43647     unsigned char *out;
43648     int out_len;
43649     int indent = -1;
43650     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43651     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43652       {
43653 	  sqlite3_result_null (context);
43654 	  return;
43655       }
43656     if (argc == 2)
43657       {
43658 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43659 	    {
43660 		sqlite3_result_null (context);
43661 		return;
43662 	    }
43663       }
43664     p_blob = sqlite3_value_blob (argv[0]);
43665     n_bytes = sqlite3_value_bytes (argv[0]);
43666     if (argc == 2)
43667 	indent = sqlite3_value_int (argv[1]);
43668     gaiaXmlFromBlob (p_blob, n_bytes, indent, &out, &out_len);
43669     if (out == NULL)
43670       {
43671 	  sqlite3_result_null (context);
43672 	  return;
43673       }
43674     sqlite3_result_blob (context, out, out_len, free);
43675 }
43676 
43677 static void
fnct_XB_StoreXML(sqlite3_context * context,int argc,sqlite3_value ** argv)43678 fnct_XB_StoreXML (sqlite3_context * context, int argc, sqlite3_value ** argv)
43679 {
43680 /* SQL function:
43681 / XB_StoreXML(XmlBLOB, text path)
43682 / XB_StoreXML(XmlBLOB, taxt path, int format)
43683 /
43684 / exports the current XMLDocument into an external file by parsing an XmlBLOB
43685 / return 1 on success, 0 on failure, -1 on invalid args
43686 /
43687 */
43688     const unsigned char *p_blob;
43689     int n_bytes;
43690     const char *path;
43691     int indent = -1;
43692     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43693     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43694       {
43695 	  sqlite3_result_int (context, -1);
43696 	  return;
43697       }
43698     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
43699       {
43700 	  sqlite3_result_int (context, -1);
43701 	  return;
43702       }
43703     if (argc == 3)
43704       {
43705 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
43706 	    {
43707 		sqlite3_result_int (context, -1);
43708 		return;
43709 	    }
43710       }
43711     p_blob = sqlite3_value_blob (argv[0]);
43712     n_bytes = sqlite3_value_bytes (argv[0]);
43713     path = (const char *) sqlite3_value_text (argv[1]);
43714     if (argc == 3)
43715 	indent = sqlite3_value_int (argv[2]);
43716     if (!gaiaXmlStore (p_blob, n_bytes, path, indent))
43717       {
43718 	  sqlite3_result_int (context, 0);
43719 	  return;
43720       }
43721     sqlite3_result_int (context, 1);
43722 }
43723 
43724 static void
fnct_XB_GetDocument(sqlite3_context * context,int argc,sqlite3_value ** argv)43725 fnct_XB_GetDocument (sqlite3_context * context, int argc, sqlite3_value ** argv)
43726 {
43727 /* SQL function:
43728 / XB_GetDocument(XmlBLOB)
43729 / XB_GetDocument(XmlBLOB, int indent)
43730 /
43731 / returns the current XMLDocument (as UTF-8 TEXT) by parsing an XmlBLOB
43732 / or NULL if any error is encountered
43733 /
43734 / the returned buffer will be always null-terminated
43735 */
43736     const unsigned char *p_blob;
43737     int n_bytes;
43738     char *xml;
43739     int len;
43740     int indent = -1;
43741     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43742     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43743       {
43744 	  sqlite3_result_null (context);
43745 	  return;
43746       }
43747     if (argc == 2)
43748       {
43749 	  if (sqlite3_value_type (argv[1]) != SQLITE_INTEGER)
43750 	    {
43751 		sqlite3_result_null (context);
43752 		return;
43753 	    }
43754       }
43755     p_blob = sqlite3_value_blob (argv[0]);
43756     n_bytes = sqlite3_value_bytes (argv[0]);
43757     if (argc == 2)
43758 	indent = sqlite3_value_int (argv[1]);
43759     xml = gaiaXmlTextFromBlob (p_blob, n_bytes, indent);
43760     if (xml == NULL)
43761       {
43762 	  sqlite3_result_null (context);
43763 	  return;
43764       }
43765     len = strlen ((const char *) xml);
43766     sqlite3_result_text (context, (char *) xml, len, free);
43767 }
43768 
43769 static void
fnct_XB_SchemaValidate(sqlite3_context * context,int argc,sqlite3_value ** argv)43770 fnct_XB_SchemaValidate (sqlite3_context * context, int argc,
43771 			sqlite3_value ** argv)
43772 {
43773 /* SQL function:
43774 / XB_SchemaValidate(XmlBLOB, text SchemaURI)
43775 / XB_SchemaValidate(XmlBLOB, text SchemaURI, bool compressed)
43776 / XB_SchemaValidate(XmlBLOB, int InternalSchemaURI)
43777 / XB_SchemaValidate(XmlBLOB, int InternalSchemaURI, bool compressed)
43778 /
43779 / returns a validated XmlBLOB object if the SchemaValidation was successful
43780 / or NULL if any error is encountered
43781 */
43782     int len = 0;
43783     unsigned char *p_result = NULL;
43784     const unsigned char *p_blob;
43785     int n_bytes;
43786     unsigned char *xml;
43787     int xml_len;
43788     int compressed = 1;
43789     const char *schemaURI = NULL;
43790     int use_internal_schema_uri = 0;
43791     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43792     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43793       {
43794 	  sqlite3_result_null (context);
43795 	  return;
43796       }
43797     if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
43798 	use_internal_schema_uri = 1;
43799     else if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
43800       {
43801 	  sqlite3_result_null (context);
43802 	  return;
43803       }
43804     if (argc == 3)
43805       {
43806 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
43807 	    {
43808 		sqlite3_result_null (context);
43809 		return;
43810 	    }
43811       }
43812     p_blob = sqlite3_value_blob (argv[0]);
43813     n_bytes = sqlite3_value_bytes (argv[0]);
43814     if (argc == 3)
43815 	compressed = sqlite3_value_int (argv[2]);
43816     gaiaXmlFromBlob (p_blob, n_bytes, -1, &xml, &xml_len);
43817     if (xml == NULL)
43818       {
43819 	  sqlite3_result_null (context);
43820 	  return;
43821       }
43822     if (use_internal_schema_uri)
43823       {
43824 	  /* using the SchemaURI internally defined within the XMLDocument */
43825 	  char *internalSchemaURI =
43826 	      gaiaXmlGetInternalSchemaURI (sqlite3_user_data (context), xml,
43827 					   xml_len);
43828 	  if (internalSchemaURI == NULL)
43829 	    {
43830 		/* unable to identify the SchemaURI */
43831 		p_result = NULL;
43832 	    }
43833 	  else
43834 	    {
43835 		/* ok, attempting to validate using the internal SchemaURI */
43836 		gaiaXmlToBlob (sqlite3_user_data (context), xml, xml_len,
43837 			       compressed, internalSchemaURI, &p_result,
43838 			       &len, NULL, NULL);
43839 		free (internalSchemaURI);
43840 	    }
43841       }
43842     else
43843       {
43844 	  schemaURI = (const char *) sqlite3_value_text (argv[1]);
43845 	  gaiaXmlToBlob (sqlite3_user_data (context), xml, xml_len,
43846 			 compressed, schemaURI, &p_result, &len, NULL, NULL);
43847       }
43848     free (xml);
43849     if (p_result == NULL)
43850       {
43851 	  sqlite3_result_null (context);
43852 	  return;
43853       }
43854     sqlite3_result_blob (context, p_result, len, free);
43855 }
43856 
43857 static void
fnct_XB_Compress(sqlite3_context * context,int argc,sqlite3_value ** argv)43858 fnct_XB_Compress (sqlite3_context * context, int argc, sqlite3_value ** argv)
43859 {
43860 /* SQL function:
43861 / XB_Compress(XmlBLOB)
43862 /
43863 / returns a compressed XmlBLOB object
43864 / or NULL if any error is encountered
43865 */
43866     int len;
43867     unsigned char *p_result = NULL;
43868     const unsigned char *p_blob;
43869     int n_bytes;
43870     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43871     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43872       {
43873 	  sqlite3_result_null (context);
43874 	  return;
43875       }
43876     p_blob = sqlite3_value_blob (argv[0]);
43877     n_bytes = sqlite3_value_bytes (argv[0]);
43878     gaiaXmlBlobCompression (p_blob, n_bytes, 1, &p_result, &len);
43879     if (p_result == NULL)
43880       {
43881 	  sqlite3_result_null (context);
43882 	  return;
43883       }
43884     sqlite3_result_blob (context, p_result, len, free);
43885 }
43886 
43887 static void
fnct_XB_Uncompress(sqlite3_context * context,int argc,sqlite3_value ** argv)43888 fnct_XB_Uncompress (sqlite3_context * context, int argc, sqlite3_value ** argv)
43889 {
43890 /* SQL function:
43891 / XB_Uncompress(XmlBLOB)
43892 /
43893 / returns an uncompressed XmlBLOB object
43894 / or NULL if any error is encountered
43895 */
43896     int len;
43897     unsigned char *p_result = NULL;
43898     const unsigned char *p_blob;
43899     int n_bytes;
43900     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43901     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43902       {
43903 	  sqlite3_result_null (context);
43904 	  return;
43905       }
43906     p_blob = sqlite3_value_blob (argv[0]);
43907     n_bytes = sqlite3_value_bytes (argv[0]);
43908     gaiaXmlBlobCompression (p_blob, n_bytes, 0, &p_result, &len);
43909     if (p_result == NULL)
43910       {
43911 	  sqlite3_result_null (context);
43912 	  return;
43913       }
43914     sqlite3_result_blob (context, p_result, len, free);
43915 }
43916 
43917 static void
fnct_XB_IsValid(sqlite3_context * context,int argc,sqlite3_value ** argv)43918 fnct_XB_IsValid (sqlite3_context * context, int argc, sqlite3_value ** argv)
43919 {
43920 /* SQL function:
43921 / XB_IsValid(XmlBLOB)
43922 /
43923 / returns TRUE if the current BLOB is an XmlBLOB, FALSE if not
43924 / or -1 if any error is encountered
43925 */
43926     unsigned char *p_blob;
43927     int n_bytes;
43928     int ret;
43929     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43930     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43931       {
43932 	  sqlite3_result_int (context, -1);
43933 	  return;
43934       }
43935     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
43936     n_bytes = sqlite3_value_bytes (argv[0]);
43937     ret = gaiaIsValidXmlBlob (p_blob, n_bytes);
43938     sqlite3_result_int (context, ret);
43939 }
43940 
43941 static void
fnct_XB_IsCompressed(sqlite3_context * context,int argc,sqlite3_value ** argv)43942 fnct_XB_IsCompressed (sqlite3_context * context, int argc,
43943 		      sqlite3_value ** argv)
43944 {
43945 /* SQL function:
43946 / XB_IsCompressed(XmlBLOB)
43947 /
43948 / returns TRUE if the current BLOB is a compressed XmlBLOB,
43949 / FALSE if it's a valid uncompressed XmlBLOB
43950 / or -1 if any error is encountered
43951 */
43952     unsigned char *p_blob;
43953     int n_bytes;
43954     int ret;
43955     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43956     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43957       {
43958 	  sqlite3_result_int (context, -1);
43959 	  return;
43960       }
43961     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
43962     n_bytes = sqlite3_value_bytes (argv[0]);
43963     ret = gaiaIsCompressedXmlBlob (p_blob, n_bytes);
43964     sqlite3_result_int (context, ret);
43965 }
43966 
43967 static void
fnct_XB_IsSchemaValidated(sqlite3_context * context,int argc,sqlite3_value ** argv)43968 fnct_XB_IsSchemaValidated (sqlite3_context * context, int argc,
43969 			   sqlite3_value ** argv)
43970 {
43971 /* SQL function:
43972 / XB_IsSchemaValidated(XmlBLOB)
43973 /
43974 / returns TRUE if the current BLOB is a Schema validated XmlBLOB,
43975 / FALSE if it's a valid but not validated XmlBLOB
43976 / or -1 if any error is encountered
43977 */
43978     unsigned char *p_blob;
43979     int n_bytes;
43980     int ret;
43981     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
43982     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
43983       {
43984 	  sqlite3_result_int (context, -1);
43985 	  return;
43986       }
43987     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
43988     n_bytes = sqlite3_value_bytes (argv[0]);
43989     ret = gaiaIsSchemaValidatedXmlBlob (p_blob, n_bytes);
43990     sqlite3_result_int (context, ret);
43991 }
43992 
43993 static void
fnct_XB_IsIsoMetadata(sqlite3_context * context,int argc,sqlite3_value ** argv)43994 fnct_XB_IsIsoMetadata (sqlite3_context * context, int argc,
43995 		       sqlite3_value ** argv)
43996 {
43997 /* SQL function:
43998 / XB_IsIsoMetadata(XmlBLOB)
43999 /
44000 / returns TRUE if the current BLOB is an ISO Metadata XmlBLOB,
44001 / FALSE if it's a valid XmlBLOB but not an ISO Metadata
44002 / or -1 if any error is encountered
44003 */
44004     unsigned char *p_blob;
44005     int n_bytes;
44006     int ret;
44007     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44008     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44009       {
44010 	  sqlite3_result_int (context, -1);
44011 	  return;
44012       }
44013     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44014     n_bytes = sqlite3_value_bytes (argv[0]);
44015     ret = gaiaIsIsoMetadataXmlBlob (p_blob, n_bytes);
44016     sqlite3_result_int (context, ret);
44017 }
44018 
44019 static void
fnct_XB_IsSldSeVectorStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)44020 fnct_XB_IsSldSeVectorStyle (sqlite3_context * context, int argc,
44021 			    sqlite3_value ** argv)
44022 {
44023 /* SQL function:
44024 / XB_IsSldSeVectorStyle(XmlBLOB)
44025 /
44026 / returns TRUE if the current BLOB is an SLD/SE Vector Style XmlBLOB,
44027 / FALSE if it's a valid XmlBLOB but not an SLD/SE Style
44028 / or -1 if any error is encountered
44029 */
44030     unsigned char *p_blob;
44031     int n_bytes;
44032     int ret;
44033     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44034     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44035       {
44036 	  sqlite3_result_int (context, -1);
44037 	  return;
44038       }
44039     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44040     n_bytes = sqlite3_value_bytes (argv[0]);
44041     ret = gaiaIsSldSeVectorStyleXmlBlob (p_blob, n_bytes);
44042     sqlite3_result_int (context, ret);
44043 }
44044 
44045 static void
fnct_XB_IsSldSeRasterStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)44046 fnct_XB_IsSldSeRasterStyle (sqlite3_context * context, int argc,
44047 			    sqlite3_value ** argv)
44048 {
44049 /* SQL function:
44050 / XB_IsSldSeRasterStyle(XmlBLOB)
44051 /
44052 / returns TRUE if the current BLOB is an SLD/SE Raster Style XmlBLOB,
44053 / FALSE if it's a valid XmlBLOB but not an SLD/SE Style
44054 / or -1 if any error is encountered
44055 */
44056     unsigned char *p_blob;
44057     int n_bytes;
44058     int ret;
44059     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44060     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44061       {
44062 	  sqlite3_result_int (context, -1);
44063 	  return;
44064       }
44065     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44066     n_bytes = sqlite3_value_bytes (argv[0]);
44067     ret = gaiaIsSldSeRasterStyleXmlBlob (p_blob, n_bytes);
44068     sqlite3_result_int (context, ret);
44069 }
44070 
44071 static void
fnct_XB_IsSldStyle(sqlite3_context * context,int argc,sqlite3_value ** argv)44072 fnct_XB_IsSldStyle (sqlite3_context * context, int argc, sqlite3_value ** argv)
44073 {
44074 /* SQL function:
44075 / XB_IsSldStyle(XmlBLOB)
44076 /
44077 / returns TRUE if the current BLOB is an SLD Style XmlBLOB,
44078 / FALSE if it's a valid XmlBLOB but not an SLD Style
44079 / or -1 if any error is encountered
44080 */
44081     unsigned char *p_blob;
44082     int n_bytes;
44083     int ret;
44084     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44085     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44086       {
44087 	  sqlite3_result_int (context, -1);
44088 	  return;
44089       }
44090     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44091     n_bytes = sqlite3_value_bytes (argv[0]);
44092     ret = gaiaIsSldStyleXmlBlob (p_blob, n_bytes);
44093     sqlite3_result_int (context, ret);
44094 }
44095 
44096 static void
fnct_XB_IsMapConfig(sqlite3_context * context,int argc,sqlite3_value ** argv)44097 fnct_XB_IsMapConfig (sqlite3_context * context, int argc, sqlite3_value ** argv)
44098 {
44099 /* SQL function:
44100 / XB_IsMapConfig(XmlBLOB)
44101 /
44102 / returns TRUE if the current BLOB is an XML MapConfig
44103 / FALSE if it's a valid XmlBLOB but not a MapConfig
44104 / or -1 if any error is encountered
44105 */
44106     unsigned char *p_blob;
44107     int n_bytes;
44108     int ret;
44109     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44110     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44111       {
44112 	  sqlite3_result_int (context, -1);
44113 	  return;
44114       }
44115     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44116     n_bytes = sqlite3_value_bytes (argv[0]);
44117     ret = gaiaIsMapConfigXmlBlob (p_blob, n_bytes);
44118     sqlite3_result_int (context, ret);
44119 }
44120 
44121 static void
fnct_XB_IsSvg(sqlite3_context * context,int argc,sqlite3_value ** argv)44122 fnct_XB_IsSvg (sqlite3_context * context, int argc, sqlite3_value ** argv)
44123 {
44124 /* SQL function:
44125 / XB_IsSvg(XmlBLOB)
44126 /
44127 / returns TRUE if the current BLOB is an SLD/SE Style XmlBLOB,
44128 / FALSE if it's a valid XmlBLOB but not an SLD/SE Style
44129 / or -1 if any error is encountered
44130 */
44131     unsigned char *p_blob;
44132     int n_bytes;
44133     int ret;
44134     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44135     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44136       {
44137 	  sqlite3_result_int (context, -1);
44138 	  return;
44139       }
44140     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44141     n_bytes = sqlite3_value_bytes (argv[0]);
44142     ret = gaiaIsSvgXmlBlob (p_blob, n_bytes);
44143     sqlite3_result_int (context, ret);
44144 }
44145 
44146 static void
fnct_XB_IsGpx(sqlite3_context * context,int argc,sqlite3_value ** argv)44147 fnct_XB_IsGpx (sqlite3_context * context, int argc, sqlite3_value ** argv)
44148 {
44149 /* SQL function:
44150 / XB_IsGpx(XmlBLOB)
44151 /
44152 / returns TRUE if the current BLOB is a GPX document XmlBLOB,
44153 / FALSE if it's a valid XmlBLOB but not a GPX document
44154 / or -1 if any error is encountered
44155 */
44156     unsigned char *p_blob;
44157     int n_bytes;
44158     int ret;
44159     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44160     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44161       {
44162 	  sqlite3_result_int (context, -1);
44163 	  return;
44164       }
44165     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44166     n_bytes = sqlite3_value_bytes (argv[0]);
44167     ret = gaiaIsGpxXmlBlob (p_blob, n_bytes);
44168     sqlite3_result_int (context, ret);
44169 }
44170 
44171 static void
fnct_XB_GetDocumentSize(sqlite3_context * context,int argc,sqlite3_value ** argv)44172 fnct_XB_GetDocumentSize (sqlite3_context * context, int argc,
44173 			 sqlite3_value ** argv)
44174 {
44175 /* SQL function:
44176 / XB_GetDocumentSize(XmlBLOB)
44177 /
44178 / if the BLOB is a valid XmlBLOB will return the XMLDocument size (in bytes)
44179 / or NULL if any error is encountered
44180 */
44181     unsigned char *p_blob;
44182     int n_bytes;
44183     int ret;
44184     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44185     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44186       {
44187 	  sqlite3_result_null (context);
44188 	  return;
44189       }
44190     p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
44191     n_bytes = sqlite3_value_bytes (argv[0]);
44192     ret = gaiaXmlBlobGetDocumentSize (p_blob, n_bytes);
44193     if (ret < 0)
44194 	sqlite3_result_null (context);
44195     else
44196 	sqlite3_result_int (context, ret);
44197 }
44198 
44199 static void
fnct_XB_GetSchemaURI(sqlite3_context * context,int argc,sqlite3_value ** argv)44200 fnct_XB_GetSchemaURI (sqlite3_context * context, int argc,
44201 		      sqlite3_value ** argv)
44202 {
44203 /* SQL function:
44204 / XB_GetSchemaURI(XmlBLOB)
44205 /
44206 / if the BLOB is a valid XmlBLOB containing a SchemaURI then
44207 / the SchemaURI will be returned
44208 / return NULL on any other case
44209 */
44210     const unsigned char *p_blob;
44211     int n_bytes;
44212     char *schema_uri;
44213     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44214     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44215       {
44216 	  sqlite3_result_null (context);
44217 	  return;
44218       }
44219     p_blob = sqlite3_value_blob (argv[0]);
44220     n_bytes = sqlite3_value_bytes (argv[0]);
44221     schema_uri = gaiaXmlBlobGetSchemaURI (p_blob, n_bytes);
44222     if (schema_uri == NULL)
44223 	sqlite3_result_null (context);
44224     else
44225 	sqlite3_result_text (context, schema_uri, strlen (schema_uri), free);
44226 }
44227 
44228 static void
fnct_XB_GetFileId(sqlite3_context * context,int argc,sqlite3_value ** argv)44229 fnct_XB_GetFileId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44230 {
44231 /* SQL function:
44232 / XB_GetFileId(XmlBLOB)
44233 /
44234 / if the BLOB is a valid XmlBLOB containing a FileIdentifier then
44235 / the FileIdentifier will be returned
44236 / return NULL on any other case
44237 */
44238     const unsigned char *p_blob;
44239     int n_bytes;
44240     char *file_identifier;
44241     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44242     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44243       {
44244 	  sqlite3_result_null (context);
44245 	  return;
44246       }
44247     p_blob = sqlite3_value_blob (argv[0]);
44248     n_bytes = sqlite3_value_bytes (argv[0]);
44249     file_identifier = gaiaXmlBlobGetFileId (p_blob, n_bytes);
44250     if (file_identifier == NULL)
44251 	sqlite3_result_null (context);
44252     else
44253 	sqlite3_result_text (context, file_identifier,
44254 			     strlen (file_identifier), free);
44255 }
44256 
44257 static void
fnct_XB_GetParentId(sqlite3_context * context,int argc,sqlite3_value ** argv)44258 fnct_XB_GetParentId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44259 {
44260 /* SQL function:
44261 / XB_GetParentId(XmlBLOB)
44262 /
44263 / if the BLOB is a valid XmlBLOB containing a ParentIdentifier then
44264 / the ParentIdentifier will be returned
44265 / return NULL on any other case
44266 */
44267     const unsigned char *p_blob;
44268     int n_bytes;
44269     char *parent_identifier;
44270     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44271     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44272       {
44273 	  sqlite3_result_null (context);
44274 	  return;
44275       }
44276     p_blob = sqlite3_value_blob (argv[0]);
44277     n_bytes = sqlite3_value_bytes (argv[0]);
44278     parent_identifier = gaiaXmlBlobGetParentId (p_blob, n_bytes);
44279     if (parent_identifier == NULL)
44280 	sqlite3_result_null (context);
44281     else
44282 	sqlite3_result_text (context, parent_identifier,
44283 			     strlen (parent_identifier), free);
44284 }
44285 
44286 static void
fnct_XB_SetFileId(sqlite3_context * context,int argc,sqlite3_value ** argv)44287 fnct_XB_SetFileId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44288 {
44289 /* SQL function:
44290 / XB_SetFileId(XmlBLOB, Text value)
44291 /
44292 / if the BLOB is a valid XmlBLOB of the ISO-Metadata type
44293 / already containing a FileID then this function will
44294 / return a new XmlBLOB containing the new FileID
44295 / return NULL on any other case
44296 */
44297     const unsigned char *p_blob;
44298     int n_bytes;
44299     unsigned char *new_blob;
44300     int new_bytes;
44301     const char *identifier;
44302     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44303     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44304       {
44305 	  sqlite3_result_null (context);
44306 	  return;
44307       }
44308     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
44309       {
44310 	  sqlite3_result_null (context);
44311 	  return;
44312       }
44313     p_blob = sqlite3_value_blob (argv[0]);
44314     n_bytes = sqlite3_value_bytes (argv[0]);
44315     identifier = (const char *) sqlite3_value_text (argv[1]);
44316     if (!gaiaXmlBlobSetFileId
44317 	(sqlite3_user_data (context), p_blob, n_bytes, identifier, &new_blob,
44318 	 &new_bytes))
44319 	sqlite3_result_null (context);
44320     else
44321 	sqlite3_result_blob (context, new_blob, new_bytes, free);
44322 }
44323 
44324 static void
fnct_XB_SetParentId(sqlite3_context * context,int argc,sqlite3_value ** argv)44325 fnct_XB_SetParentId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44326 {
44327 /* SQL function:
44328 / XB_SetParentId(XmlBLOB, Text value)
44329 /
44330 / if the BLOB is a valid XmlBLOB of the ISO-Metadata type
44331 / already containing a ParentID then this function will
44332 / return a new XmlBLOB containing the new ParentID
44333 / return NULL on any other case
44334 */
44335     const unsigned char *p_blob;
44336     int n_bytes;
44337     unsigned char *new_blob;
44338     int new_bytes;
44339     const char *identifier;
44340     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44341     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44342       {
44343 	  sqlite3_result_null (context);
44344 	  return;
44345       }
44346     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
44347       {
44348 	  sqlite3_result_null (context);
44349 	  return;
44350       }
44351     p_blob = sqlite3_value_blob (argv[0]);
44352     n_bytes = sqlite3_value_bytes (argv[0]);
44353     identifier = (const char *) sqlite3_value_text (argv[1]);
44354     if (!gaiaXmlBlobSetParentId
44355 	(sqlite3_user_data (context), p_blob, n_bytes, identifier, &new_blob,
44356 	 &new_bytes))
44357 	sqlite3_result_null (context);
44358     else
44359 	sqlite3_result_blob (context, new_blob, new_bytes, free);
44360 }
44361 
44362 static void
fnct_XB_AddFileId(sqlite3_context * context,int argc,sqlite3_value ** argv)44363 fnct_XB_AddFileId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44364 {
44365 /* SQL function:
44366 / XB_AddFileId(XmlBLOB, Text value, Text ns_id, Text uri_id, Text ns_charstr, Text uri_charstr)
44367 /
44368 / if the BLOB is a valid XmlBLOB of the ISO-Metadata type
44369 / not containing a FileID then this function will
44370 / return a new XmlBLOB containing the new FileID
44371 / return NULL on any other case
44372 */
44373     const unsigned char *p_blob;
44374     int n_bytes;
44375     unsigned char *new_blob;
44376     int new_bytes;
44377     const char *identifier;
44378     const char *ns_id = NULL;
44379     const char *uri_id = NULL;
44380     const char *ns_charstr = NULL;
44381     const char *uri_charstr = NULL;
44382     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44383     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44384       {
44385 	  sqlite3_result_null (context);
44386 	  return;
44387       }
44388     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
44389       {
44390 	  sqlite3_result_null (context);
44391 	  return;
44392       }
44393     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT
44394 	|| sqlite3_value_type (argv[2]) == SQLITE_NULL)
44395 	;
44396     else
44397       {
44398 	  sqlite3_result_null (context);
44399 	  return;
44400       }
44401     if (sqlite3_value_type (argv[3]) == SQLITE_TEXT
44402 	|| sqlite3_value_type (argv[3]) == SQLITE_NULL)
44403 	;
44404     else
44405       {
44406 	  sqlite3_result_null (context);
44407 	  return;
44408       }
44409     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT
44410 	|| sqlite3_value_type (argv[4]) == SQLITE_NULL)
44411 	;
44412     else
44413       {
44414 	  sqlite3_result_null (context);
44415 	  return;
44416       }
44417     if (sqlite3_value_type (argv[5]) == SQLITE_TEXT
44418 	|| sqlite3_value_type (argv[5]) == SQLITE_NULL)
44419 	;
44420     else
44421       {
44422 	  sqlite3_result_null (context);
44423 	  return;
44424       }
44425     p_blob = sqlite3_value_blob (argv[0]);
44426     n_bytes = sqlite3_value_bytes (argv[0]);
44427     identifier = (const char *) sqlite3_value_text (argv[1]);
44428     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
44429 	ns_id = (const char *) sqlite3_value_text (argv[2]);
44430     if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
44431 	uri_id = (const char *) sqlite3_value_text (argv[3]);
44432     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
44433 	ns_charstr = (const char *) sqlite3_value_text (argv[4]);
44434     if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
44435 	uri_charstr = (const char *) sqlite3_value_text (argv[5]);
44436     if (!gaiaXmlBlobAddFileId
44437 	(sqlite3_user_data (context), p_blob, n_bytes, identifier, ns_id,
44438 	 uri_id, ns_charstr, uri_charstr, &new_blob, &new_bytes))
44439 	sqlite3_result_null (context);
44440     else
44441 	sqlite3_result_blob (context, new_blob, new_bytes, free);
44442 }
44443 
44444 static void
fnct_XB_AddParentId(sqlite3_context * context,int argc,sqlite3_value ** argv)44445 fnct_XB_AddParentId (sqlite3_context * context, int argc, sqlite3_value ** argv)
44446 {
44447 /* SQL function:
44448 / XB_AddParentId(XmlBLOB, Text value, Text ns_id, Text uri_id, Text ns_charstr, Text url_charstr)
44449 /
44450 / if the BLOB is a valid XmlBLOB of the ISO-Metadata type
44451 / not containing a ParentID then this function will
44452 / return a new XmlBLOB containing the new ParentID
44453 / return NULL on any other case
44454 */
44455     const unsigned char *p_blob;
44456     int n_bytes;
44457     unsigned char *new_blob;
44458     int new_bytes;
44459     const char *identifier;
44460     const char *ns_id = NULL;
44461     const char *uri_id = NULL;
44462     const char *ns_charstr = NULL;
44463     const char *uri_charstr = NULL;
44464     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44465     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44466       {
44467 	  sqlite3_result_null (context);
44468 	  return;
44469       }
44470     if (sqlite3_value_type (argv[1]) != SQLITE_TEXT)
44471       {
44472 	  sqlite3_result_null (context);
44473 	  return;
44474       }
44475     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT
44476 	|| sqlite3_value_type (argv[2]) == SQLITE_NULL)
44477 	;
44478     else
44479       {
44480 	  sqlite3_result_null (context);
44481 	  return;
44482       }
44483     if (sqlite3_value_type (argv[3]) == SQLITE_TEXT
44484 	|| sqlite3_value_type (argv[3]) == SQLITE_NULL)
44485 	;
44486     else
44487       {
44488 	  sqlite3_result_null (context);
44489 	  return;
44490       }
44491     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT
44492 	|| sqlite3_value_type (argv[4]) == SQLITE_NULL)
44493 	;
44494     else
44495       {
44496 	  sqlite3_result_null (context);
44497 	  return;
44498       }
44499     if (sqlite3_value_type (argv[5]) == SQLITE_TEXT
44500 	|| sqlite3_value_type (argv[5]) == SQLITE_NULL)
44501 	;
44502     else
44503       {
44504 	  sqlite3_result_null (context);
44505 	  return;
44506       }
44507     p_blob = sqlite3_value_blob (argv[0]);
44508     n_bytes = sqlite3_value_bytes (argv[0]);
44509     identifier = (const char *) sqlite3_value_text (argv[1]);
44510     if (sqlite3_value_type (argv[2]) == SQLITE_TEXT)
44511 	ns_id = (const char *) sqlite3_value_text (argv[2]);
44512     if (sqlite3_value_type (argv[3]) == SQLITE_TEXT)
44513 	uri_id = (const char *) sqlite3_value_text (argv[3]);
44514     if (sqlite3_value_type (argv[4]) == SQLITE_TEXT)
44515 	ns_charstr = (const char *) sqlite3_value_text (argv[4]);
44516     if (sqlite3_value_type (argv[5]) == SQLITE_TEXT)
44517 	uri_charstr = (const char *) sqlite3_value_text (argv[5]);
44518     if (!gaiaXmlBlobAddParentId
44519 	(sqlite3_user_data (context), p_blob, n_bytes, identifier, ns_id,
44520 	 uri_id, ns_charstr, uri_charstr, &new_blob, &new_bytes))
44521 	sqlite3_result_null (context);
44522     else
44523 	sqlite3_result_blob (context, new_blob, new_bytes, free);
44524 }
44525 
44526 static void
fnct_XB_GetName(sqlite3_context * context,int argc,sqlite3_value ** argv)44527 fnct_XB_GetName (sqlite3_context * context, int argc, sqlite3_value ** argv)
44528 {
44529 /* SQL function:
44530 / XB_GetName(XmlBLOB)
44531 /
44532 / if the BLOB is a valid XmlBLOB containing a Name then
44533 / the Name will be returned
44534 / return NULL on any other case
44535 */
44536     const unsigned char *p_blob;
44537     int n_bytes;
44538     char *name;
44539     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44540     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44541       {
44542 	  sqlite3_result_null (context);
44543 	  return;
44544       }
44545     p_blob = sqlite3_value_blob (argv[0]);
44546     n_bytes = sqlite3_value_bytes (argv[0]);
44547     name = gaiaXmlBlobGetName (p_blob, n_bytes);
44548     if (name == NULL)
44549 	sqlite3_result_null (context);
44550     else
44551 	sqlite3_result_text (context, name, strlen (name), free);
44552 }
44553 
44554 static void
fnct_XB_GetTitle(sqlite3_context * context,int argc,sqlite3_value ** argv)44555 fnct_XB_GetTitle (sqlite3_context * context, int argc, sqlite3_value ** argv)
44556 {
44557 /* SQL function:
44558 / XB_GetTitle(XmlBLOB)
44559 /
44560 / if the BLOB is a valid XmlBLOB containing a Title then
44561 / the Title will be returned
44562 / return NULL on any other case
44563 */
44564     const unsigned char *p_blob;
44565     int n_bytes;
44566     char *title;
44567     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44568     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44569       {
44570 	  sqlite3_result_null (context);
44571 	  return;
44572       }
44573     p_blob = sqlite3_value_blob (argv[0]);
44574     n_bytes = sqlite3_value_bytes (argv[0]);
44575     title = gaiaXmlBlobGetTitle (p_blob, n_bytes);
44576     if (title == NULL)
44577 	sqlite3_result_null (context);
44578     else
44579 	sqlite3_result_text (context, title, strlen (title), free);
44580 }
44581 
44582 static void
fnct_XB_GetAbstract(sqlite3_context * context,int argc,sqlite3_value ** argv)44583 fnct_XB_GetAbstract (sqlite3_context * context, int argc, sqlite3_value ** argv)
44584 {
44585 /* SQL function:
44586 / XB_GetAbstract(XmlBLOB)
44587 /
44588 / if the BLOB is a valid XmlBLOB containing an Abstract then
44589 / the Abstract will be returned
44590 / return NULL on any other case
44591 */
44592     const unsigned char *p_blob;
44593     int n_bytes;
44594     char *abstract;
44595     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44596     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44597       {
44598 	  sqlite3_result_null (context);
44599 	  return;
44600       }
44601     p_blob = sqlite3_value_blob (argv[0]);
44602     n_bytes = sqlite3_value_bytes (argv[0]);
44603     abstract = gaiaXmlBlobGetAbstract (p_blob, n_bytes);
44604     if (abstract == NULL)
44605 	sqlite3_result_null (context);
44606     else
44607 	sqlite3_result_text (context, abstract, strlen (abstract), free);
44608 }
44609 
44610 static void
fnct_XB_GetGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)44611 fnct_XB_GetGeometry (sqlite3_context * context, int argc, sqlite3_value ** argv)
44612 {
44613 /* SQL function:
44614 / XB_GetGeometry(XmlBLOB)
44615 /
44616 / if the BLOB is a valid XmlBLOB containing a Geometry then
44617 / the Geometry will be returned
44618 / return NULL on any other case
44619 */
44620     const unsigned char *p_blob;
44621     int n_bytes;
44622     int blob_len;
44623     unsigned char *blob;
44624     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44625     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44626       {
44627 	  sqlite3_result_null (context);
44628 	  return;
44629       }
44630     p_blob = sqlite3_value_blob (argv[0]);
44631     n_bytes = sqlite3_value_bytes (argv[0]);
44632     gaiaXmlBlobGetGeometry (p_blob, n_bytes, &blob, &blob_len);
44633     if (blob == NULL)
44634 	sqlite3_result_null (context);
44635     else
44636 	sqlite3_result_blob (context, blob, blob_len, free);
44637 }
44638 
44639 static void
fnct_XB_MLineFromGPX(sqlite3_context * context,int argc,sqlite3_value ** argv)44640 fnct_XB_MLineFromGPX (sqlite3_context * context, int argc,
44641 		      sqlite3_value ** argv)
44642 {
44643 /* SQL function:
44644 / XB_MLineFromGPX(XmlBLOB)
44645 /
44646 / if the BLOB is a valid XmlBLOB of the GPX type then
44647 / a MultiLinestring will be returned
44648 / return NULL on any other case
44649 */
44650     const unsigned char *p_blob;
44651     int n_bytes;
44652     int blob_len;
44653     unsigned char *blob = NULL;
44654     gaiaGeomCollPtr geom;
44655     int gpkg_mode = 0;
44656     int tiny_point = 0;
44657     sqlite3 *sqlite = sqlite3_context_db_handle (context);
44658     struct splite_internal_cache *cache = sqlite3_user_data (context);
44659     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44660     if (cache != NULL)
44661       {
44662 	  gpkg_mode = cache->gpkg_mode;
44663 	  tiny_point = cache->tinyPointEnabled;
44664       }
44665     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44666       {
44667 	  sqlite3_result_null (context);
44668 	  return;
44669       }
44670     p_blob = sqlite3_value_blob (argv[0]);
44671     n_bytes = sqlite3_value_bytes (argv[0]);
44672     geom = gaiaXmlBlobMLineFromGPX (p_blob, n_bytes, sqlite);
44673     if (geom != NULL)
44674       {
44675 	  /* builds the BLOB geometry to be returned */
44676 	  gaiaToSpatiaLiteBlobWkbEx2 (geom, &blob, &blob_len, gpkg_mode,
44677 				      tiny_point);
44678 	  sqlite3_result_blob (context, blob, blob_len, free);
44679 	  gaiaFreeGeomColl (geom);
44680       }
44681     else
44682 	sqlite3_result_null (context);
44683 }
44684 
44685 static void
fnct_XB_GetEncoding(sqlite3_context * context,int argc,sqlite3_value ** argv)44686 fnct_XB_GetEncoding (sqlite3_context * context, int argc, sqlite3_value ** argv)
44687 {
44688 /* SQL function:
44689 / XB_GetEncoding(XmlBLOB)
44690 /
44691 / if the BLOB is a valid XmlBLOB explicitly defining an encoding then
44692 / the charset name will be returned
44693 / return NULL on any other case
44694 */
44695     const unsigned char *p_blob;
44696     int n_bytes;
44697     char *encoding;
44698     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44699     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44700       {
44701 	  sqlite3_result_null (context);
44702 	  return;
44703       }
44704     p_blob = sqlite3_value_blob (argv[0]);
44705     n_bytes = sqlite3_value_bytes (argv[0]);
44706     encoding = gaiaXmlBlobGetEncoding (p_blob, n_bytes);
44707     if (encoding == NULL)
44708 	sqlite3_result_null (context);
44709     else
44710 	sqlite3_result_text (context, encoding, strlen (encoding), free);
44711 }
44712 
44713 static void
fnct_XB_GetInternalSchemaURI(sqlite3_context * context,int argc,sqlite3_value ** argv)44714 fnct_XB_GetInternalSchemaURI (sqlite3_context * context, int argc,
44715 			      sqlite3_value ** argv)
44716 {
44717 /* SQL function:
44718 / XB_GetInternalSchemaURI(XmlDocument)
44719 /
44720 / if the XMLDocument is valid and it contains an internally
44721 / defined SchemaURI then this SchemaURI will be returned
44722 / return NULL on any other case
44723 */
44724     const unsigned char *xml;
44725     int xml_len;
44726     char *schema_uri;
44727     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44728     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
44729       {
44730 	  sqlite3_result_null (context);
44731 	  return;
44732       }
44733     xml = sqlite3_value_blob (argv[0]);
44734     xml_len = sqlite3_value_bytes (argv[0]);
44735     schema_uri =
44736 	gaiaXmlGetInternalSchemaURI (sqlite3_user_data (context), xml, xml_len);
44737     if (schema_uri == NULL)
44738 	sqlite3_result_null (context);
44739     else
44740 	sqlite3_result_text (context, schema_uri, strlen (schema_uri), free);
44741 }
44742 
44743 static void
fnct_XB_GetLastParseError(sqlite3_context * context,int argc,sqlite3_value ** argv)44744 fnct_XB_GetLastParseError (sqlite3_context * context, int argc,
44745 			   sqlite3_value ** argv)
44746 {
44747 /* SQL function:
44748 / XB_GetLastParseError()
44749 /
44750 / return the most recent XML Parse error/warning (if any)
44751 / return NULL on any other case
44752 */
44753     char *msg;
44754     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44755     msg = gaiaXmlBlobGetLastParseError (sqlite3_user_data (context));
44756     if (msg == NULL)
44757 	sqlite3_result_null (context);
44758     else
44759 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
44760 }
44761 
44762 static void
fnct_XB_GetLastValidateError(sqlite3_context * context,int argc,sqlite3_value ** argv)44763 fnct_XB_GetLastValidateError (sqlite3_context * context, int argc,
44764 			      sqlite3_value ** argv)
44765 {
44766 /* SQL function:
44767 / XB_GetLastValidateError()
44768 /
44769 / return the most recent XML Validate error/warning (if any)
44770 / return NULL on any other case
44771 */
44772     char *msg;
44773     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44774     msg = gaiaXmlBlobGetLastValidateError (sqlite3_user_data (context));
44775     if (msg == NULL)
44776 	sqlite3_result_null (context);
44777     else
44778 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
44779 }
44780 
44781 static void
fnct_XB_IsValidXPathExpression(sqlite3_context * context,int argc,sqlite3_value ** argv)44782 fnct_XB_IsValidXPathExpression (sqlite3_context * context, int argc,
44783 				sqlite3_value ** argv)
44784 {
44785 /* SQL function:
44786 / XB_IsValidXPathExpression(text XPathExpression)
44787 /
44788 / returns TRUE if the current arg is a valid XPathExpression,
44789 / FALSE if it's not
44790 / or -1 if any error is encountered
44791 */
44792     int ret;
44793     const char *xpath;
44794     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44795     if (sqlite3_value_type (argv[0]) != SQLITE_TEXT)
44796       {
44797 	  sqlite3_result_int (context, -1);
44798 	  return;
44799       }
44800     xpath = (const char *) sqlite3_value_text (argv[0]);
44801     ret = gaiaIsValidXPathExpression (sqlite3_user_data (context), xpath);
44802     sqlite3_result_int (context, ret);
44803 }
44804 
44805 static void
fnct_XB_GetLastXPathError(sqlite3_context * context,int argc,sqlite3_value ** argv)44806 fnct_XB_GetLastXPathError (sqlite3_context * context, int argc,
44807 			   sqlite3_value ** argv)
44808 {
44809 /* SQL function:
44810 / XB_GetLastXPathError()
44811 /
44812 / return the most recent XML Validate error/warning (if any)
44813 / return NULL on any other case
44814 */
44815     char *msg;
44816     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44817     msg = gaiaXmlBlobGetLastXPathError (sqlite3_user_data (context));
44818     if (msg == NULL)
44819 	sqlite3_result_null (context);
44820     else
44821 	sqlite3_result_text (context, msg, strlen (msg), SQLITE_STATIC);
44822 }
44823 
44824 static void
fnct_XB_CacheFlush(sqlite3_context * context,int argc,sqlite3_value ** argv)44825 fnct_XB_CacheFlush (sqlite3_context * context, int argc, sqlite3_value ** argv)
44826 {
44827 /* SQL function:
44828 / XB_CacheFlush()
44829 /
44830 / resets the Internal XML Schema Cache to its initial empty state
44831 /
44832 / returns TRUE on success
44833 */
44834     int i;
44835     struct splite_xmlSchema_cache_item *p_xmlSchema;
44836     struct splite_internal_cache *cache = sqlite3_user_data (context);
44837 
44838     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44839 
44840     for (i = 0; i < MAX_XMLSCHEMA_CACHE; i++)
44841       {
44842 	  /* freeing the XmlSchema cache */
44843 	  p_xmlSchema = &(cache->xmlSchemaCache[i]);
44844 	  splite_free_xml_schema_cache_item (p_xmlSchema);
44845       }
44846     sqlite3_result_int (context, 1);
44847 }
44848 
44849 #endif /* end including LIBXML2 */
44850 
44851 static void
fnct_AffineTransformMatrix_Create(sqlite3_context * context,int argc,sqlite3_value ** argv)44852 fnct_AffineTransformMatrix_Create (sqlite3_context * context, int argc,
44853 				   sqlite3_value ** argv)
44854 {
44855 /* SQL function:
44856 / ATM_Create() - identity transformation
44857 /    or
44858 / ATM_Create(double a, double b, double d, double e,
44859 /            double xoff, double yoff) - 2D
44860 /    or
44861 / ATM_Create(double a, double b, double c, double d,
44862 /            double e, double f, double g, double h,
44863 /            double i, double xoff, double yoff,
44864 /            double zoff) - 3D
44865 /
44866 / returns a BLOB-ATM object or NULL on failure
44867 */
44868     double a = 1.0;
44869     double b = 0.0;
44870     double c = 0.0;
44871     double d = 0.0;
44872     double e = 1.0;
44873     double f = 0.0;
44874     double g = 0.0;
44875     double h = 0.0;
44876     double i = 1.0;
44877     double xoff = 0.0;
44878     double yoff = 0.0;
44879     double zoff = 0.0;
44880     int int_value;
44881     unsigned char *blob;
44882     int blob_sz;
44883     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
44884 
44885 /* validating the input args */
44886     if (argc == 6)
44887       {
44888 	  /* 2D transform */
44889 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
44890 	      a = sqlite3_value_double (argv[0]);
44891 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
44892 	    {
44893 		int_value = sqlite3_value_int (argv[0]);
44894 		a = int_value;
44895 	    }
44896 	  else
44897 	    {
44898 		sqlite3_result_null (context);
44899 		return;
44900 	    }
44901 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
44902 	      b = sqlite3_value_double (argv[1]);
44903 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
44904 	    {
44905 		int_value = sqlite3_value_int (argv[1]);
44906 		b = int_value;
44907 	    }
44908 	  else
44909 	    {
44910 		sqlite3_result_null (context);
44911 		return;
44912 	    }
44913 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
44914 	      d = sqlite3_value_double (argv[2]);
44915 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
44916 	    {
44917 		int_value = sqlite3_value_int (argv[2]);
44918 		d = int_value;
44919 	    }
44920 	  else
44921 	    {
44922 		sqlite3_result_null (context);
44923 		return;
44924 	    }
44925 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
44926 	      e = sqlite3_value_double (argv[3]);
44927 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
44928 	    {
44929 		int_value = sqlite3_value_int (argv[3]);
44930 		e = int_value;
44931 	    }
44932 	  else
44933 	    {
44934 		sqlite3_result_null (context);
44935 		return;
44936 	    }
44937 	  if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
44938 	      xoff = sqlite3_value_double (argv[4]);
44939 	  else if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
44940 	    {
44941 		int_value = sqlite3_value_int (argv[4]);
44942 		xoff = int_value;
44943 	    }
44944 	  else
44945 	    {
44946 		sqlite3_result_null (context);
44947 		return;
44948 	    }
44949 	  if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
44950 	      yoff = sqlite3_value_double (argv[5]);
44951 	  else if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
44952 	    {
44953 		int_value = sqlite3_value_int (argv[5]);
44954 		yoff = int_value;
44955 	    }
44956 	  else
44957 	    {
44958 		sqlite3_result_null (context);
44959 		return;
44960 	    }
44961       }
44962     else if (argc == 12)
44963       {
44964 	  /* 3D transform */
44965 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
44966 	      a = sqlite3_value_double (argv[0]);
44967 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
44968 	    {
44969 		int_value = sqlite3_value_int (argv[0]);
44970 		a = int_value;
44971 	    }
44972 	  else
44973 	    {
44974 		sqlite3_result_null (context);
44975 		return;
44976 	    }
44977 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
44978 	      b = sqlite3_value_double (argv[1]);
44979 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
44980 	    {
44981 		int_value = sqlite3_value_int (argv[1]);
44982 		b = int_value;
44983 	    }
44984 	  else
44985 	    {
44986 		sqlite3_result_null (context);
44987 		return;
44988 	    }
44989 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
44990 	      c = sqlite3_value_double (argv[2]);
44991 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
44992 	    {
44993 		int_value = sqlite3_value_int (argv[2]);
44994 		c = int_value;
44995 	    }
44996 	  else
44997 	    {
44998 		sqlite3_result_null (context);
44999 		return;
45000 	    }
45001 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
45002 	      d = sqlite3_value_double (argv[3]);
45003 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
45004 	    {
45005 		int_value = sqlite3_value_int (argv[3]);
45006 		d = int_value;
45007 	    }
45008 	  else
45009 	    {
45010 		sqlite3_result_null (context);
45011 		return;
45012 	    }
45013 	  if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
45014 	      e = sqlite3_value_double (argv[4]);
45015 	  else if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
45016 	    {
45017 		int_value = sqlite3_value_int (argv[4]);
45018 		e = int_value;
45019 	    }
45020 	  else
45021 	    {
45022 		sqlite3_result_null (context);
45023 		return;
45024 	    }
45025 	  if (sqlite3_value_type (argv[5]) == SQLITE_FLOAT)
45026 	      f = sqlite3_value_double (argv[5]);
45027 	  else if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
45028 	    {
45029 		int_value = sqlite3_value_int (argv[5]);
45030 		f = int_value;
45031 	    }
45032 	  else
45033 	    {
45034 		sqlite3_result_null (context);
45035 		return;
45036 	    }
45037 	  if (sqlite3_value_type (argv[6]) == SQLITE_FLOAT)
45038 	      g = sqlite3_value_double (argv[6]);
45039 	  else if (sqlite3_value_type (argv[6]) == SQLITE_INTEGER)
45040 	    {
45041 		int_value = sqlite3_value_int (argv[6]);
45042 		g = int_value;
45043 	    }
45044 	  else
45045 	    {
45046 		sqlite3_result_null (context);
45047 		return;
45048 	    }
45049 	  if (sqlite3_value_type (argv[7]) == SQLITE_FLOAT)
45050 	      h = sqlite3_value_double (argv[7]);
45051 	  else if (sqlite3_value_type (argv[7]) == SQLITE_INTEGER)
45052 	    {
45053 		int_value = sqlite3_value_int (argv[7]);
45054 		h = int_value;
45055 	    }
45056 	  else
45057 	    {
45058 		sqlite3_result_null (context);
45059 		return;
45060 	    }
45061 	  if (sqlite3_value_type (argv[8]) == SQLITE_FLOAT)
45062 	      i = sqlite3_value_double (argv[8]);
45063 	  else if (sqlite3_value_type (argv[8]) == SQLITE_INTEGER)
45064 	    {
45065 		int_value = sqlite3_value_int (argv[8]);
45066 		i = int_value;
45067 	    }
45068 	  else
45069 	    {
45070 		sqlite3_result_null (context);
45071 		return;
45072 	    }
45073 	  if (sqlite3_value_type (argv[9]) == SQLITE_FLOAT)
45074 	      xoff = sqlite3_value_double (argv[6]);
45075 	  else if (sqlite3_value_type (argv[9]) == SQLITE_INTEGER)
45076 	    {
45077 		int_value = sqlite3_value_int (argv[9]);
45078 		xoff = int_value;
45079 	    }
45080 	  else
45081 	    {
45082 		sqlite3_result_null (context);
45083 		return;
45084 	    }
45085 	  if (sqlite3_value_type (argv[10]) == SQLITE_FLOAT)
45086 	      yoff = sqlite3_value_double (argv[10]);
45087 	  else if (sqlite3_value_type (argv[10]) == SQLITE_INTEGER)
45088 	    {
45089 		int_value = sqlite3_value_int (argv[10]);
45090 		yoff = int_value;
45091 	    }
45092 	  else
45093 	    {
45094 		sqlite3_result_null (context);
45095 		return;
45096 	    }
45097 	  if (sqlite3_value_type (argv[11]) == SQLITE_FLOAT)
45098 	      zoff = sqlite3_value_double (argv[11]);
45099 	  else if (sqlite3_value_type (argv[11]) == SQLITE_INTEGER)
45100 	    {
45101 		int_value = sqlite3_value_int (argv[11]);
45102 		zoff = int_value;
45103 	    }
45104 	  else
45105 	    {
45106 		sqlite3_result_null (context);
45107 		return;
45108 	    }
45109       }
45110 
45111 /* creating the BLOB-encoded Affine Transform Matrix */
45112     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45113 			&blob_sz);
45114     if (blob == NULL)
45115 	sqlite3_result_null (context);
45116     else
45117 	sqlite3_result_blob (context, blob, blob_sz, free);
45118 }
45119 
45120 static void
fnct_AffineTransformMatrix_CreateTranslate(sqlite3_context * context,int argc,sqlite3_value ** argv)45121 fnct_AffineTransformMatrix_CreateTranslate (sqlite3_context * context,
45122 					    int argc, sqlite3_value ** argv)
45123 {
45124 /* SQL function:
45125 / ATM_CreateTranslate(double tx, double ty) - 2D
45126 /    or
45127 / ATM_CreateTranslate(double tx, double ty, double tz) - 3D
45128 /
45129 / returns a BLOB-ATM object or NULL on failure
45130 */
45131     double a = 1.0;
45132     double b = 0.0;
45133     double c = 0.0;
45134     double d = 0.0;
45135     double e = 1.0;
45136     double f = 0.0;
45137     double g = 0.0;
45138     double h = 0.0;
45139     double i = 1.0;
45140     double xoff = 0.0;
45141     double yoff = 0.0;
45142     double zoff = 0.0;
45143     int int_value;
45144     unsigned char *blob;
45145     int blob_sz;
45146     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45147 
45148 /* validating the input args */
45149     if (argc == 2)
45150       {
45151 	  /* 2D translate */
45152 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45153 	      xoff = sqlite3_value_double (argv[0]);
45154 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45155 	    {
45156 		int_value = sqlite3_value_int (argv[0]);
45157 		xoff = int_value;
45158 	    }
45159 	  else
45160 	    {
45161 		sqlite3_result_null (context);
45162 		return;
45163 	    }
45164 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45165 	      yoff = sqlite3_value_double (argv[1]);
45166 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45167 	    {
45168 		int_value = sqlite3_value_int (argv[1]);
45169 		yoff = int_value;
45170 	    }
45171 	  else
45172 	    {
45173 		sqlite3_result_null (context);
45174 		return;
45175 	    }
45176       }
45177     else if (argc == 3)
45178       {
45179 	  /* 3D translate */
45180 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45181 	      xoff = sqlite3_value_double (argv[0]);
45182 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45183 	    {
45184 		int_value = sqlite3_value_int (argv[0]);
45185 		xoff = int_value;
45186 	    }
45187 	  else
45188 	    {
45189 		sqlite3_result_null (context);
45190 		return;
45191 	    }
45192 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45193 	      yoff = sqlite3_value_double (argv[1]);
45194 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45195 	    {
45196 		int_value = sqlite3_value_int (argv[1]);
45197 		yoff = int_value;
45198 	    }
45199 	  else
45200 	    {
45201 		sqlite3_result_null (context);
45202 		return;
45203 	    }
45204 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45205 	      zoff = sqlite3_value_double (argv[2]);
45206 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45207 	    {
45208 		int_value = sqlite3_value_int (argv[2]);
45209 		zoff = int_value;
45210 	    }
45211 	  else
45212 	    {
45213 		sqlite3_result_null (context);
45214 		return;
45215 	    }
45216       }
45217 
45218 /* creating the BLOB-encoded Affine Transform Matrix */
45219     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45220 			&blob_sz);
45221     if (blob == NULL)
45222 	sqlite3_result_null (context);
45223     else
45224 	sqlite3_result_blob (context, blob, blob_sz, free);
45225 }
45226 
45227 static void
fnct_AffineTransformMatrix_CreateScale(sqlite3_context * context,int argc,sqlite3_value ** argv)45228 fnct_AffineTransformMatrix_CreateScale (sqlite3_context * context, int argc,
45229 					sqlite3_value ** argv)
45230 {
45231 /* SQL function:
45232 / ATM_CreateScale(double sx, double sy) - 2D
45233 /    or
45234 / ATM_CreateScale(double sx, double sy, double sz - 3D
45235 /
45236 / returns a BLOB-ATM object or NULL on failure
45237 */
45238     double a = 1.0;
45239     double b = 0.0;
45240     double c = 0.0;
45241     double d = 0.0;
45242     double e = 1.0;
45243     double f = 0.0;
45244     double g = 0.0;
45245     double h = 0.0;
45246     double i = 1.0;
45247     double xoff = 0.0;
45248     double yoff = 0.0;
45249     double zoff = 0.0;
45250     int int_value;
45251     unsigned char *blob;
45252     int blob_sz;
45253     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45254 
45255 /* validating the input args */
45256     if (argc == 2)
45257       {
45258 	  /* 2D scale */
45259 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45260 	      a = sqlite3_value_double (argv[0]);
45261 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45262 	    {
45263 		int_value = sqlite3_value_int (argv[0]);
45264 		a = int_value;
45265 	    }
45266 	  else
45267 	    {
45268 		sqlite3_result_null (context);
45269 		return;
45270 	    }
45271 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45272 	      e = sqlite3_value_double (argv[1]);
45273 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45274 	    {
45275 		int_value = sqlite3_value_int (argv[1]);
45276 		e = int_value;
45277 	    }
45278 	  else
45279 	    {
45280 		sqlite3_result_null (context);
45281 		return;
45282 	    }
45283       }
45284     else if (argc == 3)
45285       {
45286 	  /* 3D scale */
45287 	  if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45288 	      a = sqlite3_value_double (argv[0]);
45289 	  else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45290 	    {
45291 		int_value = sqlite3_value_int (argv[0]);
45292 		a = int_value;
45293 	    }
45294 	  else
45295 	    {
45296 		sqlite3_result_null (context);
45297 		return;
45298 	    }
45299 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45300 	      e = sqlite3_value_double (argv[1]);
45301 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45302 	    {
45303 		int_value = sqlite3_value_int (argv[1]);
45304 		e = int_value;
45305 	    }
45306 	  else
45307 	    {
45308 		sqlite3_result_null (context);
45309 		return;
45310 	    }
45311 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45312 	      i = sqlite3_value_double (argv[2]);
45313 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45314 	    {
45315 		int_value = sqlite3_value_int (argv[2]);
45316 		i = int_value;
45317 	    }
45318 	  else
45319 	    {
45320 		sqlite3_result_null (context);
45321 		return;
45322 	    }
45323       }
45324 
45325 /* creating the BLOB-encoded Affine Transform Matrix */
45326     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45327 			&blob_sz);
45328     if (blob == NULL)
45329 	sqlite3_result_null (context);
45330     else
45331 	sqlite3_result_blob (context, blob, blob_sz, free);
45332 }
45333 
45334 static void
fnct_AffineTransformMatrix_CreateRotate(sqlite3_context * context,int argc,sqlite3_value ** argv)45335 fnct_AffineTransformMatrix_CreateRotate (sqlite3_context * context, int argc,
45336 					 sqlite3_value ** argv)
45337 {
45338 /* SQL function:
45339 / ATM_CreateRotate(double angleInDegrees) - 2D
45340 /    or
45341 / ATM_CreateZRoll(double angeInDegrees) - 3D
45342 /
45343 / returns a BLOB-ATM object or NULL on failure
45344 */
45345     double a = 1.0;
45346     double b = 0.0;
45347     double c = 0.0;
45348     double d = 0.0;
45349     double e = 1.0;
45350     double f = 0.0;
45351     double g = 0.0;
45352     double h = 0.0;
45353     double i = 1.0;
45354     double xoff = 0.0;
45355     double yoff = 0.0;
45356     double zoff = 0.0;
45357     int int_value;
45358     unsigned char *blob;
45359     int blob_sz;
45360     double angle;
45361     double coeff = .0174532925199432958;
45362     double rads;
45363     double vsin;
45364     double vcos;
45365     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45366 
45367 /* validating the input args */
45368     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45369 	angle = sqlite3_value_double (argv[0]);
45370     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45371       {
45372 	  int_value = sqlite3_value_int (argv[0]);
45373 	  angle = int_value;
45374       }
45375     else
45376       {
45377 	  sqlite3_result_null (context);
45378 	  return;
45379       }
45380     rads = angle * coeff;
45381     vsin = sin (rads);
45382     vcos = cos (rads);
45383     a = vcos;
45384     b = -vsin;
45385     d = vsin;
45386     e = vcos;
45387 
45388 /* creating the BLOB-encoded Affine Transform Matrix */
45389     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45390 			&blob_sz);
45391     if (blob == NULL)
45392 	sqlite3_result_null (context);
45393     else
45394 	sqlite3_result_blob (context, blob, blob_sz, free);
45395 }
45396 
45397 static void
fnct_AffineTransformMatrix_CreateXRoll(sqlite3_context * context,int argc,sqlite3_value ** argv)45398 fnct_AffineTransformMatrix_CreateXRoll (sqlite3_context * context, int argc,
45399 					sqlite3_value ** argv)
45400 {
45401 /* SQL function:
45402 / ATM_CreateXRoll(double angleInDegrees) - 3D
45403 /
45404 / returns a BLOB-ATM object or NULL on failure
45405 */
45406     double a = 1.0;
45407     double b = 0.0;
45408     double c = 0.0;
45409     double d = 0.0;
45410     double e = 1.0;
45411     double f = 0.0;
45412     double g = 0.0;
45413     double h = 0.0;
45414     double i = 1.0;
45415     double xoff = 0.0;
45416     double yoff = 0.0;
45417     double zoff = 0.0;
45418     int int_value;
45419     unsigned char *blob;
45420     int blob_sz;
45421     double angle;
45422     double coeff = .0174532925199432958;
45423     double rads;
45424     double vsin;
45425     double vcos;
45426     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45427 
45428 /* validating the input args */
45429     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45430 	angle = sqlite3_value_double (argv[0]);
45431     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45432       {
45433 	  int_value = sqlite3_value_int (argv[0]);
45434 	  angle = int_value;
45435       }
45436     else
45437       {
45438 	  sqlite3_result_null (context);
45439 	  return;
45440       }
45441     rads = angle * coeff;
45442     vsin = sin (rads);
45443     vcos = cos (rads);
45444     e = vcos;
45445     f = -vsin;
45446     h = vsin;
45447     i = vcos;
45448 
45449 /* creating the BLOB-encoded Affine Transform Matrix */
45450     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45451 			&blob_sz);
45452     if (blob == NULL)
45453 	sqlite3_result_null (context);
45454     else
45455 	sqlite3_result_blob (context, blob, blob_sz, free);
45456 }
45457 
45458 static void
fnct_AffineTransformMatrix_CreateYRoll(sqlite3_context * context,int argc,sqlite3_value ** argv)45459 fnct_AffineTransformMatrix_CreateYRoll (sqlite3_context * context, int argc,
45460 					sqlite3_value ** argv)
45461 {
45462 /* SQL function:
45463 / ATM_CreateYRoll(double angleInDegrees) - 3D
45464 /
45465 / returns a BLOB-ATM object or NULL on failure
45466 */
45467     double a = 1.0;
45468     double b = 0.0;
45469     double c = 0.0;
45470     double d = 0.0;
45471     double e = 1.0;
45472     double f = 0.0;
45473     double g = 0.0;
45474     double h = 0.0;
45475     double i = 1.0;
45476     double xoff = 0.0;
45477     double yoff = 0.0;
45478     double zoff = 0.0;
45479     int int_value;
45480     unsigned char *blob;
45481     int blob_sz;
45482     double angle;
45483     double coeff = .0174532925199432958;
45484     double rads;
45485     double vsin;
45486     double vcos;
45487     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45488 
45489 /* validating the input args */
45490     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
45491 	angle = sqlite3_value_double (argv[0]);
45492     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
45493       {
45494 	  int_value = sqlite3_value_int (argv[0]);
45495 	  angle = int_value;
45496       }
45497     else
45498       {
45499 	  sqlite3_result_null (context);
45500 	  return;
45501       }
45502     rads = angle * coeff;
45503     vsin = sin (rads);
45504     vcos = cos (rads);
45505     a = vcos;
45506     c = vsin;
45507     g = -vsin;
45508     i = vcos;
45509 
45510 /* creating the BLOB-encoded Affine Transform Matrix */
45511     gaia_matrix_create (a, b, c, d, e, f, g, h, i, xoff, yoff, zoff, &blob,
45512 			&blob_sz);
45513     if (blob == NULL)
45514 	sqlite3_result_null (context);
45515     else
45516 	sqlite3_result_blob (context, blob, blob_sz, free);
45517 }
45518 
45519 static void
fnct_AffineTransformMatrix_Multiply(sqlite3_context * context,int argc,sqlite3_value ** argv)45520 fnct_AffineTransformMatrix_Multiply (sqlite3_context * context, int argc,
45521 				     sqlite3_value ** argv)
45522 {
45523 /* SQL function:
45524 / ATM_Multiply(blob atmA, blob atmB)
45525 /
45526 / returns a BLOB-ATM object or NULL on failure
45527 */
45528     unsigned char *blob;
45529     int blob_sz;
45530     const unsigned char *iblob1;
45531     int iblob1_sz;
45532     const unsigned char *iblob2;
45533     int iblob2_sz;
45534     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45535 
45536 /* validating the input args */
45537     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45538       {
45539 	  iblob1 = sqlite3_value_blob (argv[0]);
45540 	  iblob1_sz = sqlite3_value_bytes (argv[0]);
45541       }
45542     else
45543       {
45544 	  sqlite3_result_null (context);
45545 	  return;
45546       }
45547     if (sqlite3_value_type (argv[1]) == SQLITE_BLOB)
45548       {
45549 	  iblob2 = sqlite3_value_blob (argv[1]);
45550 	  iblob2_sz = sqlite3_value_bytes (argv[1]);
45551       }
45552     else
45553       {
45554 	  sqlite3_result_null (context);
45555 	  return;
45556       }
45557 
45558 /* creating the BLOB-encoded Affine Transform Matrix */
45559     gaia_matrix_multiply (iblob1, iblob1_sz, iblob2, iblob2_sz, &blob,
45560 			  &blob_sz);
45561     if (blob == NULL)
45562 	sqlite3_result_null (context);
45563     else
45564 	sqlite3_result_blob (context, blob, blob_sz, free);
45565 }
45566 
45567 static void
fnct_AffineTransformMatrix_Translate(sqlite3_context * context,int argc,sqlite3_value ** argv)45568 fnct_AffineTransformMatrix_Translate (sqlite3_context * context, int argc,
45569 				      sqlite3_value ** argv)
45570 {
45571 /* SQL function:
45572 / ATM_Translate(blob atm, double tx, double ty) - 2D
45573 /    or
45574 / ATM_Translate(blob atm, double tx, double ty, double tz) - 3D
45575 /
45576 / returns a BLOB-ATM object or NULL on failure
45577 */
45578     double a = 1.0;
45579     double b = 0.0;
45580     double c = 0.0;
45581     double d = 0.0;
45582     double e = 1.0;
45583     double f = 0.0;
45584     double g = 0.0;
45585     double h = 0.0;
45586     double i = 1.0;
45587     double xoff = 0.0;
45588     double yoff = 0.0;
45589     double zoff = 0.0;
45590     int int_value;
45591     unsigned char *blob;
45592     int blob_sz;
45593     const unsigned char *iblob = NULL;
45594     int iblob_sz = 0;
45595     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45596 
45597 /* validating the input args */
45598     if (argc == 3)
45599       {
45600 	  /* 2D translate */
45601 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45602 	    {
45603 		iblob = sqlite3_value_blob (argv[0]);
45604 		iblob_sz = sqlite3_value_bytes (argv[0]);
45605 	    }
45606 	  else
45607 	    {
45608 		sqlite3_result_null (context);
45609 		return;
45610 	    }
45611 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45612 	      xoff = sqlite3_value_double (argv[1]);
45613 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45614 	    {
45615 		int_value = sqlite3_value_int (argv[1]);
45616 		xoff = int_value;
45617 	    }
45618 	  else
45619 	    {
45620 		sqlite3_result_null (context);
45621 		return;
45622 	    }
45623 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45624 	      yoff = sqlite3_value_double (argv[2]);
45625 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45626 	    {
45627 		int_value = sqlite3_value_int (argv[2]);
45628 		yoff = int_value;
45629 	    }
45630 	  else
45631 	    {
45632 		sqlite3_result_null (context);
45633 		return;
45634 	    }
45635       }
45636     else if (argc == 4)
45637       {
45638 	  /* 3D translate */
45639 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45640 	    {
45641 		iblob = sqlite3_value_blob (argv[0]);
45642 		iblob_sz = sqlite3_value_bytes (argv[0]);
45643 	    }
45644 	  else
45645 	    {
45646 		sqlite3_result_null (context);
45647 		return;
45648 	    }
45649 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45650 	      xoff = sqlite3_value_double (argv[1]);
45651 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45652 	    {
45653 		int_value = sqlite3_value_int (argv[1]);
45654 		xoff = int_value;
45655 	    }
45656 	  else
45657 	    {
45658 		sqlite3_result_null (context);
45659 		return;
45660 	    }
45661 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45662 	      yoff = sqlite3_value_double (argv[2]);
45663 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45664 	    {
45665 		int_value = sqlite3_value_int (argv[2]);
45666 		yoff = int_value;
45667 	    }
45668 	  else
45669 	    {
45670 		sqlite3_result_null (context);
45671 		return;
45672 	    }
45673 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
45674 	      zoff = sqlite3_value_double (argv[3]);
45675 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
45676 	    {
45677 		int_value = sqlite3_value_int (argv[3]);
45678 		zoff = int_value;
45679 	    }
45680 	  else
45681 	    {
45682 		sqlite3_result_null (context);
45683 		return;
45684 	    }
45685       }
45686 
45687 /* creating the BLOB-encoded Affine Transform Matrix */
45688     gaia_matrix_create_multiply (iblob, iblob_sz, a, b, c, d, e, f, g, h, i,
45689 				 xoff, yoff, zoff, &blob, &blob_sz);
45690     if (blob == NULL)
45691 	sqlite3_result_null (context);
45692     else
45693 	sqlite3_result_blob (context, blob, blob_sz, free);
45694 }
45695 
45696 static void
fnct_AffineTransformMatrix_Scale(sqlite3_context * context,int argc,sqlite3_value ** argv)45697 fnct_AffineTransformMatrix_Scale (sqlite3_context * context, int argc,
45698 				  sqlite3_value ** argv)
45699 {
45700 /* SQL function:
45701 / ATM_Scale(blob atm, double sx, double sy) - 2D
45702 /    or
45703 / ATM_Scale(blob atm, double sx, double sy, double sz) - 3D
45704 /
45705 / will create a BLOB-encoded Affine Transform Matrix
45706 /
45707 / returns a BLOB-ATM object or NULL on failure
45708 */
45709     double a = 1.0;
45710     double b = 0.0;
45711     double c = 0.0;
45712     double d = 0.0;
45713     double e = 1.0;
45714     double f = 0.0;
45715     double g = 0.0;
45716     double h = 0.0;
45717     double i = 1.0;
45718     double xoff = 0.0;
45719     double yoff = 0.0;
45720     double zoff = 0.0;
45721     int int_value;
45722     unsigned char *blob;
45723     int blob_sz;
45724     const unsigned char *iblob = NULL;
45725     int iblob_sz = 0;
45726     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45727 
45728 /* validating the input args */
45729     if (argc == 3)
45730       {
45731 	  /* 2D scale */
45732 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45733 	    {
45734 		iblob = sqlite3_value_blob (argv[0]);
45735 		iblob_sz = sqlite3_value_bytes (argv[0]);
45736 	    }
45737 	  else
45738 	    {
45739 		sqlite3_result_null (context);
45740 		return;
45741 	    }
45742 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45743 	      a = sqlite3_value_double (argv[1]);
45744 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45745 	    {
45746 		int_value = sqlite3_value_int (argv[1]);
45747 		a = int_value;
45748 	    }
45749 	  else
45750 	    {
45751 		sqlite3_result_null (context);
45752 		return;
45753 	    }
45754 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45755 	      e = sqlite3_value_double (argv[2]);
45756 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45757 	    {
45758 		int_value = sqlite3_value_int (argv[2]);
45759 		e = int_value;
45760 	    }
45761 	  else
45762 	    {
45763 		sqlite3_result_null (context);
45764 		return;
45765 	    }
45766       }
45767     else if (argc == 4)
45768       {
45769 	  /* 3D scale */
45770 	  if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45771 	    {
45772 		iblob = sqlite3_value_blob (argv[0]);
45773 		iblob_sz = sqlite3_value_bytes (argv[0]);
45774 	    }
45775 	  else
45776 	    {
45777 		sqlite3_result_null (context);
45778 		return;
45779 	    }
45780 	  if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45781 	      a = sqlite3_value_double (argv[1]);
45782 	  else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45783 	    {
45784 		int_value = sqlite3_value_int (argv[1]);
45785 		a = int_value;
45786 	    }
45787 	  else
45788 	    {
45789 		sqlite3_result_null (context);
45790 		return;
45791 	    }
45792 	  if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
45793 	      e = sqlite3_value_double (argv[2]);
45794 	  else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
45795 	    {
45796 		int_value = sqlite3_value_int (argv[2]);
45797 		e = int_value;
45798 	    }
45799 	  else
45800 	    {
45801 		sqlite3_result_null (context);
45802 		return;
45803 	    }
45804 	  if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
45805 	      i = sqlite3_value_double (argv[3]);
45806 	  else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
45807 	    {
45808 		int_value = sqlite3_value_int (argv[3]);
45809 		i = int_value;
45810 	    }
45811 	  else
45812 	    {
45813 		sqlite3_result_null (context);
45814 		return;
45815 	    }
45816       }
45817 
45818 /* creating the BLOB-encoded Affine Transform Matrix */
45819     gaia_matrix_create_multiply (iblob, iblob_sz, a, b, c, d, e, f, g, h, i,
45820 				 xoff, yoff, zoff, &blob, &blob_sz);
45821     if (blob == NULL)
45822 	sqlite3_result_null (context);
45823     else
45824 	sqlite3_result_blob (context, blob, blob_sz, free);
45825 }
45826 
45827 static void
fnct_AffineTransformMatrix_Rotate(sqlite3_context * context,int argc,sqlite3_value ** argv)45828 fnct_AffineTransformMatrix_Rotate (sqlite3_context * context, int argc,
45829 				   sqlite3_value ** argv)
45830 {
45831 /* SQL function:
45832 / ATM_Rotate(blob atm, double angleInDegrees) - 2D
45833 /    or
45834 / ATM_ZRoll(blob atm, double angleInDegrees) - 3D
45835 /
45836 / will create a BLOB-encoded Affine Transform Matrix
45837 /
45838 / returns a BLOB-ATM object or NULL on failure
45839 */
45840     double a = 1.0;
45841     double b = 0.0;
45842     double c = 0.0;
45843     double d = 0.0;
45844     double e = 1.0;
45845     double f = 0.0;
45846     double g = 0.0;
45847     double h = 0.0;
45848     double i = 1.0;
45849     double xoff = 0.0;
45850     double yoff = 0.0;
45851     double zoff = 0.0;
45852     int int_value;
45853     double angle;
45854     double coeff = .0174532925199432958;
45855     double rads;
45856     double vsin;
45857     double vcos;
45858     unsigned char *blob;
45859     int blob_sz;
45860     const unsigned char *iblob;
45861     int iblob_sz;
45862     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45863 
45864 /* validating the input args */
45865     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45866       {
45867 	  iblob = sqlite3_value_blob (argv[0]);
45868 	  iblob_sz = sqlite3_value_bytes (argv[0]);
45869       }
45870     else
45871       {
45872 	  sqlite3_result_null (context);
45873 	  return;
45874       }
45875     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45876 	angle = sqlite3_value_double (argv[1]);
45877     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45878       {
45879 	  int_value = sqlite3_value_int (argv[1]);
45880 	  angle = int_value;
45881       }
45882     else
45883       {
45884 	  sqlite3_result_null (context);
45885 	  return;
45886       }
45887     rads = angle * coeff;
45888     vsin = sin (rads);
45889     vcos = cos (rads);
45890     a = vcos;
45891     b = -vsin;
45892     d = vsin;
45893     e = vcos;
45894 
45895 /* creating the BLOB-encoded Affine Transform Matrix */
45896     gaia_matrix_create_multiply (iblob, iblob_sz, a, b, c, d, e, f, g, h, i,
45897 				 xoff, yoff, zoff, &blob, &blob_sz);
45898     if (blob == NULL)
45899 	sqlite3_result_null (context);
45900     else
45901 	sqlite3_result_blob (context, blob, blob_sz, free);
45902 }
45903 
45904 static void
fnct_AffineTransformMatrix_XRoll(sqlite3_context * context,int argc,sqlite3_value ** argv)45905 fnct_AffineTransformMatrix_XRoll (sqlite3_context * context, int argc,
45906 				  sqlite3_value ** argv)
45907 {
45908 /* SQL function:
45909 / ATM_XRoll(double angleInDegrees, blob atm) - 3D
45910 /
45911 / will create a BLOB-encoded Affine Transform Matrix
45912 /
45913 / returns a BLOB-ATM object or NULL on failure
45914 */
45915     double a = 1.0;
45916     double b = 0.0;
45917     double c = 0.0;
45918     double d = 0.0;
45919     double e = 1.0;
45920     double f = 0.0;
45921     double g = 0.0;
45922     double h = 0.0;
45923     double i = 1.0;
45924     double xoff = 0.0;
45925     double yoff = 0.0;
45926     double zoff = 0.0;
45927     int int_value;
45928     double angle;
45929     double coeff = .0174532925199432958;
45930     double rads;
45931     double vsin;
45932     double vcos;
45933     unsigned char *blob;
45934     int blob_sz;
45935     const unsigned char *iblob;
45936     int iblob_sz;
45937     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
45938 
45939 /* validating the input args */
45940     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
45941       {
45942 	  iblob = sqlite3_value_blob (argv[0]);
45943 	  iblob_sz = sqlite3_value_bytes (argv[0]);
45944       }
45945     else
45946       {
45947 	  sqlite3_result_null (context);
45948 	  return;
45949       }
45950     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
45951 	angle = sqlite3_value_double (argv[1]);
45952     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
45953       {
45954 	  int_value = sqlite3_value_int (argv[1]);
45955 	  angle = int_value;
45956       }
45957     else
45958       {
45959 	  sqlite3_result_null (context);
45960 	  return;
45961       }
45962     rads = angle * coeff;
45963     vsin = sin (rads);
45964     vcos = cos (rads);
45965     e = vcos;
45966     f = -vsin;
45967     h = vsin;
45968     i = vcos;
45969 
45970 /* creating the BLOB-encoded Affine Transform Matrix */
45971     gaia_matrix_create_multiply (iblob, iblob_sz, a, b, c, d, e, f, g, h, i,
45972 				 xoff, yoff, zoff, &blob, &blob_sz);
45973     if (blob == NULL)
45974 	sqlite3_result_null (context);
45975     else
45976 	sqlite3_result_blob (context, blob, blob_sz, free);
45977 }
45978 
45979 static void
fnct_AffineTransformMatrix_YRoll(sqlite3_context * context,int argc,sqlite3_value ** argv)45980 fnct_AffineTransformMatrix_YRoll (sqlite3_context * context, int argc,
45981 				  sqlite3_value ** argv)
45982 {
45983 /* SQL function:
45984 / ATM_YRoll(double angleInDegrees, blob atm) - 3D
45985 /
45986 / will create a BLOB-encoded Affine Transform Matrix
45987 /
45988 / returns a BLOB-ATM object or NULL on failure
45989 */
45990     double a = 1.0;
45991     double b = 0.0;
45992     double c = 0.0;
45993     double d = 0.0;
45994     double e = 1.0;
45995     double f = 0.0;
45996     double g = 0.0;
45997     double h = 0.0;
45998     double i = 1.0;
45999     double xoff = 0.0;
46000     double yoff = 0.0;
46001     double zoff = 0.0;
46002     int int_value;
46003     double angle;
46004     double coeff = .0174532925199432958;
46005     double rads;
46006     double vsin;
46007     double vcos;
46008     unsigned char *blob;
46009     int blob_sz;
46010     const unsigned char *iblob;
46011     int iblob_sz;
46012     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46013 
46014 /* validating the input args */
46015     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46016       {
46017 	  iblob = sqlite3_value_blob (argv[0]);
46018 	  iblob_sz = sqlite3_value_bytes (argv[0]);
46019       }
46020     else
46021       {
46022 	  sqlite3_result_null (context);
46023 	  return;
46024       }
46025     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
46026 	angle = sqlite3_value_double (argv[1]);
46027     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
46028       {
46029 	  int_value = sqlite3_value_int (argv[1]);
46030 	  angle = int_value;
46031       }
46032     else
46033       {
46034 	  sqlite3_result_null (context);
46035 	  return;
46036       }
46037     rads = angle * coeff;
46038     vsin = sin (rads);
46039     vcos = cos (rads);
46040     a = vcos;
46041     c = vsin;
46042     g = -vsin;
46043     i = vcos;
46044 
46045 /* creating the BLOB-encoded Affine Transform Matrix */
46046     gaia_matrix_create_multiply (iblob, iblob_sz, a, b, c, d, e, f, g, h, i,
46047 				 xoff, yoff, zoff, &blob, &blob_sz);
46048     if (blob == NULL)
46049 	sqlite3_result_null (context);
46050     else
46051 	sqlite3_result_blob (context, blob, blob_sz, free);
46052 }
46053 
46054 static void
fnct_AffineTransformMatrix_Determinant(sqlite3_context * context,int argc,sqlite3_value ** argv)46055 fnct_AffineTransformMatrix_Determinant (sqlite3_context * context, int argc,
46056 					sqlite3_value ** argv)
46057 {
46058 /* SQL function:
46059 / ATM_Determinant(blob atm)
46060 /
46061 / will return the Determinant from a BLOB-encoded Affine Transform Matrix
46062 / or 0.0 on failure
46063 */
46064     const unsigned char *iblob;
46065     int iblob_sz;
46066     double det = 0.0;
46067     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46068 
46069 /* validating the input args */
46070     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46071       {
46072 	  iblob = sqlite3_value_blob (argv[0]);
46073 	  iblob_sz = sqlite3_value_bytes (argv[0]);
46074       }
46075     else
46076       {
46077 	  sqlite3_result_double (context, det);
46078 	  return;
46079       }
46080 
46081 /* evaluating the Affine Transform Matrix */
46082     det = gaia_matrix_determinant (iblob, iblob_sz);
46083     sqlite3_result_double (context, det);
46084 }
46085 
46086 static void
fnct_AffineTransformMatrix_IsInvertible(sqlite3_context * context,int argc,sqlite3_value ** argv)46087 fnct_AffineTransformMatrix_IsInvertible (sqlite3_context * context, int argc,
46088 					 sqlite3_value ** argv)
46089 {
46090 /* SQL function:
46091 / ATM_IsInvertible(blob atm)
46092 /
46093 / will return TRUE if the a BLOB-encoded Affine Transform Matrix
46094 / is Invertible, FALSE if not
46095 / -1 on invalid arguments
46096 */
46097     const unsigned char *iblob;
46098     int iblob_sz;
46099     double det;
46100     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46101 
46102 /* validating the input args */
46103     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46104       {
46105 	  iblob = sqlite3_value_blob (argv[0]);
46106 	  iblob_sz = sqlite3_value_bytes (argv[0]);
46107       }
46108     else
46109       {
46110 	  sqlite3_result_int (context, -1);
46111 	  return;
46112       }
46113 
46114 /* evaluating the Affine Transform Matrix */
46115     det = gaia_matrix_determinant (iblob, iblob_sz);
46116     if (det != 0.0)
46117 	sqlite3_result_int (context, 1);
46118     else
46119 	sqlite3_result_int (context, 0);
46120 }
46121 
46122 static void
fnct_AffineTransformMatrix_Invert(sqlite3_context * context,int argc,sqlite3_value ** argv)46123 fnct_AffineTransformMatrix_Invert (sqlite3_context * context, int argc,
46124 				   sqlite3_value ** argv)
46125 {
46126 /* SQL function:
46127 / ATM_Invert(blob atm)
46128 /
46129 / will create an Inverse BLOB-encoded Affine Transform Matrix
46130 /
46131 / returns a BLOB-ATM object or NULL on failure
46132 */
46133     unsigned char *blob;
46134     int blob_sz;
46135     const unsigned char *iblob;
46136     int iblob_sz;
46137     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46138 
46139 /* validating the input args */
46140     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46141       {
46142 	  iblob = sqlite3_value_blob (argv[0]);
46143 	  iblob_sz = sqlite3_value_bytes (argv[0]);
46144       }
46145     else
46146       {
46147 	  sqlite3_result_null (context);
46148 	  return;
46149       }
46150 
46151 /* creating the BLOB-encoded Affine Transform Matrix (Inverse) */
46152     gaia_matrix_invert (iblob, iblob_sz, &blob, &blob_sz);
46153     if (blob == NULL)
46154 	sqlite3_result_null (context);
46155     else
46156 	sqlite3_result_blob (context, blob, blob_sz, free);
46157 }
46158 
46159 static void
fnct_AffineTransformMatrix_GeometryTransform(sqlite3_context * context,int argc,sqlite3_value ** argv)46160 fnct_AffineTransformMatrix_GeometryTransform (sqlite3_context * context,
46161 					      int argc, sqlite3_value ** argv)
46162 {
46163 /* SQL function:
46164 / ATM_Transform(blob geom, blob atm [ , int srid] )
46165 /
46166 / will create a BLOB-Geometry by applying to the input Geometry all
46167 / transformations specified by the Affine Transform Matrix
46168 /
46169 / returns a BLOB-ATM object or NULL on failure
46170 */
46171     unsigned char *blob;
46172     int blob_sz;
46173     const unsigned char *iblob1;
46174     int iblob1_sz;
46175     const unsigned char *iblob2;
46176     int iblob2_sz;
46177     gaiaGeomCollPtr g1;
46178     gaiaGeomCollPtr g2;
46179     int srid = -9999;
46180     int gpkg_amphibious = 0;
46181     int gpkg_mode = 0;
46182     int tiny_point = 0;
46183     struct splite_internal_cache *cache = sqlite3_user_data (context);
46184     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46185     if (cache != NULL)
46186       {
46187 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
46188 	  gpkg_mode = cache->gpkg_mode;
46189 	  tiny_point = cache->tinyPointEnabled;
46190       }
46191 
46192 /* validating the input args */
46193     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46194       {
46195 	  iblob1 = sqlite3_value_blob (argv[0]);
46196 	  iblob1_sz = sqlite3_value_bytes (argv[0]);
46197       }
46198     else
46199       {
46200 	  sqlite3_result_null (context);
46201 	  return;
46202       }
46203     if (sqlite3_value_type (argv[1]) == SQLITE_BLOB)
46204       {
46205 	  iblob2 = sqlite3_value_blob (argv[1]);
46206 	  iblob2_sz = sqlite3_value_bytes (argv[1]);
46207       }
46208     else
46209       {
46210 	  sqlite3_result_null (context);
46211 	  return;
46212       }
46213     if (argc == 3)
46214       {
46215 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
46216 	      srid = sqlite3_value_int (argv[2]);
46217 	  else
46218 	    {
46219 		sqlite3_result_null (context);
46220 		return;
46221 	    }
46222       }
46223 
46224 /* attempting to parse the BLOB-Geometry */
46225     g1 = gaiaFromSpatiaLiteBlobWkbEx (iblob1, iblob1_sz, gpkg_mode,
46226 				      gpkg_amphibious);
46227     if (g1 == NULL)
46228       {
46229 	  sqlite3_result_null (context);
46230 	  return;
46231       }
46232     g2 = gaia_matrix_transform_geometry (g1, iblob2, iblob2_sz);
46233     gaiaFreeGeomColl (g1);
46234     if (g2 == NULL)
46235       {
46236 	  sqlite3_result_null (context);
46237 	  return;
46238       }
46239     if (srid != -9999)
46240 	g2->Srid = srid;
46241     gaiaToSpatiaLiteBlobWkbEx2 (g2, &blob, &blob_sz, gpkg_mode, tiny_point);
46242     gaiaFreeGeomColl (g2);
46243     if (blob == NULL)
46244 	sqlite3_result_null (context);
46245     else
46246 	sqlite3_result_blob (context, blob, blob_sz, free);
46247 }
46248 
46249 static void
fnct_AffineTransformMatrix_IsValid(sqlite3_context * context,int argc,sqlite3_value ** argv)46250 fnct_AffineTransformMatrix_IsValid (sqlite3_context * context, int argc,
46251 				    sqlite3_value ** argv)
46252 {
46253 /* SQL function:
46254 / ATM_IsValid(BLOB matrix)
46255 /
46256 / returns TRUE if the current BLOB is a valid BLOB-ATM, FALSE if not
46257 / or -1 if any error is encountered
46258 */
46259     const unsigned char *blob;
46260     int blob_sz;
46261     int ret;
46262     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46263 /* validating the input args */
46264     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46265       {
46266 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
46267 	  blob_sz = sqlite3_value_bytes (argv[0]);
46268       }
46269     else
46270       {
46271 	  sqlite3_result_int (context, -1);
46272 	  return;
46273       }
46274 
46275 /* verifying the BLOB-Matrix */
46276     ret = gaia_matrix_is_valid (blob, blob_sz);
46277     if (ret)
46278 	sqlite3_result_int (context, 1);
46279     else
46280 	sqlite3_result_int (context, 0);
46281 }
46282 
46283 static void
fnct_AffineTransformMatrix_AsText(sqlite3_context * context,int argc,sqlite3_value ** argv)46284 fnct_AffineTransformMatrix_AsText (sqlite3_context * context, int argc,
46285 				   sqlite3_value ** argv)
46286 {
46287 /* SQL function:
46288 / ATM_AsText(BLOB matrix)
46289 /
46290 / returns a textual representaion of the BLOB-Matrix
46291 / or NULL if any error is encountered
46292 */
46293     const unsigned char *blob;
46294     int blob_sz;
46295     char *text;
46296     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46297 /* validating the input args */
46298     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46299       {
46300 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
46301 	  blob_sz = sqlite3_value_bytes (argv[0]);
46302       }
46303     else
46304       {
46305 	  sqlite3_result_null (context);
46306 	  return;
46307       }
46308 
46309 /* retrieving the textual representation from the BLOB-Matrix */
46310     text = gaia_matrix_as_text (blob, blob_sz);
46311     if (text == NULL)
46312 	sqlite3_result_null (context);
46313     else
46314 	sqlite3_result_text (context, text, strlen (text), sqlite3_free);
46315 }
46316 
46317 #ifdef ENABLE_GCP		/* only if ControlPoints enabled */
46318 
46319 static int
get_control_point(gaiaGeomCollPtr geom,double * x,double * y,double * z,int * has3d)46320 get_control_point (gaiaGeomCollPtr geom, double *x, double *y, double *z,
46321 		   int *has3d)
46322 {
46323 /* checking a Control Point */
46324     gaiaPointPtr pt;
46325     if (geom == NULL)
46326 	return 0;
46327     if (geom->FirstLinestring != NULL || geom->FirstPolygon != NULL)
46328 	return 0;
46329     pt = geom->FirstPoint;
46330     if (pt == NULL || pt != geom->LastPoint)
46331 	return 0;
46332     if (geom->DimensionModel == GAIA_XY_Z
46333 	|| geom->DimensionModel == GAIA_XY_Z_M)
46334       {
46335 	  *has3d = 1;
46336 	  *x = pt->X;
46337 	  *y = pt->Y;
46338 	  *z = pt->Z;
46339       }
46340     else
46341       {
46342 	  *has3d = 0;
46343 	  *x = pt->X;
46344 	  *y = pt->Y;
46345       }
46346     return 1;
46347 }
46348 
46349 static int
check_control_point_dims(GaiaControlPointsPtr cp_handle,int has3d_0,int has3d_1)46350 check_control_point_dims (GaiaControlPointsPtr cp_handle, int has3d_0,
46351 			  int has3d_1)
46352 {
46353 /* validating Control Point dimensions */
46354     struct gaia_control_points *cp = (struct gaia_control_points *) cp_handle;
46355     if (cp == NULL)
46356 	return 0;
46357     if (has3d_0 != cp->has3d)
46358 	return 0;
46359     if (has3d_1 != cp->has3d)
46360 	return 0;
46361     return 1;
46362 }
46363 
46364 static void
fnct_GroundControlPoints_Compute_step(sqlite3_context * context,int argc,sqlite3_value ** argv)46365 fnct_GroundControlPoints_Compute_step (sqlite3_context * context,
46366 				       int argc, sqlite3_value ** argv)
46367 {
46368 /* SQL function:
46369 / GCP_Compute(BLOB point1, BLOB point2 [ , int order ] )
46370 /
46371 / aggregate function - STEP
46372 /
46373 */
46374     unsigned char *p_blob0;
46375     int n_bytes0;
46376     unsigned char *p_blob1;
46377     int n_bytes1;
46378     gaiaGeomCollPtr geom0 = NULL;
46379     gaiaGeomCollPtr geom1 = NULL;
46380     double x0;
46381     double y0;
46382     double z0;
46383     double x1;
46384     double y1;
46385     double z1;
46386     int has3d_0;
46387     int has3d_1;
46388     int order = 1;
46389     int tps = 0;
46390     GaiaControlPointsPtr *cp;
46391     int gpkg_amphibious = 0;
46392     int gpkg_mode = 0;
46393     struct splite_internal_cache *cache = sqlite3_user_data (context);
46394     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46395     if (cache != NULL)
46396       {
46397 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
46398 	  gpkg_mode = cache->gpkg_mode;
46399       }
46400     if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
46401       {
46402 	  sqlite3_result_null (context);
46403 	  return;
46404       }
46405     if (sqlite3_value_type (argv[1]) != SQLITE_BLOB)
46406       {
46407 	  sqlite3_result_null (context);
46408 	  return;
46409       }
46410     if (argc == 3)
46411       {
46412 	  if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
46413 	    {
46414 		sqlite3_result_null (context);
46415 		return;
46416 	    }
46417 	  order = sqlite3_value_int (argv[2]);
46418 	  if (order >= 1 && order <= 3)
46419 	      ;			/* 1st, 2nd or 3rd polynomial order */
46420 	  else if (order == 0)
46421 	    {
46422 		/* Thin Plate Splite */
46423 		order = 1;
46424 		tps = 1;
46425 	    }
46426 	  else
46427 	    {
46428 		sqlite3_result_null (context);
46429 		return;
46430 	    }
46431       }
46432     p_blob0 = (unsigned char *) sqlite3_value_blob (argv[0]);
46433     n_bytes0 = sqlite3_value_bytes (argv[0]);
46434     p_blob1 = (unsigned char *) sqlite3_value_blob (argv[1]);
46435     n_bytes1 = sqlite3_value_bytes (argv[1]);
46436     geom0 =
46437 	gaiaFromSpatiaLiteBlobWkbEx (p_blob0, n_bytes0, gpkg_mode,
46438 				     gpkg_amphibious);
46439     geom1 =
46440 	gaiaFromSpatiaLiteBlobWkbEx (p_blob1, n_bytes1, gpkg_mode,
46441 				     gpkg_amphibious);
46442     if (!get_control_point (geom0, &x0, &y0, &z0, &has3d_0))
46443 	goto error;
46444     if (!get_control_point (geom1, &x1, &y1, &z1, &has3d_1))
46445 	goto error;
46446     if (has3d_0 != has3d_1)
46447 	goto error;
46448     cp = sqlite3_aggregate_context (context,
46449 				    sizeof (struct gaia_control_points));
46450     if (*cp == NULL)
46451       {
46452 	  /* this is the first row */
46453 	  *cp = gaiaCreateControlPoints (1024, has3d_0, order, tps);
46454 	  if (has3d_0)
46455 	      gaiaAddControlPoint3D (*cp, x0, y0, z0, x1, y1, z1);
46456 	  else
46457 	      gaiaAddControlPoint2D (*cp, x0, y0, x1, y1);
46458       }
46459     else
46460       {
46461 	  /* subsequent rows */
46462 	  if (!check_control_point_dims (*cp, has3d_0, has3d_1))
46463 	      goto error;
46464 	  if (has3d_0)
46465 	      gaiaAddControlPoint3D (*cp, x0, y0, z0, x1, y1, z1);
46466 	  else
46467 	      gaiaAddControlPoint2D (*cp, x0, y0, x1, y1);
46468       }
46469     gaiaFreeGeomColl (geom0);
46470     gaiaFreeGeomColl (geom1);
46471     return;
46472 
46473   error:
46474     if (geom0 != NULL)
46475 	gaiaFreeGeomColl (geom0);
46476     if (geom1 != NULL)
46477 	gaiaFreeGeomColl (geom1);
46478     sqlite3_result_null (context);
46479 }
46480 
46481 static void
fnct_GroundControlPoints_Compute_final(sqlite3_context * context)46482 fnct_GroundControlPoints_Compute_final (sqlite3_context * context)
46483 {
46484 /* SQL function:
46485 / GCP_Compute(BLOB point1, BLOB point2 [ , int order ] )
46486 /
46487 / aggregate function - FINAL
46488 /
46489 */
46490     unsigned char *blob = NULL;
46491     int blob_sz;
46492     int ret;
46493     GaiaControlPointsPtr *cp = sqlite3_aggregate_context (context, 0);
46494     if (cp == NULL)
46495       {
46496 	  sqlite3_result_null (context);
46497 	  return;
46498       }
46499     ret = gaiaCreatePolynomialCoeffs (*cp, &blob, &blob_sz);
46500     if (!ret)
46501 	sqlite3_result_null (context);
46502     else
46503 	sqlite3_result_blob (context, blob, blob_sz, free);
46504     gaiaFreeControlPoints (*cp);
46505 }
46506 
46507 static void
fnct_GroundControlPoints_GeometryTransform(sqlite3_context * context,int argc,sqlite3_value ** argv)46508 fnct_GroundControlPoints_GeometryTransform (sqlite3_context * context,
46509 					    int argc, sqlite3_value ** argv)
46510 {
46511 /* SQL function:
46512 / GCP_Transform(blob geom, blob gcp [ , int srid ] )
46513 /
46514 / will create a BLOB-Geometry by applying to the input Geometry all
46515 / transformations specified by the Polynomial coefficients
46516 /
46517 / returns a BLOB-ATM object or NULL on failure
46518 */
46519     unsigned char *blob;
46520     int blob_sz;
46521     const unsigned char *iblob1;
46522     int iblob1_sz;
46523     const unsigned char *iblob2;
46524     int iblob2_sz;
46525     gaiaGeomCollPtr g1;
46526     gaiaGeomCollPtr g2;
46527     int srid = -9999;
46528     int gpkg_amphibious = 0;
46529     int gpkg_mode = 0;
46530     int tiny_point = 0;
46531     struct splite_internal_cache *cache = sqlite3_user_data (context);
46532     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46533     if (cache != NULL)
46534       {
46535 	  gpkg_amphibious = cache->gpkg_amphibious_mode;
46536 	  gpkg_mode = cache->gpkg_mode;
46537 	  tiny_point = cache->tinyPointEnabled;
46538       }
46539 
46540 /* validating the input args */
46541     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46542       {
46543 	  iblob1 = sqlite3_value_blob (argv[0]);
46544 	  iblob1_sz = sqlite3_value_bytes (argv[0]);
46545       }
46546     else
46547       {
46548 	  sqlite3_result_null (context);
46549 	  return;
46550       }
46551     if (sqlite3_value_type (argv[1]) == SQLITE_BLOB)
46552       {
46553 	  iblob2 = sqlite3_value_blob (argv[1]);
46554 	  iblob2_sz = sqlite3_value_bytes (argv[1]);
46555       }
46556     else
46557       {
46558 	  sqlite3_result_null (context);
46559 	  return;
46560       }
46561     if (argc == 3)
46562       {
46563 	  if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
46564 	      srid = sqlite3_value_int (argv[2]);
46565 	  else
46566 	    {
46567 		sqlite3_result_null (context);
46568 		return;
46569 	    }
46570       }
46571 
46572 /* attempting to parse the BLOB-Geometry */
46573     g1 = gaiaFromSpatiaLiteBlobWkbEx (iblob1, iblob1_sz, gpkg_mode,
46574 				      gpkg_amphibious);
46575     if (g1 == NULL)
46576       {
46577 	  sqlite3_result_null (context);
46578 	  return;
46579       }
46580     g2 = gaiaPolynomialTransformGeometry (g1, iblob2, iblob2_sz);
46581     gaiaFreeGeomColl (g1);
46582     if (g2 == NULL)
46583       {
46584 	  sqlite3_result_null (context);
46585 	  return;
46586       }
46587     if (srid != -9999)
46588 	g2->Srid = srid;
46589     gaiaToSpatiaLiteBlobWkbEx2 (g2, &blob, &blob_sz, gpkg_mode, tiny_point);
46590     gaiaFreeGeomColl (g2);
46591     if (blob == NULL)
46592 	sqlite3_result_null (context);
46593     else
46594 	sqlite3_result_blob (context, blob, blob_sz, free);
46595 }
46596 
46597 static void
fnct_GroundControlPoints_IsValid(sqlite3_context * context,int argc,sqlite3_value ** argv)46598 fnct_GroundControlPoints_IsValid (sqlite3_context * context, int argc,
46599 				  sqlite3_value ** argv)
46600 {
46601 /* SQL function:
46602 / GCO_IsValid(BLOB polynomail)
46603 /
46604 / returns TRUE if the current BLOB is a valid BLOB-GCP, FALSE if not
46605 / or -1 if any error is encountered
46606 */
46607     const unsigned char *blob;
46608     int blob_sz;
46609     int ret;
46610     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46611 /* validating the input args */
46612     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46613       {
46614 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
46615 	  blob_sz = sqlite3_value_bytes (argv[0]);
46616       }
46617     else
46618       {
46619 	  sqlite3_result_int (context, -1);
46620 	  return;
46621       }
46622 
46623 /* verifying the BLOB-Polynomail */
46624     ret = gaiaPolynomialIsValid (blob, blob_sz);
46625     if (ret)
46626 	sqlite3_result_int (context, 1);
46627     else
46628 	sqlite3_result_int (context, 0);
46629 }
46630 
46631 static void
fnct_GroundControlPoints_AsText(sqlite3_context * context,int argc,sqlite3_value ** argv)46632 fnct_GroundControlPoints_AsText (sqlite3_context * context, int argc,
46633 				 sqlite3_value ** argv)
46634 {
46635 /* SQL function:
46636 / GCP_AsText(BLOB polynomail)
46637 /
46638 / returns a textual representaion of the BLOB-Polynomial
46639 / or NULL if any error is encountered
46640 */
46641     const unsigned char *blob;
46642     int blob_sz;
46643     char *text;
46644     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46645 /* validating the input args */
46646     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46647       {
46648 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
46649 	  blob_sz = sqlite3_value_bytes (argv[0]);
46650       }
46651     else
46652       {
46653 	  sqlite3_result_null (context);
46654 	  return;
46655       }
46656 
46657 /* retrieving the textual representation from the BLOB-Matrix */
46658     text = gaiaPolynomialAsText (blob, blob_sz);
46659     if (text == NULL)
46660 	sqlite3_result_null (context);
46661     else
46662 	sqlite3_result_text (context, text, strlen (text), sqlite3_free);
46663 }
46664 
46665 static void
fnct_GroundControlPoints_ToATM(sqlite3_context * context,int argc,sqlite3_value ** argv)46666 fnct_GroundControlPoints_ToATM (sqlite3_context * context, int argc,
46667 				sqlite3_value ** argv)
46668 {
46669 /* SQL function:
46670 / GCP2ATM(BLOB polynomail)
46671 /
46672 / returns a BLOB-Atm corresponding to a BLOB-Polynomial (first order only)
46673 / or NULL if any error is encountered
46674 */
46675     const unsigned char *blob;
46676     int blob_sz;
46677     unsigned char *oblob;
46678     int oblob_sz;
46679     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46680 /* validating the input args */
46681     if (sqlite3_value_type (argv[0]) == SQLITE_BLOB)
46682       {
46683 	  blob = (const unsigned char *) sqlite3_value_blob (argv[0]);
46684 	  blob_sz = sqlite3_value_bytes (argv[0]);
46685       }
46686     else
46687       {
46688 	  sqlite3_result_null (context);
46689 	  return;
46690       }
46691 
46692 /* converting Polynomial coefficients into an Affine Transformation matrix */
46693     if (!gaiaPolynomialToMatrix (blob, blob_sz, &oblob, &oblob_sz))
46694 	sqlite3_result_null (context);
46695     else
46696 	sqlite3_result_blob (context, oblob, oblob_sz, free);
46697 }
46698 
46699 #endif /* end including GCP */
46700 
46701 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
46702 
46703 static void
fnct_enableGpkgMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46704 fnct_enableGpkgMode (sqlite3_context * context, int argc, sqlite3_value ** argv)
46705 {
46706 /* SQL function:
46707 / EnableGpkgMode ( void )
46708 /
46709 / returns: nothing
46710 */
46711     sqlite3 *sqlite;
46712     int ret;
46713     struct splite_internal_cache *cache = sqlite3_user_data (context);
46714     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46715     if (cache == NULL)
46716 	return;
46717     sqlite = sqlite3_context_db_handle (context);
46718     ret = checkSpatialMetaData (sqlite);
46719     if (ret != 4)
46720 	return;			/* not GeoPackage */
46721     cache->gpkg_mode = 1;
46722     cache->gpkg_amphibious_mode = 0;
46723 }
46724 
46725 static void
fnct_disableGpkgMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46726 fnct_disableGpkgMode (sqlite3_context * context, int argc,
46727 		      sqlite3_value ** argv)
46728 {
46729 /* SQL function:
46730 / DisableGpkgMode ( void )
46731 /
46732 / returns: nothing
46733 */
46734     struct splite_internal_cache *cache = sqlite3_user_data (context);
46735     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46736     if (cache == NULL)
46737 	return;
46738     cache->gpkg_mode = 0;
46739 }
46740 
46741 static void
fnct_getGpkgMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46742 fnct_getGpkgMode (sqlite3_context * context, int argc, sqlite3_value ** argv)
46743 {
46744 /* SQL function:
46745 / GetGpkgMode ( void )
46746 /
46747 / returns: TRUE or FALSE
46748 */
46749     struct splite_internal_cache *cache = sqlite3_user_data (context);
46750     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46751     if (cache == NULL)
46752       {
46753 	  sqlite3_result_int (context, 0);
46754 	  return;
46755       }
46756     sqlite3_result_int (context, cache->gpkg_mode);
46757 }
46758 
46759 
46760 static void
fnct_enableGpkgAmphibiousMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46761 fnct_enableGpkgAmphibiousMode (sqlite3_context * context, int argc,
46762 			       sqlite3_value ** argv)
46763 {
46764 /* SQL function:
46765 / EnableGpkgAmphibiousMode ( void )
46766 /
46767 / returns: nothing
46768 */
46769     struct splite_internal_cache *cache = sqlite3_user_data (context);
46770     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46771     if (cache == NULL)
46772 	return;
46773     cache->gpkg_mode = 0;
46774     cache->gpkg_amphibious_mode = 1;
46775 }
46776 
46777 static void
fnct_disableGpkgAmphibiousMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46778 fnct_disableGpkgAmphibiousMode (sqlite3_context * context, int argc,
46779 				sqlite3_value ** argv)
46780 {
46781 /* SQL function:
46782 / DisableGpkgAmphibiousMode ( void )
46783 /
46784 / returns: nothing
46785 */
46786     struct splite_internal_cache *cache = sqlite3_user_data (context);
46787     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46788     if (cache == NULL)
46789 	return;
46790     cache->gpkg_amphibious_mode = 0;
46791 }
46792 
46793 static void
fnct_getGpkgAmphibiousMode(sqlite3_context * context,int argc,sqlite3_value ** argv)46794 fnct_getGpkgAmphibiousMode (sqlite3_context * context, int argc,
46795 			    sqlite3_value ** argv)
46796 {
46797 /* SQL function:
46798 / GetGpkgAmphibiousMode ( void )
46799 /
46800 / returns: TRUE or FALSE
46801 */
46802     struct splite_internal_cache *cache = sqlite3_user_data (context);
46803     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46804     if (cache == NULL)
46805       {
46806 	  sqlite3_result_int (context, 0);
46807 	  return;
46808       }
46809     sqlite3_result_int (context, cache->gpkg_amphibious_mode);
46810 }
46811 
46812 #endif /* end GPKG conditional */
46813 
46814 static void
fnct_EnablePause(sqlite3_context * context,int argc,sqlite3_value ** argv)46815 fnct_EnablePause (sqlite3_context * context, int argc, sqlite3_value ** argv)
46816 {
46817 /* SQL function:
46818 / EnablePause ( void )
46819 /
46820 / returns: nothing
46821 */
46822     struct splite_internal_cache *cache = sqlite3_user_data (context);
46823     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46824     if (cache == NULL)
46825 	return;
46826     cache->is_pause_enabled = 1;
46827 }
46828 
46829 static void
fnct_DisablePause(sqlite3_context * context,int argc,sqlite3_value ** argv)46830 fnct_DisablePause (sqlite3_context * context, int argc, sqlite3_value ** argv)
46831 {
46832 /* SQL function:
46833 / DisablePause ( void )
46834 /
46835 / returns: nothing
46836 */
46837     struct splite_internal_cache *cache = sqlite3_user_data (context);
46838     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46839     if (cache == NULL)
46840 	return;
46841     cache->is_pause_enabled = 0;
46842 }
46843 
46844 static void
fnct_IsPauseEnabled(sqlite3_context * context,int argc,sqlite3_value ** argv)46845 fnct_IsPauseEnabled (sqlite3_context * context, int argc, sqlite3_value ** argv)
46846 {
46847 /* SQL function:
46848 / IsPauseEnabled ( void )
46849 /
46850 / returns: TRUE or FALSE
46851 */
46852     struct splite_internal_cache *cache = sqlite3_user_data (context);
46853     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46854     if (cache == NULL)
46855       {
46856 	  sqlite3_result_int (context, 0);
46857 	  return;
46858       }
46859     if (cache->is_pause_enabled)
46860 	sqlite3_result_int (context, 1);
46861     else
46862 	sqlite3_result_int (context, 0);
46863 }
46864 
46865 static void
fnct_Pause(sqlite3_context * context,int argc,sqlite3_value ** argv)46866 fnct_Pause (sqlite3_context * context, int argc, sqlite3_value ** argv)
46867 {
46868 /* SQL function:
46869 / Pause ( void )
46870 /
46871 / returns: nothing
46872 */
46873     struct splite_internal_cache *cache = sqlite3_user_data (context);
46874     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46875     if (cache == NULL)
46876 	return;
46877     if (cache->is_pause_enabled == 0)
46878 	return;
46879 
46880 /* only if PAUSE is explicitly enabled */
46881 #ifdef _WIN32
46882     splite_pause_windows ();
46883 #else
46884     splite_pause_signal ();
46885 #endif
46886 }
46887 
46888 static void
fnct_setDecimalPrecision(sqlite3_context * context,int argc,sqlite3_value ** argv)46889 fnct_setDecimalPrecision (sqlite3_context * context, int argc,
46890 			  sqlite3_value ** argv)
46891 {
46892 /* SQL function:
46893 / SetDecimalPrecision ( int precision )
46894 / a negative precision identifies the default setting
46895 /
46896 / returns: nothing
46897 */
46898     int precision = -1;
46899     struct splite_internal_cache *cache = sqlite3_user_data (context);
46900     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46901     if (cache == NULL)
46902 	return;
46903     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
46904 	precision = sqlite3_value_int (argv[0]);
46905     else
46906 	return;
46907     if (precision < 0)
46908 	precision = -1;
46909     else if (precision == 6)
46910 	precision = -1;
46911     else if (precision > 18)
46912 	precision = 18;
46913     cache->decimal_precision = precision;
46914 }
46915 
46916 static void
fnct_getDecimalPrecision(sqlite3_context * context,int argc,sqlite3_value ** argv)46917 fnct_getDecimalPrecision (sqlite3_context * context, int argc,
46918 			  sqlite3_value ** argv)
46919 {
46920 /* SQL function:
46921 / GetDecimalPrecision ( void )
46922 /
46923 / returns: the currently set Decimal Precision
46924 */
46925     struct splite_internal_cache *cache = sqlite3_user_data (context);
46926     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46927     if (cache == NULL)
46928       {
46929 	  sqlite3_result_int (context, -1);
46930 	  return;
46931       }
46932     sqlite3_result_int (context, cache->decimal_precision);
46933 }
46934 
46935 static void
fnct_enableTinyPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)46936 fnct_enableTinyPoint (sqlite3_context * context, int argc,
46937 		      sqlite3_value ** argv)
46938 {
46939 /* SQL function:
46940 / EnableTinyPoint ( void )
46941 /
46942 / returns: nothing
46943 */
46944     const void *cache = sqlite3_user_data (context);
46945     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46946     enable_tiny_point (cache);
46947 }
46948 
46949 static void
fnct_disableTinyPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)46950 fnct_disableTinyPoint (sqlite3_context * context, int argc,
46951 		       sqlite3_value ** argv)
46952 {
46953 /* SQL function:
46954 / DisableTinyPoint ( void )
46955 /
46956 / returns: nothing
46957 */
46958     const void *cache = sqlite3_user_data (context);
46959     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46960     disable_tiny_point (cache);
46961 }
46962 
46963 static void
fnct_isTinyPointEnabled(sqlite3_context * context,int argc,sqlite3_value ** argv)46964 fnct_isTinyPointEnabled (sqlite3_context * context, int argc,
46965 			 sqlite3_value ** argv)
46966 {
46967 /* SQL function:
46968 / IsTinyPointEnabled ( void )
46969 /
46970 / returns: TRUE or FALSE
46971 */
46972     int enabled;
46973     const void *cache = sqlite3_user_data (context);
46974     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46975     enabled = is_tiny_point_enabled (cache);
46976     sqlite3_result_int (context, enabled);
46977 }
46978 
46979 static void
fnct_postgres_reset_error(sqlite3_context * context,int argc,sqlite3_value ** argv)46980 fnct_postgres_reset_error (sqlite3_context * context, int argc,
46981 			   sqlite3_value ** argv)
46982 {
46983 /* SQL function:
46984 / PostgreSql_ResetLastError ( void )
46985 /
46986 / returns: 1 on success, 0 on failure
46987 */
46988     struct splite_internal_cache *cache = sqlite3_user_data (context);
46989     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
46990     if (cache == NULL)
46991       {
46992 	  sqlite3_result_int (context, 0);
46993 	  return;
46994       }
46995     if (cache->lastPostgreSqlError != NULL)
46996 	sqlite3_free (cache->lastPostgreSqlError);
46997     cache->lastPostgreSqlError = NULL;
46998     sqlite3_result_int (context, 1);
46999 }
47000 
47001 static void
fnct_postgres_set_error(sqlite3_context * context,int argc,sqlite3_value ** argv)47002 fnct_postgres_set_error (sqlite3_context * context, int argc,
47003 			 sqlite3_value ** argv)
47004 {
47005 /* SQL function:
47006 / PostgreSql_SetLastError ( err-msg TEXT )
47007 /
47008 / returns: 1 on success, 0 on failure; -1 on invalid argument
47009 */
47010     char *msg;
47011     const char *err_msg;
47012     struct splite_internal_cache *cache = sqlite3_user_data (context);
47013     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47014     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47015 	err_msg = (const char *) sqlite3_value_blob (argv[0]);
47016     else
47017       {
47018 	  sqlite3_result_int (context, -1);
47019 	  return;
47020       }
47021     if (cache == NULL)
47022       {
47023 	  sqlite3_result_int (context, 0);
47024 	  return;
47025       }
47026     msg = sqlite3_mprintf ("%s", err_msg);
47027     if (cache->lastPostgreSqlError != NULL)
47028 	sqlite3_free (cache->lastPostgreSqlError);
47029     cache->lastPostgreSqlError = msg;
47030     sqlite3_result_int (context, 1);
47031 }
47032 
47033 static void
fnct_postgres_get_error(sqlite3_context * context,int argc,sqlite3_value ** argv)47034 fnct_postgres_get_error (sqlite3_context * context, int argc,
47035 			 sqlite3_value ** argv)
47036 {
47037 /* SQL function:
47038 / PostgreSql_GetLastError ( void )
47039 /
47040 / returns: the last message registered by PostgreSql_SetLastError
47041 / or NULL if no such message exists
47042 */
47043     struct splite_internal_cache *cache = sqlite3_user_data (context);
47044     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47045     if (cache == NULL)
47046       {
47047 	  sqlite3_result_null (context);
47048 	  return;
47049       }
47050     if (cache->lastPostgreSqlError == NULL)
47051 	sqlite3_result_null (context);
47052     else
47053 	sqlite3_result_text (context, cache->lastPostgreSqlError,
47054 			     strlen (cache->lastPostgreSqlError),
47055 			     SQLITE_STATIC);
47056 }
47057 
47058 static void
fnct_bufferoptions_reset(sqlite3_context * context,int argc,sqlite3_value ** argv)47059 fnct_bufferoptions_reset (sqlite3_context * context, int argc,
47060 			  sqlite3_value ** argv)
47061 {
47062 /* SQL function:
47063 / BufferOptions_Reset ( void )
47064 /
47065 / returns: 1 on success, 0 on failure
47066 */
47067 #ifndef OMIT_GEOS		/* including GEOS */
47068     struct splite_internal_cache *cache = sqlite3_user_data (context);
47069     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47070     if (cache == NULL)
47071       {
47072 	  sqlite3_result_int (context, 0);
47073 	  return;
47074       }
47075     cache->buffer_end_cap_style = GEOSBUF_CAP_ROUND;
47076     cache->buffer_join_style = GEOSBUF_JOIN_ROUND;
47077     cache->buffer_mitre_limit = 5.0;
47078     cache->buffer_quadrant_segments = 30;
47079     sqlite3_result_int (context, 1);
47080 #else /* GEOS is disabled */
47081 	sqlite3_result_int (context, 0);
47082 #endif /* end including GEOS */
47083 }
47084 
47085 static void
fnct_bufferoptions_set_endcap(sqlite3_context * context,int argc,sqlite3_value ** argv)47086 fnct_bufferoptions_set_endcap (sqlite3_context * context, int argc,
47087 			       sqlite3_value ** argv)
47088 {
47089 /* SQL function:
47090 / BufferOptions_SetEndCapStyle ( text style )
47091 /
47092 / returns: 1 on success, 0 on failure
47093 */
47094 #ifndef OMIT_GEOS		/* including GEOS */
47095     const char *value;
47096     int val = -1;
47097     struct splite_internal_cache *cache = sqlite3_user_data (context);
47098     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47099     if (cache == NULL)
47100       {
47101 	  sqlite3_result_int (context, 0);
47102 	  return;
47103       }
47104     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47105 	value = (const char *) sqlite3_value_text (argv[0]);
47106     else
47107       {
47108 	  sqlite3_result_int (context, 0);
47109 	  return;
47110       }
47111     if (strcasecmp (value, "ROUND") == 0)
47112 	val = GEOSBUF_CAP_ROUND;
47113     if (strcasecmp (value, "FLAT") == 0)
47114 	val = GEOSBUF_CAP_FLAT;
47115     if (strcasecmp (value, "SQUARE") == 0)
47116 	val = GEOSBUF_CAP_SQUARE;
47117     if (val >= 1)
47118       {
47119 	  cache->buffer_end_cap_style = val;
47120 	  sqlite3_result_int (context, 1);
47121       }
47122     else
47123 	sqlite3_result_int (context, 0);
47124 #else /* GEOS is disabled */
47125 	sqlite3_result_int (context, 0);
47126 #endif /* end including GEOS */
47127 }
47128 
47129 static void
fnct_bufferoptions_set_join(sqlite3_context * context,int argc,sqlite3_value ** argv)47130 fnct_bufferoptions_set_join (sqlite3_context * context, int argc,
47131 			     sqlite3_value ** argv)
47132 {
47133 /* SQL function:
47134 / BufferOptions_SetJoinStyle ( text style )
47135 /
47136 / returns: 1 on success, 0 on failure
47137 */
47138 #ifndef OMIT_GEOS		/* including GEOS */
47139     const char *value;
47140     int val = -1;
47141     struct splite_internal_cache *cache = sqlite3_user_data (context);
47142     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47143     if (cache == NULL)
47144       {
47145 	  sqlite3_result_int (context, 0);
47146 	  return;
47147       }
47148     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47149 	value = (const char *) sqlite3_value_text (argv[0]);
47150     else
47151       {
47152 	  sqlite3_result_int (context, 0);
47153 	  return;
47154       }
47155     if (strcasecmp (value, "ROUND") == 0)
47156 	val = GEOSBUF_JOIN_ROUND;
47157     if (strcasecmp (value, "MITRE") == 0)
47158 	val = GEOSBUF_JOIN_MITRE;
47159     if (strcasecmp (value, "MITER") == 0)
47160 	val = GEOSBUF_JOIN_MITRE;
47161     if (strcasecmp (value, "BEVEL") == 0)
47162 	val = GEOSBUF_JOIN_BEVEL;
47163     if (val >= 1)
47164       {
47165 	  cache->buffer_join_style = val;
47166 	  sqlite3_result_int (context, 1);
47167       }
47168     else
47169 	sqlite3_result_int (context, 0);
47170 #else /* GEOS is disabled */
47171 	sqlite3_result_int (context, 0);
47172 #endif /* end including GEOS */
47173 }
47174 
47175 static void
fnct_bufferoptions_set_mitrelimit(sqlite3_context * context,int argc,sqlite3_value ** argv)47176 fnct_bufferoptions_set_mitrelimit (sqlite3_context * context, int argc,
47177 				   sqlite3_value ** argv)
47178 {
47179 /* SQL function:
47180 / BufferOptions_SetMitreLimit ( double limit )
47181 /
47182 / returns: 1 on success, 0 on failure
47183 */
47184 #ifndef OMIT_GEOS		/* including GEOS */
47185     double value;
47186     struct splite_internal_cache *cache = sqlite3_user_data (context);
47187     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47188     if (cache == NULL)
47189       {
47190 	  sqlite3_result_int (context, 0);
47191 	  return;
47192       }
47193     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
47194 	value = sqlite3_value_double (argv[0]);
47195     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
47196       {
47197 	  int val = sqlite3_value_int (argv[0]);
47198 	  value = val;
47199       }
47200     else
47201       {
47202 	  sqlite3_result_int (context, 0);
47203 	  return;
47204       }
47205     cache->buffer_mitre_limit = value;
47206     sqlite3_result_int (context, 1);
47207 #else /* GEOS is disabled */
47208 	sqlite3_result_int (context, 0);
47209 #endif /* end including GEOS */
47210 }
47211 
47212 static void
fnct_bufferoptions_set_quadsegs(sqlite3_context * context,int argc,sqlite3_value ** argv)47213 fnct_bufferoptions_set_quadsegs (sqlite3_context * context, int argc,
47214 				 sqlite3_value ** argv)
47215 {
47216 /* SQL function:
47217 / BufferOptions_SetQuadrantSegments ( int points )
47218 /
47219 / returns: 1 on success, 0 on failure
47220 */
47221 #ifndef OMIT_GEOS		/* including GEOS */
47222     int value;
47223     struct splite_internal_cache *cache = sqlite3_user_data (context);
47224     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47225     if (cache == NULL)
47226       {
47227 	  sqlite3_result_int (context, 0);
47228 	  return;
47229       }
47230     if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
47231 	value = sqlite3_value_int (argv[0]);
47232     else
47233       {
47234 	  sqlite3_result_int (context, 0);
47235 	  return;
47236       }
47237     if (value <= 0)
47238 	value = 1;
47239     cache->buffer_quadrant_segments = value;
47240     sqlite3_result_int (context, 1);
47241 #else /* GEOS is disabled */
47242 	sqlite3_result_int (context, 0);
47243 #endif /* end including GEOS */
47244 }
47245 
47246 static void
fnct_bufferoptions_get_endcap(sqlite3_context * context,int argc,sqlite3_value ** argv)47247 fnct_bufferoptions_get_endcap (sqlite3_context * context, int argc,
47248 			       sqlite3_value ** argv)
47249 {
47250 /* SQL function:
47251 / BufferOptions_GetEndCapStyle ( void )
47252 /
47253 / returns: a Text string on success, NULL on failure
47254 */
47255 #ifndef OMIT_GEOS		/* including GEOS */
47256     struct splite_internal_cache *cache = sqlite3_user_data (context);
47257     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47258     if (cache == NULL)
47259       {
47260 	  sqlite3_result_null (context);
47261 	  return;
47262       }
47263     switch (cache->buffer_end_cap_style)
47264       {
47265       case GEOSBUF_CAP_ROUND:
47266 	  sqlite3_result_text (context, "ROUND", strlen ("ROUND"),
47267 			       SQLITE_TRANSIENT);
47268 	  break;
47269       case GEOSBUF_CAP_FLAT:
47270 	  sqlite3_result_text (context, "FLAT", strlen ("FLAT"),
47271 			       SQLITE_TRANSIENT);
47272 	  break;
47273       case GEOSBUF_CAP_SQUARE:
47274 	  sqlite3_result_text (context, "SQUARE", strlen ("SQUARE"),
47275 			       SQLITE_TRANSIENT);
47276 	  break;
47277       default:
47278 	  sqlite3_result_null (context);
47279       };
47280 #else /* GEOS is disabled */
47281 	  sqlite3_result_null (context);
47282 #endif /* end including GEOS */
47283 }
47284 
47285 static void
fnct_bufferoptions_get_join(sqlite3_context * context,int argc,sqlite3_value ** argv)47286 fnct_bufferoptions_get_join (sqlite3_context * context, int argc,
47287 			     sqlite3_value ** argv)
47288 {
47289 /* SQL function:
47290 / BufferOptions_GetJoinStyle ( void )
47291 /
47292 / returns: a Text string on success, NULL on failure
47293 */
47294 #ifndef OMIT_GEOS		/* including GEOS */
47295     struct splite_internal_cache *cache = sqlite3_user_data (context);
47296     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47297     if (cache == NULL)
47298       {
47299 	  sqlite3_result_null (context);
47300 	  return;
47301       }
47302     switch (cache->buffer_join_style)
47303       {
47304       case GEOSBUF_JOIN_ROUND:
47305 	  sqlite3_result_text (context, "ROUND", strlen ("ROUND"),
47306 			       SQLITE_TRANSIENT);
47307 	  break;
47308       case GEOSBUF_JOIN_MITRE:
47309 	  sqlite3_result_text (context, "MITRE", strlen ("MITRE"),
47310 			       SQLITE_TRANSIENT);
47311 	  break;
47312       case GEOSBUF_JOIN_BEVEL:
47313 	  sqlite3_result_text (context, "BEVEL", strlen ("BEVEL"),
47314 			       SQLITE_TRANSIENT);
47315 	  break;
47316       default:
47317 	  sqlite3_result_null (context);
47318       };
47319 #else /* GEOS is disabled */
47320 	  sqlite3_result_null (context);
47321 #endif /* end including GEOS */
47322 }
47323 
47324 static void
fnct_bufferoptions_get_mitrelimit(sqlite3_context * context,int argc,sqlite3_value ** argv)47325 fnct_bufferoptions_get_mitrelimit (sqlite3_context * context, int argc,
47326 				   sqlite3_value ** argv)
47327 {
47328 /* SQL function:
47329 / BufferOptions_GetMitreLimit ( void )
47330 /
47331 / returns: a Double on success, NULL on failure
47332 */
47333 #ifndef OMIT_GEOS		/* including GEOS */
47334     struct splite_internal_cache *cache = sqlite3_user_data (context);
47335     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47336     if (cache == NULL)
47337       {
47338 	  sqlite3_result_null (context);
47339 	  return;
47340       }
47341     sqlite3_result_double (context, cache->buffer_mitre_limit);
47342 #else /* GEOS is disabled */
47343 	  sqlite3_result_null (context);
47344 #endif /* end including GEOS */
47345 }
47346 
47347 static void
fnct_bufferoptions_get_quadsegs(sqlite3_context * context,int argc,sqlite3_value ** argv)47348 fnct_bufferoptions_get_quadsegs (sqlite3_context * context, int argc,
47349 				 sqlite3_value ** argv)
47350 {
47351 /* SQL function:
47352 / BufferOptions_GetQuadrantSegments ( void )
47353 /
47354 / returns: an Integer on success, NULL on failure
47355 */
47356 #ifndef OMIT_GEOS		/* including GEOS */
47357     struct splite_internal_cache *cache = sqlite3_user_data (context);
47358     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47359     if (cache == NULL)
47360       {
47361 	  sqlite3_result_null (context);
47362 	  return;
47363       }
47364     sqlite3_result_int (context, cache->buffer_quadrant_segments);
47365 #else /* GEOS is disabled */
47366 	  sqlite3_result_null (context);
47367 #endif /* end including GEOS */
47368 }
47369 
47370 static void
fnct_addVirtualTableExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)47371 fnct_addVirtualTableExtent (sqlite3_context * context, int argc,
47372 			    sqlite3_value ** argv)
47373 {
47374 /* SQL function:
47375 / AddVirtualTableExtent ( table Text, minx Double miny Double, maxx Double,
47376 /                      maxy Double, srid Integer )
47377 /
47378 / returns: 1 on success, 0 on failure
47379 */
47380     const char *table;
47381     double minx;
47382     double miny;
47383     double maxx;
47384     double maxy;
47385     int srid;
47386     struct splite_internal_cache *cache = sqlite3_user_data (context);
47387     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47388     if (cache == NULL)
47389       {
47390 	  sqlite3_result_int (context, 0);
47391 	  return;
47392       }
47393     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47394 	table = (const char *) sqlite3_value_text (argv[0]);
47395     else
47396       {
47397 	  sqlite3_result_int (context, 0);
47398 	  return;
47399       }
47400     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
47401 	minx = sqlite3_value_double (argv[1]);
47402     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
47403       {
47404 	  int val = sqlite3_value_int (argv[1]);
47405 	  minx = val;
47406       }
47407     else
47408       {
47409 	  sqlite3_result_int (context, 0);
47410 	  return;
47411       }
47412     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
47413 	miny = sqlite3_value_double (argv[2]);
47414     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
47415       {
47416 	  int val = sqlite3_value_int (argv[2]);
47417 	  miny = val;
47418       }
47419     else
47420       {
47421 	  sqlite3_result_int (context, 0);
47422 	  return;
47423       }
47424     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
47425 	maxx = sqlite3_value_double (argv[3]);
47426     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
47427       {
47428 	  int val = sqlite3_value_int (argv[3]);
47429 	  maxx = val;
47430       }
47431     else
47432       {
47433 	  sqlite3_result_int (context, 0);
47434 	  return;
47435       }
47436     if (sqlite3_value_type (argv[4]) == SQLITE_FLOAT)
47437 	maxy = sqlite3_value_double (argv[4]);
47438     else if (sqlite3_value_type (argv[4]) == SQLITE_INTEGER)
47439       {
47440 	  int val = sqlite3_value_int (argv[4]);
47441 	  maxy = val;
47442       }
47443     else
47444       {
47445 	  sqlite3_result_int (context, 0);
47446 	  return;
47447       }
47448     if (sqlite3_value_type (argv[5]) == SQLITE_INTEGER)
47449 	srid = sqlite3_value_int (argv[5]);
47450     else
47451       {
47452 	  sqlite3_result_int (context, 0);
47453 	  return;
47454       }
47455     add_vtable_extent (table, minx, miny, maxx, maxy, srid, cache);
47456     sqlite3_result_int (context, 1);
47457 }
47458 
47459 static void
fnct_removeVirtualTableExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)47460 fnct_removeVirtualTableExtent (sqlite3_context * context, int argc,
47461 			       sqlite3_value ** argv)
47462 {
47463 /* SQL function:
47464 / RemoveVirtualTableExtent ( table Text )
47465 /
47466 / returns: 1 on success, 0 on failure
47467 */
47468     const char *table;
47469     struct splite_internal_cache *cache = sqlite3_user_data (context);
47470     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47471     if (cache == NULL)
47472       {
47473 	  sqlite3_result_int (context, 0);
47474 	  return;
47475       }
47476     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47477 	table = (const char *) sqlite3_value_text (argv[0]);
47478     else
47479       {
47480 	  sqlite3_result_int (context, 0);
47481 	  return;
47482       }
47483     remove_vtable_extent (table, cache);
47484     sqlite3_result_int (context, 1);
47485 }
47486 
47487 static void
fnct_getVirtualTableExtent(sqlite3_context * context,int argc,sqlite3_value ** argv)47488 fnct_getVirtualTableExtent (sqlite3_context * context, int argc,
47489 			    sqlite3_value ** argv)
47490 {
47491 /* SQL function:
47492 / GetVirtualTableExtent ( table Text )
47493 /
47494 / note: both GetVirtualShapeExtent() and GetVirtualGeoJsonExtent()
47495 / are accepted as valid alias names
47496 /
47497 / returns: the Virtual Table Full Extent (Envelope)
47498 /          or NULL on error
47499 */
47500     const char *table;
47501     double minx;
47502     double miny;
47503     double maxx;
47504     double maxy;
47505     int srid;
47506     gaiaGeomCollPtr bbox;
47507     gaiaPolygonPtr polyg;
47508     gaiaRingPtr rect;
47509     char *sql;
47510     char *xtable;
47511     int len;
47512     unsigned char *p_result = NULL;
47513     sqlite3 *sqlite = sqlite3_context_db_handle (context);
47514     struct splite_internal_cache *cache = sqlite3_user_data (context);
47515     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47516     if (cache == NULL)
47517       {
47518 	  sqlite3_result_null (context);
47519 	  return;
47520       }
47521     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47522 	table = (const char *) sqlite3_value_text (argv[0]);
47523     else
47524       {
47525 	  sqlite3_result_null (context);
47526 	  return;
47527       }
47528 
47529 /* ensuring to initialize the VirtualShape Table */
47530     xtable = gaiaDoubleQuotedSql (table);
47531     sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", xtable);
47532     free (xtable);
47533     sqlite3_exec (sqlite, sql, NULL, NULL, NULL);
47534     sqlite3_free (sql);
47535 
47536     if (!get_vtable_extent (table, &minx, &miny, &maxx, &maxy, &srid, cache))
47537       {
47538 	  sqlite3_result_null (context);
47539 	  return;
47540       }
47541 
47542 /* building the Envelope */
47543     bbox = gaiaAllocGeomColl ();
47544     bbox->Srid = srid;
47545     polyg = gaiaAddPolygonToGeomColl (bbox, 5, 0);
47546     rect = polyg->Exterior;
47547     gaiaSetPoint (rect->Coords, 0, minx, miny);	/* vertex # 1 */
47548     gaiaSetPoint (rect->Coords, 1, maxx, miny);	/* vertex # 2 */
47549     gaiaSetPoint (rect->Coords, 2, maxx, maxy);	/* vertex # 3 */
47550     gaiaSetPoint (rect->Coords, 3, minx, maxy);	/* vertex # 4 */
47551     gaiaSetPoint (rect->Coords, 4, minx, miny);	/* vertex # 5 [same as vertex # 1 to close the polygon] */
47552 /* builds the BLOB geometry to be returned */
47553     gaiaToSpatiaLiteBlobWkb (bbox, &p_result, &len);
47554     sqlite3_result_blob (context, p_result, len, free);
47555     gaiaFreeGeomColl (bbox);
47556 }
47557 
47558 static void
fnct_isLowASCII(sqlite3_context * context,int argc,sqlite3_value ** argv)47559 fnct_isLowASCII (sqlite3_context * context, int argc, sqlite3_value ** argv)
47560 {
47561 /* SQL function:
47562 / IsLowASCII ( string Text )
47563 /
47564 / returns: 1 (TRUE) is the argument is a text string containing
47565 /          all low-ASCII chars (7-bit, < 128)
47566 /          0 if not
47567 /          -1 on invalid arg
47568 */
47569     int len;
47570     int i;
47571     const unsigned char *string;
47572     int result = 1;
47573     GAIA_UNUSED ();		/* LCOV_EXCL_LINE */
47574     if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
47575 	string = (const unsigned char *) sqlite3_value_text (argv[0]);
47576     else
47577       {
47578 	  sqlite3_result_int (context, -1);
47579 	  return;
47580       }
47581 
47582     len = strlen ((const char *) string);
47583     for (i = 0; i < len; i++)
47584       {
47585 	  if (string[i] >= 128)
47586 	      result = 0;
47587       }
47588     sqlite3_result_int (context, result);
47589 }
47590 
47591 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
47592 
47593 static void
fnct_CreateTopoTables(sqlite3_context * context,int argc,sqlite3_value ** argv)47594 fnct_CreateTopoTables (sqlite3_context * context, int argc,
47595 		       sqlite3_value ** argv)
47596 {
47597     fnctaux_CreateTopoTables (context, argc, argv);
47598 }
47599 
47600 static void
fnct_ReCreateTopoTriggers(sqlite3_context * context,int argc,sqlite3_value ** argv)47601 fnct_ReCreateTopoTriggers (sqlite3_context * context, int argc,
47602 			   sqlite3_value ** argv)
47603 {
47604     fnctaux_ReCreateTopoTriggers (context, argc, argv);
47605 }
47606 
47607 static void
fnct_CreateTopology(sqlite3_context * context,int argc,sqlite3_value ** argv)47608 fnct_CreateTopology (sqlite3_context * context, int argc, sqlite3_value ** argv)
47609 {
47610     fnctaux_CreateTopology (context, argc, argv);
47611 }
47612 
47613 static void
fnct_DropTopology(sqlite3_context * context,int argc,sqlite3_value ** argv)47614 fnct_DropTopology (sqlite3_context * context, int argc, sqlite3_value ** argv)
47615 {
47616     fnctaux_DropTopology (context, argc, argv);
47617 }
47618 
47619 static void
fnct_GetLastTopologyException(sqlite3_context * context,int argc,sqlite3_value ** argv)47620 fnct_GetLastTopologyException (sqlite3_context * context, int argc,
47621 			       sqlite3_value ** argv)
47622 {
47623     fnctaux_GetLastTopologyException (context, argc, argv);
47624 }
47625 
47626 static void
fnct_AddIsoNode(sqlite3_context * context,int argc,sqlite3_value ** argv)47627 fnct_AddIsoNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
47628 {
47629     fnctaux_AddIsoNode (context, argc, argv);
47630 }
47631 
47632 static void
fnct_MoveIsoNode(sqlite3_context * context,int argc,sqlite3_value ** argv)47633 fnct_MoveIsoNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
47634 {
47635     fnctaux_MoveIsoNode (context, argc, argv);
47636 }
47637 
47638 static void
fnct_RemIsoNode(sqlite3_context * context,int argc,sqlite3_value ** argv)47639 fnct_RemIsoNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
47640 {
47641     fnctaux_RemIsoNode (context, argc, argv);
47642 }
47643 
47644 static void
fnct_AddIsoEdge(sqlite3_context * context,int argc,sqlite3_value ** argv)47645 fnct_AddIsoEdge (sqlite3_context * context, int argc, sqlite3_value ** argv)
47646 {
47647     fnctaux_AddIsoEdge (context, argc, argv);
47648 }
47649 
47650 static void
fnct_RemIsoEdge(sqlite3_context * context,int argc,sqlite3_value ** argv)47651 fnct_RemIsoEdge (sqlite3_context * context, int argc, sqlite3_value ** argv)
47652 {
47653     fnctaux_RemIsoEdge (context, argc, argv);
47654 }
47655 
47656 static void
fnct_ModEdgeSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)47657 fnct_ModEdgeSplit (sqlite3_context * context, int argc, sqlite3_value ** argv)
47658 {
47659     fnctaux_ModEdgeSplit (context, argc, argv);
47660 }
47661 
47662 static void
fnct_NewEdgesSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)47663 fnct_NewEdgesSplit (sqlite3_context * context, int argc, sqlite3_value ** argv)
47664 {
47665     fnctaux_NewEdgesSplit (context, argc, argv);
47666 }
47667 
47668 static void
fnct_AddEdgeModFace(sqlite3_context * context,int argc,sqlite3_value ** argv)47669 fnct_AddEdgeModFace (sqlite3_context * context, int argc, sqlite3_value ** argv)
47670 {
47671     fnctaux_AddEdgeModFace (context, argc, argv);
47672 }
47673 
47674 static void
fnct_AddEdgeNewFaces(sqlite3_context * context,int argc,sqlite3_value ** argv)47675 fnct_AddEdgeNewFaces (sqlite3_context * context, int argc,
47676 		      sqlite3_value ** argv)
47677 {
47678     fnctaux_AddEdgeNewFaces (context, argc, argv);
47679 }
47680 
47681 static void
fnct_ChangeEdgeGeom(sqlite3_context * context,int argc,sqlite3_value ** argv)47682 fnct_ChangeEdgeGeom (sqlite3_context * context, int argc, sqlite3_value ** argv)
47683 {
47684     fnctaux_ChangeEdgeGeom (context, argc, argv);
47685 }
47686 
47687 static void
fnct_RemEdgeModFace(sqlite3_context * context,int argc,sqlite3_value ** argv)47688 fnct_RemEdgeModFace (sqlite3_context * context, int argc, sqlite3_value ** argv)
47689 {
47690     fnctaux_RemEdgeModFace (context, argc, argv);
47691 }
47692 
47693 static void
fnct_RemEdgeNewFace(sqlite3_context * context,int argc,sqlite3_value ** argv)47694 fnct_RemEdgeNewFace (sqlite3_context * context, int argc, sqlite3_value ** argv)
47695 {
47696     fnctaux_RemEdgeNewFace (context, argc, argv);
47697 }
47698 
47699 static void
fnct_ModEdgeHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)47700 fnct_ModEdgeHeal (sqlite3_context * context, int argc, sqlite3_value ** argv)
47701 {
47702     fnctaux_ModEdgeHeal (context, argc, argv);
47703 }
47704 
47705 static void
fnct_NewEdgeHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)47706 fnct_NewEdgeHeal (sqlite3_context * context, int argc, sqlite3_value ** argv)
47707 {
47708     fnctaux_NewEdgeHeal (context, argc, argv);
47709 }
47710 
47711 static void
fnct_GetFaceGeometry(sqlite3_context * context,int argc,sqlite3_value ** argv)47712 fnct_GetFaceGeometry (sqlite3_context * context, int argc,
47713 		      sqlite3_value ** argv)
47714 {
47715     fnctaux_GetFaceGeometry (context, argc, argv);
47716 }
47717 
47718 static void
fnct_GetFaceEdges(sqlite3_context * context,int argc,sqlite3_value ** argv)47719 fnct_GetFaceEdges (sqlite3_context * context, int argc, sqlite3_value ** argv)
47720 {
47721     fnctaux_GetFaceEdges (context, argc, argv);
47722 }
47723 
47724 static void
fnct_ValidateTopoGeo(sqlite3_context * context,int argc,sqlite3_value ** argv)47725 fnct_ValidateTopoGeo (sqlite3_context * context, int argc,
47726 		      sqlite3_value ** argv)
47727 {
47728     fnctaux_ValidateTopoGeo (context, argc, argv);
47729 }
47730 
47731 static void
fnct_CreateTopoGeo(sqlite3_context * context,int argc,sqlite3_value ** argv)47732 fnct_CreateTopoGeo (sqlite3_context * context, int argc, sqlite3_value ** argv)
47733 {
47734     fnctaux_CreateTopoGeo (context, argc, argv);
47735 }
47736 
47737 static void
fnct_GetNodeByPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)47738 fnct_GetNodeByPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
47739 {
47740     fnctaux_GetNodeByPoint (context, argc, argv);
47741 }
47742 
47743 static void
fnct_GetEdgeByPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)47744 fnct_GetEdgeByPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
47745 {
47746     fnctaux_GetEdgeByPoint (context, argc, argv);
47747 }
47748 
47749 static void
fnct_GetFaceByPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)47750 fnct_GetFaceByPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
47751 {
47752     fnctaux_GetFaceByPoint (context, argc, argv);
47753 }
47754 
47755 static void
fnct_TopoGeo_AddPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)47756 fnct_TopoGeo_AddPoint (sqlite3_context * context, int argc,
47757 		       sqlite3_value ** argv)
47758 {
47759     fnctaux_TopoGeo_AddPoint (context, argc, argv);
47760 }
47761 
47762 static void
fnct_TopoGeo_AddLineString(sqlite3_context * context,int argc,sqlite3_value ** argv)47763 fnct_TopoGeo_AddLineString (sqlite3_context * context, int argc,
47764 			    sqlite3_value ** argv)
47765 {
47766     fnctaux_TopoGeo_AddLineString (context, argc, argv);
47767 }
47768 
47769 static void
fnct_TopoGeo_AddLineStringNoFace(sqlite3_context * context,int argc,sqlite3_value ** argv)47770 fnct_TopoGeo_AddLineStringNoFace (sqlite3_context * context, int argc,
47771 				  sqlite3_value ** argv)
47772 {
47773     fnctaux_TopoGeo_AddLineStringNoFace (context, argc, argv);
47774 }
47775 
47776 static void
fnct_TopoGeo_FromGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)47777 fnct_TopoGeo_FromGeoTable (sqlite3_context * context, int argc,
47778 			   sqlite3_value ** argv)
47779 {
47780     fnctaux_TopoGeo_FromGeoTable (context, argc, argv);
47781 }
47782 
47783 static void
fnct_TopoGeo_FromGeoTableNoFace(sqlite3_context * context,int argc,sqlite3_value ** argv)47784 fnct_TopoGeo_FromGeoTableNoFace (sqlite3_context * context, int argc,
47785 				 sqlite3_value ** argv)
47786 {
47787     fnctaux_TopoGeo_FromGeoTableNoFace (context, argc, argv);
47788 }
47789 
47790 static void
fnct_TopoGeo_FromGeoTableExt(sqlite3_context * context,int argc,sqlite3_value ** argv)47791 fnct_TopoGeo_FromGeoTableExt (sqlite3_context * context, int argc,
47792 			      sqlite3_value ** argv)
47793 {
47794     fnctaux_TopoGeo_FromGeoTableExt (context, argc, argv);
47795 }
47796 
47797 static void
fnct_TopoGeo_FromGeoTableNoFaceExt(sqlite3_context * context,int argc,sqlite3_value ** argv)47798 fnct_TopoGeo_FromGeoTableNoFaceExt (sqlite3_context * context, int argc,
47799 				    sqlite3_value ** argv)
47800 {
47801     fnctaux_TopoGeo_FromGeoTableNoFaceExt (context, argc, argv);
47802 }
47803 
47804 static void
fnct_TopoGeo_Polygonize(sqlite3_context * context,int argc,sqlite3_value ** argv)47805 fnct_TopoGeo_Polygonize (sqlite3_context * context, int argc,
47806 			 sqlite3_value ** argv)
47807 {
47808     fnctaux_TopoGeo_Polygonize (context, argc, argv);
47809 }
47810 
47811 static void
fnct_TopoGeo_TopoSnap(sqlite3_context * context,int argc,sqlite3_value ** argv)47812 fnct_TopoGeo_TopoSnap (sqlite3_context * context, int argc,
47813 		       sqlite3_value ** argv)
47814 {
47815     fnctaux_TopoGeo_TopoSnap (context, argc, argv);
47816 }
47817 
47818 static void
fnct_TopoGeo_SnappedGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)47819 fnct_TopoGeo_SnappedGeoTable (sqlite3_context * context, int argc,
47820 			      sqlite3_value ** argv)
47821 {
47822     fnctaux_TopoGeo_SnappedGeoTable (context, argc, argv);
47823 }
47824 
47825 static void
fnct_TopoGeo_ToGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)47826 fnct_TopoGeo_ToGeoTable (sqlite3_context * context, int argc,
47827 			 sqlite3_value ** argv)
47828 {
47829     fnctaux_TopoGeo_ToGeoTable (context, argc, argv);
47830 }
47831 
47832 static void
fnct_TopoGeo_PolyFacesList(sqlite3_context * context,int argc,sqlite3_value ** argv)47833 fnct_TopoGeo_PolyFacesList (sqlite3_context * context, int argc,
47834 			    sqlite3_value ** argv)
47835 {
47836     fnctaux_TopoGeo_PolyFacesList (context, argc, argv);
47837 }
47838 
47839 static void
fnct_TopoGeo_LineEdgesList(sqlite3_context * context,int argc,sqlite3_value ** argv)47840 fnct_TopoGeo_LineEdgesList (sqlite3_context * context, int argc,
47841 			    sqlite3_value ** argv)
47842 {
47843     fnctaux_TopoGeo_LineEdgesList (context, argc, argv);
47844 }
47845 
47846 static void
fnct_TopoGeo_ToGeoTableGeneralize(sqlite3_context * context,int argc,sqlite3_value ** argv)47847 fnct_TopoGeo_ToGeoTableGeneralize (sqlite3_context * context, int argc,
47848 				   sqlite3_value ** argv)
47849 {
47850     fnctaux_TopoGeo_ToGeoTableGeneralize (context, argc, argv);
47851 }
47852 
47853 static void
fnct_TopoGeo_RemoveSmallFaces(sqlite3_context * context,int argc,sqlite3_value ** argv)47854 fnct_TopoGeo_RemoveSmallFaces (sqlite3_context * context, int argc,
47855 			       sqlite3_value ** argv)
47856 {
47857     fnctaux_TopoGeo_RemoveSmallFaces (context, argc, argv);
47858 }
47859 
47860 static void
fnct_TopoGeo_RemoveDanglingEdges(sqlite3_context * context,int argc,sqlite3_value ** argv)47861 fnct_TopoGeo_RemoveDanglingEdges (sqlite3_context * context, int argc,
47862 				  sqlite3_value ** argv)
47863 {
47864     fnctaux_TopoGeo_RemoveDanglingEdges (context, argc, argv);
47865 }
47866 
47867 static void
fnct_TopoGeo_RemoveDanglingNodes(sqlite3_context * context,int argc,sqlite3_value ** argv)47868 fnct_TopoGeo_RemoveDanglingNodes (sqlite3_context * context, int argc,
47869 				  sqlite3_value ** argv)
47870 {
47871     fnctaux_TopoGeo_RemoveDanglingNodes (context, argc, argv);
47872 }
47873 
47874 static void
fnct_TopoGeo_NewEdgeHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)47875 fnct_TopoGeo_NewEdgeHeal (sqlite3_context * context, int argc,
47876 			  sqlite3_value ** argv)
47877 {
47878     fnctaux_TopoGeo_NewEdgeHeal (context, argc, argv);
47879 }
47880 
47881 static void
fnct_TopoGeo_ModEdgeHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)47882 fnct_TopoGeo_ModEdgeHeal (sqlite3_context * context, int argc,
47883 			  sqlite3_value ** argv)
47884 {
47885     fnctaux_TopoGeo_ModEdgeHeal (context, argc, argv);
47886 }
47887 
47888 static void
fnct_TopoGeo_NewEdgesSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)47889 fnct_TopoGeo_NewEdgesSplit (sqlite3_context * context, int argc,
47890 			    sqlite3_value ** argv)
47891 {
47892     fnctaux_TopoGeo_NewEdgesSplit (context, argc, argv);
47893 }
47894 
47895 static void
fnct_TopoGeo_ModEdgeSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)47896 fnct_TopoGeo_ModEdgeSplit (sqlite3_context * context, int argc,
47897 			   sqlite3_value ** argv)
47898 {
47899     fnctaux_TopoGeo_ModEdgeSplit (context, argc, argv);
47900 }
47901 
47902 static void
fnct_TopoGeo_CreateTopoLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)47903 fnct_TopoGeo_CreateTopoLayer (sqlite3_context * context, int argc,
47904 			      sqlite3_value ** argv)
47905 {
47906     fnctaux_TopoGeo_CreateTopoLayer (context, argc, argv);
47907 }
47908 
47909 static void
fnct_TopoGeo_InitTopoLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)47910 fnct_TopoGeo_InitTopoLayer (sqlite3_context * context, int argc,
47911 			    sqlite3_value ** argv)
47912 {
47913     fnctaux_TopoGeo_InitTopoLayer (context, argc, argv);
47914 }
47915 
47916 static void
fnct_TopoGeo_RemoveTopoLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)47917 fnct_TopoGeo_RemoveTopoLayer (sqlite3_context * context, int argc,
47918 			      sqlite3_value ** argv)
47919 {
47920     fnctaux_TopoGeo_RemoveTopoLayer (context, argc, argv);
47921 }
47922 
47923 static void
fnct_TopoGeo_ExportTopoLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)47924 fnct_TopoGeo_ExportTopoLayer (sqlite3_context * context, int argc,
47925 			      sqlite3_value ** argv)
47926 {
47927     fnctaux_TopoGeo_ExportTopoLayer (context, argc, argv);
47928 }
47929 
47930 static void
fnct_TopoGeo_InsertFeatureFromTopoLayer(sqlite3_context * context,int argc,sqlite3_value ** argv)47931 fnct_TopoGeo_InsertFeatureFromTopoLayer (sqlite3_context * context, int argc,
47932 					 sqlite3_value ** argv)
47933 {
47934     fnctaux_TopoGeo_InsertFeatureFromTopoLayer (context, argc, argv);
47935 }
47936 
47937 static void
fnct_TopoGeo_Clone(sqlite3_context * context,int argc,sqlite3_value ** argv)47938 fnct_TopoGeo_Clone (sqlite3_context * context, int argc, sqlite3_value ** argv)
47939 {
47940     fnctaux_TopoGeo_Clone (context, argc, argv);
47941 }
47942 
47943 static void
fnct_TopoGeo_SubdivideLines(sqlite3_context * context,int argc,sqlite3_value ** argv)47944 fnct_TopoGeo_SubdivideLines (sqlite3_context * context, int argc,
47945 			     sqlite3_value ** argv)
47946 {
47947     fnctaux_TopoGeo_SubdivideLines (context, argc, argv);
47948 }
47949 
47950 static void
fnct_TopoGeo_DisambiguateSegmentEdges(sqlite3_context * context,int argc,sqlite3_value ** argv)47951 fnct_TopoGeo_DisambiguateSegmentEdges (sqlite3_context * context, int argc,
47952 				       sqlite3_value ** argv)
47953 {
47954     fnctaux_TopoGeo_DisambiguateSegmentEdges (context, argc, argv);
47955 }
47956 
47957 static void
fnct_TopoGeo_GetEdgeSeed(sqlite3_context * context,int argc,sqlite3_value ** argv)47958 fnct_TopoGeo_GetEdgeSeed (sqlite3_context * context, int argc,
47959 			  sqlite3_value ** argv)
47960 {
47961     fnctaux_TopoGeo_GetEdgeSeed (context, argc, argv);
47962 }
47963 
47964 static void
fnct_TopoGeo_GetFaceSeed(sqlite3_context * context,int argc,sqlite3_value ** argv)47965 fnct_TopoGeo_GetFaceSeed (sqlite3_context * context, int argc,
47966 			  sqlite3_value ** argv)
47967 {
47968     fnctaux_TopoGeo_GetFaceSeed (context, argc, argv);
47969 }
47970 
47971 static void
fnct_TopoGeo_UpdateSeeds(sqlite3_context * context,int argc,sqlite3_value ** argv)47972 fnct_TopoGeo_UpdateSeeds (sqlite3_context * context, int argc,
47973 			  sqlite3_value ** argv)
47974 {
47975     fnctaux_TopoGeo_UpdateSeeds (context, argc, argv);
47976 }
47977 
47978 static void
fnct_TopoGeo_SnapPointToSeed(sqlite3_context * context,int argc,sqlite3_value ** argv)47979 fnct_TopoGeo_SnapPointToSeed (sqlite3_context * context, int argc,
47980 			      sqlite3_value ** argv)
47981 {
47982     fnctaux_TopoGeo_SnapPointToSeed (context, argc, argv);
47983 }
47984 
47985 static void
fnct_TopoGeo_SnapLineToSeed(sqlite3_context * context,int argc,sqlite3_value ** argv)47986 fnct_TopoGeo_SnapLineToSeed (sqlite3_context * context, int argc,
47987 			     sqlite3_value ** argv)
47988 {
47989     fnctaux_TopoGeo_SnapLineToSeed (context, argc, argv);
47990 }
47991 
47992 static void
fnct_CreateNetwork(sqlite3_context * context,int argc,sqlite3_value ** argv)47993 fnct_CreateNetwork (sqlite3_context * context, int argc, sqlite3_value ** argv)
47994 {
47995     fnctaux_CreateNetwork (context, argc, argv);
47996 }
47997 
47998 static void
fnct_DropNetwork(sqlite3_context * context,int argc,sqlite3_value ** argv)47999 fnct_DropNetwork (sqlite3_context * context, int argc, sqlite3_value ** argv)
48000 {
48001     fnctaux_DropNetwork (context, argc, argv);
48002 }
48003 
48004 static void
fnct_GetLastNetworkException(sqlite3_context * context,int argc,sqlite3_value ** argv)48005 fnct_GetLastNetworkException (sqlite3_context * context, int argc,
48006 			      sqlite3_value ** argv)
48007 {
48008     fnctaux_GetLastNetworkException (context, argc, argv);
48009 }
48010 
48011 static void
fnct_AddIsoNetNode(sqlite3_context * context,int argc,sqlite3_value ** argv)48012 fnct_AddIsoNetNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
48013 {
48014     fnctaux_AddIsoNetNode (context, argc, argv);
48015 }
48016 
48017 static void
fnct_MoveIsoNetNode(sqlite3_context * context,int argc,sqlite3_value ** argv)48018 fnct_MoveIsoNetNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
48019 {
48020     fnctaux_MoveIsoNetNode (context, argc, argv);
48021 }
48022 
48023 static void
fnct_RemIsoNetNode(sqlite3_context * context,int argc,sqlite3_value ** argv)48024 fnct_RemIsoNetNode (sqlite3_context * context, int argc, sqlite3_value ** argv)
48025 {
48026     fnctaux_RemIsoNetNode (context, argc, argv);
48027 }
48028 
48029 static void
fnct_AddLink(sqlite3_context * context,int argc,sqlite3_value ** argv)48030 fnct_AddLink (sqlite3_context * context, int argc, sqlite3_value ** argv)
48031 {
48032     fnctaux_AddLink (context, argc, argv);
48033 }
48034 
48035 static void
fnct_ChangeLinkGeom(sqlite3_context * context,int argc,sqlite3_value ** argv)48036 fnct_ChangeLinkGeom (sqlite3_context * context, int argc, sqlite3_value ** argv)
48037 {
48038     fnctaux_ChangeLinkGeom (context, argc, argv);
48039 }
48040 
48041 static void
fnct_RemoveLink(sqlite3_context * context,int argc,sqlite3_value ** argv)48042 fnct_RemoveLink (sqlite3_context * context, int argc, sqlite3_value ** argv)
48043 {
48044     fnctaux_RemoveLink (context, argc, argv);
48045 }
48046 
48047 static void
fnct_NewLogLinkSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)48048 fnct_NewLogLinkSplit (sqlite3_context * context, int argc,
48049 		      sqlite3_value ** argv)
48050 {
48051     fnctaux_NewLogLinkSplit (context, argc, argv);
48052 }
48053 
48054 static void
fnct_ModLogLinkSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)48055 fnct_ModLogLinkSplit (sqlite3_context * context, int argc,
48056 		      sqlite3_value ** argv)
48057 {
48058     fnctaux_ModLogLinkSplit (context, argc, argv);
48059 }
48060 
48061 static void
fnct_NewGeoLinkSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)48062 fnct_NewGeoLinkSplit (sqlite3_context * context, int argc,
48063 		      sqlite3_value ** argv)
48064 {
48065     fnctaux_NewGeoLinkSplit (context, argc, argv);
48066 }
48067 
48068 static void
fnct_ModGeoLinkSplit(sqlite3_context * context,int argc,sqlite3_value ** argv)48069 fnct_ModGeoLinkSplit (sqlite3_context * context, int argc,
48070 		      sqlite3_value ** argv)
48071 {
48072     fnctaux_ModGeoLinkSplit (context, argc, argv);
48073 }
48074 
48075 static void
fnct_ModLinkHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)48076 fnct_ModLinkHeal (sqlite3_context * context, int argc, sqlite3_value ** argv)
48077 {
48078     fnctaux_ModLinkHeal (context, argc, argv);
48079 }
48080 
48081 static void
fnct_NewLinkHeal(sqlite3_context * context,int argc,sqlite3_value ** argv)48082 fnct_NewLinkHeal (sqlite3_context * context, int argc, sqlite3_value ** argv)
48083 {
48084     fnctaux_NewLinkHeal (context, argc, argv);
48085 }
48086 
48087 static void
fnct_LogiNetFromTGeo(sqlite3_context * context,int argc,sqlite3_value ** argv)48088 fnct_LogiNetFromTGeo (sqlite3_context * context, int argc,
48089 		      sqlite3_value ** argv)
48090 {
48091     fnctaux_LogiNetFromTGeo (context, argc, argv);
48092 }
48093 
48094 static void
fnct_SpatNetFromTGeo(sqlite3_context * context,int argc,sqlite3_value ** argv)48095 fnct_SpatNetFromTGeo (sqlite3_context * context, int argc,
48096 		      sqlite3_value ** argv)
48097 {
48098     fnctaux_SpatNetFromTGeo (context, argc, argv);
48099 }
48100 
48101 static void
fnct_SpatNetFromGeom(sqlite3_context * context,int argc,sqlite3_value ** argv)48102 fnct_SpatNetFromGeom (sqlite3_context * context, int argc,
48103 		      sqlite3_value ** argv)
48104 {
48105     fnctaux_SpatNetFromGeom (context, argc, argv);
48106 }
48107 
48108 static void
fnct_ValidLogicalNet(sqlite3_context * context,int argc,sqlite3_value ** argv)48109 fnct_ValidLogicalNet (sqlite3_context * context, int argc,
48110 		      sqlite3_value ** argv)
48111 {
48112     fnctaux_ValidLogicalNet (context, argc, argv);
48113 }
48114 
48115 static void
fnct_ValidSpatialNet(sqlite3_context * context,int argc,sqlite3_value ** argv)48116 fnct_ValidSpatialNet (sqlite3_context * context, int argc,
48117 		      sqlite3_value ** argv)
48118 {
48119     fnctaux_ValidSpatialNet (context, argc, argv);
48120 }
48121 
48122 static void
fnct_GetNetNodeByPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)48123 fnct_GetNetNodeByPoint (sqlite3_context * context, int argc,
48124 			sqlite3_value ** argv)
48125 {
48126     fnctaux_GetNetNodeByPoint (context, argc, argv);
48127 }
48128 
48129 static void
fnct_GetLinkByPoint(sqlite3_context * context,int argc,sqlite3_value ** argv)48130 fnct_GetLinkByPoint (sqlite3_context * context, int argc, sqlite3_value ** argv)
48131 {
48132     fnctaux_GetLinkByPoint (context, argc, argv);
48133 }
48134 
48135 static void
fnct_TopoNet_FromGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)48136 fnct_TopoNet_FromGeoTable (sqlite3_context * context, int argc,
48137 			   sqlite3_value ** argv)
48138 {
48139     fnctaux_TopoNet_FromGeoTable (context, argc, argv);
48140 }
48141 
48142 static void
fnct_TopoNet_ToGeoTable(sqlite3_context * context,int argc,sqlite3_value ** argv)48143 fnct_TopoNet_ToGeoTable (sqlite3_context * context, int argc,
48144 			 sqlite3_value ** argv)
48145 {
48146     fnctaux_TopoNet_ToGeoTable (context, argc, argv);
48147 }
48148 
48149 static void
fnct_TopoNet_ToGeoTableGeneralize(sqlite3_context * context,int argc,sqlite3_value ** argv)48150 fnct_TopoNet_ToGeoTableGeneralize (sqlite3_context * context, int argc,
48151 				   sqlite3_value ** argv)
48152 {
48153     fnctaux_TopoNet_ToGeoTableGeneralize (context, argc, argv);
48154 }
48155 
48156 static void
fnct_TopoNet_Clone(sqlite3_context * context,int argc,sqlite3_value ** argv)48157 fnct_TopoNet_Clone (sqlite3_context * context, int argc, sqlite3_value ** argv)
48158 {
48159     fnctaux_TopoNet_Clone (context, argc, argv);
48160 }
48161 
48162 static void
fnct_TopoNet_GetLinkSeed(sqlite3_context * context,int argc,sqlite3_value ** argv)48163 fnct_TopoNet_GetLinkSeed (sqlite3_context * context, int argc,
48164 			  sqlite3_value ** argv)
48165 {
48166     fnctaux_TopoNet_GetLinkSeed (context, argc, argv);
48167 }
48168 
48169 static void
fnct_TopoNet_UpdateSeeds(sqlite3_context * context,int argc,sqlite3_value ** argv)48170 fnct_TopoNet_UpdateSeeds (sqlite3_context * context, int argc,
48171 			  sqlite3_value ** argv)
48172 {
48173     fnctaux_TopoNet_UpdateSeeds (context, argc, argv);
48174 }
48175 
48176 static void
fnct_TopoNet_DisambiguateSegmentLinks(sqlite3_context * context,int argc,sqlite3_value ** argv)48177 fnct_TopoNet_DisambiguateSegmentLinks (sqlite3_context * context, int argc,
48178 				       sqlite3_value ** argv)
48179 {
48180     fnctaux_TopoNet_DisambiguateSegmentLinks (context, argc, argv);
48181 }
48182 
48183 static void
fnct_TopoNet_LineLinksList(sqlite3_context * context,int argc,sqlite3_value ** argv)48184 fnct_TopoNet_LineLinksList (sqlite3_context * context, int argc,
48185 			    sqlite3_value ** argv)
48186 {
48187     fnctaux_TopoNet_LineLinksList (context, argc, argv);
48188 }
48189 
48190 #endif /* end TOPOLOGY conditionals */
48191 
48192 #ifdef LOADABLE_EXTENSION
48193 static void
splite_close_callback(void * p_cache)48194 splite_close_callback (void *p_cache)
48195 {
48196 /*
48197 / the DB connection has been terminated
48198 /
48199 / this callback function is expected to be invoked only if
48200 / SpatiaLite was loaded as a dynamic extension and will
48201 / perform a final clean-up releasing the internal cache
48202 /
48203 */
48204     struct splite_internal_cache *cache =
48205 	(struct splite_internal_cache *) p_cache;
48206 
48207     if (cache == NULL)
48208 	return;
48209     if (cache->magic1 != SPATIALITE_CACHE_MAGIC1
48210 	|| cache->magic2 != SPATIALITE_CACHE_MAGIC2)
48211 	return;
48212 
48213 #ifdef ENABLE_RTTOPO
48214     gaiaResetRtTopoMsg (cache);
48215 #endif
48216 
48217     free_internal_cache (cache);
48218 }
48219 #endif
48220 
48221 SPATIALITE_PRIVATE void *
register_spatialite_sql_functions(void * p_db,const void * p_cache)48222 register_spatialite_sql_functions (void *p_db, const void *p_cache)
48223 {
48224     sqlite3 *db = p_db;
48225     struct splite_internal_cache *cache =
48226 	(struct splite_internal_cache *) p_cache;
48227     const char *security_level;
48228 
48229 #ifdef LOADABLE_EXTENSION
48230 /* registering the CLOSE-CALLBACK function */
48231     sqlite3_create_function_v2 (db, "spatialite_version", 0,
48232 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48233 				fnct_spatialite_version, 0, 0,
48234 				splite_close_callback);
48235 #else
48236     sqlite3_create_function_v2 (db, "spatialite_version", 0,
48237 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48238 				fnct_spatialite_version, 0, 0, 0);
48239 #endif
48240 
48241     sqlite3_create_function_v2 (db, "CreateMissingSystemTables", 0,
48242 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48243 				fnct_createMissingSystemTables, 0, 0, 0);
48244     sqlite3_create_function_v2 (db, "CreateMissingSystemTables", 1,
48245 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48246 				fnct_createMissingSystemTables, 0, 0, 0);
48247     sqlite3_create_function_v2 (db, "CreateMissingSystemTables", 2,
48248 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48249 				fnct_createMissingSystemTables, 0, 0, 0);
48250 
48251     sqlite3_create_function_v2 (db, "spatialite_target_cpu", 0,
48252 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48253 				fnct_spatialite_target_cpu, 0, 0, 0);
48254     sqlite3_create_function_v2 (db, "check_strict_sql_quoting", 0,
48255 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48256 				fnct_check_strict_sql_quoting, 0, 0, 0);
48257     sqlite3_create_function_v2 (db, "freexl_version", 0,
48258 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48259 				fnct_freexl_version, 0, 0, 0);
48260     sqlite3_create_function_v2 (db, "proj4_version", 0,
48261 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48262 				fnct_proj4_version, 0, 0, 0);
48263     sqlite3_create_function_v2 (db, "proj_version", 0,
48264 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48265 				fnct_proj4_version, 0, 0, 0);
48266     sqlite3_create_function_v2 (db, "geos_version", 0,
48267 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48268 				fnct_geos_version, 0, 0, 0);
48269     sqlite3_create_function_v2 (db, "rttopo_version", 0,
48270 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48271 				fnct_rttopo_version, 0, 0, 0);
48272     sqlite3_create_function_v2 (db, "libxml2_version", 0,
48273 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48274 				fnct_libxml2_version, 0, 0, 0);
48275     sqlite3_create_function_v2 (db, "HasProj", 0,
48276 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48277 				fnct_has_proj, 0, 0, 0);
48278     sqlite3_create_function_v2 (db, "HasProj6", 0,
48279 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48280 				fnct_has_proj6, 0, 0, 0);
48281     sqlite3_create_function_v2 (db, "HasProjGeodesic", 0,
48282 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48283 				fnct_has_proj_geodesic, 0, 0, 0);
48284     sqlite3_create_function_v2 (db, "HasGeos", 0,
48285 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48286 				fnct_has_geos, 0, 0, 0);
48287     sqlite3_create_function_v2 (db, "HasGeosAdvanced", 0,
48288 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48289 				fnct_has_geos_advanced, 0, 0, 0);
48290     sqlite3_create_function_v2 (db, "HasGeosTrunk", 0,
48291 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48292 				fnct_has_geos_trunk, 0, 0, 0);
48293     sqlite3_create_function_v2 (db, "HasGeosReentrant", 0,
48294 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48295 				fnct_has_geos_reentrant, 0, 0, 0);
48296     sqlite3_create_function_v2 (db, "HasGeosOnlyReentrant", 0,
48297 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48298 				fnct_has_geos_only_reentrant, 0, 0, 0);
48299     sqlite3_create_function_v2 (db, "HasMinZip", 0,
48300 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48301 				fnct_has_minizip, 0, 0, 0);
48302     sqlite3_create_function_v2 (db, "HasRtTopo", 0,
48303 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48304 				fnct_has_rttopo, 0, 0, 0);
48305     sqlite3_create_function_v2 (db, "HasMathSql", 0,
48306 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48307 				fnct_has_math_sql, 0, 0, 0);
48308     sqlite3_create_function_v2 (db, "HasGeoCallbacks", 0,
48309 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48310 				fnct_has_geo_callbacks, 0, 0, 0);
48311     sqlite3_create_function_v2 (db, "HasIconv", 0,
48312 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48313 				fnct_has_iconv, 0, 0, 0);
48314     sqlite3_create_function_v2 (db, "HasFreeXL", 0,
48315 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48316 				fnct_has_freeXL, 0, 0, 0);
48317     sqlite3_create_function_v2 (db, "HasEpsg", 0,
48318 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48319 				fnct_has_epsg, 0, 0, 0);
48320     sqlite3_create_function_v2 (db, "HasLibXML2", 0,
48321 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48322 				fnct_has_libxml2, 0, 0, 0);
48323     sqlite3_create_function_v2 (db, "HasGeoPackage", 0,
48324 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48325 				fnct_has_geopackage, 0, 0, 0);
48326     sqlite3_create_function_v2 (db, "HasGCP", 0,
48327 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48328 				fnct_has_gcp, 0, 0, 0);
48329     sqlite3_create_function_v2 (db, "HasGroundControlPoints", 0,
48330 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48331 				fnct_has_gcp, 0, 0, 0);
48332     sqlite3_create_function_v2 (db, "HasTopology", 0,
48333 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48334 				fnct_has_topology, 0, 0, 0);
48335     sqlite3_create_function_v2 (db, "HasKNN", 0,
48336 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48337 				fnct_has_knn, 0, 0, 0);
48338     sqlite3_create_function_v2 (db, "HasRouting", 0,
48339 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48340 				fnct_has_routing, 0, 0, 0);
48341     sqlite3_create_function_v2 (db, "GeometryConstraints", 3,
48342 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48343 				fnct_GeometryConstraints, 0, 0, 0);
48344     sqlite3_create_function_v2 (db, "GeometryConstraints", 4,
48345 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48346 				fnct_GeometryConstraints, 0, 0, 0);
48347     sqlite3_create_function_v2 (db, "RTreeAlign", 3,
48348 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48349 				fnct_RTreeAlign, 0, 0, 0);
48350     sqlite3_create_function_v2 (db, "TemporaryRTreeAlign", 4,
48351 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48352 				fnct_TemporaryRTreeAlign, 0, 0, 0);
48353     sqlite3_create_function_v2 (db, "IsValidFont", 1,
48354 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48355 				fnct_IsValidFont, 0, 0, 0);
48356     sqlite3_create_function_v2 (db, "CheckFontFaceName", 2,
48357 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48358 				fnct_CheckFontFacename, 0, 0, 0);
48359     sqlite3_create_function_v2 (db, "GetFontFamily", 1,
48360 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48361 				fnct_GetFontFamily, 0, 0, 0);
48362     sqlite3_create_function_v2 (db, "IsFontBold", 1,
48363 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48364 				fnct_IsFontBold, 0, 0, 0);
48365     sqlite3_create_function_v2 (db, "IsFontItalic", 1,
48366 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48367 				fnct_IsFontItalic, 0, 0, 0);
48368     sqlite3_create_function_v2 (db, "IsValidPixel", 3,
48369 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48370 				fnct_IsValidPixel, 0, 0, 0);
48371     sqlite3_create_function_v2 (db, "IsValidRasterPalette", 2,
48372 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48373 				fnct_IsValidRasterPalette, 0, 0, 0);
48374     sqlite3_create_function_v2 (db, "IsValidRasterStatistics", 3,
48375 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48376 				fnct_IsValidRasterStatistics, 0, 0, 0);
48377     sqlite3_create_function_v2 (db, "IsValidRasterTile", 5,
48378 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48379 				fnct_IsValidRasterTile, 0, 0, 0);
48380     sqlite3_create_function_v2 (db, "IsPopulatedCoverage", 2,
48381 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48382 				fnct_IsPopulatedCoverage, 0, 0, 0);
48383     sqlite3_create_function_v2 (db, "CheckSpatialMetaData", 0,
48384 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48385 				fnct_CheckSpatialMetaData, 0, 0, 0);
48386     sqlite3_create_function_v2 (db, "CheckSpatialMetaData", 1,
48387 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48388 				fnct_CheckSpatialMetaData, 0, 0, 0);
48389     sqlite3_create_function_v2 (db, "CheckGeoPackageMetaData", 0,
48390 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48391 				fnct_CheckGeoPackageMetaData, 0, 0, 0);
48392     sqlite3_create_function_v2 (db, "CheckGeoPackageMetaData", 1,
48393 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48394 				fnct_CheckGeoPackageMetaData, 0, 0, 0);
48395     sqlite3_create_function_v2 (db, "AutoFDOStart", 0,
48396 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48397 				fnct_AutoFDOStart, 0, 0, 0);
48398     sqlite3_create_function_v2 (db, "AutoFDOStart", 1,
48399 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48400 				fnct_AutoFDOStart, 0, 0, 0);
48401     sqlite3_create_function_v2 (db, "AutoFDOStop", 0,
48402 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48403 				fnct_AutoFDOStop, 0, 0, 0);
48404     sqlite3_create_function_v2 (db, "AutoFDOStop", 1,
48405 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48406 				fnct_AutoFDOStop, 0, 0, 0);
48407     sqlite3_create_function_v2 (db, "InitFDOSpatialMetaData", 0,
48408 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48409 				fnct_InitFDOSpatialMetaData, 0, 0, 0);
48410     sqlite3_create_function_v2 (db, "AddFDOGeometryColumn", 6,
48411 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48412 				fnct_AddFDOGeometryColumn, 0, 0, 0);
48413     sqlite3_create_function_v2 (db, "RecoverFDOGeometryColumn", 6,
48414 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48415 				fnct_RecoverFDOGeometryColumn, 0, 0, 0);
48416     sqlite3_create_function_v2 (db, "DiscardFDOGeometryColumn", 2,
48417 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48418 				fnct_DiscardFDOGeometryColumn, 0, 0, 0);
48419     sqlite3_create_function_v2 (db, "GetDbObjectScope", 2,
48420 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48421 				fnct_GetDbObjectScope, 0, 0, 0);
48422 
48423     sqlite3_create_function_v2 (db, "InitSpatialMetaData", 0,
48424 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48425 				fnct_InitSpatialMetaData, 0, 0, 0);
48426     sqlite3_create_function_v2 (db, "InitSpatialMetaData", 1,
48427 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48428 				fnct_InitSpatialMetaData, 0, 0, 0);
48429     sqlite3_create_function_v2 (db, "InitSpatialMetaData", 2,
48430 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48431 				fnct_InitSpatialMetaData, 0, 0, 0);
48432 
48433     sqlite3_create_function_v2 (db, "InitAdvancedMetaData", 0,
48434 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48435 				fnct_InitAdvancedMetaData, 0, 0, 0);
48436     sqlite3_create_function_v2 (db, "InitAdvancedMetaData", 1,
48437 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48438 				fnct_InitAdvancedMetaData, 0, 0, 0);
48439 
48440     sqlite3_create_function_v2 (db, "InitSpatialMetaDataFull", 0,
48441 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48442 				fnct_InitSpatialMetaDataFull, 0, 0, 0);
48443     sqlite3_create_function_v2 (db, "InitSpatialMetaDataFull", 1,
48444 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48445 				fnct_InitSpatialMetaDataFull, 0, 0, 0);
48446     sqlite3_create_function_v2 (db, "InitSpatialMetaDataFull", 2,
48447 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48448 				fnct_InitSpatialMetaDataFull, 0, 0, 0);
48449 
48450     sqlite3_create_function_v2 (db, "InsertEpsgSrid", 1,
48451 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48452 				fnct_InsertEpsgSrid, 0, 0, 0);
48453     sqlite3_create_function_v2 (db, "SridIsGeographic", 1,
48454 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48455 				fnct_SridIsGeographic, 0, 0, 0);
48456     sqlite3_create_function_v2 (db, "SridIsProjected", 1,
48457 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48458 				fnct_SridIsProjected, 0, 0, 0);
48459     sqlite3_create_function_v2 (db, "SridHasFlippedAxes", 1,
48460 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48461 				fnct_SridHasFlippedAxes, 0, 0, 0);
48462     sqlite3_create_function_v2 (db, "SridGetSpheroid", 1,
48463 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48464 				fnct_SridGetSpheroid, 0, 0, 0);
48465     sqlite3_create_function_v2 (db, "SridGetEllipsoid", 1,
48466 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48467 				fnct_SridGetSpheroid, 0, 0, 0);
48468     sqlite3_create_function_v2 (db, "SridGetPrimeMeridian", 1,
48469 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48470 				fnct_SridGetPrimeMeridian, 0, 0, 0);
48471     sqlite3_create_function_v2 (db, "SridGetDatum", 1,
48472 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48473 				fnct_SridGetDatum, 0, 0, 0);
48474     sqlite3_create_function_v2 (db, "SridGetProjection", 1,
48475 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48476 				fnct_SridGetProjection, 0, 0, 0);
48477     sqlite3_create_function_v2 (db, "SridGetUnit", 1,
48478 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48479 				fnct_SridGetUnit, 0, 0, 0);
48480     sqlite3_create_function_v2 (db, "SridGetAxis_1_Name", 1,
48481 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48482 				fnct_SridGetAxis1Name, 0, 0, 0);
48483     sqlite3_create_function_v2 (db, "SridGetAxis_1_Orientation", 1,
48484 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48485 				fnct_SridGetAxis1Orientation, 0, 0, 0);
48486     sqlite3_create_function_v2 (db, "SridGetAxis_2_Name", 1,
48487 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48488 				fnct_SridGetAxis2Name, 0, 0, 0);
48489     sqlite3_create_function_v2 (db, "SridGetAxis_2_Orientation", 1,
48490 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48491 				fnct_SridGetAxis2Orientation, 0, 0, 0);
48492     sqlite3_create_function_v2 (db, "AddGeometryColumn", 4,
48493 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48494 				fnct_AddGeometryColumn, 0, 0, 0);
48495     sqlite3_create_function_v2 (db, "AddGeometryColumn", 5,
48496 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48497 				fnct_AddGeometryColumn, 0, 0, 0);
48498     sqlite3_create_function_v2 (db, "AddGeometryColumn", 6,
48499 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48500 				fnct_AddGeometryColumn, 0, 0, 0);
48501     sqlite3_create_function_v2 (db, "AddTemporaryGeometryColumn", 5,
48502 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48503 				fnct_AddTemporaryGeometryColumn, 0, 0, 0);
48504     sqlite3_create_function_v2 (db, "AddTemporaryGeometryColumn", 6,
48505 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48506 				fnct_AddTemporaryGeometryColumn, 0, 0, 0);
48507     sqlite3_create_function_v2 (db, "AddTemporaryGeometryColumn", 7,
48508 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48509 				fnct_AddTemporaryGeometryColumn, 0, 0, 0);
48510     sqlite3_create_function_v2 (db, "RecoverGeometryColumn", 4,
48511 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48512 				fnct_RecoverGeometryColumn, 0, 0, 0);
48513     sqlite3_create_function_v2 (db, "RecoverGeometryColumn", 5,
48514 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48515 				fnct_RecoverGeometryColumn, 0, 0, 0);
48516     sqlite3_create_function_v2 (db, "UpgradeGeometryTriggers", 1,
48517 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48518 				fnct_UpgradeGeometryTriggers, 0, 0, 0);
48519     sqlite3_create_function_v2 (db, "DiscardGeometryColumn", 2,
48520 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48521 				fnct_DiscardGeometryColumn, 0, 0, 0);
48522     sqlite3_create_function_v2 (db, "RegisterVirtualGeometry", 1,
48523 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48524 				fnct_RegisterVirtualGeometry, 0, 0, 0);
48525     sqlite3_create_function_v2 (db, "DropVirtualGeometry", 1,
48526 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48527 				fnct_DropVirtualGeometry, 0, 0, 0);
48528     sqlite3_create_function_v2 (db, "RecoverSpatialIndex", 0,
48529 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48530 				fnct_RecoverSpatialIndex, 0, 0, 0);
48531     sqlite3_create_function_v2 (db, "RecoverSpatialIndex", 1,
48532 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48533 				fnct_RecoverSpatialIndex, 0, 0, 0);
48534     sqlite3_create_function_v2 (db, "RecoverSpatialIndex", 2,
48535 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48536 				fnct_RecoverSpatialIndex, 0, 0, 0);
48537     sqlite3_create_function_v2 (db, "RecoverSpatialIndex", 3,
48538 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48539 				fnct_RecoverSpatialIndex, 0, 0, 0);
48540     sqlite3_create_function_v2 (db, "CheckSpatialIndex", 0,
48541 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48542 				fnct_CheckSpatialIndex, 0, 0, 0);
48543     sqlite3_create_function_v2 (db, "CheckSpatialIndex", 2,
48544 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48545 				fnct_CheckSpatialIndex, 0, 0, 0);
48546     sqlite3_create_function_v2 (db, "GetSpatialIndexExtent", 3,
48547 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48548 				fnct_GetSpatialIndexExtent, 0, 0, 0);
48549     sqlite3_create_function_v2 (db, "CheckShadowedRowid", 1,
48550 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48551 				fnct_CheckShadowedRowid, 0, 0, 0);
48552     sqlite3_create_function_v2 (db, "CheckWithoutRowid", 1,
48553 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48554 				fnct_CheckWithoutRowid, 0, 0, 0);
48555     sqlite3_create_function_v2 (db, "CreateSpatialIndex", 2,
48556 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48557 				fnct_CreateSpatialIndex, 0, 0, 0);
48558     sqlite3_create_function_v2 (db, "CreateTemporarySpatialIndex", 3,
48559 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48560 				fnct_CreateTemporarySpatialIndex, 0, 0, 0);
48561     sqlite3_create_function_v2 (db, "CreateMbrCache", 2,
48562 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48563 				fnct_CreateMbrCache, 0, 0, 0);
48564     sqlite3_create_function_v2 (db, "DisableSpatialIndex", 2,
48565 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48566 				fnct_DisableSpatialIndex, 0, 0, 0);
48567     sqlite3_create_function_v2 (db, "RebuildGeometryTriggers", 2,
48568 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48569 				fnct_RebuildGeometryTriggers, 0, 0, 0);
48570     sqlite3_create_function_v2 (db, "UpdateLayerStatistics", 0,
48571 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48572 				fnct_UpdateLayerStatistics, 0, 0, 0);
48573     sqlite3_create_function_v2 (db, "UpdateLayerStatistics", 1,
48574 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48575 				fnct_UpdateLayerStatistics, 0, 0, 0);
48576     sqlite3_create_function_v2 (db, "UpdateLayerStatistics", 2,
48577 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48578 				fnct_UpdateLayerStatistics, 0, 0, 0);
48579     sqlite3_create_function_v2 (db, "GetLayerExtent", 1,
48580 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48581 				fnct_GetLayerExtent, 0, 0, 0);
48582     sqlite3_create_function_v2 (db, "GetLayerExtent", 2,
48583 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48584 				fnct_GetLayerExtent, 0, 0, 0);
48585     sqlite3_create_function_v2 (db, "GetLayerExtent", 3,
48586 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48587 				fnct_GetLayerExtent, 0, 0, 0);
48588     sqlite3_create_function_v2 (db, "InvalidateLayerStatistics", 0,
48589 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48590 				fnct_InvalidateLayerStatistics, 0, 0, 0);
48591     sqlite3_create_function_v2 (db, "InvalidateLayerStatistics", 1,
48592 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48593 				fnct_InvalidateLayerStatistics, 0, 0, 0);
48594     sqlite3_create_function_v2 (db, "InvalidateLayerStatistics", 2,
48595 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48596 				fnct_InvalidateLayerStatistics, 0, 0, 0);
48597     sqlite3_create_function_v2 (db, "CreateRasterCoveragesTable", 0,
48598 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48599 				fnct_CreateRasterCoveragesTable, 0, 0, 0);
48600     sqlite3_create_function_v2 (db, "ReCreateRasterCoveragesTriggers", 0,
48601 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48602 				fnct_ReCreateRasterCoveragesTriggers, 0, 0, 0);
48603     sqlite3_create_function_v2 (db, "CreateVectorCoveragesTables", 0,
48604 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48605 				fnct_CreateVectorCoveragesTables, 0, 0, 0);
48606     sqlite3_create_function_v2 (db, "ReCreateVectorCoveragesTriggers", 0,
48607 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48608 				fnct_ReCreateVectorCoveragesTriggers, 0, 0, 0);
48609     sqlite3_create_function_v2 (db, "WMS_CreateTables", 0,
48610 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48611 				fnct_CreateWMSTables, 0, 0, 0);
48612     sqlite3_create_function (db, "WMS_RegisterGetCapabilities", 1, SQLITE_ANY,
48613 			     0, fnct_RegisterWMSGetCapabilities, 0, 0);
48614     sqlite3_create_function (db, "WMS_RegisterGetCapabilities", 3, SQLITE_ANY,
48615 			     0, fnct_RegisterWMSGetCapabilities, 0, 0);
48616     sqlite3_create_function (db, "WMS_UnRegisterGetCapabilities", 1,
48617 			     SQLITE_ANY, 0, fnct_UnregisterWMSGetCapabilities,
48618 			     0, 0);
48619     sqlite3_create_function (db, "WMS_SetGetCapabilitiesInfos", 3, SQLITE_ANY,
48620 			     0, fnct_SetWMSGetCapabilitiesInfos, 0, 0);
48621     sqlite3_create_function (db, "WMS_RegisterGetMap", 9, SQLITE_ANY, 0,
48622 			     fnct_RegisterWMSGetMap, 0, 0);
48623     sqlite3_create_function (db, "WMS_RegisterGetMap", 13, SQLITE_ANY, 0,
48624 			     fnct_RegisterWMSGetMap, 0, 0);
48625     sqlite3_create_function (db, "WMS_RegisterGetMap", 18, SQLITE_ANY, 0,
48626 			     fnct_RegisterWMSGetMap, 0, 0);
48627     sqlite3_create_function (db, "WMS_UnRegisterGetMap", 2, SQLITE_ANY, 0,
48628 			     fnct_UnregisterWMSGetMap, 0, 0);
48629     sqlite3_create_function (db, "WMS_SetGetMapInfos", 4, SQLITE_ANY, 0,
48630 			     fnct_SetWMSGetMapInfos, 0, 0);
48631     sqlite3_create_function (db, "WMS_SetGetMapCopyright", 3, SQLITE_ANY, 0,
48632 			     fnct_SetWMSGetMapCopyright, 0, 0);
48633     sqlite3_create_function (db, "WMS_SetGetMapCopyright", 4, SQLITE_ANY, 0,
48634 			     fnct_SetWMSGetMapCopyright, 0, 0);
48635     sqlite3_create_function (db, "WMS_SetGetMapOptions", 3, SQLITE_ANY, 0,
48636 			     fnct_SetWMSGetMapOptions, 0, 0);
48637     sqlite3_create_function (db, "WMS_SetGetMapOptions", 4, SQLITE_ANY, 0,
48638 			     fnct_SetWMSGetMapOptions, 0, 0);
48639     sqlite3_create_function (db, "WMS_SetGetMapOptions", 6, SQLITE_ANY, 0,
48640 			     fnct_SetWMSGetMapOptions, 0, 0);
48641     sqlite3_create_function (db, "WMS_RegisterSetting", 4, SQLITE_ANY, 0,
48642 			     fnct_RegisterWMSSetting, 0, 0);
48643     sqlite3_create_function (db, "WMS_RegisterSetting", 5, SQLITE_ANY, 0,
48644 			     fnct_RegisterWMSSetting, 0, 0);
48645     sqlite3_create_function (db, "WMS_DefaultSetting", 4, SQLITE_ANY, 0,
48646 			     fnct_DefaultWMSSetting, 0, 0);
48647     sqlite3_create_function (db, "WMS_UnRegisterSetting", 4, SQLITE_ANY, 0,
48648 			     fnct_UnregisterWMSSetting, 0, 0);
48649     sqlite3_create_function (db, "WMS_RegisterRefSys", 7, SQLITE_ANY, 0,
48650 			     fnct_RegisterWMSRefSys, 0, 0);
48651     sqlite3_create_function (db, "WMS_RegisterRefSys", 8, SQLITE_ANY, 0,
48652 			     fnct_RegisterWMSRefSys, 0, 0);
48653     sqlite3_create_function (db, "WMS_DefaultRefSys", 3, SQLITE_ANY, 0,
48654 			     fnct_DefaultWMSRefSys, 0, 0);
48655     sqlite3_create_function (db, "WMS_UnRegisterRefSys", 3, SQLITE_ANY, 0,
48656 			     fnct_UnregisterWMSRefSys, 0, 0);
48657     sqlite3_create_function (db, "WMS_GetMapRequestURL", 8, SQLITE_ANY, 0,
48658 			     fnct_WMSGetMapRequestURL, 0, 0);
48659     sqlite3_create_function (db, "WMS_GetFeatureInfoRequestURL", 10,
48660 			     SQLITE_ANY, 0, fnct_WMSGetFeatureInfoRequestURL,
48661 			     0, 0);
48662     sqlite3_create_function (db, "WMS_GetFeatureInfoRequestURL", 11,
48663 			     SQLITE_ANY, 0, fnct_WMSGetFeatureInfoRequestURL,
48664 			     0, 0);
48665     sqlite3_create_function (db, "RegisterDataLicense", 1, SQLITE_ANY, 0,
48666 			     fnct_RegisterDataLicense, 0, 0);
48667     sqlite3_create_function (db, "RegisterDataLicense", 2, SQLITE_ANY, 0,
48668 			     fnct_RegisterDataLicense, 0, 0);
48669     sqlite3_create_function (db, "UnRegisterDataLicense", 1, SQLITE_ANY, 0,
48670 			     fnct_UnRegisterDataLicense, 0, 0);
48671     sqlite3_create_function (db, "RenameDataLicense", 2, SQLITE_ANY, 0,
48672 			     fnct_RenameDataLicense, 0, 0);
48673     sqlite3_create_function (db, "SetDataLicenseUrl", 2, SQLITE_ANY, 0,
48674 			     fnct_SetDataLicenseUrl, 0, 0);
48675     sqlite3_create_function_v2 (db, "CreateMetaCatalogTables", 1,
48676 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48677 				fnct_CreateMetaCatalogTables, 0, 0, 0);
48678     sqlite3_create_function_v2 (db, "UpdateMetaCatalogStatistics", 3,
48679 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48680 				fnct_UpdateMetaCatalogStatistics, 0, 0, 0);
48681     sqlite3_create_function_v2 (db, "UpdateMetaCatalogStatistics", 4,
48682 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48683 				fnct_UpdateMetaCatalogStatistics, 0, 0, 0);
48684     sqlite3_create_function_v2 (db, "AsText", 1,
48685 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48686 				fnct_AsText, 0, 0, 0);
48687     sqlite3_create_function_v2 (db, "ST_AsText", 1,
48688 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48689 				fnct_AsText, 0, 0, 0);
48690     sqlite3_create_function_v2 (db, "AsWkt", 1,
48691 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48692 				fnct_AsWkt, 0, 0, 0);
48693     sqlite3_create_function_v2 (db, "AsWkt", 2,
48694 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48695 				fnct_AsWkt, 0, 0, 0);
48696     sqlite3_create_function_v2 (db, "AsSvg", 1,
48697 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48698 				fnct_AsSvg1, 0, 0, 0);
48699     sqlite3_create_function_v2 (db, "AsSvg", 2,
48700 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48701 				fnct_AsSvg2, 0, 0, 0);
48702     sqlite3_create_function_v2 (db, "AsSvg", 3,
48703 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48704 				fnct_AsSvg3, 0, 0, 0);
48705     sqlite3_create_function_v2 (db, "CloneTable", 4,
48706 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48707 				fnct_CloneTable, 0, 0, 0);
48708     sqlite3_create_function_v2 (db, "CloneTable", 5,
48709 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48710 				fnct_CloneTable, 0, 0, 0);
48711     sqlite3_create_function_v2 (db, "CloneTable", 6,
48712 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48713 				fnct_CloneTable, 0, 0, 0);
48714     sqlite3_create_function_v2 (db, "CloneTable", 7,
48715 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48716 				fnct_CloneTable, 0, 0, 0);
48717     sqlite3_create_function_v2 (db, "CloneTable", 8,
48718 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48719 				fnct_CloneTable, 0, 0, 0);
48720     sqlite3_create_function_v2 (db, "CloneTable", 9,
48721 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48722 				fnct_CloneTable, 0, 0, 0);
48723     sqlite3_create_function_v2 (db, "CloneTable", 10,
48724 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48725 				fnct_CloneTable, 0, 0, 0);
48726     sqlite3_create_function_v2 (db, "CloneTable", 11,
48727 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48728 				fnct_CloneTable, 0, 0, 0);
48729     sqlite3_create_function_v2 (db, "CloneTable", 12,
48730 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48731 				fnct_CloneTable, 0, 0, 0);
48732     sqlite3_create_function_v2 (db, "CloneTable", 13,
48733 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48734 				fnct_CloneTable, 0, 0, 0);
48735     sqlite3_create_function_v2 (db, "CloneTable", 14,
48736 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48737 				fnct_CloneTable, 0, 0, 0);
48738     sqlite3_create_function_v2 (db, "CreateClonedTable", 4,
48739 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48740 				fnct_CreateClonedTable, 0, 0, 0);
48741     sqlite3_create_function_v2 (db, "CreateClonedTable", 5,
48742 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48743 				fnct_CreateClonedTable, 0, 0, 0);
48744     sqlite3_create_function_v2 (db, "CreateClonedTable", 6,
48745 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48746 				fnct_CreateClonedTable, 0, 0, 0);
48747     sqlite3_create_function_v2 (db, "CreateClonedTable", 7,
48748 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48749 				fnct_CreateClonedTable, 0, 0, 0);
48750     sqlite3_create_function_v2 (db, "CreateClonedTable", 8,
48751 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48752 				fnct_CreateClonedTable, 0, 0, 0);
48753     sqlite3_create_function_v2 (db, "CreateClonedTable", 9,
48754 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48755 				fnct_CreateClonedTable, 0, 0, 0);
48756     sqlite3_create_function_v2 (db, "CreateClonedTable", 10,
48757 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48758 				fnct_CreateClonedTable, 0, 0, 0);
48759     sqlite3_create_function_v2 (db, "CreateClonedTable", 11,
48760 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48761 				fnct_CreateClonedTable, 0, 0, 0);
48762     sqlite3_create_function_v2 (db, "CreateClonedTable", 12,
48763 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48764 				fnct_CreateClonedTable, 0, 0, 0);
48765     sqlite3_create_function_v2 (db, "CreateClonedTable", 13,
48766 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48767 				fnct_CreateClonedTable, 0, 0, 0);
48768     sqlite3_create_function_v2 (db, "CreateClonedTable", 14,
48769 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48770 				fnct_CreateClonedTable, 0, 0, 0);
48771 
48772 #ifndef OMIT_PROJ		/* PROJ.4 is strictly required to support KML */
48773     sqlite3_create_function_v2 (db, "AsKml", 1,
48774 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48775 				fnct_AsKml, 0, 0, 0);
48776     sqlite3_create_function_v2 (db, "AsKml", 2,
48777 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48778 				fnct_AsKml, 0, 0, 0);
48779     sqlite3_create_function_v2 (db, "AsKml", 3,
48780 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48781 				fnct_AsKml, 0, 0, 0);
48782     sqlite3_create_function_v2 (db, "AsKml", 4,
48783 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48784 				fnct_AsKml, 0, 0, 0);
48785 #endif /* end including PROJ.4 */
48786 
48787     sqlite3_create_function_v2 (db, "AsGml", 1,
48788 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48789 				fnct_AsGml, 0, 0, 0);
48790     sqlite3_create_function_v2 (db, "AsGml", 2,
48791 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48792 				fnct_AsGml, 0, 0, 0);
48793     sqlite3_create_function_v2 (db, "AsGml", 3,
48794 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48795 				fnct_AsGml, 0, 0, 0);
48796     sqlite3_create_function_v2 (db, "GeomFromGml", 1,
48797 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48798 				fnct_FromGml, 0, 0, 0);
48799     sqlite3_create_function_v2 (db, "AsGeoJSON", 1,
48800 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48801 				fnct_AsGeoJSON, 0, 0, 0);
48802     sqlite3_create_function_v2 (db, "AsGeoJSON", 2,
48803 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48804 				fnct_AsGeoJSON, 0, 0, 0);
48805     sqlite3_create_function_v2 (db, "AsGeoJSON", 3,
48806 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48807 				fnct_AsGeoJSON, 0, 0, 0);
48808     sqlite3_create_function_v2 (db, "GeomFromGeoJSON", 1,
48809 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48810 				fnct_FromGeoJSON, 0, 0, 0);
48811     sqlite3_create_function_v2 (db, "GeomFromKml", 1,
48812 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48813 				fnct_FromKml, 0, 0, 0);
48814     sqlite3_create_function_v2 (db, "AsFGF", 2,
48815 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48816 				fnct_AsFGF, 0, 0, 0);
48817     sqlite3_create_function_v2 (db, "GeomFromEWKB", 1,
48818 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48819 				fnct_FromEWKB, 0, 0, 0);
48820     sqlite3_create_function_v2 (db, "AsEWKB", 1,
48821 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48822 				fnct_ToEWKB, 0, 0, 0);
48823     sqlite3_create_function_v2 (db, "AsEWKT", 1,
48824 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48825 				fnct_ToEWKT, 0, 0, 0);
48826     sqlite3_create_function_v2 (db, "GeomFromEWKT", 1,
48827 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48828 				fnct_FromEWKT, 0, 0, 0);
48829     sqlite3_create_function_v2 (db, "AsBinary", 1,
48830 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48831 				fnct_AsBinary, 0, 0, 0);
48832     sqlite3_create_function_v2 (db, "ST_AsBinary", 1,
48833 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48834 				fnct_AsBinary, 0, 0, 0);
48835     sqlite3_create_function_v2 (db, "GeomFromText", 1,
48836 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48837 				fnct_GeomFromText1, 0, 0, 0);
48838     sqlite3_create_function_v2 (db, "GeomFromText", 2,
48839 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48840 				fnct_GeomFromText2, 0, 0, 0);
48841     sqlite3_create_function_v2 (db, "GeometryFromText", 1,
48842 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48843 				fnct_GeomFromText1, 0, 0, 0);
48844     sqlite3_create_function_v2 (db, "GeometryFromText", 2,
48845 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48846 				fnct_GeomFromText2, 0, 0, 0);
48847     sqlite3_create_function_v2 (db, "GeomCollFromText", 1,
48848 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48849 				fnct_GeomCollFromText1, 0, 0, 0);
48850     sqlite3_create_function_v2 (db, "GeomCollFromText", 2,
48851 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48852 				fnct_GeomCollFromText2, 0, 0, 0);
48853     sqlite3_create_function_v2 (db, "GeometryCollectionFromText", 1,
48854 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48855 				fnct_GeomCollFromText1, 0, 0, 0);
48856     sqlite3_create_function_v2 (db, "GeometryCollectionFromText", 2,
48857 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48858 				fnct_GeomCollFromText2, 0, 0, 0);
48859     sqlite3_create_function_v2 (db, "PointFromText", 1,
48860 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48861 				fnct_PointFromText1, 0, 0, 0);
48862     sqlite3_create_function_v2 (db, "PointFromText", 2,
48863 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48864 				fnct_PointFromText2, 0, 0, 0);
48865     sqlite3_create_function_v2 (db, "LineFromText", 1,
48866 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48867 				fnct_LineFromText1, 0, 0, 0);
48868     sqlite3_create_function_v2 (db, "LineFromText", 2,
48869 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48870 				fnct_LineFromText2, 0, 0, 0);
48871     sqlite3_create_function_v2 (db, "LineStringFromText", 1,
48872 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48873 				fnct_LineFromText1, 0, 0, 0);
48874     sqlite3_create_function_v2 (db, "LineStringFromText", 2,
48875 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48876 				fnct_LineFromText2, 0, 0, 0);
48877     sqlite3_create_function_v2 (db, "PolyFromText", 1,
48878 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48879 				fnct_PolyFromText1, 0, 0, 0);
48880     sqlite3_create_function_v2 (db, "PolyFromText", 2,
48881 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48882 				fnct_PolyFromText2, 0, 0, 0);
48883     sqlite3_create_function_v2 (db, "PolygonFromText", 1,
48884 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48885 				fnct_PolyFromText1, 0, 0, 0);
48886     sqlite3_create_function_v2 (db, "PolygonFromText", 2,
48887 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48888 				fnct_PolyFromText2, 0, 0, 0);
48889     sqlite3_create_function_v2 (db, "MPointFromText", 1,
48890 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48891 				fnct_MPointFromText1, 0, 0, 0);
48892     sqlite3_create_function_v2 (db, "MPointFromText", 2,
48893 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48894 				fnct_MPointFromText2, 0, 0, 0);
48895     sqlite3_create_function_v2 (db, "MultiPointFromText", 1,
48896 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48897 				fnct_MPointFromText1, 0, 0, 0);
48898     sqlite3_create_function_v2 (db, "MultiPointFromText", 2,
48899 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48900 				fnct_MPointFromText2, 0, 0, 0);
48901     sqlite3_create_function_v2 (db, "MLineFromText", 1,
48902 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48903 				fnct_MLineFromText1, 0, 0, 0);
48904     sqlite3_create_function_v2 (db, "MLineFromText", 2,
48905 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48906 				fnct_MLineFromText2, 0, 0, 0);
48907     sqlite3_create_function_v2 (db, "MultiLineStringFromText", 1,
48908 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48909 				fnct_MLineFromText1, 0, 0, 0);
48910     sqlite3_create_function_v2 (db, "MultiLineStringFromText", 2,
48911 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48912 				fnct_MLineFromText2, 0, 0, 0);
48913     sqlite3_create_function_v2 (db, "MPolyFromText", 1,
48914 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48915 				fnct_MPolyFromText1, 0, 0, 0);
48916     sqlite3_create_function_v2 (db, "MPolyFromText", 2,
48917 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48918 				fnct_MPolyFromText2, 0, 0, 0);
48919     sqlite3_create_function_v2 (db, "MultiPolygonFromText", 1,
48920 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48921 				fnct_MPolyFromText1, 0, 0, 0);
48922     sqlite3_create_function_v2 (db, "MultiPolygonFromText", 2,
48923 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48924 				fnct_MPolyFromText2, 0, 0, 0);
48925     sqlite3_create_function_v2 (db, "GeomFromWKB", 1,
48926 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48927 				fnct_GeomFromWkb1, 0, 0, 0);
48928     sqlite3_create_function_v2 (db, "GeomFromWKB", 2,
48929 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48930 				fnct_GeomFromWkb2, 0, 0, 0);
48931     sqlite3_create_function_v2 (db, "GeometryFromWKB", 1,
48932 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48933 				fnct_GeomFromWkb1, 0, 0, 0);
48934     sqlite3_create_function_v2 (db, "GeometryFromWKB", 2,
48935 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48936 				fnct_GeomFromWkb2, 0, 0, 0);
48937     sqlite3_create_function_v2 (db, "GeomCollFromWKB", 1,
48938 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48939 				fnct_GeomCollFromWkb1, 0, 0, 0);
48940     sqlite3_create_function_v2 (db, "GeomCollFromWKB", 2,
48941 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48942 				fnct_GeomCollFromWkb2, 0, 0, 0);
48943     sqlite3_create_function_v2 (db, "GeometryCollectionFromWKB", 1,
48944 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48945 				fnct_GeomCollFromWkb1, 0, 0, 0);
48946     sqlite3_create_function_v2 (db, "GeometryCollectionFromWKB", 2,
48947 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48948 				fnct_GeomCollFromWkb2, 0, 0, 0);
48949     sqlite3_create_function_v2 (db, "PointFromWKB", 1,
48950 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48951 				fnct_PointFromWkb1, 0, 0, 0);
48952     sqlite3_create_function_v2 (db, "PointFromWKB", 2,
48953 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48954 				fnct_PointFromWkb2, 0, 0, 0);
48955     sqlite3_create_function_v2 (db, "LineFromWKB", 1,
48956 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48957 				fnct_LineFromWkb1, 0, 0, 0);
48958     sqlite3_create_function_v2 (db, "LineFromWKB", 2,
48959 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48960 				fnct_LineFromWkb2, 0, 0, 0);
48961     sqlite3_create_function_v2 (db, "LineStringFromWKB", 1,
48962 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
48963 				fnct_LineFromWkb1, 0, 0, 0);
48964     sqlite3_create_function_v2 (db, "LineStringFromWKB", 2,
48965 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48966 				fnct_LineFromWkb2, 0, 0, 0);
48967     sqlite3_create_function_v2 (db, "PolyFromWKB", 1,
48968 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48969 				fnct_PolyFromWkb1, 0, 0, 0);
48970     sqlite3_create_function_v2 (db, "PolyFromWKB", 2,
48971 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48972 				fnct_PolyFromWkb2, 0, 0, 0);
48973     sqlite3_create_function_v2 (db, "PolygonFromWKB", 1,
48974 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48975 				fnct_PolyFromWkb1, 0, 0, 0);
48976     sqlite3_create_function_v2 (db, "PolygonFromWKB", 2,
48977 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48978 				fnct_PolyFromWkb2, 0, 0, 0);
48979     sqlite3_create_function_v2 (db, "MPointFromWKB", 1,
48980 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48981 				fnct_MPointFromWkb1, 0, 0, 0);
48982     sqlite3_create_function_v2 (db, "MPointFromWKB", 2,
48983 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48984 				fnct_MPointFromWkb2, 0, 0, 0);
48985     sqlite3_create_function_v2 (db, "MultiPointFromWKB", 1,
48986 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48987 				fnct_MPointFromWkb1, 0, 0, 0);
48988     sqlite3_create_function_v2 (db, "MultiPointFromWKB", 2,
48989 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48990 				fnct_MPointFromWkb2, 0, 0, 0);
48991     sqlite3_create_function_v2 (db, "MLineFromWKB", 1,
48992 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48993 				fnct_MLineFromWkb1, 0, 0, 0);
48994     sqlite3_create_function_v2 (db, "MLineFromWKB", 2,
48995 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48996 				fnct_MLineFromWkb2, 0, 0, 0);
48997     sqlite3_create_function_v2 (db, "MultiLineStringFromWKB", 1,
48998 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
48999 				fnct_MLineFromWkb1, 0, 0, 0);
49000     sqlite3_create_function_v2 (db, "MultiLineStringFromWKB", 2,
49001 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49002 				fnct_MLineFromWkb2, 0, 0, 0);
49003     sqlite3_create_function_v2 (db, "MPolyFromWKB", 1,
49004 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49005 				fnct_MPolyFromWkb1, 0, 0, 0);
49006     sqlite3_create_function_v2 (db, "MPolyFromWKB", 2,
49007 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49008 				fnct_MPolyFromWkb2, 0, 0, 0);
49009     sqlite3_create_function_v2 (db, "MultiPolygonFromWKB", 1,
49010 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49011 				fnct_MPolyFromWkb1, 0, 0, 0);
49012     sqlite3_create_function_v2 (db, "MultiPolygonFromWKB", 2,
49013 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49014 				fnct_MPolyFromWkb2, 0, 0, 0);
49015     sqlite3_create_function_v2 (db, "ST_WKTToSQL", 1,
49016 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49017 				fnct_WktToSql, 0, 0, 0);
49018     sqlite3_create_function_v2 (db, "ST_GeomFromText", 1,
49019 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49020 				fnct_GeomFromText1, 0, 0, 0);
49021     sqlite3_create_function_v2 (db, "ST_GeomFromText", 2,
49022 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49023 				fnct_GeomFromText2, 0, 0, 0);
49024     sqlite3_create_function_v2 (db, "ST_GeometryFromText", 1,
49025 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49026 				fnct_GeomFromText1, 0, 0, 0);
49027     sqlite3_create_function_v2 (db, "ST_GeometryFromText", 2,
49028 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49029 				fnct_GeomFromText2, 0, 0, 0);
49030     sqlite3_create_function_v2 (db, "ST_GeomCollFromText", 1,
49031 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49032 				fnct_GeomCollFromText1, 0, 0, 0);
49033     sqlite3_create_function_v2 (db, "ST_GeomCollFromText", 2,
49034 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49035 				fnct_GeomCollFromText2, 0, 0, 0);
49036     sqlite3_create_function_v2 (db, "ST_GeometryCollectionFromText", 1,
49037 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49038 				fnct_GeomCollFromText1, 0, 0, 0);
49039     sqlite3_create_function_v2 (db, "ST_GeometryCollectionFromText", 2,
49040 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49041 				fnct_GeomCollFromText2, 0, 0, 0);
49042     sqlite3_create_function_v2 (db, "ST_PointFromText", 1,
49043 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49044 				fnct_PointFromText1, 0, 0, 0);
49045     sqlite3_create_function_v2 (db, "ST_PointFromText", 2,
49046 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49047 				fnct_PointFromText2, 0, 0, 0);
49048     sqlite3_create_function_v2 (db, "ST_LineFromText", 1,
49049 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49050 				fnct_LineFromText1, 0, 0, 0);
49051     sqlite3_create_function_v2 (db, "ST_LineFromText", 2,
49052 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49053 				fnct_LineFromText2, 0, 0, 0);
49054     sqlite3_create_function_v2 (db, "ST_LineStringFromText", 1,
49055 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49056 				fnct_LineFromText1, 0, 0, 0);
49057     sqlite3_create_function_v2 (db, "ST_LineStringFromText", 2,
49058 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49059 				fnct_LineFromText2, 0, 0, 0);
49060     sqlite3_create_function_v2 (db, "ST_PolyFromText", 1,
49061 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49062 				fnct_PolyFromText1, 0, 0, 0);
49063     sqlite3_create_function_v2 (db, "ST_PolyFromText", 2,
49064 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49065 				fnct_PolyFromText2, 0, 0, 0);
49066     sqlite3_create_function_v2 (db, "ST_PolygonFromText", 1,
49067 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49068 				fnct_PolyFromText1, 0, 0, 0);
49069     sqlite3_create_function_v2 (db, "ST_PolygonFromText", 2,
49070 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49071 				fnct_PolyFromText2, 0, 0, 0);
49072     sqlite3_create_function_v2 (db, "ST_MPointFromText", 1,
49073 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49074 				fnct_MPointFromText1, 0, 0, 0);
49075     sqlite3_create_function_v2 (db, "ST_MPointFromText", 2,
49076 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49077 				fnct_MPointFromText2, 0, 0, 0);
49078     sqlite3_create_function_v2 (db, "ST_MultiPointFromText", 1,
49079 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49080 				fnct_MPointFromText1, 0, 0, 0);
49081     sqlite3_create_function_v2 (db, "ST_MultiPointFromText", 2,
49082 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49083 				fnct_MPointFromText2, 0, 0, 0);
49084     sqlite3_create_function_v2 (db, "ST_MLineFromText", 1,
49085 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49086 				fnct_MLineFromText1, 0, 0, 0);
49087     sqlite3_create_function_v2 (db, "ST_MLineFromText", 2,
49088 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49089 				fnct_MLineFromText2, 0, 0, 0);
49090     sqlite3_create_function_v2 (db, "ST_MultiLineStringFromText", 1,
49091 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49092 				fnct_MLineFromText1, 0, 0, 0);
49093     sqlite3_create_function_v2 (db, "ST_MultiLineStringFromText", 2,
49094 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49095 				fnct_MLineFromText2, 0, 0, 0);
49096     sqlite3_create_function_v2 (db, "ST_MPolyFromText", 1,
49097 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49098 				fnct_MPolyFromText1, 0, 0, 0);
49099     sqlite3_create_function_v2 (db, "ST_MPolyFromText", 2,
49100 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49101 				fnct_MPolyFromText2, 0, 0, 0);
49102     sqlite3_create_function_v2 (db, "ST_MultiPolygonFromText", 1,
49103 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49104 				fnct_MPolyFromText1, 0, 0, 0);
49105     sqlite3_create_function_v2 (db, "ST_MultiPolygonFromText", 2,
49106 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49107 				fnct_MPolyFromText2, 0, 0, 0);
49108     sqlite3_create_function_v2 (db, "ST_WKBToSQL", 1,
49109 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49110 				fnct_WkbToSql, 0, 0, 0);
49111     sqlite3_create_function_v2 (db, "ST_GeomFromWKB", 1,
49112 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49113 				fnct_GeomFromWkb1, 0, 0, 0);
49114     sqlite3_create_function_v2 (db, "ST_GeomFromWKB", 2,
49115 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49116 				fnct_GeomFromWkb2, 0, 0, 0);
49117     sqlite3_create_function_v2 (db, "ST_GeometryFromWKB", 1,
49118 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49119 				fnct_GeomFromWkb1, 0, 0, 0);
49120     sqlite3_create_function_v2 (db, "ST_GeometryFromWKB", 2,
49121 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49122 				fnct_GeomFromWkb2, 0, 0, 0);
49123     sqlite3_create_function_v2 (db, "ST_GeomCollFromWKB", 1,
49124 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49125 				fnct_GeomCollFromWkb1, 0, 0, 0);
49126     sqlite3_create_function_v2 (db, "ST_GeomCollFromWKB", 2,
49127 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49128 				fnct_GeomCollFromWkb2, 0, 0, 0);
49129     sqlite3_create_function_v2 (db, "ST_GeometryCollectionFromWKB", 1,
49130 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49131 				fnct_GeomCollFromWkb1, 0, 0, 0);
49132     sqlite3_create_function_v2 (db, "ST_GeometryCollectionFromWKB", 2,
49133 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49134 				fnct_GeomCollFromWkb2, 0, 0, 0);
49135     sqlite3_create_function_v2 (db, "ST_PointFromWKB", 1,
49136 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49137 				fnct_PointFromWkb1, 0, 0, 0);
49138     sqlite3_create_function_v2 (db, "ST_PointFromWKB", 2,
49139 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49140 				fnct_PointFromWkb2, 0, 0, 0);
49141     sqlite3_create_function_v2 (db, "ST_LineFromWKB", 1,
49142 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49143 				fnct_LineFromWkb1, 0, 0, 0);
49144     sqlite3_create_function_v2 (db, "ST_LineFromWKB", 2,
49145 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49146 				fnct_LineFromWkb2, 0, 0, 0);
49147     sqlite3_create_function_v2 (db, "ST_LineStringFromWKB", 1,
49148 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49149 				fnct_LineFromWkb1, 0, 0, 0);
49150     sqlite3_create_function_v2 (db, "ST_LineStringFromWKB", 2,
49151 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49152 				fnct_LineFromWkb2, 0, 0, 0);
49153     sqlite3_create_function_v2 (db, "ST_PolyFromWKB", 1,
49154 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49155 				fnct_PolyFromWkb1, 0, 0, 0);
49156     sqlite3_create_function_v2 (db, "ST_PolyFromWKB", 2,
49157 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49158 				fnct_PolyFromWkb2, 0, 0, 0);
49159     sqlite3_create_function_v2 (db, "ST_PolygonFromWKB", 1,
49160 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49161 				fnct_PolyFromWkb1, 0, 0, 0);
49162     sqlite3_create_function_v2 (db, "ST_PolygonFromWKB", 2,
49163 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49164 				fnct_PolyFromWkb2, 0, 0, 0);
49165     sqlite3_create_function_v2 (db, "ST_MPointFromWKB", 1,
49166 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49167 				fnct_MPointFromWkb1, 0, 0, 0);
49168     sqlite3_create_function_v2 (db, "ST_MPointFromWKB", 2,
49169 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49170 				fnct_MPointFromWkb2, 0, 0, 0);
49171     sqlite3_create_function_v2 (db, "ST_MultiPointFromWKB", 1,
49172 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49173 				fnct_MPointFromWkb1, 0, 0, 0);
49174     sqlite3_create_function_v2 (db, "ST_MultiPointFromWKB", 2,
49175 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49176 				fnct_MPointFromWkb2, 0, 0, 0);
49177     sqlite3_create_function_v2 (db, "ST_MLineFromWKB", 1,
49178 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49179 				fnct_MLineFromWkb1, 0, 0, 0);
49180     sqlite3_create_function_v2 (db, "ST_MLineFromWKB", 2,
49181 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49182 				fnct_MLineFromWkb2, 0, 0, 0);
49183     sqlite3_create_function_v2 (db, "ST_MultiLineStringFromWKB", 1,
49184 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49185 				fnct_MLineFromWkb1, 0, 0, 0);
49186     sqlite3_create_function_v2 (db, "ST_MultiLineStringFromWKB", 2,
49187 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49188 				fnct_MLineFromWkb2, 0, 0, 0);
49189     sqlite3_create_function_v2 (db, "ST_MPolyFromWKB", 1,
49190 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49191 				fnct_MPolyFromWkb1, 0, 0, 0);
49192     sqlite3_create_function_v2 (db, "ST_MPolyFromWKB", 2,
49193 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49194 				fnct_MPolyFromWkb2, 0, 0, 0);
49195     sqlite3_create_function_v2 (db, "ST_MultiPolygonFromWKB", 1,
49196 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49197 				fnct_MPolyFromWkb1, 0, 0, 0);
49198     sqlite3_create_function_v2 (db, "ST_MultiPolygonFromWKB", 2,
49199 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49200 				fnct_MPolyFromWkb2, 0, 0, 0);
49201     sqlite3_create_function_v2 (db, "GeomFromFGF", 1,
49202 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49203 				fnct_GeometryFromFGF1, 0, 0, 0);
49204     sqlite3_create_function_v2 (db, "GeomFromFGF", 2,
49205 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49206 				fnct_GeometryFromFGF2, 0, 0, 0);
49207     sqlite3_create_function_v2 (db, "CompressGeometry", 1,
49208 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49209 				fnct_CompressGeometry, 0, 0, 0);
49210     sqlite3_create_function_v2 (db, "UncompressGeometry", 1,
49211 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49212 				fnct_UncompressGeometry, 0, 0, 0);
49213     sqlite3_create_function_v2 (db, "SanitizeGeometry", 1,
49214 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49215 				fnct_SanitizeGeometry, 0, 0, 0);
49216     sqlite3_create_function_v2 (db, "EnsureClosedRings", 1,
49217 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49218 				fnct_EnsureClosedRings, 0, 0, 0);
49219     sqlite3_create_function_v2 (db, "RemoveRepeatedPoints", 1,
49220 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49221 				fnct_RemoveRepeatedPoints, 0, 0, 0);
49222     sqlite3_create_function_v2 (db, "RemoveRepeatedPoints", 2,
49223 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49224 				fnct_RemoveRepeatedPoints, 0, 0, 0);
49225     sqlite3_create_function_v2 (db, "IsInteger", 1,
49226 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49227 				fnct_IsInteger, 0, 0, 0);
49228     sqlite3_create_function_v2 (db, "IsDecimalNumber", 1,
49229 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49230 				fnct_IsDecimalNumber, 0, 0, 0);
49231     sqlite3_create_function_v2 (db, "IsNumber", 1,
49232 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49233 				fnct_IsNumber, 0, 0, 0);
49234     sqlite3_create_function_v2 (db, "CastToInteger", 1,
49235 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49236 				fnct_CastToInteger, 0, 0, 0);
49237     sqlite3_create_function_v2 (db, "CastToDouble", 1,
49238 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49239 				fnct_CastToDouble, 0, 0, 0);
49240     sqlite3_create_function_v2 (db, "CastToText", 1,
49241 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49242 				fnct_CastToText, 0, 0, 0);
49243     sqlite3_create_function_v2 (db, "CastToText", 2,
49244 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49245 				fnct_CastToText, 0, 0, 0);
49246     sqlite3_create_function_v2 (db, "CastToBlob", 1,
49247 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49248 				fnct_CastToBlob, 0, 0, 0);
49249     sqlite3_create_function_v2 (db, "CastToBlob", 2,
49250 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49251 				fnct_CastToBlob, 0, 0, 0);
49252     sqlite3_create_function_v2 (db, "ForceAsNull", 2,
49253 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49254 				fnct_ForceAsNull, 0, 0, 0);
49255     sqlite3_create_function_v2 (db, "CreateUUID", 0, SQLITE_UTF8, 0,
49256 				fnct_CreateUUID, 0, 0, 0);
49257     sqlite3_create_function_v2 (db, "MD5Checksum", 1,
49258 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49259 				fnct_MD5Checksum, 0, 0, 0);
49260     sqlite3_create_function_v2 (db, "MD5TotalChecksum", 1,
49261 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
49262 				fnct_MD5TotalChecksum_step,
49263 				fnct_MD5TotalChecksum_final, 0);
49264 
49265     sqlite3_create_function_v2 (db, "RemoveExtraSpaces", 1,
49266 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49267 				fnct_RemoveExtraSpaces, 0, 0, 0);
49268 
49269 #if OMIT_ICONV == 0		/* ICONV is absolutely required */
49270 
49271     sqlite3_create_function_v2 (db, "EncodeURL", 1,
49272 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49273 				fnct_EncodeURL, 0, 0, 0);
49274     sqlite3_create_function_v2 (db, "EncodeURL", 2,
49275 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49276 				fnct_EncodeURL, 0, 0, 0);
49277     sqlite3_create_function_v2 (db, "DecodeURL", 1,
49278 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49279 				fnct_DecodeURL, 0, 0, 0);
49280     sqlite3_create_function_v2 (db, "DecodeURL", 2,
49281 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49282 				fnct_DecodeURL, 0, 0, 0);
49283 
49284 #ifdef ENABLE_MINIZIP		/* only if MINIZIP is enabled */
49285     sqlite3_create_function_v2 (db, "Zipfile_NumSHP", 1,
49286 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49287 				fnct_Zipfile_NumSHP, 0, 0, 0);
49288     sqlite3_create_function_v2 (db, "Zipfile_ShpN", 2,
49289 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49290 				fnct_Zipfile_ShpN, 0, 0, 0);
49291     sqlite3_create_function_v2 (db, "Zipfile_NumDBF", 1,
49292 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49293 				fnct_Zipfile_NumDBF, 0, 0, 0);
49294     sqlite3_create_function_v2 (db, "Zipfile_DbfN", 2,
49295 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49296 				fnct_Zipfile_DbfN, 0, 0, 0);
49297 #endif /* end MINIZIP */
49298 
49299 #endif /* ICONV enabled/disabled */
49300 
49301     sqlite3_create_function_v2 (db, "DirNameFromPath", 1,
49302 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49303 				fnct_DirNameFromPath, 0, 0, 0);
49304     sqlite3_create_function_v2 (db, "FullFileNameFromPath", 1,
49305 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49306 				fnct_FullFileNameFromPath, 0, 0, 0);
49307     sqlite3_create_function_v2 (db, "FileNameFromPath", 1,
49308 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49309 				fnct_FileNameFromPath, 0, 0, 0);
49310     sqlite3_create_function_v2 (db, "FileExtFromPath", 1,
49311 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49312 				fnct_FileExtFromPath, 0, 0, 0);
49313     sqlite3_create_function_v2 (db, "CastToPoint", 1,
49314 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49315 				fnct_CastToPoint, 0, 0, 0);
49316     sqlite3_create_function_v2 (db, "CastToLinestring", 1,
49317 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49318 				fnct_CastToLinestring, 0, 0, 0);
49319     sqlite3_create_function_v2 (db, "CastToPolygon", 1,
49320 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49321 				fnct_CastToPolygon, 0, 0, 0);
49322     sqlite3_create_function_v2 (db, "CastToMultiPoint", 1,
49323 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49324 				fnct_CastToMultiPoint, 0, 0, 0);
49325     sqlite3_create_function_v2 (db, "CastToMultiLinestring", 1,
49326 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49327 				fnct_CastToMultiLinestring, 0, 0, 0);
49328     sqlite3_create_function_v2 (db, "CastToMultiPolygon", 1,
49329 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49330 				fnct_CastToMultiPolygon, 0, 0, 0);
49331     sqlite3_create_function_v2 (db, "CastToGeometryCollection", 1,
49332 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49333 				fnct_CastToGeometryCollection, 0, 0, 0);
49334     sqlite3_create_function_v2 (db, "CastToMulti", 1,
49335 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49336 				fnct_CastToMulti, 0, 0, 0);
49337     sqlite3_create_function_v2 (db, "ST_Multi", 1,
49338 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49339 				fnct_CastToMulti, 0, 0, 0);
49340     sqlite3_create_function_v2 (db, "CastToSingle", 1,
49341 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49342 				fnct_CastToSingle, 0, 0, 0);
49343     sqlite3_create_function_v2 (db, "CastToXY", 1,
49344 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49345 				fnct_CastToXY, 0, 0, 0);
49346     sqlite3_create_function_v2 (db, "CastToXYZ", 1,
49347 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49348 				fnct_CastToXYZ, 0, 0, 0);
49349     sqlite3_create_function_v2 (db, "CastToXYZ", 2,
49350 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49351 				fnct_CastToXYZ, 0, 0, 0);
49352     sqlite3_create_function_v2 (db, "CastToXYM", 1,
49353 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49354 				fnct_CastToXYM, 0, 0, 0);
49355     sqlite3_create_function_v2 (db, "CastToXYM", 2,
49356 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49357 				fnct_CastToXYM, 0, 0, 0);
49358     sqlite3_create_function_v2 (db, "CastToXYZM", 1,
49359 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49360 				fnct_CastToXYZM, 0, 0, 0);
49361     sqlite3_create_function_v2 (db, "CastToXYZM", 3,
49362 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49363 				fnct_CastToXYZM, 0, 0, 0);
49364     sqlite3_create_function_v2 (db, "ExtractMultiPoint", 1,
49365 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49366 				fnct_ExtractMultiPoint, 0, 0, 0);
49367     sqlite3_create_function_v2 (db, "ExtractMultiLinestring", 1,
49368 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49369 				fnct_ExtractMultiLinestring, 0, 0, 0);
49370     sqlite3_create_function_v2 (db, "ExtractMultiPolygon", 1,
49371 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49372 				fnct_ExtractMultiPolygon, 0, 0, 0);
49373     sqlite3_create_function_v2 (db, "ST_Reverse", 1,
49374 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49375 				fnct_Reverse, 0, 0, 0);
49376     sqlite3_create_function_v2 (db, "ST_ForceLHR", 1,
49377 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49378 				fnct_ForcePolygonCW, 0, 0, 0);
49379     sqlite3_create_function_v2 (db, "ST_ForcePolygonCW", 1,
49380 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49381 				fnct_ForcePolygonCW, 0, 0, 0);
49382     sqlite3_create_function_v2 (db, "ST_ForcePolygonCCW", 1,
49383 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49384 				fnct_ForcePolygonCCW, 0, 0, 0);
49385     sqlite3_create_function_v2 (db, "ST_IsPolygonCW", 1,
49386 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49387 				fnct_IsPolygonCW, 0, 0, 0);
49388     sqlite3_create_function_v2 (db, "ST_IsPolygonCCW", 1,
49389 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49390 				fnct_IsPolygonCCW, 0, 0, 0);
49391     sqlite3_create_function_v2 (db, "Dimension", 1,
49392 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49393 				fnct_Dimension, 0, 0, 0);
49394     sqlite3_create_function_v2 (db, "ST_Dimension", 1,
49395 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49396 				fnct_Dimension, 0, 0, 0);
49397     sqlite3_create_function_v2 (db, "CoordDimension", 1,
49398 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49399 				fnct_CoordDimension, 0, 0, 0);
49400     sqlite3_create_function_v2 (db, "ST_NDims", 1,
49401 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49402 				fnct_NDims, 0, 0, 0);
49403     sqlite3_create_function_v2 (db, "GeometryType", 1,
49404 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49405 				fnct_GeometryType, 0, 0, 0);
49406     sqlite3_create_function_v2 (db, "ST_GeometryType", 1,
49407 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49408 				fnct_GeometryType, 0, 0, 0);
49409     sqlite3_create_function_v2 (db, "GeometryAliasType", 1,
49410 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49411 				fnct_GeometryAliasType, 0, 0, 0);
49412     sqlite3_create_function_v2 (db, "SridFromAuthCRS", 2,
49413 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49414 				fnct_SridFromAuthCRS, 0, 0, 0);
49415     sqlite3_create_function_v2 (db, "SRID", 1,
49416 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49417 				fnct_SRID, 0, 0, 0);
49418     sqlite3_create_function_v2 (db, "ST_SRID", 1,
49419 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49420 				fnct_SRID, 0, 0, 0);
49421     sqlite3_create_function_v2 (db, "SetSRID", 2,
49422 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49423 				fnct_SetSRID, 0, 0, 0);
49424     sqlite3_create_function_v2 (db, "IsEmpty", 1,
49425 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49426 				fnct_IsEmpty, 0, 0, 0);
49427     sqlite3_create_function_v2 (db, "ST_IsEmpty", 1,
49428 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49429 				fnct_IsEmpty, 0, 0, 0);
49430     sqlite3_create_function_v2 (db, "ST_Is3D", 1,
49431 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49432 				fnct_Is3D, 0, 0, 0);
49433     sqlite3_create_function_v2 (db, "ST_IsMeasured", 1,
49434 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49435 				fnct_IsMeasured, 0, 0, 0);
49436     sqlite3_create_function_v2 (db, "Envelope", 1,
49437 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49438 				fnct_Envelope, 0, 0, 0);
49439     sqlite3_create_function_v2 (db, "ST_Envelope", 1,
49440 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49441 				fnct_Envelope, 0, 0, 0);
49442     sqlite3_create_function_v2 (db, "ST_Expand", 2,
49443 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49444 				fnct_Expand, 0, 0, 0);
49445     sqlite3_create_function_v2 (db, "X", 1,
49446 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49447 				fnct_X, 0, 0, 0);
49448     sqlite3_create_function_v2 (db, "Y", 1,
49449 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49450 				fnct_Y, 0, 0, 0);
49451     sqlite3_create_function_v2 (db, "Z", 1,
49452 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49453 				fnct_Z, 0, 0, 0);
49454     sqlite3_create_function_v2 (db, "M", 1,
49455 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49456 				fnct_M, 0, 0, 0);
49457     sqlite3_create_function_v2 (db, "ST_X", 1,
49458 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49459 				fnct_X, 0, 0, 0);
49460     sqlite3_create_function_v2 (db, "ST_Y", 1,
49461 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49462 				fnct_Y, 0, 0, 0);
49463     sqlite3_create_function_v2 (db, "ST_Z", 1,
49464 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49465 				fnct_Z, 0, 0, 0);
49466     sqlite3_create_function_v2 (db, "ST_M", 1,
49467 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49468 				fnct_M, 0, 0, 0);
49469     sqlite3_create_function_v2 (db, "ST_MinX", 1,
49470 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49471 				fnct_MbrMinX, 0, 0, 0);
49472     sqlite3_create_function_v2 (db, "ST_MinY", 1,
49473 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49474 				fnct_MbrMinY, 0, 0, 0);
49475     sqlite3_create_function_v2 (db, "ST_MinZ", 1,
49476 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49477 				fnct_MinZ, 0, 0, 0);
49478     sqlite3_create_function_v2 (db, "ST_MinZ", 2,
49479 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49480 				fnct_MinZ, 0, 0, 0);
49481     sqlite3_create_function_v2 (db, "ST_MinM", 1,
49482 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49483 				fnct_MinM, 0, 0, 0);
49484     sqlite3_create_function_v2 (db, "ST_MinM", 2,
49485 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49486 				fnct_MinM, 0, 0, 0);
49487     sqlite3_create_function_v2 (db, "ST_MaxX", 1,
49488 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49489 				fnct_MbrMaxX, 0, 0, 0);
49490     sqlite3_create_function_v2 (db, "ST_MaxY", 1,
49491 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49492 				fnct_MbrMaxY, 0, 0, 0);
49493     sqlite3_create_function_v2 (db, "ST_MaxZ", 1,
49494 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49495 				fnct_MaxZ, 0, 0, 0);
49496     sqlite3_create_function_v2 (db, "ST_MaxZ", 2,
49497 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49498 				fnct_MaxZ, 0, 0, 0);
49499     sqlite3_create_function_v2 (db, "ST_MaxM", 1,
49500 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49501 				fnct_MaxM, 0, 0, 0);
49502     sqlite3_create_function_v2 (db, "ST_MaxM", 2,
49503 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49504 				fnct_MaxM, 0, 0, 0);
49505     sqlite3_create_function_v2 (db, "NumPoints", 1,
49506 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49507 				fnct_NumPoints, 0, 0, 0);
49508     sqlite3_create_function_v2 (db, "ST_NumPoints", 1,
49509 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49510 				fnct_NumPoints, 0, 0, 0);
49511     sqlite3_create_function_v2 (db, "StartPoint", 1,
49512 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49513 				fnct_StartPoint, 0, 0, 0);
49514     sqlite3_create_function_v2 (db, "EndPoint", 1,
49515 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49516 				fnct_EndPoint, 0, 0, 0);
49517     sqlite3_create_function_v2 (db, "ST_StartPoint", 1,
49518 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49519 				fnct_StartPoint, 0, 0, 0);
49520     sqlite3_create_function_v2 (db, "ST_EndPoint", 1,
49521 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49522 				fnct_EndPoint, 0, 0, 0);
49523     sqlite3_create_function_v2 (db, "PointN", 2,
49524 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49525 				fnct_PointN, 0, 0, 0);
49526     sqlite3_create_function_v2 (db, "ST_PointN", 2,
49527 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49528 				fnct_PointN, 0, 0, 0);
49529     sqlite3_create_function_v2 (db, "ExteriorRing", 1,
49530 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49531 				fnct_ExteriorRing, 0, 0, 0);
49532     sqlite3_create_function_v2 (db, "ST_ExteriorRing", 1,
49533 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49534 				fnct_ExteriorRing, 0, 0, 0);
49535     sqlite3_create_function_v2 (db, "NumInteriorRing", 1,
49536 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49537 				fnct_NumInteriorRings, 0, 0, 0);
49538     sqlite3_create_function_v2 (db, "NumInteriorRings", 1,
49539 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49540 				fnct_NumInteriorRings, 0, 0, 0);
49541     sqlite3_create_function_v2 (db, "ST_NumInteriorRing", 1,
49542 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49543 				fnct_NumInteriorRings, 0, 0, 0);
49544     sqlite3_create_function_v2 (db, "InteriorRingN", 2,
49545 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49546 				fnct_InteriorRingN, 0, 0, 0);
49547     sqlite3_create_function_v2 (db, "ST_InteriorRingN", 2,
49548 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49549 				fnct_InteriorRingN, 0, 0, 0);
49550     sqlite3_create_function_v2 (db, "NumGeometries", 1,
49551 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49552 				fnct_NumGeometries, 0, 0, 0);
49553     sqlite3_create_function_v2 (db, "ST_NumGeometries", 1,
49554 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49555 				fnct_NumGeometries, 0, 0, 0);
49556     sqlite3_create_function_v2 (db, "GeometryN", 2,
49557 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49558 				fnct_GeometryN, 0, 0, 0);
49559     sqlite3_create_function_v2 (db, "ST_GeometryN", 2,
49560 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49561 				fnct_GeometryN, 0, 0, 0);
49562     sqlite3_create_function_v2 (db, "MBRContains", 2,
49563 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49564 				fnct_MbrContains, 0, 0, 0);
49565     sqlite3_create_function_v2 (db, "MbrDisjoint", 2,
49566 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49567 				fnct_MbrDisjoint, 0, 0, 0);
49568     sqlite3_create_function_v2 (db, "MBREqual", 2,
49569 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49570 				fnct_MbrEqual, 0, 0, 0);
49571     sqlite3_create_function_v2 (db, "MbrIntersects", 2,
49572 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49573 				fnct_MbrIntersects, 0, 0, 0);
49574     sqlite3_create_function_v2 (db, "ST_EnvIntersects", 2,
49575 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49576 				fnct_MbrIntersects, 0, 0, 0);
49577     sqlite3_create_function_v2 (db, "ST_EnvIntersects", 5,
49578 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49579 				fnct_EnvIntersects, 0, 0, 0);
49580     sqlite3_create_function_v2 (db, "ST_EnvelopesIntersects", 2,
49581 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49582 				fnct_MbrIntersects, 0, 0, 0);
49583     sqlite3_create_function_v2 (db, "ST_EnvelopesIntersects", 5,
49584 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49585 				fnct_EnvIntersects, 0, 0, 0);
49586     sqlite3_create_function_v2 (db, "MBROverlaps", 2,
49587 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49588 				fnct_MbrOverlaps, 0, 0, 0);
49589     sqlite3_create_function_v2 (db, "MbrTouches", 2,
49590 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49591 				fnct_MbrTouches, 0, 0, 0);
49592     sqlite3_create_function_v2 (db, "MbrWithin", 2,
49593 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49594 				fnct_MbrWithin, 0, 0, 0);
49595     sqlite3_create_function_v2 (db, "ShiftCoords", 3,
49596 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49597 				fnct_ShiftCoords, 0, 0, 0);
49598     sqlite3_create_function_v2 (db, "ShiftCoordinates", 3,
49599 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49600 				fnct_ShiftCoords, 0, 0, 0);
49601     sqlite3_create_function_v2 (db, "ST_Translate", 4,
49602 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49603 				fnct_Translate, 0, 0, 0);
49604     sqlite3_create_function_v2 (db, "ST_Shift_Longitude", 1,
49605 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49606 				fnct_ShiftLongitude, 0, 0, 0);
49607     sqlite3_create_function_v2 (db, "NormalizeLonLat", 1,
49608 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49609 				fnct_NormalizeLonLat, 0, 0, 0);
49610     sqlite3_create_function_v2 (db, "ScaleCoords", 2,
49611 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49612 				fnct_ScaleCoords, 0, 0, 0);
49613     sqlite3_create_function_v2 (db, "ScaleCoordinates", 2,
49614 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49615 				fnct_ScaleCoords, 0, 0, 0);
49616     sqlite3_create_function_v2 (db, "ScaleCoords", 3,
49617 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49618 				fnct_ScaleCoords, 0, 0, 0);
49619     sqlite3_create_function_v2 (db, "ScaleCoordinates", 3,
49620 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49621 				fnct_ScaleCoords, 0, 0, 0);
49622     sqlite3_create_function_v2 (db, "RotateCoords", 2,
49623 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49624 				fnct_RotateCoords, 0, 0, 0);
49625     sqlite3_create_function_v2 (db, "RotateCoordinates", 2,
49626 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49627 				fnct_RotateCoords, 0, 0, 0);
49628     sqlite3_create_function_v2 (db, "ReflectCoords", 3,
49629 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49630 				fnct_ReflectCoords, 0, 0, 0);
49631     sqlite3_create_function_v2 (db, "ReflectCoordinates", 3,
49632 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49633 				fnct_ReflectCoords, 0, 0, 0);
49634     sqlite3_create_function_v2 (db, "SwapCoords", 1,
49635 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49636 				fnct_SwapCoords, 0, 0, 0);
49637     sqlite3_create_function_v2 (db, "SwapCoordinates", 1,
49638 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49639 				fnct_SwapCoords, 0, 0, 0);
49640     sqlite3_create_function_v2 (db, "BuildMbr", 4,
49641 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49642 				fnct_BuildMbr1, 0, 0, 0);
49643     sqlite3_create_function_v2 (db, "BuildMbr", 5,
49644 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49645 				fnct_BuildMbr2, 0, 0, 0);
49646     sqlite3_create_function_v2 (db, "BuildCircleMbr", 3,
49647 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49648 				fnct_BuildCircleMbr1, 0, 0, 0);
49649     sqlite3_create_function_v2 (db, "BuildCircleMbr", 4,
49650 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49651 				fnct_BuildCircleMbr2, 0, 0, 0);
49652     sqlite3_create_function_v2 (db, "Extent", 1,
49653 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49654 				fnct_Extent_step, fnct_Extent_final, 0);
49655     sqlite3_create_function_v2 (db, "MbrMinX", 1,
49656 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49657 				fnct_MbrMinX, 0, 0, 0);
49658     sqlite3_create_function_v2 (db, "MbrMaxX", 1,
49659 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49660 				fnct_MbrMaxX, 0, 0, 0);
49661     sqlite3_create_function_v2 (db, "MbrMinY", 1,
49662 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49663 				fnct_MbrMinY, 0, 0, 0);
49664     sqlite3_create_function_v2 (db, "MbrMaxY", 1,
49665 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49666 				fnct_MbrMaxY, 0, 0, 0);
49667     sqlite3_create_function_v2 (db, "TinyPointEncode", 1,
49668 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49669 				fnct_tiny_point_encode, 0, 0, 0);
49670     sqlite3_create_function_v2 (db, "GeometryPointEncode", 1,
49671 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49672 				fnct_geometry_point_encode, 0, 0, 0);
49673     sqlite3_create_function_v2 (db, "ST_Point", 2,
49674 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49675 				fnct_MakePoint1, 0, 0, 0);
49676     sqlite3_create_function_v2 (db, "MakePoint", 2,
49677 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49678 				fnct_MakePoint1, 0, 0, 0);
49679     sqlite3_create_function_v2 (db, "MakePoint", 3,
49680 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49681 				fnct_MakePoint2, 0, 0, 0);
49682     sqlite3_create_function_v2 (db, "MakePointZ", 3,
49683 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49684 				fnct_MakePointZ1, 0, 0, 0);
49685     sqlite3_create_function_v2 (db, "MakePointZ", 4,
49686 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49687 				fnct_MakePointZ2, 0, 0, 0);
49688     sqlite3_create_function_v2 (db, "MakePointM", 3,
49689 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49690 				fnct_MakePointM1, 0, 0, 0);
49691     sqlite3_create_function_v2 (db, "MakePointM", 4,
49692 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49693 				fnct_MakePointM2, 0, 0, 0);
49694     sqlite3_create_function_v2 (db, "MakePointZM", 4,
49695 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49696 				fnct_MakePointZM1, 0, 0, 0);
49697     sqlite3_create_function_v2 (db, "MakePointZM", 5,
49698 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49699 				fnct_MakePointZM2, 0, 0, 0);
49700     sqlite3_create_function_v2 (db, "MakeLine", 1,
49701 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49702 				fnct_MakeLine_step, fnct_MakeLine_final, 0);
49703     sqlite3_create_function_v2 (db, "MakeLine", 2,
49704 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49705 				fnct_MakeLine, 0, 0, 0);
49706     sqlite3_create_function_v2 (db, "MakeCircle", 3,
49707 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49708 				fnct_MakeCircle, 0, 0, 0);
49709     sqlite3_create_function_v2 (db, "MakeCircle", 4,
49710 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49711 				fnct_MakeCircle, 0, 0, 0);
49712     sqlite3_create_function_v2 (db, "MakeCircle", 5,
49713 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49714 				fnct_MakeCircle, 0, 0, 0);
49715     sqlite3_create_function_v2 (db, "MakeEllipse", 4,
49716 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49717 				fnct_MakeEllipse, 0, 0, 0);
49718     sqlite3_create_function_v2 (db, "MakeEllipse", 5,
49719 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49720 				fnct_MakeEllipse, 0, 0, 0);
49721     sqlite3_create_function_v2 (db, "MakeEllipse", 6,
49722 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49723 				fnct_MakeEllipse, 0, 0, 0);
49724     sqlite3_create_function_v2 (db, "MakeArc", 5,
49725 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49726 				fnct_MakeArc, 0, 0, 0);
49727     sqlite3_create_function_v2 (db, "MakeArc", 6,
49728 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49729 				fnct_MakeArc, 0, 0, 0);
49730     sqlite3_create_function_v2 (db, "MakeArc", 7,
49731 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49732 				fnct_MakeArc, 0, 0, 0);
49733     sqlite3_create_function_v2 (db, "MakeEllipticArc", 6,
49734 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49735 				fnct_MakeEllipticArc, 0, 0, 0);
49736     sqlite3_create_function_v2 (db, "MakeEllipticArc", 7,
49737 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49738 				fnct_MakeEllipticArc, 0, 0, 0);
49739     sqlite3_create_function_v2 (db, "MakeEllipticArc", 8,
49740 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49741 				fnct_MakeEllipticArc, 0, 0, 0);
49742     sqlite3_create_function_v2 (db, "MakeCircularSector", 5,
49743 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49744 				fnct_MakeCircularSector, 0, 0, 0);
49745     sqlite3_create_function_v2 (db, "MakeCircularSector", 6,
49746 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49747 				fnct_MakeCircularSector, 0, 0, 0);
49748     sqlite3_create_function_v2 (db, "MakeCircularSector", 7,
49749 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49750 				fnct_MakeCircularSector, 0, 0, 0);
49751     sqlite3_create_function_v2 (db, "MakeCircularStripe", 6,
49752 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49753 				fnct_MakeCircularStripe, 0, 0, 0);
49754     sqlite3_create_function_v2 (db, "MakeCircularStripe", 7,
49755 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49756 				fnct_MakeCircularStripe, 0, 0, 0);
49757     sqlite3_create_function_v2 (db, "MakeCircularStripe", 8,
49758 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49759 				fnct_MakeCircularStripe, 0, 0, 0);
49760     sqlite3_create_function_v2 (db, "MakeEllipticSector", 6,
49761 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49762 				fnct_MakeEllipticSector, 0, 0, 0);
49763     sqlite3_create_function_v2 (db, "MakeEllipticSector", 7,
49764 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49765 				fnct_MakeEllipticSector, 0, 0, 0);
49766     sqlite3_create_function_v2 (db, "MakeEllipticSector", 8,
49767 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49768 				fnct_MakeEllipticSector, 0, 0, 0);
49769     sqlite3_create_function_v2 (db, "Collect", 1,
49770 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49771 				fnct_Collect_step, fnct_Collect_final, 0);
49772     sqlite3_create_function_v2 (db, "Collect", 2,
49773 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49774 				fnct_Collect, 0, 0, 0);
49775     sqlite3_create_function_v2 (db, "ST_Collect", 1,
49776 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49777 				fnct_Collect_step, fnct_Collect_final, 0);
49778     sqlite3_create_function_v2 (db, "ST_Collect", 2,
49779 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49780 				fnct_Collect, 0, 0, 0);
49781     sqlite3_create_function_v2 (db, "BuildMbrFilter", 4,
49782 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49783 				fnct_BuildMbrFilter, 0, 0, 0);
49784     sqlite3_create_function_v2 (db, "FilterMbrWithin", 4,
49785 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49786 				fnct_FilterMbrWithin, 0, 0, 0);
49787     sqlite3_create_function_v2 (db, "FilterMbrContains", 4,
49788 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49789 				fnct_FilterMbrContains, 0, 0, 0);
49790     sqlite3_create_function_v2 (db, "FilterMbrIntersects", 4,
49791 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49792 				fnct_FilterMbrIntersects, 0, 0, 0);
49793     sqlite3_create_function_v2 (db, "LinesFromRings", 1,
49794 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49795 				fnct_LinesFromRings, 0, 0, 0);
49796     sqlite3_create_function_v2 (db, "ST_LinesFromRings", 1,
49797 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49798 				fnct_LinesFromRings, 0, 0, 0);
49799     sqlite3_create_function_v2 (db, "LinesFromRings", 2,
49800 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49801 				fnct_LinesFromRings, 0, 0, 0);
49802     sqlite3_create_function_v2 (db, "ST_LinesFromRings", 2,
49803 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49804 				fnct_LinesFromRings, 0, 0, 0);
49805     sqlite3_create_function_v2 (db, "ST_NPoints", 1,
49806 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49807 				fnct_NPoints, 0, 0, 0);
49808     sqlite3_create_function_v2 (db, "ST_nrings", 1,
49809 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49810 				fnct_NRings, 0, 0, 0);
49811     sqlite3_create_function_v2 (db, "ToGARS", 1,
49812 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49813 				fnct_ToGARS, 0, 0, 0);
49814     sqlite3_create_function_v2 (db, "GARSMbr", 1,
49815 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49816 				fnct_GARSMbr, 0, 0, 0);
49817     sqlite3_create_function_v2 (db, "SnapToGrid", 2,
49818 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49819 				fnct_SnapToGrid, 0, 0, 0);
49820     sqlite3_create_function_v2 (db, "ST_SnapToGrid", 2,
49821 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49822 				fnct_SnapToGrid, 0, 0, 0);
49823     sqlite3_create_function_v2 (db, "SnapToGrid", 3,
49824 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49825 				fnct_SnapToGrid, 0, 0, 0);
49826     sqlite3_create_function_v2 (db, "ST_SnapToGrid", 3,
49827 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49828 				fnct_SnapToGrid, 0, 0, 0);
49829     sqlite3_create_function_v2 (db, "SnapToGrid", 5,
49830 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49831 				fnct_SnapToGrid, 0, 0, 0);
49832     sqlite3_create_function_v2 (db, "ST_SnapToGrid", 5,
49833 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49834 				fnct_SnapToGrid, 0, 0, 0);
49835     sqlite3_create_function_v2 (db, "SnapToGrid", 6,
49836 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49837 				fnct_SnapToGrid, 0, 0, 0);
49838     sqlite3_create_function_v2 (db, "ST_SnapToGrid", 6,
49839 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49840 				fnct_SnapToGrid, 0, 0, 0);
49841     sqlite3_create_function_v2 (db, "AddPoint", 2,
49842 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49843 				fnct_AddPoint, 0, 0, 0);
49844     sqlite3_create_function_v2 (db, "ST_AddPoint", 2,
49845 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49846 				fnct_AddPoint, 0, 0, 0);
49847     sqlite3_create_function_v2 (db, "AddPoint", 3,
49848 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49849 				fnct_AddPoint, 0, 0, 0);
49850     sqlite3_create_function_v2 (db, "ST_AddPoint", 3,
49851 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49852 				fnct_AddPoint, 0, 0, 0);
49853     sqlite3_create_function_v2 (db, "RemovePoint", 2,
49854 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49855 				fnct_RemovePoint, 0, 0, 0);
49856     sqlite3_create_function_v2 (db, "ST_RemovePoint", 2,
49857 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49858 				fnct_RemovePoint, 0, 0, 0);
49859     sqlite3_create_function_v2 (db, "SetPoint", 3,
49860 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49861 				fnct_SetPoint, 0, 0, 0);
49862     sqlite3_create_function_v2 (db, "ST_SetPoint", 3,
49863 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49864 				fnct_SetPoint, 0, 0, 0);
49865     sqlite3_create_function_v2 (db, "SetStartPoint", 2,
49866 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49867 				fnct_SetStartPoint, 0, 0, 0);
49868     sqlite3_create_function_v2 (db, "ST_SetStartPoint", 2,
49869 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49870 				fnct_SetStartPoint, 0, 0, 0);
49871     sqlite3_create_function_v2 (db, "SetEndPoint", 2,
49872 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49873 				fnct_SetEndPoint, 0, 0, 0);
49874     sqlite3_create_function_v2 (db, "ST_SetEndPoint", 2,
49875 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49876 				fnct_SetEndPoint, 0, 0, 0);
49877     sqlite3_create_function_v2 (db, "MakePolygon", 1,
49878 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49879 				fnct_MakePolygon, 0, 0, 0);
49880     sqlite3_create_function_v2 (db, "ST_MakePolygon", 1,
49881 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49882 				fnct_MakePolygon, 0, 0, 0);
49883     sqlite3_create_function_v2 (db, "MakePolygon", 2,
49884 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49885 				fnct_MakePolygon, 0, 0, 0);
49886     sqlite3_create_function_v2 (db, "ST_MakePolygon", 2,
49887 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49888 				fnct_MakePolygon, 0, 0, 0);
49889 
49890     sqlite3_create_function_v2 (db, "ATM_Create", 0,
49891 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49892 				fnct_AffineTransformMatrix_Create, 0, 0, 0);
49893     sqlite3_create_function_v2 (db, "ATM_Create", 6,
49894 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49895 				fnct_AffineTransformMatrix_Create, 0, 0, 0);
49896     sqlite3_create_function_v2 (db, "ATM_Create", 12,
49897 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49898 				fnct_AffineTransformMatrix_Create, 0, 0, 0);
49899     sqlite3_create_function_v2 (db, "ATM_CreateTranslate", 2,
49900 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49901 				fnct_AffineTransformMatrix_CreateTranslate, 0,
49902 				0, 0);
49903     sqlite3_create_function_v2 (db, "ATM_CreateTranslate", 3,
49904 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49905 				fnct_AffineTransformMatrix_CreateTranslate, 0,
49906 				0, 0);
49907     sqlite3_create_function_v2 (db, "ATM_CreateScale", 2,
49908 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49909 				fnct_AffineTransformMatrix_CreateScale, 0, 0,
49910 				0);
49911     sqlite3_create_function_v2 (db, "ATM_CreateScale", 3,
49912 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49913 				fnct_AffineTransformMatrix_CreateScale, 0, 0,
49914 				0);
49915     sqlite3_create_function_v2 (db, "ATM_CreateRotate", 1,
49916 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49917 				fnct_AffineTransformMatrix_CreateRotate, 0, 0,
49918 				0);
49919     sqlite3_create_function_v2 (db, "ATM_CreateXRoll", 1,
49920 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49921 				fnct_AffineTransformMatrix_CreateXRoll, 0, 0,
49922 				0);
49923     sqlite3_create_function_v2 (db, "ATM_CreateYRoll", 1,
49924 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49925 				fnct_AffineTransformMatrix_CreateYRoll, 0, 0,
49926 				0);
49927     sqlite3_create_function_v2 (db, "ATM_CreateZRoll", 1,
49928 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49929 				fnct_AffineTransformMatrix_CreateRotate, 0, 0,
49930 				0);
49931     sqlite3_create_function_v2 (db, "ATM_Multiply", 2,
49932 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49933 				fnct_AffineTransformMatrix_Multiply, 0, 0, 0);
49934     sqlite3_create_function_v2 (db, "ATM_Translate", 3,
49935 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49936 				fnct_AffineTransformMatrix_Translate, 0, 0, 0);
49937     sqlite3_create_function_v2 (db, "ATM_Translate", 4,
49938 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49939 				fnct_AffineTransformMatrix_Translate, 0, 0, 0);
49940     sqlite3_create_function_v2 (db, "ATM_Scale", 3,
49941 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49942 				fnct_AffineTransformMatrix_Scale, 0, 0, 0);
49943     sqlite3_create_function_v2 (db, "ATM_Scale", 4,
49944 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49945 				fnct_AffineTransformMatrix_Scale, 0, 0, 0);
49946     sqlite3_create_function_v2 (db, "ATM_Rotate", 2,
49947 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49948 				fnct_AffineTransformMatrix_Rotate, 0, 0, 0);
49949     sqlite3_create_function_v2 (db, "ATM_XRoll", 2,
49950 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49951 				fnct_AffineTransformMatrix_XRoll, 0, 0, 0);
49952     sqlite3_create_function_v2 (db, "ATM_YRoll", 2,
49953 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49954 				fnct_AffineTransformMatrix_YRoll, 0, 0, 0);
49955     sqlite3_create_function_v2 (db, "ATM_ZRoll", 2,
49956 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49957 				fnct_AffineTransformMatrix_Rotate, 0, 0, 0);
49958     sqlite3_create_function_v2 (db, "ATM_Determinant", 1,
49959 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49960 				fnct_AffineTransformMatrix_Determinant, 0, 0,
49961 				0);
49962     sqlite3_create_function_v2 (db, "ATM_IsInvertible", 1,
49963 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49964 				fnct_AffineTransformMatrix_IsInvertible, 0, 0,
49965 				0);
49966     sqlite3_create_function_v2 (db, "ATM_Invert", 1,
49967 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49968 				fnct_AffineTransformMatrix_Invert, 0, 0, 0);
49969     sqlite3_create_function_v2 (db, "ATM_IsValid", 1,
49970 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49971 				fnct_AffineTransformMatrix_IsValid, 0, 0, 0);
49972     sqlite3_create_function_v2 (db, "ATM_AsText", 1,
49973 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
49974 				fnct_AffineTransformMatrix_AsText, 0, 0, 0);
49975     sqlite3_create_function_v2 (db, "ATM_Transform", 2,
49976 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49977 				fnct_AffineTransformMatrix_GeometryTransform,
49978 				0, 0, 0);
49979     sqlite3_create_function_v2 (db, "ATM_Transform", 3,
49980 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49981 				fnct_AffineTransformMatrix_GeometryTransform,
49982 				0, 0, 0);
49983 
49984 #ifdef ENABLE_GCP		/* only if ControlPoints enabled */
49985     sqlite3_create_function_v2 (db, "GCP_Compute", 2,
49986 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49987 				fnct_GroundControlPoints_Compute_step,
49988 				fnct_GroundControlPoints_Compute_final, 0);
49989     sqlite3_create_function_v2 (db, "GCP_Compute", 3,
49990 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
49991 				fnct_GroundControlPoints_Compute_step,
49992 				fnct_GroundControlPoints_Compute_final, 0);
49993     sqlite3_create_function_v2 (db, "GCP_Transform", 2,
49994 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49995 				fnct_GroundControlPoints_GeometryTransform, 0,
49996 				0, 0);
49997     sqlite3_create_function_v2 (db, "GCP_Transform", 3,
49998 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
49999 				fnct_GroundControlPoints_GeometryTransform, 0,
50000 				0, 0);
50001     sqlite3_create_function_v2 (db, "GCP_IsValid", 1,
50002 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50003 				fnct_GroundControlPoints_IsValid, 0, 0, 0);
50004     sqlite3_create_function_v2 (db, "GCP_AsText", 1,
50005 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50006 				fnct_GroundControlPoints_AsText, 0, 0, 0);
50007     sqlite3_create_function_v2 (db, "GCP2ATM", 1,
50008 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50009 				fnct_GroundControlPoints_ToATM, 0, 0, 0);
50010 #endif /* end including GCP */
50011 
50012 #ifndef OMIT_GEOS		/* including GEOS */
50013     sqlite3_create_function_v2 (db, "BuildArea", 1,
50014 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50015 				fnct_BuildArea, 0, 0, 0);
50016     sqlite3_create_function_v2 (db, "ST_BuildArea", 1,
50017 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50018 				fnct_BuildArea, 0, 0, 0);
50019     sqlite3_create_function_v2 (db, "Polygonize", 1,
50020 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
50021 				fnct_Polygonize_step, fnct_Polygonize_final, 0);
50022     sqlite3_create_function_v2 (db, "ST_Polygonize", 1,
50023 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
50024 				fnct_Polygonize_step, fnct_Polygonize_final, 0);
50025 #endif /* end including GEOS */
50026 
50027     sqlite3_create_function_v2 (db, "DissolveSegments", 1,
50028 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50029 				fnct_DissolveSegments, 0, 0, 0);
50030     sqlite3_create_function_v2 (db, "ST_DissolveSegments", 1,
50031 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50032 				fnct_DissolveSegments, 0, 0, 0);
50033     sqlite3_create_function_v2 (db, "DissolvePoints", 1,
50034 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50035 				fnct_DissolvePoints, 0, 0, 0);
50036     sqlite3_create_function_v2 (db, "ST_DissolvePoints", 1,
50037 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50038 				fnct_DissolvePoints, 0, 0, 0);
50039     sqlite3_create_function_v2 (db, "CollectionExtract", 2,
50040 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50041 				fnct_CollectionExtract, 0, 0, 0);
50042     sqlite3_create_function_v2 (db, "ST_CollectionExtract", 2,
50043 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50044 				fnct_CollectionExtract, 0, 0, 0);
50045     sqlite3_create_function_v2 (db, "ST_InterpolatePoint", 2,
50046 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50047 				fnct_InterpolatePoint, 0, 0, 0);
50048     sqlite3_create_function_v2 (db, "ST_AddMeasure", 3,
50049 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50050 				fnct_AddMeasure, 0, 0, 0);
50051     sqlite3_create_function_v2 (db, "ST_Locate_Along_Measure", 2,
50052 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50053 				fnct_LocateBetweenMeasures, 0, 0, 0);
50054     sqlite3_create_function_v2 (db, "ST_LocateAlong", 2,
50055 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50056 				fnct_LocateBetweenMeasures, 0, 0, 0);
50057     sqlite3_create_function_v2 (db, "ST_Locate_Between_Measures", 3,
50058 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50059 				fnct_LocateBetweenMeasures, 0, 0, 0);
50060     sqlite3_create_function_v2 (db, "ST_LocateBetween", 3,
50061 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50062 				fnct_LocateBetweenMeasures, 0, 0, 0);
50063     sqlite3_create_function_v2 (db, "ST_IsValidTrajectory", 1,
50064 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50065 				fnct_IsValidTrajectory, 0, 0, 0);
50066     sqlite3_create_function_v2 (db, "ST_TrajectoryInterpolatePoint", 2,
50067 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
50068 				fnct_TrajectoryInterpolatePoint, 0, 0, 0);
50069 
50070 #ifndef OMIT_GEOCALLBACKS	/* supporting RTree geometry callbacks */
50071     sqlite3_rtree_geometry_callback (db, "RTreeWithin", fnct_RTreeIntersects,
50072 				     0);
50073     sqlite3_rtree_geometry_callback (db, "RTreeContains",
50074 				     fnct_RTreeIntersects, 0);
50075     sqlite3_rtree_geometry_callback (db, "RTreeIntersects",
50076 				     fnct_RTreeIntersects, 0);
50077     sqlite3_rtree_geometry_callback (db, "RTreeDistWithin",
50078 				     fnct_RTreeDistWithin, 0);
50079 #endif /* end RTree geometry callbacks */
50080 
50081 /* some BLOB/JPEG/EXIF functions */
50082     sqlite3_create_function_v2 (db, "IsGeometryBlob", 1,
50083 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50084 				fnct_IsGeometryBlob, 0, 0, 0);
50085     sqlite3_create_function_v2 (db, "IsCompressedGeometryBlob", 1,
50086 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50087 				fnct_IsCompressedGeometryBlob, 0, 0, 0);
50088     sqlite3_create_function_v2 (db, "IsTinyPointBlob", 1,
50089 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50090 				fnct_IsTinyPointBlob, 0, 0, 0);
50091     sqlite3_create_function_v2 (db, "IsZipBlob", 1,
50092 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50093 				fnct_IsZipBlob, 0, 0, 0);
50094     sqlite3_create_function_v2 (db, "IsPdfBlob", 1,
50095 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50096 				fnct_IsPdfBlob, 0, 0, 0);
50097     sqlite3_create_function_v2 (db, "IsTiffBlob", 1,
50098 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50099 				fnct_IsTiffBlob, 0, 0, 0);
50100     sqlite3_create_function_v2 (db, "IsGifBlob", 1,
50101 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50102 				fnct_IsGifBlob, 0, 0, 0);
50103     sqlite3_create_function_v2 (db, "IsPngBlob", 1,
50104 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50105 				fnct_IsPngBlob, 0, 0, 0);
50106     sqlite3_create_function_v2 (db, "IsJpegBlob", 1,
50107 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50108 				fnct_IsJpegBlob, 0, 0, 0);
50109     sqlite3_create_function_v2 (db, "IsExifBlob", 1,
50110 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50111 				fnct_IsExifBlob, 0, 0, 0);
50112     sqlite3_create_function_v2 (db, "IsExifGpsBlob", 1,
50113 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50114 				fnct_IsExifGpsBlob, 0, 0, 0);
50115     sqlite3_create_function_v2 (db, "IsWebpBlob", 1,
50116 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50117 				fnct_IsWebPBlob, 0, 0, 0);
50118     sqlite3_create_function_v2 (db, "IsJP2Blob", 1,
50119 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50120 				fnct_IsJP2Blob, 0, 0, 0);
50121     sqlite3_create_function_v2 (db, "GeomFromExifGpsBlob", 1,
50122 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50123 				fnct_GeomFromExifGpsBlob, 0, 0, 0);
50124     sqlite3_create_function_v2 (db, "GetMimeType", 1,
50125 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50126 				fnct_GetMimeType, 0, 0, 0);
50127     sqlite3_create_function_v2 (db, "CountUnsafeTriggers", 0,
50128 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50129 				fnct_CountUnsafeTriggers, 0, 0, 0);
50130     sqlite3_create_function_v2 (db, "CheckDuplicateRows", 1,
50131 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50132 				fnct_CheckDuplicateRows, 0, 0, 0);
50133     sqlite3_create_function_v2 (db, "RemoveDuplicateRows", 1,
50134 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50135 				fnct_RemoveDuplicateRows, 0, 0, 0);
50136     sqlite3_create_function_v2 (db, "RemoveDuplicateRows", 2,
50137 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50138 				fnct_RemoveDuplicateRows, 0, 0, 0);
50139     sqlite3_create_function_v2 (db, "ElementaryGeometries", 5,
50140 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50141 				fnct_ElementaryGeometries, 0, 0, 0);
50142     sqlite3_create_function_v2 (db, "ElementaryGeometries", 6,
50143 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50144 				fnct_ElementaryGeometries, 0, 0, 0);
50145     sqlite3_create_function_v2 (db, "ElementaryGeometries", 7,
50146 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50147 				fnct_ElementaryGeometries, 0, 0, 0);
50148     sqlite3_create_function_v2 (db, "ElementaryGeometries", 8,
50149 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50150 				fnct_ElementaryGeometries, 0, 0, 0);
50151     sqlite3_create_function_v2 (db, "ElementaryGeometries", 9,
50152 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50153 				fnct_ElementaryGeometries, 0, 0, 0);
50154     sqlite3_create_function_v2 (db, "ElementaryGeometries", 10,
50155 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50156 				fnct_ElementaryGeometries, 0, 0, 0);
50157     sqlite3_create_function_v2 (db, "ElementaryGeometries", 11,
50158 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50159 				fnct_ElementaryGeometries, 0, 0, 0);
50160     sqlite3_create_function_v2 (db, "ElementaryGeometries", 12,
50161 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50162 				fnct_ElementaryGeometries, 0, 0, 0);
50163     sqlite3_create_function_v2 (db, "ElementaryGeometries", 13,
50164 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50165 				fnct_ElementaryGeometries, 0, 0, 0);
50166     sqlite3_create_function_v2 (db, "ElementaryGeometries", 14,
50167 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50168 				fnct_ElementaryGeometries, 0, 0, 0);
50169     sqlite3_create_function_v2 (db, "ElementaryGeometries", 15,
50170 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50171 				fnct_ElementaryGeometries, 0, 0, 0);
50172     sqlite3_create_function_v2 (db, "ElementaryGeometries", 16,
50173 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50174 				fnct_ElementaryGeometries, 0, 0, 0);
50175     sqlite3_create_function_v2 (db, "DropGeoTable", 1,
50176 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50177 				fnct_DropGeoTable, 0, 0, 0);
50178     sqlite3_create_function_v2 (db, "DropGeoTable", 2,
50179 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50180 				fnct_DropGeoTable, 0, 0, 0);
50181     sqlite3_create_function_v2 (db, "DropGeoTable", 3,
50182 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50183 				fnct_DropGeoTable, 0, 0, 0);
50184     sqlite3_create_function_v2 (db, "DropTable", 2,
50185 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50186 				fnct_DropTable, 0, 0, 0);
50187     sqlite3_create_function_v2 (db, "DropTable", 3,
50188 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50189 				fnct_DropTable, 0, 0, 0);
50190     sqlite3_create_function_v2 (db, "RenameTable", 3,
50191 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50192 				fnct_RenameTable, 0, 0, 0);
50193     sqlite3_create_function_v2 (db, "RenameTable", 4,
50194 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50195 				fnct_RenameTable, 0, 0, 0);
50196     sqlite3_create_function_v2 (db, "RenameColumn", 4,
50197 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50198 				fnct_RenameColumn, 0, 0, 0);
50199     sqlite3_create_function_v2 (db, "RenameColumn", 5,
50200 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50201 				fnct_RenameColumn, 0, 0, 0);
50202 
50203     sqlite3_create_function_v2 (db, "SqlProc_GetLastError", 0, SQLITE_UTF8,
50204 				cache, fnct_sp_get_last_error, 0, 0, 0);
50205     sqlite3_create_function_v2 (db, "SqlProc_GetLogfile", 0, SQLITE_UTF8,
50206 				cache, fnct_sp_get_logfile, 0, 0, 0);
50207     sqlite3_create_function_v2 (db, "SqlProc_FromText", 1, SQLITE_UTF8,
50208 				cache, fnct_sp_from_text, 0, 0, 0);
50209     sqlite3_create_function_v2 (db, "SqlProc_FromText", 2, SQLITE_UTF8,
50210 				cache, fnct_sp_from_text, 0, 0, 0);
50211     sqlite3_create_function_v2 (db, "SqlProc_IsValid", 1, SQLITE_UTF8, 0,
50212 				fnct_sp_is_valid, 0, 0, 0);
50213     sqlite3_create_function_v2 (db, "SqlProc_NumVariables", 1, SQLITE_UTF8,
50214 				0, fnct_sp_var_count, 0, 0, 0);
50215     sqlite3_create_function_v2 (db, "SqlProc_VariableN", 2, SQLITE_UTF8, 0,
50216 				fnct_sp_variable, 0, 0, 0);
50217     sqlite3_create_function_v2 (db, "SqlProc_AllVariables", 1, SQLITE_UTF8,
50218 				0, fnct_sp_all_variables, 0, 0, 0);
50219     sqlite3_create_function_v2 (db, "SqlProc_VarValue", 2, SQLITE_UTF8, 0,
50220 				fnct_sp_var_arg, 0, 0, 0);
50221     sqlite3_create_function_v2 (db, "SqlProc_IsValidVarValue", 1, SQLITE_UTF8,
50222 				0, fnct_sp_is_valid_var, 0, 0, 0);
50223     sqlite3_create_function_v2 (db, "SqlProc_RawSQL", 1, SQLITE_UTF8, 0,
50224 				fnct_sp_raw_sql, 0, 0, 0);
50225     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 1, SQLITE_UTF8,
50226 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50227     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 2, SQLITE_UTF8,
50228 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50229     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 3, SQLITE_UTF8,
50230 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50231     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 4, SQLITE_UTF8,
50232 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50233     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 5, SQLITE_UTF8,
50234 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50235     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 6, SQLITE_UTF8,
50236 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50237     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 7, SQLITE_UTF8,
50238 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50239     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 8, SQLITE_UTF8,
50240 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50241     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 9, SQLITE_UTF8,
50242 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50243     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 10, SQLITE_UTF8,
50244 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50245     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 11, SQLITE_UTF8,
50246 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50247     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 12, SQLITE_UTF8,
50248 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50249     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 13, SQLITE_UTF8,
50250 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50251     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 14, SQLITE_UTF8,
50252 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50253     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 15, SQLITE_UTF8,
50254 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50255     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 16, SQLITE_UTF8,
50256 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50257     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 17, SQLITE_UTF8,
50258 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50259     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 18, SQLITE_UTF8,
50260 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50261     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 19, SQLITE_UTF8,
50262 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50263     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 20, SQLITE_UTF8,
50264 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50265     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 21, SQLITE_UTF8,
50266 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50267     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 22, SQLITE_UTF8,
50268 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50269     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 23, SQLITE_UTF8,
50270 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50271     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 24, SQLITE_UTF8,
50272 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50273     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 25, SQLITE_UTF8,
50274 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50275     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 26, SQLITE_UTF8,
50276 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50277     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 27, SQLITE_UTF8,
50278 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50279     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 28, SQLITE_UTF8,
50280 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50281     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 29, SQLITE_UTF8,
50282 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50283     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 30, SQLITE_UTF8,
50284 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50285     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 31, SQLITE_UTF8,
50286 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50287     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 32, SQLITE_UTF8,
50288 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50289     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 33, SQLITE_UTF8,
50290 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50291     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 34, SQLITE_UTF8,
50292 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50293     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 35, SQLITE_UTF8,
50294 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50295     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 36, SQLITE_UTF8,
50296 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50297     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 37, SQLITE_UTF8,
50298 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50299     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 38, SQLITE_UTF8,
50300 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50301     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 39, SQLITE_UTF8,
50302 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50303     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 40, SQLITE_UTF8,
50304 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50305     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 41, SQLITE_UTF8,
50306 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50307     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 42, SQLITE_UTF8,
50308 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50309     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 43, SQLITE_UTF8,
50310 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50311     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 44, SQLITE_UTF8,
50312 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50313     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 45, SQLITE_UTF8,
50314 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50315     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 46, SQLITE_UTF8,
50316 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50317     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 47, SQLITE_UTF8,
50318 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50319     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 48, SQLITE_UTF8,
50320 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50321     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 49, SQLITE_UTF8,
50322 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50323     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 50, SQLITE_UTF8,
50324 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50325     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 51, SQLITE_UTF8,
50326 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50327     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 52, SQLITE_UTF8,
50328 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50329     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 53, SQLITE_UTF8,
50330 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50331     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 54, SQLITE_UTF8,
50332 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50333     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 55, SQLITE_UTF8,
50334 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50335     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 56, SQLITE_UTF8,
50336 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50337     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 57, SQLITE_UTF8,
50338 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50339     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 58, SQLITE_UTF8,
50340 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50341     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 59, SQLITE_UTF8,
50342 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50343     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 60, SQLITE_UTF8,
50344 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50345     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 61, SQLITE_UTF8,
50346 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50347     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 62, SQLITE_UTF8,
50348 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50349     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 63, SQLITE_UTF8,
50350 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50351     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 64, SQLITE_UTF8,
50352 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50353     sqlite3_create_function_v2 (db, "SqlProc_CookedSQL", 65, SQLITE_UTF8,
50354 				cache, fnct_sp_cooked_sql, 0, 0, 0);
50355     sqlite3_create_function_v2 (db, "SqlProc_Execute", 1, SQLITE_UTF8, cache,
50356 				fnct_sp_execute, 0, 0, 0);
50357     sqlite3_create_function_v2 (db, "SqlProc_Execute", 2, SQLITE_UTF8, cache,
50358 				fnct_sp_execute, 0, 0, 0);
50359     sqlite3_create_function_v2 (db, "SqlProc_Execute", 3, SQLITE_UTF8, cache,
50360 				fnct_sp_execute, 0, 0, 0);
50361     sqlite3_create_function_v2 (db, "SqlProc_Execute", 4, SQLITE_UTF8, cache,
50362 				fnct_sp_execute, 0, 0, 0);
50363     sqlite3_create_function_v2 (db, "SqlProc_Execute", 5, SQLITE_UTF8, cache,
50364 				fnct_sp_execute, 0, 0, 0);
50365     sqlite3_create_function_v2 (db, "SqlProc_Execute", 6, SQLITE_UTF8, cache,
50366 				fnct_sp_execute, 0, 0, 0);
50367     sqlite3_create_function_v2 (db, "SqlProc_Execute", 7, SQLITE_UTF8, cache,
50368 				fnct_sp_execute, 0, 0, 0);
50369     sqlite3_create_function_v2 (db, "SqlProc_Execute", 8, SQLITE_UTF8, cache,
50370 				fnct_sp_execute, 0, 0, 0);
50371     sqlite3_create_function_v2 (db, "SqlProc_Execute", 9, SQLITE_UTF8, cache,
50372 				fnct_sp_execute, 0, 0, 0);
50373     sqlite3_create_function_v2 (db, "SqlProc_Execute", 10, SQLITE_UTF8, cache,
50374 				fnct_sp_execute, 0, 0, 0);
50375     sqlite3_create_function_v2 (db, "SqlProc_Execute", 11, SQLITE_UTF8, cache,
50376 				fnct_sp_execute, 0, 0, 0);
50377     sqlite3_create_function_v2 (db, "SqlProc_Execute", 12, SQLITE_UTF8, cache,
50378 				fnct_sp_execute, 0, 0, 0);
50379     sqlite3_create_function_v2 (db, "SqlProc_Execute", 13, SQLITE_UTF8, cache,
50380 				fnct_sp_execute, 0, 0, 0);
50381     sqlite3_create_function_v2 (db, "SqlProc_Execute", 14, SQLITE_UTF8, cache,
50382 				fnct_sp_execute, 0, 0, 0);
50383     sqlite3_create_function_v2 (db, "SqlProc_Execute", 15, SQLITE_UTF8, cache,
50384 				fnct_sp_execute, 0, 0, 0);
50385     sqlite3_create_function_v2 (db, "SqlProc_Execute", 16, SQLITE_UTF8, cache,
50386 				fnct_sp_execute, 0, 0, 0);
50387     sqlite3_create_function_v2 (db, "SqlProc_Execute", 17, SQLITE_UTF8, cache,
50388 				fnct_sp_execute, 0, 0, 0);
50389     sqlite3_create_function_v2 (db, "SqlProc_Execute", 18, SQLITE_UTF8, cache,
50390 				fnct_sp_execute, 0, 0, 0);
50391     sqlite3_create_function_v2 (db, "SqlProc_Execute", 19, SQLITE_UTF8, cache,
50392 				fnct_sp_execute, 0, 0, 0);
50393     sqlite3_create_function_v2 (db, "SqlProc_Execute", 20, SQLITE_UTF8, cache,
50394 				fnct_sp_execute, 0, 0, 0);
50395     sqlite3_create_function_v2 (db, "SqlProc_Execute", 21, SQLITE_UTF8, cache,
50396 				fnct_sp_execute, 0, 0, 0);
50397     sqlite3_create_function_v2 (db, "SqlProc_Execute", 22, SQLITE_UTF8, cache,
50398 				fnct_sp_execute, 0, 0, 0);
50399     sqlite3_create_function_v2 (db, "SqlProc_Execute", 23, SQLITE_UTF8, cache,
50400 				fnct_sp_execute, 0, 0, 0);
50401     sqlite3_create_function_v2 (db, "SqlProc_Execute", 24, SQLITE_UTF8, cache,
50402 				fnct_sp_execute, 0, 0, 0);
50403     sqlite3_create_function_v2 (db, "SqlProc_Execute", 25, SQLITE_UTF8, cache,
50404 				fnct_sp_execute, 0, 0, 0);
50405     sqlite3_create_function_v2 (db, "SqlProc_Execute", 26, SQLITE_UTF8, cache,
50406 				fnct_sp_execute, 0, 0, 0);
50407     sqlite3_create_function_v2 (db, "SqlProc_Execute", 27, SQLITE_UTF8, cache,
50408 				fnct_sp_execute, 0, 0, 0);
50409     sqlite3_create_function_v2 (db, "SqlProc_Execute", 28, SQLITE_UTF8, cache,
50410 				fnct_sp_execute, 0, 0, 0);
50411     sqlite3_create_function_v2 (db, "SqlProc_Execute", 29, SQLITE_UTF8, cache,
50412 				fnct_sp_execute, 0, 0, 0);
50413     sqlite3_create_function_v2 (db, "SqlProc_Execute", 30, SQLITE_UTF8, cache,
50414 				fnct_sp_execute, 0, 0, 0);
50415     sqlite3_create_function_v2 (db, "SqlProc_Execute", 31, SQLITE_UTF8, cache,
50416 				fnct_sp_execute, 0, 0, 0);
50417     sqlite3_create_function_v2 (db, "SqlProc_Execute", 32, SQLITE_UTF8, cache,
50418 				fnct_sp_execute, 0, 0, 0);
50419     sqlite3_create_function_v2 (db, "SqlProc_Execute", 33, SQLITE_UTF8, cache,
50420 				fnct_sp_execute, 0, 0, 0);
50421     sqlite3_create_function_v2 (db, "SqlProc_Execute", 34, SQLITE_UTF8, cache,
50422 				fnct_sp_execute, 0, 0, 0);
50423     sqlite3_create_function_v2 (db, "SqlProc_Execute", 35, SQLITE_UTF8, cache,
50424 				fnct_sp_execute, 0, 0, 0);
50425     sqlite3_create_function_v2 (db, "SqlProc_Execute", 36, SQLITE_UTF8, cache,
50426 				fnct_sp_execute, 0, 0, 0);
50427     sqlite3_create_function_v2 (db, "SqlProc_Execute", 37, SQLITE_UTF8, cache,
50428 				fnct_sp_execute, 0, 0, 0);
50429     sqlite3_create_function_v2 (db, "SqlProc_Execute", 38, SQLITE_UTF8, cache,
50430 				fnct_sp_execute, 0, 0, 0);
50431     sqlite3_create_function_v2 (db, "SqlProc_Execute", 39, SQLITE_UTF8, cache,
50432 				fnct_sp_execute, 0, 0, 0);
50433     sqlite3_create_function_v2 (db, "SqlProc_Execute", 40, SQLITE_UTF8, cache,
50434 				fnct_sp_execute, 0, 0, 0);
50435     sqlite3_create_function_v2 (db, "SqlProc_Execute", 41, SQLITE_UTF8, cache,
50436 				fnct_sp_execute, 0, 0, 0);
50437     sqlite3_create_function_v2 (db, "SqlProc_Execute", 42, SQLITE_UTF8, cache,
50438 				fnct_sp_execute, 0, 0, 0);
50439     sqlite3_create_function_v2 (db, "SqlProc_Execute", 43, SQLITE_UTF8, cache,
50440 				fnct_sp_execute, 0, 0, 0);
50441     sqlite3_create_function_v2 (db, "SqlProc_Execute", 44, SQLITE_UTF8, cache,
50442 				fnct_sp_execute, 0, 0, 0);
50443     sqlite3_create_function_v2 (db, "SqlProc_Execute", 45, SQLITE_UTF8, cache,
50444 				fnct_sp_execute, 0, 0, 0);
50445     sqlite3_create_function_v2 (db, "SqlProc_Execute", 46, SQLITE_UTF8, cache,
50446 				fnct_sp_execute, 0, 0, 0);
50447     sqlite3_create_function_v2 (db, "SqlProc_Execute", 47, SQLITE_UTF8, cache,
50448 				fnct_sp_execute, 0, 0, 0);
50449     sqlite3_create_function_v2 (db, "SqlProc_Execute", 48, SQLITE_UTF8, cache,
50450 				fnct_sp_execute, 0, 0, 0);
50451     sqlite3_create_function_v2 (db, "SqlProc_Execute", 49, SQLITE_UTF8, cache,
50452 				fnct_sp_execute, 0, 0, 0);
50453     sqlite3_create_function_v2 (db, "SqlProc_Execute", 50, SQLITE_UTF8, cache,
50454 				fnct_sp_execute, 0, 0, 0);
50455     sqlite3_create_function_v2 (db, "SqlProc_Execute", 51, SQLITE_UTF8, cache,
50456 				fnct_sp_execute, 0, 0, 0);
50457     sqlite3_create_function_v2 (db, "SqlProc_Execute", 52, SQLITE_UTF8, cache,
50458 				fnct_sp_execute, 0, 0, 0);
50459     sqlite3_create_function_v2 (db, "SqlProc_Execute", 53, SQLITE_UTF8, cache,
50460 				fnct_sp_execute, 0, 0, 0);
50461     sqlite3_create_function_v2 (db, "SqlProc_Execute", 54, SQLITE_UTF8, cache,
50462 				fnct_sp_execute, 0, 0, 0);
50463     sqlite3_create_function_v2 (db, "SqlProc_Execute", 55, SQLITE_UTF8, cache,
50464 				fnct_sp_execute, 0, 0, 0);
50465     sqlite3_create_function_v2 (db, "SqlProc_Execute", 56, SQLITE_UTF8, cache,
50466 				fnct_sp_execute, 0, 0, 0);
50467     sqlite3_create_function_v2 (db, "SqlProc_Execute", 57, SQLITE_UTF8, cache,
50468 				fnct_sp_execute, 0, 0, 0);
50469     sqlite3_create_function_v2 (db, "SqlProc_Execute", 58, SQLITE_UTF8, cache,
50470 				fnct_sp_execute, 0, 0, 0);
50471     sqlite3_create_function_v2 (db, "SqlProc_Execute", 59, SQLITE_UTF8, cache,
50472 				fnct_sp_execute, 0, 0, 0);
50473     sqlite3_create_function_v2 (db, "SqlProc_Execute", 60, SQLITE_UTF8, cache,
50474 				fnct_sp_execute, 0, 0, 0);
50475     sqlite3_create_function_v2 (db, "SqlProc_Execute", 61, SQLITE_UTF8, cache,
50476 				fnct_sp_execute, 0, 0, 0);
50477     sqlite3_create_function_v2 (db, "SqlProc_Execute", 62, SQLITE_UTF8, cache,
50478 				fnct_sp_execute, 0, 0, 0);
50479     sqlite3_create_function_v2 (db, "SqlProc_Execute", 63, SQLITE_UTF8, cache,
50480 				fnct_sp_execute, 0, 0, 0);
50481     sqlite3_create_function_v2 (db, "SqlProc_Execute", 64, SQLITE_UTF8, cache,
50482 				fnct_sp_execute, 0, 0, 0);
50483     sqlite3_create_function_v2 (db, "SqlProc_Execute", 65, SQLITE_UTF8, cache,
50484 				fnct_sp_execute, 0, 0, 0);
50485     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 1, SQLITE_UTF8,
50486 				cache, fnct_sp_execute_loop, 0, 0, 0);
50487     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 2, SQLITE_UTF8,
50488 				cache, fnct_sp_execute_loop, 0, 0, 0);
50489     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 3, SQLITE_UTF8,
50490 				cache, fnct_sp_execute_loop, 0, 0, 0);
50491     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 4, SQLITE_UTF8,
50492 				cache, fnct_sp_execute_loop, 0, 0, 0);
50493     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 5, SQLITE_UTF8,
50494 				cache, fnct_sp_execute_loop, 0, 0, 0);
50495     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 6, SQLITE_UTF8,
50496 				cache, fnct_sp_execute_loop, 0, 0, 0);
50497     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 7, SQLITE_UTF8,
50498 				cache, fnct_sp_execute_loop, 0, 0, 0);
50499     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 8, SQLITE_UTF8,
50500 				cache, fnct_sp_execute_loop, 0, 0, 0);
50501     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 9, SQLITE_UTF8,
50502 				cache, fnct_sp_execute_loop, 0, 0, 0);
50503     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 10, SQLITE_UTF8,
50504 				cache, fnct_sp_execute_loop, 0, 0, 0);
50505     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 11, SQLITE_UTF8,
50506 				cache, fnct_sp_execute_loop, 0, 0, 0);
50507     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 12, SQLITE_UTF8,
50508 				cache, fnct_sp_execute_loop, 0, 0, 0);
50509     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 13, SQLITE_UTF8,
50510 				cache, fnct_sp_execute_loop, 0, 0, 0);
50511     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 14, SQLITE_UTF8,
50512 				cache, fnct_sp_execute_loop, 0, 0, 0);
50513     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 15, SQLITE_UTF8,
50514 				cache, fnct_sp_execute_loop, 0, 0, 0);
50515     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 16, SQLITE_UTF8,
50516 				cache, fnct_sp_execute_loop, 0, 0, 0);
50517     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 17, SQLITE_UTF8,
50518 				cache, fnct_sp_execute_loop, 0, 0, 0);
50519     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 18, SQLITE_UTF8,
50520 				cache, fnct_sp_execute_loop, 0, 0, 0);
50521     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 19, SQLITE_UTF8,
50522 				cache, fnct_sp_execute_loop, 0, 0, 0);
50523     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 20, SQLITE_UTF8,
50524 				cache, fnct_sp_execute_loop, 0, 0, 0);
50525     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 21, SQLITE_UTF8,
50526 				cache, fnct_sp_execute_loop, 0, 0, 0);
50527     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 22, SQLITE_UTF8,
50528 				cache, fnct_sp_execute_loop, 0, 0, 0);
50529     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 23, SQLITE_UTF8,
50530 				cache, fnct_sp_execute_loop, 0, 0, 0);
50531     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 24, SQLITE_UTF8,
50532 				cache, fnct_sp_execute_loop, 0, 0, 0);
50533     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 25, SQLITE_UTF8,
50534 				cache, fnct_sp_execute_loop, 0, 0, 0);
50535     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 26, SQLITE_UTF8,
50536 				cache, fnct_sp_execute_loop, 0, 0, 0);
50537     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 27, SQLITE_UTF8,
50538 				cache, fnct_sp_execute_loop, 0, 0, 0);
50539     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 28, SQLITE_UTF8,
50540 				cache, fnct_sp_execute_loop, 0, 0, 0);
50541     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 29, SQLITE_UTF8,
50542 				cache, fnct_sp_execute_loop, 0, 0, 0);
50543     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 30, SQLITE_UTF8,
50544 				cache, fnct_sp_execute_loop, 0, 0, 0);
50545     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 31, SQLITE_UTF8,
50546 				cache, fnct_sp_execute_loop, 0, 0, 0);
50547     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 32, SQLITE_UTF8,
50548 				cache, fnct_sp_execute_loop, 0, 0, 0);
50549     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 33, SQLITE_UTF8,
50550 				cache, fnct_sp_execute_loop, 0, 0, 0);
50551     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 34, SQLITE_UTF8,
50552 				cache, fnct_sp_execute_loop, 0, 0, 0);
50553     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 35, SQLITE_UTF8,
50554 				cache, fnct_sp_execute_loop, 0, 0, 0);
50555     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 36, SQLITE_UTF8,
50556 				cache, fnct_sp_execute_loop, 0, 0, 0);
50557     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 37, SQLITE_UTF8,
50558 				cache, fnct_sp_execute_loop, 0, 0, 0);
50559     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 38, SQLITE_UTF8,
50560 				cache, fnct_sp_execute_loop, 0, 0, 0);
50561     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 39, SQLITE_UTF8,
50562 				cache, fnct_sp_execute_loop, 0, 0, 0);
50563     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 40, SQLITE_UTF8,
50564 				cache, fnct_sp_execute_loop, 0, 0, 0);
50565     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 41, SQLITE_UTF8,
50566 				cache, fnct_sp_execute_loop, 0, 0, 0);
50567     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 42, SQLITE_UTF8,
50568 				cache, fnct_sp_execute_loop, 0, 0, 0);
50569     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 43, SQLITE_UTF8,
50570 				cache, fnct_sp_execute_loop, 0, 0, 0);
50571     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 44, SQLITE_UTF8,
50572 				cache, fnct_sp_execute_loop, 0, 0, 0);
50573     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 45, SQLITE_UTF8,
50574 				cache, fnct_sp_execute_loop, 0, 0, 0);
50575     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 46, SQLITE_UTF8,
50576 				cache, fnct_sp_execute_loop, 0, 0, 0);
50577     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 47, SQLITE_UTF8,
50578 				cache, fnct_sp_execute_loop, 0, 0, 0);
50579     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 48, SQLITE_UTF8,
50580 				cache, fnct_sp_execute_loop, 0, 0, 0);
50581     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 49, SQLITE_UTF8,
50582 				cache, fnct_sp_execute_loop, 0, 0, 0);
50583     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 50, SQLITE_UTF8,
50584 				cache, fnct_sp_execute_loop, 0, 0, 0);
50585     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 51, SQLITE_UTF8,
50586 				cache, fnct_sp_execute_loop, 0, 0, 0);
50587     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 52, SQLITE_UTF8,
50588 				cache, fnct_sp_execute_loop, 0, 0, 0);
50589     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 53, SQLITE_UTF8,
50590 				cache, fnct_sp_execute_loop, 0, 0, 0);
50591     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 54, SQLITE_UTF8,
50592 				cache, fnct_sp_execute_loop, 0, 0, 0);
50593     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 55, SQLITE_UTF8,
50594 				cache, fnct_sp_execute_loop, 0, 0, 0);
50595     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 56, SQLITE_UTF8,
50596 				cache, fnct_sp_execute_loop, 0, 0, 0);
50597     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 57, SQLITE_UTF8,
50598 				cache, fnct_sp_execute_loop, 0, 0, 0);
50599     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 58, SQLITE_UTF8,
50600 				cache, fnct_sp_execute_loop, 0, 0, 0);
50601     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 59, SQLITE_UTF8,
50602 				cache, fnct_sp_execute_loop, 0, 0, 0);
50603     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 60, SQLITE_UTF8,
50604 				cache, fnct_sp_execute_loop, 0, 0, 0);
50605     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 61, SQLITE_UTF8,
50606 				cache, fnct_sp_execute_loop, 0, 0, 0);
50607     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 62, SQLITE_UTF8,
50608 				cache, fnct_sp_execute_loop, 0, 0, 0);
50609     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 63, SQLITE_UTF8,
50610 				cache, fnct_sp_execute_loop, 0, 0, 0);
50611     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 64, SQLITE_UTF8,
50612 				cache, fnct_sp_execute_loop, 0, 0, 0);
50613     sqlite3_create_function_v2 (db, "SqlProc_ExecuteLoop", 65, SQLITE_UTF8,
50614 				cache, fnct_sp_execute_loop, 0, 0, 0);
50615     sqlite3_create_function_v2 (db, "SqlProc_Return", 1, SQLITE_UTF8, cache,
50616 				fnct_sp_return, 0, 0, 0);
50617     sqlite3_create_function_v2 (db, "StoredProc_Return", 1, SQLITE_UTF8, cache,
50618 				fnct_sp_return, 0, 0, 0);
50619     sqlite3_create_function_v2 (db, "StoredProc_CreateTables", 0, SQLITE_UTF8,
50620 				cache, fnct_sp_create_tables, 0, 0, 0);
50621     sqlite3_create_function_v2 (db, "StoredProc_Register", 3, SQLITE_UTF8,
50622 				cache, fnct_sp_register, 0, 0, 0);
50623     sqlite3_create_function_v2 (db, "StoredProc_Get", 1, SQLITE_UTF8, cache,
50624 				fnct_sp_get, 0, 0, 0);
50625     sqlite3_create_function_v2 (db, "StoredProc_Delete", 1, SQLITE_UTF8, cache,
50626 				fnct_sp_delete, 0, 0, 0);
50627     sqlite3_create_function_v2 (db, "StoredProc_UpdateTitle", 2, SQLITE_UTF8,
50628 				cache, fnct_sp_update_title, 0, 0, 0);
50629     sqlite3_create_function_v2 (db, "StoredProc_UpdateSqlBody", 2, SQLITE_UTF8,
50630 				cache, fnct_sp_update_sql, 0, 0, 0);
50631     sqlite3_create_function_v2 (db, "StoredVar_Register", 3, SQLITE_UTF8, cache,
50632 				fnct_sp_var_register, 0, 0, 0);
50633     sqlite3_create_function_v2 (db, "StoredVar_Get", 1, SQLITE_UTF8, cache,
50634 				fnct_sp_var_get, 0, 0, 0);
50635     sqlite3_create_function_v2 (db, "StoredVar_GetValue", 1, SQLITE_UTF8, cache,
50636 				fnct_sp_var_get_value, 0, 0, 0);
50637     sqlite3_create_function_v2 (db, "StoredVar_Delete", 1, SQLITE_UTF8, cache,
50638 				fnct_sp_var_delete, 0, 0, 0);
50639     sqlite3_create_function_v2 (db, "StoredVar_UpdateTitle", 2, SQLITE_UTF8,
50640 				cache, fnct_sp_var_update_title, 0, 0, 0);
50641     sqlite3_create_function_v2 (db, "StoredVar_UpdateValue", 2, SQLITE_UTF8,
50642 				cache, fnct_sp_var_update_value, 0, 0, 0);
50643     sqlite3_create_function_v2 (db, "StoredProc_Execute", 1, SQLITE_UTF8, cache,
50644 				fnct_sp_stored_execute, 0, 0, 0);
50645     sqlite3_create_function_v2 (db, "StoredProc_Execute", 2, SQLITE_UTF8, cache,
50646 				fnct_sp_stored_execute, 0, 0, 0);
50647     sqlite3_create_function_v2 (db, "StoredProc_Execute", 3, SQLITE_UTF8, cache,
50648 				fnct_sp_stored_execute, 0, 0, 0);
50649     sqlite3_create_function_v2 (db, "StoredProc_Execute", 4, SQLITE_UTF8, cache,
50650 				fnct_sp_stored_execute, 0, 0, 0);
50651     sqlite3_create_function_v2 (db, "StoredProc_Execute", 5, SQLITE_UTF8, cache,
50652 				fnct_sp_stored_execute, 0, 0, 0);
50653     sqlite3_create_function_v2 (db, "StoredProc_Execute", 6, SQLITE_UTF8, cache,
50654 				fnct_sp_stored_execute, 0, 0, 0);
50655     sqlite3_create_function_v2 (db, "StoredProc_Execute", 7, SQLITE_UTF8, cache,
50656 				fnct_sp_stored_execute, 0, 0, 0);
50657     sqlite3_create_function_v2 (db, "StoredProc_Execute", 8, SQLITE_UTF8, cache,
50658 				fnct_sp_stored_execute, 0, 0, 0);
50659     sqlite3_create_function_v2 (db, "StoredProc_Execute", 9, SQLITE_UTF8, cache,
50660 				fnct_sp_stored_execute, 0, 0, 0);
50661     sqlite3_create_function_v2 (db, "StoredProc_Execute", 10, SQLITE_UTF8,
50662 				cache, fnct_sp_stored_execute, 0, 0, 0);
50663     sqlite3_create_function_v2 (db, "StoredProc_Execute", 11, SQLITE_UTF8,
50664 				cache, fnct_sp_stored_execute, 0, 0, 0);
50665     sqlite3_create_function_v2 (db, "StoredProc_Execute", 12, SQLITE_UTF8,
50666 				cache, fnct_sp_stored_execute, 0, 0, 0);
50667     sqlite3_create_function_v2 (db, "StoredProc_Execute", 13, SQLITE_UTF8,
50668 				cache, fnct_sp_stored_execute, 0, 0, 0);
50669     sqlite3_create_function_v2 (db, "StoredProc_Execute", 14, SQLITE_UTF8,
50670 				cache, fnct_sp_stored_execute, 0, 0, 0);
50671     sqlite3_create_function_v2 (db, "StoredProc_Execute", 15, SQLITE_UTF8,
50672 				cache, fnct_sp_stored_execute, 0, 0, 0);
50673     sqlite3_create_function_v2 (db, "StoredProc_Execute", 16, SQLITE_UTF8,
50674 				cache, fnct_sp_stored_execute, 0, 0, 0);
50675     sqlite3_create_function_v2 (db, "StoredProc_Execute", 17, SQLITE_UTF8,
50676 				cache, fnct_sp_stored_execute, 0, 0, 0);
50677     sqlite3_create_function_v2 (db, "StoredProc_Execute", 18, SQLITE_UTF8,
50678 				cache, fnct_sp_stored_execute, 0, 0, 0);
50679     sqlite3_create_function_v2 (db, "StoredProc_Execute", 19, SQLITE_UTF8,
50680 				cache, fnct_sp_stored_execute, 0, 0, 0);
50681     sqlite3_create_function_v2 (db, "StoredProc_Execute", 20, SQLITE_UTF8,
50682 				cache, fnct_sp_stored_execute, 0, 0, 0);
50683     sqlite3_create_function_v2 (db, "StoredProc_Execute", 21, SQLITE_UTF8,
50684 				cache, fnct_sp_stored_execute, 0, 0, 0);
50685     sqlite3_create_function_v2 (db, "StoredProc_Execute", 22, SQLITE_UTF8,
50686 				cache, fnct_sp_stored_execute, 0, 0, 0);
50687     sqlite3_create_function_v2 (db, "StoredProc_Execute", 23, SQLITE_UTF8,
50688 				cache, fnct_sp_stored_execute, 0, 0, 0);
50689     sqlite3_create_function_v2 (db, "StoredProc_Execute", 24, SQLITE_UTF8,
50690 				cache, fnct_sp_stored_execute, 0, 0, 0);
50691     sqlite3_create_function_v2 (db, "StoredProc_Execute", 25, SQLITE_UTF8,
50692 				cache, fnct_sp_stored_execute, 0, 0, 0);
50693     sqlite3_create_function_v2 (db, "StoredProc_Execute", 26, SQLITE_UTF8,
50694 				cache, fnct_sp_stored_execute, 0, 0, 0);
50695     sqlite3_create_function_v2 (db, "StoredProc_Execute", 27, SQLITE_UTF8,
50696 				cache, fnct_sp_stored_execute, 0, 0, 0);
50697     sqlite3_create_function_v2 (db, "StoredProc_Execute", 28, SQLITE_UTF8,
50698 				cache, fnct_sp_stored_execute, 0, 0, 0);
50699     sqlite3_create_function_v2 (db, "StoredProc_Execute", 29, SQLITE_UTF8,
50700 				cache, fnct_sp_stored_execute, 0, 0, 0);
50701     sqlite3_create_function_v2 (db, "StoredProc_Execute", 30, SQLITE_UTF8,
50702 				cache, fnct_sp_stored_execute, 0, 0, 0);
50703     sqlite3_create_function_v2 (db, "StoredProc_Execute", 31, SQLITE_UTF8,
50704 				cache, fnct_sp_stored_execute, 0, 0, 0);
50705     sqlite3_create_function_v2 (db, "StoredProc_Execute", 32, SQLITE_UTF8,
50706 				cache, fnct_sp_stored_execute, 0, 0, 0);
50707     sqlite3_create_function_v2 (db, "StoredProc_Execute", 33, SQLITE_UTF8,
50708 				cache, fnct_sp_stored_execute, 0, 0, 0);
50709     sqlite3_create_function_v2 (db, "StoredProc_Execute", 34, SQLITE_UTF8,
50710 				cache, fnct_sp_stored_execute, 0, 0, 0);
50711     sqlite3_create_function_v2 (db, "StoredProc_Execute", 35, SQLITE_UTF8,
50712 				cache, fnct_sp_stored_execute, 0, 0, 0);
50713     sqlite3_create_function_v2 (db, "StoredProc_Execute", 36, SQLITE_UTF8,
50714 				cache, fnct_sp_stored_execute, 0, 0, 0);
50715     sqlite3_create_function_v2 (db, "StoredProc_Execute", 37, SQLITE_UTF8,
50716 				cache, fnct_sp_stored_execute, 0, 0, 0);
50717     sqlite3_create_function_v2 (db, "StoredProc_Execute", 38, SQLITE_UTF8,
50718 				cache, fnct_sp_stored_execute, 0, 0, 0);
50719     sqlite3_create_function_v2 (db, "StoredProc_Execute", 39, SQLITE_UTF8,
50720 				cache, fnct_sp_stored_execute, 0, 0, 0);
50721     sqlite3_create_function_v2 (db, "StoredProc_Execute", 40, SQLITE_UTF8,
50722 				cache, fnct_sp_stored_execute, 0, 0, 0);
50723     sqlite3_create_function_v2 (db, "StoredProc_Execute", 41, SQLITE_UTF8,
50724 				cache, fnct_sp_stored_execute, 0, 0, 0);
50725     sqlite3_create_function_v2 (db, "StoredProc_Execute", 42, SQLITE_UTF8,
50726 				cache, fnct_sp_stored_execute, 0, 0, 0);
50727     sqlite3_create_function_v2 (db, "StoredProc_Execute", 43, SQLITE_UTF8,
50728 				cache, fnct_sp_stored_execute, 0, 0, 0);
50729     sqlite3_create_function_v2 (db, "StoredProc_Execute", 44, SQLITE_UTF8,
50730 				cache, fnct_sp_stored_execute, 0, 0, 0);
50731     sqlite3_create_function_v2 (db, "StoredProc_Execute", 45, SQLITE_UTF8,
50732 				cache, fnct_sp_stored_execute, 0, 0, 0);
50733     sqlite3_create_function_v2 (db, "StoredProc_Execute", 46, SQLITE_UTF8,
50734 				cache, fnct_sp_stored_execute, 0, 0, 0);
50735     sqlite3_create_function_v2 (db, "StoredProc_Execute", 47, SQLITE_UTF8,
50736 				cache, fnct_sp_stored_execute, 0, 0, 0);
50737     sqlite3_create_function_v2 (db, "StoredProc_Execute", 48, SQLITE_UTF8,
50738 				cache, fnct_sp_stored_execute, 0, 0, 0);
50739     sqlite3_create_function_v2 (db, "StoredProc_Execute", 49, SQLITE_UTF8,
50740 				cache, fnct_sp_stored_execute, 0, 0, 0);
50741     sqlite3_create_function_v2 (db, "StoredProc_Execute", 50, SQLITE_UTF8,
50742 				cache, fnct_sp_stored_execute, 0, 0, 0);
50743     sqlite3_create_function_v2 (db, "StoredProc_Execute", 51, SQLITE_UTF8,
50744 				cache, fnct_sp_stored_execute, 0, 0, 0);
50745     sqlite3_create_function_v2 (db, "StoredProc_Execute", 52, SQLITE_UTF8,
50746 				cache, fnct_sp_stored_execute, 0, 0, 0);
50747     sqlite3_create_function_v2 (db, "StoredProc_Execute", 53, SQLITE_UTF8,
50748 				cache, fnct_sp_stored_execute, 0, 0, 0);
50749     sqlite3_create_function_v2 (db, "StoredProc_Execute", 54, SQLITE_UTF8,
50750 				cache, fnct_sp_stored_execute, 0, 0, 0);
50751     sqlite3_create_function_v2 (db, "StoredProc_Execute", 55, SQLITE_UTF8,
50752 				cache, fnct_sp_stored_execute, 0, 0, 0);
50753     sqlite3_create_function_v2 (db, "StoredProc_Execute", 56, SQLITE_UTF8,
50754 				cache, fnct_sp_stored_execute, 0, 0, 0);
50755     sqlite3_create_function_v2 (db, "StoredProc_Execute", 57, SQLITE_UTF8,
50756 				cache, fnct_sp_stored_execute, 0, 0, 0);
50757     sqlite3_create_function_v2 (db, "StoredProc_Execute", 58, SQLITE_UTF8,
50758 				cache, fnct_sp_stored_execute, 0, 0, 0);
50759     sqlite3_create_function_v2 (db, "StoredProc_Execute", 59, SQLITE_UTF8,
50760 				cache, fnct_sp_stored_execute, 0, 0, 0);
50761     sqlite3_create_function_v2 (db, "StoredProc_Execute", 60, SQLITE_UTF8,
50762 				cache, fnct_sp_stored_execute, 0, 0, 0);
50763     sqlite3_create_function_v2 (db, "StoredProc_Execute", 61, SQLITE_UTF8,
50764 				cache, fnct_sp_stored_execute, 0, 0, 0);
50765     sqlite3_create_function_v2 (db, "StoredProc_Execute", 62, SQLITE_UTF8,
50766 				cache, fnct_sp_stored_execute, 0, 0, 0);
50767     sqlite3_create_function_v2 (db, "StoredProc_Execute", 63, SQLITE_UTF8,
50768 				cache, fnct_sp_stored_execute, 0, 0, 0);
50769     sqlite3_create_function_v2 (db, "StoredProc_Execute", 64, SQLITE_UTF8,
50770 				cache, fnct_sp_stored_execute, 0, 0, 0);
50771     sqlite3_create_function_v2 (db, "StoredProc_Execute", 65, SQLITE_UTF8,
50772 				cache, fnct_sp_stored_execute, 0, 0, 0);
50773     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 1, SQLITE_UTF8,
50774 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50775     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 2, SQLITE_UTF8,
50776 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50777     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 3, SQLITE_UTF8,
50778 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50779     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 4, SQLITE_UTF8,
50780 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50781     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 5, SQLITE_UTF8,
50782 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50783     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 6, SQLITE_UTF8,
50784 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50785     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 7, SQLITE_UTF8,
50786 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50787     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 8, SQLITE_UTF8,
50788 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50789     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 9, SQLITE_UTF8,
50790 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50791     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 10, SQLITE_UTF8,
50792 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50793     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 11, SQLITE_UTF8,
50794 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50795     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 12, SQLITE_UTF8,
50796 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50797     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 13, SQLITE_UTF8,
50798 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50799     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 14, SQLITE_UTF8,
50800 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50801     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 15, SQLITE_UTF8,
50802 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50803     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 16, SQLITE_UTF8,
50804 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50805     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 17, SQLITE_UTF8,
50806 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50807     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 18, SQLITE_UTF8,
50808 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50809     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 19, SQLITE_UTF8,
50810 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50811     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 20, SQLITE_UTF8,
50812 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50813     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 21, SQLITE_UTF8,
50814 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50815     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 22, SQLITE_UTF8,
50816 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50817     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 23, SQLITE_UTF8,
50818 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50819     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 24, SQLITE_UTF8,
50820 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50821     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 25, SQLITE_UTF8,
50822 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50823     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 26, SQLITE_UTF8,
50824 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50825     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 27, SQLITE_UTF8,
50826 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50827     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 28, SQLITE_UTF8,
50828 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50829     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 29, SQLITE_UTF8,
50830 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50831     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 30, SQLITE_UTF8,
50832 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50833     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 31, SQLITE_UTF8,
50834 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50835     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 32, SQLITE_UTF8,
50836 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50837     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 33, SQLITE_UTF8,
50838 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50839     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 34, SQLITE_UTF8,
50840 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50841     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 35, SQLITE_UTF8,
50842 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50843     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 36, SQLITE_UTF8,
50844 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50845     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 37, SQLITE_UTF8,
50846 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50847     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 38, SQLITE_UTF8,
50848 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50849     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 39, SQLITE_UTF8,
50850 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50851     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 40, SQLITE_UTF8,
50852 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50853     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 41, SQLITE_UTF8,
50854 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50855     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 42, SQLITE_UTF8,
50856 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50857     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 43, SQLITE_UTF8,
50858 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50859     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 44, SQLITE_UTF8,
50860 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50861     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 45, SQLITE_UTF8,
50862 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50863     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 46, SQLITE_UTF8,
50864 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50865     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 47, SQLITE_UTF8,
50866 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50867     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 48, SQLITE_UTF8,
50868 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50869     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 49, SQLITE_UTF8,
50870 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50871     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 50, SQLITE_UTF8,
50872 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50873     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 51, SQLITE_UTF8,
50874 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50875     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 52, SQLITE_UTF8,
50876 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50877     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 53, SQLITE_UTF8,
50878 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50879     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 54, SQLITE_UTF8,
50880 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50881     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 55, SQLITE_UTF8,
50882 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50883     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 56, SQLITE_UTF8,
50884 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50885     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 57, SQLITE_UTF8,
50886 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50887     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 58, SQLITE_UTF8,
50888 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50889     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 59, SQLITE_UTF8,
50890 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50891     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 60, SQLITE_UTF8,
50892 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50893     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 61, SQLITE_UTF8,
50894 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50895     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 62, SQLITE_UTF8,
50896 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50897     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 63, SQLITE_UTF8,
50898 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50899     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 64, SQLITE_UTF8,
50900 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50901     sqlite3_create_function_v2 (db, "StoredProc_ExecuteLoop", 65, SQLITE_UTF8,
50902 				cache, fnct_sp_stored_execute_loop, 0, 0, 0);
50903     sqlite3_create_function_v2 (db, "CreateRoutingNodes", 5, SQLITE_UTF8, cache,
50904 				fnct_create_routing_nodes, 0, 0, 0);
50905     sqlite3_create_function_v2 (db, "CreateRouting", 7, SQLITE_UTF8, cache,
50906 				fnct_create_routing, 0, 0, 0);
50907     sqlite3_create_function_v2 (db, "CreateRouting", 10, SQLITE_UTF8, cache,
50908 				fnct_create_routing, 0, 0, 0);
50909     sqlite3_create_function_v2 (db, "CreateRouting", 12, SQLITE_UTF8, cache,
50910 				fnct_create_routing, 0, 0, 0);
50911     sqlite3_create_function_v2 (db, "CreateRouting", 13, SQLITE_UTF8, cache,
50912 				fnct_create_routing, 0, 0, 0);
50913     sqlite3_create_function_v2 (db, "CreateRouting_GetLastError", 0,
50914 				SQLITE_UTF8, cache,
50915 				fnct_create_routing_get_last_error, 0, 0, 0);
50916 
50917 /*
50918 // enabling BlobFromFile, BlobToFile and XB_LoadXML, XB_StoreXML,
50919 // ExportDXF and other import/export functions
50920 //
50921 // these functions could potentially introduce serious security issues,
50922 // most notably when invoked from within some Trigger
50923 // - BlobToFile: some arbitrary code, possibly harmfull (e.g. virus or
50924 //   trojan) could be installed on the local file-system, the user being
50925 //   completely unaware of this
50926 // - BlobFromFile: some file could be maliciously "stolen" from the local
50927 //   file system and then inseted into the DB
50928 // - the same is for XB_LoadXML and XB_StoreXML
50929 // - ExportDXF could potentially flood the local file-system by
50930 //   outputting a huge size of data
50931 //
50932 // so by default such functions are disabled.
50933 // if for any good/legitimate reason the user really wants to enable them
50934 // the following environment variable has to be explicitly declared:
50935 //
50936 // SPATIALITE_SECURITY=relaxed
50937 //
50938 */
50939     security_level = getenv ("SPATIALITE_SECURITY");
50940     if (security_level == NULL)
50941 	;
50942     else if (strcasecmp (security_level, "relaxed") == 0)
50943       {
50944 	  sqlite3_create_function_v2 (db, "BlobFromFile", 1,
50945 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50946 				      fnct_BlobFromFile, 0, 0, 0);
50947 	  sqlite3_create_function_v2 (db, "BlobToFile", 2,
50948 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50949 				      fnct_BlobToFile, 0, 0, 0);
50950 
50951 #ifndef OMIT_GEOS		/* only if GEOS is enabled */
50952 
50953 	  sqlite3_create_function_v2 (db, "ImportDXF", 1,
50954 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50955 				      cache, fnct_ImportDXF, 0, 0, 0);
50956 	  sqlite3_create_function_v2 (db, "ImportDXF", 8,
50957 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50958 				      cache, fnct_ImportDXF, 0, 0, 0);
50959 	  sqlite3_create_function_v2 (db, "ImportDXFfromDir", 1,
50960 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50961 				      cache, fnct_ImportDXFfromDir, 0, 0, 0);
50962 	  sqlite3_create_function_v2 (db, "ImportDXFfromDir", 8,
50963 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50964 				      cache, fnct_ImportDXFfromDir, 0, 0, 0);
50965 
50966 #endif /* GEOS enabled */
50967 
50968 	  sqlite3_create_function_v2 (db, "ExportDXF", 9,
50969 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50970 				      cache, fnct_ExportDXF, 0, 0, 0);
50971 	  sqlite3_create_function_v2 (db, "ExportDXF", 10,
50972 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
50973 				      cache, fnct_ExportDXF, 0, 0, 0);
50974 
50975 #ifndef OMIT_ICONV		/* ICONV is supported */
50976 
50977 	  sqlite3_create_function_v2 (db, "ImportDBF", 3,
50978 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50979 				      fnct_ImportDBF, 0, 0, 0);
50980 	  sqlite3_create_function_v2 (db, "ImportDBF", 4,
50981 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50982 				      fnct_ImportDBF, 0, 0, 0);
50983 	  sqlite3_create_function_v2 (db, "ImportDBF", 5,
50984 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50985 				      fnct_ImportDBF, 0, 0, 0);
50986 	  sqlite3_create_function_v2 (db, "ImportDBF", 6,
50987 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50988 				      fnct_ImportDBF, 0, 0, 0);
50989 	  sqlite3_create_function_v2 (db, "ExportDBF", 3,
50990 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50991 				      fnct_ExportDBF, 0, 0, 0);
50992 	  sqlite3_create_function_v2 (db, "ExportDBF", 4,
50993 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50994 				      fnct_ExportDBF, 0, 0, 0);
50995 	  sqlite3_create_function_v2 (db, "ImportSHP", 3,
50996 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
50997 				      fnct_ImportSHP, 0, 0, 0);
50998 	  sqlite3_create_function_v2 (db, "ImportSHP", 4,
50999 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51000 				      fnct_ImportSHP, 0, 0, 0);
51001 	  sqlite3_create_function_v2 (db, "ImportSHP", 5,
51002 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51003 				      fnct_ImportSHP, 0, 0, 0);
51004 	  sqlite3_create_function_v2 (db, "ImportSHP", 6,
51005 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51006 				      fnct_ImportSHP, 0, 0, 0);
51007 	  sqlite3_create_function_v2 (db, "ImportSHP", 7,
51008 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51009 				      fnct_ImportSHP, 0, 0, 0);
51010 	  sqlite3_create_function_v2 (db, "ImportSHP", 8,
51011 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51012 				      fnct_ImportSHP, 0, 0, 0);
51013 	  sqlite3_create_function_v2 (db, "ImportSHP", 9,
51014 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51015 				      fnct_ImportSHP, 0, 0, 0);
51016 	  sqlite3_create_function_v2 (db, "ImportSHP", 10,
51017 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51018 				      fnct_ImportSHP, 0, 0, 0);
51019 	  sqlite3_create_function_v2 (db, "ImportSHP", 11,
51020 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51021 				      fnct_ImportSHP, 0, 0, 0);
51022 	  sqlite3_create_function_v2 (db, "ImportSHP", 12,
51023 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51024 				      fnct_ImportSHP, 0, 0, 0);
51025 	  sqlite3_create_function_v2 (db, "ImportSHP", 13,
51026 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51027 				      fnct_ImportSHP, 0, 0, 0);
51028 	  sqlite3_create_function_v2 (db, "ImportSHP", 14,
51029 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51030 				      fnct_ImportSHP, 0, 0, 0);
51031 
51032 #ifdef ENABLE_MINIZIP		/* only if MINIZIP is enabled */
51033 
51034 	  sqlite3_create_function_v2 (db, "ImportZipDBF", 4,
51035 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51036 				      fnct_ImportZipDBF, 0, 0, 0);
51037 	  sqlite3_create_function_v2 (db, "ImportZipDBF", 5,
51038 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51039 				      fnct_ImportZipDBF, 0, 0, 0);
51040 	  sqlite3_create_function_v2 (db, "ImportZipDBF", 6,
51041 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51042 				      fnct_ImportZipDBF, 0, 0, 0);
51043 	  sqlite3_create_function_v2 (db, "ImportZipDBF", 7,
51044 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51045 				      fnct_ImportZipDBF, 0, 0, 0);
51046 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 4,
51047 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51048 				      fnct_ImportZipSHP, 0, 0, 0);
51049 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 5,
51050 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51051 				      fnct_ImportZipSHP, 0, 0, 0);
51052 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 6,
51053 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51054 				      fnct_ImportZipSHP, 0, 0, 0);
51055 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 7,
51056 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51057 				      fnct_ImportZipSHP, 0, 0, 0);
51058 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 8,
51059 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51060 				      fnct_ImportZipSHP, 0, 0, 0);
51061 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 9,
51062 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51063 				      fnct_ImportZipSHP, 0, 0, 0);
51064 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 10,
51065 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51066 				      fnct_ImportZipSHP, 0, 0, 0);
51067 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 11,
51068 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51069 				      fnct_ImportZipSHP, 0, 0, 0);
51070 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 12,
51071 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51072 				      fnct_ImportZipSHP, 0, 0, 0);
51073 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 13,
51074 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51075 				      fnct_ImportZipSHP, 0, 0, 0);
51076 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 14,
51077 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51078 				      fnct_ImportZipSHP, 0, 0, 0);
51079 	  sqlite3_create_function_v2 (db, "ImportZipSHP", 15,
51080 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51081 				      fnct_ImportZipSHP, 0, 0, 0);
51082 
51083 #endif /* end enabling ImportZipSHP */
51084 
51085 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
51086 	  sqlite3_create_function_v2 (db, "PROJ_GuessSridFromSHP", 1,
51087 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51088 				      fnct_PROJ_GuessSridFromSHP, 0, 0, 0);
51089 
51090 #ifdef ENABLE_MINIZIP		/* only if MINIZIP is enabled */
51091 	  sqlite3_create_function_v2 (db, "PROJ_GuessSridFromZipSHP", 2,
51092 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51093 				      fnct_PROJ_GuessSridFromZipSHP, 0, 0, 0);
51094 #endif /* end MINIZIP */
51095 
51096 #endif /* end PROJ_NEW */
51097 
51098 	  sqlite3_create_function_v2 (db, "ExportSHP", 4,
51099 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51100 				      fnct_ExportSHP, 0, 0, 0);
51101 	  sqlite3_create_function_v2 (db, "ExportSHP", 5,
51102 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51103 				      fnct_ExportSHP, 0, 0, 0);
51104 	  sqlite3_create_function_v2 (db, "ExportSHP", 6,
51105 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51106 				      fnct_ExportSHP, 0, 0, 0);
51107 	  sqlite3_create_function_v2 (db, "ExportGeoJSON", 3,
51108 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51109 				      fnct_ExportGeoJSON, 0, 0, 0);
51110 	  sqlite3_create_function_v2 (db, "ExportGeoJSON", 4,
51111 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51112 				      fnct_ExportGeoJSON, 0, 0, 0);
51113 	  sqlite3_create_function_v2 (db, "ExportGeoJSON", 5,
51114 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51115 				      fnct_ExportGeoJSON, 0, 0, 0);
51116 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 3,
51117 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51118 				      fnct_ExportGeoJSON2, 0, 0, 0);
51119 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 4,
51120 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51121 				      fnct_ExportGeoJSON2, 0, 0, 0);
51122 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 5,
51123 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51124 				      fnct_ExportGeoJSON2, 0, 0, 0);
51125 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 6,
51126 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51127 				      fnct_ExportGeoJSON2, 0, 0, 0);
51128 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 7,
51129 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51130 				      fnct_ExportGeoJSON2, 0, 0, 0);
51131 	  sqlite3_create_function_v2 (db, "ExportGeoJSON2", 8,
51132 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51133 				      fnct_ExportGeoJSON2, 0, 0, 0);
51134 	  sqlite3_create_function_v2 (db, "ImportGeoJSON", 2,
51135 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51136 				      fnct_ImportGeoJSON, 0, 0, 0);
51137 	  sqlite3_create_function_v2 (db, "ImportGeoJSON", 3,
51138 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51139 				      fnct_ImportGeoJSON, 0, 0, 0);
51140 	  sqlite3_create_function_v2 (db, "ImportGeoJSON", 4,
51141 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51142 				      fnct_ImportGeoJSON, 0, 0, 0);
51143 	  sqlite3_create_function_v2 (db, "ImportGeoJSON", 5,
51144 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51145 				      fnct_ImportGeoJSON, 0, 0, 0);
51146 	  sqlite3_create_function_v2 (db, "ImportGeoJSON", 6,
51147 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51148 				      fnct_ImportGeoJSON, 0, 0, 0);
51149 	  sqlite3_create_function_v2 (db, "ExportKML", 3,
51150 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51151 				      fnct_ExportKML, 0, 0, 0);
51152 	  sqlite3_create_function_v2 (db, "ExportKML", 4,
51153 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51154 				      fnct_ExportKML, 0, 0, 0);
51155 	  sqlite3_create_function_v2 (db, "ExportKML", 5,
51156 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51157 				      fnct_ExportKML, 0, 0, 0);
51158 	  sqlite3_create_function_v2 (db, "ExportKML", 6,
51159 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51160 				      fnct_ExportKML, 0, 0, 0);
51161 
51162 #endif /* ICONV enabled */
51163 
51164 
51165 	  sqlite3_create_function_v2 (db, "eval", 1, SQLITE_UTF8, 0,
51166 				      fnct_EvalFunc, 0, 0, 0);
51167 	  sqlite3_create_function_v2 (db, "eval", 2, SQLITE_UTF8, 0,
51168 				      fnct_EvalFunc, 0, 0, 0);
51169 
51170 	  sqlite3_create_function_v2 (db, "SqlProc_FromFile", 1, SQLITE_UTF8,
51171 				      cache, fnct_sp_from_file, 0, 0, 0);
51172 	  sqlite3_create_function_v2 (db, "SqlProc_FromFile", 2, SQLITE_UTF8,
51173 				      cache, fnct_sp_from_file, 0, 0, 0);
51174 	  sqlite3_create_function_v2 (db, "SqlProc_SetLogfile", 1,
51175 				      SQLITE_UTF8, cache, fnct_sp_set_logfile,
51176 				      0, 0, 0);
51177 	  sqlite3_create_function_v2 (db, "SqlProc_SetLogfile", 2,
51178 				      SQLITE_UTF8, cache, fnct_sp_set_logfile,
51179 				      0, 0, 0);
51180 
51181 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
51182 
51183 	  sqlite3_create_function_v2 (db, "XB_LoadXML", 1,
51184 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
51185 				      cache, fnct_XB_LoadXML, 0, 0, 0);
51186 	  sqlite3_create_function_v2 (db, "XB_StoreXML", 2,
51187 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51188 				      fnct_XB_StoreXML, 0, 0, 0);
51189 	  sqlite3_create_function_v2 (db, "XB_StoreXML", 3,
51190 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51191 				      fnct_XB_StoreXML, 0, 0, 0);
51192 	  sqlite3_create_function_v2 (db, "ImportWFS", 3,
51193 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51194 				      fnct_ImportWFS, 0, 0, 0);
51195 	  sqlite3_create_function_v2 (db, "ImportWFS", 4,
51196 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51197 				      fnct_ImportWFS, 0, 0, 0);
51198 	  sqlite3_create_function_v2 (db, "ImportWFS", 5,
51199 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51200 				      fnct_ImportWFS, 0, 0, 0);
51201 	  sqlite3_create_function_v2 (db, "ImportWFS", 6,
51202 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51203 				      fnct_ImportWFS, 0, 0, 0);
51204 	  sqlite3_create_function_v2 (db, "ImportWFS", 7,
51205 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51206 				      fnct_ImportWFS, 0, 0, 0);
51207 
51208 #endif /* end including LIBXML2 */
51209 
51210 #ifndef OMIT_FREEXL		/* FREEXL is enabled */
51211 	  sqlite3_create_function_v2 (db, "ImportXLS", 2,
51212 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51213 				      fnct_ImportXLS, 0, 0, 0);
51214 	  sqlite3_create_function_v2 (db, "ImportXLS", 3,
51215 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51216 				      fnct_ImportXLS, 0, 0, 0);
51217 	  sqlite3_create_function_v2 (db, "ImportXLS", 4,
51218 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51219 				      fnct_ImportXLS, 0, 0, 0);
51220 #endif /* end FREEXL support */
51221 
51222       }
51223 
51224 
51225 /* global settings */
51226 
51227 #ifdef ENABLE_GEOPACKAGE	/* GEOPACKAGE enabled: supporting GPKG geometries */
51228     sqlite3_create_function_v2 (db, "EnableGpkgMode", 0,
51229 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51230 				fnct_enableGpkgMode, 0, 0, 0);
51231     sqlite3_create_function_v2 (db, "DisableGpkgMode", 0,
51232 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51233 				fnct_disableGpkgMode, 0, 0, 0);
51234     sqlite3_create_function_v2 (db, "GetGpkgMode", 0,
51235 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51236 				fnct_getGpkgMode, 0, 0, 0);
51237     sqlite3_create_function_v2 (db, "EnableGpkgAmphibiousMode", 0,
51238 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51239 				fnct_enableGpkgAmphibiousMode, 0, 0, 0);
51240     sqlite3_create_function_v2 (db, "DisableGpkgAmphibiousMode", 0,
51241 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51242 				fnct_disableGpkgAmphibiousMode, 0, 0, 0);
51243     sqlite3_create_function_v2 (db, "GetGpkgAmphibiousMode", 0,
51244 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51245 				fnct_getGpkgAmphibiousMode, 0, 0, 0);
51246 #endif /* end GPKG conditional */
51247 
51248     sqlite3_create_function_v2 (db, "EnablePause", 0,
51249 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51250 				fnct_EnablePause, 0, 0, 0);
51251     sqlite3_create_function_v2 (db, "DisablePause", 0,
51252 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51253 				fnct_DisablePause, 0, 0, 0);
51254     sqlite3_create_function_v2 (db, "IsPauseEnabled", 0,
51255 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51256 				fnct_IsPauseEnabled, 0, 0, 0);
51257     sqlite3_create_function_v2 (db, "Pause", 0,
51258 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51259 				fnct_Pause, 0, 0, 0);
51260 
51261     sqlite3_create_function_v2 (db, "SetDecimalPrecision", 1,
51262 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51263 				fnct_setDecimalPrecision, 0, 0, 0);
51264     sqlite3_create_function_v2 (db, "GetDecimalPrecision", 0,
51265 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51266 				fnct_getDecimalPrecision, 0, 0, 0);
51267 
51268     sqlite3_create_function_v2 (db, "*Add-VirtualTable+Extent", 6,
51269 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51270 				fnct_addVirtualTableExtent, 0, 0, 0);
51271     sqlite3_create_function_v2 (db, "*Remove-VirtualTable+Extent", 1,
51272 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51273 				fnct_removeVirtualTableExtent, 0, 0, 0);
51274     sqlite3_create_function_v2 (db, "GetVirtualShapeExtent", 1,
51275 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51276 				fnct_getVirtualTableExtent, 0, 0, 0);
51277     sqlite3_create_function_v2 (db, "GetVirtualGeoJsonExtent", 1,
51278 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51279 				fnct_getVirtualTableExtent, 0, 0, 0);
51280     sqlite3_create_function_v2 (db, "GetVirtualTableExtent", 1,
51281 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51282 				fnct_getVirtualTableExtent, 0, 0, 0);
51283 
51284     sqlite3_create_function_v2 (db, "IsLowASCII", 1,
51285 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51286 				fnct_isLowASCII, 0, 0, 0);
51287 
51288     sqlite3_create_function_v2 (db, "IsTinyPointEnabled", 0,
51289 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51290 				fnct_isTinyPointEnabled, 0, 0, 0);
51291     sqlite3_create_function_v2 (db, "EnableTinyPoint", 0,
51292 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51293 				fnct_enableTinyPoint, 0, 0, 0);
51294     sqlite3_create_function_v2 (db, "DisableTinyPoint", 0,
51295 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51296 				fnct_disableTinyPoint, 0, 0, 0);
51297 
51298     sqlite3_create_function_v2 (db, "MakeStringList", 1,
51299 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51300 				fnct_make_string_list_step,
51301 				fnct_make_string_list_final, 0);
51302     sqlite3_create_function_v2 (db, "MakeStringList", 2,
51303 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51304 				fnct_make_string_list_step,
51305 				fnct_make_string_list_final, 0);
51306 
51307     sqlite3_create_function_v2 (db, "PostgreSql_ResetLastError", 0,
51308 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51309 				fnct_postgres_reset_error, 0, 0, 0);
51310     sqlite3_create_function_v2 (db, "PostgreSql_SetLastError", 1,
51311 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51312 				fnct_postgres_set_error, 0, 0, 0);
51313     sqlite3_create_function_v2 (db, "PostgreSql_GetLastError", 0,
51314 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51315 				fnct_postgres_get_error, 0, 0, 0);
51316 
51317     sqlite3_create_function_v2 (db, "BufferOptions_Reset", 0,
51318 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51319 				fnct_bufferoptions_reset, 0, 0, 0);
51320     sqlite3_create_function_v2 (db, "BufferOptions_SetEndCapStyle", 1,
51321 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51322 				fnct_bufferoptions_set_endcap, 0, 0, 0);
51323     sqlite3_create_function_v2 (db, "BufferOptions_SetJoinStyle", 1,
51324 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51325 				fnct_bufferoptions_set_join, 0, 0, 0);
51326     sqlite3_create_function_v2 (db, "BufferOptions_SetMitreLimit", 1,
51327 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51328 				fnct_bufferoptions_set_mitrelimit, 0, 0, 0);
51329     sqlite3_create_function_v2 (db, "BufferOptions_SetQuadrantSegments", 1,
51330 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51331 				fnct_bufferoptions_set_quadsegs, 0, 0, 0);
51332     sqlite3_create_function_v2 (db, "BufferOptions_GetEndCapStyle", 0,
51333 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51334 				fnct_bufferoptions_get_endcap, 0, 0, 0);
51335     sqlite3_create_function_v2 (db, "BufferOptions_GetJoinStyle", 0,
51336 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51337 				fnct_bufferoptions_get_join, 0, 0, 0);
51338     sqlite3_create_function_v2 (db, "BufferOptions_GetMitreLimit", 0,
51339 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51340 				fnct_bufferoptions_get_mitrelimit, 0, 0, 0);
51341     sqlite3_create_function_v2 (db, "BufferOptions_GetQuadrantSegments", 0,
51342 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51343 				fnct_bufferoptions_get_quadsegs, 0, 0, 0);
51344 
51345 /* some Geodesic functions */
51346     sqlite3_create_function_v2 (db, "GreatCircleLength", 1,
51347 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51348 				fnct_GreatCircleLength, 0, 0, 0);
51349     sqlite3_create_function_v2 (db, "GeodesicLength", 1,
51350 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51351 				fnct_GeodesicLength, 0, 0, 0);
51352     sqlite3_create_function_v2 (db, "GeodesicArcLength", 2,
51353 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51354 				fnct_GeodesicArcLength, 0, 0, 0);
51355     sqlite3_create_function_v2 (db, "GeodesicArcLength", 3,
51356 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51357 				fnct_GeodesicArcLength, 0, 0, 0);
51358     sqlite3_create_function_v2 (db, "GeodesicChordLength", 2,
51359 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51360 				fnct_GeodesicChordLength, 0, 0, 0);
51361     sqlite3_create_function_v2 (db, "GeodesicChordLength", 3,
51362 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51363 				fnct_GeodesicChordLength, 0, 0, 0);
51364     sqlite3_create_function_v2 (db, "GeodesicCentralAngle", 2,
51365 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51366 				fnct_GeodesicCentralAngle, 0, 0, 0);
51367     sqlite3_create_function_v2 (db, "GeodesicCentralAngle", 3,
51368 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51369 				fnct_GeodesicCentralAngle, 0, 0, 0);
51370     sqlite3_create_function_v2 (db, "GeodesicArcArea", 2,
51371 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51372 				fnct_GeodesicArcArea, 0, 0, 0);
51373     sqlite3_create_function_v2 (db, "GeodesicArcHeight", 2,
51374 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51375 				fnct_GeodesicArcHeight, 0, 0, 0);
51376 
51377 /* some Length Unit conversion functions */
51378     sqlite3_create_function_v2 (db, "CvtToKm", 1,
51379 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51380 				fnct_cvtToKm, 0, 0, 0);
51381     sqlite3_create_function_v2 (db, "CvtToDm", 1,
51382 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51383 				fnct_cvtToDm, 0, 0, 0);
51384     sqlite3_create_function_v2 (db, "CvtToCm", 1,
51385 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51386 				fnct_cvtToCm, 0, 0, 0);
51387     sqlite3_create_function_v2 (db, "CvtToMm", 1,
51388 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51389 				fnct_cvtToMm, 0, 0, 0);
51390     sqlite3_create_function_v2 (db, "CvtToKmi", 1,
51391 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51392 				fnct_cvtToKmi, 0, 0, 0);
51393     sqlite3_create_function_v2 (db, "CvtToIn", 1,
51394 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51395 				fnct_cvtToIn, 0, 0, 0);
51396     sqlite3_create_function_v2 (db, "CvtToFt", 1,
51397 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51398 				fnct_cvtToFt, 0, 0, 0);
51399     sqlite3_create_function_v2 (db, "CvtToYd", 1,
51400 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51401 				fnct_cvtToYd, 0, 0, 0);
51402     sqlite3_create_function_v2 (db, "CvtToMi", 1,
51403 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51404 				fnct_cvtToMi, 0, 0, 0);
51405     sqlite3_create_function_v2 (db, "CvtToFath", 1,
51406 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51407 				fnct_cvtToFath, 0, 0, 0);
51408     sqlite3_create_function_v2 (db, "CvtToCh", 1,
51409 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51410 				fnct_cvtToCh, 0, 0, 0);
51411     sqlite3_create_function_v2 (db, "CvtToLink", 1,
51412 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51413 				fnct_cvtToLink, 0, 0, 0);
51414     sqlite3_create_function_v2 (db, "CvtToUsIn", 1,
51415 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51416 				fnct_cvtToUsIn, 0, 0, 0);
51417     sqlite3_create_function_v2 (db, "CvtToUsFt", 1,
51418 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51419 				fnct_cvtToUsFt, 0, 0, 0);
51420     sqlite3_create_function_v2 (db, "CvtToUsYd", 1,
51421 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51422 				fnct_cvtToUsYd, 0, 0, 0);
51423     sqlite3_create_function_v2 (db, "CvtToUsCh", 1,
51424 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51425 				fnct_cvtToUsCh, 0, 0, 0);
51426     sqlite3_create_function_v2 (db, "CvtToUsMi", 1,
51427 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51428 				fnct_cvtToUsMi, 0, 0, 0);
51429     sqlite3_create_function_v2 (db, "CvtToIndFt", 1,
51430 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51431 				fnct_cvtToIndFt, 0, 0, 0);
51432     sqlite3_create_function_v2 (db, "CvtToIndYd", 1,
51433 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51434 				fnct_cvtToIndYd, 0, 0, 0);
51435     sqlite3_create_function_v2 (db, "CvtToIndCh", 1,
51436 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51437 				fnct_cvtToIndCh, 0, 0, 0);
51438     sqlite3_create_function_v2 (db, "CvtFromKm", 1,
51439 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51440 				fnct_cvtFromKm, 0, 0, 0);
51441     sqlite3_create_function_v2 (db, "CvtFromDm", 1,
51442 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51443 				fnct_cvtFromDm, 0, 0, 0);
51444     sqlite3_create_function_v2 (db, "CvtFromCm", 1,
51445 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51446 				fnct_cvtFromCm, 0, 0, 0);
51447     sqlite3_create_function_v2 (db, "CvtFromMm", 1,
51448 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51449 				fnct_cvtFromMm, 0, 0, 0);
51450     sqlite3_create_function_v2 (db, "CvtFromKmi", 1,
51451 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51452 				fnct_cvtFromKmi, 0, 0, 0);
51453     sqlite3_create_function_v2 (db, "CvtFromIn", 1,
51454 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51455 				fnct_cvtFromIn, 0, 0, 0);
51456     sqlite3_create_function_v2 (db, "CvtFromFt", 1,
51457 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51458 				fnct_cvtFromFt, 0, 0, 0);
51459     sqlite3_create_function_v2 (db, "CvtFromYd", 1,
51460 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51461 				fnct_cvtFromYd, 0, 0, 0);
51462     sqlite3_create_function_v2 (db, "CvtFromMi", 1,
51463 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51464 				fnct_cvtFromMi, 0, 0, 0);
51465     sqlite3_create_function_v2 (db, "CvtFromFath", 1,
51466 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51467 				fnct_cvtFromFath, 0, 0, 0);
51468     sqlite3_create_function_v2 (db, "CvtFromCh", 1,
51469 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51470 				fnct_cvtFromCh, 0, 0, 0);
51471     sqlite3_create_function_v2 (db, "CvtFromLink", 1,
51472 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51473 				fnct_cvtFromLink, 0, 0, 0);
51474     sqlite3_create_function_v2 (db, "CvtFromUsIn", 1,
51475 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51476 				fnct_cvtFromUsIn, 0, 0, 0);
51477     sqlite3_create_function_v2 (db, "CvtFromUsFt", 1,
51478 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51479 				fnct_cvtFromUsFt, 0, 0, 0);
51480     sqlite3_create_function_v2 (db, "CvtFromUsYd", 1,
51481 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51482 				fnct_cvtFromUsYd, 0, 0, 0);
51483     sqlite3_create_function_v2 (db, "CvtFromUsCh", 1,
51484 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51485 				fnct_cvtFromUsCh, 0, 0, 0);
51486     sqlite3_create_function_v2 (db, "CvtFromUsMi", 1,
51487 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51488 				fnct_cvtFromUsMi, 0, 0, 0);
51489     sqlite3_create_function_v2 (db, "CvtFromIndFt", 1,
51490 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51491 				fnct_cvtFromIndFt, 0, 0, 0);
51492     sqlite3_create_function_v2 (db, "CvtFromIndYd", 1,
51493 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51494 				fnct_cvtFromIndYd, 0, 0, 0);
51495     sqlite3_create_function_v2 (db, "CvtFromIndCh", 1,
51496 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51497 				fnct_cvtFromIndCh, 0, 0, 0);
51498 
51499 /* DMS (Degrees/Minutes/Seconds) to DD (decimal degrees) */
51500     sqlite3_create_function_v2 (db, "LongitudeFromDMS", 1,
51501 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51502 				fnct_longFromDMS, 0, 0, 0);
51503     sqlite3_create_function_v2 (db, "LatitudeFromDMS", 1,
51504 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51505 				fnct_latFromDMS, 0, 0, 0);
51506     sqlite3_create_function_v2 (db, "LongLatToDMS", 2,
51507 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51508 				fnct_toDMS, 0, 0, 0);
51509     sqlite3_create_function_v2 (db, "LongLatToDMS", 3,
51510 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51511 				fnct_toDMS, 0, 0, 0);
51512 
51513     if (cache != NULL)
51514       {
51515 	  /* Sequences */
51516 	  sqlite3_create_function_v2 (db, "sequence_currval", 1,
51517 				      SQLITE_UTF8, cache,
51518 				      fnct_sequence_currval, 0, 0, 0);
51519 	  sqlite3_create_function_v2 (db, "sequence_lastval", 0,
51520 				      SQLITE_UTF8, cache,
51521 				      fnct_sequence_lastval, 0, 0, 0);
51522 	  sqlite3_create_function_v2 (db, "sequence_nextval", 1,
51523 				      SQLITE_UTF8, cache,
51524 				      fnct_sequence_nextval, 0, 0, 0);
51525 	  sqlite3_create_function_v2 (db, "sequence_setval", 2,
51526 				      SQLITE_UTF8, cache,
51527 				      fnct_sequence_setval, 0, 0, 0);
51528       }
51529 
51530 #ifndef OMIT_MATHSQL		/* supporting SQL math functions */
51531 
51532 /* some extra math functions */
51533     sqlite3_create_function_v2 (db, "acos", 1,
51534 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51535 				fnct_math_acos, 0, 0, 0);
51536     sqlite3_create_function_v2 (db, "asin", 1,
51537 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51538 				fnct_math_asin, 0, 0, 0);
51539     sqlite3_create_function_v2 (db, "atan", 1,
51540 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51541 				fnct_math_atan, 0, 0, 0);
51542     sqlite3_create_function_v2 (db, "atan2", 2,
51543 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51544 				fnct_math_atan2, 0, 0, 0);
51545     sqlite3_create_function_v2 (db, "ceil", 1,
51546 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51547 				fnct_math_ceil, 0, 0, 0);
51548     sqlite3_create_function_v2 (db, "ceiling", 1,
51549 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51550 				fnct_math_ceil, 0, 0, 0);
51551     sqlite3_create_function_v2 (db, "cos", 1,
51552 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51553 				fnct_math_cos, 0, 0, 0);
51554     sqlite3_create_function_v2 (db, "cot", 1,
51555 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51556 				fnct_math_cot, 0, 0, 0);
51557     sqlite3_create_function_v2 (db, "degrees", 1,
51558 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51559 				fnct_math_degrees, 0, 0, 0);
51560     sqlite3_create_function_v2 (db, "exp", 1,
51561 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51562 				fnct_math_exp, 0, 0, 0);
51563     sqlite3_create_function_v2 (db, "floor", 1,
51564 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51565 				fnct_math_floor, 0, 0, 0);
51566     sqlite3_create_function_v2 (db, "ln", 1,
51567 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51568 				fnct_math_logn, 0, 0, 0);
51569     sqlite3_create_function_v2 (db, "log", 1,
51570 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51571 				fnct_math_logn, 0, 0, 0);
51572     sqlite3_create_function_v2 (db, "log", 2,
51573 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51574 				fnct_math_logn2, 0, 0, 0);
51575     sqlite3_create_function_v2 (db, "log2", 1,
51576 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51577 				fnct_math_log_2, 0, 0, 0);
51578     sqlite3_create_function_v2 (db, "log10", 1,
51579 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51580 				fnct_math_log_10, 0, 0, 0);
51581     sqlite3_create_function_v2 (db, "pi", 0,
51582 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51583 				fnct_math_pi, 0, 0, 0);
51584     sqlite3_create_function_v2 (db, "pow", 2,
51585 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51586 				fnct_math_pow, 0, 0, 0);
51587     sqlite3_create_function_v2 (db, "power", 2,
51588 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51589 				fnct_math_pow, 0, 0, 0);
51590     sqlite3_create_function_v2 (db, "radians", 1,
51591 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51592 				fnct_math_radians, 0, 0, 0);
51593     sqlite3_create_function_v2 (db, "sign", 1,
51594 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51595 				fnct_math_sign, 0, 0, 0);
51596     sqlite3_create_function_v2 (db, "sin", 1,
51597 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51598 				fnct_math_sin, 0, 0, 0);
51599     sqlite3_create_function_v2 (db, "stddev_pop", 1,
51600 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51601 				fnct_math_stddev_step,
51602 				fnct_math_stddev_pop_final, 0);
51603     sqlite3_create_function_v2 (db, "stddev_samp", 1,
51604 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51605 				fnct_math_stddev_step,
51606 				fnct_math_stddev_samp_final, 0);
51607     sqlite3_create_function_v2 (db, "sqrt", 1,
51608 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51609 				fnct_math_sqrt, 0, 0, 0);
51610     sqlite3_create_function_v2 (db, "tan", 1,
51611 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
51612 				fnct_math_tan, 0, 0, 0);
51613     sqlite3_create_function_v2 (db, "var_pop", 1,
51614 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51615 				fnct_math_stddev_step,
51616 				fnct_math_var_pop_final, 0);
51617     sqlite3_create_function_v2 (db, "var_samp", 1,
51618 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, 0,
51619 				fnct_math_stddev_step,
51620 				fnct_math_var_samp_final, 0);
51621 
51622 #endif /* end supporting SQL math functions */
51623 
51624 #ifndef OMIT_PROJ		/* including PROJ.4 */
51625 
51626     sqlite3_create_function_v2 (db, "Transform", 2,
51627 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51628 				fnct_Transform, 0, 0, 0);
51629     sqlite3_create_function_v2 (db, "ST_Transform", 2,
51630 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51631 				fnct_Transform, 0, 0, 0);
51632     sqlite3_create_function_v2 (db, "Transform", 3,
51633 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51634 				fnct_Transform, 0, 0, 0);
51635     sqlite3_create_function_v2 (db, "ST_Transform", 3,
51636 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51637 				fnct_Transform, 0, 0, 0);
51638     sqlite3_create_function_v2 (db, "Transform", 4,
51639 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51640 				fnct_Transform, 0, 0, 0);
51641     sqlite3_create_function_v2 (db, "ST_Transform", 4,
51642 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51643 				fnct_Transform, 0, 0, 0);
51644     sqlite3_create_function_v2 (db, "Transform", 5,
51645 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51646 				fnct_Transform, 0, 0, 0);
51647     sqlite3_create_function_v2 (db, "ST_Transform", 5,
51648 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51649 				fnct_Transform, 0, 0, 0);
51650     sqlite3_create_function_v2 (db, "TransformXY", 2,
51651 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51652 				fnct_TransformXY, 0, 0, 0);
51653     sqlite3_create_function_v2 (db, "ST_TransformXY", 2,
51654 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51655 				fnct_TransformXY, 0, 0, 0);
51656     sqlite3_create_function_v2 (db, "TransformXYZ", 2,
51657 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51658 				fnct_TransformXYZ, 0, 0, 0);
51659     sqlite3_create_function_v2 (db, "ST_TransformXYZ", 2,
51660 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51661 				fnct_TransformXYZ, 0, 0, 0);
51662 
51663 #ifdef PROJ_NEW			/* only if PROJ.6 is supported */
51664     sqlite3_create_function_v2 (db, "PROJ_GetLastErrorMsg", 0, SQLITE_UTF8,
51665 				cache, fnct_PROJ_GetLastErrorMsg, 0, 0, 0);
51666     sqlite3_create_function_v2 (db, "PROJ_GetDatabasePath", 0, SQLITE_UTF8,
51667 				cache, fnct_PROJ_GetDatabasePath, 0, 0, 0);
51668     sqlite3_create_function_v2 (db, "PROJ_SetDatabasePath", 1, SQLITE_UTF8,
51669 				cache, fnct_PROJ_SetDatabasePath, 0, 0, 0);
51670     sqlite3_create_function_v2 (db, "PROJ_AsProjString", 2, SQLITE_UTF8,
51671 				cache, fnct_PROJ_AsProjString, 0, 0, 0);
51672     sqlite3_create_function_v2 (db, "PROJ_AsWKT", 2, SQLITE_UTF8,
51673 				cache, fnct_PROJ_AsWKT, 0, 0, 0);
51674     sqlite3_create_function_v2 (db, "PROJ_AsWKT", 3, SQLITE_UTF8,
51675 				cache, fnct_PROJ_AsWKT, 0, 0, 0);
51676     sqlite3_create_function_v2 (db, "PROJ_AsWKT", 4, SQLITE_UTF8,
51677 				cache, fnct_PROJ_AsWKT, 0, 0, 0);
51678     sqlite3_create_function_v2 (db, "PROJ_AsWKT", 5, SQLITE_UTF8,
51679 				cache, fnct_PROJ_AsWKT, 0, 0, 0);
51680     sqlite3_create_function_v2 (db, "PROJ_GuessSridFromWKT", 1, SQLITE_UTF8,
51681 				cache, fnct_PROJ_GuessSridFromWKT, 0, 0, 0);
51682 #endif
51683 
51684 #endif /* end including PROJ.4 */
51685 
51686 #ifndef OMIT_GEOS		/* including GEOS */
51687 
51688     sqlite3_create_function_v2 (db, "GEOS_GetLastErrorMsg", 0, SQLITE_UTF8,
51689 				cache, fnct_GEOS_GetLastErrorMsg, 0, 0, 0);
51690     sqlite3_create_function_v2 (db, "GEOS_GetLastWarningMsg", 0, SQLITE_UTF8,
51691 				cache, fnct_GEOS_GetLastWarningMsg, 0, 0, 0);
51692     sqlite3_create_function_v2 (db, "GEOS_GetLastAuxErrorMsg", 0, SQLITE_UTF8,
51693 				cache, fnct_GEOS_GetLastAuxErrorMsg, 0, 0, 0);
51694     sqlite3_create_function_v2 (db, "GEOS_GetCriticalPointFromMsg", 0,
51695 				SQLITE_UTF8, cache,
51696 				fnct_GEOS_GetCriticalPointFromMsg, 0, 0, 0);
51697     sqlite3_create_function_v2 (db, "GEOS_GetCriticalPointFromMsg", 1,
51698 				SQLITE_UTF8, cache,
51699 				fnct_GEOS_GetCriticalPointFromMsg, 0, 0, 0);
51700     sqlite3_create_function_v2 (db, "IsValidReason", 1,
51701 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51702 				fnct_IsValidReason, 0, 0, 0);
51703     sqlite3_create_function_v2 (db, "IsValidReason", 2,
51704 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51705 				fnct_IsValidReason, 0, 0, 0);
51706     sqlite3_create_function_v2 (db, "ST_IsValidReason", 1,
51707 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51708 				fnct_IsValidReason, 0, 0, 0);
51709     sqlite3_create_function_v2 (db, "ST_IsValidReason", 2,
51710 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51711 				fnct_IsValidReason, 0, 0, 0);
51712     sqlite3_create_function_v2 (db, "IsValidDetail", 1,
51713 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51714 				fnct_IsValidDetail, 0, 0, 0);
51715     sqlite3_create_function_v2 (db, "IsValidDetail", 2,
51716 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51717 				fnct_IsValidDetail, 0, 0, 0);
51718     sqlite3_create_function_v2 (db, "ST_IsValidDetail", 1,
51719 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51720 				fnct_IsValidDetail, 0, 0, 0);
51721     sqlite3_create_function_v2 (db, "ST_IsValidDetail", 2,
51722 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51723 				fnct_IsValidDetail, 0, 0, 0);
51724 
51725     sqlite3_create_function_v2 (db, "Boundary", 1,
51726 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51727 				fnct_Boundary, 0, 0, 0);
51728     sqlite3_create_function_v2 (db, "ST_Boundary", 1,
51729 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51730 				fnct_Boundary, 0, 0, 0);
51731     sqlite3_create_function_v2 (db, "IsClosed", 1,
51732 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51733 				fnct_IsClosed, 0, 0, 0);
51734     sqlite3_create_function_v2 (db, "ST_IsClosed", 1,
51735 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51736 				fnct_IsClosed, 0, 0, 0);
51737     sqlite3_create_function_v2 (db, "IsSimple", 1,
51738 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51739 				fnct_IsSimple, 0, 0, 0);
51740     sqlite3_create_function_v2 (db, "ST_IsSimple", 1,
51741 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51742 				fnct_IsSimple, 0, 0, 0);
51743     sqlite3_create_function_v2 (db, "IsRing", 1,
51744 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51745 				fnct_IsRing, 0, 0, 0);
51746     sqlite3_create_function_v2 (db, "ST_IsRing", 1,
51747 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51748 				fnct_IsRing, 0, 0, 0);
51749     sqlite3_create_function_v2 (db, "IsValid", 1,
51750 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51751 				fnct_IsValid, 0, 0, 0);
51752     sqlite3_create_function_v2 (db, "IsValid", 2,
51753 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51754 				fnct_IsValid, 0, 0, 0);
51755     sqlite3_create_function_v2 (db, "ST_IsValid", 1,
51756 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51757 				fnct_IsValid, 0, 0, 0);
51758     sqlite3_create_function_v2 (db, "ST_IsValid", 2,
51759 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51760 				fnct_IsValid, 0, 0, 0);
51761     sqlite3_create_function_v2 (db, "GLength", 1,
51762 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51763 				fnct_Length, 0, 0, 0);
51764     sqlite3_create_function_v2 (db, "GLength", 2,
51765 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51766 				fnct_Length, 0, 0, 0);
51767     sqlite3_create_function_v2 (db, "ST_Length", 1,
51768 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51769 				fnct_Length, 0, 0, 0);
51770     sqlite3_create_function_v2 (db, "ST_Length", 2,
51771 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51772 				fnct_Length, 0, 0, 0);
51773     sqlite3_create_function_v2 (db, "Perimeter", 1,
51774 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51775 				fnct_Perimeter, 0, 0, 0);
51776     sqlite3_create_function_v2 (db, "Perimeter", 2,
51777 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51778 				fnct_Perimeter, 0, 0, 0);
51779     sqlite3_create_function_v2 (db, "ST_Perimeter", 1,
51780 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51781 				fnct_Perimeter, 0, 0, 0);
51782     sqlite3_create_function_v2 (db, "ST_Perimeter", 2,
51783 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51784 				fnct_Perimeter, 0, 0, 0);
51785     sqlite3_create_function_v2 (db, "LinestringMinSegmentLength", 1,
51786 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51787 				fnct_LinestringMinSegmentLength, 0, 0, 0);
51788     sqlite3_create_function_v2 (db, "ST_LinestringMinSegmentLength", 1,
51789 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51790 				fnct_LinestringMinSegmentLength, 0, 0, 0);
51791     sqlite3_create_function_v2 (db, "LinestringMinSegmentLength", 2,
51792 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51793 				fnct_LinestringMinSegmentLength, 0, 0, 0);
51794     sqlite3_create_function_v2 (db, "ST_LinestringMinSegmentLength", 2,
51795 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51796 				fnct_LinestringMinSegmentLength, 0, 0, 0);
51797     sqlite3_create_function_v2 (db, "LinestringMaxSegmentLength", 1,
51798 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51799 				fnct_LinestringMaxSegmentLength, 0, 0, 0);
51800     sqlite3_create_function_v2 (db, "ST_LinestringMaxSegmentLength", 1,
51801 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51802 				fnct_LinestringMaxSegmentLength, 0, 0, 0);
51803     sqlite3_create_function_v2 (db, "LinestringAvgSegmentLength", 1,
51804 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51805 				fnct_LinestringAvgSegmentLength, 0, 0, 0);
51806     sqlite3_create_function_v2 (db, "ST_LinestringAvgSegmentLength", 1,
51807 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51808 				fnct_LinestringAvgSegmentLength, 0, 0, 0);
51809     sqlite3_create_function_v2 (db, "CurvosityIndex", 1,
51810 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51811 				fnct_CurvosityIndex, 0, 0, 0);
51812     sqlite3_create_function_v2 (db, "ST_CurvosityIndex", 1,
51813 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51814 				fnct_CurvosityIndex, 0, 0, 0);
51815     sqlite3_create_function_v2 (db, "CurvosityIndex", 2,
51816 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51817 				fnct_CurvosityIndex, 0, 0, 0);
51818     sqlite3_create_function_v2 (db, "ST_CurvosityIndex", 2,
51819 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51820 				fnct_CurvosityIndex, 0, 0, 0);
51821     sqlite3_create_function_v2 (db, "UphillHeight", 1,
51822 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51823 				fnct_UphillHeight, 0, 0, 0);
51824     sqlite3_create_function_v2 (db, "ST_UphillHeight", 1,
51825 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51826 				fnct_UphillHeight, 0, 0, 0);
51827     sqlite3_create_function_v2 (db, "DownhillHeight", 1,
51828 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51829 				fnct_DownhillHeight, 0, 0, 0);
51830     sqlite3_create_function_v2 (db, "ST_DownhillHeight", 1,
51831 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51832 				fnct_DownhillHeight, 0, 0, 0);
51833     sqlite3_create_function_v2 (db, "UpDownHeight", 1,
51834 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51835 				fnct_UpDownHeight, 0, 0, 0);
51836     sqlite3_create_function_v2 (db, "ST_UpDownHeight", 1,
51837 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51838 				fnct_UpDownHeight, 0, 0, 0);
51839     sqlite3_create_function_v2 (db, "Area", 1,
51840 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51841 				fnct_Area, 0, 0, 0);
51842     sqlite3_create_function_v2 (db, "ST_Area", 1,
51843 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51844 				fnct_Area, 0, 0, 0);
51845     sqlite3_create_function_v2 (db, "Circularity", 1,
51846 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51847 				fnct_Circularity, 0, 0, 0);
51848     sqlite3_create_function_v2 (db, "ST_Centroid", 1,
51849 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51850 				fnct_Centroid, 0, 0, 0);
51851     sqlite3_create_function_v2 (db, "Centroid", 1,
51852 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51853 				fnct_Centroid, 0, 0, 0);
51854     sqlite3_create_function_v2 (db, "PointOnSurface", 1,
51855 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51856 				fnct_PointOnSurface, 0, 0, 0);
51857     sqlite3_create_function_v2 (db, "ST_PointOnSurface", 1,
51858 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51859 				fnct_PointOnSurface, 0, 0, 0);
51860     sqlite3_create_function_v2 (db, "Simplify", 2,
51861 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51862 				fnct_Simplify, 0, 0, 0);
51863     sqlite3_create_function_v2 (db, "ST_Simplify", 2,
51864 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51865 				fnct_Simplify, 0, 0, 0);
51866     sqlite3_create_function_v2 (db, "ST_Generalize", 2,
51867 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51868 				fnct_Simplify, 0, 0, 0);
51869     sqlite3_create_function_v2 (db, "SimplifyPreserveTopology", 2,
51870 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51871 				fnct_SimplifyPreserveTopology, 0, 0, 0);
51872     sqlite3_create_function_v2 (db, "ST_SimplifyPreserveTopology", 2,
51873 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51874 				fnct_SimplifyPreserveTopology, 0, 0, 0);
51875     sqlite3_create_function_v2 (db, "ConvexHull", 1,
51876 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51877 				fnct_ConvexHull, 0, 0, 0);
51878     sqlite3_create_function_v2 (db, "ST_ConvexHull", 1,
51879 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51880 				fnct_ConvexHull, 0, 0, 0);
51881     sqlite3_create_function_v2 (db, "Buffer", 2,
51882 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51883 				fnct_Buffer, 0, 0, 0);
51884     sqlite3_create_function_v2 (db, "ST_Buffer", 2,
51885 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51886 				fnct_Buffer, 0, 0, 0);
51887     sqlite3_create_function_v2 (db, "Buffer", 3,
51888 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51889 				fnct_Buffer, 0, 0, 0);
51890     sqlite3_create_function_v2 (db, "ST_Buffer", 3,
51891 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51892 				fnct_Buffer, 0, 0, 0);
51893     sqlite3_create_function_v2 (db, "Intersection", 2,
51894 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51895 				fnct_Intersection, 0, 0, 0);
51896     sqlite3_create_function_v2 (db, "ST_Intersection", 2,
51897 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51898 				fnct_Intersection, 0, 0, 0);
51899     sqlite3_create_function_v2 (db, "GUnion", 1,
51900 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
51901 				fnct_Union_step, fnct_Union_final, 0);
51902     sqlite3_create_function_v2 (db, "GUnion", 2,
51903 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51904 				fnct_Union, 0, 0, 0);
51905     sqlite3_create_function_v2 (db, "ST_Union", 1,
51906 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache, 0,
51907 				fnct_Union_step, fnct_Union_final, 0);
51908     sqlite3_create_function_v2 (db, "ST_Union", 2,
51909 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51910 				fnct_Union, 0, 0, 0);
51911     sqlite3_create_function_v2 (db, "Difference", 2,
51912 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51913 				fnct_Difference, 0, 0, 0);
51914     sqlite3_create_function_v2 (db, "ST_Difference", 2,
51915 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51916 				fnct_Difference, 0, 0, 0);
51917     sqlite3_create_function_v2 (db, "SymDifference", 2,
51918 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51919 				fnct_SymDifference, 0, 0, 0);
51920     sqlite3_create_function_v2 (db, "ST_SymDifference", 2,
51921 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51922 				fnct_SymDifference, 0, 0, 0);
51923     sqlite3_create_function_v2 (db, "Equals", 2,
51924 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51925 				fnct_Equals, 0, 0, 0);
51926     sqlite3_create_function_v2 (db, "ST_Equals", 2,
51927 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51928 				fnct_Equals, 0, 0, 0);
51929     sqlite3_create_function_v2 (db, "Intersects", 2,
51930 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51931 				fnct_Intersects, 0, 0, 0);
51932     sqlite3_create_function_v2 (db, "ST_Intersects", 2,
51933 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51934 				fnct_Intersects, 0, 0, 0);
51935     sqlite3_create_function_v2 (db, "Disjoint", 2,
51936 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51937 				fnct_Disjoint, 0, 0, 0);
51938     sqlite3_create_function_v2 (db, "ST_Disjoint", 2,
51939 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51940 				fnct_Disjoint, 0, 0, 0);
51941     sqlite3_create_function_v2 (db, "Overlaps", 2,
51942 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51943 				fnct_Overlaps, 0, 0, 0);
51944     sqlite3_create_function_v2 (db, "ST_Overlaps", 2,
51945 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51946 				fnct_Overlaps, 0, 0, 0);
51947     sqlite3_create_function_v2 (db, "Crosses", 2,
51948 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51949 				fnct_Crosses, 0, 0, 0);
51950     sqlite3_create_function_v2 (db, "ST_Crosses", 2,
51951 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51952 				fnct_Crosses, 0, 0, 0);
51953     sqlite3_create_function_v2 (db, "Touches", 2,
51954 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51955 				fnct_Touches, 0, 0, 0);
51956     sqlite3_create_function_v2 (db, "ST_Touches", 2,
51957 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51958 				fnct_Touches, 0, 0, 0);
51959     sqlite3_create_function_v2 (db, "Within", 2,
51960 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51961 				fnct_Within, 0, 0, 0);
51962     sqlite3_create_function_v2 (db, "ST_Within", 2,
51963 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51964 				fnct_Within, 0, 0, 0);
51965     sqlite3_create_function_v2 (db, "Contains", 2,
51966 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51967 				fnct_Contains, 0, 0, 0);
51968     sqlite3_create_function_v2 (db, "ST_Contains", 2,
51969 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51970 				fnct_Contains, 0, 0, 0);
51971     sqlite3_create_function_v2 (db, "Relate", 2,
51972 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51973 				fnct_Relate, 0, 0, 0);
51974     sqlite3_create_function_v2 (db, "Relate", 3,
51975 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51976 				fnct_Relate, 0, 0, 0);
51977     sqlite3_create_function_v2 (db, "ST_Relate", 2,
51978 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51979 				fnct_Relate, 0, 0, 0);
51980     sqlite3_create_function_v2 (db, "ST_Relate", 3,
51981 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51982 				fnct_Relate, 0, 0, 0);
51983     sqlite3_create_function_v2 (db, "ST_RelateMatch", 2,
51984 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51985 				fnct_RelateMatch, 0, 0, 0);
51986     sqlite3_create_function_v2 (db, "Distance", 2,
51987 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51988 				fnct_Distance, 0, 0, 0);
51989     sqlite3_create_function_v2 (db, "Distance", 3,
51990 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51991 				fnct_Distance, 0, 0, 0);
51992     sqlite3_create_function_v2 (db, "ST_Distance", 2,
51993 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51994 				fnct_Distance, 0, 0, 0);
51995     sqlite3_create_function_v2 (db, "ST_Distance", 3,
51996 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
51997 				fnct_Distance, 0, 0, 0);
51998     sqlite3_create_function_v2 (db, "PtDistWithin", 3,
51999 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52000 				fnct_PtDistWithin, 0, 0, 0);
52001     sqlite3_create_function_v2 (db, "PtDistWithin", 4,
52002 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52003 				fnct_PtDistWithin, 0, 0, 0);
52004     sqlite3_create_function_v2 (db, "BdPolyFromText", 1,
52005 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52006 				fnct_BdPolyFromText1, 0, 0, 0);
52007     sqlite3_create_function_v2 (db, "BdPolyFromText", 2,
52008 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52009 				fnct_BdPolyFromText2, 0, 0, 0);
52010     sqlite3_create_function_v2 (db, "BdMPolyFromText", 1,
52011 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52012 				fnct_BdMPolyFromText1, 0, 0, 0);
52013     sqlite3_create_function_v2 (db, "BdMPolyFromText", 2,
52014 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52015 				fnct_BdMPolyFromText2, 0, 0, 0);
52016     sqlite3_create_function_v2 (db, "BdPolyFromWKB", 1,
52017 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52018 				fnct_BdPolyFromWKB1, 0, 0, 0);
52019     sqlite3_create_function_v2 (db, "BdPolyFromWKB", 2,
52020 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52021 				fnct_BdPolyFromWKB2, 0, 0, 0);
52022     sqlite3_create_function_v2 (db, "BdMPolyFromWKB", 1,
52023 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52024 				fnct_BdMPolyFromWKB1, 0, 0, 0);
52025     sqlite3_create_function_v2 (db, "BdMPolyFromWKB", 2,
52026 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52027 				fnct_BdMPolyFromWKB2, 0, 0, 0);
52028     sqlite3_create_function_v2 (db, "ST_BdPolyFromText", 1,
52029 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52030 				fnct_BdPolyFromText1, 0, 0, 0);
52031     sqlite3_create_function_v2 (db, "ST_BdPolyFromText", 2,
52032 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52033 				fnct_BdPolyFromText2, 0, 0, 0);
52034     sqlite3_create_function_v2 (db, "ST_BdMPolyFromText", 1,
52035 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52036 				fnct_BdMPolyFromText1, 0, 0, 0);
52037     sqlite3_create_function_v2 (db, "ST_BdMPolyFromText", 2,
52038 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52039 				fnct_BdMPolyFromText2, 0, 0, 0);
52040     sqlite3_create_function_v2 (db, "ST_BdPolyFromWKB", 1,
52041 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52042 				fnct_BdPolyFromWKB1, 0, 0, 0);
52043     sqlite3_create_function_v2 (db, "ST_BdPolyFromWKB", 2,
52044 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52045 				fnct_BdPolyFromWKB2, 0, 0, 0);
52046     sqlite3_create_function_v2 (db, "ST_BdMPolyFromWKB", 1,
52047 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52048 				fnct_BdMPolyFromWKB1, 0, 0, 0);
52049     sqlite3_create_function_v2 (db, "ST_BdMPolyFromWKB", 2,
52050 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52051 				fnct_BdMPolyFromWKB2, 0, 0, 0);
52052     sqlite3_create_function_v2 (db, "OffsetCurve", 2,
52053 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52054 				fnct_OffsetCurve, 0, 0, 0);
52055     sqlite3_create_function_v2 (db, "ST_OffsetCurve", 2,
52056 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52057 				fnct_OffsetCurve, 0, 0, 0);
52058     sqlite3_create_function_v2 (db, "SingleSidedBuffer", 3,
52059 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52060 				fnct_SingleSidedBuffer, 0, 0, 0);
52061     sqlite3_create_function_v2 (db, "ST_SingleSidedBuffer", 3,
52062 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52063 				fnct_SingleSidedBuffer, 0, 0, 0);
52064     sqlite3_create_function_v2 (db, "HausdorffDistance", 2,
52065 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52066 				fnct_HausdorffDistance, 0, 0, 0);
52067     sqlite3_create_function_v2 (db, "ST_HausdorffDistance", 2,
52068 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52069 				fnct_HausdorffDistance, 0, 0, 0);
52070 
52071 #ifdef GEOS_370			/* only if GEOS_370 support is available */
52072     sqlite3_create_function_v2 (db, "HausdorffDistance", 3,
52073 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52074 				fnct_HausdorffDistanceDensify, 0, 0, 0);
52075     sqlite3_create_function_v2 (db, "ST_HausdorffDistance", 3,
52076 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52077 				fnct_HausdorffDistanceDensify, 0, 0, 0);
52078     sqlite3_create_function_v2 (db, "FrechetDistance", 2,
52079 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52080 				fnct_FrechetDistance, 0, 0, 0);
52081     sqlite3_create_function_v2 (db, "ST_FrechetDistance", 2,
52082 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52083 				fnct_FrechetDistance, 0, 0, 0);
52084     sqlite3_create_function_v2 (db, "FrechetDistance", 3,
52085 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52086 				fnct_FrechetDistanceDensify, 0, 0, 0);
52087     sqlite3_create_function_v2 (db, "ST_FrechetDistance", 3,
52088 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52089 				fnct_FrechetDistanceDensify, 0, 0, 0);
52090 #endif /* end GEOS_370 conditional */
52091 
52092     sqlite3_create_function_v2 (db, "SharedPaths", 2,
52093 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52094 				fnct_SharedPaths, 0, 0, 0);
52095     sqlite3_create_function_v2 (db, "ST_SharedPaths", 2,
52096 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52097 				fnct_SharedPaths, 0, 0, 0);
52098     sqlite3_create_function_v2 (db, "Covers", 2,
52099 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52100 				fnct_Covers, 0, 0, 0);
52101     sqlite3_create_function_v2 (db, "ST_Covers", 2,
52102 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52103 				fnct_Covers, 0, 0, 0);
52104     sqlite3_create_function_v2 (db, "CoveredBy", 2,
52105 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52106 				fnct_CoveredBy, 0, 0, 0);
52107     sqlite3_create_function_v2 (db, "ST_CoveredBy", 2,
52108 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52109 				fnct_CoveredBy, 0, 0, 0);
52110     sqlite3_create_function_v2 (db, "Line_Interpolate_Point", 2,
52111 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52112 				fnct_LineInterpolatePoint, 0, 0, 0);
52113     sqlite3_create_function_v2 (db, "ST_Line_Interpolate_Point", 2,
52114 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52115 				fnct_LineInterpolatePoint, 0, 0, 0);
52116     sqlite3_create_function_v2 (db, "Line_Interpolate_Equidistant_Points", 2,
52117 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52118 				fnct_LineInterpolateEquidistantPoints, 0, 0, 0);
52119     sqlite3_create_function_v2 (db, "ST_Line_Interpolate_Equidistant_Points",
52120 				2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52121 				fnct_LineInterpolateEquidistantPoints, 0, 0, 0);
52122     sqlite3_create_function_v2 (db, "Line_Locate_Point", 2,
52123 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52124 				fnct_LineLocatePoint, 0, 0, 0);
52125     sqlite3_create_function_v2 (db, "ST_Line_Locate_Point", 2,
52126 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52127 				fnct_LineLocatePoint, 0, 0, 0);
52128     sqlite3_create_function_v2 (db, "Line_Substring", 3,
52129 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52130 				fnct_LineSubstring, 0, 0, 0);
52131     sqlite3_create_function_v2 (db, "ST_Line_Substring", 3,
52132 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52133 				fnct_LineSubstring, 0, 0, 0);
52134     sqlite3_create_function_v2 (db, "ClosestPoint", 2,
52135 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52136 				fnct_ClosestPoint, 0, 0, 0);
52137     sqlite3_create_function_v2 (db, "ST_ClosestPoint", 2,
52138 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52139 				fnct_ClosestPoint, 0, 0, 0);
52140     sqlite3_create_function_v2 (db, "ShortestLine", 2,
52141 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52142 				fnct_ShortestLine, 0, 0, 0);
52143     sqlite3_create_function_v2 (db, "ST_ShortestLine", 2,
52144 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52145 				fnct_ShortestLine, 0, 0, 0);
52146     sqlite3_create_function_v2 (db, "Snap", 3,
52147 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52148 				fnct_Snap, 0, 0, 0);
52149     sqlite3_create_function_v2 (db, "ST_Snap", 3,
52150 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52151 				fnct_Snap, 0, 0, 0);
52152     sqlite3_create_function_v2 (db, "LineMerge", 1,
52153 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52154 				fnct_LineMerge, 0, 0, 0);
52155     sqlite3_create_function_v2 (db, "ST_LineMerge", 1,
52156 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52157 				fnct_LineMerge, 0, 0, 0);
52158     sqlite3_create_function_v2 (db, "UnaryUnion", 1,
52159 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52160 				fnct_UnaryUnion, 0, 0, 0);
52161     sqlite3_create_function_v2 (db, "ST_UnaryUnion", 1,
52162 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52163 				fnct_UnaryUnion, 0, 0, 0);
52164     sqlite3_create_function_v2 (db, "SquareGrid", 2,
52165 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52166 				fnct_SquareGrid, 0, 0, 0);
52167     sqlite3_create_function_v2 (db, "SquareGrid", 3,
52168 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52169 				fnct_SquareGrid, 0, 0, 0);
52170     sqlite3_create_function_v2 (db, "SquareGrid", 4,
52171 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52172 				fnct_SquareGrid, 0, 0, 0);
52173     sqlite3_create_function_v2 (db, "ST_SquareGrid", 2,
52174 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52175 				fnct_SquareGrid, 0, 0, 0);
52176     sqlite3_create_function_v2 (db, "ST_SquareGrid", 3,
52177 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52178 				fnct_SquareGrid, 0, 0, 0);
52179     sqlite3_create_function_v2 (db, "ST_SquareGrid", 4,
52180 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52181 				fnct_SquareGrid, 0, 0, 0);
52182     sqlite3_create_function_v2 (db, "TriangularGrid", 2,
52183 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52184 				fnct_TriangularGrid, 0, 0, 0);
52185     sqlite3_create_function_v2 (db, "TriangularGrid", 3,
52186 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52187 				fnct_TriangularGrid, 0, 0, 0);
52188     sqlite3_create_function_v2 (db, "TriangularGrid", 4,
52189 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52190 				fnct_TriangularGrid, 0, 0, 0);
52191     sqlite3_create_function_v2 (db, "ST_TriangularGrid", 2,
52192 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52193 				fnct_TriangularGrid, 0, 0, 0);
52194     sqlite3_create_function_v2 (db, "ST_TriangularGrid", 3,
52195 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52196 				fnct_TriangularGrid, 0, 0, 0);
52197     sqlite3_create_function_v2 (db, "ST_TriangularGrid", 4,
52198 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52199 				fnct_TriangularGrid, 0, 0, 0);
52200     sqlite3_create_function_v2 (db, "HexagonalGrid", 2,
52201 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52202 				fnct_HexagonalGrid, 0, 0, 0);
52203     sqlite3_create_function_v2 (db, "HexagonalGrid", 3,
52204 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52205 				fnct_HexagonalGrid, 0, 0, 0);
52206     sqlite3_create_function_v2 (db, "HexagonalGrid", 4,
52207 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52208 				fnct_HexagonalGrid, 0, 0, 0);
52209     sqlite3_create_function_v2 (db, "ST_HexagonalGrid", 2,
52210 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52211 				fnct_HexagonalGrid, 0, 0, 0);
52212     sqlite3_create_function_v2 (db, "ST_HexagonalGrid", 3,
52213 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52214 				fnct_HexagonalGrid, 0, 0, 0);
52215     sqlite3_create_function_v2 (db, "ST_HexagonalGrid", 4,
52216 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52217 				fnct_HexagonalGrid, 0, 0, 0);
52218     sqlite3_create_function_v2 (db, "LinesCutAtNodes", 2,
52219 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52220 				fnct_LinesCutAtNodes, 0, 0, 0);
52221     sqlite3_create_function_v2 (db, "ST_LinesCutAtNodes", 2,
52222 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52223 				fnct_LinesCutAtNodes, 0, 0, 0);
52224     sqlite3_create_function_v2 (db, "RingsCutAtNodes", 1,
52225 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52226 				fnct_RingsCutAtNodes, 0, 0, 0);
52227     sqlite3_create_function_v2 (db, "ST_RingsCutAtNodes", 1,
52228 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52229 				fnct_RingsCutAtNodes, 0, 0, 0);
52230 
52231 #ifdef GEOS_ADVANCED		/* GEOS advanced features - 3.4.0 */
52232 
52233     sqlite3_create_function_v2 (db, "DelaunayTriangulation", 1,
52234 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52235 				fnct_DelaunayTriangulation, 0, 0, 0);
52236     sqlite3_create_function_v2 (db, "DelaunayTriangulation", 2,
52237 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52238 				fnct_DelaunayTriangulation, 0, 0, 0);
52239     sqlite3_create_function_v2 (db, "DelaunayTriangulation", 3,
52240 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52241 				fnct_DelaunayTriangulation, 0, 0, 0);
52242     sqlite3_create_function_v2 (db, "ST_DelaunayTriangulation", 1,
52243 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52244 				fnct_DelaunayTriangulation, 0, 0, 0);
52245     sqlite3_create_function_v2 (db, "ST_DelaunayTriangulation", 2,
52246 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52247 				fnct_DelaunayTriangulation, 0, 0, 0);
52248     sqlite3_create_function_v2 (db, "ST_DelaunayTriangulation", 3,
52249 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52250 				fnct_DelaunayTriangulation, 0, 0, 0);
52251     sqlite3_create_function_v2 (db, "VoronojDiagram", 1,
52252 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52253 				fnct_VoronojDiagram, 0, 0, 0);
52254     sqlite3_create_function_v2 (db, "VoronojDiagram", 2,
52255 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52256 				fnct_VoronojDiagram, 0, 0, 0);
52257     sqlite3_create_function_v2 (db, "VoronojDiagram", 3,
52258 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52259 				fnct_VoronojDiagram, 0, 0, 0);
52260     sqlite3_create_function_v2 (db, "VoronojDiagram", 4,
52261 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52262 				fnct_VoronojDiagram, 0, 0, 0);
52263     sqlite3_create_function_v2 (db, "ST_VoronojDiagram", 1,
52264 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52265 				fnct_VoronojDiagram, 0, 0, 0);
52266     sqlite3_create_function_v2 (db, "ST_VoronojDiagram", 2,
52267 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52268 				fnct_VoronojDiagram, 0, 0, 0);
52269     sqlite3_create_function_v2 (db, "ST_VoronojDiagram", 3,
52270 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52271 				fnct_VoronojDiagram, 0, 0, 0);
52272     sqlite3_create_function_v2 (db, "ST_VoronojDiagram", 4,
52273 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52274 				fnct_VoronojDiagram, 0, 0, 0);
52275     sqlite3_create_function_v2 (db, "ConcaveHull", 1,
52276 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52277 				fnct_ConcaveHull, 0, 0, 0);
52278     sqlite3_create_function_v2 (db, "ConcaveHull", 2,
52279 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52280 				fnct_ConcaveHull, 0, 0, 0);
52281     sqlite3_create_function_v2 (db, "ConcaveHull", 3,
52282 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52283 				fnct_ConcaveHull, 0, 0, 0);
52284     sqlite3_create_function_v2 (db, "ConcaveHull", 4,
52285 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52286 				fnct_ConcaveHull, 0, 0, 0);
52287     sqlite3_create_function_v2 (db, "ST_ConcaveHull", 1,
52288 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52289 				fnct_ConcaveHull, 0, 0, 0);
52290     sqlite3_create_function_v2 (db, "ST_ConcaveHull", 2,
52291 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52292 				fnct_ConcaveHull, 0, 0, 0);
52293     sqlite3_create_function_v2 (db, "ST_ConcaveHull", 3,
52294 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52295 				fnct_ConcaveHull, 0, 0, 0);
52296     sqlite3_create_function_v2 (db, "ST_ConcaveHull", 4,
52297 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52298 				fnct_ConcaveHull, 0, 0, 0);
52299 
52300 #endif /* end GEOS advanced features */
52301 
52302 #ifdef ENABLE_RTTOPO		/* enabling RTTOPO support */
52303 
52304     sqlite3_create_function_v2 (db, "RTTOPO_GetLastErrorMsg", 0, SQLITE_UTF8,
52305 				0, fnct_RTTOPO_GetLastErrorMsg, 0, 0, 0);
52306     sqlite3_create_function_v2 (db, "RTTOPO_GetLastWarningMsg", 0,
52307 				SQLITE_UTF8, 0, fnct_RTTOPO_GetLastWarningMsg,
52308 				0, 0, 0);
52309 
52310     sqlite3_create_function_v2 (db, "MakeValid", 1,
52311 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52312 				fnct_MakeValid, 0, 0, 0);
52313     sqlite3_create_function_v2 (db, "ST_MakeValid", 1,
52314 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52315 				fnct_MakeValid, 0, 0, 0);
52316     sqlite3_create_function_v2 (db, "MakeValidDiscarded", 1,
52317 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52318 				fnct_MakeValidDiscarded, 0, 0, 0);
52319     sqlite3_create_function_v2 (db, "ST_MakeValidDiscarded", 1,
52320 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52321 				fnct_MakeValidDiscarded, 0, 0, 0);
52322     sqlite3_create_function_v2 (db, "Area", 2,
52323 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52324 				fnct_Area, 0, 0, 0);
52325     sqlite3_create_function_v2 (db, "ST_Area", 2,
52326 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52327 				fnct_Area, 0, 0, 0);
52328     sqlite3_create_function_v2 (db, "Circularity", 2,
52329 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52330 				fnct_Circularity, 0, 0, 0);
52331     sqlite3_create_function_v2 (db, "Segmentize", 2,
52332 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52333 				fnct_Segmentize, 0, 0, 0);
52334     sqlite3_create_function_v2 (db, "ST_Segmentize", 2,
52335 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52336 				fnct_Segmentize, 0, 0, 0);
52337     sqlite3_create_function_v2 (db, "Azimuth", 2,
52338 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52339 				fnct_Azimuth, 0, 0, 0);
52340     sqlite3_create_function_v2 (db, "ST_Azimuth", 2,
52341 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52342 				fnct_Azimuth, 0, 0, 0);
52343     sqlite3_create_function_v2 (db, "Project", 3,
52344 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52345 				fnct_Project, 0, 0, 0);
52346     sqlite3_create_function_v2 (db, "ST_Project", 3,
52347 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52348 				fnct_Project, 0, 0, 0);
52349     sqlite3_create_function_v2 (db, "GeoHash", 1,
52350 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52351 				fnct_GeoHash, 0, 0, 0);
52352     sqlite3_create_function_v2 (db, "GeoHash", 2,
52353 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52354 				fnct_GeoHash, 0, 0, 0);
52355     sqlite3_create_function_v2 (db, "ST_GeoHash", 1,
52356 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52357 				fnct_GeoHash, 0, 0, 0);
52358     sqlite3_create_function_v2 (db, "ST_GeoHash", 2,
52359 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52360 				fnct_GeoHash, 0, 0, 0);
52361     sqlite3_create_function_v2 (db, "AsX3D", 1,
52362 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52363 				fnct_AsX3D, 0, 0, 0);
52364     sqlite3_create_function_v2 (db, "AsX3D", 2,
52365 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52366 				fnct_AsX3D, 0, 0, 0);
52367     sqlite3_create_function_v2 (db, "AsX3D", 3,
52368 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52369 				fnct_AsX3D, 0, 0, 0);
52370     sqlite3_create_function_v2 (db, "AsX3D", 4,
52371 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52372 				fnct_AsX3D, 0, 0, 0);
52373     sqlite3_create_function_v2 (db, "ST_AsX3D", 1,
52374 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52375 				fnct_AsX3D, 0, 0, 0);
52376     sqlite3_create_function_v2 (db, "ST_AsX3D", 2,
52377 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52378 				fnct_AsX3D, 0, 0, 0);
52379     sqlite3_create_function_v2 (db, "ST_AsX3D", 3,
52380 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52381 				fnct_AsX3D, 0, 0, 0);
52382     sqlite3_create_function_v2 (db, "ST_AsX3D", 4,
52383 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52384 				fnct_AsX3D, 0, 0, 0);
52385     sqlite3_create_function_v2 (db, "ST_3DDistance", 2,
52386 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52387 				fnct_3DDistance, 0, 0, 0);
52388     sqlite3_create_function_v2 (db, "MaxDistance", 2,
52389 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52390 				fnct_MaxDistance, 0, 0, 0);
52391     sqlite3_create_function_v2 (db, "ST_MaxDistance", 2,
52392 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52393 				fnct_MaxDistance, 0, 0, 0);
52394     sqlite3_create_function_v2 (db, "ST_3DMaxDistance", 2,
52395 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52396 				fnct_3DMaxDistance, 0, 0, 0);
52397     sqlite3_create_function_v2 (db, "Split", 2,
52398 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52399 				fnct_Split, 0, 0, 0);
52400     sqlite3_create_function_v2 (db, "ST_Split", 2,
52401 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52402 				fnct_Split, 0, 0, 0);
52403     sqlite3_create_function_v2 (db, "SplitLeft", 2,
52404 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52405 				fnct_SplitLeft, 0, 0, 0);
52406     sqlite3_create_function_v2 (db, "ST_SplitLeft", 2,
52407 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52408 				fnct_SplitLeft, 0, 0, 0);
52409     sqlite3_create_function_v2 (db, "SplitRight", 2,
52410 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52411 				fnct_SplitRight, 0, 0, 0);
52412     sqlite3_create_function_v2 (db, "ST_SplitRight", 2,
52413 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52414 				fnct_SplitRight, 0, 0, 0);
52415     sqlite3_create_function_v2 (db, "SnapAndSplit", 3,
52416 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52417 				fnct_SnapAndSplit, 0, 0, 0);
52418     sqlite3_create_function_v2 (db, "ST_SnapAndSplit", 3,
52419 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52420 				fnct_SnapAndSplit, 0, 0, 0);
52421     sqlite3_create_function_v2 (db, "ST_Node", 1,
52422 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52423 				fnct_Node, 0, 0, 0);
52424     sqlite3_create_function_v2 (db, "SelfIntersections", 1,
52425 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52426 				fnct_SelfIntersections, 0, 0, 0);
52427     sqlite3_create_function_v2 (db, "ST_SelfIntersections", 1,
52428 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52429 				fnct_SelfIntersections, 0, 0, 0);
52430     sqlite3_create_function_v2 (db, "ST_Subdivide", 1,
52431 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52432 				fnct_Subdivide, 0, 0, 0);
52433     sqlite3_create_function_v2 (db, "ST_Subdivide", 2,
52434 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52435 				fnct_Subdivide, 0, 0, 0);
52436     sqlite3_create_function_v2 (db, "ST_3dLength", 1,
52437 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52438 				fnct_3dLength, 0, 0, 0);
52439     sqlite3_create_function_v2 (db, "GeomFromTWKB", 1,
52440 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52441 				fnct_FromTWKB, 0, 0, 0);
52442     sqlite3_create_function_v2 (db, "GeomFromTWKB", 2,
52443 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52444 				fnct_FromTWKB, 0, 0, 0);
52445     sqlite3_create_function_v2 (db, "AsTWKB", 1,
52446 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52447 				fnct_ToTWKB, 0, 0, 0);
52448     sqlite3_create_function_v2 (db, "AsTWKB", 2,
52449 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52450 				fnct_ToTWKB, 0, 0, 0);
52451     sqlite3_create_function_v2 (db, "AsTWKB", 3,
52452 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52453 				fnct_ToTWKB, 0, 0, 0);
52454     sqlite3_create_function_v2 (db, "AsTWKB", 4,
52455 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52456 				fnct_ToTWKB, 0, 0, 0);
52457     sqlite3_create_function_v2 (db, "AsTWKB", 5,
52458 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52459 				fnct_ToTWKB, 0, 0, 0);
52460     sqlite3_create_function_v2 (db, "AsTWKB", 6,
52461 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52462 				fnct_ToTWKB, 0, 0, 0);
52463     sqlite3_create_function_v2 (db, "ST_AsEncodedPolyline", 1,
52464 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52465 				fnct_AsEncodedPolyline, 0, 0, 0);
52466     sqlite3_create_function_v2 (db, "ST_AsEncodedPolyline", 2,
52467 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52468 				fnct_AsEncodedPolyline, 0, 0, 0);
52469     sqlite3_create_function_v2 (db, "ST_LineFromEncodedPolyline", 1,
52470 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52471 				fnct_LineFromEncodedPolyline, 0, 0, 0);
52472     sqlite3_create_function_v2 (db, "ST_LineFromEncodedPolyline", 2,
52473 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52474 				fnct_LineFromEncodedPolyline, 0, 0, 0);
52475 
52476 #endif /* end RTTOPO support */
52477 
52478     sqlite3_create_function_v2 (db, "ST_Cutter", 7,
52479 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52480 				fnct_Cutter, 0, 0, 0);
52481     sqlite3_create_function_v2 (db, "ST_Cutter", 8,
52482 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52483 				fnct_Cutter, 0, 0, 0);
52484     sqlite3_create_function_v2 (db, "ST_Cutter", 9,
52485 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52486 				fnct_Cutter, 0, 0, 0);
52487     sqlite3_create_function_v2 (db, "GetCutterMessage", 0,
52488 				SQLITE_UTF8, cache,
52489 				fnct_GetCutterMessage, 0, 0, 0);
52490     sqlite3_create_function_v2 (db, "ST_DrapeLine", 2,
52491 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52492 				fnct_DrapeLine, 0, 0, 0);
52493     sqlite3_create_function_v2 (db, "ST_DrapeLine", 3,
52494 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52495 				fnct_DrapeLine, 0, 0, 0);
52496     sqlite3_create_function_v2 (db, "ST_DrapeLineExceptions", 2,
52497 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52498 				fnct_DrapeLineExceptions, 0, 0, 0);
52499     sqlite3_create_function_v2 (db, "ST_DrapeLineExceptions", 3,
52500 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52501 				fnct_DrapeLineExceptions, 0, 0, 0);
52502     sqlite3_create_function_v2 (db, "ST_DrapeLineExceptions", 4,
52503 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52504 				fnct_DrapeLineExceptions, 0, 0, 0);
52505 
52506 #endif /* end including GEOS */
52507 
52508 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
52509 
52510     sqlite3_create_function_v2 (db, "CreateStylingTables", 0,
52511 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52512 				fnct_CreateStylingTables, 0, 0, 0);
52513     sqlite3_create_function_v2 (db, "CreateStylingTables", 1,
52514 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52515 				fnct_CreateStylingTables, 0, 0, 0);
52516     sqlite3_create_function_v2 (db, "CreateStylingTables", 2,
52517 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52518 				fnct_CreateStylingTables, 0, 0, 0);
52519     sqlite3_create_function_v2 (db, "ReCreateStylingTriggers", 0,
52520 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52521 				fnct_ReCreateStylingTriggers, 0, 0, 0);
52522     sqlite3_create_function_v2 (db, "ReCreateStylingTriggers", 1,
52523 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52524 				fnct_ReCreateStylingTriggers, 0, 0, 0);
52525     sqlite3_create_function_v2 (db, "ReCreateStylingTriggers", 2,
52526 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52527 				fnct_ReCreateStylingTriggers, 0, 0, 0);
52528     sqlite3_create_function (db, "SE_RegisterVectorCoverage", 3, SQLITE_ANY,
52529 			     0, fnct_RegisterVectorCoverage, 0, 0);
52530     sqlite3_create_function (db, "SE_RegisterVectorCoverage", 5, SQLITE_ANY,
52531 			     0, fnct_RegisterVectorCoverage, 0, 0);
52532     sqlite3_create_function (db, "SE_RegisterVectorCoverage", 7, SQLITE_ANY,
52533 			     0, fnct_RegisterVectorCoverage, 0, 0);
52534     sqlite3_create_function (db, "SE_RegisterSpatialViewCoverage", 3,
52535 			     SQLITE_ANY, 0, fnct_RegisterSpatialViewCoverage,
52536 			     0, 0);
52537     sqlite3_create_function (db, "SE_RegisterSpatialViewCoverage", 5,
52538 			     SQLITE_ANY, 0, fnct_RegisterSpatialViewCoverage,
52539 			     0, 0);
52540     sqlite3_create_function (db, "SE_RegisterSpatialViewCoverage", 7,
52541 			     SQLITE_ANY, 0, fnct_RegisterSpatialViewCoverage,
52542 			     0, 0);
52543     sqlite3_create_function (db, "SE_RegisterVirtualShapeCoverage", 3,
52544 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52545 			     0, 0);
52546     sqlite3_create_function (db, "SE_RegisterVirtualShapeCoverage", 5,
52547 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52548 			     0, 0);
52549     sqlite3_create_function (db, "SE_RegisterVirtualShapeCoverage", 6,
52550 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52551 			     0, 0);
52552     sqlite3_create_function (db, "SE_RegisterVirtualGeoJsonCoverage", 3,
52553 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52554 			     0, 0);
52555     sqlite3_create_function (db, "SE_RegisterVirtualGeoJsonCoverage", 5,
52556 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52557 			     0, 0);
52558     sqlite3_create_function (db, "SE_RegisterVirtualGeoJsonCoverage", 6,
52559 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52560 			     0, 0);
52561     sqlite3_create_function (db, "SE_RegisterVirtualTableCoverage", 3,
52562 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52563 			     0, 0);
52564     sqlite3_create_function (db, "SE_RegisterVirtualTableCoverage", 5,
52565 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52566 			     0, 0);
52567     sqlite3_create_function (db, "SE_RegisterVirtualTableCoverage", 6,
52568 			     SQLITE_ANY, 0, fnct_RegisterVirtualTableCoverage,
52569 			     0, 0);
52570     sqlite3_create_function (db, "SE_RegisterTopoGeoCoverage", 2, SQLITE_ANY,
52571 			     0, fnct_RegisterTopoGeoCoverage, 0, 0);
52572     sqlite3_create_function (db, "SE_RegisterTopoGeoCoverage", 4, SQLITE_ANY,
52573 			     0, fnct_RegisterTopoGeoCoverage, 0, 0);
52574     sqlite3_create_function (db, "SE_RegisterTopoGeoCoverage", 6, SQLITE_ANY,
52575 			     0, fnct_RegisterTopoGeoCoverage, 0, 0);
52576     sqlite3_create_function (db, "SE_RegisterTopoNetCoverage", 2, SQLITE_ANY,
52577 			     0, fnct_RegisterTopoNetCoverage, 0, 0);
52578     sqlite3_create_function (db, "SE_RegisterTopoNetCoverage", 4, SQLITE_ANY,
52579 			     0, fnct_RegisterTopoNetCoverage, 0, 0);
52580     sqlite3_create_function (db, "SE_RegisterTopoNetCoverage", 6, SQLITE_ANY,
52581 			     0, fnct_RegisterTopoNetCoverage, 0, 0);
52582     sqlite3_create_function (db, "SE_UnRegisterVectorCoverage", 1, SQLITE_ANY,
52583 			     0, fnct_UnregisterVectorCoverage, 0, 0);
52584     sqlite3_create_function (db, "SE_SetVectorCoverageInfos", 3, SQLITE_ANY,
52585 			     0, fnct_SetVectorCoverageInfos, 0, 0);
52586     sqlite3_create_function (db, "SE_SetVectorCoverageInfos", 5, SQLITE_ANY,
52587 			     0, fnct_SetVectorCoverageInfos, 0, 0);
52588     sqlite3_create_function (db, "SE_SetVectorCoverageCopyright", 2,
52589 			     SQLITE_ANY, 0, fnct_SetVectorCoverageCopyright,
52590 			     0, 0);
52591     sqlite3_create_function (db, "SE_SetVectorCoverageCopyright", 3,
52592 			     SQLITE_ANY, 0, fnct_SetVectorCoverageCopyright,
52593 			     0, 0);
52594     sqlite3_create_function (db, "SE_RegisterVectorCoverageSrid", 2,
52595 			     SQLITE_ANY, 0, fnct_RegisterVectorCoverageSrid,
52596 			     0, 0);
52597     sqlite3_create_function (db, "SE_UnRegisterVectorCoverageSrid", 2,
52598 			     SQLITE_ANY, 0, fnct_UnregisterVectorCoverageSrid,
52599 			     0, 0);
52600     sqlite3_create_function (db, "SE_RegisterVectorCoverageKeyword", 2,
52601 			     SQLITE_ANY, 0,
52602 			     fnct_RegisterVectorCoverageKeyword, 0, 0);
52603     sqlite3_create_function (db, "SE_UnRegisterVectorCoverageKeyword", 2,
52604 			     SQLITE_ANY, 0,
52605 			     fnct_UnregisterVectorCoverageKeyword, 0, 0);
52606     sqlite3_create_function (db, "SE_UpdateVectorCoverageExtent", 0,
52607 			     SQLITE_ANY, 0, fnct_UpdateVectorCoverageExtent,
52608 			     0, 0);
52609     sqlite3_create_function (db, "SE_UpdateVectorCoverageExtent", 1,
52610 			     SQLITE_ANY, 0, fnct_UpdateVectorCoverageExtent,
52611 			     0, 0);
52612     sqlite3_create_function (db, "SE_UpdateVectorCoverageExtent", 2,
52613 			     SQLITE_ANY, 0, fnct_UpdateVectorCoverageExtent,
52614 			     0, 0);
52615     sqlite3_create_function_v2 (db, "SE_AutoRegisterStandardBrushes", 0,
52616 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52617 				fnct_AutoRegisterStandardBrushes, 0, 0, 0);
52618     sqlite3_create_function_v2 (db, "SE_RegisterExternalGraphic", 2,
52619 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52620 				fnct_RegisterExternalGraphic, 0, 0, 0);
52621     sqlite3_create_function_v2 (db, "SE_RegisterExternalGraphic", 5,
52622 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52623 				fnct_RegisterExternalGraphic, 0, 0, 0);
52624     sqlite3_create_function_v2 (db, "SE_UnregisterExternalGraphic", 1,
52625 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52626 				fnct_UnregisterExternalGraphic, 0, 0, 0);
52627     sqlite3_create_function_v2 (db, "SE_RegisterVectorStyle", 1,
52628 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52629 				fnct_RegisterVectorStyle, 0, 0, 0);
52630     sqlite3_create_function_v2 (db, "SE_UnRegisterVectorStyle", 1,
52631 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52632 				fnct_UnRegisterVectorStyle, 0, 0, 0);
52633     sqlite3_create_function_v2 (db, "SE_UnRegisterVectorStyle", 2,
52634 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52635 				fnct_UnRegisterVectorStyle, 0, 0, 0);
52636     sqlite3_create_function_v2 (db, "SE_ReloadVectorStyle", 2,
52637 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52638 				fnct_ReloadVectorStyle, 0, 0, 0);
52639     sqlite3_create_function_v2 (db, "SE_RegisterVectorStyledLayer", 2,
52640 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52641 				fnct_RegisterVectorStyledLayer, 0, 0, 0);
52642     sqlite3_create_function_v2 (db, "SE_UnRegisterVectorStyledLayer", 2,
52643 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52644 				fnct_UnRegisterVectorStyledLayer, 0, 0, 0);
52645     sqlite3_create_function_v2 (db, "SE_RegisterRasterStyle", 1,
52646 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52647 				fnct_RegisterRasterStyle, 0, 0, 0);
52648     sqlite3_create_function_v2 (db, "SE_UnRegisterRasterStyle", 1,
52649 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52650 				fnct_UnRegisterRasterStyle, 0, 0, 0);
52651     sqlite3_create_function_v2 (db, "SE_UnRegisterRasterStyle", 2,
52652 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52653 				fnct_UnRegisterRasterStyle, 0, 0, 0);
52654     sqlite3_create_function_v2 (db, "SE_ReloadRasterStyle", 2,
52655 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52656 				fnct_ReloadRasterStyle, 0, 0, 0);
52657     sqlite3_create_function_v2 (db, "SE_RegisterRasterStyledLayer", 2,
52658 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52659 				fnct_RegisterRasterStyledLayer, 0, 0, 0);
52660     sqlite3_create_function_v2 (db, "SE_UnRegisterRasterStyledLayer", 2,
52661 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52662 				fnct_UnRegisterRasterStyledLayer, 0, 0, 0);
52663     sqlite3_create_function (db, "SE_RegisterRasterCoverageSrid", 2,
52664 			     SQLITE_ANY, 0, fnct_RegisterRasterCoverageSrid,
52665 			     0, 0);
52666     sqlite3_create_function (db, "SE_UnRegisterRasterCoverageSrid", 2,
52667 			     SQLITE_ANY, 0, fnct_UnregisterRasterCoverageSrid,
52668 			     0, 0);
52669     sqlite3_create_function (db, "SE_RegisterRasterCoverageKeyword", 2,
52670 			     SQLITE_ANY, 0,
52671 			     fnct_RegisterRasterCoverageKeyword, 0, 0);
52672     sqlite3_create_function (db, "SE_UnRegisterRasterCoverageKeyword", 2,
52673 			     SQLITE_ANY, 0,
52674 			     fnct_UnregisterRasterCoverageKeyword, 0, 0);
52675     sqlite3_create_function (db, "SE_UpdateRasterCoverageExtent", 0,
52676 			     SQLITE_ANY, 0, fnct_UpdateRasterCoverageExtent,
52677 			     0, 0);
52678     sqlite3_create_function (db, "SE_UpdateRasterCoverageExtent", 1,
52679 			     SQLITE_ANY, 0, fnct_UpdateRasterCoverageExtent,
52680 			     0, 0);
52681     sqlite3_create_function (db, "SE_UpdateRasterCoverageExtent", 2,
52682 			     SQLITE_ANY, 0, fnct_UpdateRasterCoverageExtent,
52683 			     0, 0);
52684 
52685     sqlite3_create_function_v2 (db, "RL2_RegisterMapConfiguration", 1,
52686 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52687 				fnct_RegisterMapConfiguration, 0, 0, 0);
52688     sqlite3_create_function_v2 (db, "RL2_UnRegisterMapConfiguration", 1,
52689 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52690 				fnct_UnRegisterMapConfiguration, 0, 0, 0);
52691     sqlite3_create_function_v2 (db, "RL2_ReloadMapConfiguration", 2,
52692 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52693 				fnct_ReloadMapConfiguration, 0, 0, 0);
52694     sqlite3_create_function_v2 (db, "RL2_NumMapConfigurations", 0,
52695 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52696 				fnct_NumMapConfigurations, 0, 0, 0);
52697     sqlite3_create_function_v2 (db, "RL2_MapConfigurationNameN", 1,
52698 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52699 				fnct_MapConfigurationNameN, 0, 0, 0);
52700     sqlite3_create_function_v2 (db, "RL2_MapConfigurationTitleN", 1,
52701 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52702 				fnct_MapConfigurationTitleN, 0, 0, 0);
52703     sqlite3_create_function_v2 (db, "RL2_MapConfigurationAbstractN", 1,
52704 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52705 				fnct_MapConfigurationAbstractN, 0, 0, 0);
52706 
52707     sqlite3_create_function_v2 (db, "CreateIsoMetadataTables", 0,
52708 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52709 				fnct_CreateIsoMetadataTables, 0, 0, 0);
52710     sqlite3_create_function_v2 (db, "CreateIsoMetadataTables", 1,
52711 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52712 				fnct_CreateIsoMetadataTables, 0, 0, 0);
52713     sqlite3_create_function_v2 (db, "GetIsoMetadataId", 1,
52714 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52715 				fnct_GetIsoMetadataId, 0, 0, 0);
52716     sqlite3_create_function_v2 (db, "RegisterIsoMetadata", 2,
52717 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52718 				fnct_RegisterIsoMetadata, 0, 0, 0);
52719     sqlite3_create_function_v2 (db, "RegisterIsoMetadata", 3,
52720 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52721 				fnct_RegisterIsoMetadata, 0, 0, 0);
52722     sqlite3_create_function_v2 (db, "XB_Create", 1,
52723 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52724 				fnct_XB_Create, 0, 0, 0);
52725     sqlite3_create_function_v2 (db, "XB_Create", 2,
52726 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52727 				fnct_XB_Create, 0, 0, 0);
52728     sqlite3_create_function_v2 (db, "XB_Create", 3,
52729 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52730 				fnct_XB_Create, 0, 0, 0);
52731     sqlite3_create_function_v2 (db, "XB_GetPayload", 1,
52732 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52733 				fnct_XB_GetPayload, 0, 0, 0);
52734     sqlite3_create_function_v2 (db, "XB_GetPayload", 2,
52735 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52736 				fnct_XB_GetPayload, 0, 0, 0);
52737     sqlite3_create_function_v2 (db, "XB_GetDocument", 1,
52738 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52739 				fnct_XB_GetDocument, 0, 0, 0);
52740     sqlite3_create_function_v2 (db, "XB_GetDocument", 2,
52741 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52742 				fnct_XB_GetDocument, 0, 0, 0);
52743     sqlite3_create_function_v2 (db, "XB_SchemaValidate", 2,
52744 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52745 				fnct_XB_SchemaValidate, 0, 0, 0);
52746     sqlite3_create_function_v2 (db, "XB_Compress", 1,
52747 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52748 				fnct_XB_Compress, 0, 0, 0);
52749     sqlite3_create_function_v2 (db, "XB_Uncompress", 1,
52750 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52751 				fnct_XB_Uncompress, 0, 0, 0);
52752     sqlite3_create_function_v2 (db, "XB_IsValid", 1,
52753 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52754 				fnct_XB_IsValid, 0, 0, 0);
52755     sqlite3_create_function_v2 (db, "XB_IsSchemaValidated", 1,
52756 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52757 				fnct_XB_IsSchemaValidated, 0, 0, 0);
52758     sqlite3_create_function_v2 (db, "XB_IsCompressed", 1,
52759 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52760 				fnct_XB_IsCompressed, 0, 0, 0);
52761     sqlite3_create_function_v2 (db, "XB_IsIsoMetadata", 1,
52762 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52763 				fnct_XB_IsIsoMetadata, 0, 0, 0);
52764     sqlite3_create_function_v2 (db, "XB_IsSldSeVectorStyle", 1,
52765 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52766 				fnct_XB_IsSldSeVectorStyle, 0, 0, 0);
52767     sqlite3_create_function_v2 (db, "XB_IsSldSeRasterStyle", 1,
52768 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52769 				fnct_XB_IsSldSeRasterStyle, 0, 0, 0);
52770     sqlite3_create_function_v2 (db, "XB_IsSldStyle", 1,
52771 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52772 				fnct_XB_IsSldStyle, 0, 0, 0);
52773     sqlite3_create_function_v2 (db, "XB_IsMapConfig", 1,
52774 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52775 				fnct_XB_IsMapConfig, 0, 0, 0);
52776     sqlite3_create_function_v2 (db, "XB_IsSvg", 1,
52777 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52778 				fnct_XB_IsSvg, 0, 0, 0);
52779     sqlite3_create_function_v2 (db, "XB_IsGpx", 1,
52780 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52781 				fnct_XB_IsGpx, 0, 0, 0);
52782     sqlite3_create_function_v2 (db, "XB_IsGpx", 1,
52783 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52784 				fnct_XB_IsGpx, 0, 0, 0);
52785     sqlite3_create_function_v2 (db, "XB_GetSchemaURI", 1,
52786 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52787 				fnct_XB_GetSchemaURI, 0, 0, 0);
52788     sqlite3_create_function_v2 (db, "XB_GetInternalSchemaURI", 1,
52789 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52790 				fnct_XB_GetInternalSchemaURI, 0, 0, 0);
52791     sqlite3_create_function_v2 (db, "XB_GetFileId", 1,
52792 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52793 				fnct_XB_GetFileId, 0, 0, 0);
52794     sqlite3_create_function_v2 (db, "XB_GetParentId", 1,
52795 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52796 				fnct_XB_GetParentId, 0, 0, 0);
52797     sqlite3_create_function_v2 (db, "XB_SetFileId", 2,
52798 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52799 				fnct_XB_SetFileId, 0, 0, 0);
52800     sqlite3_create_function_v2 (db, "XB_SetParentId", 2,
52801 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52802 				fnct_XB_SetParentId, 0, 0, 0);
52803     sqlite3_create_function_v2 (db, "XB_AddFileId", 6,
52804 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52805 				fnct_XB_AddFileId, 0, 0, 0);
52806     sqlite3_create_function_v2 (db, "XB_AddParentId", 6,
52807 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52808 				fnct_XB_AddParentId, 0, 0, 0);
52809     sqlite3_create_function_v2 (db, "XB_GetName", 1,
52810 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52811 				fnct_XB_GetName, 0, 0, 0);
52812     sqlite3_create_function_v2 (db, "XB_GetTitle", 1,
52813 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52814 				fnct_XB_GetTitle, 0, 0, 0);
52815     sqlite3_create_function_v2 (db, "XB_GetAbstract", 1,
52816 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52817 				fnct_XB_GetAbstract, 0, 0, 0);
52818     sqlite3_create_function_v2 (db, "XB_GetGeometry", 1,
52819 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52820 				fnct_XB_GetGeometry, 0, 0, 0);
52821     sqlite3_create_function_v2 (db, "XB_MLineFromGPX", 1,
52822 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52823 				fnct_XB_MLineFromGPX, 0, 0, 0);
52824     sqlite3_create_function_v2 (db, "XB_GetDocumentSize", 1,
52825 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52826 				fnct_XB_GetDocumentSize, 0, 0, 0);
52827     sqlite3_create_function_v2 (db, "XB_GetEncoding", 1,
52828 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52829 				fnct_XB_GetEncoding, 0, 0, 0);
52830     sqlite3_create_function_v2 (db, "XB_GetLastParseError", 0, SQLITE_UTF8,
52831 				cache, fnct_XB_GetLastParseError, 0, 0, 0);
52832     sqlite3_create_function_v2 (db, "XB_GetLastValidateError", 0, SQLITE_UTF8,
52833 				cache, fnct_XB_GetLastValidateError, 0, 0, 0);
52834     sqlite3_create_function_v2 (db, "XB_IsValidXPathExpression", 1,
52835 				SQLITE_UTF8, cache,
52836 				fnct_XB_IsValidXPathExpression, 0, 0, 0);
52837     sqlite3_create_function_v2 (db, "XB_GetLastXPathError", 0, SQLITE_UTF8,
52838 				cache, fnct_XB_GetLastXPathError, 0, 0, 0);
52839     sqlite3_create_function_v2 (db, "XB_CacheFlush", 0,
52840 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52841 				fnct_XB_CacheFlush, 0, 0, 0);
52842 
52843 #endif /* end including LIBXML2 */
52844 
52845 #ifdef ENABLE_GEOPACKAGE	/* enabling GeoPackage extensions */
52846 
52847     sqlite3_create_function_v2 (db, "AutoGPKGStart", 0,
52848 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52849 				fnct_AutoGPKGStart, 0, 0, 0);
52850     sqlite3_create_function_v2 (db, "AutoGPKGStart", 1,
52851 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52852 				fnct_AutoGPKGStart, 0, 0, 0);
52853     sqlite3_create_function_v2 (db, "AutoGPKGStop", 0,
52854 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52855 				fnct_AutoGPKGStop, 0, 0, 0);
52856     sqlite3_create_function_v2 (db, "AutoGPKGStop", 1,
52857 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52858 				fnct_AutoGPKGStop, 0, 0, 0);
52859 
52860     /* not yet finalised geopackage raster functions, plus some convenience API */
52861     sqlite3_create_function_v2 (db, "gpkgCreateBaseTables", 0,
52862 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52863 				fnct_gpkgCreateBaseTables, 0, 0, 0);
52864     sqlite3_create_function_v2 (db, "gpkgInsertEpsgSRID", 1,
52865 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52866 				fnct_gpkgInsertEpsgSRID, 0, 0, 0);
52867     sqlite3_create_function_v2 (db, "gpkgCreateTilesTable", 6,
52868 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52869 				fnct_gpkgCreateTilesTable, 0, 0, 0);
52870     sqlite3_create_function_v2 (db, "gpkgCreateTilesZoomLevel", 4,
52871 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52872 				fnct_gpkgCreateTilesZoomLevel, 0, 0, 0);
52873     sqlite3_create_function_v2 (db, "gpkgAddTileTriggers", 1,
52874 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52875 				fnct_gpkgAddTileTriggers, 0, 0, 0);
52876     sqlite3_create_function_v2 (db, "gpkgGetNormalZoom", 2,
52877 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52878 				fnct_gpkgGetNormalZoom, 0, 0, 0);
52879     sqlite3_create_function_v2 (db, "gpkgGetNormalRow", 3,
52880 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52881 				fnct_gpkgGetNormalRow, 0, 0, 0);
52882     sqlite3_create_function_v2 (db, "gpkgGetImageType", 1,
52883 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52884 				fnct_gpkgGetImageType, 0, 0, 0);
52885     sqlite3_create_function_v2 (db, "gpkgAddGeometryColumn", 6,
52886 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52887 				fnct_gpkgAddGeometryColumn, 0, 0, 0);
52888     sqlite3_create_function_v2 (db, "gpkgAddGeometryTriggers", 2,
52889 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52890 				fnct_gpkgAddGeometryTriggers, 0, 0, 0);
52891     sqlite3_create_function_v2 (db, "gpkgAddSpatialIndex", 2,
52892 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52893 				fnct_gpkgAddSpatialIndex, 0, 0, 0);
52894     sqlite3_create_function_v2 (db, "gpkgMakePoint", 2,
52895 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52896 				fnct_gpkgMakePoint, 0, 0, 0);
52897     sqlite3_create_function_v2 (db, "gpkgMakePoint", 3,
52898 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52899 				fnct_gpkgMakePointWithSRID, 0, 0, 0);
52900     sqlite3_create_function_v2 (db, "gpkgMakePointZ", 3,
52901 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52902 				fnct_gpkgMakePointZ, 0, 0, 0);
52903     sqlite3_create_function_v2 (db, "gpkgMakePointZ", 4,
52904 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52905 				fnct_gpkgMakePointZWithSRID, 0, 0, 0);
52906     sqlite3_create_function_v2 (db, "gpkgMakePointM", 3,
52907 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52908 				fnct_gpkgMakePointM, 0, 0, 0);
52909     sqlite3_create_function_v2 (db, "gpkgMakePointM", 4,
52910 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52911 				fnct_gpkgMakePointMWithSRID, 0, 0, 0);
52912     sqlite3_create_function_v2 (db, "gpkgMakePointZM", 4,
52913 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52914 				fnct_gpkgMakePointZM, 0, 0, 0);
52915     sqlite3_create_function_v2 (db, "gpkgMakePointZM", 5,
52916 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52917 				fnct_gpkgMakePointZMWithSRID, 0, 0, 0);
52918     sqlite3_create_function_v2 (db, "AsGPB", 1,
52919 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52920 				fnct_ToGPB, 0, 0, 0);
52921     sqlite3_create_function_v2 (db, "GeomFromGPB", 1,
52922 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52923 				fnct_GeomFromGPB, 0, 0, 0);
52924     sqlite3_create_function_v2 (db, "IsValidGPB", 1,
52925 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52926 				fnct_IsValidGPB, 0, 0, 0);
52927     sqlite3_create_function_v2 (db, "GPKG_IsAssignable", 2,
52928 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
52929 				fnct_GPKG_IsAssignable, 0, 0, 0);
52930     sqlite3_create_function_v2 (db, "CastAutomagic", 1,
52931 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52932 				fnct_CastAutomagic, 0, 0, 0);
52933 
52934 #endif /* end enabling GeoPackage extensions */
52935 
52936 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
52937     if (sqlite3_libversion_number () >= 3008003)
52938       {
52939 	  /* only SQLite >= 3.8.3 can suppoty WITH RECURSIVE */
52940 	  sqlite3_create_function_v2 (db, "CreateTopoTables", 0,
52941 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
52942 				      cache, fnct_CreateTopoTables, 0, 0, 0);
52943 	  sqlite3_create_function_v2 (db, "ReCreateTopoTriggers", 0,
52944 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC,
52945 				      cache, fnct_ReCreateTopoTriggers, 0, 0,
52946 				      0);
52947 	  sqlite3_create_function_v2 (db, "CreateTopology", 1,
52948 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52949 				      fnct_CreateTopology, 0, 0, 0);
52950 	  sqlite3_create_function_v2 (db, "CreateTopology", 2,
52951 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52952 				      fnct_CreateTopology, 0, 0, 0);
52953 	  sqlite3_create_function_v2 (db, "CreateTopology", 3,
52954 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52955 				      fnct_CreateTopology, 0, 0, 0);
52956 	  sqlite3_create_function_v2 (db, "CreateTopology", 4,
52957 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52958 				      fnct_CreateTopology, 0, 0, 0);
52959 	  sqlite3_create_function_v2 (db, "ST_InitTopoGeo", 1,
52960 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52961 				      fnct_CreateTopology, 0, 0, 0);
52962 	  sqlite3_create_function_v2 (db, "DropTopology", 1,
52963 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52964 				      fnct_DropTopology, 0, 0, 0);
52965 	  sqlite3_create_function_v2 (db, "GetLastTopologyException", 1,
52966 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52967 				      fnct_GetLastTopologyException, 0, 0, 0);
52968 	  sqlite3_create_function_v2 (db, "ST_AddIsoNode", 3,
52969 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52970 				      fnct_AddIsoNode, 0, 0, 0);
52971 	  sqlite3_create_function_v2 (db, "ST_MoveIsoNode", 3,
52972 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52973 				      fnct_MoveIsoNode, 0, 0, 0);
52974 	  sqlite3_create_function_v2 (db, "ST_RemIsoNode", 2,
52975 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52976 				      fnct_RemIsoNode, 0, 0, 0);
52977 	  sqlite3_create_function_v2 (db, "ST_AddIsoEdge", 4,
52978 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52979 				      fnct_AddIsoEdge, 0, 0, 0);
52980 	  sqlite3_create_function_v2 (db, "ST_RemIsoEdge", 2,
52981 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52982 				      fnct_RemIsoEdge, 0, 0, 0);
52983 	  sqlite3_create_function_v2 (db, "ST_ModEdgeSplit", 3,
52984 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52985 				      fnct_ModEdgeSplit, 0, 0, 0);
52986 	  sqlite3_create_function_v2 (db, "ST_NewEdgesSplit", 3,
52987 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52988 				      fnct_NewEdgesSplit, 0, 0, 0);
52989 	  sqlite3_create_function_v2 (db, "ST_AddEdgeModFace", 4,
52990 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52991 				      fnct_AddEdgeModFace, 0, 0, 0);
52992 	  sqlite3_create_function_v2 (db, "ST_AddEdgeNewFaces", 4,
52993 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52994 				      fnct_AddEdgeNewFaces, 0, 0, 0);
52995 	  sqlite3_create_function_v2 (db, "ST_ChangeEdgeGeom", 3,
52996 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
52997 				      fnct_ChangeEdgeGeom, 0, 0, 0);
52998 	  sqlite3_create_function_v2 (db, "ST_RemEdgeNewFace", 2,
52999 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53000 				      fnct_RemEdgeNewFace, 0, 0, 0);
53001 	  sqlite3_create_function_v2 (db, "ST_RemEdgeModFace", 2,
53002 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53003 				      fnct_RemEdgeModFace, 0, 0, 0);
53004 	  sqlite3_create_function_v2 (db, "ST_ModEdgeHeal", 3,
53005 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53006 				      fnct_ModEdgeHeal, 0, 0, 0);
53007 	  sqlite3_create_function_v2 (db, "ST_NewEdgeHeal", 3,
53008 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53009 				      fnct_NewEdgeHeal, 0, 0, 0);
53010 	  sqlite3_create_function_v2 (db, "ST_GetFaceGeometry", 2,
53011 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53012 				      fnct_GetFaceGeometry, 0, 0, 0);
53013 	  sqlite3_create_function_v2 (db, "ST_GetFaceEdges", 2,
53014 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53015 				      fnct_GetFaceEdges, 0, 0, 0);
53016 	  sqlite3_create_function_v2 (db, "ST_ValidateTopoGeo", 1,
53017 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53018 				      fnct_ValidateTopoGeo, 0, 0, 0);
53019 	  sqlite3_create_function_v2 (db, "ST_CreateTopoGeo", 2,
53020 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53021 				      fnct_CreateTopoGeo, 0, 0, 0);
53022 	  sqlite3_create_function_v2 (db, "GetNodeByPoint", 2,
53023 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53024 				      fnct_GetNodeByPoint, 0, 0, 0);
53025 	  sqlite3_create_function_v2 (db, "GetNodeByPoint", 3,
53026 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53027 				      fnct_GetNodeByPoint, 0, 0, 0);
53028 	  sqlite3_create_function_v2 (db, "GetEdgeByPoint", 2,
53029 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53030 				      fnct_GetEdgeByPoint, 0, 0, 0);
53031 	  sqlite3_create_function_v2 (db, "GetEdgeByPoint", 3,
53032 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53033 				      fnct_GetEdgeByPoint, 0, 0, 0);
53034 	  sqlite3_create_function_v2 (db, "GetFaceByPoint", 2,
53035 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53036 				      fnct_GetFaceByPoint, 0, 0, 0);
53037 	  sqlite3_create_function_v2 (db, "GetFaceByPoint", 3,
53038 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53039 				      fnct_GetFaceByPoint, 0, 0, 0);
53040 	  sqlite3_create_function_v2 (db, "TopoGeo_AddPoint", 2,
53041 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53042 				      fnct_TopoGeo_AddPoint, 0, 0, 0);
53043 	  sqlite3_create_function_v2 (db, "TopoGeo_AddPoint", 3,
53044 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53045 				      fnct_TopoGeo_AddPoint, 0, 0, 0);
53046 	  sqlite3_create_function_v2 (db, "TopoGeo_AddLineString", 2,
53047 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53048 				      fnct_TopoGeo_AddLineString, 0, 0, 0);
53049 	  sqlite3_create_function_v2 (db, "TopoGeo_AddLineString", 3,
53050 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53051 				      fnct_TopoGeo_AddLineString, 0, 0, 0);
53052 	  sqlite3_create_function_v2 (db, "TopoGeo_AddLineStringNoFace", 2,
53053 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53054 				      fnct_TopoGeo_AddLineStringNoFace, 0, 0,
53055 				      0);
53056 	  sqlite3_create_function_v2 (db, "TopoGeo_AddLineStringNoFace", 3,
53057 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53058 				      fnct_TopoGeo_AddLineStringNoFace, 0, 0,
53059 				      0);
53060 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTable", 4,
53061 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53062 				      fnct_TopoGeo_FromGeoTable, 0, 0, 0);
53063 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTable", 5,
53064 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53065 				      fnct_TopoGeo_FromGeoTable, 0, 0, 0);
53066 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTable", 6,
53067 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53068 				      fnct_TopoGeo_FromGeoTable, 0, 0, 0);
53069 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTable", 7,
53070 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53071 				      fnct_TopoGeo_FromGeoTable, 0, 0, 0);
53072 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFace", 4,
53073 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53074 				      fnct_TopoGeo_FromGeoTableNoFace, 0, 0, 0);
53075 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFace", 5,
53076 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53077 				      fnct_TopoGeo_FromGeoTableNoFace, 0, 0, 0);
53078 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFace", 6,
53079 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53080 				      fnct_TopoGeo_FromGeoTableNoFace, 0, 0, 0);
53081 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFace", 7,
53082 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53083 				      fnct_TopoGeo_FromGeoTableNoFace, 0, 0, 0);
53084 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableExt", 6,
53085 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53086 				      fnct_TopoGeo_FromGeoTableExt, 0, 0, 0);
53087 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableExt", 7,
53088 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53089 				      fnct_TopoGeo_FromGeoTableExt, 0, 0, 0);
53090 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableExt", 8,
53091 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53092 				      fnct_TopoGeo_FromGeoTableExt, 0, 0, 0);
53093 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableExt", 9,
53094 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53095 				      fnct_TopoGeo_FromGeoTableExt, 0, 0, 0);
53096 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFaceExt", 6,
53097 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53098 				      fnct_TopoGeo_FromGeoTableNoFaceExt, 0, 0,
53099 				      0);
53100 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFaceExt", 7,
53101 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53102 				      fnct_TopoGeo_FromGeoTableNoFaceExt, 0, 0,
53103 				      0);
53104 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFaceExt", 8,
53105 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53106 				      fnct_TopoGeo_FromGeoTableNoFaceExt, 0, 0,
53107 				      0);
53108 	  sqlite3_create_function_v2 (db, "TopoGeo_FromGeoTableNoFaceExt", 9,
53109 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53110 				      fnct_TopoGeo_FromGeoTableNoFaceExt, 0, 0,
53111 				      0);
53112 	  sqlite3_create_function_v2 (db, "TopoGeo_Polygonize", 1,
53113 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53114 				      fnct_TopoGeo_Polygonize, 0, 0, 0);
53115 	  sqlite3_create_function_v2 (db, "TopoGeo_Polygonize", 2,
53116 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53117 				      fnct_TopoGeo_Polygonize, 0, 0, 0);
53118 	  sqlite3_create_function_v2 (db, "TopoGeo_TopoSnap", 3,
53119 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53120 				      fnct_TopoGeo_TopoSnap, 0, 0, 0);
53121 	  sqlite3_create_function_v2 (db, "TopoGeo_TopoSnap", 5,
53122 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53123 				      fnct_TopoGeo_TopoSnap, 0, 0, 0);
53124 	  sqlite3_create_function_v2 (db, "TopoGeo_SnappedGeoTable", 6,
53125 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53126 				      fnct_TopoGeo_SnappedGeoTable, 0, 0, 0);
53127 	  sqlite3_create_function_v2 (db, "TopoGeo_SnappedGeoTable", 8,
53128 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53129 				      fnct_TopoGeo_SnappedGeoTable, 0, 0, 0);
53130 	  sqlite3_create_function_v2 (db, "TopoGeo_ToGeoTable", 5,
53131 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53132 				      fnct_TopoGeo_ToGeoTable, 0, 0, 0);
53133 	  sqlite3_create_function_v2 (db, "TopoGeo_ToGeoTable", 6,
53134 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53135 				      fnct_TopoGeo_ToGeoTable, 0, 0, 0);
53136 	  sqlite3_create_function_v2 (db, "TopoGeo_PolyFacesList", 5,
53137 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53138 				      fnct_TopoGeo_PolyFacesList, 0, 0, 0);
53139 	  sqlite3_create_function_v2 (db, "TopoGeo_LineEdgesList", 5,
53140 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53141 				      fnct_TopoGeo_LineEdgesList, 0, 0, 0);
53142 	  sqlite3_create_function_v2 (db, "TopoGeo_ToGeoTableGeneralize", 6,
53143 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53144 				      fnct_TopoGeo_ToGeoTableGeneralize, 0, 0,
53145 				      0);
53146 	  sqlite3_create_function_v2 (db, "TopoGeo_ToGeoTableGeneralize", 7,
53147 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53148 				      fnct_TopoGeo_ToGeoTableGeneralize, 0, 0,
53149 				      0);
53150 	  sqlite3_create_function_v2 (db, "TopoGeo_RemoveSmallFaces", 2,
53151 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53152 				      fnct_TopoGeo_RemoveSmallFaces, 0, 0, 0);
53153 	  sqlite3_create_function_v2 (db, "TopoGeo_RemoveSmallFaces", 3,
53154 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53155 				      fnct_TopoGeo_RemoveSmallFaces, 0, 0, 0);
53156 	  sqlite3_create_function_v2 (db, "TopoGeo_RemoveDanglingEdges", 1,
53157 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53158 				      fnct_TopoGeo_RemoveDanglingEdges, 0, 0,
53159 				      0);
53160 	  sqlite3_create_function_v2 (db, "TopoGeo_RemoveDanglingNodes", 1,
53161 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53162 				      fnct_TopoGeo_RemoveDanglingNodes, 0, 0,
53163 				      0);
53164 	  sqlite3_create_function_v2 (db, "TopoGeo_NewEdgeHeal", 1,
53165 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53166 				      fnct_TopoGeo_NewEdgeHeal, 0, 0, 0);
53167 	  sqlite3_create_function_v2 (db, "TopoGeo_ModEdgeHeal", 1,
53168 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53169 				      fnct_TopoGeo_ModEdgeHeal, 0, 0, 0);
53170 	  sqlite3_create_function_v2 (db, "TopoGeo_NewEdgesSplit", 2,
53171 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53172 				      fnct_TopoGeo_NewEdgesSplit, 0, 0, 0);
53173 	  sqlite3_create_function_v2 (db, "TopoGeo_NewEdgesSplit", 3,
53174 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53175 				      fnct_TopoGeo_NewEdgesSplit, 0, 0, 0);
53176 	  sqlite3_create_function_v2 (db, "TopoGeo_ModEdgeSplit", 2,
53177 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53178 				      fnct_TopoGeo_ModEdgeSplit, 0, 0, 0);
53179 	  sqlite3_create_function_v2 (db, "TopoGeo_ModEdgeSplit", 3,
53180 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53181 				      fnct_TopoGeo_ModEdgeSplit, 0, 0, 0);
53182 	  sqlite3_create_function_v2 (db, "TopoGeo_Clone", 3,
53183 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53184 				      fnct_TopoGeo_Clone, 0, 0, 0);
53185 	  sqlite3_create_function_v2 (db, "TopoGeo_SubdivideLines", 2,
53186 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53187 				      fnct_TopoGeo_SubdivideLines, 0, 0, 0);
53188 	  sqlite3_create_function_v2 (db, "TopoGeo_SubdivideLines", 3,
53189 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53190 				      fnct_TopoGeo_SubdivideLines, 0, 0, 0);
53191 	  sqlite3_create_function_v2 (db, "TopoGeo_DisambiguateSegmentEdges", 1,
53192 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53193 				      fnct_TopoGeo_DisambiguateSegmentEdges, 0,
53194 				      0, 0);
53195 	  sqlite3_create_function_v2 (db, "TopoGeo_GetEdgeSeed", 2,
53196 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53197 				      fnct_TopoGeo_GetEdgeSeed, 0, 0, 0);
53198 	  sqlite3_create_function_v2 (db, "TopoGeo_GetFaceSeed", 2,
53199 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53200 				      fnct_TopoGeo_GetFaceSeed, 0, 0, 0);
53201 	  sqlite3_create_function_v2 (db, "TopoGeo_UpdateSeeds", 1,
53202 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53203 				      fnct_TopoGeo_UpdateSeeds, 0, 0, 0);
53204 	  sqlite3_create_function_v2 (db, "TopoGeo_UpdateSeeds", 2,
53205 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53206 				      fnct_TopoGeo_UpdateSeeds, 0, 0, 0);
53207 	  sqlite3_create_function_v2 (db, "TopoGeo_SnapPointToSeed", 3,
53208 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53209 				      fnct_TopoGeo_SnapPointToSeed, 0, 0, 0);
53210 	  sqlite3_create_function_v2 (db, "TopoGeo_SnapLineToSeed", 3,
53211 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53212 				      fnct_TopoGeo_SnapLineToSeed, 0, 0, 0);
53213 	  sqlite3_create_function_v2 (db, "TopoGeo_CreateTopoLayer", 5,
53214 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53215 				      fnct_TopoGeo_CreateTopoLayer, 0, 0, 0);
53216 	  sqlite3_create_function_v2 (db, "TopoGeo_CreateTopoLayer", 6,
53217 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53218 				      fnct_TopoGeo_CreateTopoLayer, 0, 0, 0);
53219 	  sqlite3_create_function_v2 (db, "TopoGeo_InitTopoLayer", 4,
53220 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53221 				      fnct_TopoGeo_InitTopoLayer, 0, 0, 0);
53222 	  sqlite3_create_function_v2 (db, "TopoGeo_RemoveTopoLayer", 2,
53223 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53224 				      fnct_TopoGeo_RemoveTopoLayer, 0, 0, 0);
53225 	  sqlite3_create_function_v2 (db, "TopoGeo_ExportTopoLayer", 3,
53226 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53227 				      fnct_TopoGeo_ExportTopoLayer, 0, 0, 0);
53228 	  sqlite3_create_function_v2 (db, "TopoGeo_ExportTopoLayer", 4,
53229 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53230 				      fnct_TopoGeo_ExportTopoLayer, 0, 0, 0);
53231 	  sqlite3_create_function_v2 (db, "TopoGeo_ExportTopoLayer", 5,
53232 				      SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53233 				      fnct_TopoGeo_ExportTopoLayer, 0, 0, 0);
53234 	  sqlite3_create_function_v2 (db, "TopoGeo_InsertFeatureFromTopoLayer",
53235 				      4, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
53236 				      cache,
53237 				      fnct_TopoGeo_InsertFeatureFromTopoLayer,
53238 				      0, 0, 0);
53239       }
53240 
53241     sqlite3_create_function_v2 (db, "CreateNetwork", 1,
53242 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53243 				fnct_CreateNetwork, 0, 0, 0);
53244     sqlite3_create_function_v2 (db, "CreateNetwork", 2,
53245 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53246 				fnct_CreateNetwork, 0, 0, 0);
53247     sqlite3_create_function_v2 (db, "CreateNetwork", 3,
53248 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53249 				fnct_CreateNetwork, 0, 0, 0);
53250     sqlite3_create_function_v2 (db, "CreateNetwork", 4,
53251 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53252 				fnct_CreateNetwork, 0, 0, 0);
53253     sqlite3_create_function_v2 (db, "CreateNetwork", 5,
53254 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53255 				fnct_CreateNetwork, 0, 0, 0);
53256     sqlite3_create_function_v2 (db, "ST_InitTopoNet", 1,
53257 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53258 				fnct_CreateNetwork, 0, 0, 0);
53259     sqlite3_create_function_v2 (db, "DropNetwork", 1,
53260 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53261 				fnct_DropNetwork, 0, 0, 0);
53262     sqlite3_create_function_v2 (db, "GetLastNetworkException", 1,
53263 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53264 				fnct_GetLastNetworkException, 0, 0, 0);
53265     sqlite3_create_function_v2 (db, "ST_AddIsoNetNode", 2,
53266 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53267 				fnct_AddIsoNetNode, 0, 0, 0);
53268     sqlite3_create_function_v2 (db, "ST_MoveIsoNetNode", 3,
53269 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53270 				fnct_MoveIsoNetNode, 0, 0, 0);
53271     sqlite3_create_function_v2 (db, "ST_RemIsoNetNode", 2,
53272 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53273 				fnct_RemIsoNetNode, 0, 0, 0);
53274     sqlite3_create_function_v2 (db, "ST_AddLink", 4,
53275 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53276 				fnct_AddLink, 0, 0, 0);
53277     sqlite3_create_function_v2 (db, "ST_ChangeLinkGeom", 3,
53278 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53279 				fnct_ChangeLinkGeom, 0, 0, 0);
53280     sqlite3_create_function_v2 (db, "ST_RemoveLink", 2,
53281 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53282 				fnct_RemoveLink, 0, 0, 0);
53283     sqlite3_create_function_v2 (db, "ST_NewLogLinkSplit", 2,
53284 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53285 				fnct_NewLogLinkSplit, 0, 0, 0);
53286     sqlite3_create_function_v2 (db, "ST_ModLogLinkSplit", 2,
53287 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53288 				fnct_ModLogLinkSplit, 0, 0, 0);
53289     sqlite3_create_function_v2 (db, "ST_NewGeoLinkSplit", 3,
53290 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53291 				fnct_NewGeoLinkSplit, 0, 0, 0);
53292     sqlite3_create_function_v2 (db, "ST_ModGeoLinkSplit", 3,
53293 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53294 				fnct_ModGeoLinkSplit, 0, 0, 0);
53295     sqlite3_create_function_v2 (db, "ST_NewLinkHeal", 3,
53296 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53297 				fnct_NewLinkHeal, 0, 0, 0);
53298     sqlite3_create_function_v2 (db, "ST_ModLinkHeal", 3,
53299 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53300 				fnct_ModLinkHeal, 0, 0, 0);
53301     sqlite3_create_function_v2 (db, "ST_LogiNetFromTGeo", 2,
53302 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53303 				fnct_LogiNetFromTGeo, 0, 0, 0);
53304     sqlite3_create_function_v2 (db, "ST_SpatNetFromTGeo", 2,
53305 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53306 				fnct_SpatNetFromTGeo, 0, 0, 0);
53307     sqlite3_create_function_v2 (db, "ST_SpatNetFromGeom", 2,
53308 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53309 				fnct_SpatNetFromGeom, 0, 0, 0);
53310     sqlite3_create_function_v2 (db, "ST_ValidLogicalNet", 1,
53311 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53312 				fnct_ValidLogicalNet, 0, 0, 0);
53313     sqlite3_create_function_v2 (db, "ST_ValidSpatialNet", 1,
53314 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53315 				fnct_ValidSpatialNet, 0, 0, 0);
53316     sqlite3_create_function_v2 (db, "GetNetNodeByPoint", 2,
53317 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53318 				fnct_GetNetNodeByPoint, 0, 0, 0);
53319     sqlite3_create_function_v2 (db, "GetNetNodeByPoint", 3,
53320 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53321 				fnct_GetNetNodeByPoint, 0, 0, 0);
53322     sqlite3_create_function_v2 (db, "GetLinkByPoint", 2,
53323 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53324 				fnct_GetLinkByPoint, 0, 0, 0);
53325     sqlite3_create_function_v2 (db, "GetLinkByPoint", 3,
53326 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53327 				fnct_GetLinkByPoint, 0, 0, 0);
53328     sqlite3_create_function_v2 (db, "TopoNet_FromGeoTable", 4,
53329 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53330 				fnct_TopoNet_FromGeoTable, 0, 0, 0);
53331     sqlite3_create_function_v2 (db, "TopoNet_ToGeoTable", 5,
53332 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53333 				fnct_TopoNet_ToGeoTable, 0, 0, 0);
53334     sqlite3_create_function_v2 (db, "TopoNet_ToGeoTable", 6,
53335 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53336 				fnct_TopoNet_ToGeoTable, 0, 0, 0);
53337     sqlite3_create_function_v2 (db, "TopoNet_ToGeoTableGeneralize", 6,
53338 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53339 				fnct_TopoNet_ToGeoTableGeneralize, 0, 0, 0);
53340     sqlite3_create_function_v2 (db, "TopoNet_ToGeoTableGeneralize", 7,
53341 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53342 				fnct_TopoNet_ToGeoTableGeneralize, 0, 0, 0);
53343     sqlite3_create_function_v2 (db, "TopoNet_Clone", 3,
53344 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53345 				fnct_TopoNet_Clone, 0, 0, 0);
53346     sqlite3_create_function_v2 (db, "TopoNet_DisambiguateSegmentLinks", 1,
53347 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53348 				fnct_TopoNet_DisambiguateSegmentLinks, 0, 0, 0);
53349     sqlite3_create_function_v2 (db, "TopoNet_GetLinkSeed", 2,
53350 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53351 				fnct_TopoNet_GetLinkSeed, 0, 0, 0);
53352     sqlite3_create_function_v2 (db, "TopoNet_UpdateSeeds", 1,
53353 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53354 				fnct_TopoNet_UpdateSeeds, 0, 0, 0);
53355     sqlite3_create_function_v2 (db, "TopoNet_UpdateSeeds", 2,
53356 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53357 				fnct_TopoNet_UpdateSeeds, 0, 0, 0);
53358     sqlite3_create_function_v2 (db, "TopoNet_LineLinksList", 5,
53359 				SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
53360 				fnct_TopoNet_LineLinksList, 0, 0, 0);
53361 #endif /* end TOPOLOGY conditionals */
53362 
53363     return cache;
53364 }
53365 
53366 SPATIALITE_PRIVATE void
init_spatialite_virtualtables(void * p_db,const void * p_cache)53367 init_spatialite_virtualtables (void *p_db, const void *p_cache)
53368 {
53369     sqlite3 *db = (sqlite3 *) p_db;
53370 
53371 #ifndef OMIT_ICONV		/* when ICONV is disabled SHP/DBF/TXT cannot be supported */
53372 /* initializing the VirtualShape  extension */
53373     virtualshape_extension_init (db);
53374 /* initializing the VirtualDbf  extension */
53375     virtualdbf_extension_init (db);
53376 /* initializing the VirtualText extension */
53377     virtualtext_extension_init (db);
53378 /* initializing the VirtualGeoJson  extension */
53379     virtualgeojson_extension_init (db);
53380 
53381 #ifndef OMIT_FREEXL
53382 /* initializing the VirtualXL  extension */
53383     virtualXL_extension_init (db);
53384 #endif /* FreeXL enabled/disable */
53385 #endif /* ICONV enabled/disabled */
53386 
53387 /* initializing the VirtualNetwork  extension */
53388     virtualnetwork_extension_init (db);
53389 /* initializing the MbrCache  extension */
53390     mbrcache_extension_init (db);
53391 /* initializing the VirtualFDO  extension */
53392     virtualfdo_extension_init (db);
53393 /* initializing the VirtualBBox  extension */
53394     virtualbbox_extension_init (db, p_cache);
53395 /* initializing the VirtualSpatialIndex  extension */
53396     virtual_spatialindex_extension_init (db);
53397 /* initializing the VirtualElementary  extension */
53398     virtual_elementary_extension_init (db);
53399 
53400 #ifndef OMIT_GEOS		/* only if GEOS is supported */
53401 /* initializing the VirtualRouting  extension */
53402     virtualrouting_extension_init (db);
53403 #ifndef OMIT_KNN		/* only if KNN is enabled */
53404 /* initializing the VirtualKNN  extension */
53405     virtual_knn_extension_init (db);
53406 #endif /* end KNN conditional */
53407 #endif /* end GEOS conditional */
53408 
53409 #ifdef ENABLE_GEOPACKAGE	/* only if GeoPackage support is enabled */
53410 /* initializing the VirtualGPKG  extension */
53411     virtualgpkg_extension_init (db);
53412 #endif /* end GEOPACKAGE conditional */
53413 
53414 #ifdef ENABLE_LIBXML2		/* including LIBXML2 */
53415 /* initializing the VirtualXPath extension */
53416     virtual_xpath_extension_init (db, p_cache);
53417 #endif /* LIBXML2 enabled/disable */
53418 }
53419 
53420 #ifdef LOADABLE_EXTENSION	/* loadable-extension only */
53421 SQLITE_EXTENSION_INIT1 static int
init_spatialite_extension(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)53422 init_spatialite_extension (sqlite3 * db, char **pzErrMsg,
53423 			   const sqlite3_api_routines * pApi)
53424 {
53425     void *p_cache;
53426     struct splite_internal_cache *cache;
53427     SQLITE_EXTENSION_INIT2 (pApi);
53428     p_cache = spatialite_alloc_connection ();
53429     cache = (struct splite_internal_cache *) p_cache;
53430 
53431 /* setting the POSIX locale for numeric */
53432     setlocale (LC_NUMERIC, "POSIX");
53433     *pzErrMsg = NULL;
53434 
53435     register_spatialite_sql_functions (db, cache);
53436 
53437     init_spatialite_virtualtables (db, p_cache);
53438 
53439 /* setting a timeout handler */
53440     sqlite3_busy_timeout (db, 5000);
53441 
53442     return 0;
53443 }
53444 #endif
53445 
53446 SPATIALITE_DECLARE void
spatialite_init_geos(void)53447 spatialite_init_geos (void)
53448 {
53449 /* initializes GEOS (or resets to initial state - as required by RTTOPO) */
53450 #ifndef OMIT_GEOS		/* initializing GEOS */
53451 #ifndef GEOS_USE_ONLY_R_API	/* obsolete versions non fully thread-safe */
53452     initGEOS (geos_warning, geos_error);
53453 #endif
53454 #endif /* end GEOS  */
53455 }
53456 
53457 SPATIALITE_PRIVATE void
spatialite_splash_screen(int verbose)53458 spatialite_splash_screen (int verbose)
53459 {
53460     if (isatty (1))
53461       {
53462 	  /* printing "hello" message only when stdout is on console */
53463 	  if (verbose)
53464 	    {
53465 		spatialite_i ("SpatiaLite version ..: %s",
53466 			      spatialite_version ());
53467 		spatialite_i ("\tSupported Extensions:\n");
53468 #ifndef OMIT_ICONV		/* ICONV is required by SHP/DBF/TXT */
53469 		spatialite_i
53470 		    ("\t- 'VirtualShape'\t[direct Shapefile access]\n");
53471 		spatialite_i ("\t- 'VirtualDbf'\t\t[direct DBF access]\n");
53472 		spatialite_i ("\t- 'VirtualText'\t\t[direct CSV/TXT access]\n");
53473 		spatialite_i
53474 		    ("\t- 'VirtualGeoJSON'\t\t[direct GeoJSON access]\n");
53475 #ifndef OMIT_FREEXL
53476 		spatialite_i ("\t- 'VirtualXL'\t\t[direct XLS access]\n");
53477 #endif /* end FreeXL conditional */
53478 #endif /* end ICONV conditional */
53479 		spatialite_i
53480 		    ("\t- 'VirtualNetwork'\t[Dijkstra shortest path - obsolete]\n");
53481 		spatialite_i ("\t- 'RTree'\t\t[Spatial Index - R*Tree]\n");
53482 		spatialite_i
53483 		    ("\t- 'MbrCache'\t\t[Spatial Index - MBR cache]\n");
53484 		spatialite_i
53485 		    ("\t- 'VirtualFDO'\t\t[FDO-OGR interoperability]\n");
53486 		spatialite_i ("\t- 'VirtualBBox'\t\t[BoundingBox tables]\n");
53487 		spatialite_i
53488 		    ("\t- 'VirtualSpatialIndex'\t[R*Tree metahandler]\n");
53489 		spatialite_i
53490 		    ("\t- 'VirtualElementary'\t[ElemGeoms metahandler]\n");
53491 
53492 #ifndef OMIT_GEOS		/* only if GEOS is supported */
53493 /* initializing the VirtualRouting  extension */
53494 		spatialite_i
53495 		    ("\t- 'VirtualRouting'\t[Dijkstra shortest path - advanced]\n");
53496 #ifndef OMIT_KNN		/* only if KNN is enabled */
53497 /* initializing the VirtualKNN  extension */ spatialite_i
53498 		    ("\t- 'VirtualKNN'\t[K-Nearest Neighbors metahandler]\n");
53499 #endif /* end KNN conditional */
53500 #endif /* end GEOS conditional */
53501 
53502 #ifdef ENABLE_GEOPACKAGE	/* VirtualGPKG is supported */
53503 		spatialite_i
53504 		    ("\t- 'VirtualGPKG'\t[OGC GeoPackage interoperability]\n");
53505 #endif
53506 #ifdef ENABLE_LIBXML2		/* VirtualXPath is supported */
53507 		spatialite_i
53508 		    ("\t- 'VirtualXPath'\t[XML Path Language - XPath]\n");
53509 #endif /* end including LIBXML2 */
53510 		spatialite_i ("\t- 'SpatiaLite'\t\t[Spatial SQL - OGC]\n");
53511 	    }
53512 
53513 
53514 #ifndef OMIT_PROJ		/* PROJ.4 version */
53515 	  if (verbose)
53516 	    {
53517 		const char *p_result = "unknown";
53518 #ifdef PROJ_NEW			/* supporting new PROJ.6 */
53519 		PJ_INFO info = proj_info ();
53520 		p_result = info.release;
53521 #else /* supporting old PROJ.4 */
53522 		p_result = pj_get_release ();
53523 #endif
53524 		spatialite_i ("PROJ version ........: %s\n", p_result);
53525 	    }
53526 #endif /* end PROJ */
53527 
53528 #ifndef OMIT_GEOS		/* GEOS version */
53529 	  if (verbose)
53530 	      spatialite_i ("GEOS version ........: %s\n", GEOSversion ());
53531 #endif /* end GEOS version */
53532 #ifdef ENABLE_RTTOPO		/* RTTOPO version */
53533 	  if (verbose)
53534 	      spatialite_i ("RTTOPO version ......: %s\n",
53535 			    splite_rttopo_version ());
53536 #endif /* end RTTOPO version */
53537 	  if (verbose)
53538 	      spatialite_i ("TARGET CPU ..........: %s\n",
53539 			    spatialite_target_cpu ());
53540       }
53541 }
53542 
53543 #ifndef LOADABLE_EXTENSION
53544 SPATIALITE_DECLARE void
spatialite_init_ex(sqlite3 * db_handle,const void * p_cache,int verbose)53545 spatialite_init_ex (sqlite3 * db_handle, const void *p_cache, int verbose)
53546 {
53547 /* used when SQLite initializes as an ordinary lib */
53548     struct splite_internal_cache *cache =
53549 	(struct splite_internal_cache *) p_cache;
53550     if (p_cache == NULL)
53551       {
53552 	  spatialite_e
53553 	      ("ERROR unable to initialize the SpatiaLite extension: NULL cache !!!\n");
53554 	  return;
53555       }
53556 
53557 /* setting the POSIX locale for numeric */
53558     setlocale (LC_NUMERIC, "POSIX");
53559 
53560     register_spatialite_sql_functions (db_handle, cache);
53561 
53562     init_spatialite_virtualtables (db_handle, p_cache);
53563     spatialite_splash_screen (verbose);
53564 
53565 /* setting a timeout handler */
53566     sqlite3_busy_timeout (db_handle, 5000);
53567 }
53568 
53569 SPATIALITE_DECLARE void
spatialite_cleanup_ex(const void * ptr)53570 spatialite_cleanup_ex (const void *ptr)
53571 {
53572     struct splite_internal_cache *cache = (struct splite_internal_cache *) ptr;
53573 
53574     if (cache == NULL)
53575 	return;
53576     if (cache->magic1 != SPATIALITE_CACHE_MAGIC1
53577 	|| cache->magic2 != SPATIALITE_CACHE_MAGIC2)
53578 	return;
53579 
53580 #ifdef ENABLE_RTTOPO
53581     gaiaResetRtTopoMsg (cache);
53582 #endif
53583 
53584     free_internal_cache (cache);
53585     sqlite3_reset_auto_extension ();
53586 }
53587 #endif /* not built as loadable-extension only */
53588 
53589 SPATIALITE_PRIVATE void
spatialite_internal_init(void * handle,const void * p_cache)53590 spatialite_internal_init (void *handle, const void *p_cache)
53591 {
53592 /* used only for internal usage */
53593     sqlite3 *db_handle = (sqlite3 *) handle;
53594     struct splite_internal_cache *cache =
53595 	(struct splite_internal_cache *) p_cache;
53596     if (p_cache == NULL)
53597       {
53598 	  spatialite_e
53599 	      ("ERROR unable to initialize the SpatiaLite extension: NULL cache !!!\n");
53600 	  return;
53601       }
53602     register_spatialite_sql_functions (db_handle, cache);
53603     init_spatialite_virtualtables (db_handle, p_cache);
53604 /* setting a timeout handler */
53605     sqlite3_busy_timeout (db_handle, 5000);
53606 }
53607 
53608 SPATIALITE_PRIVATE void
spatialite_internal_cleanup(const void * ptr)53609 spatialite_internal_cleanup (const void *ptr)
53610 {
53611     struct splite_internal_cache *cache = (struct splite_internal_cache *) ptr;
53612 
53613     if (cache == NULL)
53614 	return;
53615     if (cache->magic1 != SPATIALITE_CACHE_MAGIC1
53616 	|| cache->magic2 != SPATIALITE_CACHE_MAGIC2)
53617 	return;
53618 
53619 #ifdef ENABLE_RTTOPO
53620     gaiaResetRtTopoMsg (cache);
53621 #endif
53622 
53623     free_internal_cache (cache);
53624 }
53625 
53626 #ifdef LOADABLE_EXTENSION	/* loadable-extension only */
53627 #if !(defined _WIN32) || defined(__MINGW32__)
53628 /* MSVC is unable to understand this declaration */
53629 __attribute__((visibility ("default")))
53630 #endif
53631      SPATIALITE_DECLARE int
sqlite3_modspatialite_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)53632 	 sqlite3_modspatialite_init (sqlite3 * db, char **pzErrMsg,
53633 				     const sqlite3_api_routines * pApi)
53634 {
53635 /* SQLite invokes this routine once when it dynamically loads the extension. */
53636     spatialite_initialize ();
53637     return init_spatialite_extension (db, pzErrMsg, pApi);
53638 }
53639 #endif
53640 
53641 SPATIALITE_DECLARE sqlite3_int64
math_llabs(sqlite3_int64 value)53642 math_llabs (sqlite3_int64 value)
53643 {
53644 /* replacing the C99 llabs() function */
53645     return value < 0 ? -value : value;
53646 }
53647 
53648 SPATIALITE_DECLARE double
math_round(double value)53649 math_round (double value)
53650 {
53651 /* replacing the C99 round() function */
53652     double min = floor (value);
53653     if (fabs (value - min) < 0.5)
53654 	return min;
53655     return min + 1.0;
53656 }
53657