Coverage Report

Created: 2026-06-30 08:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  SQLite Virtual Table module using OGR layers
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
#define DEFINE_OGRSQLiteSQLFunctionsSetCaseSensitiveLike
14
15
#include "cpl_port.h"
16
#include "ogrsqlitevirtualogr.h"
17
18
#include <cctype>
19
#include <cstdio>
20
#include <cstdlib>
21
#include <cstring>
22
#include <limits>
23
#include <map>
24
#include <set>
25
#include <string>
26
#include <utility>
27
#include <vector>
28
29
#include "cpl_conv.h"
30
#include "cpl_error.h"
31
#include "cpl_string.h"
32
33
/************************************************************************/
34
/*                OGR2SQLITE_GetNameForGeometryColumn()                 */
35
/************************************************************************/
36
37
CPLString OGR2SQLITE_GetNameForGeometryColumn(OGRLayer *poLayer)
38
0
{
39
0
    const char *pszGeomColumn = poLayer->GetGeometryColumn();
40
0
    if (pszGeomColumn != nullptr && !EQUAL(pszGeomColumn, ""))
41
0
    {
42
0
        if (poLayer->GetLayerDefn()->GetFieldIndex(pszGeomColumn) < 0)
43
0
            return pszGeomColumn;
44
0
    }
45
46
0
    CPLString osGeomCol("GEOMETRY");
47
0
    int nTry = 2;
48
0
    while (poLayer->GetLayerDefn()->GetFieldIndex(osGeomCol) >= 0)
49
0
    {
50
0
        osGeomCol.Printf("GEOMETRY%d", nTry++);
51
0
    }
52
0
    return osGeomCol;
53
0
}
54
55
#if !defined(HAVE_SQLITE3EXT_H)
56
57
// Stub functions
58
59
void OGR2SQLITE_Register()
60
{
61
}
62
63
OGR2SQLITEModule *OGR2SQLITE_Setup(GDALDataset *, OGRSQLiteDataSource *)
64
{
65
    return nullptr;
66
}
67
68
void OGR2SQLITE_SetCaseSensitiveLike(OGR2SQLITEModule *, bool)
69
{
70
}
71
72
int OGR2SQLITE_AddExtraDS(OGR2SQLITEModule *, GDALDataset *)
73
{
74
    return 0;
75
}
76
77
#else
78
79
/************************************************************************/
80
/*                        OGR2SQLITE_Register()                         */
81
/************************************************************************/
82
83
CPL_C_START
84
int CPL_DLL OGR2SQLITE_static_register(sqlite3 *hDB, char **pzErrMsg,
85
                                       void *pApi);
86
CPL_C_END
87
88
/* We call this function so that each time a db is created, */
89
/* OGR2SQLITE_static_register is called, to initialize the sqlite3_api */
90
/* structure with the right pointers. */
91
/* We need to declare this function before including sqlite3ext.h, since */
92
/* sqlite 3.8.7, sqlite3_auto_extension can be a macro (#5725) */
93
94
void OGR2SQLITE_Register()
95
1.07k
{
96
1.07k
#if defined(__GNUC__)
97
1.07k
#pragma GCC diagnostic push
98
#if !defined(SQLITE_HAS_NON_DEPRECATED_AUTO_EXTENSION)
99
#pragma GCC diagnostic ignored "-Wdeprecated"
100
#endif
101
1.07k
#ifdef HAVE_WFLAG_CAST_FUNCTION_TYPE
102
1.07k
#pragma GCC diagnostic ignored "-Wcast-function-type"
103
1.07k
#endif
104
1.07k
#endif
105
1.07k
    sqlite3_auto_extension(
106
1.07k
        reinterpret_cast<void (*)(void)>(OGR2SQLITE_static_register));
107
1.07k
#if defined(__GNUC__)
108
1.07k
#pragma GCC diagnostic pop
109
1.07k
#endif
110
1.07k
}
111
112
#define VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
113
// #define DEBUG_OGR2SQLITE
114
115
#include "gdal_priv.h"
116
#include "ogr_api.h"
117
#include "ogr_core.h"
118
#include "ogr_feature.h"
119
#include "ogr_geometry.h"
120
#include "ogr_p.h"
121
#include "ogr_spatialref.h"
122
#include "ogrsf_frmts.h"
123
#include "ogrsqlitesqlfunctions.h"
124
#include "ogrsqliteutility.h"
125
#include "ogr_swq.h"
126
#include "sqlite3.h"
127
#include "sqlite3ext.h"
128
129
#undef SQLITE_EXTENSION_INIT1
130
#define SQLITE_EXTENSION_INIT1                                                 \
131
    const sqlite3_api_routines *sqlite3_api = nullptr;
132
133
/* Declaration of sqlite3_api structure */
134
static SQLITE_EXTENSION_INIT1
135
136
/* The layout of fields is :
137
   0   : RegularField0
138
   ...
139
   n-1 : RegularField(n-1)
140
   n   : OGR_STYLE (may be HIDDEN)
141
   n+1 : GEOMETRY
142
*/
143
144
#define COMPILATION_ALLOWED
145
#include "ogrsqlitesqlfunctions.cpp" /* yes the .cpp file, to make it work on Windows with load_extension('gdalXX.dll') */
146
#undef COMPILATION_ALLOWED
147
148
    /************************************************************************/
149
    /*                           OGR2SQLITEModule                           */
150
    /************************************************************************/
151
152
    class OGR2SQLITEModule
153
{
154
#ifdef DEBUG
155
    void *pDummy = nullptr; /* to track memory leaks */
156
#endif
157
    sqlite3 *hDB = nullptr; /* *NOT* to be freed */
158
159
    GDALDataset *poDS = nullptr; /* *NOT* to be freed */
160
    std::vector<std::unique_ptr<GDALDataset>>
161
        apoExtraDS{}; /* each datasource to be freed */
162
163
    OGRSQLiteDataSource *poSQLiteDS =
164
        nullptr; /* *NOT* to be freed, might be NULL */
165
166
    std::map<CPLString, OGRLayer *> oMapVTableToOGRLayer{};
167
168
    void *hHandleSQLFunctions = nullptr;
169
170
    CPL_DISALLOW_COPY_ASSIGN(OGR2SQLITEModule)
171
172
  public:
173
    OGR2SQLITEModule();
174
    ~OGR2SQLITEModule();
175
176
    int Setup(GDALDataset *poDS, OGRSQLiteDataSource *poSQLiteDS);
177
    int Setup(sqlite3 *hDB);
178
179
    GDALDataset *GetDS()
180
0
    {
181
0
        return poDS;
182
0
    }
183
184
    int AddExtraDS(GDALDataset *poDS);
185
    GDALDataset *GetExtraDS(int nIndex);
186
187
    int FetchSRSId(const OGRSpatialReference *poSRS);
188
189
    void RegisterVTable(const char *pszVTableName, OGRLayer *poLayer);
190
    void UnregisterVTable(const char *pszVTableName);
191
    OGRLayer *GetLayerForVTable(const char *pszVTableName);
192
193
    void SetHandleSQLFunctions(void *hHandleSQLFunctionsIn);
194
195
    void SetCaseSensitiveLike(bool b)
196
0
    {
197
0
        OGRSQLiteSQLFunctionsSetCaseSensitiveLike(hHandleSQLFunctions, b);
198
0
    }
199
};
200
201
/************************************************************************/
202
/*                          OGR2SQLITEModule()                          */
203
/************************************************************************/
204
205
OGR2SQLITEModule::OGR2SQLITEModule()
206
#ifdef DEBUG
207
    : pDummy(CPLMalloc(1))
208
#endif
209
8.01k
{
210
8.01k
}
211
212
/************************************************************************/
213
/*                          ~OGR2SQLITEModule                           */
214
/************************************************************************/
215
216
OGR2SQLITEModule::~OGR2SQLITEModule()
217
8.01k
{
218
#ifdef DEBUG
219
    CPLFree(pDummy);
220
#endif
221
222
8.01k
    apoExtraDS.clear();
223
224
8.01k
    OGRSQLiteUnregisterSQLFunctions(hHandleSQLFunctions);
225
8.01k
}
226
227
/************************************************************************/
228
/*                       SetHandleSQLFunctions()                        */
229
/************************************************************************/
230
231
void OGR2SQLITEModule::SetHandleSQLFunctions(void *hHandleSQLFunctionsIn)
232
8.01k
{
233
8.01k
    CPLAssert(hHandleSQLFunctions == nullptr);
234
8.01k
    hHandleSQLFunctions = hHandleSQLFunctionsIn;
235
8.01k
}
236
237
/************************************************************************/
238
/*                             AddExtraDS()                             */
239
/************************************************************************/
240
241
int OGR2SQLITEModule::AddExtraDS(GDALDataset *poDSIn)
242
0
{
243
0
    const int nRet = static_cast<int>(apoExtraDS.size());
244
0
    apoExtraDS.push_back(std::unique_ptr<GDALDataset>(poDSIn));
245
0
    return nRet;
246
0
}
247
248
/************************************************************************/
249
/*                             GetExtraDS()                             */
250
/************************************************************************/
251
252
GDALDataset *OGR2SQLITEModule::GetExtraDS(int nIndex)
253
0
{
254
0
    if (nIndex < 0 || nIndex >= static_cast<int>(apoExtraDS.size()))
255
0
        return nullptr;
256
0
    return apoExtraDS[nIndex].get();
257
0
}
258
259
/************************************************************************/
260
/*                               Setup()                                */
261
/************************************************************************/
262
263
int OGR2SQLITEModule::Setup(GDALDataset *poDSIn,
264
                            OGRSQLiteDataSource *poSQLiteDSIn)
265
739
{
266
739
    CPLAssert(poDS == nullptr);
267
739
    CPLAssert(poSQLiteDS == nullptr);
268
739
    poDS = poDSIn;
269
739
    poSQLiteDS = poSQLiteDSIn;
270
739
    return Setup(poSQLiteDS->GetDB());
271
739
}
272
273
/************************************************************************/
274
/*                             FetchSRSId()                             */
275
/************************************************************************/
276
277
// TODO(schwehr): Refactor FetchSRSId to be much simpler.
278
int OGR2SQLITEModule::FetchSRSId(const OGRSpatialReference *poSRS)
279
0
{
280
0
    int nSRSId = -1;
281
282
0
    if (poSQLiteDS != nullptr)
283
0
    {
284
0
        nSRSId = poSQLiteDS->GetUndefinedSRID();
285
0
        if (poSRS != nullptr)
286
0
            nSRSId = poSQLiteDS->FetchSRSId(poSRS);
287
0
    }
288
0
    else
289
0
    {
290
0
        if (poSRS != nullptr)
291
0
        {
292
0
            const char *pszAuthorityName = poSRS->GetAuthorityName();
293
0
            if (pszAuthorityName != nullptr && EQUAL(pszAuthorityName, "EPSG"))
294
0
            {
295
0
                const char *pszAuthorityCode = poSRS->GetAuthorityCode();
296
0
                if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
297
0
                {
298
0
                    nSRSId = atoi(pszAuthorityCode);
299
0
                }
300
0
            }
301
0
        }
302
0
    }
303
304
0
    return nSRSId;
305
0
}
306
307
/************************************************************************/
308
/*                           RegisterVTable()                           */
309
/************************************************************************/
310
311
void OGR2SQLITEModule::RegisterVTable(const char *pszVTableName,
312
                                      OGRLayer *poLayer)
313
0
{
314
0
    oMapVTableToOGRLayer[pszVTableName] = poLayer;
315
0
}
316
317
/************************************************************************/
318
/*                          UnregisterVTable()                          */
319
/************************************************************************/
320
321
void OGR2SQLITEModule::UnregisterVTable(const char *pszVTableName)
322
0
{
323
0
    oMapVTableToOGRLayer[pszVTableName] = nullptr;
324
0
}
325
326
/************************************************************************/
327
/*                         GetLayerForVTable()                          */
328
/************************************************************************/
329
330
OGRLayer *OGR2SQLITEModule::GetLayerForVTable(const char *pszVTableName)
331
0
{
332
0
    std::map<CPLString, OGRLayer *>::iterator oIter =
333
0
        oMapVTableToOGRLayer.find(pszVTableName);
334
0
    if (oIter == oMapVTableToOGRLayer.end())
335
0
    {
336
0
        if (poDS == poSQLiteDS)
337
0
            return poSQLiteDS->GetLayerByName(pszVTableName);
338
0
        return nullptr;
339
0
    }
340
341
0
    OGRLayer *poLayer = oIter->second;
342
0
    if (poLayer == nullptr)
343
0
    {
344
        /* If the associate layer is null, then try to "ping" the virtual */
345
        /* table since we know that we have managed to create it before */
346
0
        if (sqlite3_exec(hDB,
347
0
                         CPLSPrintf("PRAGMA table_info(\"%s\")",
348
0
                                    SQLEscapeName(pszVTableName).c_str()),
349
0
                         nullptr, nullptr, nullptr) == SQLITE_OK)
350
0
        {
351
0
            poLayer = oMapVTableToOGRLayer[pszVTableName];
352
0
        }
353
0
    }
354
355
0
    return poLayer;
356
0
}
357
358
/* See http://www.sqlite.org/vtab.html for the documentation on how to
359
   implement a new module for the Virtual Table mechanism. */
360
361
/************************************************************************/
362
/*                           OGR2SQLITE_vtab                            */
363
/************************************************************************/
364
365
typedef struct
366
{
367
    /* Mandatory fields by sqlite3: don't change or reorder them ! */
368
    const sqlite3_module *pModule;
369
    int nRef;
370
    char *zErrMsg;
371
372
    /* Extension fields */
373
    char *pszVTableName;
374
    OGR2SQLITEModule *poModule;
375
    GDALDataset *poDS;
376
    int bCloseDS;
377
    OGRLayer *poLayer;
378
    int nMyRef;
379
    bool bHasFIDColumn;
380
} OGR2SQLITE_vtab;
381
382
/************************************************************************/
383
/*                        OGR2SQLITE_vtab_cursor                        */
384
/************************************************************************/
385
386
typedef struct
387
{
388
    /* Mandatory fields by sqlite3: don't change or reorder them ! */
389
    OGR2SQLITE_vtab *pVTab;
390
391
    /* Extension fields */
392
    GDALDataset *poDupDataSource;
393
    OGRLayer *poLayer;
394
    OGRFeature *poFeature;
395
396
    /* nFeatureCount >= 0 if the layer has a feast feature count capability. */
397
    /* In which case nNextWishedIndex and nCurFeatureIndex */
398
    /* will be used to avoid useless GetNextFeature() */
399
    /* Helps in SELECT COUNT(*) FROM xxxx scenarios */
400
    GIntBig nFeatureCount;
401
    GIntBig nNextWishedIndex;
402
    GIntBig nCurFeatureIndex;
403
404
    GByte *pabyGeomBLOB;
405
    int nGeomBLOBLen;
406
} OGR2SQLITE_vtab_cursor;
407
408
#ifdef VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
409
410
/************************************************************************/
411
/*                  OGR2SQLITEDetectSuspiciousUsage()                   */
412
/************************************************************************/
413
414
static int OGR2SQLITEDetectSuspiciousUsage(sqlite3 *hDB,
415
                                           const char *pszVirtualTableName,
416
                                           char **pzErr)
