Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Extension SQL functions
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2013, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : /* WARNING: VERY IMPORTANT NOTE: This file MUST not be directly compiled as */
30 : /* a standalone object. It must be included from ogrsqlitevirtualogr.cpp */
31 : #ifndef COMPILATION_ALLOWED
32 : #error See comment in file
33 : #endif
34 :
35 : #include "ogrsqlitesqlfunctions.h"
36 : #include "ogr_geocoding.h"
37 :
38 : #include "ogr_swq.h"
39 :
40 : #include <limits>
41 :
42 : #undef SQLITE_STATIC
43 : #define SQLITE_STATIC ((sqlite3_destructor_type) nullptr)
44 :
45 : #ifndef HAVE_SPATIALITE
46 : #define MINIMAL_SPATIAL_FUNCTIONS
47 : #endif
48 :
49 : #define DEFINE_OGRSQLiteExtensionData_GetTransform
50 : #include "ogrsqlitesqlfunctionscommon.cpp"
51 :
52 : /************************************************************************/
53 : /* OGR2SQLITE_ogr_version() */
54 : /************************************************************************/
55 :
56 4 : static void OGR2SQLITE_ogr_version(sqlite3_context *pContext, int argc,
57 : sqlite3_value **argv)
58 : {
59 4 : if (argc == 0 || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
60 : {
61 4 : sqlite3_result_text(pContext, GDALVersionInfo("RELEASE_NAME"), -1,
62 : SQLITE_TRANSIENT);
63 : }
64 : else
65 : {
66 0 : sqlite3_result_text(
67 : pContext,
68 0 : GDALVersionInfo((const char *)sqlite3_value_text(argv[0])), -1,
69 : SQLITE_TRANSIENT);
70 : }
71 4 : }
72 :
73 : /************************************************************************/
74 : /* OGR2SQLITE_Transform() */
75 : /************************************************************************/
76 :
77 0 : static void OGR2SQLITE_Transform(sqlite3_context *pContext, int argc,
78 : sqlite3_value **argv)
79 : {
80 0 : if (argc != 3)
81 : {
82 0 : sqlite3_result_null(pContext);
83 0 : return;
84 : }
85 :
86 0 : if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
87 : {
88 0 : sqlite3_result_null(pContext);
89 0 : return;
90 : }
91 :
92 0 : if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
93 : {
94 0 : sqlite3_result_null(pContext);
95 0 : return;
96 : }
97 :
98 0 : if (sqlite3_value_type(argv[2]) != SQLITE_INTEGER)
99 : {
100 0 : sqlite3_result_null(pContext);
101 0 : return;
102 : }
103 :
104 0 : int nSrcSRSId = sqlite3_value_int(argv[1]);
105 0 : int nDstSRSId = sqlite3_value_int(argv[2]);
106 :
107 : OGRSQLiteExtensionData *poModule =
108 0 : (OGRSQLiteExtensionData *)sqlite3_user_data(pContext);
109 : OGRCoordinateTransformation *poCT =
110 0 : poModule->GetTransform(nSrcSRSId, nDstSRSId);
111 0 : if (poCT == nullptr)
112 : {
113 0 : sqlite3_result_null(pContext);
114 0 : return;
115 : }
116 :
117 0 : GByte *pabySLBLOB = (GByte *)sqlite3_value_blob(argv[0]);
118 0 : int nBLOBLen = sqlite3_value_bytes(argv[0]);
119 0 : OGRGeometry *poGeom = nullptr;
120 0 : if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(pabySLBLOB, nBLOBLen,
121 0 : &poGeom) == OGRERR_NONE &&
122 0 : poGeom->transform(poCT) == OGRERR_NONE &&
123 0 : OGRSQLiteLayer::ExportSpatiaLiteGeometry(poGeom, nDstSRSId, wkbNDR,
124 : FALSE, FALSE, &pabySLBLOB,
125 : &nBLOBLen) == OGRERR_NONE)
126 : {
127 0 : sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
128 : }
129 : else
130 : {
131 0 : sqlite3_result_null(pContext);
132 : }
133 0 : delete poGeom;
134 : }
135 :
136 : /************************************************************************/
137 : /* OGR2SQLITE_ogr_deflate() */
138 : /************************************************************************/
139 :
140 4 : static void OGR2SQLITE_ogr_deflate(sqlite3_context *pContext, int argc,
141 : sqlite3_value **argv)
142 : {
143 4 : int nLevel = -1;
144 8 : if (!(argc == 1 || argc == 2) ||
145 4 : !(sqlite3_value_type(argv[0]) == SQLITE_TEXT ||
146 1 : sqlite3_value_type(argv[0]) == SQLITE_BLOB))
147 : {
148 0 : sqlite3_result_null(pContext);
149 0 : return;
150 : }
151 4 : if (argc == 2)
152 : {
153 2 : if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
154 : {
155 1 : sqlite3_result_null(pContext);
156 1 : return;
157 : }
158 1 : nLevel = sqlite3_value_int(argv[1]);
159 : }
160 :
161 3 : size_t nOutBytes = 0;
162 3 : void *pOut = nullptr;
163 3 : if (sqlite3_value_type(argv[0]) == SQLITE_TEXT)
164 : {
165 2 : const char *pszVal = (const char *)sqlite3_value_text(argv[0]);
166 2 : pOut = CPLZLibDeflate(pszVal, strlen(pszVal) + 1, nLevel, nullptr, 0,
167 : &nOutBytes);
168 : }
169 : else
170 : {
171 1 : const void *pSrc = sqlite3_value_blob(argv[0]);
172 1 : int nLen = sqlite3_value_bytes(argv[0]);
173 1 : pOut = CPLZLibDeflate(pSrc, nLen, nLevel, nullptr, 0, &nOutBytes);
174 : }
175 3 : if (pOut != nullptr)
176 : {
177 3 : sqlite3_result_blob(pContext, pOut, static_cast<int>(nOutBytes),
178 : VSIFree);
179 : }
180 : else
181 : {
182 0 : sqlite3_result_null(pContext);
183 : }
184 :
185 3 : return;
186 : }
187 :
188 : /************************************************************************/
189 : /* OGR2SQLITE_ogr_inflate() */
190 : /************************************************************************/
191 :
192 5 : static void OGR2SQLITE_ogr_inflate(sqlite3_context *pContext, int argc,
193 : sqlite3_value **argv)
194 : {
195 5 : if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_BLOB)
196 : {
197 1 : sqlite3_result_null(pContext);
198 1 : return;
199 : }
200 :
201 4 : size_t nOutBytes = 0;
202 :
203 4 : const void *pSrc = sqlite3_value_blob(argv[0]);
204 4 : int nLen = sqlite3_value_bytes(argv[0]);
205 4 : void *pOut = CPLZLibInflate(pSrc, nLen, nullptr, 0, &nOutBytes);
206 :
207 4 : if (pOut != nullptr)
208 : {
209 3 : sqlite3_result_blob(pContext, pOut, static_cast<int>(nOutBytes),
210 : VSIFree);
211 : }
212 : else
213 : {
214 1 : sqlite3_result_null(pContext);
215 : }
216 :
217 4 : return;
218 : }
219 :
220 : /************************************************************************/
221 : /* OGR2SQLITE_ogr_geocode_set_result() */
222 : /************************************************************************/
223 :
224 112 : static void OGR2SQLITE_ogr_geocode_set_result(sqlite3_context *pContext,
225 : OGRLayerH hLayer,
226 : const char *pszField)
227 : {
228 112 : if (hLayer == nullptr)
229 8 : sqlite3_result_null(pContext);
230 : else
231 : {
232 104 : OGRLayer *poLayer = (OGRLayer *)hLayer;
233 104 : OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
234 104 : OGRFeature *poFeature = poLayer->GetNextFeature();
235 : int nIdx;
236 104 : if (poFeature == nullptr)
237 8 : sqlite3_result_null(pContext);
238 128 : else if (strcmp(pszField, "geometry") == 0 &&
239 32 : poFeature->GetGeometryRef() != nullptr)
240 : {
241 32 : GByte *pabyGeomBLOB = nullptr;
242 32 : int nGeomBLOBLen = 0;
243 64 : if (OGRSQLiteLayer::ExportSpatiaLiteGeometry(
244 32 : poFeature->GetGeometryRef(), 4326, wkbNDR, FALSE, FALSE,
245 32 : &pabyGeomBLOB, &nGeomBLOBLen) != OGRERR_NONE)
246 : {
247 0 : sqlite3_result_null(pContext);
248 : }
249 : else
250 : {
251 32 : sqlite3_result_blob(pContext, pabyGeomBLOB, nGeomBLOBLen,
252 : CPLFree);
253 : }
254 : }
255 126 : else if ((nIdx = poFDefn->GetFieldIndex(pszField)) >= 0 &&
256 62 : poFeature->IsFieldSetAndNotNull(nIdx))
257 : {
258 62 : OGRFieldType eType = poFDefn->GetFieldDefn(nIdx)->GetType();
259 62 : if (eType == OFTInteger)
260 0 : sqlite3_result_int(pContext,
261 : poFeature->GetFieldAsInteger(nIdx));
262 62 : else if (eType == OFTInteger64)
263 0 : sqlite3_result_int64(pContext,
264 : poFeature->GetFieldAsInteger64(nIdx));
265 62 : else if (eType == OFTReal)
266 0 : sqlite3_result_double(pContext,
267 : poFeature->GetFieldAsDouble(nIdx));
268 : else
269 62 : sqlite3_result_text(pContext, poFeature->GetFieldAsString(nIdx),
270 : -1, SQLITE_TRANSIENT);
271 : }
272 : else
273 2 : sqlite3_result_null(pContext);
274 104 : delete poFeature;
275 104 : OGRGeocodeFreeResult(hLayer);
276 : }
277 112 : }
278 :
279 : /************************************************************************/
280 : /* OGR2SQLITE_ogr_geocode() */
281 : /************************************************************************/
282 :
283 80 : static void OGR2SQLITE_ogr_geocode(sqlite3_context *pContext, int argc,
284 : sqlite3_value **argv)
285 : {
286 : OGRSQLiteExtensionData *poModule =
287 80 : (OGRSQLiteExtensionData *)sqlite3_user_data(pContext);
288 :
289 80 : if (argc < 1 || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
290 : {
291 16 : sqlite3_result_null(pContext);
292 16 : return;
293 : }
294 64 : const char *pszQuery = (const char *)sqlite3_value_text(argv[0]);
295 :
296 128 : CPLString osField = "geometry";
297 64 : if (argc >= 2 && sqlite3_value_type(argv[1]) == SQLITE_TEXT)
298 : {
299 32 : osField = (const char *)sqlite3_value_text(argv[1]);
300 : }
301 :
302 64 : char **papszOptions = nullptr;
303 72 : for (int i = 2; i < argc; i++)
304 : {
305 8 : if (sqlite3_value_type(argv[i]) == SQLITE_TEXT)
306 : {
307 0 : papszOptions = CSLAddString(
308 0 : papszOptions, (const char *)sqlite3_value_text(argv[i]));
309 : }
310 : }
311 :
312 64 : OGRGeocodingSessionH hSession = poModule->GetGeocodingSession();
313 64 : if (hSession == nullptr)
314 : {
315 64 : hSession = OGRGeocodeCreateSession(papszOptions);
316 64 : if (hSession == nullptr)
317 : {
318 0 : sqlite3_result_null(pContext);
319 0 : CSLDestroy(papszOptions);
320 0 : return;
321 : }
322 64 : poModule->SetGeocodingSession(hSession);
323 : }
324 :
325 64 : if (osField == "raw")
326 8 : papszOptions = CSLAddString(papszOptions, "RAW_FEATURE=YES");
327 :
328 64 : if (CSLFindString(papszOptions, "LIMIT") == -1)
329 64 : papszOptions = CSLAddString(papszOptions, "LIMIT=1");
330 :
331 64 : OGRLayerH hLayer = OGRGeocode(hSession, pszQuery, nullptr, papszOptions);
332 :
333 64 : OGR2SQLITE_ogr_geocode_set_result(pContext, hLayer, osField);
334 :
335 64 : CSLDestroy(papszOptions);
336 :
337 64 : return;
338 : }
339 :
340 : /************************************************************************/
341 : /* OGR2SQLITE_GetValAsDouble() */
342 : /************************************************************************/
343 :
344 144 : static double OGR2SQLITE_GetValAsDouble(sqlite3_value *val, int *pbGotVal)
345 : {
346 144 : switch (sqlite3_value_type(val))
347 : {
348 32 : case SQLITE_FLOAT:
349 32 : if (pbGotVal)
350 32 : *pbGotVal = TRUE;
351 32 : return sqlite3_value_double(val);
352 :
353 64 : case SQLITE_INTEGER:
354 64 : if (pbGotVal)
355 64 : *pbGotVal = TRUE;
356 64 : return (double)sqlite3_value_int64(val);
357 :
358 48 : default:
359 48 : if (pbGotVal)
360 48 : *pbGotVal = FALSE;
361 48 : return 0.0;
362 : }
363 : }
364 :
365 : /************************************************************************/
366 : /* OGR2SQLITE_GetGeom() */
367 : /************************************************************************/
368 :
369 : static std::unique_ptr<OGRGeometry>
370 21 : OGR2SQLITE_GetGeom(sqlite3_context * /*pContext*/, int /* argc */,
371 : sqlite3_value **argv, int *pnSRSId)
372 : {
373 21 : if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
374 : {
375 1 : return nullptr;
376 : }
377 :
378 20 : GByte *pabySLBLOB = (GByte *)sqlite3_value_blob(argv[0]);
379 20 : int nBLOBLen = sqlite3_value_bytes(argv[0]);
380 20 : OGRGeometry *poGeom = nullptr;
381 20 : if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(pabySLBLOB, nBLOBLen, &poGeom,
382 20 : pnSRSId) != OGRERR_NONE)
383 : {
384 0 : delete poGeom;
385 0 : return nullptr;
386 : }
387 :
388 20 : return std::unique_ptr<OGRGeometry>(poGeom);
389 : }
390 :
391 : /************************************************************************/
392 : /* OGR2SQLITE_ogr_geocode_reverse() */
393 : /************************************************************************/
394 :
395 96 : static void OGR2SQLITE_ogr_geocode_reverse(sqlite3_context *pContext, int argc,
396 : sqlite3_value **argv)
397 : {
398 : OGRSQLiteExtensionData *poModule =
399 96 : (OGRSQLiteExtensionData *)sqlite3_user_data(pContext);
400 :
401 96 : double dfLon = 0.0;
402 96 : double dfLat = 0.0;
403 96 : int iAfterGeomIdx = 0;
404 96 : int bGotLon = FALSE;
405 96 : int bGotLat = FALSE;
406 :
407 96 : if (argc >= 2)
408 : {
409 72 : dfLon = OGR2SQLITE_GetValAsDouble(argv[0], &bGotLon);
410 72 : dfLat = OGR2SQLITE_GetValAsDouble(argv[1], &bGotLat);
411 : }
412 :
413 128 : if (argc >= 3 && bGotLon && bGotLat &&
414 32 : sqlite3_value_type(argv[2]) == SQLITE_TEXT)
415 : {
416 32 : iAfterGeomIdx = 2;
417 : }
418 88 : else if (argc >= 2 && sqlite3_value_type(argv[0]) == SQLITE_BLOB &&
419 24 : sqlite3_value_type(argv[1]) == SQLITE_TEXT)
420 : {
421 16 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
422 32 : if (poGeom != nullptr &&
423 16 : wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
424 : {
425 16 : const OGRPoint *poPoint = poGeom->toPoint();
426 16 : dfLon = poPoint->getX();
427 16 : dfLat = poPoint->getY();
428 : }
429 : else
430 : {
431 0 : sqlite3_result_null(pContext);
432 0 : return;
433 : }
434 16 : iAfterGeomIdx = 1;
435 : }
436 : else
437 : {
438 48 : sqlite3_result_null(pContext);
439 48 : return;
440 : }
441 :
442 : const char *pszField =
443 48 : (const char *)sqlite3_value_text(argv[iAfterGeomIdx]);
444 :
445 48 : char **papszOptions = nullptr;
446 64 : for (int i = iAfterGeomIdx + 1; i < argc; i++)
447 : {
448 16 : if (sqlite3_value_type(argv[i]) == SQLITE_TEXT)
449 : {
450 16 : papszOptions = CSLAddString(
451 16 : papszOptions, (const char *)sqlite3_value_text(argv[i]));
452 : }
453 : }
454 :
455 48 : OGRGeocodingSessionH hSession = poModule->GetGeocodingSession();
456 48 : if (hSession == nullptr)
457 : {
458 48 : hSession = OGRGeocodeCreateSession(papszOptions);
459 48 : if (hSession == nullptr)
460 : {
461 0 : sqlite3_result_null(pContext);
462 0 : CSLDestroy(papszOptions);
463 0 : return;
464 : }
465 48 : poModule->SetGeocodingSession(hSession);
466 : }
467 :
468 48 : if (strcmp(pszField, "raw") == 0)
469 8 : papszOptions = CSLAddString(papszOptions, "RAW_FEATURE=YES");
470 :
471 48 : OGRLayerH hLayer = OGRGeocodeReverse(hSession, dfLon, dfLat, papszOptions);
472 :
473 48 : OGR2SQLITE_ogr_geocode_set_result(pContext, hLayer, pszField);
474 :
475 48 : CSLDestroy(papszOptions);
476 :
477 48 : return;
478 : }
479 :
480 : /************************************************************************/
481 : /* OGR2SQLITE_ogr_datasource_load_layers() */
482 : /************************************************************************/
483 :
484 8 : static void OGR2SQLITE_ogr_datasource_load_layers(sqlite3_context *pContext,
485 : int argc,
486 : sqlite3_value **argv)
487 : {
488 8 : sqlite3 *hDB = (sqlite3 *)sqlite3_user_data(pContext);
489 :
490 8 : if ((argc < 1 || argc > 3) || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
491 : {
492 1 : sqlite3_result_int(pContext, 0);
493 4 : return;
494 : }
495 7 : const char *pszDataSource = (const char *)sqlite3_value_text(argv[0]);
496 :
497 7 : int bUpdate = FALSE;
498 7 : if (argc >= 2)
499 : {
500 4 : if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
501 : {
502 1 : sqlite3_result_int(pContext, 0);
503 1 : return;
504 : }
505 3 : bUpdate = sqlite3_value_int(argv[1]);
506 : }
507 :
508 6 : const char *pszPrefix = nullptr;
509 6 : if (argc >= 3)
510 : {
511 2 : if (sqlite3_value_type(argv[2]) != SQLITE_TEXT)
512 : {
513 1 : sqlite3_result_int(pContext, 0);
514 1 : return;
515 : }
516 1 : pszPrefix = (const char *)sqlite3_value_text(argv[2]);
517 : }
518 :
519 : OGRDataSource *poDS =
520 5 : (OGRDataSource *)OGROpenShared(pszDataSource, bUpdate, nullptr);
521 5 : if (poDS == nullptr)
522 : {
523 1 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszDataSource);
524 1 : sqlite3_result_int(pContext, 0);
525 1 : return;
526 : }
527 :
528 8 : CPLString osEscapedDataSource = SQLEscapeLiteral(pszDataSource);
529 8 : for (int i = 0; i < poDS->GetLayerCount(); i++)
530 : {
531 4 : const char *pszLayerName = poDS->GetLayer(i)->GetName();
532 8 : CPLString osEscapedLayerName = SQLEscapeLiteral(pszLayerName);
533 8 : CPLString osTableName;
534 4 : if (pszPrefix != nullptr)
535 : {
536 1 : osTableName = pszPrefix;
537 1 : osTableName += "_";
538 1 : osTableName += SQLEscapeName(pszLayerName);
539 : }
540 : else
541 : {
542 3 : osTableName = SQLEscapeName(pszLayerName);
543 : }
544 :
545 4 : SQLCommand(
546 : hDB,
547 : CPLSPrintf(
548 : "CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR('%s', %d, '%s')",
549 : osTableName.c_str(), osEscapedDataSource.c_str(), bUpdate,
550 : osEscapedLayerName.c_str()));
551 : }
552 :
553 4 : poDS->Release();
554 4 : sqlite3_result_int(pContext, 1);
555 : }
556 :
557 : #ifdef notdef
558 : /************************************************************************/
559 : /* OGR2SQLITE_ogr_GetConfigOption() */
560 : /************************************************************************/
561 :
562 : static void OGR2SQLITE_ogr_GetConfigOption(sqlite3_context *pContext, int argc,
563 : sqlite3_value **argv)
564 : {
565 : if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
566 : {
567 : sqlite3_result_null(pContext);
568 : return;
569 : }
570 :
571 : const char *pszKey = (const char *)sqlite3_value_text(argv[0]);
572 : const char *pszVal = CPLGetConfigOption(pszKey, nullptr);
573 : if (pszVal == nullptr)
574 : sqlite3_result_null(pContext);
575 : else
576 : sqlite3_result_text(pContext, pszVal, -1, SQLITE_TRANSIENT);
577 : }
578 :
579 : /************************************************************************/
580 : /* OGR2SQLITE_ogr_SetConfigOption() */
581 : /************************************************************************/
582 :
583 : static void OGR2SQLITE_ogr_SetConfigOption(sqlite3_context *pContext, int argc,
584 : sqlite3_value **argv)
585 : {
586 : if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
587 : {
588 : sqlite3_result_null(pContext);
589 : return;
590 : }
591 : if (sqlite3_value_type(argv[1]) != SQLITE_TEXT &&
592 : sqlite3_value_type(argv[1]) != SQLITE_NULL)
593 : {
594 : sqlite3_result_null(pContext);
595 : return;
596 : }
597 :
598 : const char *pszKey = (const char *)sqlite3_value_text(argv[0]);
599 : const char *pszVal = (sqlite3_value_type(argv[1]) == SQLITE_TEXT)
600 : ? (const char *)sqlite3_value_text(argv[1])
601 : : nullptr;
602 : CPLSetConfigOption(pszKey, pszVal);
603 : sqlite3_result_null(pContext);
604 : }
605 : #endif // notdef
606 :
607 : /************************************************************************/
608 : /* OGR2SQLITE_SetGeom_AndDestroy() */
609 : /************************************************************************/
610 :
611 1 : static void OGR2SQLITE_SetGeom_AndDestroy(sqlite3_context *pContext,
612 : OGRGeometry *poGeom, int nSRSId)
613 : {
614 1 : GByte *pabySLBLOB = nullptr;
615 1 : int nBLOBLen = 0;
616 1 : if (poGeom != nullptr && OGRSQLiteLayer::ExportSpatiaLiteGeometry(
617 : poGeom, nSRSId, wkbNDR, FALSE, FALSE,
618 : &pabySLBLOB, &nBLOBLen) == OGRERR_NONE)
619 : {
620 1 : sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
621 : }
622 : else
623 : {
624 0 : sqlite3_result_null(pContext);
625 : }
626 1 : delete poGeom;
627 1 : }
628 :
629 : /************************************************************************/
630 : /* OGR2SQLITE_ST_GeodesicArea() */
631 : /************************************************************************/
632 :
633 4 : static void OGR2SQLITE_ST_GeodesicArea(sqlite3_context *pContext, int argc,
634 : sqlite3_value **argv)
635 : {
636 4 : if (sqlite3_value_int(argv[1]) != 1)
637 : {
638 1 : CPLError(CE_Warning, CPLE_NotSupported,
639 : "ST_Area(geom, use_ellipsoid) is only supported for "
640 : "use_ellipsoid = 1");
641 : }
642 :
643 4 : int nSRSId = -1;
644 4 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
645 4 : if (poGeom != nullptr)
646 : {
647 3 : OGRSpatialReference oSRS;
648 3 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
649 3 : if (nSRSId > 0)
650 : {
651 2 : if (oSRS.importFromEPSG(nSRSId) != OGRERR_NONE)
652 : {
653 0 : sqlite3_result_null(pContext);
654 0 : return;
655 : }
656 : }
657 : else
658 : {
659 1 : CPLDebug("OGR_SQLITE",
660 : "Assuming EPSG:4326 for GeodesicArea() computation");
661 1 : oSRS.importFromEPSG(4326);
662 : }
663 3 : poGeom->assignSpatialReference(&oSRS);
664 3 : sqlite3_result_double(
665 : pContext, OGR_G_GeodesicArea(OGRGeometry::ToHandle(poGeom.get())));
666 3 : poGeom->assignSpatialReference(nullptr);
667 : }
668 : else
669 : {
670 1 : sqlite3_result_null(pContext);
671 : }
672 : }
673 :
674 : #ifdef MINIMAL_SPATIAL_FUNCTIONS
675 :
676 : /************************************************************************/
677 : /* OGR2SQLITE_ST_AsText() */
678 : /************************************************************************/
679 :
680 : static void OGR2SQLITE_ST_AsText(sqlite3_context *pContext, int argc,
681 : sqlite3_value **argv)
682 : {
683 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
684 : if (poGeom != nullptr)
685 : {
686 : char *pszWKT = nullptr;
687 : if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
688 : sqlite3_result_text(pContext, pszWKT, -1, CPLFree);
689 : else
690 : sqlite3_result_null(pContext);
691 : }
692 : else
693 : sqlite3_result_null(pContext);
694 : }
695 :
696 : /************************************************************************/
697 : /* OGR2SQLITE_ST_AsBinary() */
698 : /************************************************************************/
699 :
700 : static void OGR2SQLITE_ST_AsBinary(sqlite3_context *pContext, int argc,
701 : sqlite3_value **argv)
702 : {
703 : if (auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr))
704 : {
705 : const size_t nBLOBLen = poGeom->WkbSize();
706 : if (nBLOBLen > static_cast<size_t>(std::numeric_limits<int>::max()))
707 : {
708 : CPLError(CE_Failure, CPLE_NotSupported, "Too large geometry");
709 : sqlite3_result_null(pContext);
710 : return;
711 : }
712 : GByte *pabyGeomBLOB = (GByte *)VSI_MALLOC_VERBOSE(nBLOBLen);
713 : if (pabyGeomBLOB != nullptr)
714 : {
715 : if (poGeom->exportToWkb(wkbNDR, pabyGeomBLOB) == OGRERR_NONE)
716 : sqlite3_result_blob(pContext, pabyGeomBLOB,
717 : static_cast<int>(nBLOBLen), CPLFree);
718 : else
719 : {
720 : VSIFree(pabyGeomBLOB);
721 : sqlite3_result_null(pContext);
722 : }
723 : }
724 : else
725 : sqlite3_result_null(pContext);
726 : }
727 : else
728 : sqlite3_result_null(pContext);
729 : }
730 :
731 : /************************************************************************/
732 : /* OGR2SQLITE_ST_GeomFromText() */
733 : /************************************************************************/
734 :
735 : static void OGR2SQLITE_ST_GeomFromText(sqlite3_context *pContext, int argc,
736 : sqlite3_value **argv)
737 : {
738 : if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
739 : {
740 : sqlite3_result_null(pContext);
741 : return;
742 : }
743 : const char *pszWKT =
744 : reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
745 :
746 : int nSRID = -1;
747 : if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_INTEGER)
748 : nSRID = sqlite3_value_int(argv[1]);
749 :
750 : OGRGeometry *poGeom = nullptr;
751 : if (OGRGeometryFactory::createFromWkt(pszWKT, nullptr, &poGeom) ==
752 : OGRERR_NONE)
753 : {
754 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom, nSRID);
755 : }
756 : else
757 : sqlite3_result_null(pContext);
758 : }
759 :
760 : /************************************************************************/
761 : /* OGR2SQLITE_ST_GeomFromWKB() */
762 : /************************************************************************/
763 :
764 : static void OGR2SQLITE_ST_GeomFromWKB(sqlite3_context *pContext, int argc,
765 : sqlite3_value **argv)
766 : {
767 : if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
768 : {
769 : sqlite3_result_null(pContext);
770 : return;
771 : }
772 :
773 : int nSRID = -1;
774 : if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_INTEGER)
775 : nSRID = sqlite3_value_int(argv[1]);
776 :
777 : GByte *pabySLBLOB = (GByte *)sqlite3_value_blob(argv[0]);
778 : int nBLOBLen = sqlite3_value_bytes(argv[0]);
779 : OGRGeometry *poGeom = nullptr;
780 :
781 : if (OGRGeometryFactory::createFromWkb(pabySLBLOB, nullptr, &poGeom,
782 : nBLOBLen) == OGRERR_NONE)
783 : {
784 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom, nSRID);
785 : }
786 : else
787 : sqlite3_result_null(pContext);
788 : }
789 :
790 : /************************************************************************/
791 : /* CheckSTFunctions() */
792 : /************************************************************************/
793 :
794 : static bool CheckSTFunctions(sqlite3_context *pContext, int argc,
795 : sqlite3_value **argv,
796 : std::unique_ptr<OGRGeometry> &poGeom1,
797 : std::unique_ptr<OGRGeometry> &poGeom2,
798 : int *pnSRSId)
799 : {
800 : if (argc != 2)
801 : {
802 : return false;
803 : }
804 :
805 : poGeom1 = OGR2SQLITE_GetGeom(pContext, argc, argv, pnSRSId);
806 : poGeom2 = OGR2SQLITE_GetGeom(pContext, argc - 1, argv + 1, nullptr);
807 : return poGeom1 && poGeom2;
808 : }
809 :
810 : /************************************************************************/
811 : /* OGR2SQLITE_ST_int_geomgeom_op() */
812 : /************************************************************************/
813 :
814 : #define OGR2SQLITE_ST_int_geomgeom_op(op) \
815 : static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc, \
816 : sqlite3_value **argv) \
817 : { \
818 : std::unique_ptr<OGRGeometry> poGeom1; \
819 : std::unique_ptr<OGRGeometry> poGeom2; \
820 : if (!CheckSTFunctions(pContext, argc, argv, poGeom1, poGeom2, \
821 : nullptr)) \
822 : { \
823 : sqlite3_result_int(pContext, 0); \
824 : return; \
825 : } \
826 : \
827 : sqlite3_result_int(pContext, poGeom1->op(poGeom2.get())); \
828 : }
829 :
830 : // clang-format off
831 : OGR2SQLITE_ST_int_geomgeom_op(Intersects)
832 : OGR2SQLITE_ST_int_geomgeom_op(Equals)
833 : OGR2SQLITE_ST_int_geomgeom_op(Disjoint)
834 : OGR2SQLITE_ST_int_geomgeom_op(Touches)
835 : OGR2SQLITE_ST_int_geomgeom_op(Crosses)
836 : OGR2SQLITE_ST_int_geomgeom_op(Within)
837 : OGR2SQLITE_ST_int_geomgeom_op(Contains)
838 : OGR2SQLITE_ST_int_geomgeom_op(Overlaps)
839 : // clang-format on
840 :
841 : /************************************************************************/
842 : /* OGR2SQLITE_ST_int_geom_op() */
843 : /************************************************************************/
844 :
845 : #define OGR2SQLITE_ST_int_geom_op(op) \
846 : static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc, \
847 : sqlite3_value **argv) \
848 : { \
849 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr); \
850 : if (poGeom != nullptr) \
851 : sqlite3_result_int(pContext, poGeom->op()); \
852 : else \
853 : sqlite3_result_int(pContext, 0); \
854 : }
855 :
856 : // clang-format off
857 : OGR2SQLITE_ST_int_geom_op(IsEmpty)
858 : OGR2SQLITE_ST_int_geom_op(IsSimple)
859 : OGR2SQLITE_ST_int_geom_op(IsValid)
860 : // clang-format on
861 :
862 : /************************************************************************/
863 : /* OGR2SQLITE_ST_geom_geomgeom_op() */
864 : /************************************************************************/
865 :
866 : #define OGR2SQLITE_ST_geom_geomgeom_op(op) \
867 : static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc, \
868 : sqlite3_value **argv) \
869 : { \
870 : std::unique_ptr<OGRGeometry> poGeom1; \
871 : std::unique_ptr<OGRGeometry> poGeom2; \
872 : int nSRSId = -1; \
873 : if (!CheckSTFunctions(pContext, argc, argv, poGeom1, poGeom2, \
874 : &nSRSId)) \
875 : { \
876 : sqlite3_result_null(pContext); \
877 : return; \
878 : } \
879 : \
880 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom1->op(poGeom2.get()), \
881 : nSRSId); \
882 : }
883 :
884 : // clang-format off
885 : OGR2SQLITE_ST_geom_geomgeom_op(Intersection)
886 : OGR2SQLITE_ST_geom_geomgeom_op(Difference)
887 : OGR2SQLITE_ST_geom_geomgeom_op(Union)
888 : OGR2SQLITE_ST_geom_geomgeom_op(SymDifference)
889 : // clang-format on
890 :
891 : /************************************************************************/
892 : /* OGR2SQLITE_ST_SRID() */
893 : /************************************************************************/
894 :
895 : static void OGR2SQLITE_ST_SRID(sqlite3_context *pContext, int argc,
896 : sqlite3_value **argv)
897 : {
898 : int nSRSId = -1;
899 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
900 : if (poGeom != nullptr)
901 : {
902 : CPLPushErrorHandler(CPLQuietErrorHandler);
903 : sqlite3_result_int(pContext, nSRSId);
904 : CPLPopErrorHandler();
905 : }
906 : else
907 : sqlite3_result_null(pContext);
908 : }
909 :
910 : /************************************************************************/
911 : /* OGR2SQLITE_ST_Area() */
912 : /************************************************************************/
913 :
914 : static void OGR2SQLITE_ST_Area(sqlite3_context *pContext, int argc,
915 : sqlite3_value **argv)
916 : {
917 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
918 : if (poGeom != nullptr)
919 : {
920 : CPLPushErrorHandler(CPLQuietErrorHandler);
921 : sqlite3_result_double(pContext,
922 : OGR_G_Area(OGRGeometry::ToHandle(poGeom.get())));
923 : CPLPopErrorHandler();
924 : }
925 : else
926 : sqlite3_result_null(pContext);
927 : }
928 :
929 : /************************************************************************/
930 : /* OGR2SQLITE_ST_Buffer() */
931 : /************************************************************************/
932 :
933 : static void OGR2SQLITE_ST_Buffer(sqlite3_context *pContext, int argc,
934 : sqlite3_value **argv)
935 : {
936 : int nSRSId = -1;
937 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
938 : int bGotVal = FALSE;
939 : double dfDist = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
940 : if (poGeom != nullptr && bGotVal)
941 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom->Buffer(dfDist), nSRSId);
942 : else
943 : sqlite3_result_null(pContext);
944 : }
945 :
946 : /************************************************************************/
947 : /* OGR2SQLITE_ST_MakePoint() */
948 : /************************************************************************/
949 :
950 : static void OGR2SQLITE_ST_MakePoint(sqlite3_context *pContext, int argc,
951 : sqlite3_value **argv)
952 : {
953 : double dfY = 0.0;
954 : int bGotVal = FALSE;
955 : const double dfX = OGR2SQLITE_GetValAsDouble(argv[0], &bGotVal);
956 : if (bGotVal)
957 : dfY = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
958 : if (!bGotVal)
959 : {
960 : sqlite3_result_null(pContext);
961 : return;
962 : }
963 :
964 : OGRPoint *poPoint = nullptr;
965 : if (argc == 3)
966 : {
967 : double dfZ = OGR2SQLITE_GetValAsDouble(argv[2], &bGotVal);
968 : if (!bGotVal)
969 : {
970 : sqlite3_result_null(pContext);
971 : return;
972 : }
973 :
974 : poPoint = new OGRPoint(dfX, dfY, dfZ);
975 : }
976 : else
977 : {
978 : poPoint = new OGRPoint(dfX, dfY);
979 : }
980 :
981 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poPoint, -1);
982 : }
983 :
984 : #endif // #ifdef MINIMAL_SPATIAL_FUNCTIONS
985 :
986 : /************************************************************************/
987 : /* OGR2SQLITE_ST_MakeValid() */
988 : /************************************************************************/
989 :
990 1 : static void OGR2SQLITE_ST_MakeValid(sqlite3_context *pContext, int argc,
991 : sqlite3_value **argv)
992 : {
993 1 : int nSRSId = -1;
994 2 : auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
995 1 : if (poGeom != nullptr)
996 1 : OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom->MakeValid(), nSRSId);
997 : else
998 0 : sqlite3_result_null(pContext);
999 1 : }
1000 :
1001 : /************************************************************************/
1002 : /* OGRSQLITE_hstore_get_value() */
1003 : /************************************************************************/
1004 :
1005 6 : static void OGRSQLITE_hstore_get_value(sqlite3_context *pContext,
1006 : CPL_UNUSED int argc,
1007 : sqlite3_value **argv)
1008 : {
1009 10 : if (sqlite3_value_type(argv[0]) != SQLITE_TEXT ||
1010 4 : sqlite3_value_type(argv[1]) != SQLITE_TEXT)
1011 : {
1012 4 : sqlite3_result_null(pContext);
1013 4 : return;
1014 : }
1015 :
1016 2 : const char *pszHStore = (const char *)sqlite3_value_text(argv[0]);
1017 2 : const char *pszSearchedKey = (const char *)sqlite3_value_text(argv[1]);
1018 2 : char *pszValue = OGRHStoreGetValue(pszHStore, pszSearchedKey);
1019 2 : if (pszValue != nullptr)
1020 1 : sqlite3_result_text(pContext, pszValue, -1, CPLFree);
1021 : else
1022 1 : sqlite3_result_null(pContext);
1023 : }
1024 :
1025 : /************************************************************************/
1026 : /* OGRSQLiteRegisterSQLFunctions() */
1027 : /************************************************************************/
1028 :
1029 : #ifndef SQLITE_DETERMINISTIC
1030 : #define SQLITE_DETERMINISTIC 0
1031 : #endif
1032 :
1033 : #ifndef SQLITE_INNOCUOUS
1034 : #define SQLITE_INNOCUOUS 0
1035 : #endif
1036 :
1037 : #ifndef UTF8_INNOCUOUS
1038 : #define UTF8_INNOCUOUS (SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS)
1039 : #endif
1040 :
1041 1218 : static void *OGRSQLiteRegisterSQLFunctions(sqlite3 *hDB)
1042 : {
1043 1218 : OGRSQLiteExtensionData *pData = OGRSQLiteRegisterSQLFunctionsCommon(hDB);
1044 :
1045 1218 : sqlite3_create_function(hDB, "ogr_version", 0, UTF8_INNOCUOUS, nullptr,
1046 : OGR2SQLITE_ogr_version, nullptr, nullptr);
1047 :
1048 1218 : sqlite3_create_function(hDB, "ogr_version", 1, UTF8_INNOCUOUS, nullptr,
1049 : OGR2SQLITE_ogr_version, nullptr, nullptr);
1050 :
1051 1218 : sqlite3_create_function(hDB, "ogr_deflate", 1, UTF8_INNOCUOUS, nullptr,
1052 : OGR2SQLITE_ogr_deflate, nullptr, nullptr);
1053 :
1054 1218 : sqlite3_create_function(hDB, "ogr_deflate", 2, UTF8_INNOCUOUS, nullptr,
1055 : OGR2SQLITE_ogr_deflate, nullptr, nullptr);
1056 :
1057 1218 : sqlite3_create_function(hDB, "ogr_inflate", 1, UTF8_INNOCUOUS, nullptr,
1058 : OGR2SQLITE_ogr_inflate, nullptr, nullptr);
1059 :
1060 1218 : sqlite3_create_function(hDB, "ogr_geocode", -1, SQLITE_UTF8, pData,
1061 : OGR2SQLITE_ogr_geocode, nullptr, nullptr);
1062 :
1063 1218 : sqlite3_create_function(hDB, "ogr_geocode_reverse", -1, SQLITE_UTF8, pData,
1064 : OGR2SQLITE_ogr_geocode_reverse, nullptr, nullptr);
1065 :
1066 1218 : sqlite3_create_function(hDB, "ogr_datasource_load_layers", 1, SQLITE_UTF8,
1067 : hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
1068 : nullptr);
1069 :
1070 1218 : sqlite3_create_function(hDB, "ogr_datasource_load_layers", 2, SQLITE_UTF8,
1071 : hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
1072 : nullptr);
1073 :
1074 1218 : sqlite3_create_function(hDB, "ogr_datasource_load_layers", 3, SQLITE_UTF8,
1075 : hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
1076 : nullptr);
1077 :
1078 : #if notdef
1079 : sqlite3_create_function(hDB, "ogr_GetConfigOption", 1, SQLITE_UTF8, nullptr,
1080 : OGR2SQLITE_ogr_GetConfigOption, nullptr, nullptr);
1081 :
1082 : sqlite3_create_function(hDB, "ogr_SetConfigOption", 2, SQLITE_UTF8, nullptr,
1083 : OGR2SQLITE_ogr_SetConfigOption, nullptr, nullptr);
1084 : #endif
1085 :
1086 : // Custom and undocumented function, not sure I'll keep it.
1087 1218 : sqlite3_create_function(hDB, "Transform3", 3, UTF8_INNOCUOUS, pData,
1088 : OGR2SQLITE_Transform, nullptr, nullptr);
1089 :
1090 : // HSTORE functions
1091 1218 : sqlite3_create_function(hDB, "hstore_get_value", 2, UTF8_INNOCUOUS, nullptr,
1092 : OGRSQLITE_hstore_get_value, nullptr, nullptr);
1093 :
1094 : /* Check if spatialite is available */
1095 1218 : int rc = sqlite3_exec(hDB, "SELECT spatialite_version()", nullptr, nullptr,
1096 : nullptr);
1097 :
1098 : /* Reset error flag */
1099 1218 : sqlite3_exec(hDB, "SELECT 1", nullptr, nullptr, nullptr);
1100 :
1101 1218 : const bool bSpatialiteAvailable = rc == SQLITE_OK;
1102 : const bool bAllowOGRSQLiteSpatialFunctions =
1103 1218 : CPLTestBool(CPLGetConfigOption("OGR_SQLITE_SPATIAL_FUNCTIONS", "YES"));
1104 :
1105 : #define REGISTER_ST_op(argc, op) \
1106 : sqlite3_create_function(hDB, #op, argc, UTF8_INNOCUOUS, nullptr, \
1107 : OGR2SQLITE_ST_##op, nullptr, nullptr); \
1108 : sqlite3_create_function(hDB, "ST_" #op, argc, UTF8_INNOCUOUS, nullptr, \
1109 : OGR2SQLITE_ST_##op, nullptr, nullptr);
1110 :
1111 : #ifdef MINIMAL_SPATIAL_FUNCTIONS
1112 : if (!bSpatialiteAvailable && bAllowOGRSQLiteSpatialFunctions)
1113 : {
1114 : static const auto DebugOnce = []()
1115 : {
1116 : CPLDebug("SQLITE",
1117 : "Spatialite not available. Implementing a few functions");
1118 : return true;
1119 : }();
1120 : CPL_IGNORE_RET_VAL(DebugOnce);
1121 :
1122 : REGISTER_ST_op(1, AsText);
1123 : REGISTER_ST_op(1, AsBinary);
1124 : REGISTER_ST_op(1, GeomFromText);
1125 : REGISTER_ST_op(2, GeomFromText);
1126 : REGISTER_ST_op(1, GeomFromWKB);
1127 : REGISTER_ST_op(2, GeomFromWKB);
1128 :
1129 : REGISTER_ST_op(1, IsEmpty);
1130 : REGISTER_ST_op(1, IsSimple);
1131 : REGISTER_ST_op(1, IsValid);
1132 :
1133 : REGISTER_ST_op(2, Intersects);
1134 : REGISTER_ST_op(2, Equals);
1135 : REGISTER_ST_op(2, Disjoint);
1136 : REGISTER_ST_op(2, Touches);
1137 : REGISTER_ST_op(2, Crosses);
1138 : REGISTER_ST_op(2, Within);
1139 : REGISTER_ST_op(2, Contains);
1140 : REGISTER_ST_op(2, Overlaps);
1141 :
1142 : REGISTER_ST_op(2, Intersection);
1143 : REGISTER_ST_op(2, Difference);
1144 : // Union() is invalid
1145 : sqlite3_create_function(hDB, "ST_Union", 2, UTF8_INNOCUOUS, nullptr,
1146 : OGR2SQLITE_ST_Union, nullptr, nullptr);
1147 : REGISTER_ST_op(2, SymDifference);
1148 :
1149 : REGISTER_ST_op(1, SRID);
1150 : REGISTER_ST_op(1, Area);
1151 : REGISTER_ST_op(2, Buffer);
1152 : REGISTER_ST_op(2, MakePoint);
1153 : REGISTER_ST_op(3, MakePoint);
1154 : }
1155 : #endif // #ifdef MINIMAL_SPATIAL_FUNCTIONS
1156 :
1157 1218 : if (bAllowOGRSQLiteSpatialFunctions)
1158 : {
1159 : // We add a ST_Area() method with 2 arguments even when Spatialite
1160 : // is there to indicate we want to use the ellipsoid version
1161 1218 : sqlite3_create_function(hDB, "Area", 2, UTF8_INNOCUOUS, nullptr,
1162 : OGR2SQLITE_ST_GeodesicArea, nullptr, nullptr);
1163 1218 : sqlite3_create_function(hDB, "ST_Area", 2, UTF8_INNOCUOUS, nullptr,
1164 : OGR2SQLITE_ST_GeodesicArea, nullptr, nullptr);
1165 :
1166 61 : static bool gbRegisterMakeValid = [bSpatialiteAvailable, hDB]()
1167 : {
1168 21 : bool bRegisterMakeValid = false;
1169 21 : if (bSpatialiteAvailable)
1170 : {
1171 : // ST_MakeValid() only available (at time of writing) in
1172 : // Spatialite builds against (GPL) liblwgeom
1173 : // In the future, if they use GEOS 3.8 MakeValid, we could
1174 : // get rid of this.
1175 20 : int l_rc = sqlite3_exec(
1176 : hDB, "SELECT ST_MakeValid(ST_GeomFromText('POINT (0 0)'))",
1177 : nullptr, nullptr, nullptr);
1178 :
1179 : /* Reset error flag */
1180 20 : sqlite3_exec(hDB, "SELECT 1", nullptr, nullptr, nullptr);
1181 :
1182 20 : bRegisterMakeValid = (l_rc != SQLITE_OK);
1183 : }
1184 : else
1185 : {
1186 1 : bRegisterMakeValid = true;
1187 : }
1188 21 : if (bRegisterMakeValid)
1189 : {
1190 21 : return OGRGeometryFactory::haveGEOS();
1191 : }
1192 0 : return false;
1193 1218 : }();
1194 1218 : if (gbRegisterMakeValid)
1195 : {
1196 1218 : REGISTER_ST_op(1, MakeValid);
1197 : }
1198 : }
1199 :
1200 1218 : return pData;
1201 : }
|