Coverage Report

Created: 2026-02-14 09:00

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