417
0
{
418
0
    char **papszResult = nullptr;
419
0
    int nRowCount = 0;
420
0
    int nColCount = 0;
421
422
    /* Collect database names */
423
0
    sqlite3_get_table(hDB, "PRAGMA database_list", &papszResult, &nRowCount,
424
0
                      &nColCount, nullptr);
425
426
0
    std::vector<CPLString> aosDatabaseNames;
427
0
    for (int i = 1; i <= nRowCount; i++)
428
0
    {
429
0
        const char *pszUnescapedName = papszResult[i * nColCount + 1];
430
0
        aosDatabaseNames.push_back(CPLSPrintf(
431
0
            "\"%s\".sqlite_master", SQLEscapeName(pszUnescapedName).c_str()));
432
0
    }
433
434
    /* Add special database (just in case, not sure it is really needed) */
435
0
    aosDatabaseNames.push_back("sqlite_temp_master");
436
437
0
    sqlite3_free_table(papszResult);
438
0
    papszResult = nullptr;
439
440
    /* Check the triggers of each database */
441
0
    for (const auto &osDBName : aosDatabaseNames)
442
0
    {
443
0
        nRowCount = 0;
444
0
        nColCount = 0;
445
446
0
        const char *pszSQL =
447
0
            CPLSPrintf("SELECT name, sql FROM %s "
448
0
                       "WHERE (type = 'trigger' OR type = 'view') AND ("
449
0
                       "sql LIKE '%%%s%%' OR "
450
0
                       "sql LIKE '%%\"%s\"%%' OR "
451
0
                       "sql LIKE '%%ogr_layer_%%' )",
452
0
                       osDBName.c_str(), pszVirtualTableName,
453
0
                       SQLEscapeName(pszVirtualTableName).c_str());
454
455
0
        sqlite3_get_table(hDB, pszSQL, &papszResult, &nRowCount, &nColCount,
456
0
                          nullptr);
457
458
0
        sqlite3_free_table(papszResult);
459
0
        papszResult = nullptr;
460
461
0
        if (nRowCount > 0)
462
0
        {
463
0
            if (!CPLTestBool(CPLGetConfigOption(
464
0
                    "ALLOW_VIRTUAL_OGR_FROM_TRIGGER_AND_VIEW", "NO")))
465
0
            {
466
0
                *pzErr = sqlite3_mprintf(
467
0
                    "A trigger and/or view might reference VirtualOGR table "
468
0
                    "'%s'.\n"
469
0
                    "This is suspicious practice that could be used to steal "
470
0
                    "data without your consent.\n"
471
0
                    "Disabling access to it unless you define the "
472
0
                    "ALLOW_VIRTUAL_OGR_FROM_TRIGGER_AND_VIEW "
473
0
                    "configuration option to YES.",
474
0
                    pszVirtualTableName);
475
0
                return TRUE;
476
0
            }
477
0
        }
478
0
    }
479
480
0
    return FALSE;
481
0
}
482
483
#endif  // VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
484
485
/************************************************************************/
486
/*                      OGR2SQLITE_ConnectCreate()                      */
487
/************************************************************************/
488
489
static int OGR2SQLITE_DisconnectDestroy(sqlite3_vtab *pVTab);
490
491
static int OGR2SQLITE_ConnectCreate(sqlite3 *hDB, void *pAux, int argc,
492
                                    const char *const *argv,
493
                                    sqlite3_vtab **ppVTab, char **pzErr)
494
0
{
495
#ifdef DEBUG_OGR2SQLITE
496
    CPLDebug("OGR2SQLITE", "ConnectCreate(%s)", argv[2]);
497
#endif
498
499
0
    OGR2SQLITEModule *poModule = static_cast<OGR2SQLITEModule *>(pAux);
500
0
    OGRLayer *poLayer = nullptr;
501
0
    bool bExposeOGR_STYLE = false;
502
0
    bool bCloseDS = false;
503
0
    bool bInternalUse = false;
504
0
    bool bExposeOGRNativeData = false;
505
506
    /* -------------------------------------------------------------------- */
507
    /*      If called from ogrexecutesql.cpp                                */
508
    /* -------------------------------------------------------------------- */
509
0
    GDALDataset *poDS = poModule->GetDS();
510
0
    if (poDS != nullptr && (argc == 6 || argc == 7) &&
511
0
        CPLGetValueType(argv[3]) == CPL_VALUE_INTEGER)
512
0
    {
513
0
        bInternalUse = true;
514
515
0
        int nDSIndex = atoi(argv[3]);
516
0
        if (nDSIndex >= 0)
517
0
        {
518
0
            poDS = poModule->GetExtraDS(nDSIndex);
519
0
            if (poDS == nullptr)
520
0
            {
521
0
                *pzErr =
522
0
                    sqlite3_mprintf("Invalid dataset index : %d", nDSIndex);
523
0
                return SQLITE_ERROR;
524
0
            }
525
0
        }
526
0
        CPLString osLayerName(SQLUnescape(argv[4]));
527
528
0
        poLayer = poDS->GetLayerByName(osLayerName);
529
0
        if (poLayer == nullptr)
530
0
        {
531
0
            *pzErr =
532
0
                sqlite3_mprintf("Cannot find layer '%s' in '%s'",
533
0
                                osLayerName.c_str(), poDS->GetDescription());
534
0
            return SQLITE_ERROR;
535
0
        }
536
537
0
        bExposeOGR_STYLE = atoi(SQLUnescape(argv[5])) != 0;
538
0
        bExposeOGRNativeData =
539
0
            (argc == 7) ? atoi(SQLUnescape(argv[6])) != 0 : false;
540
0
    }
541
0
#ifdef VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
542
    /* -------------------------------------------------------------------- */
543
    /*      If called from outside (OGR loaded as a sqlite3 extension)      */
544
    /* -------------------------------------------------------------------- */
545
0
    else
546
0
    {
547
0
        if (argc < 4 || argc > 8)
548
0
        {
549
0
            *pzErr = sqlite3_mprintf(
550
0
                "Expected syntax: CREATE VIRTUAL TABLE xxx USING "
551
0
                "VirtualOGR(datasource_name[, update_mode, [layer_name[, "
552
0
                "expose_ogr_style[, expose_ogr_native_data]]]])");
553
0
            return SQLITE_ERROR;
554
0
        }
555
556
0
        if (OGR2SQLITEDetectSuspiciousUsage(hDB, argv[2], pzErr))
557
0
        {
558
0
            return SQLITE_ERROR;
559
0
        }
560
561
0
        CPLString osDSName(SQLUnescape(argv[3]));
562
0
        CPLString osUpdate(SQLUnescape((argc >= 5) ? argv[4] : "0"));
563
564
0
        if (!EQUAL(osUpdate, "1") && !EQUAL(osUpdate, "0"))
565
0
        {
566
0
            *pzErr = sqlite3_mprintf("update_mode parameter should be 0 or 1");
567
0
            return SQLITE_ERROR;
568
0
        }
569
570
0
        const bool bUpdate = atoi(osUpdate) != 0;
571
572
0
        poDS = GDALDataset::Open(
573
0
            osDSName.c_str(),
574
0
            GDAL_OF_VECTOR | (bUpdate ? GDAL_OF_UPDATE : GDAL_OF_READONLY),
575
0
            nullptr, nullptr, nullptr);
576
0
        if (poDS == nullptr)
577
0
        {
578
0
            *pzErr = sqlite3_mprintf("Cannot open datasource '%s'",
579
0
                                     osDSName.c_str());
580
0
            return SQLITE_ERROR;
581
0
        }
582
583
0
        CPLString osLayerName;
584
0
        if (argc >= 6)
585
0
        {
586
0
            osLayerName = SQLUnescape(argv[5]);
587
0
            poLayer = poDS->GetLayerByName(osLayerName);
588
0
        }
589
0
        else
590
0
        {
591
0
            if (poDS->GetLayerCount() == 0)
592
0
            {
593
0
                *pzErr = sqlite3_mprintf("Datasource '%s' has no layers",
594
0
                                         osDSName.c_str());
595
0
                poDS->Release();
596
0
                return SQLITE_ERROR;
597
0
            }
598
599
0
            if (poDS->GetLayerCount() > 1)
600
0
            {
601
0
                *pzErr =
602
0
                    sqlite3_mprintf("Datasource '%s' has more than one layers, "
603
0
                                    "and none was explicitly selected.",
604
0
                                    osDSName.c_str());
605
0
                poDS->Release();
606
0
                return SQLITE_ERROR;
607
0
            }
608
609
0
            poLayer = poDS->GetLayer(0);
610
0
        }
611
612
0
        if (poLayer == nullptr)
613
0
        {
614
0
            *pzErr = sqlite3_mprintf("Cannot find layer '%s' in '%s'",
615
0
                                     osLayerName.c_str(), osDSName.c_str());
616
0
            poDS->Release();
617
0
            return SQLITE_ERROR;
618
0
        }
619
620
0
        if (argc >= 7)
621
0
        {
622
0
            bExposeOGR_STYLE = atoi(SQLUnescape(argv[6])) != 0;
623
0
        }
624
0
        if (argc >= 8)
625
0
        {
626
0
            bExposeOGRNativeData = atoi(SQLUnescape(argv[7])) != 0;
627
0
        }
628
629
0
        bCloseDS = true;
630
0
    }
631
0
#endif  // VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
632
0
    OGR2SQLITE_vtab *vtab =
633
0
        static_cast<OGR2SQLITE_vtab *>(CPLCalloc(1, sizeof(OGR2SQLITE_vtab)));
634
    /* We do not need to fill the non-extended fields */
635
0
    vtab->pszVTableName = CPLStrdup(SQLEscapeName(argv[2]));
636
0
    vtab->poModule = poModule;
637
0
    vtab->poDS = poDS;
638
0
    vtab->bCloseDS = bCloseDS;
639
0
    vtab->poLayer = poLayer;
640
0
    vtab->nMyRef = 0;
641
642
0
    poModule->RegisterVTable(vtab->pszVTableName, poLayer);
643
644
0
    *ppVTab = reinterpret_cast<sqlite3_vtab *>(vtab);
645
646
0
    CPLString osSQL;
647
0
    osSQL = "CREATE TABLE ";
648
0
    osSQL += "\"";
649
0
    osSQL += SQLEscapeName(argv[2]);
650
0
    osSQL += "\"";
651
0
    osSQL += "(";
652
653
0
    bool bAddComma = false;
654
655
0
    const OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
656
657
0
    const char *pszFIDColumn = poLayer->GetFIDColumn();
658
0
    std::set<std::string> oSetNamesUC;
659
0
    if (pszFIDColumn[0])
660
0
    {
661
0
        osSQL += "\"";
662
0
        osSQL += SQLEscapeName(pszFIDColumn);
663
0
        oSetNamesUC.insert(CPLString(pszFIDColumn).toupper());
664
0
        if (poFDefn->GetFieldIndex(pszFIDColumn) >= 0)
665
0
            osSQL += "\" INTEGER PRIMARY KEY NOT NULL";
666
0
        else
667
0
            osSQL += "\" INTEGER HIDDEN PRIMARY KEY NOT NULL";
668
0
        bAddComma = true;
669
0
        vtab->bHasFIDColumn = true;
670
0
    }
671
672
0
    bool bHasOGR_STYLEField = false;
673
0
    for (int i = 0; i < poFDefn->GetFieldCount(); i++)
674
0
    {
675
0
        const OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(i);
676
677
0
        if (bAddComma)
678
0
            osSQL += ",";
679
0
        bAddComma = true;
680
681
0
        if (EQUAL(poFieldDefn->GetNameRef(), "OGR_STYLE"))
682
0
            bHasOGR_STYLEField = true;
683
684
0
        CPLString osFieldName(poFieldDefn->GetNameRef());
685
0
        int nCounter = 2;
686
0
        while (oSetNamesUC.find(CPLString(osFieldName).toupper()) !=
687
0
               oSetNamesUC.end())
688
0
        {
689
0
            do
690
0
            {
691
0
                osFieldName.Printf("%s%d", poFieldDefn->GetNameRef(), nCounter);
692
0
                nCounter++;
693
0
            } while (poFDefn->GetFieldIndex(osFieldName) >= 0);
694
0
        }
695
0
        oSetNamesUC.insert(CPLString(osFieldName).toupper());
696
697
0
        osSQL += "\"";
698
0
        osSQL += SQLEscapeName(osFieldName);
699
0
        osSQL += "\"";
700
0
        osSQL += " ";
701
702
0
        std::string osType(OGRSQLiteFieldDefnToSQliteFieldDefn(
703
0
            poFieldDefn, bInternalUse, false));
704
0
        if (bInternalUse)
705
0
        {
706
0
            const auto &osDomainName = poFieldDefn->GetDomainName();
707
0
            if (!osDomainName.empty())
708
0
            {
709
                // Avoids illegal VARCHAR(n)_BEGIN_DOMAIN_NAME_... to be
710
                // emitted
711
0
                if (poFieldDefn->GetType() == OFTString)
712
0
                    osType = "VARCHAR";
713
0
                osType += "_BEGIN_DOMAIN_NAME_";
714
0
                char *pszEncoded = CPLBinaryToHex(
715
0
                    static_cast<int>(osDomainName.size()),
716
0
                    reinterpret_cast<const GByte *>(osDomainName.data()));
717
0
                osType += pszEncoded;
718
0
                CPLFree(pszEncoded);
719
0
                osType += "_END_DOMAIN_NAME";
720
0
            }
721
0
        }
722
0
        osSQL += osType;
723
724
0
        if (EQUAL(poFieldDefn->GetNameRef(), pszFIDColumn))
725
0
            osSQL += " HIDDEN";
726
0
    }
727
728
0
    if (bAddComma)
729
0
        osSQL += ",";
730
731
0
    if (bHasOGR_STYLEField)
732
0
    {
733
0
        osSQL += "'dummy' VARCHAR HIDDEN";
734
0
    }
735
0
    else
736
0
    {
737
0
        osSQL += "OGR_STYLE VARCHAR";
738
0
        if (!bExposeOGR_STYLE)
739
0
            osSQL += " HIDDEN";
740
0
    }
741
742
0
    for (int i = 0; i < poFDefn->GetGeomFieldCount(); i++)
743
0
    {
744
0
        osSQL += ",";
745
746
0
        const OGRGeomFieldDefn *poFieldDefn = poFDefn->GetGeomFieldDefn(i);
747
748
0
        osSQL += "\"";
749
0
        if (i == 0)
750
0
            osSQL +=
751
0
                SQLEscapeName(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
752
0
        else
753
0
            osSQL += SQLEscapeName(poFieldDefn->GetNameRef());
754
0
        osSQL += "\"";
755
0
        osSQL += " BLOB";
756
757
        /* We use a special column type, e.g. BLOB_POINT_25D_4326 */
758
        /* when the virtual table is created by OGRSQLiteExecuteSQL() */
759
        /* and thus for internal use only. */
760
0
        if (bInternalUse)
761
0
        {
762
0
            osSQL += "_";
763
0
            osSQL += OGRToOGCGeomType(poFieldDefn->GetType());
764
0
            osSQL += "_XY";
765
0
            if (wkbHasZ(poFieldDefn->GetType()))
766
0
                osSQL += "Z";
767
0
            if (wkbHasM(poFieldDefn->GetType()))
768
0
                osSQL += "M";
769
0
            const OGRSpatialReference *poSRS = poFieldDefn->GetSpatialRef();
770
0
            if (poSRS == nullptr && i == 0)
771
0
                poSRS = poLayer->GetSpatialRef();
772
0
            int nSRID = poModule->FetchSRSId(poSRS);
773
0
            if (nSRID >= 0)
774
0
            {
775
0
                osSQL += "_";
776
0
                osSQL += CPLSPrintf("%d", nSRID);
777
0
            }
778
0
        }
779
0
    }
780
781
0
    osSQL += ", OGR_NATIVE_DATA VARCHAR";
782
0
    if (!bExposeOGRNativeData)
783
0
        osSQL += " HIDDEN";
784
0
    osSQL += ", OGR_NATIVE_MEDIA_TYPE VARCHAR";
785
0
    if (!bExposeOGRNativeData)
786
0
        osSQL += " HIDDEN";
787
788
0
    osSQL += ")";
789
790
0
    CPLDebug("OGR2SQLITE", "sqlite3_declare_vtab(%s)", osSQL.c_str());
791
0
    if (sqlite3_declare_vtab(hDB, osSQL.c_str()) != SQLITE_OK)
792
0
    {
793
0
        *pzErr = sqlite3_mprintf("CREATE VIRTUAL: invalid SQL statement : %s",
794
0
                                 osSQL.c_str());
795
0
        OGR2SQLITE_DisconnectDestroy(reinterpret_cast<sqlite3_vtab *>(vtab));
796
0
        return SQLITE_ERROR;
797
0
    }
798
799
0
    return SQLITE_OK;
800
0
}
801
802
/************************************************************************/
803
/*                       OGR2SQLITE_IsHandledOp()                       */
804
/************************************************************************/
805
806
static bool OGR2SQLITE_IsHandledOp(int op)
807
0
{
808
0
    switch (op)
809
0
    {
810
0
        case SQLITE_INDEX_CONSTRAINT_EQ:
811
0
            return true;
812
0
        case SQLITE_INDEX_CONSTRAINT_GT:
813
0
            return true;
814
0
        case SQLITE_INDEX_CONSTRAINT_LE:
815
0
            return true;
816
0
        case SQLITE_INDEX_CONSTRAINT_LT:
817
0
            return true;
818
0
        case SQLITE_INDEX_CONSTRAINT_GE:
819
0
            return true;
820
0
        case SQLITE_INDEX_CONSTRAINT_MATCH:
821
0
            return false;  // unhandled
822
0
#ifdef SQLITE_INDEX_CONSTRAINT_LIKE
823
        /* SQLite >= 3.10 */
824
0
        case SQLITE_INDEX_CONSTRAINT_LIKE:
825
0
            return true;
826
0
        case SQLITE_INDEX_CONSTRAINT_GLOB:
827
0
            return false;  // unhandled
828
0
        case SQLITE_INDEX_CONSTRAINT_REGEXP:
829
0
            return false;  // unhandled
830
0
#endif
831
0
#ifdef SQLITE_INDEX_CONSTRAINT_NE
832
            /* SQLite >= 3.21 */
833
0
        case SQLITE_INDEX_CONSTRAINT_NE:
834
0
            return true;
835
0
        case SQLITE_INDEX_CONSTRAINT_ISNOT:
836
0
            return false;  // OGR SQL only handles IS [NOT] NULL
837
0
        case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
838
0
            return true;
839
0
        case SQLITE_INDEX_CONSTRAINT_ISNULL:
840
0
            return true;
841
0
            ;
842
0
        case SQLITE_INDEX_CONSTRAINT_IS:
843
0
            return false;  // OGR SQL only handles IS [NOT] NULL
844
0
#endif
845
0
        default:
846
0
            break;
847
0
    }
848
0
    return false;
849
0
}
850
851
/************************************************************************/
852
/*                        OGR2SQLITE_BestIndex()                        */
853
/************************************************************************/
854
855
static int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pIndex)
856
0
{
857
0
    OGR2SQLITE_vtab *pMyVTab = reinterpret_cast<OGR2SQLITE_vtab *>(pVTab);
858
0
    OGRFeatureDefn *poFDefn = pMyVTab->poLayer->GetLayerDefn();
859
860
#ifdef DEBUG_OGR2SQLITE
861
    CPLString osQueryPatternUsable, osQueryPatternNotUsable;
862
    for (int i = 0; i < pIndex->nConstraint; i++)
863
    {
864
        int iCol = pIndex->aConstraint[i].iColumn;
865
        const char *pszFieldName = NULL;
866
867
        if (pMyVTab->bHasFIDColumn && iCol >= 0)
868
            --iCol;
869
870
        if (iCol == -1)
871
            pszFieldName = "FID";
872
        else if (iCol >= 0 && iCol < poFDefn->GetFieldCount())
873
            pszFieldName = poFDefn->GetFieldDefn(iCol)->GetNameRef();
874
        else
875
            pszFieldName = "unknown_field";
876
877
        const char *pszOp = NULL;
878
        switch (pIndex->aConstraint[i].op)
879
        {
880
            case SQLITE_INDEX_CONSTRAINT_EQ:
881
                pszOp = " = ";
882
                break;
883
            case SQLITE_INDEX_CONSTRAINT_GT:
884
                pszOp = " > ";
885
                break;
886
            case SQLITE_INDEX_CONSTRAINT_LE:
887
                pszOp = " <= ";
888
                break;
889
            case SQLITE_INDEX_CONSTRAINT_LT:
890
                pszOp = " < ";
891
                break;
892
            case SQLITE_INDEX_CONSTRAINT_GE:
893
                pszOp = " >= ";
894
                break;
895
            case SQLITE_INDEX_CONSTRAINT_MATCH:
896
                pszOp = " MATCH ";
897
                break;
898
#ifdef SQLITE_INDEX_CONSTRAINT_LIKE
899
            /* SQLite >= 3.10 */
900
            case SQLITE_INDEX_CONSTRAINT_LIKE:
901
                pszOp = " LIKE ";
902
                break;
903
            case SQLITE_INDEX_CONSTRAINT_GLOB:
904
                pszOp = " GLOB ";
905
                break;
906
            case SQLITE_INDEX_CONSTRAINT_REGEXP:
907
                pszOp = " REGEXP ";
908
                break;
909
#endif
910
#ifdef SQLITE_INDEX_CONSTRAINT_NE
911
            /* SQLite >= 3.21 */
912
            case SQLITE_INDEX_CONSTRAINT_NE:
913
                pszOp = " <> ";
914
                break;
915
            case SQLITE_INDEX_CONSTRAINT_ISNOT:
916
                pszOp = " IS NOT ";
917
                break;
918
            case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
919
                pszOp = " IS NOT NULL";
920
                break;
921
            case SQLITE_INDEX_CONSTRAINT_ISNULL:
922
                pszOp = " IS NULL";
923
                break;
924
            case SQLITE_INDEX_CONSTRAINT_IS:
925
                pszOp = " IS ";
926
                break;
927
#endif
928
            default:
929
                pszOp = " (unknown op) ";
930
                break;
931
        }
932
933
        if (pIndex->aConstraint[i].usable)
934
        {
935
            if (!osQueryPatternUsable.empty())
936
                osQueryPatternUsable += " AND ";
937
            osQueryPatternUsable += pszFieldName;
938
            osQueryPatternUsable += pszOp;
939
            osQueryPatternUsable += "?";
940
        }
941
        else
942
        {
943
            if (!osQueryPatternNotUsable.empty())
944
                osQueryPatternNotUsable += " AND ";
945
            osQueryPatternNotUsable += pszFieldName;
946
            osQueryPatternNotUsable += pszOp;
947
            osQueryPatternNotUsable += "?";
948
        }
949
    }
950
    CPLDebug("OGR2SQLITE", "BestIndex, usable ( %s ), not usable ( %s )",
951
             osQueryPatternUsable.c_str(), osQueryPatternNotUsable.c_str());
952
#endif
953
954
0
    int nConstraints = 0;
955
0
    for (int i = 0; i < pIndex->nConstraint; i++)
956
0
    {
957
0
        int iCol = pIndex->aConstraint[i].iColumn;
958
959
0
        if (pMyVTab->bHasFIDColumn && iCol >= 0)
960
0
            --iCol;
961
962
0
        if (pIndex->aConstraint[i].usable &&
963
0
            OGR2SQLITE_IsHandledOp(pIndex->aConstraint[i].op) &&
964
0
            iCol < poFDefn->GetFieldCount() &&
965
0
            (iCol < 0 || poFDefn->GetFieldDefn(iCol)->GetType() != OFTBinary))
966
0
        {
967
0
            pIndex->aConstraintUsage[i].argvIndex = nConstraints + 1;
968
0
            pIndex->aConstraintUsage[i].omit = true;
969
970
0
            nConstraints++;
971
0
        }
972
0
        else
973
0
        {
974
0
            pIndex->aConstraintUsage[i].argvIndex = 0;
975
0
            pIndex->aConstraintUsage[i].omit = false;
976
0
        }
977
0
    }
978
979
0
    int *panConstraints = nullptr;
980
981
0
    if (nConstraints)
982
0
    {
983
0
        panConstraints = static_cast<int *>(sqlite3_malloc(
984
0
            static_cast<int>(sizeof(int)) * (1 + 2 * nConstraints)));
985
0
        panConstraints[0] = nConstraints;
986
987
0
        nConstraints = 0;
988
989
0
        for (int i = 0; i < pIndex->nConstraint; i++)
990
0
        {
991
0
            if (pIndex->aConstraintUsage[i].omit)
992
0
            {
993
0
                panConstraints[2 * nConstraints + 1] =
994
0
                    pIndex->aConstraint[i].iColumn;
995
0
                panConstraints[2 * nConstraints + 2] =
996
0
                    pIndex->aConstraint[i].op;
997
998
0
                nConstraints++;
999
0
            }
1000
0
        }
1001
0
    }
1002
1003
0
    pIndex->orderByConsumed = false;
1004
0
    pIndex->idxNum = 0;
1005
1006
0
    if (nConstraints != 0)
1007
0
    {
1008
0
        pIndex->idxStr = reinterpret_cast<char *>(panConstraints);
1009
0
        pIndex->needToFreeIdxStr = true;
1010
0
    }
1011
0
    else
1012
0
    {
1013
0
        pIndex->idxStr = nullptr;
1014
0
        pIndex->needToFreeIdxStr = false;
1015
0
    }
1016
1017
0
    return SQLITE_OK;
1018
0
}
1019
1020
/************************************************************************/
1021
/*                    OGR2SQLITE_DisconnectDestroy()                    */
1022
/************************************************************************/
1023
1024
static int OGR2SQLITE_DisconnectDestroy(sqlite3_vtab *pVTab)
1025
0
{
1026
0
    OGR2SQLITE_vtab *pMyVTab = reinterpret_cast<OGR2SQLITE_vtab *>(pVTab);
1027
1028
#ifdef DEBUG_OGR2SQLITE
1029
    CPLDebug("OGR2SQLITE", "DisconnectDestroy(%s)", pMyVTab->pszVTableName);
1030
#endif
1031
1032
0
    sqlite3_free(pMyVTab->zErrMsg);
1033
0
    if (pMyVTab->bCloseDS)
1034
0
        pMyVTab->poDS->Release();
1035
0
    pMyVTab->poModule->UnregisterVTable(pMyVTab->pszVTableName);
1036
0
    CPLFree(pMyVTab->pszVTableName);
1037
0
    CPLFree(pMyVTab);
1038
1039
0
    return SQLITE_OK;
1040
0
}
1041
1042
/************************************************************************/
1043
/*                          OGR2SQLITE_Open()                           */
1044
/************************************************************************/
1045
1046
static int OGR2SQLITE_Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
1047
0
{
1048
0
    OGR2SQLITE_vtab *pMyVTab = reinterpret_cast<OGR2SQLITE_vtab *>(pVTab);
1049
#ifdef DEBUG_OGR2SQLITE
1050
    CPLDebug("OGR2SQLITE", "Open(%s, %s)", pMyVTab->poDS->GetDescription(),
1051
             pMyVTab->poLayer->GetDescription());
1052
#endif
1053
1054
0
    GDALDataset *poDupDataSource = nullptr;
1055
0
    OGRLayer *poLayer = nullptr;
1056
1057
0
    if (pMyVTab->nMyRef == 0)
1058
0
    {
1059
0
        poLayer = pMyVTab->poLayer;
1060
0
    }
1061
0
    else
1062
0
    {
1063
0
        poDupDataSource = GDALDataset::FromHandle(
1064
0
            OGROpen(pMyVTab->poDS->GetDescription(), FALSE, nullptr));
1065
0
        if (poDupDataSource == nullptr)
1066
0
            return SQLITE_ERROR;
1067
0
        poLayer = poDupDataSource->GetLayerByName(pMyVTab->poLayer->GetName());
1068
0
        if (poLayer == nullptr)
1069
0
        {
1070
0
            delete poDupDataSource;
1071
0
            return SQLITE_ERROR;
1072
0
        }
1073
0
        if (!poLayer->GetLayerDefn()->IsSame(pMyVTab->poLayer->GetLayerDefn()))
1074
0
        {
1075
0
            delete poDupDataSource;
1076
0
            return SQLITE_ERROR;
1077
0
        }
1078
0
    }
1079
0
    pMyVTab->nMyRef++;
1080
1081
0
    OGR2SQLITE_vtab_cursor *pCursor = static_cast<OGR2SQLITE_vtab_cursor *>(
1082
0
        CPLCalloc(1, sizeof(OGR2SQLITE_vtab_cursor)));
1083
    // We do not need to fill the non-extended fields.
1084
0
    *ppCursor = reinterpret_cast<sqlite3_vtab_cursor *>(pCursor);
1085
1086
0
    pCursor->poDupDataSource = poDupDataSource;
1087
0
    pCursor->poLayer = poLayer;
1088
0
    pCursor->poLayer->ResetReading();
1089
0
    pCursor->poFeature = nullptr;
1090
0
    pCursor->nNextWishedIndex = 0;
1091
0
    pCursor->nCurFeatureIndex = -1;
1092
0
    pCursor->nFeatureCount = -1;
1093
1094
0
    pCursor->pabyGeomBLOB = nullptr;
1095
0
    pCursor->nGeomBLOBLen = -1;
1096
1097
0
    return SQLITE_OK;
1098
0
}
1099
1100
/************************************************************************/
1101
/*                          OGR2SQLITE_Close()                          */
1102
/************************************************************************/
1103
1104
static int OGR2SQLITE_Close(sqlite3_vtab_cursor *pCursor)
1105
0
{
1106
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1107
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1108
0
    OGR2SQLITE_vtab *pMyVTab = pMyCursor->pVTab;
1109
#ifdef DEBUG_OGR2SQLITE
1110
    CPLDebug("OGR2SQLITE", "Close(%s, %s)", pMyVTab->poDS->GetDescription(),
1111
             pMyVTab->poLayer->GetDescription());
1112
#endif
1113
0
    pMyVTab->nMyRef--;
1114
1115
0
    delete pMyCursor->poFeature;
1116
0
    delete pMyCursor->poDupDataSource;
1117
1118
0
    CPLFree(pMyCursor->pabyGeomBLOB);
1119
1120
0
    CPLFree(pCursor);
1121
1122
0
    return SQLITE_OK;
1123
0
}
1124
1125
/************************************************************************/
1126
/*                         OGR2SQLITE_Filter()                          */
1127
/************************************************************************/
1128
1129
static int OGR2SQLITE_Filter(sqlite3_vtab_cursor *pCursor,
1130
                             CPL_UNUSED int idxNum, const char *idxStr,
1131
                             int argc, sqlite3_value **argv)
