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

Generated by: LCOV version 1.14