LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitevirtualogr.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 876 995 88.0 %
Date: 2026-09-05 00:44:35 Functions: 48 49 98.0 %

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

Generated by: LCOV version 1.14