1132
0
{
1133
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1134
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1135
#ifdef DEBUG_OGR2SQLITE
1136
    CPLDebug("OGR2SQLITE", "Filter");
1137
#endif
1138
1139
0
    const int *panConstraints = reinterpret_cast<const int *>(idxStr);
1140
0
    int nConstraints = panConstraints ? panConstraints[0] : 0;
1141
1142
0
    if (nConstraints != argc)
1143
0
        return SQLITE_ERROR;
1144
1145
0
    CPLString osAttributeFilter;
1146
1147
0
    OGRFeatureDefn *poFDefn = pMyCursor->poLayer->GetLayerDefn();
1148
1149
0
    for (int i = 0; i < argc; i++)
1150
0
    {
1151
0
        int nCol = panConstraints[2 * i + 1];
1152
0
        OGRFieldDefn *poFieldDefn = nullptr;
1153
1154
0
        if (pMyCursor->pVTab->bHasFIDColumn && nCol >= 0)
1155
0
        {
1156
0
            --nCol;
1157
0
        }
1158
1159
0
        if (nCol >= 0)
1160
0
        {
1161
0
            poFieldDefn = poFDefn->GetFieldDefn(nCol);
1162
0
            if (poFieldDefn == nullptr)
1163
0
                return SQLITE_ERROR;
1164
0
        }
1165
1166
0
        if (i != 0)
1167
0
            osAttributeFilter += " AND ";
1168
1169
0
        if (poFieldDefn != nullptr)
1170
0
        {
1171
0
            const char *pszFieldName = poFieldDefn->GetNameRef();
1172
0
            char ch = '\0';
1173
0
            bool bNeedsQuoting = swq_is_reserved_keyword(pszFieldName) != 0;
1174
0
            for (int j = 0; !bNeedsQuoting && (ch = pszFieldName[j]) != '\0';
1175
0
                 j++)
1176
0
            {
1177
0
                if (!(isalnum(static_cast<unsigned char>(ch)) || ch == '_'))
1178
0
                    bNeedsQuoting = true;
1179
0
            }
1180
1181
0
            if (bNeedsQuoting)
1182
0
            {
1183
0
                osAttributeFilter += '"';
1184
0
                osAttributeFilter += SQLEscapeName(pszFieldName);
1185
0
                osAttributeFilter += '"';
1186
0
            }
1187
0
            else
1188
0
            {
1189
0
                osAttributeFilter += pszFieldName;
1190
0
            }
1191
0
        }
1192
0
        else
1193
0
        {
1194
0
            const char *pszSrcFIDColumn = pMyCursor->poLayer->GetFIDColumn();
1195
0
            if (pszSrcFIDColumn && *pszSrcFIDColumn != '\0')
1196
0
            {
1197
0
                osAttributeFilter += '"';
1198
0
                osAttributeFilter += SQLEscapeName(pszSrcFIDColumn);
1199
0
                osAttributeFilter += '"';
1200
0
            }
1201
0
            else
1202
0
            {
1203
0
                osAttributeFilter += "FID";
1204
0
            }
1205
0
        }
1206
1207
0
        bool bExpectRightOperator = true;
1208
0
        std::string osOp;
1209
0
        const auto eSQLiteConstraintOp = panConstraints[2 * i + 2];
1210
0
        switch (eSQLiteConstraintOp)
1211
0
        {
1212
0
            case SQLITE_INDEX_CONSTRAINT_EQ:
1213
0
                osOp = " = ";
1214
0
                break;
1215
0
            case SQLITE_INDEX_CONSTRAINT_GT:
1216
0
                osAttributeFilter += " > ";
1217
0
                break;
1218
0
            case SQLITE_INDEX_CONSTRAINT_LE:
1219
0
                osAttributeFilter += " <= ";
1220
0
                break;
1221
0
            case SQLITE_INDEX_CONSTRAINT_LT:
1222
0
                osAttributeFilter += " < ";
1223
0
                break;
1224
0
            case SQLITE_INDEX_CONSTRAINT_GE:
1225
0
                osAttributeFilter += " >= ";
1226
0
                break;
1227
                // unhandled: SQLITE_INDEX_CONSTRAINT_MATCH
1228
0
#ifdef SQLITE_INDEX_CONSTRAINT_LIKE
1229
            /* SQLite >= 3.10 */
1230
0
            case SQLITE_INDEX_CONSTRAINT_LIKE:
1231
0
                osAttributeFilter += " LIKE ";
1232
0
                break;
1233
                // unhandled: SQLITE_INDEX_CONSTRAINT_GLOB
1234
                // unhandled: SQLITE_INDEX_CONSTRAINT_REGEXP
1235
0
#endif
1236
0
#ifdef SQLITE_INDEX_CONSTRAINT_NE
1237
            /* SQLite >= 3.21 */
1238
0
            case SQLITE_INDEX_CONSTRAINT_NE:
1239
0
                osAttributeFilter += " <> ";
1240
0
                break;
1241
            // case SQLITE_INDEX_CONSTRAINT_ISNOT: osAttributeFilter += " IS NOT
1242
            // "; break;
1243
0
            case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
1244
0
                osAttributeFilter += " IS NOT NULL";
1245
0
                bExpectRightOperator = false;
1246
0
                break;
1247
0
            case SQLITE_INDEX_CONSTRAINT_ISNULL:
1248
0
                osAttributeFilter += " IS NULL";
1249
0
                bExpectRightOperator = false;
1250
0
                break;
1251
                // case SQLITE_INDEX_CONSTRAINT_IS: osAttributeFilter += " IS ";
1252
                // break;
1253
0
#endif
1254
0
            default:
1255
0
            {
1256
0
                sqlite3_free(pMyCursor->pVTab->zErrMsg);
1257
0
                pMyCursor->pVTab->zErrMsg =
1258
0
                    sqlite3_mprintf("Unhandled constraint operator : %d",
1259
0
                                    panConstraints[2 * i + 2]);
1260
0
                return SQLITE_ERROR;
1261
0
            }
1262
0
        }
1263
1264
0
        if (bExpectRightOperator)
1265
0
        {
1266
0
            const auto eSQLiteType = sqlite3_value_type(argv[i]);
1267
0
            if (eSQLiteType == SQLITE_INTEGER)
1268
0
            {
1269
0
                osAttributeFilter += osOp;
1270
0
                osAttributeFilter +=
1271
0
                    CPLSPrintf(CPL_FRMT_GIB, sqlite3_value_int64(argv[i]));
1272
0
            }
1273
0
            else if (eSQLiteType == SQLITE_FLOAT)
1274
0
            {  // Insure that only Decimal.Points are used, never local settings
1275
                // such as Decimal.Comma.
1276
0
                osAttributeFilter += osOp;
1277
0
                osAttributeFilter +=
1278
0
                    CPLSPrintf("%.17g", sqlite3_value_double(argv[i]));
1279
0
            }
1280
0
            else if (eSQLiteType == SQLITE_TEXT)
1281
0
            {
1282
0
                osAttributeFilter += osOp;
1283
0
                osAttributeFilter += "'";
1284
0
                osAttributeFilter +=
1285
0
                    SQLEscapeLiteral(reinterpret_cast<const char *>(
1286
0
                        sqlite3_value_text(argv[i])));
1287
0
                osAttributeFilter += "'";
1288
0
            }
1289
0
            else if (eSQLiteConstraintOp == SQLITE_INDEX_CONSTRAINT_EQ &&
1290
0
                     eSQLiteType == SQLITE_NULL)
1291
0
            {
1292
0
                osAttributeFilter += " IN (NULL)";
1293
0
            }
1294
0
            else
1295
0
            {
1296
0
                sqlite3_free(pMyCursor->pVTab->zErrMsg);
1297
0
                pMyCursor->pVTab->zErrMsg = sqlite3_mprintf(
1298
0
                    "Unhandled constraint data type : %d", eSQLiteType);
1299
0
                return SQLITE_ERROR;
1300
0
            }
1301
0
        }
1302
0
    }
1303
1304
#ifdef DEBUG_OGR2SQLITE
1305
    CPLDebug("OGR2SQLITE", "Attribute filter : %s", osAttributeFilter.c_str());
1306
#endif
1307
1308
0
    if (pMyCursor->poLayer->SetAttributeFilter(!osAttributeFilter.empty()
1309
0
                                                   ? osAttributeFilter.c_str()
1310
0
                                                   : nullptr) != OGRERR_NONE)
1311
0
    {
1312
0
        sqlite3_free(pMyCursor->pVTab->zErrMsg);
1313
0
        pMyCursor->pVTab->zErrMsg = sqlite3_mprintf(
1314
0
            "Cannot apply attribute filter : %s", osAttributeFilter.c_str());
1315
0
        return SQLITE_ERROR;
1316
0
    }
1317
1318
0
    if (pMyCursor->poLayer->TestCapability(OLCFastFeatureCount))
1319
0
        pMyCursor->nFeatureCount = pMyCursor->poLayer->GetFeatureCount();
1320
0
    else
1321
0
        pMyCursor->nFeatureCount = -1;
1322
0
    pMyCursor->poLayer->ResetReading();
1323
1324
0
    if (pMyCursor->nFeatureCount < 0)
1325
0
    {
1326
0
        pMyCursor->poFeature = pMyCursor->poLayer->GetNextFeature();
1327
#ifdef DEBUG_OGR2SQLITE
1328
        CPLDebug("OGR2SQLITE", "GetNextFeature() --> " CPL_FRMT_GIB,
1329
                 pMyCursor->poFeature ? pMyCursor->poFeature->GetFID() : -1);
1330
#endif
1331
0
    }
1332
1333
0
    pMyCursor->nNextWishedIndex = 0;
1334
0
    pMyCursor->nCurFeatureIndex = -1;
1335
1336
0
    return SQLITE_OK;
1337
0
}
1338
1339
/************************************************************************/
1340
/*                          OGR2SQLITE_Next()                           */
1341
/************************************************************************/
1342
1343
static int OGR2SQLITE_Next(sqlite3_vtab_cursor *pCursor)
1344
0
{
1345
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1346
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1347
#ifdef DEBUG_OGR2SQLITE
1348
    CPLDebug("OGR2SQLITE", "Next");
1349
#endif
1350
1351
0
    pMyCursor->nNextWishedIndex++;
1352
0
    if (pMyCursor->nFeatureCount < 0)
1353
0
    {
1354
0
        delete pMyCursor->poFeature;
1355
0
        pMyCursor->poFeature = pMyCursor->poLayer->GetNextFeature();
1356
1357
0
        CPLFree(pMyCursor->pabyGeomBLOB);
1358
0
        pMyCursor->pabyGeomBLOB = nullptr;
1359
0
        pMyCursor->nGeomBLOBLen = -1;
1360
1361
#ifdef DEBUG_OGR2SQLITE
1362
        CPLDebug("OGR2SQLITE", "GetNextFeature() --> " CPL_FRMT_GIB,
1363
                 pMyCursor->poFeature ? pMyCursor->poFeature->GetFID() : -1);
1364
#endif
1365
0
    }
1366
0
    return SQLITE_OK;
1367
0
}
1368
1369
/************************************************************************/
1370
/*                           OGR2SQLITE_Eof()                           */
1371
/************************************************************************/
1372
1373
static int OGR2SQLITE_Eof(sqlite3_vtab_cursor *pCursor)
1374
0
{
1375
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1376
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1377
#ifdef DEBUG_OGR2SQLITE
1378
    CPLDebug("OGR2SQLITE", "Eof");
1379
#endif
1380
1381
0
    if (pMyCursor->nFeatureCount < 0)
1382
0
    {
1383
0
        return pMyCursor->poFeature == nullptr;
1384
0
    }
1385
0
    else
1386
0
    {
1387
0
        return pMyCursor->nNextWishedIndex >= pMyCursor->nFeatureCount;
1388
0
    }
1389
0
}
1390
1391
/************************************************************************/
1392
/*                     OGR2SQLITE_GoToWishedIndex()                     */
1393
/************************************************************************/
1394
1395
static void OGR2SQLITE_GoToWishedIndex(OGR2SQLITE_vtab_cursor *pMyCursor)
1396
0
{
1397
0
    if (pMyCursor->nFeatureCount >= 0)
1398
0
    {
1399
0
        if (pMyCursor->nCurFeatureIndex < pMyCursor->nNextWishedIndex)
1400
0
        {
1401
0
            do
1402
0
            {
1403
0
                pMyCursor->nCurFeatureIndex++;
1404
1405
0
                delete pMyCursor->poFeature;
1406
0
                pMyCursor->poFeature = pMyCursor->poLayer->GetNextFeature();
1407
#ifdef DEBUG_OGR2SQLITE
1408
                CPLDebug("OGR2SQLITE", "GetNextFeature() --> " CPL_FRMT_GIB,
1409
                         pMyCursor->poFeature ? pMyCursor->poFeature->GetFID()
1410
                                              : -1);
1411
#endif
1412
0
            } while (pMyCursor->nCurFeatureIndex < pMyCursor->nNextWishedIndex);
1413
1414
0
            CPLFree(pMyCursor->pabyGeomBLOB);
1415
0
            pMyCursor->pabyGeomBLOB = nullptr;
1416
0
            pMyCursor->nGeomBLOBLen = -1;
1417
0
        }
1418
0
    }
1419
0
}
1420
1421
/************************************************************************/
1422
/*                     OGR2SQLITE_ExportGeometry()                      */
1423
/************************************************************************/
1424
1425
static void OGR2SQLITE_ExportGeometry(OGRGeometry *poGeom, int nSRSId,
1426
                                      GByte *&pabyGeomBLOB, int &nGeomBLOBLen)
