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

Generated by: LCOV version 1.14