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