1427
0
{
1428
0
    if (OGRSQLiteLayer::ExportSpatiaLiteGeometry(poGeom, nSRSId, wkbNDR, FALSE,
1429
0
                                                 FALSE, &pabyGeomBLOB,
1430
0
                                                 &nGeomBLOBLen) != OGRERR_NONE)
1431
0
    {
1432
0
        nGeomBLOBLen = 0;
1433
0
    }
1434
    /* This is a hack: we add the original curve geometry after */
1435
    /* the spatialite blob */
1436
0
    else if (poGeom->hasCurveGeometry())
1437
0
    {
1438
0
        const size_t nWkbSize = poGeom->WkbSize();
1439
0
        if (nWkbSize + 1 >
1440
0
            static_cast<size_t>(std::numeric_limits<int>::max()) - nGeomBLOBLen)
1441
0
        {
1442
0
            CPLError(CE_Failure, CPLE_NotSupported, "Too large geometry");
1443
0
            nGeomBLOBLen = 0;
1444
0
            return;
1445
0
        }
1446
1447
0
        pabyGeomBLOB = static_cast<GByte *>(
1448
0
            CPLRealloc(pabyGeomBLOB, nGeomBLOBLen + nWkbSize + 1));
1449
0
        poGeom->exportToWkb(wkbNDR, pabyGeomBLOB + nGeomBLOBLen, wkbVariantIso);
1450
        /* Cheat a bit and add a end-of-blob spatialite marker */
1451
0
        pabyGeomBLOB[nGeomBLOBLen + nWkbSize] = 0xFE;
1452
0
        nGeomBLOBLen += static_cast<int>(nWkbSize) + 1;
1453
0
    }
1454
0
}
1455
1456
/************************************************************************/
1457
/*                         OGR2SQLITE_Column()                          */
1458
/************************************************************************/
1459
1460
static int OGR2SQLITE_Column(sqlite3_vtab_cursor *pCursor,
1461
                             sqlite3_context *pContext, int nCol)
1462
0
{
1463
#ifdef DEBUG_OGR2SQLITE
1464
    CPLDebug("OGR2SQLITE", "Column %d", nCol);
1465
#endif
1466
1467
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1468
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1469
1470
0
    OGR2SQLITE_GoToWishedIndex(pMyCursor);
1471
1472
0
    OGRFeature *poFeature = pMyCursor->poFeature;
1473
0
    if (poFeature == nullptr)
1474
0
        return SQLITE_ERROR;
1475
1476
0
    if (pMyCursor->pVTab->bHasFIDColumn)
1477
0
    {
1478
0
        if (nCol == 0)
1479
0
        {
1480
0
            sqlite3_result_int64(pContext, poFeature->GetFID());
1481
0
            return SQLITE_OK;
1482
0
        }
1483
0
        --nCol;
1484
0
    }
1485
1486
0
    OGRFeatureDefn *poFDefn = pMyCursor->poLayer->GetLayerDefn();
1487
0
    int nFieldCount = poFDefn->GetFieldCount();
1488
1489
0
    if (nCol == nFieldCount)
1490
0
    {
1491
0
        sqlite3_result_text(pContext, poFeature->GetStyleString(), -1,
1492
0
                            SQLITE_TRANSIENT);
1493
0
        return SQLITE_OK;
1494
0
    }
1495
0
    else if (nCol == (nFieldCount + 1) && poFDefn->GetGeomType() != wkbNone)
1496
0
    {
1497
0
        if (pMyCursor->nGeomBLOBLen < 0)
1498
0
        {
1499
0
            OGRGeometry *poGeom = poFeature->GetGeometryRef();
1500
0
            if (poGeom == nullptr)
1501
0
            {
1502
0
                pMyCursor->nGeomBLOBLen = 0;
1503
0
            }
1504
0
            else
1505
0
            {
1506
0
                CPLAssert(pMyCursor->pabyGeomBLOB == nullptr);
1507
1508
0
                const OGRSpatialReference *poSRS =
1509
0
                    poGeom->getSpatialReference();
1510
0
                int nSRSId = pMyCursor->pVTab->poModule->FetchSRSId(poSRS);
1511
1512
0
                OGR2SQLITE_ExportGeometry(poGeom, nSRSId,
1513
0
                                          pMyCursor->pabyGeomBLOB,
1514
0
                                          pMyCursor->nGeomBLOBLen);
1515
0
            }
1516
0
        }
1517
1518
0
        if (pMyCursor->nGeomBLOBLen == 0)
1519
0
        {
1520
0
            sqlite3_result_null(pContext);
1521
0
        }
1522
0
        else
1523
0
        {
1524
0
            GByte *pabyGeomBLOBDup =
1525
0
                static_cast<GByte *>(CPLMalloc(pMyCursor->nGeomBLOBLen));
1526
0
            memcpy(pabyGeomBLOBDup, pMyCursor->pabyGeomBLOB,
1527
0
                   pMyCursor->nGeomBLOBLen);
1528
0
            sqlite3_result_blob(pContext, pabyGeomBLOBDup,
1529
0
                                pMyCursor->nGeomBLOBLen, CPLFree);
1530
0
        }
1531
1532
0
        return SQLITE_OK;
1533
0
    }
1534
0
    else if (nCol > (nFieldCount + 1) &&
1535
0
             nCol - (nFieldCount + 1) < poFDefn->GetGeomFieldCount())
1536
0
    {
1537
0
        OGRGeometry *poGeom =
1538
0
            poFeature->GetGeomFieldRef(nCol - (nFieldCount + 1));
1539
0
        if (poGeom == nullptr)
1540
0
        {
1541
0
            sqlite3_result_null(pContext);
1542
0
        }
1543
0
        else
1544
0
        {
1545
0
            const OGRSpatialReference *poSRS = poGeom->getSpatialReference();
1546
0
            int nSRSId = pMyCursor->pVTab->poModule->FetchSRSId(poSRS);
1547
1548
0
            GByte *pabyGeomBLOB = nullptr;
1549
0
            int nGeomBLOBLen = 0;
1550
0
            OGR2SQLITE_ExportGeometry(poGeom, nSRSId, pabyGeomBLOB,
1551
0
                                      nGeomBLOBLen);
1552
1553
0
            if (nGeomBLOBLen == 0)
1554
0
            {
1555
0
                sqlite3_result_null(pContext);
1556
0
            }
1557
0
            else
1558
0
            {
1559
0
                sqlite3_result_blob(pContext, pabyGeomBLOB, nGeomBLOBLen,
1560
0
                                    CPLFree);
1561
0
            }
1562
0
        }
1563
0
        return SQLITE_OK;
1564
0
    }
1565
0
    else if (nCol == nFieldCount + 1 + poFDefn->GetGeomFieldCount())
1566
0
    {
1567
0
        sqlite3_result_text(pContext, poFeature->GetNativeData(), -1,
1568
0
                            SQLITE_TRANSIENT);
1569
0
        return SQLITE_OK;
1570
0
    }
1571
0
    else if (nCol == nFieldCount + 1 + poFDefn->GetGeomFieldCount() + 1)
1572
0
    {
1573
0
        sqlite3_result_text(pContext, poFeature->GetNativeMediaType(), -1,
1574
0
                            SQLITE_TRANSIENT);
1575
0
        return SQLITE_OK;
1576
0
    }
1577
0
    else if (nCol < 0 ||
1578
0
             nCol >= nFieldCount + 1 + poFDefn->GetGeomFieldCount() + 2)
1579
0
    {
1580
0
        return SQLITE_ERROR;
1581
0
    }
1582
0
    else if (!poFeature->IsFieldSetAndNotNull(nCol))
1583
0
    {
1584
0
        sqlite3_result_null(pContext);
1585
0
        return SQLITE_OK;
1586
0
    }
1587
1588
0
    switch (poFDefn->GetFieldDefn(nCol)->GetType())
1589
0
    {
1590
0
        case OFTInteger:
1591
0
            sqlite3_result_int(pContext, poFeature->GetFieldAsInteger(nCol));
1592
0
            break;
1593
1594
0
        case OFTInteger64:
1595
0
            sqlite3_result_int64(pContext,
1596
0
                                 poFeature->GetFieldAsInteger64(nCol));
1597
0
            break;
1598
1599
0
        case OFTReal:
1600
0
            sqlite3_result_double(pContext, poFeature->GetFieldAsDouble(nCol));
1601
0
            break;
1602
1603
0
        case OFTBinary:
1604
0
        {
1605
0
            int nSize = 0;
1606
0
            GByte *pBlob = poFeature->GetFieldAsBinary(nCol, &nSize);
1607
0
            sqlite3_result_blob(pContext, pBlob, nSize, SQLITE_TRANSIENT);
1608
0
            break;
1609
0
        }
1610
1611
0
        case OFTDateTime:
1612
0
        {
1613
0
            char *pszStr = OGRGetXMLDateTime(poFeature->GetRawFieldRef(nCol));
1614
0
            sqlite3_result_text(pContext, pszStr, -1, SQLITE_TRANSIENT);
1615
0
            CPLFree(pszStr);
1616
0
            break;
1617
0
        }
1618
1619
0
        case OFTDate:
1620
0
        {
1621
0
            int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZ;
1622
0
            poFeature->GetFieldAsDateTime(nCol, &nYear, &nMonth, &nDay, &nHour,
1623
0
                                          &nMinute, &nSecond, &nTZ);
1624
0
            char szBuffer[64];
1625
0
            snprintf(szBuffer, sizeof(szBuffer), "%04d-%02d-%02d", nYear,
1626
0
                     nMonth, nDay);
1627
0
            sqlite3_result_text(pContext, szBuffer, -1, SQLITE_TRANSIENT);
1628
0
            break;
1629
0
        }
1630
1631
0
        case OFTTime:
1632
0
        {
1633
0
            int nYear = 0;
1634
0
            int nMonth = 0;
1635
0
            int nDay = 0;
1636
0
            int nHour = 0;
1637
0
            int nMinute = 0;
1638
0
            int nTZ = 0;
1639
0
            float fSecond = 0.0f;
1640
0
            poFeature->GetFieldAsDateTime(nCol, &nYear, &nMonth, &nDay, &nHour,
1641
0
                                          &nMinute, &fSecond, &nTZ);
1642
0
            char szBuffer[64];
1643
0
            if (OGR_GET_MS(fSecond) != 0)
1644
0
                snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%06.3f", nHour,
1645
0
                         nMinute, fSecond);
1646
0
            else
1647
0
                snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%02d", nHour,
1648
0
                         nMinute, static_cast<int>(fSecond));
1649
0
            sqlite3_result_text(pContext, szBuffer, -1, SQLITE_TRANSIENT);
1650
0
            break;
1651
0
        }
