LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitevirtualogr.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 793 892 88.9 %
Date: 2024-11-25 13:07:18 Functions: 42 43 97.7 %

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

Generated by: LCOV version 1.14