LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitevirtualogr.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 798 897 89.0 %
Date: 2025-05-31 00:00:17 Functions: 42 43 97.7 %

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

Generated by: LCOV version 1.14