1652
1653
0
        default:
1654
0
            sqlite3_result_text(pContext, poFeature->GetFieldAsString(nCol), -1,
1655
0
                                SQLITE_TRANSIENT);
1656
0
            break;
1657
0
    }
1658
1659
0
    return SQLITE_OK;
1660
0
}
1661
1662
/************************************************************************/
1663
/*                          OGR2SQLITE_Rowid()                          */
1664
/************************************************************************/
1665
1666
static int OGR2SQLITE_Rowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid)
1667
0
{
1668
0
    OGR2SQLITE_vtab_cursor *pMyCursor =
1669
0
        reinterpret_cast<OGR2SQLITE_vtab_cursor *>(pCursor);
1670
#ifdef DEBUG_OGR2SQLITE
1671
    CPLDebug("OGR2SQLITE", "Rowid");
1672
#endif
1673
1674
0
    OGR2SQLITE_GoToWishedIndex(pMyCursor);
1675
1676
0
    if (pMyCursor->poFeature == nullptr)
1677
0
        return SQLITE_ERROR;
1678
1679
0
    *pRowid = pMyCursor->poFeature->GetFID();
1680
1681
0
    return SQLITE_OK;
1682
0
}
1683
1684
/************************************************************************/
1685
/*                         OGR2SQLITE_Rename()                          */
1686
/************************************************************************/
1687
1688
static int OGR2SQLITE_Rename(CPL_UNUSED sqlite3_vtab *pVtab,
1689
                             CPL_UNUSED const char *zNew)
1690
0
{
1691
    // CPLDebug("OGR2SQLITE", "Rename");
1692
0
    return SQLITE_ERROR;
1693
0
}
1694
1695
#if 0
1696
/************************************************************************/
1697
/*                      OGR2SQLITE_FindFunction()                       */
1698
/************************************************************************/
1699
1700
static
1701
int OGR2SQLITE_FindFunction(sqlite3_vtab *pVtab,
1702
                            int nArg,
1703
                            const char *zName,
1704
                            void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
1705
                            void **ppArg)
1706
{
1707
    CPLDebug("OGR2SQLITE", "FindFunction %s", zName);
1708
1709
    return 0;
1710
}
1711
#endif
1712
1713
/************************************************************************/
1714
/*                     OGR2SQLITE_FeatureFromArgs()                     */
1715
/************************************************************************/
1716
1717
static OGRFeature *OGR2SQLITE_FeatureFromArgs(OGR2SQLITE_vtab *pMyVTab,
1718
                                              int argc, sqlite3_value **argv)
1719
0
{
1720
0
    OGRLayer *poLayer = pMyVTab->poLayer;
1721
0
    OGRFeatureDefn *poLayerDefn = poLayer->GetLayerDefn();
1722
0
    const int nFieldCount = poLayerDefn->GetFieldCount();
1723
0
    const int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
1724
    // The argv[0] parameter is the rowid of a row in the virtual table to be deleted.
1725
    // The argv[1] parameter is the rowid of a new row to be inserted into the virtual table
1726
    // If bHasFIDColumn, we have an extra column, before the attributes
1727
0
    const int nLeadingColumns = pMyVTab->bHasFIDColumn ? 3 : 2;
1728
0
    if (argc != nLeadingColumns + nFieldCount + 1 + /* OGR_STYLE */
1729
0
                    nGeomFieldCount + 2 /* NativeData and NativeMediaType */)
1730
0
    {
1731
0
        CPLDebug("OGR2SQLITE", "Did not get expect argument count : %d, %d",
1732
0
                 argc, nLeadingColumns + nFieldCount + 1 + nGeomFieldCount + 2);
1733
0
        return nullptr;
1734
0
    }
1735
1736
0
    auto poFeature = std::make_unique<OGRFeature>(poLayerDefn);
1737
1738
0
    if (pMyVTab->bHasFIDColumn)
1739
0
    {
1740
0
        if (sqlite3_value_type(argv[2]) == SQLITE_INTEGER)
1741
0
        {
1742
0
            if (sqlite3_value_type(argv[1]) == SQLITE_INTEGER &&
1743
0
                sqlite3_value_int64(argv[1]) != sqlite3_value_int64(argv[2]))
1744
0
            {
1745
0
                CPLError(CE_Failure, CPLE_AppDefined,
1746
0
                         "Value provided through ROWID and %s are different",
1747
0
                         poLayer->GetFIDColumn());
1748
0
                return nullptr;
1749
0
            }
1750
0
            poFeature->SetFID(sqlite3_value_int64(argv[2]));
1751
0
        }
1752
0
    }
1753
0
    else if (sqlite3_value_type(argv[1]) == SQLITE_INTEGER)
1754
0
    {
1755
0
        poFeature->SetFID(sqlite3_value_int64(argv[1]));
1756
0
    }
1757
1758
0
    int iArgc = nLeadingColumns;
1759
0
    for (int i = 0; i < nFieldCount; i++, ++iArgc)
1760
0
    {
1761
0
        switch (sqlite3_value_type(argv[iArgc]))
1762
0
        {
1763
0
            case SQLITE_NULL:
1764
0
                poFeature->SetFieldNull(i);
1765
0
                break;
1766
0
            case SQLITE_INTEGER:
1767
0
                poFeature->SetField(i, sqlite3_value_int64(argv[iArgc]));
1768
0
                break;
1769
0
            case SQLITE_FLOAT:
1770
0
                poFeature->SetField(i, sqlite3_value_double(argv[iArgc]));
1771
0
                break;
1772
0
            case SQLITE_TEXT:
1773
0
            {
1774
0
                const char *pszValue = reinterpret_cast<const char *>(
1775
0
                    sqlite3_value_text(argv[iArgc]));
1776
0
                switch (poLayerDefn->GetFieldDefn(i)->GetType())
1777
0
                {
1778
0
                    case OFTDate:
1779
0
                    case OFTTime:
1780
0
                    case OFTDateTime:
1781
0
                        if (!OGRParseDate(pszValue,
1782
0
                                          poFeature->GetRawFieldRef(i), 0))
1783
0
                            poFeature->SetField(i, pszValue);
1784
0
                        break;
1785
1786
0
                    default:
1787
0
                        poFeature->SetField(i, pszValue);
1788
0
                        break;
1789
0
                }
1790
0
                break;
1791
0
            }
1792
0
            case SQLITE_BLOB:
1793
0
            {
1794
0
                GByte *paby = reinterpret_cast<GByte *>(
1795
0
                    const_cast<void *>(sqlite3_value_blob(argv[iArgc])));
1796
0
                int nLen = sqlite3_value_bytes(argv[iArgc]);
1797
0
                poFeature->SetField(i, nLen, paby);
1798
0
                break;
1799
0
            }
1800
0
            default:
1801
0
                break;
1802
0
        }
1803
0
    }
1804
1805
0
    if (sqlite3_value_type(argv[iArgc]) == SQLITE_TEXT)
1806
0
    {
1807
0
        poFeature->SetStyleString(
1808
0
            reinterpret_cast<const char *>(sqlite3_value_text(argv[iArgc])));
1809
0
    }
1810
0
    ++iArgc;
1811
1812
0
    for (int i = 0; i < nGeomFieldCount; i++, ++iArgc)
1813
0
    {
1814
0
        if (sqlite3_value_type(argv[iArgc]) == SQLITE_BLOB)
1815
0
        {
1816
0
            const GByte *pabyBlob = reinterpret_cast<const GByte *>(
1817
0
                sqlite3_value_blob(argv[iArgc]));
1818
0
            int nLen = sqlite3_value_bytes(argv[iArgc]);
1819
0
            OGRGeometry *poGeom = nullptr;
1820
0
            if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(
1821
0
                    pabyBlob, nLen, &poGeom) == OGRERR_NONE)
1822
0
            {
1823
                /*                OGRwkbGeometryType eGeomFieldType =
1824
                                    poFeature->GetDefnRef()->GetGeomFieldDefn(i)->GetType();
1825
                                if( OGR_GT_IsCurve(eGeomFieldType) &&
1826
                   !OGR_GT_IsCurve(poGeom->getGeometryType()) )
1827
                                {
1828
                                    OGRGeometry* poCurveGeom =
1829
                   poGeom->getCurveGeometry();
1830
                                    poFeature->SetGeomFieldDirectly(i,
1831
                   poCurveGeom); delete poCurveGeom;
1832
                                }
1833
                                else*/
1834
0
                poFeature->SetGeomFieldDirectly(i, poGeom);
1835
0
            }
1836
0
        }
1837
0
    }
1838
1839
0
    if (sqlite3_value_type(argv[iArgc]) == SQLITE_TEXT)
1840
0
    {
1841
0
        poFeature->SetNativeData(
1842
0
            reinterpret_cast<const char *>(sqlite3_value_text(argv[iArgc])));
1843
0
    }
1844
0
    ++iArgc;
1845
1846
0
    if (sqlite3_value_type(argv[iArgc]) == SQLITE_TEXT)
1847
0
    {
1848
0
        poFeature->SetNativeMediaType(
1849
0
            reinterpret_cast<const char *>(sqlite3_value_text(argv[iArgc])));
1850
0
    }
1851
1852
0
    return poFeature.release();
1853
0
}
1854
1855
/************************************************************************/
1856
/*                         OGR2SQLITE_Update()                          */
1857
/************************************************************************/
1858
1859
static int OGR2SQLITE_Update(sqlite3_vtab *pVTab, int argc,
1860
                             sqlite3_value **argv, sqlite_int64 *pRowid)
1861
0
{
1862
0
    CPLDebug("OGR2SQLITE", "OGR2SQLITE_Update");
1863
1864
0
    OGR2SQLITE_vtab *pMyVTab = reinterpret_cast<OGR2SQLITE_vtab *>(pVTab);
1865
0
    OGRLayer *poLayer = pMyVTab->poLayer;
1866
1867
0
    if (argc == 1)
1868
0
    {
1869
        /* DELETE */
1870
1871
0
        OGRErr eErr = poLayer->DeleteFeature(sqlite3_value_int64(argv[0]));
1872
1873
0
        return (eErr == OGRERR_NONE) ? SQLITE_OK : SQLITE_ERROR;
1874
0
    }
1875
0
    else if (argc > 1 && sqlite3_value_type(argv[0]) == SQLITE_NULL)
1876
0
    {
1877
        /* INSERT */
1878
1879
0
        OGRFeature *poFeature = OGR2SQLITE_FeatureFromArgs(pMyVTab, argc, argv);
1880
0
        if (poFeature == nullptr)
1881
0
            return SQLITE_ERROR;
1882
1883
0
        OGRErr eErr = poLayer->CreateFeature(poFeature);
1884
0
        if (eErr == OGRERR_NONE)
1885
0
            *pRowid = poFeature->GetFID();
1886
1887
0
        delete poFeature;
1888
1889
0
        return (eErr == OGRERR_NONE) ? SQLITE_OK : SQLITE_ERROR;
1890
0
    }
1891
0
    else if (argc > 1 && sqlite3_value_type(argv[0]) == SQLITE_INTEGER &&
1892
0
             sqlite3_value_type(argv[1]) == SQLITE_INTEGER &&
1893
0
             sqlite3_value_int64(argv[0]) == sqlite3_value_int64(argv[1]))
1894
0
    {
1895
        /* UPDATE */
1896
1897
0
        OGRFeature *poFeature = OGR2SQLITE_FeatureFromArgs(pMyVTab, argc, argv);
1898
0
        if (poFeature == nullptr)
1899
0
            return SQLITE_ERROR;
1900
1901
0
        OGRErr eErr = poLayer->SetFeature(poFeature);
1902
1903
0
        delete poFeature;
1904
1905
0
        return (eErr == OGRERR_NONE) ? SQLITE_OK : SQLITE_ERROR;
1906
0
    }
1907
1908
    // UPDATE table SET rowid=rowid+1 WHERE ... unsupported
1909
1910
0
    return SQLITE_ERROR;
1911
0
}
1912
1913
/************************************************************************/
1914
/*                          sOGR2SQLITEModule                           */
1915
/************************************************************************/
1916
1917
static const struct sqlite3_module sOGR2SQLITEModule = {
1918
    1,                        /* iVersion */
1919
    OGR2SQLITE_ConnectCreate, /* xCreate */
1920
    OGR2SQLITE_ConnectCreate, /* xConnect */
1921
    OGR2SQLITE_BestIndex,
1922
    OGR2SQLITE_DisconnectDestroy, /* xDisconnect */
1923
    OGR2SQLITE_DisconnectDestroy, /* xDestroy */
1924
    OGR2SQLITE_Open,
1925
    OGR2SQLITE_Close,
1926
    OGR2SQLITE_Filter,
1927
    OGR2SQLITE_Next,
1928
    OGR2SQLITE_Eof,
1929
    OGR2SQLITE_Column,
1930
    OGR2SQLITE_Rowid,
1931
    OGR2SQLITE_Update,
1932
    nullptr, /* xBegin */
1933
    nullptr, /* xSync */
1934
    nullptr, /* xCommit */
1935
    nullptr, /* xFindFunctionRollback */
1936
    nullptr,
1937
    /* xFindFunction */  // OGR2SQLITE_FindFunction;
1938
    OGR2SQLITE_Rename,
1939
    nullptr,  // xSavepoint
1940
    nullptr,  // xRelease
1941
    nullptr,  // xRollbackTo
1942
    nullptr,  // xShadowName
1943
#if SQLITE_VERSION_NUMBER >=                                                   \
1944
    3044000L /* should be the first version with the below symbols */
1945
    nullptr,  // xIntegrity
1946
#endif
1947
};
1948
1949
/************************************************************************/
1950
/*                        OGR2SQLITE_GetLayer()                         */
1951
/************************************************************************/
1952
1953
static OGRLayer *OGR2SQLITE_GetLayer(const char *pszFuncName,
1954
                                     sqlite3_context *pContext, int argc,
1955
                                     sqlite3_value **argv,
1956
                                     int iLayerNameArg = 0)
1957
0
{
1958
0
    if (argc <= iLayerNameArg)
1959
0
    {
1960
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s(): %s", "VirtualOGR",
1961
0
                 pszFuncName, "Invalid number of arguments");
1962
0
        sqlite3_result_null(pContext);
1963
0
        return nullptr;
1964
0
    }
1965
1966
0
    if (sqlite3_value_type(argv[iLayerNameArg]) != SQLITE_TEXT)
1967
0
    {
1968
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s(): %s", "VirtualOGR",
1969
0
                 pszFuncName, "Invalid argument type");
1970
0
        sqlite3_result_null(pContext);
1971
0
        return nullptr;
1972
0
    }
1973
1974
0
    const char *pszVTableName =
1975
0
        reinterpret_cast<const char *>(sqlite3_value_text(argv[iLayerNameArg]));
1976
1977
0
    OGR2SQLITEModule *poModule =
1978
0
        static_cast<OGR2SQLITEModule *>(sqlite3_user_data(pContext));
1979
1980
0
    OGRLayer *poLayer = poModule->GetLayerForVTable(SQLUnescape(pszVTableName));
1981
0
    if (poLayer == nullptr)
1982
0
    {
1983
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s(): %s '%s'", "VirtualOGR",
1984
0
                 pszFuncName, "unknown layer", pszVTableName);
1985
0
        sqlite3_result_null(pContext);
1986
0
        return nullptr;
1987
0
    }
1988
1989
0
    return poLayer;
1990
0
}
1991
1992
/************************************************************************/
1993
/*                    OGR2SQLITE_ogr_layer_Extent()                     */
1994
/************************************************************************/
1995
1996
static void OGR2SQLITE_ogr_layer_Extent(sqlite3_context *pContext, int argc,
1997
                                        sqlite3_value **argv)
1998
0
{
1999
0
    OGRLayer *poLayer =
2000
0
        OGR2SQLITE_GetLayer("ogr_layer_Extent", pContext, argc, argv);
2001
0
    if (poLayer == nullptr)
2002
0
        return;
2003
2004
0
    OGR2SQLITEModule *poModule =
2005
0
        static_cast<OGR2SQLITEModule *>(sqlite3_user_data(pContext));
2006
2007
0
    if (poLayer->GetGeomType() == wkbNone)
2008
0
    {
2009
0
        sqlite3_result_null(pContext);
2010
0
        return;
2011
0
    }
2012
2013
0
    OGREnvelope sExtent;
2014
0
    if (poLayer->GetExtent(&sExtent) != OGRERR_NONE)
2015
0
    {
2016
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s(): %s", "VirtualOGR",
2017
0
                 "ogr_layer_Extent", "Cannot fetch layer extent");
2018
0
        sqlite3_result_null(pContext);
2019
0
        return;
2020
0
    }
2021
2022
0
    OGRPolygon oPoly;
2023
0
    OGRLinearRing *poRing = new OGRLinearRing();
2024
0
    oPoly.addRingDirectly(poRing);
2025
0
    poRing->addPoint(sExtent.MinX, sExtent.MinY);
2026
0
    poRing->addPoint(sExtent.MaxX, sExtent.MinY);
2027
0
    poRing->addPoint(sExtent.MaxX, sExtent.MaxY);
2028
0
    poRing->addPoint(sExtent.MinX, sExtent.MaxY);
2029
0
    poRing->addPoint(sExtent.MinX, sExtent.MinY);
2030
2031
0
    GByte *pabySLBLOB = nullptr;
2032
0
    int nBLOBLen = 0;
2033
0
    int nSRID = poModule->FetchSRSId(poLayer->GetSpatialRef());
2034
0
    if (OGRSQLiteLayer::ExportSpatiaLiteGeometry(&oPoly, nSRID, wkbNDR, FALSE,
2035
0
                                                 FALSE, &pabySLBLOB,
2036
0
                                                 &nBLOBLen) == OGRERR_NONE)
2037
0
    {
2038
0
        sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
2039
0
    }
2040
0
    else
2041
0
    {
2042
0
        sqlite3_result_null(pContext);
2043
0
    }
2044
0
}
2045
2046
/************************************************************************/
2047
/*                     OGR2SQLITE_ogr_layer_SRID()                      */
2048
/************************************************************************/
2049
2050
static void OGR2SQLITE_ogr_layer_SRID(sqlite3_context *pContext, int argc,
2051
                                      sqlite3_value **argv)
2052
0
{
2053
0
    OGRLayer *poLayer =
2054
0
        OGR2SQLITE_GetLayer("OGR2SQLITE_ogr_layer_SRID", pContext, argc, argv);
2055
0
    if (poLayer == nullptr)
2056
0
        return;
2057
2058
0
    OGR2SQLITEModule *poModule =
2059
0
        static_cast<OGR2SQLITEModule *>(sqlite3_user_data(pContext));
2060
2061
0
    if (poLayer->GetGeomType() == wkbNone)
2062
0
    {
2063
0
        sqlite3_result_null(pContext);
2064
0
        return;
2065
0
    }
2066
2067
0
    int nSRID = poModule->FetchSRSId(poLayer->GetSpatialRef());
2068
0
    sqlite3_result_int(pContext, nSRID);
2069
0
}
2070
2071
/************************************************************************/
2072
/*                 OGR2SQLITE_ogr_layer_GeometryType()                  */
2073
/************************************************************************/
2074
2075
static void OGR2SQLITE_ogr_layer_GeometryType(sqlite3_context *pContext,
2076
                                              int argc, sqlite3_value **argv)
2077
0
{
2078
0
    OGRLayer *poLayer = OGR2SQLITE_GetLayer("OGR2SQLITE_ogr_layer_GeometryType",
2079
0
                                            pContext, argc, argv);
2080
0
    if (poLayer == nullptr)
2081
0
        return;
2082
2083
0
    OGRwkbGeometryType eType = poLayer->GetGeomType();
2084
2085
0
    if (eType == wkbNone)
2086
0
    {
2087
0
        sqlite3_result_null(pContext);
2088
0
        return;
2089
0
    }
2090
2091
0
    const char *psz2DName = OGRToOGCGeomType(eType);
2092
0
    if (wkbHasZ(eType))
2093
0
        sqlite3_result_text(pContext, CPLSPrintf("%s Z", psz2DName), -1,
2094
0
                            SQLITE_TRANSIENT);
2095
0
    else
2096
0
        sqlite3_result_text(pContext, psz2DName, -1, SQLITE_TRANSIENT);
2097
0
}
2098
2099
/************************************************************************/
2100
/*                 OGR2SQLITE_ogr_layer_FeatureCount()                  */
2101
/************************************************************************/
2102
2103
static void OGR2SQLITE_ogr_layer_FeatureCount(sqlite3_context *pContext,
2104
                                              int argc, sqlite3_value **argv)
2105
0
{
2106
0
    OGRLayer *poLayer = OGR2SQLITE_GetLayer("OGR2SQLITE_ogr_layer_FeatureCount",
2107
0
                                            pContext, argc, argv);
2108
0
    if (poLayer == nullptr)
2109
0
        return;
2110
2111
0
    sqlite3_result_int64(pContext, poLayer->GetFeatureCount());
2112
0
}
2113
2114
/************************************************************************/
2115
/*                OGR2SQLITE_ST_Hilbert_X_Y_TableName()                 */
2116
/************************************************************************/
2117
2118
static void OGR2SQLITE_ST_Hilbert_X_Y_TableName(sqlite3_context *pContext,
2119
                                                int argc, sqlite3_value **argv)
2120
0
{
2121
0
    CPLAssert(argc == 3);
2122
0
    const double dfX = sqlite3_value_double(argv[0]);
2123
0
    const double dfY = sqlite3_value_double(argv[1]);
2124
2125
0
    OGRLayer *poLayer =
2126
0
        OGR2SQLITE_GetLayer("ST_Hilbert", pContext, argc, argv, 2);
2127
0
    if (poLayer == nullptr)
2128
0
    {
2129
0
        sqlite3_result_null(pContext);
2130
0
        return;
2131
0
    }
2132
2133
0
    OGREnvelope sExtent;
2134
0
    if (poLayer->GetExtent(&sExtent, true) != OGRERR_NONE)
2135
0
    {
2136
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: Cannot fetch layer extent",
2137
0
                 "ST_Hilbert()");
2138
0
        sqlite3_result_null(pContext);
2139
0
        return;
2140
0
    }
2141
0
    if (!(dfX >= sExtent.MinX && dfY >= sExtent.MinY && dfX <= sExtent.MaxX &&
2142
0
          dfY <= sExtent.MaxY))
2143
0
    {
2144
0
        CPLError(CE_Warning, CPLE_AppDefined,
2145
0
                 "ST_Hilbert(): (%g, %g) is not within passed bounding box",
2146
0
                 dfX, dfY);
2147
0
        sqlite3_result_null(pContext);
2148
0
        return;
2149
0
    }
2150
0
    sqlite3_result_int64(pContext, GDALHilbertCode(&sExtent, dfX, dfY));
2151
0
}
2152
2153
/************************************************************************/
2154
/*                         OGR2SQLITE_GetGeom()                         */
2155
/************************************************************************/
2156
2157
static std::unique_ptr<OGRGeometry>
2158
OGR2SQLITE_GetGeom(sqlite3_context * /*pContext*/, int /* argc */,
2159
                   sqlite3_value **argv, int *pnSRSId, int iGeomArg)
2160
0
{
2161
0
    if (sqlite3_value_type(argv[iGeomArg]) != SQLITE_BLOB)
2162
0
    {
2163
0
        return nullptr;
2164
0
    }
2165
2166
0
    const GByte *pabySLBLOB =
2167
0
        reinterpret_cast<const GByte *>(sqlite3_value_blob(argv[iGeomArg]));
2168
0
    int nBLOBLen = sqlite3_value_bytes(argv[iGeomArg]);
2169
0
    OGRGeometry *poGeom = nullptr;
2170
0
    if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(pabySLBLOB, nBLOBLen, &poGeom,
2171
0
                                                 pnSRSId) != OGRERR_NONE)
2172
0
    {
2173
0
        delete poGeom;
2174
0
        return nullptr;
2175
0
    }
2176
2177
0
    return std::unique_ptr<OGRGeometry>(poGeom);
2178
0
}
2179
2180
/************************************************************************/
2181
/*                  OGR2SQLITE_ST_Hilbert_Geom_BBOX()                   */
2182
/************************************************************************/
2183
2184
static void OGR2SQLITE_ST_Hilbert_Geom_BBOX(sqlite3_context *pContext, int argc,
2185
                                            sqlite3_value **argv)
2186
0
{
2187
0
    CPLAssert(argc == 5);
2188
0
    auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr, 0);
2189
0
    if (!poGeom || poGeom->IsEmpty())
2190
0
    {
2191
0
        sqlite3_result_null(pContext);
2192
0
        return;
2193
0
    }
2194
0
    OGREnvelope sGeomEnvelope;
2195
0
    poGeom->getEnvelope(&sGeomEnvelope);
2196
0
    const double dfX = (sGeomEnvelope.MinX + sGeomEnvelope.MaxX) / 2;
2197
0
    const double dfY = (sGeomEnvelope.MinY + sGeomEnvelope.MaxY) / 2;
2198
2199
0
    OGREnvelope sExtent;
2200
0
    sExtent.MinX = sqlite3_value_double(argv[1]);
2201
0
    sExtent.MinY = sqlite3_value_double(argv[2]);
2202
0
    sExtent.MaxX = sqlite3_value_double(argv[3]);
2203
0
    sExtent.MaxY = sqlite3_value_double(argv[4]);
2204
0
    if (!(dfX >= sExtent.MinX && dfY >= sExtent.MinY && dfX <= sExtent.MaxX &&
2205
0
          dfY <= sExtent.MaxY))
2206
0
    {
2207
0
        CPLError(CE_Warning, CPLE_AppDefined,
2208
0
                 "ST_Hilbert(): (%g, %g) is not within passed bounding box",
2209
0
                 dfX, dfY);
2210
0
        sqlite3_result_null(pContext);
2211
0
        return;
2212
0
    }
2213
0
    sqlite3_result_int64(pContext, GDALHilbertCode(&sExtent, dfX, dfY));
2214
0
}
2215
2216
/************************************************************************/
2217
/*                OGR2SQLITE_ST_Hilbert_Geom_TableName()                */
2218
/************************************************************************/
2219
2220
static void OGR2SQLITE_ST_Hilbert_Geom_TableName(sqlite3_context *pContext,
2221
                                                 int argc, sqlite3_value **argv)
2222
0
{
2223
0
    CPLAssert(argc == 2);
2224
0
    auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr, 0);
2225
0
    if (!poGeom || poGeom->IsEmpty())
2226
0
    {
2227
0
        sqlite3_result_null(pContext);
2228
0
        return;
2229
0
    }
2230
0
    OGREnvelope sGeomEnvelope;
2231
0
    poGeom->getEnvelope(&sGeomEnvelope);
2232
0
    const double dfX = (sGeomEnvelope.MinX + sGeomEnvelope.MaxX) / 2;
2233
0
    const double dfY = (sGeomEnvelope.MinY + sGeomEnvelope.MaxY) / 2;
2234
2235
0
    if (sqlite3_value_type(argv[1]) != SQLITE_TEXT)
2236
0
    {
2237
0
        CPLError(CE_Failure, CPLE_AppDefined,
2238
0
                 "%s: Invalid argument type for 2nd argument. Text expected",
2239
0
                 "ST_Hilbert()");
2240
0
        sqlite3_result_null(pContext);
2241
0
        return;
2242
0
    }
2243
2244
0
    OGRLayer *poLayer =
2245
0
        OGR2SQLITE_GetLayer("ST_Hilbert", pContext, argc, argv, 1);
2246
0
    if (poLayer == nullptr)
2247
0
    {
2248
0
        sqlite3_result_null(pContext);
2249
0
        return;
2250
0
    }
2251
2252
0
    OGREnvelope sExtent;
2253
0
    if (poLayer->GetExtent(&sExtent, true) != OGRERR_NONE)
2254
0
    {
2255
0
        CPLError(CE_Failure, CPLE_AppDefined, "%s: Cannot fetch layer extent",
2256
0
                 "ST_Hilbert()");
2257
0
        sqlite3_result_null(pContext);
2258
0
        return;
2259
0
    }
2260
0
    if (!(dfX >= sExtent.MinX && dfY >= sExtent.MinY && dfX <= sExtent.MaxX &&
2261
0
          dfY <= sExtent.MaxY))
2262
0
    {
2263
0
        CPLError(CE_Warning, CPLE_AppDefined,
2264
0
                 "ST_Hilbert(): (%g, %g) is not within passed bounding box",
2265
0
                 dfX, dfY);
2266
0
        sqlite3_result_null(pContext);
2267
0
        return;
2268
0
    }
2269
0
    sqlite3_result_int64(pContext, GDALHilbertCode(&sExtent, dfX, dfY));
2270
0
}
2271
2272
/************************************************************************/
2273
/*                      OGR2SQLITEDestroyModule()                       */
2274
/************************************************************************/
2275
2276
static void OGR2SQLITEDestroyModule(void *pData)
2277
8.01k
{
2278
    // Comment out this debug message, as the module can be registered in the
2279
    // connection of proj.db that is since PROJ 8.1 a cache that is destroyed at
2280
    // PROJ unloading, after GDAL itself has cleaned up itself. CPLDebug("OGR",
2281
    // "Unloading VirtualOGR module");
2282
8.01k
    delete static_cast<OGR2SQLITEModule *>(pData);
2283
8.01k
}
2284
2285
/* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
2286
#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
2287
2288
/************************************************************************/
2289
/*                     OGR2SQLITESpatialIndex_vtab                      */
2290
/************************************************************************/
2291
2292
typedef struct
2293
{
2294
    /* Mandatory fields by sqlite3: don't change or reorder them ! */
2295
    const sqlite3_module *pModule;
2296
    int nRef;
2297
    char *zErrMsg;
2298
2299
    /* Extension fields */
2300
    char *pszVTableName;
2301
    OGR2SQLITEModule *poModule;
2302
    GDALDataset *poDS;
2303
    int bCloseDS;
2304
    OGRLayer *poLayer;
2305
    int nMyRef;
2306
} OGR2SQLITESpatialIndex_vtab;
2307
2308
/************************************************************************/
2309
/*                  OGR2SQLITESpatialIndex_vtab_cursor                  */
2310
/************************************************************************/
2311
2312
typedef struct
2313
{
2314
    /* Mandatory fields by sqlite3: don't change or reorder them ! */
2315
    OGR2SQLITESpatialIndex_vtab *pVTab;
2316
2317
    /* Extension fields */
2318
    GDALDataset *poDupDataSource;
2319
    OGRLayer *poLayer;
2320
    OGRFeature *poFeature;
2321
    int bHasSetBounds;
2322
    double dfMinX;
2323
    double dfMinY;
2324
    double dfMaxX;
2325
    double dfMaxY;
2326
} OGR2SQLITESpatialIndex_vtab_cursor;
2327
2328
/************************************************************************/
2329
/*                OGR2SQLITESpatialIndex_ConnectCreate()                */
2330
/************************************************************************/
2331
2332
static int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3 *hDB, void *pAux,
2333
                                                int argc,
2334
                                                const char *const *argv,
2335
                                                sqlite3_vtab **ppVTab,
2336
                                                char **pzErr)
2337
{
2338
#ifdef DEBUG_OGR2SQLITE
2339
    CPLDebug("OGR2SQLITE", "ConnectCreate(%s)", argv[2]);
2340
#endif
2341
2342
    OGR2SQLITEModule *poModule = (OGR2SQLITEModule *)pAux;
2343
2344
    /* -------------------------------------------------------------------- */
2345
    /*      If called from ogrexecutesql.cpp                                */
2346
    /* -------------------------------------------------------------------- */
2347
    GDALDataset *poDS = poModule->GetDS();
2348
    if (poDS == NULL)
2349
        return SQLITE_ERROR;
2350
2351
    if (argc != 10)
2352
    {
2353
        *pzErr =
2354
            sqlite3_mprintf("Expected syntax: CREATE VIRTUAL TABLE xxx USING "
2355
                            "VirtualOGRSpatialIndex(ds_idx, layer_name, pkid, "
2356
                            "xmin, xmax, ymin, ymax)");
2357
        return SQLITE_ERROR;
2358
    }
2359
2360
    int nDSIndex = atoi(argv[3]);
2361
    if (nDSIndex >= 0)
2362
    {
2363
        poDS = poModule->GetExtraDS(nDSIndex);
2364
        if (poDS == NULL)
2365
        {
2366
            *pzErr = sqlite3_mprintf("Invalid dataset index : %d", nDSIndex);
2367
            return SQLITE_ERROR;
2368
        }
2369
    }
2370
2371
    poDS = (GDALDataset *)OGROpen(poDS->GetName(), FALSE, NULL);
2372
    if (poDS == NULL)
2373
    {
2374
        return SQLITE_ERROR;
2375
    }
2376
2377
    CPLString osLayerName(SQLUnescape(argv[4]));
2378
2379
    OGRLayer *poLayer = poDS->GetLayerByName(osLayerName);
2380
    if (poLayer == NULL)
2381
    {
2382
        *pzErr = sqlite3_mprintf("Cannot find layer '%s' in '%s'",
2383
                                 osLayerName.c_str(), poDS->GetName());
2384
        return SQLITE_ERROR;
2385
    }
2386
2387
    OGR2SQLITESpatialIndex_vtab *vtab =
2388
        (OGR2SQLITESpatialIndex_vtab *)CPLCalloc(
2389
            1, sizeof(OGR2SQLITESpatialIndex_vtab));
2390
    // We do not need to fill the non-extended fields.
2391
    vtab->pszVTableName = CPLStrdup(SQLEscapeName(argv[2]));
2392
    vtab->poModule = poModule;
2393
    vtab->poDS = poDS;
2394
    vtab->bCloseDS = true;
2395
    vtab->poLayer = poLayer;
2396
    vtab->nMyRef = 0;
2397
2398
    *ppVTab = (sqlite3_vtab *)vtab;
2399
2400
    CPLString osSQL;
2401
    osSQL = "CREATE TABLE ";
2402
    osSQL += "\"";
2403
    osSQL += SQLEscapeName(argv[2]);
2404
    osSQL += "\"";
2405
    osSQL += "(";
2406
2407
    bool bAddComma = false;
2408
2409
    for (i = 0; i < 5; i++)
2410
    {
2411
        if (bAddComma)
2412
            osSQL += ",";
2413
        bAddComma = true;
2414
2415
        osSQL += "\"";
2416
        osSQL += SQLEscapeName(SQLUnescape(argv[5 + i]));
2417
        osSQL += "\"";
2418
        osSQL += " ";
2419
        osSQL += (i == 0) ? "INTEGER" : "FLOAT";
2420
    }
2421
2422
    osSQL += ")";
2423
2424
    CPLDebug("OGR2SQLITE", "sqlite3_declare_vtab(%s)", osSQL.c_str());
2425
    if (sqlite3_declare_vtab(hDB, osSQL.c_str()) != SQLITE_OK)
2426
    {
2427
        *pzErr = sqlite3_mprintf("CREATE VIRTUAL: invalid SQL statement : %s",
2428
                                 osSQL.c_str());
2429
        return SQLITE_ERROR;
2430
    }
2431
2432
    return SQLITE_OK;
2433
}
2434
2435
/************************************************************************/
2436
/*                  OGR2SQLITESpatialIndex_BestIndex()                  */
2437
/************************************************************************/
2438
2439
static int OGR2SQLITESpatialIndex_BestIndex(sqlite3_vtab *pVTab,
2440
                                            sqlite3_index_info *pIndex)
2441
{
2442
#ifdef DEBUG_OGR2SQLITE
2443
    CPLDebug("OGR2SQLITE", "BestIndex");
2444
#endif
2445
2446
    bool bMinX = false;
2447
    bool bMinY = false;
2448
    bool bMaxX = false;
2449
    bool bMaxY = false;
2450
2451
    for (int i = 0; i < pIndex->nConstraint; i++)
2452
    {
2453
        int iCol = pIndex->aConstraint[i].iColumn;
2454
        /* MinX */
2455
        if (!bMinX && iCol == 1 && pIndex->aConstraint[i].usable &&
2456
            (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LE ||
2457
             pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LT))
2458
            bMinX = true;
2459
        /* MaxX */
2460
        else if (!bMaxX && iCol == 2 && pIndex->aConstraint[i].usable &&
2461
                 (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GE ||
2462
                  pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GT))
2463
            bMaxX = true;
2464
        /* MinY */
2465
        else if (!bMinY && iCol == 3 && pIndex->aConstraint[i].usable &&
2466
                 (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LE ||
2467
                  pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LT))
2468
            bMinY = true;
2469
        /* MaxY */
2470
        else if (!bMaxY && iCol == 4 && pIndex->aConstraint[i].usable &&
2471
                 (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GE ||
2472
                  pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GT))
2473
            bMaxY = true;
2474
        else
2475
            break;
2476
    }
2477
2478
    if (bMinX && bMinY && bMaxX && bMaxY)
2479
    {
2480
        CPLAssert(pIndex->nConstraint == 4);
2481
2482
        int nConstraints = 0;
2483
        for (int i = 0; i < pIndex->nConstraint; i++)
2484
        {
2485
            pIndex->aConstraintUsage[i].argvIndex = nConstraints + 1;
2486
            pIndex->aConstraintUsage[i].omit = true;
2487
2488
            nConstraints++;
2489
        }
2490
2491
        int *panConstraints =
2492
            (int *)sqlite3_malloc(sizeof(int) * (1 + 2 * nConstraints));
2493
        panConstraints[0] = nConstraints;
2494
2495
        nConstraints = 0;
2496
2497
        for (int i = 0; i < pIndex->nConstraint; i++)
2498
        {
2499
            if (pIndex->aConstraintUsage[i].omit)
2500
            {
2501
                panConstraints[2 * nConstraints + 1] =
2502
                    pIndex->aConstraint[i].iColumn;
2503
                panConstraints[2 * nConstraints + 2] =
2504
                    pIndex->aConstraint[i].op;
2505
2506
                nConstraints++;
2507
            }
2508
        }
2509
2510
        pIndex->idxStr = (char *)panConstraints;
2511
        pIndex->needToFreeIdxStr = true;
2512
2513
        pIndex->orderByConsumed = false;
2514
        pIndex->idxNum = 0;
2515
2516
        return SQLITE_OK;
2517
    }
2518
    else
2519
    {
2520
        CPLDebug("OGR2SQLITE",
2521
                 "OGR2SQLITESpatialIndex_BestIndex: unhandled request");
2522
        return SQLITE_ERROR;
2523
        /*
2524
                for (i = 0; i < pIndex->nConstraint; i++)
2525
                {
2526
                    pIndex->aConstraintUsage[i].argvIndex = 0;
2527
                    pIndex->aConstraintUsage[i].omit = false;
2528
                }
2529
2530
                pIndex->idxStr = NULL;
2531
                pIndex->needToFreeIdxStr = false;
2532
        */
2533
    }
2534
}
2535
2536
/************************************************************************/
2537
/*              OGR2SQLITESpatialIndex_DisconnectDestroy()              */
2538
/************************************************************************/
2539
2540
static int OGR2SQLITESpatialIndex_DisconnectDestroy(sqlite3_vtab *pVTab)
2541
{
2542
    OGR2SQLITESpatialIndex_vtab *pMyVTab = (OGR2SQLITESpatialIndex_vtab *)pVTab;
2543
2544
#ifdef DEBUG_OGR2SQLITE
2545
    CPLDebug("OGR2SQLITE", "DisconnectDestroy(%s)", pMyVTab->pszVTableName);
2546
#endif
2547
2548
    sqlite3_free(pMyVTab->zErrMsg);
2549
    if (pMyVTab->bCloseDS)
2550
        delete pMyVTab->poDS;
2551
    CPLFree(pMyVTab->pszVTableName);
2552
    CPLFree(pMyVTab);
2553
2554
    return SQLITE_OK;
2555
}
2556
2557
/************************************************************************/
2558
/*                    OGR2SQLITESpatialIndex_Open()                     */
2559
/************************************************************************/
2560
2561
static int OGR2SQLITESpatialIndex_Open(sqlite3_vtab *pVTab,
2562
                                       sqlite3_vtab_cursor **ppCursor)
2563
{
2564
    OGR2SQLITESpatialIndex_vtab *pMyVTab = (OGR2SQLITESpatialIndex_vtab *)pVTab;
2565
#ifdef DEBUG_OGR2SQLITE
2566
    CPLDebug("OGR2SQLITE", "Open(%s, %s)", pMyVTab->poDS->GetName(),
2567
             pMyVTab->poLayer->GetName());
2568
#endif
2569
2570
    GDALDataset *poDupDataSource = NULL;
2571
    OGRLayer *poLayer = NULL;
2572
2573
    if (pMyVTab->nMyRef == 0)
2574
    {
2575
        poLayer = pMyVTab->poLayer;
2576
    }
2577
    else
2578
    {
2579
        poDupDataSource =
2580
            (GDALDataset *)OGROpen(pMyVTab->poDS->GetName(), FALSE, NULL);
2581
        if (poDupDataSource == NULL)
2582
            return SQLITE_ERROR;
2583
        poLayer = poDupDataSource->GetLayerByName(pMyVTab->poLayer->GetName());
2584
        if (poLayer == NULL)
2585
        {
2586
            delete poDupDataSource;
2587
            return SQLITE_ERROR;
2588
        }
2589
        if (!poLayer->GetLayerDefn()->IsSame(pMyVTab->poLayer->GetLayerDefn()))
2590
        {
2591
            delete poDupDataSource;
2592
            return SQLITE_ERROR;
2593
        }
2594
    }
2595
    pMyVTab->nMyRef++;
2596
2597
    OGR2SQLITESpatialIndex_vtab_cursor *pCursor =
2598
        (OGR2SQLITESpatialIndex_vtab_cursor *)CPLCalloc(
2599
            1, sizeof(OGR2SQLITESpatialIndex_vtab_cursor));
2600
    // We do not need to fill the non-extended fields.
2601
    *ppCursor = (sqlite3_vtab_cursor *)pCursor;
2602
2603
    pCursor->poDupDataSource = poDupDataSource;
2604
    pCursor->poLayer = poLayer;
2605
    pCursor->poLayer->ResetReading();
2606
    pCursor->poFeature = NULL;
2607
2608
    return SQLITE_OK;
2609
}
2610
2611
/************************************************************************/
2612
/*                    OGR2SQLITESpatialIndex_Close()                    */
2613
/************************************************************************/
2614
2615
static int OGR2SQLITESpatialIndex_Close(sqlite3_vtab_cursor *pCursor)
2616
{
2617
    OGR2SQLITESpatialIndex_vtab_cursor *pMyCursor =
2618
        (OGR2SQLITESpatialIndex_vtab_cursor *)pCursor;
2619
    OGR2SQLITESpatialIndex_vtab *pMyVTab = pMyCursor->pVTab;
2620
#ifdef DEBUG_OGR2SQLITE
2621
    CPLDebug("OGR2SQLITE", "Close(%s, %s)", pMyVTab->poDS->GetName(),
2622
             pMyVTab->poLayer->GetName());
2623
#endif
2624
    pMyVTab->nMyRef--;
2625
2626
    delete pMyCursor->poFeature;
2627
    delete pMyCursor->poDupDataSource;
2628
2629
    CPLFree(pCursor);
2630
2631
    return SQLITE_OK;
2632
}
2633
2634
/************************************************************************/
2635
/*                   OGR2SQLITESpatialIndex_Filter()                    */
2636
/************************************************************************/
2637
2638
static int OGR2SQLITESpatialIndex_Filter(sqlite3_vtab_cursor *pCursor,
2639
                                         int idxNum, const char *idxStr,
2640
                                         int argc, sqlite3_value **argv)
2641
{
2642
    OGR2SQLITESpatialIndex_vtab_cursor *pMyCursor =
2643
        (OGR2SQLITESpatialIndex_vtab_cursor *)pCursor;
2644
#ifdef DEBUG_OGR2SQLITE
2645
    CPLDebug("OGR2SQLITE", "Filter");
2646
#endif
2647
2648
    int *panConstraints = (int *)idxStr;
2649
    int nConstraints = panConstraints ? panConstraints[0] : 0;
2650
2651
    if (nConstraints != argc)
2652
        return SQLITE_ERROR;
2653
2654
    double dfMinX = 0.0;
2655
    double dfMaxX = 0.0;
2656
    double dfMinY = 0.0;
2657
    double dfMaxY = 0.0;
2658
    for (int i = 0; i < argc; i++)
2659
    {
2660
        const int nCol = panConstraints[2 * i + 1];
2661
        if (nCol < 0)
2662
            return SQLITE_ERROR;
2663
2664
        double dfVal = 0.0;
2665
        if (sqlite3_value_type(argv[i]) == SQLITE_INTEGER)
2666
            dfVal = sqlite3_value_int64(argv[i]);
2667
        else if (sqlite3_value_type(argv[i]) == SQLITE_FLOAT)
2668
            dfVal = sqlite3_value_double(argv[i]);
2669
        else
2670
            return SQLITE_ERROR;
2671
2672
        if (nCol == 1)
2673
            dfMaxX = dfVal;
2674
        else if (nCol == 2)
2675
            dfMinX = dfVal;
2676
        else if (nCol == 3)
2677
            dfMaxY = dfVal;
2678
        else if (nCol == 4)
2679
            dfMinY = dfVal;
2680
        else
2681
            return SQLITE_ERROR;
2682
    }
2683
2684
#ifdef DEBUG_OGR2SQLITE
2685
    CPLDebug("OGR2SQLITE", "Spatial filter : %.17g, %.17g, %.17g, %.17g",
2686
             dfMinX, dfMinY, dfMaxX, dfMaxY);
2687
#endif
2688
2689
    pMyCursor->poLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
2690
    pMyCursor->poLayer->ResetReading();
2691
2692
    pMyCursor->poFeature = pMyCursor->poLayer->GetNextFeature();
2693
    pMyCursor->bHasSetBounds = false;
2694
2695
    return SQLITE_OK;
2696
}
2697
2698
/************************************************************************/
2699
/*                    OGR2SQLITESpatialIndex_Next()                     */
2700
/************************************************************************/
2701
2702
static int OGR2SQLITESpatialIndex_Next(sqlite3_vtab_cursor *pCursor)
2703
{
2704
    OGR2SQLITESpatialIndex_vtab_cursor *pMyCursor =
2705
        (OGR2SQLITESpatialIndex_vtab_cursor *)pCursor;
2706
#ifdef DEBUG_OGR2SQLITE
2707
    CPLDebug("OGR2SQLITE", "Next");
2708
#endif
2709
2710
    delete pMyCursor->poFeature;
2711
    pMyCursor->poFeature = pMyCursor->poLayer->GetNextFeature();
2712
    pMyCursor->bHasSetBounds = false;
2713
2714
    return SQLITE_OK;
2715
}
2716
2717
/************************************************************************/
2718
/*                     OGR2SQLITESpatialIndex_Eof()                     */
2719
/************************************************************************/
2720
2721
static int OGR2SQLITESpatialIndex_Eof(sqlite3_vtab_cursor *pCursor)
2722
{
2723
    OGR2SQLITESpatialIndex_vtab_cursor *pMyCursor =
2724
        (OGR2SQLITESpatialIndex_vtab_cursor *)pCursor;
2725
#ifdef DEBUG_OGR2SQLITE
2726
    CPLDebug("OGR2SQLITE", "Eof");
2727
#endif
2728
2729
    return pMyCursor->poFeature == NULL;
2730
}
2731
2732
/************************************************************************/
2733
/*                   OGR2SQLITESpatialIndex_Column()                    */
2734
/************************************************************************/
2735
2736
static int OGR2SQLITESpatialIndex_Column(sqlite3_vtab_cursor *pCursor,
2737
                                         sqlite3_context *pContext, int nCol)
2738
{
2739
#ifdef DEBUG_OGR2SQLITE
2740
    CPLDebug("OGR2SQLITE", "Column %d", nCol);
2741
#endif
2742
2743
    OGR2SQLITESpatialIndex_vtab_cursor *pMyCursor =
2744
        (OGR2SQLITESpatialIndex_vtab_cursor *)pCursor;
2745
2746
    OGRFeature *poFeature = pMyCursor->poFeature;
2747
    if (poFeature == NULL)
2748
        return SQLITE_ERROR;
2749
2750
    if (nCol == 0)
2751
    {
2752
        CPLDebug("OGR2SQLITE", "--> FID = " CPL_FRMT_GIB, poFeature->GetFID());
2753
        sqlite3_result_int64(pContext, poFeature->GetFID());
2754
        return SQLITE_OK;
2755
    }
2756
2757
    if (!pMyCursor->bHasSetBounds)
2758
    {
2759
        OGRGeometry *poGeom = poFeature->GetGeometryRef();
2760
        if (poGeom != NULL && !poGeom->IsEmpty())
2761
        {
2762
            OGREnvelope sEnvelope;
2763
            poGeom->getEnvelope(&sEnvelope);
2764
            pMyCursor->bHasSetBounds = true;
2765
            pMyCursor->dfMinX = sEnvelope.MinX;
2766
            pMyCursor->dfMinY = sEnvelope.MinY;
2767
            pMyCursor->dfMaxX = sEnvelope.MaxX;
2768
            pMyCursor->dfMaxY = sEnvelope.MaxY;
2769
        }
2770
    }
2771
    if (!pMyCursor->bHasSetBounds)
2772
    {
2773
        sqlite3_result_null(pContext);
2774
        return SQLITE_OK;
2775
    }
2776
2777
    if (nCol == 1)
2778
    {
2779
        sqlite3_result_double(pContext, pMyCursor->dfMinX);
2780
        return SQLITE_OK;
2781
    }
2782
    if (nCol == 2)
2783
    {
2784
        sqlite3_result_double(pContext, pMyCursor->dfMaxX);
2785
        return SQLITE_OK;
2786
    }
2787
    if (nCol == 3)
2788
    {
2789
        sqlite3_result_double(pContext, pMyCursor->dfMinY);
2790
        return SQLITE_OK;
2791
    }
2792
    if (nCol == 4)
2793
    {
2794
        sqlite3_result_double(pContext, pMyCursor->dfMaxY);
2795
        return SQLITE_OK;
2796
    }
2797
2798
    return SQLITE_ERROR;
2799
}
2800
2801
/************************************************************************/
2802
/*                    OGR2SQLITESpatialIndex_Rowid()                    */
2803
/************************************************************************/
2804
2805
static int OGR2SQLITESpatialIndex_Rowid(sqlite3_vtab_cursor *pCursor,
2806
                                        sqlite3_int64 *pRowid)
2807
{
2808
#ifdef DEBUG_OGR2SQLITE
2809
    CPLDebug("OGR2SQLITE", "Rowid");
2810
#endif
2811
2812
    return SQLITE_ERROR;
2813
}
2814
2815
/************************************************************************/
2816
/*                   OGR2SQLITESpatialIndex_Rename()                    */
2817
/************************************************************************/
2818
2819
static int OGR2SQLITESpatialIndex_Rename(sqlite3_vtab *pVtab, const char *zNew)
2820
{
2821
    // CPLDebug("OGR2SQLITE", "Rename");
2822
    return SQLITE_ERROR;
2823
}
2824
2825
/************************************************************************/
2826
/*                       sOGR2SQLITESpatialIndex                        */
2827
/************************************************************************/
2828
2829
static const struct sqlite3_module sOGR2SQLITESpatialIndex = {
2830
    1,                                    /* iVersion */
2831
    OGR2SQLITESpatialIndex_ConnectCreate, /* xCreate */
2832
    OGR2SQLITESpatialIndex_ConnectCreate, /* xConnect */
2833
    OGR2SQLITESpatialIndex_BestIndex,
2834
    OGR2SQLITESpatialIndex_DisconnectDestroy, /* xDisconnect */
2835
    OGR2SQLITESpatialIndex_DisconnectDestroy, /* xDestroy */
2836
    OGR2SQLITESpatialIndex_Open,
2837
    OGR2SQLITESpatialIndex_Close,
2838
    OGR2SQLITESpatialIndex_Filter,
2839
    OGR2SQLITESpatialIndex_Next,
2840
    OGR2SQLITESpatialIndex_Eof,
2841
    OGR2SQLITESpatialIndex_Column,
2842
    OGR2SQLITESpatialIndex_Rowid,
2843
    NULL, /* xUpdate */
2844
    NULL, /* xBegin */
2845
    NULL, /* xSync */
2846
    NULL, /* xCommit */
2847
    NULL, /* xFindFunctionRollback */
2848
    NULL, /* xFindFunction */
2849
    OGR2SQLITESpatialIndex_Rename};
2850
#endif  // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
2851
2852
/************************************************************************/
2853
/*                               Setup()                                */
2854
/************************************************************************/
2855
2856
#ifndef SQLITE_DETERMINISTIC
2857
#define SQLITE_DETERMINISTIC 0
2858
#endif
2859
2860
#ifndef SQLITE_INNOCUOUS
2861
#define SQLITE_INNOCUOUS 0
2862
#endif
2863
2864
24.0k
#define UTF8_INNOCUOUS (SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS)
2865
2866
int OGR2SQLITEModule::Setup(sqlite3 *hDBIn)
2867
8.01k
{
2868
8.01k
    hDB = hDBIn;
2869
2870
8.01k
    int rc = sqlite3_create_module_v2(hDB, "VirtualOGR", &sOGR2SQLITEModule,
2871
8.01k
                                      this, OGR2SQLITEDestroyModule);
2872
8.01k
    if (rc != SQLITE_OK)
2873
0
        return FALSE;
2874
2875
#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
2876
    rc = sqlite3_create_module(hDB, "VirtualOGRSpatialIndex",
2877
                               &sOGR2SQLITESpatialIndex, this);
2878
    if (rc != SQLITE_OK)
2879
        return FALSE;
2880
#endif  // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
2881
2882
8.01k
    rc = sqlite3_create_function(hDB, "ogr_layer_Extent", 1, SQLITE_ANY, this,
2883
8.01k
                                 OGR2SQLITE_ogr_layer_Extent, nullptr, nullptr);
2884
8.01k
    if (rc != SQLITE_OK)
2885
0
        return FALSE;
2886
2887
8.01k
    rc = sqlite3_create_function(hDB, "ogr_layer_SRID", 1, SQLITE_ANY, this,
2888
8.01k
                                 OGR2SQLITE_ogr_layer_SRID, nullptr, nullptr);
2889
8.01k
    if (rc != SQLITE_OK)
2890
0
        return FALSE;
2891
2892
8.01k
    rc = sqlite3_create_function(hDB, "ogr_layer_GeometryType", 1, SQLITE_ANY,
2893
8.01k
                                 this, OGR2SQLITE_ogr_layer_GeometryType,
2894
8.01k
                                 nullptr, nullptr);
2895
8.01k
    if (rc != SQLITE_OK)
2896
0
        return FALSE;
2897
2898
8.01k
    rc = sqlite3_create_function(hDB, "ogr_layer_FeatureCount", 1, SQLITE_ANY,
2899
8.01k
                                 this, OGR2SQLITE_ogr_layer_FeatureCount,
2900
8.01k
                                 nullptr, nullptr);
2901
8.01k
    if (rc != SQLITE_OK)
2902
0
        return FALSE;
2903
2904
    // X,Y,table_name
2905
8.01k
    sqlite3_create_function(hDB, "ST_Hilbert", 2 + 1, UTF8_INNOCUOUS, this,
2906
8.01k
                            OGR2SQLITE_ST_Hilbert_X_Y_TableName, nullptr,
2907
8.01k
                            nullptr);
2908
2909
    // geometry,minX,minY,maxX,maxY
2910
8.01k
    sqlite3_create_function(hDB, "ST_Hilbert", 1 + 4, UTF8_INNOCUOUS, nullptr,
2911
8.01k
                            OGR2SQLITE_ST_Hilbert_Geom_BBOX, nullptr, nullptr);
2912
2913
    // geometry,table_name
2914
8.01k
    sqlite3_create_function(hDB, "ST_Hilbert", 1 + 1, UTF8_INNOCUOUS, this,
2915
8.01k
                            OGR2SQLITE_ST_Hilbert_Geom_TableName, nullptr,
2916
8.01k
                            nullptr);
2917
2918
8.01k
    SetHandleSQLFunctions(OGRSQLiteRegisterSQLFunctions(hDB));
2919
2920
8.01k
    return TRUE;
2921
8.01k
}
2922
2923
/************************************************************************/
2924
/*                          OGR2SQLITE_Setup()                          */
2925
/************************************************************************/
2926
2927
OGR2SQLITEModule *OGR2SQLITE_Setup(GDALDataset *poDS,
2928
                                   OGRSQLiteDataSource *poSQLiteDS)
2929
739
{
2930
739
    if (sqlite3_api == nullptr)
2931
0
    {
2932
        // Unlikely to happen. One theoretical possibility would be that:
2933
        // - thread A calls OGR2SQLITE_Register(), which calls sqlite3_auto_extension((void (*)(void))OGR2SQLITE_static_register)
2934
        // - thread B calls sqlite3_reset_auto_extension()
2935
        // - thread A opens a sqlite3 handle (which normally would have caused OGR2SQLITE_static_register() to be called, and setting the sqlite3_api static variable, without prior B intervention.
2936
        // - thread A calls us (OGR2SQLITE_Setup()) with sqlite3_api still set to its initial nullptr value
2937
0
        CPLError(CE_Failure, CPLE_AppDefined,
2938
0
                 "OGR2SQLITE_Setup() failed due to sqlite3_api == nullptr");
2939
0
        return nullptr;
2940
0
    }
2941
739
    OGR2SQLITEModule *poModule = new OGR2SQLITEModule();
2942
739
    poModule->Setup(poDS, poSQLiteDS);
2943
739
    return poModule;
2944
739
}
2945
2946
/************************************************************************/
2947
/*                  OGR2SQLITE_SetCaseSensitiveLike()                   */
2948
/************************************************************************/
2949
2950
void OGR2SQLITE_SetCaseSensitiveLike(OGR2SQLITEModule *poModule, bool b)
2951
0
{
2952
0
    poModule->SetCaseSensitiveLike(b);
2953
0
}
2954
2955
/************************************************************************/
2956
/*                       OGR2SQLITE_AddExtraDS()                        */
2957
/************************************************************************/
2958
2959
int OGR2SQLITE_AddExtraDS(OGR2SQLITEModule *poModule, GDALDataset *poDS)
2960
0
{
2961
0
    return poModule->AddExtraDS(poDS);
2962
0
}
2963
2964
#ifdef VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
2965
2966
/************************************************************************/
2967
/*                       sqlite3_extension_init()                       */
2968
/************************************************************************/
2969
2970
CPL_C_START
2971
int CPL_DLL sqlite3_extension_init(sqlite3 *hDB, char **pzErrMsg,
2972
                                   const sqlite3_api_routines *pApi);
2973
CPL_C_END
2974
2975
/* Entry point for dynamically loaded extension (typically called by
2976
 * load_extension()) */
2977
int sqlite3_extension_init(sqlite3 *hDB, char **pzErrMsg,
2978
                           const sqlite3_api_routines *pApi)
2979
0
{
2980
0
    CPLDebug("OGR", "OGR SQLite extension loading...");
2981
2982
0
    SQLITE_EXTENSION_INIT2(pApi);
2983
2984
    // Super hacky: this forces the malloc subsystem to be initialized.
2985
    // Normally we would not need to do this, but libgdal.so links against
2986
    // libsqlite3.so If doing SELECT load_extension('libgdal.so') from the
2987
    // sqlite3 console binary which statically links sqlite3, we might get 2
2988
    // copies of sqlite3 into memory: the static one from the sqlite3 binary,
2989
    // and the shared one linked by libgdal.so If the sqlite3_create_module_v2()
2990
    // function executed happens to be the one of the shared libsqlite3 and not
2991
    // the one of the sqlite3 binary, then the initialization of the malloc
2992
    // subsystem might not have been done. This demonstrates that our approach
2993
    // of having libgdal.so to link to libsqlite3 and be a sqlite3 extension is
2994
    // very fragile. But there aren't many other alternatives... There's no
2995
    // problem for applications (including the sqlite3 binary) that are built
2996
    // against a shared libsqlite3, since only one copy gets loaded.
2997
0
    sqlite3_free(sqlite3_malloc(1));
2998
2999
0
    *pzErrMsg = nullptr;
3000
3001
    /* Check if we have been already loaded. */
3002
    /* This is to avoid 'ogrinfo :memory: --config OGR_SQLITE_LOAD_EXTENSIONS
3003
     * libgdal.so' to crash */
3004
    /* since it would run OGR2SQLITEModule::Setup() first with
3005
     * OGR2SQLITE_static_register() */
3006
    /* and then through here. */
3007
0
    int rc =
3008
0
        sqlite3_exec(hDB, "SELECT ogr_version()", nullptr, nullptr, nullptr);
3009
3010
    /* Reset error flag */
3011
0
    sqlite3_exec(hDB, "SELECT 1", nullptr, nullptr, nullptr);
3012
3013
0
    if (rc == SQLITE_OK)
3014
0
    {
3015
3016
0
        CPLDebug("OGR", "... OGR virtual OGR already loaded !");
3017
0
        *pzErrMsg = sqlite3_mprintf(
3018
0
            "Cannot load libgdal as an extension from a OGR SQLite datasource");
3019
0
        return SQLITE_ERROR;
3020
0
    }
3021
3022
0
    OGRRegisterAll();
3023
3024
0
    OGR2SQLITEModule *poModule = new OGR2SQLITEModule();
3025
0
    if (poModule->Setup(hDB))
3026
0
    {
3027
0
        CPLDebug("OGR", "OGR SQLite extension loaded");
3028
0
        return SQLITE_OK;
3029
0
    }
3030
0
    else
3031
0
        return SQLITE_ERROR;
3032
0
}
3033
3034
#endif  // VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
3035
3036
/************************************************************************/
3037
/*                     OGR2SQLITE_static_register()                     */
3038
/************************************************************************/
3039
3040
#ifndef _WIN32
3041
extern const struct sqlite3_api_routines OGRSQLITE_static_routines;
3042
#endif
3043
3044
int OGR2SQLITE_static_register(sqlite3 *hDB, char **pzErrMsg, void *_pApi)
3045
8.17k
{
3046
8.17k
    const sqlite3_api_routines *pApi =
3047
8.17k
        static_cast<const sqlite3_api_routines *>(_pApi);
3048
8.17k
#ifndef _WIN32
3049
8.17k
    if ((pApi == nullptr) || (pApi->create_module == nullptr))
3050
0
    {
3051
0
        pApi = &OGRSQLITE_static_routines;
3052
0
    }
3053
8.17k
#endif
3054
8.17k
    SQLITE_EXTENSION_INIT2(pApi);
3055
3056
8.17k
    *pzErrMsg = nullptr;
3057
3058
    /* The config option is turned off by ogrsqliteexecutesql.cpp that needs */
3059
    /* to create a custom module */
3060
8.17k
    if (CPLTestBool(CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "YES")))
3061
7.27k
    {
3062
        /* Can happen if SQLite is compiled with SQLITE_OMIT_LOAD_EXTENSION
3063
         * (with SQLite 3.6.10 for example) */
3064
        /* We return here OK since it is not vital for regular SQLite databases
3065
         */
3066
        /* to load the OGR SQL functions */
3067
7.27k
        if (pApi->create_module == nullptr)
3068
0
            return SQLITE_OK;
3069
3070
7.27k
        OGR2SQLITEModule *poModule = new OGR2SQLITEModule();
3071
7.27k
        return poModule->Setup(hDB) ? SQLITE_OK : SQLITE_ERROR;
3072
7.27k
    }
3073
898
    else
3074
898
    {
3075
        /* Can happen if SQLite is compiled with SQLITE_OMIT_LOAD_EXTENSION
3076
         * (with SQLite 3.6.10 for example) */
3077
        /* We return fail since Setup() will later be called, and crash */
3078
        /* if create_module isn't available */
3079
898
        if (pApi->create_module == nullptr)
3080
0
            return SQLITE_ERROR;
3081
898
    }
3082
3083
898
    return SQLITE_OK;
3084
8.17k
}
3085
3086
#endif  // HAVE_SQLITE3EXT_H