LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitesqlfunctions.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 279 339 82.3 %
Date: 2024-11-25 13:07:18 Functions: 16 17 94.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Extension SQL functions
       5             :  * Author:   Even Rouault, even dot rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2012-2013, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : /* WARNING: VERY IMPORTANT NOTE: This file MUST not be directly compiled as */
      14             : /* a standalone object. It must be included from ogrsqlitevirtualogr.cpp */
      15             : #ifndef COMPILATION_ALLOWED
      16             : #error See comment in file
      17             : #endif
      18             : 
      19             : #include "ogrsqlitesqlfunctions.h"
      20             : #include "ogr_geocoding.h"
      21             : 
      22             : #include "ogr_swq.h"
      23             : 
      24             : #include <limits>
      25             : 
      26             : #undef SQLITE_STATIC
      27             : #define SQLITE_STATIC ((sqlite3_destructor_type) nullptr)
      28             : 
      29             : #ifndef HAVE_SPATIALITE
      30             : #define MINIMAL_SPATIAL_FUNCTIONS
      31             : #endif
      32             : 
      33             : #define DEFINE_OGRSQLiteExtensionData_GetTransform
      34             : #include "ogrsqlitesqlfunctionscommon.cpp"
      35             : 
      36             : /************************************************************************/
      37             : /*                        OGR2SQLITE_ogr_version()                      */
      38             : /************************************************************************/
      39             : 
      40           4 : static void OGR2SQLITE_ogr_version(sqlite3_context *pContext, int argc,
      41             :                                    sqlite3_value **argv)
      42             : {
      43           4 :     if (argc == 0 || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
      44             :     {
      45           4 :         sqlite3_result_text(pContext, GDALVersionInfo("RELEASE_NAME"), -1,
      46             :                             SQLITE_TRANSIENT);
      47             :     }
      48             :     else
      49             :     {
      50           0 :         sqlite3_result_text(pContext,
      51             :                             GDALVersionInfo(reinterpret_cast<const char *>(
      52           0 :                                 sqlite3_value_text(argv[0]))),
      53             :                             -1, SQLITE_TRANSIENT);
      54             :     }
      55           4 : }
      56             : 
      57             : /************************************************************************/
      58             : /*                          OGR2SQLITE_Transform()                      */
      59             : /************************************************************************/
      60             : 
      61           0 : static void OGR2SQLITE_Transform(sqlite3_context *pContext, int argc,
      62             :                                  sqlite3_value **argv)
      63             : {
      64           0 :     if (argc != 3)
      65             :     {
      66           0 :         sqlite3_result_null(pContext);
      67           0 :         return;
      68             :     }
      69             : 
      70           0 :     if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
      71             :     {
      72           0 :         sqlite3_result_null(pContext);
      73           0 :         return;
      74             :     }
      75             : 
      76           0 :     if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
      77             :     {
      78           0 :         sqlite3_result_null(pContext);
      79           0 :         return;
      80             :     }
      81             : 
      82           0 :     if (sqlite3_value_type(argv[2]) != SQLITE_INTEGER)
      83             :     {
      84           0 :         sqlite3_result_null(pContext);
      85           0 :         return;
      86             :     }
      87             : 
      88           0 :     int nSrcSRSId = sqlite3_value_int(argv[1]);
      89           0 :     int nDstSRSId = sqlite3_value_int(argv[2]);
      90             : 
      91             :     OGRSQLiteExtensionData *poModule =
      92           0 :         static_cast<OGRSQLiteExtensionData *>(sqlite3_user_data(pContext));
      93             :     OGRCoordinateTransformation *poCT =
      94           0 :         poModule->GetTransform(nSrcSRSId, nDstSRSId);
      95           0 :     if (poCT == nullptr)
      96             :     {
      97           0 :         sqlite3_result_null(pContext);
      98           0 :         return;
      99             :     }
     100             : 
     101             :     const GByte *pabySLBLOB =
     102           0 :         reinterpret_cast<const GByte *>(sqlite3_value_blob(argv[0]));
     103           0 :     int nBLOBLen = sqlite3_value_bytes(argv[0]);
     104           0 :     OGRGeometry *poGeom = nullptr;
     105           0 :     GByte *pabyOutBlob = nullptr;
     106           0 :     int nOutBlobLen = 0;
     107           0 :     if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(pabySLBLOB, nBLOBLen,
     108           0 :                                                  &poGeom) == OGRERR_NONE &&
     109           0 :         poGeom->transform(poCT) == OGRERR_NONE &&
     110           0 :         OGRSQLiteLayer::ExportSpatiaLiteGeometry(poGeom, nDstSRSId, wkbNDR,
     111             :                                                  FALSE, FALSE, &pabyOutBlob,
     112             :                                                  &nOutBlobLen) == OGRERR_NONE)
     113             :     {
     114           0 :         sqlite3_result_blob(pContext, pabyOutBlob, nOutBlobLen, CPLFree);
     115             :     }
     116             :     else
     117             :     {
     118           0 :         sqlite3_result_null(pContext);
     119             :     }
     120           0 :     delete poGeom;
     121             : }
     122             : 
     123             : /************************************************************************/
     124             : /*                       OGR2SQLITE_ogr_deflate()                       */
     125             : /************************************************************************/
     126             : 
     127           4 : static void OGR2SQLITE_ogr_deflate(sqlite3_context *pContext, int argc,
     128             :                                    sqlite3_value **argv)
     129             : {
     130           4 :     int nLevel = -1;
     131           8 :     if (!(argc == 1 || argc == 2) ||
     132           4 :         !(sqlite3_value_type(argv[0]) == SQLITE_TEXT ||
     133           1 :           sqlite3_value_type(argv[0]) == SQLITE_BLOB))
     134             :     {
     135           0 :         sqlite3_result_null(pContext);
     136           0 :         return;
     137             :     }
     138           4 :     if (argc == 2)
     139             :     {
     140           2 :         if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
     141             :         {
     142           1 :             sqlite3_result_null(pContext);
     143           1 :             return;
     144             :         }
     145           1 :         nLevel = sqlite3_value_int(argv[1]);
     146             :     }
     147             : 
     148           3 :     size_t nOutBytes = 0;
     149           3 :     void *pOut = nullptr;
     150           3 :     if (sqlite3_value_type(argv[0]) == SQLITE_TEXT)
     151             :     {
     152             :         const char *pszVal =
     153           2 :             reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     154           2 :         pOut = CPLZLibDeflate(pszVal, strlen(pszVal) + 1, nLevel, nullptr, 0,
     155             :                               &nOutBytes);
     156             :     }
     157             :     else
     158             :     {
     159           1 :         const void *pSrc = sqlite3_value_blob(argv[0]);
     160           1 :         int nLen = sqlite3_value_bytes(argv[0]);
     161           1 :         pOut = CPLZLibDeflate(pSrc, nLen, nLevel, nullptr, 0, &nOutBytes);
     162             :     }
     163           3 :     if (pOut != nullptr)
     164             :     {
     165           3 :         sqlite3_result_blob(pContext, pOut, static_cast<int>(nOutBytes),
     166             :                             VSIFree);
     167             :     }
     168             :     else
     169             :     {
     170           0 :         sqlite3_result_null(pContext);
     171             :     }
     172             : 
     173           3 :     return;
     174             : }
     175             : 
     176             : /************************************************************************/
     177             : /*                       OGR2SQLITE_ogr_inflate()                       */
     178             : /************************************************************************/
     179             : 
     180           5 : static void OGR2SQLITE_ogr_inflate(sqlite3_context *pContext, int argc,
     181             :                                    sqlite3_value **argv)
     182             : {
     183           5 :     if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_BLOB)
     184             :     {
     185           1 :         sqlite3_result_null(pContext);
     186           1 :         return;
     187             :     }
     188             : 
     189           4 :     size_t nOutBytes = 0;
     190             : 
     191           4 :     const void *pSrc = sqlite3_value_blob(argv[0]);
     192           4 :     int nLen = sqlite3_value_bytes(argv[0]);
     193           4 :     void *pOut = CPLZLibInflate(pSrc, nLen, nullptr, 0, &nOutBytes);
     194             : 
     195           4 :     if (pOut != nullptr)
     196             :     {
     197           3 :         sqlite3_result_blob(pContext, pOut, static_cast<int>(nOutBytes),
     198             :                             VSIFree);
     199             :     }
     200             :     else
     201             :     {
     202           1 :         sqlite3_result_null(pContext);
     203             :     }
     204             : 
     205           4 :     return;
     206             : }
     207             : 
     208             : /************************************************************************/
     209             : /*                     OGR2SQLITE_ogr_geocode_set_result()              */
     210             : /************************************************************************/
     211             : 
     212         112 : static void OGR2SQLITE_ogr_geocode_set_result(sqlite3_context *pContext,
     213             :                                               OGRLayerH hLayer,
     214             :                                               const char *pszField)
     215             : {
     216         112 :     if (hLayer == nullptr)
     217           8 :         sqlite3_result_null(pContext);
     218             :     else
     219             :     {
     220         104 :         OGRLayer *poLayer = OGRLayer::FromHandle(hLayer);
     221         104 :         OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
     222         104 :         OGRFeature *poFeature = poLayer->GetNextFeature();
     223             :         int nIdx;
     224         104 :         if (poFeature == nullptr)
     225           8 :             sqlite3_result_null(pContext);
     226         128 :         else if (strcmp(pszField, "geometry") == 0 &&
     227          32 :                  poFeature->GetGeometryRef() != nullptr)
     228             :         {
     229          32 :             GByte *pabyGeomBLOB = nullptr;
     230          32 :             int nGeomBLOBLen = 0;
     231          64 :             if (OGRSQLiteLayer::ExportSpatiaLiteGeometry(
     232          32 :                     poFeature->GetGeometryRef(), 4326, wkbNDR, FALSE, FALSE,
     233          32 :                     &pabyGeomBLOB, &nGeomBLOBLen) != OGRERR_NONE)
     234             :             {
     235           0 :                 sqlite3_result_null(pContext);
     236             :             }
     237             :             else
     238             :             {
     239          32 :                 sqlite3_result_blob(pContext, pabyGeomBLOB, nGeomBLOBLen,
     240             :                                     CPLFree);
     241             :             }
     242             :         }
     243         126 :         else if ((nIdx = poFDefn->GetFieldIndex(pszField)) >= 0 &&
     244          62 :                  poFeature->IsFieldSetAndNotNull(nIdx))
     245             :         {
     246          62 :             OGRFieldType eType = poFDefn->GetFieldDefn(nIdx)->GetType();
     247          62 :             if (eType == OFTInteger)
     248           0 :                 sqlite3_result_int(pContext,
     249             :                                    poFeature->GetFieldAsInteger(nIdx));
     250          62 :             else if (eType == OFTInteger64)
     251           0 :                 sqlite3_result_int64(pContext,
     252             :                                      poFeature->GetFieldAsInteger64(nIdx));
     253          62 :             else if (eType == OFTReal)
     254           0 :                 sqlite3_result_double(pContext,
     255             :                                       poFeature->GetFieldAsDouble(nIdx));
     256             :             else
     257          62 :                 sqlite3_result_text(pContext, poFeature->GetFieldAsString(nIdx),
     258             :                                     -1, SQLITE_TRANSIENT);
     259             :         }
     260             :         else
     261           2 :             sqlite3_result_null(pContext);
     262         104 :         delete poFeature;
     263         104 :         OGRGeocodeFreeResult(hLayer);
     264             :     }
     265         112 : }
     266             : 
     267             : /************************************************************************/
     268             : /*                       OGR2SQLITE_ogr_geocode()                       */
     269             : /************************************************************************/
     270             : 
     271          80 : static void OGR2SQLITE_ogr_geocode(sqlite3_context *pContext, int argc,
     272             :                                    sqlite3_value **argv)
     273             : {
     274             :     OGRSQLiteExtensionData *poModule =
     275          80 :         static_cast<OGRSQLiteExtensionData *>(sqlite3_user_data(pContext));
     276             : 
     277          80 :     if (argc < 1 || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
     278             :     {
     279          16 :         sqlite3_result_null(pContext);
     280          16 :         return;
     281             :     }
     282             :     const char *pszQuery =
     283          64 :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     284             : 
     285         128 :     CPLString osField = "geometry";
     286          64 :     if (argc >= 2 && sqlite3_value_type(argv[1]) == SQLITE_TEXT)
     287             :     {
     288          32 :         osField = reinterpret_cast<const char *>(sqlite3_value_text(argv[1]));
     289             :     }
     290             : 
     291          64 :     char **papszOptions = nullptr;
     292          72 :     for (int i = 2; i < argc; i++)
     293             :     {
     294           8 :         if (sqlite3_value_type(argv[i]) == SQLITE_TEXT)
     295             :         {
     296           0 :             papszOptions = CSLAddString(
     297             :                 papszOptions,
     298           0 :                 reinterpret_cast<const char *>(sqlite3_value_text(argv[i])));
     299             :         }
     300             :     }
     301             : 
     302          64 :     OGRGeocodingSessionH hSession = poModule->GetGeocodingSession();
     303          64 :     if (hSession == nullptr)
     304             :     {
     305          64 :         hSession = OGRGeocodeCreateSession(papszOptions);
     306          64 :         if (hSession == nullptr)
     307             :         {
     308           0 :             sqlite3_result_null(pContext);
     309           0 :             CSLDestroy(papszOptions);
     310           0 :             return;
     311             :         }
     312          64 :         poModule->SetGeocodingSession(hSession);
     313             :     }
     314             : 
     315          64 :     if (osField == "raw")
     316           8 :         papszOptions = CSLAddString(papszOptions, "RAW_FEATURE=YES");
     317             : 
     318          64 :     if (CSLFindString(papszOptions, "LIMIT") == -1)
     319          64 :         papszOptions = CSLAddString(papszOptions, "LIMIT=1");
     320             : 
     321          64 :     OGRLayerH hLayer = OGRGeocode(hSession, pszQuery, nullptr, papszOptions);
     322             : 
     323          64 :     OGR2SQLITE_ogr_geocode_set_result(pContext, hLayer, osField);
     324             : 
     325          64 :     CSLDestroy(papszOptions);
     326             : 
     327          64 :     return;
     328             : }
     329             : 
     330             : /************************************************************************/
     331             : /*                    OGR2SQLITE_GetValAsDouble()                       */
     332             : /************************************************************************/
     333             : 
     334         144 : static double OGR2SQLITE_GetValAsDouble(sqlite3_value *val, int *pbGotVal)
     335             : {
     336         144 :     switch (sqlite3_value_type(val))
     337             :     {
     338          32 :         case SQLITE_FLOAT:
     339          32 :             if (pbGotVal)
     340          32 :                 *pbGotVal = TRUE;
     341          32 :             return sqlite3_value_double(val);
     342             : 
     343          64 :         case SQLITE_INTEGER:
     344          64 :             if (pbGotVal)
     345          64 :                 *pbGotVal = TRUE;
     346          64 :             return static_cast<double>(sqlite3_value_int64(val));
     347             : 
     348          48 :         default:
     349          48 :             if (pbGotVal)
     350          48 :                 *pbGotVal = FALSE;
     351          48 :             return 0.0;
     352             :     }
     353             : }
     354             : 
     355             : /************************************************************************/
     356             : /*                      OGR2SQLITE_GetGeom()                            */
     357             : /************************************************************************/
     358             : 
     359             : static std::unique_ptr<OGRGeometry>
     360          25 : OGR2SQLITE_GetGeom(sqlite3_context * /*pContext*/, int /* argc */,
     361             :                    sqlite3_value **argv, int *pnSRSId)
     362             : {
     363          25 :     if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
     364             :     {
     365           2 :         return nullptr;
     366             :     }
     367             : 
     368             :     const GByte *pabySLBLOB =
     369          23 :         reinterpret_cast<const GByte *>(sqlite3_value_blob(argv[0]));
     370          23 :     int nBLOBLen = sqlite3_value_bytes(argv[0]);
     371          23 :     OGRGeometry *poGeom = nullptr;
     372          23 :     if (OGRSQLiteLayer::ImportSpatiaLiteGeometry(pabySLBLOB, nBLOBLen, &poGeom,
     373          23 :                                                  pnSRSId) != OGRERR_NONE)
     374             :     {
     375           1 :         delete poGeom;
     376           1 :         return nullptr;
     377             :     }
     378             : 
     379          22 :     return std::unique_ptr<OGRGeometry>(poGeom);
     380             : }
     381             : 
     382             : /************************************************************************/
     383             : /*                   OGR2SQLITE_ogr_geocode_reverse()                   */
     384             : /************************************************************************/
     385             : 
     386          96 : static void OGR2SQLITE_ogr_geocode_reverse(sqlite3_context *pContext, int argc,
     387             :                                            sqlite3_value **argv)
     388             : {
     389             :     OGRSQLiteExtensionData *poModule =
     390          96 :         static_cast<OGRSQLiteExtensionData *>(sqlite3_user_data(pContext));
     391             : 
     392          96 :     double dfLon = 0.0;
     393          96 :     double dfLat = 0.0;
     394          96 :     int iAfterGeomIdx = 0;
     395          96 :     int bGotLon = FALSE;
     396          96 :     int bGotLat = FALSE;
     397             : 
     398          96 :     if (argc >= 2)
     399             :     {
     400          72 :         dfLon = OGR2SQLITE_GetValAsDouble(argv[0], &bGotLon);
     401          72 :         dfLat = OGR2SQLITE_GetValAsDouble(argv[1], &bGotLat);
     402             :     }
     403             : 
     404         128 :     if (argc >= 3 && bGotLon && bGotLat &&
     405          32 :         sqlite3_value_type(argv[2]) == SQLITE_TEXT)
     406             :     {
     407          32 :         iAfterGeomIdx = 2;
     408             :     }
     409          88 :     else if (argc >= 2 && sqlite3_value_type(argv[0]) == SQLITE_BLOB &&
     410          24 :              sqlite3_value_type(argv[1]) == SQLITE_TEXT)
     411             :     {
     412          16 :         auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
     413          32 :         if (poGeom != nullptr &&
     414          16 :             wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     415             :         {
     416          16 :             const OGRPoint *poPoint = poGeom->toPoint();
     417          16 :             dfLon = poPoint->getX();
     418          16 :             dfLat = poPoint->getY();
     419             :         }
     420             :         else
     421             :         {
     422           0 :             sqlite3_result_null(pContext);
     423           0 :             return;
     424             :         }
     425          16 :         iAfterGeomIdx = 1;
     426             :     }
     427             :     else
     428             :     {
     429          48 :         sqlite3_result_null(pContext);
     430          48 :         return;
     431             :     }
     432             : 
     433             :     const char *pszField =
     434          48 :         reinterpret_cast<const char *>(sqlite3_value_text(argv[iAfterGeomIdx]));
     435             : 
     436          48 :     char **papszOptions = nullptr;
     437          64 :     for (int i = iAfterGeomIdx + 1; i < argc; i++)
     438             :     {
     439          16 :         if (sqlite3_value_type(argv[i]) == SQLITE_TEXT)
     440             :         {
     441          16 :             papszOptions = CSLAddString(
     442             :                 papszOptions,
     443          16 :                 reinterpret_cast<const char *>(sqlite3_value_text(argv[i])));
     444             :         }
     445             :     }
     446             : 
     447          48 :     OGRGeocodingSessionH hSession = poModule->GetGeocodingSession();
     448          48 :     if (hSession == nullptr)
     449             :     {
     450          48 :         hSession = OGRGeocodeCreateSession(papszOptions);
     451          48 :         if (hSession == nullptr)
     452             :         {
     453           0 :             sqlite3_result_null(pContext);
     454           0 :             CSLDestroy(papszOptions);
     455           0 :             return;
     456             :         }
     457          48 :         poModule->SetGeocodingSession(hSession);
     458             :     }
     459             : 
     460          48 :     if (strcmp(pszField, "raw") == 0)
     461           8 :         papszOptions = CSLAddString(papszOptions, "RAW_FEATURE=YES");
     462             : 
     463          48 :     OGRLayerH hLayer = OGRGeocodeReverse(hSession, dfLon, dfLat, papszOptions);
     464             : 
     465          48 :     OGR2SQLITE_ogr_geocode_set_result(pContext, hLayer, pszField);
     466             : 
     467          48 :     CSLDestroy(papszOptions);
     468             : 
     469          48 :     return;
     470             : }
     471             : 
     472             : /************************************************************************/
     473             : /*               OGR2SQLITE_ogr_datasource_load_layers()                */
     474             : /************************************************************************/
     475             : 
     476           8 : static void OGR2SQLITE_ogr_datasource_load_layers(sqlite3_context *pContext,
     477             :                                                   int argc,
     478             :                                                   sqlite3_value **argv)
     479             : {
     480           8 :     sqlite3 *hDB = static_cast<sqlite3 *>(sqlite3_user_data(pContext));
     481             : 
     482           8 :     if ((argc < 1 || argc > 3) || sqlite3_value_type(argv[0]) != SQLITE_TEXT)
     483             :     {
     484           1 :         sqlite3_result_int(pContext, 0);
     485           4 :         return;
     486             :     }
     487             :     const char *pszDataSource =
     488           7 :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     489             : 
     490           7 :     int bUpdate = FALSE;
     491           7 :     if (argc >= 2)
     492             :     {
     493           4 :         if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER)
     494             :         {
     495           1 :             sqlite3_result_int(pContext, 0);
     496           1 :             return;
     497             :         }
     498           3 :         bUpdate = sqlite3_value_int(argv[1]);
     499             :     }
     500             : 
     501           6 :     const char *pszPrefix = nullptr;
     502           6 :     if (argc >= 3)
     503             :     {
     504           2 :         if (sqlite3_value_type(argv[2]) != SQLITE_TEXT)
     505             :         {
     506           1 :             sqlite3_result_int(pContext, 0);
     507           1 :             return;
     508             :         }
     509           1 :         pszPrefix = reinterpret_cast<const char *>(sqlite3_value_text(argv[2]));
     510             :     }
     511             : 
     512             :     auto poDS = std::unique_ptr<GDALDataset>(GDALDataset::Open(
     513             :         pszDataSource,
     514             :         GDAL_OF_VECTOR | (bUpdate ? GDAL_OF_UPDATE : GDAL_OF_READONLY), nullptr,
     515           5 :         nullptr, nullptr));
     516           5 :     if (poDS == nullptr)
     517             :     {
     518           1 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszDataSource);
     519           1 :         sqlite3_result_int(pContext, 0);
     520           1 :         return;
     521             :     }
     522             : 
     523           8 :     CPLString osEscapedDataSource = SQLEscapeLiteral(pszDataSource);
     524           8 :     for (int i = 0; i < poDS->GetLayerCount(); i++)
     525             :     {
     526           4 :         const char *pszLayerName = poDS->GetLayer(i)->GetName();
     527           8 :         CPLString osEscapedLayerName = SQLEscapeLiteral(pszLayerName);
     528           8 :         CPLString osTableName;
     529           4 :         if (pszPrefix != nullptr)
     530             :         {
     531           1 :             osTableName = pszPrefix;
     532           1 :             osTableName += "_";
     533           1 :             osTableName += SQLEscapeName(pszLayerName);
     534             :         }
     535             :         else
     536             :         {
     537           3 :             osTableName = SQLEscapeName(pszLayerName);
     538             :         }
     539             : 
     540           4 :         SQLCommand(
     541             :             hDB,
     542             :             CPLSPrintf(
     543             :                 "CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR('%s', %d, '%s')",
     544             :                 osTableName.c_str(), osEscapedDataSource.c_str(), bUpdate,
     545             :                 osEscapedLayerName.c_str()));
     546             :     }
     547             : 
     548           4 :     sqlite3_result_int(pContext, 1);
     549             : }
     550             : 
     551             : #ifdef notdef
     552             : /************************************************************************/
     553             : /*                  OGR2SQLITE_ogr_GetConfigOption()                    */
     554             : /************************************************************************/
     555             : 
     556             : static void OGR2SQLITE_ogr_GetConfigOption(sqlite3_context *pContext, int argc,
     557             :                                            sqlite3_value **argv)
     558             : {
     559             :     if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
     560             :     {
     561             :         sqlite3_result_null(pContext);
     562             :         return;
     563             :     }
     564             : 
     565             :     const char *pszKey =
     566             :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     567             :     const char *pszVal = CPLGetConfigOption(pszKey, nullptr);
     568             :     if (pszVal == nullptr)
     569             :         sqlite3_result_null(pContext);
     570             :     else
     571             :         sqlite3_result_text(pContext, pszVal, -1, SQLITE_TRANSIENT);
     572             : }
     573             : 
     574             : /************************************************************************/
     575             : /*                  OGR2SQLITE_ogr_SetConfigOption()                    */
     576             : /************************************************************************/
     577             : 
     578             : static void OGR2SQLITE_ogr_SetConfigOption(sqlite3_context *pContext, int argc,
     579             :                                            sqlite3_value **argv)
     580             : {
     581             :     if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
     582             :     {
     583             :         sqlite3_result_null(pContext);
     584             :         return;
     585             :     }
     586             :     if (sqlite3_value_type(argv[1]) != SQLITE_TEXT &&
     587             :         sqlite3_value_type(argv[1]) != SQLITE_NULL)
     588             :     {
     589             :         sqlite3_result_null(pContext);
     590             :         return;
     591             :     }
     592             : 
     593             :     const char *pszKey =
     594             :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     595             :     const char *pszVal =
     596             :         (sqlite3_value_type(argv[1]) == SQLITE_TEXT)
     597             :             ? reinterpret_cast<const char *>(sqlite3_value_text(argv[1]))
     598             :             : nullptr;
     599             :     CPLSetConfigOption(pszKey, pszVal);
     600             :     sqlite3_result_null(pContext);
     601             : }
     602             : #endif  // notdef
     603             : 
     604             : /************************************************************************/
     605             : /*                OGR2SQLITE_SetGeom_AndDestroy()                       */
     606             : /************************************************************************/
     607             : 
     608           1 : static void OGR2SQLITE_SetGeom_AndDestroy(sqlite3_context *pContext,
     609             :                                           OGRGeometry *poGeom, int nSRSId)
     610             : {
     611           1 :     GByte *pabySLBLOB = nullptr;
     612           1 :     int nBLOBLen = 0;
     613           1 :     if (poGeom != nullptr && OGRSQLiteLayer::ExportSpatiaLiteGeometry(
     614             :                                  poGeom, nSRSId, wkbNDR, FALSE, FALSE,
     615             :                                  &pabySLBLOB, &nBLOBLen) == OGRERR_NONE)
     616             :     {
     617           1 :         sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
     618             :     }
     619             :     else
     620             :     {
     621           0 :         sqlite3_result_null(pContext);
     622             :     }
     623           1 :     delete poGeom;
     624           1 : }
     625             : 
     626             : /************************************************************************/
     627             : /*                     OGR2SQLITE_ST_GeodesicArea()                     */
     628             : /************************************************************************/
     629             : 
     630           4 : static void OGR2SQLITE_ST_GeodesicArea(sqlite3_context *pContext, int argc,
     631             :                                        sqlite3_value **argv)
     632             : {
     633           4 :     if (sqlite3_value_int(argv[1]) != 1)
     634             :     {
     635           1 :         CPLError(CE_Warning, CPLE_NotSupported,
     636             :                  "ST_Area(geom, use_ellipsoid) is only supported for "
     637             :                  "use_ellipsoid = 1");
     638             :     }
     639             : 
     640           4 :     int nSRSId = -1;
     641           4 :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
     642           4 :     if (poGeom != nullptr)
     643             :     {
     644           3 :         OGRSpatialReference oSRS;
     645           3 :         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     646           3 :         if (nSRSId > 0)
     647             :         {
     648           2 :             if (oSRS.importFromEPSG(nSRSId) != OGRERR_NONE)
     649             :             {
     650           0 :                 sqlite3_result_null(pContext);
     651           0 :                 return;
     652             :             }
     653             :         }
     654             :         else
     655             :         {
     656           1 :             CPLDebug("OGR_SQLITE",
     657             :                      "Assuming EPSG:4326 for GeodesicArea() computation");
     658           1 :             oSRS.importFromEPSG(4326);
     659             :         }
     660           3 :         poGeom->assignSpatialReference(&oSRS);
     661           3 :         sqlite3_result_double(
     662             :             pContext, OGR_G_GeodesicArea(OGRGeometry::ToHandle(poGeom.get())));
     663           3 :         poGeom->assignSpatialReference(nullptr);
     664             :     }
     665             :     else
     666             :     {
     667           1 :         sqlite3_result_null(pContext);
     668             :     }
     669             : }
     670             : 
     671             : /************************************************************************/
     672             : /*                     OGR2SQLITE_ST_GeodesicLength()                   */
     673             : /************************************************************************/
     674             : 
     675           4 : static void OGR2SQLITE_ST_GeodesicLength(sqlite3_context *pContext, int argc,
     676             :                                          sqlite3_value **argv)
     677             : {
     678           4 :     if (sqlite3_value_int(argv[1]) != 1)
     679             :     {
     680           1 :         CPLError(CE_Warning, CPLE_NotSupported,
     681             :                  "ST_Length(geom, use_ellipsoid) is only supported for "
     682             :                  "use_ellipsoid = 1");
     683             :     }
     684             : 
     685           4 :     int nSRSId = -1;
     686           4 :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
     687           4 :     if (poGeom != nullptr)
     688             :     {
     689           2 :         OGRSpatialReference oSRS;
     690           2 :         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     691           2 :         if (nSRSId > 0)
     692             :         {
     693           2 :             if (oSRS.importFromEPSG(nSRSId) != OGRERR_NONE)
     694             :             {
     695           0 :                 sqlite3_result_null(pContext);
     696           0 :                 return;
     697             :             }
     698             :         }
     699             :         else
     700             :         {
     701           0 :             CPLDebug("OGR_SQLITE",
     702             :                      "Assuming EPSG:4326 for GeodesicLength() computation");
     703           0 :             oSRS.importFromEPSG(4326);
     704             :         }
     705           2 :         poGeom->assignSpatialReference(&oSRS);
     706           2 :         sqlite3_result_double(
     707             :             pContext,
     708             :             OGR_G_GeodesicLength(OGRGeometry::ToHandle(poGeom.get())));
     709           2 :         poGeom->assignSpatialReference(nullptr);
     710             :     }
     711             :     else
     712             :     {
     713           2 :         sqlite3_result_null(pContext);
     714             :     }
     715             : }
     716             : 
     717             : #ifdef MINIMAL_SPATIAL_FUNCTIONS
     718             : 
     719             : /************************************************************************/
     720             : /*                     OGR2SQLITE_ST_AsText()                           */
     721             : /************************************************************************/
     722             : 
     723             : static void OGR2SQLITE_ST_AsText(sqlite3_context *pContext, int argc,
     724             :                                  sqlite3_value **argv)
     725             : {
     726             :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
     727             :     if (poGeom != nullptr)
     728             :     {
     729             :         char *pszWKT = nullptr;
     730             :         if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
     731             :             sqlite3_result_text(pContext, pszWKT, -1, CPLFree);
     732             :         else
     733             :             sqlite3_result_null(pContext);
     734             :     }
     735             :     else
     736             :         sqlite3_result_null(pContext);
     737             : }
     738             : 
     739             : /************************************************************************/
     740             : /*                    OGR2SQLITE_ST_AsBinary()                          */
     741             : /************************************************************************/
     742             : 
     743             : static void OGR2SQLITE_ST_AsBinary(sqlite3_context *pContext, int argc,
     744             :                                    sqlite3_value **argv)
     745             : {
     746             :     if (auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr))
     747             :     {
     748             :         const size_t nBLOBLen = poGeom->WkbSize();
     749             :         if (nBLOBLen > static_cast<size_t>(std::numeric_limits<int>::max()))
     750             :         {
     751             :             CPLError(CE_Failure, CPLE_NotSupported, "Too large geometry");
     752             :             sqlite3_result_null(pContext);
     753             :             return;
     754             :         }
     755             :         GByte *pabyGeomBLOB =
     756             :             static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBLOBLen));
     757             :         if (pabyGeomBLOB != nullptr)
     758             :         {
     759             :             if (poGeom->exportToWkb(wkbNDR, pabyGeomBLOB) == OGRERR_NONE)
     760             :                 sqlite3_result_blob(pContext, pabyGeomBLOB,
     761             :                                     static_cast<int>(nBLOBLen), CPLFree);
     762             :             else
     763             :             {
     764             :                 VSIFree(pabyGeomBLOB);
     765             :                 sqlite3_result_null(pContext);
     766             :             }
     767             :         }
     768             :         else
     769             :             sqlite3_result_null(pContext);
     770             :     }
     771             :     else
     772             :         sqlite3_result_null(pContext);
     773             : }
     774             : 
     775             : /************************************************************************/
     776             : /*                   OGR2SQLITE_ST_GeomFromText()                       */
     777             : /************************************************************************/
     778             : 
     779             : static void OGR2SQLITE_ST_GeomFromText(sqlite3_context *pContext, int argc,
     780             :                                        sqlite3_value **argv)
     781             : {
     782             :     if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
     783             :     {
     784             :         sqlite3_result_null(pContext);
     785             :         return;
     786             :     }
     787             :     const char *pszWKT =
     788             :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
     789             : 
     790             :     int nSRID = -1;
     791             :     if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_INTEGER)
     792             :         nSRID = sqlite3_value_int(argv[1]);
     793             : 
     794             :     OGRGeometry *poGeom = nullptr;
     795             :     if (OGRGeometryFactory::createFromWkt(pszWKT, nullptr, &poGeom) ==
     796             :         OGRERR_NONE)
     797             :     {
     798             :         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom, nSRID);
     799             :     }
     800             :     else
     801             :         sqlite3_result_null(pContext);
     802             : }
     803             : 
     804             : /************************************************************************/
     805             : /*                   OGR2SQLITE_ST_GeomFromWKB()                        */
     806             : /************************************************************************/
     807             : 
     808             : static void OGR2SQLITE_ST_GeomFromWKB(sqlite3_context *pContext, int argc,
     809             :                                       sqlite3_value **argv)
     810             : {
     811             :     if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
     812             :     {
     813             :         sqlite3_result_null(pContext);
     814             :         return;
     815             :     }
     816             : 
     817             :     int nSRID = -1;
     818             :     if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_INTEGER)
     819             :         nSRID = sqlite3_value_int(argv[1]);
     820             : 
     821             :     const GByte *pabySLBLOB =
     822             :         reinterpret_cast<const GByte *>(sqlite3_value_blob(argv[0]));
     823             :     int nBLOBLen = sqlite3_value_bytes(argv[0]);
     824             :     OGRGeometry *poGeom = nullptr;
     825             : 
     826             :     if (OGRGeometryFactory::createFromWkb(pabySLBLOB, nullptr, &poGeom,
     827             :                                           nBLOBLen) == OGRERR_NONE)
     828             :     {
     829             :         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom, nSRID);
     830             :     }
     831             :     else
     832             :         sqlite3_result_null(pContext);
     833             : }
     834             : 
     835             : /************************************************************************/
     836             : /*                         CheckSTFunctions()                           */
     837             : /************************************************************************/
     838             : 
     839             : static bool CheckSTFunctions(sqlite3_context *pContext, int argc,
     840             :                              sqlite3_value **argv,
     841             :                              std::unique_ptr<OGRGeometry> &poGeom1,
     842             :                              std::unique_ptr<OGRGeometry> &poGeom2,
     843             :                              int *pnSRSId)
     844             : {
     845             :     if (argc != 2)
     846             :     {
     847             :         return false;
     848             :     }
     849             : 
     850             :     poGeom1 = OGR2SQLITE_GetGeom(pContext, argc, argv, pnSRSId);
     851             :     poGeom2 = OGR2SQLITE_GetGeom(pContext, argc - 1, argv + 1, nullptr);
     852             :     return poGeom1 && poGeom2;
     853             : }
     854             : 
     855             : /************************************************************************/
     856             : /*                 OGR2SQLITE_ST_int_geomgeom_op()                      */
     857             : /************************************************************************/
     858             : 
     859             : #define OGR2SQLITE_ST_int_geomgeom_op(op)                                      \
     860             :     static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc,        \
     861             :                                    sqlite3_value **argv)                       \
     862             :     {                                                                          \
     863             :         std::unique_ptr<OGRGeometry> poGeom1;                                  \
     864             :         std::unique_ptr<OGRGeometry> poGeom2;                                  \
     865             :         if (!CheckSTFunctions(pContext, argc, argv, poGeom1, poGeom2,          \
     866             :                               nullptr))                                        \
     867             :         {                                                                      \
     868             :             sqlite3_result_int(pContext, 0);                                   \
     869             :             return;                                                            \
     870             :         }                                                                      \
     871             :                                                                                \
     872             :         sqlite3_result_int(pContext, poGeom1->op(poGeom2.get()));              \
     873             :     }
     874             : 
     875             : // clang-format off
     876             : OGR2SQLITE_ST_int_geomgeom_op(Intersects)
     877             : OGR2SQLITE_ST_int_geomgeom_op(Equals)
     878             : OGR2SQLITE_ST_int_geomgeom_op(Disjoint)
     879             : OGR2SQLITE_ST_int_geomgeom_op(Touches)
     880             : OGR2SQLITE_ST_int_geomgeom_op(Crosses)
     881             : OGR2SQLITE_ST_int_geomgeom_op(Within)
     882             : OGR2SQLITE_ST_int_geomgeom_op(Contains)
     883             : OGR2SQLITE_ST_int_geomgeom_op(Overlaps)
     884             : // clang-format on
     885             : 
     886             : /************************************************************************/
     887             : /*                   OGR2SQLITE_ST_int_geom_op()                        */
     888             : /************************************************************************/
     889             : 
     890             : #define OGR2SQLITE_ST_int_geom_op(op)                                          \
     891             :     static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc,        \
     892             :                                    sqlite3_value **argv)                       \
     893             :     {                                                                          \
     894             :         auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);       \
     895             :         if (poGeom != nullptr)                                                 \
     896             :             sqlite3_result_int(pContext, poGeom->op());                        \
     897             :         else                                                                   \
     898             :             sqlite3_result_int(pContext, 0);                                   \
     899             :     }
     900             : 
     901             :     // clang-format off
     902             : OGR2SQLITE_ST_int_geom_op(IsEmpty)
     903             : OGR2SQLITE_ST_int_geom_op(IsSimple)
     904             : OGR2SQLITE_ST_int_geom_op(IsValid)
     905             : // clang-format on
     906             : 
     907             : /************************************************************************/
     908             : /*                  OGR2SQLITE_ST_geom_geomgeom_op()                    */
     909             : /************************************************************************/
     910             : 
     911             : #define OGR2SQLITE_ST_geom_geomgeom_op(op)                                     \
     912             :     static void OGR2SQLITE_ST_##op(sqlite3_context *pContext, int argc,        \
     913             :                                    sqlite3_value **argv)                       \
     914             :     {                                                                          \
     915             :         std::unique_ptr<OGRGeometry> poGeom1;                                  \
     916             :         std::unique_ptr<OGRGeometry> poGeom2;                                  \
     917             :         int nSRSId = -1;                                                       \
     918             :         if (!CheckSTFunctions(pContext, argc, argv, poGeom1, poGeom2,          \
     919             :                               &nSRSId))                                        \
     920             :         {                                                                      \
     921             :             sqlite3_result_null(pContext);                                     \
     922             :             return;                                                            \
     923             :         }                                                                      \
     924             :                                                                                \
     925             :         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom1->op(poGeom2.get()),    \
     926             :                                       nSRSId);                                 \
     927             :     }
     928             : 
     929             :     // clang-format off
     930             : OGR2SQLITE_ST_geom_geomgeom_op(Intersection)
     931             : OGR2SQLITE_ST_geom_geomgeom_op(Difference)
     932             : OGR2SQLITE_ST_geom_geomgeom_op(Union)
     933             : OGR2SQLITE_ST_geom_geomgeom_op(SymDifference)
     934             :     // clang-format on
     935             : 
     936             :     /************************************************************************/
     937             :     /*                      OGR2SQLITE_ST_SRID()                            */
     938             :     /************************************************************************/
     939             : 
     940             :     static void OGR2SQLITE_ST_SRID(sqlite3_context *pContext, int argc,
     941             :                                    sqlite3_value **argv)
     942             : {
     943             :     int nSRSId = -1;
     944             :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
     945             :     if (poGeom != nullptr)
     946             :     {
     947             :         CPLPushErrorHandler(CPLQuietErrorHandler);
     948             :         sqlite3_result_int(pContext, nSRSId);
     949             :         CPLPopErrorHandler();
     950             :     }
     951             :     else
     952             :         sqlite3_result_null(pContext);
     953             : }
     954             : 
     955             : /************************************************************************/
     956             : /*                      OGR2SQLITE_ST_Area()                            */
     957             : /************************************************************************/
     958             : 
     959             : static void OGR2SQLITE_ST_Area(sqlite3_context *pContext, int argc,
     960             :                                sqlite3_value **argv)
     961             : {
     962             :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
     963             :     if (poGeom != nullptr)
     964             :     {
     965             :         CPLPushErrorHandler(CPLQuietErrorHandler);
     966             :         sqlite3_result_double(pContext,
     967             :                               OGR_G_Area(OGRGeometry::ToHandle(poGeom.get())));
     968             :         CPLPopErrorHandler();
     969             :     }
     970             :     else
     971             :         sqlite3_result_null(pContext);
     972             : }
     973             : 
     974             : /************************************************************************/
     975             : /*                      OGR2SQLITE_ST_Length()                          */
     976             : /************************************************************************/
     977             : 
     978             : static void OGR2SQLITE_ST_Length(sqlite3_context *pContext, int argc,
     979             :                                  sqlite3_value **argv)
     980             : {
     981             :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, nullptr);
     982             :     if (poGeom != nullptr)
     983             :     {
     984             :         CPLPushErrorHandler(CPLQuietErrorHandler);
     985             :         sqlite3_result_double(
     986             :             pContext, OGR_G_Length(OGRGeometry::ToHandle(poGeom.get())));
     987             :         CPLPopErrorHandler();
     988             :     }
     989             :     else
     990             :         sqlite3_result_null(pContext);
     991             : }
     992             : 
     993             : /************************************************************************/
     994             : /*                     OGR2SQLITE_ST_Buffer()                           */
     995             : /************************************************************************/
     996             : 
     997             : static void OGR2SQLITE_ST_Buffer(sqlite3_context *pContext, int argc,
     998             :                                  sqlite3_value **argv)
     999             : {
    1000             :     int nSRSId = -1;
    1001             :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
    1002             :     int bGotVal = FALSE;
    1003             :     double dfDist = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
    1004             :     if (poGeom != nullptr && bGotVal)
    1005             :         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom->Buffer(dfDist), nSRSId);
    1006             :     else
    1007             :         sqlite3_result_null(pContext);
    1008             : }
    1009             : 
    1010             : /************************************************************************/
    1011             : /*                    OGR2SQLITE_ST_MakePoint()                         */
    1012             : /************************************************************************/
    1013             : 
    1014             : static void OGR2SQLITE_ST_MakePoint(sqlite3_context *pContext, int argc,
    1015             :                                     sqlite3_value **argv)
    1016             : {
    1017             :     double dfY = 0.0;
    1018             :     int bGotVal = FALSE;
    1019             :     const double dfX = OGR2SQLITE_GetValAsDouble(argv[0], &bGotVal);
    1020             :     if (bGotVal)
    1021             :         dfY = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
    1022             :     if (!bGotVal)
    1023             :     {
    1024             :         sqlite3_result_null(pContext);
    1025             :         return;
    1026             :     }
    1027             : 
    1028             :     OGRPoint *poPoint = nullptr;
    1029             :     if (argc == 3)
    1030             :     {
    1031             :         double dfZ = OGR2SQLITE_GetValAsDouble(argv[2], &bGotVal);
    1032             :         if (!bGotVal)
    1033             :         {
    1034             :             sqlite3_result_null(pContext);
    1035             :             return;
    1036             :         }
    1037             : 
    1038             :         poPoint = new OGRPoint(dfX, dfY, dfZ);
    1039             :     }
    1040             :     else
    1041             :     {
    1042             :         poPoint = new OGRPoint(dfX, dfY);
    1043             :     }
    1044             : 
    1045             :     OGR2SQLITE_SetGeom_AndDestroy(pContext, poPoint, -1);
    1046             : }
    1047             : 
    1048             : #endif  // #ifdef MINIMAL_SPATIAL_FUNCTIONS
    1049             : 
    1050             : /************************************************************************/
    1051             : /*                    OGR2SQLITE_ST_MakeValid()                         */
    1052             : /************************************************************************/
    1053             : 
    1054           1 : static void OGR2SQLITE_ST_MakeValid(sqlite3_context *pContext, int argc,
    1055             :                                     sqlite3_value **argv)
    1056             : {
    1057           1 :     int nSRSId = -1;
    1058           2 :     auto poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
    1059           1 :     if (poGeom != nullptr)
    1060           1 :         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom->MakeValid(), nSRSId);
    1061             :     else
    1062           0 :         sqlite3_result_null(pContext);
    1063           1 : }
    1064             : 
    1065             : /************************************************************************/
    1066             : /*                     OGRSQLITE_hstore_get_value()                     */
    1067             : /************************************************************************/
    1068             : 
    1069           6 : static void OGRSQLITE_hstore_get_value(sqlite3_context *pContext,
    1070             :                                        CPL_UNUSED int argc,
    1071             :                                        sqlite3_value **argv)
    1072             : {
    1073          10 :     if (sqlite3_value_type(argv[0]) != SQLITE_TEXT ||
    1074           4 :         sqlite3_value_type(argv[1]) != SQLITE_TEXT)
    1075             :     {
    1076           4 :         sqlite3_result_null(pContext);
    1077           4 :         return;
    1078             :     }
    1079             : 
    1080             :     const char *pszHStore =
    1081           2 :         reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
    1082             :     const char *pszSearchedKey =
    1083           2 :         reinterpret_cast<const char *>(sqlite3_value_text(argv[1]));
    1084           2 :     char *pszValue = OGRHStoreGetValue(pszHStore, pszSearchedKey);
    1085           2 :     if (pszValue != nullptr)
    1086           1 :         sqlite3_result_text(pContext, pszValue, -1, CPLFree);
    1087             :     else
    1088           1 :         sqlite3_result_null(pContext);
    1089             : }
    1090             : 
    1091             : /************************************************************************/
    1092             : /*                   OGRSQLiteRegisterSQLFunctions()                    */
    1093             : /************************************************************************/
    1094             : 
    1095             : #ifndef SQLITE_DETERMINISTIC
    1096             : #define SQLITE_DETERMINISTIC 0
    1097             : #endif
    1098             : 
    1099             : #ifndef SQLITE_INNOCUOUS
    1100             : #define SQLITE_INNOCUOUS 0
    1101             : #endif
    1102             : 
    1103             : #ifndef UTF8_INNOCUOUS
    1104             : #define UTF8_INNOCUOUS (SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS)
    1105             : #endif
    1106             : 
    1107        1317 : static void *OGRSQLiteRegisterSQLFunctions(sqlite3 *hDB)
    1108             : {
    1109        1317 :     OGRSQLiteExtensionData *pData = OGRSQLiteRegisterSQLFunctionsCommon(hDB);
    1110             : 
    1111        1317 :     sqlite3_create_function(hDB, "ogr_version", 0, UTF8_INNOCUOUS, nullptr,
    1112             :                             OGR2SQLITE_ogr_version, nullptr, nullptr);
    1113             : 
    1114        1317 :     sqlite3_create_function(hDB, "ogr_version", 1, UTF8_INNOCUOUS, nullptr,
    1115             :                             OGR2SQLITE_ogr_version, nullptr, nullptr);
    1116             : 
    1117        1317 :     sqlite3_create_function(hDB, "ogr_deflate", 1, UTF8_INNOCUOUS, nullptr,
    1118             :                             OGR2SQLITE_ogr_deflate, nullptr, nullptr);
    1119             : 
    1120        1317 :     sqlite3_create_function(hDB, "ogr_deflate", 2, UTF8_INNOCUOUS, nullptr,
    1121             :                             OGR2SQLITE_ogr_deflate, nullptr, nullptr);
    1122             : 
    1123        1317 :     sqlite3_create_function(hDB, "ogr_inflate", 1, UTF8_INNOCUOUS, nullptr,
    1124             :                             OGR2SQLITE_ogr_inflate, nullptr, nullptr);
    1125             : 
    1126        1317 :     sqlite3_create_function(hDB, "ogr_geocode", -1, SQLITE_UTF8, pData,
    1127             :                             OGR2SQLITE_ogr_geocode, nullptr, nullptr);
    1128             : 
    1129        1317 :     sqlite3_create_function(hDB, "ogr_geocode_reverse", -1, SQLITE_UTF8, pData,
    1130             :                             OGR2SQLITE_ogr_geocode_reverse, nullptr, nullptr);
    1131             : 
    1132        1317 :     sqlite3_create_function(hDB, "ogr_datasource_load_layers", 1, SQLITE_UTF8,
    1133             :                             hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
    1134             :                             nullptr);
    1135             : 
    1136        1317 :     sqlite3_create_function(hDB, "ogr_datasource_load_layers", 2, SQLITE_UTF8,
    1137             :                             hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
    1138             :                             nullptr);
    1139             : 
    1140        1317 :     sqlite3_create_function(hDB, "ogr_datasource_load_layers", 3, SQLITE_UTF8,
    1141             :                             hDB, OGR2SQLITE_ogr_datasource_load_layers, nullptr,
    1142             :                             nullptr);
    1143             : 
    1144             : #if notdef
    1145             :     sqlite3_create_function(hDB, "ogr_GetConfigOption", 1, SQLITE_UTF8, nullptr,
    1146             :                             OGR2SQLITE_ogr_GetConfigOption, nullptr, nullptr);
    1147             : 
    1148             :     sqlite3_create_function(hDB, "ogr_SetConfigOption", 2, SQLITE_UTF8, nullptr,
    1149             :                             OGR2SQLITE_ogr_SetConfigOption, nullptr, nullptr);
    1150             : #endif
    1151             : 
    1152             :     // Custom and undocumented function, not sure I'll keep it.
    1153        1317 :     sqlite3_create_function(hDB, "Transform3", 3, UTF8_INNOCUOUS, pData,
    1154             :                             OGR2SQLITE_Transform, nullptr, nullptr);
    1155             : 
    1156             :     // HSTORE functions
    1157        1317 :     sqlite3_create_function(hDB, "hstore_get_value", 2, UTF8_INNOCUOUS, nullptr,
    1158             :                             OGRSQLITE_hstore_get_value, nullptr, nullptr);
    1159             : 
    1160             :     /* Check if spatialite is available */
    1161        1317 :     int rc = sqlite3_exec(hDB, "SELECT spatialite_version()", nullptr, nullptr,
    1162             :                           nullptr);
    1163             : 
    1164             :     /* Reset error flag */
    1165        1317 :     sqlite3_exec(hDB, "SELECT 1", nullptr, nullptr, nullptr);
    1166             : 
    1167        1317 :     const bool bSpatialiteAvailable = rc == SQLITE_OK;
    1168             :     const bool bAllowOGRSQLiteSpatialFunctions =
    1169        1317 :         CPLTestBool(CPLGetConfigOption("OGR_SQLITE_SPATIAL_FUNCTIONS", "YES"));
    1170             : 
    1171             : #define REGISTER_ST_op(argc, op)                                               \
    1172             :     sqlite3_create_function(hDB, #op, argc, UTF8_INNOCUOUS, nullptr,           \
    1173             :                             OGR2SQLITE_ST_##op, nullptr, nullptr);             \
    1174             :     sqlite3_create_function(hDB, "ST_" #op, argc, UTF8_INNOCUOUS, nullptr,     \
    1175             :                             OGR2SQLITE_ST_##op, nullptr, nullptr);
    1176             : 
    1177             : #ifdef MINIMAL_SPATIAL_FUNCTIONS
    1178             :     if (!bSpatialiteAvailable && bAllowOGRSQLiteSpatialFunctions)
    1179             :     {
    1180             :         static const auto DebugOnce = []()
    1181             :         {
    1182             :             CPLDebug("SQLITE",
    1183             :                      "Spatialite not available. Implementing a few functions");
    1184             :             return true;
    1185             :         }();
    1186             :         CPL_IGNORE_RET_VAL(DebugOnce);
    1187             : 
    1188             :         REGISTER_ST_op(1, AsText);
    1189             :         REGISTER_ST_op(1, AsBinary);
    1190             :         REGISTER_ST_op(1, GeomFromText);
    1191             :         REGISTER_ST_op(2, GeomFromText);
    1192             :         REGISTER_ST_op(1, GeomFromWKB);
    1193             :         REGISTER_ST_op(2, GeomFromWKB);
    1194             : 
    1195             :         REGISTER_ST_op(1, IsEmpty);
    1196             :         REGISTER_ST_op(1, IsSimple);
    1197             :         REGISTER_ST_op(1, IsValid);
    1198             : 
    1199             :         REGISTER_ST_op(2, Intersects);
    1200             :         REGISTER_ST_op(2, Equals);
    1201             :         REGISTER_ST_op(2, Disjoint);
    1202             :         REGISTER_ST_op(2, Touches);
    1203             :         REGISTER_ST_op(2, Crosses);
    1204             :         REGISTER_ST_op(2, Within);
    1205             :         REGISTER_ST_op(2, Contains);
    1206             :         REGISTER_ST_op(2, Overlaps);
    1207             : 
    1208             :         REGISTER_ST_op(2, Intersection);
    1209             :         REGISTER_ST_op(2, Difference);
    1210             :         // Union() is invalid
    1211             :         sqlite3_create_function(hDB, "ST_Union", 2, UTF8_INNOCUOUS, nullptr,
    1212             :                                 OGR2SQLITE_ST_Union, nullptr, nullptr);
    1213             :         REGISTER_ST_op(2, SymDifference);
    1214             : 
    1215             :         REGISTER_ST_op(1, SRID);
    1216             :         REGISTER_ST_op(1, Area);
    1217             :         // length() is a reserved SQLite function
    1218             :         sqlite3_create_function(hDB, "ST_Length", 1, UTF8_INNOCUOUS, nullptr,
    1219             :                                 OGR2SQLITE_ST_Length, nullptr, nullptr);
    1220             :         REGISTER_ST_op(2, Buffer);
    1221             :         REGISTER_ST_op(2, MakePoint);
    1222             :         REGISTER_ST_op(3, MakePoint);
    1223             :     }
    1224             : #endif  // #ifdef MINIMAL_SPATIAL_FUNCTIONS
    1225             : 
    1226        1317 :     if (bAllowOGRSQLiteSpatialFunctions)
    1227             :     {
    1228             :         // We add a ST_Area() method with 2 arguments even when Spatialite
    1229             :         // is there to indicate we want to use the ellipsoid version
    1230        1317 :         sqlite3_create_function(hDB, "Area", 2, UTF8_INNOCUOUS, nullptr,
    1231             :                                 OGR2SQLITE_ST_GeodesicArea, nullptr, nullptr);
    1232        1317 :         sqlite3_create_function(hDB, "ST_Area", 2, UTF8_INNOCUOUS, nullptr,
    1233             :                                 OGR2SQLITE_ST_GeodesicArea, nullptr, nullptr);
    1234             : 
    1235             :         // We add a ST_Length() method with 2 arguments even when Spatialite
    1236             :         // is there to indicate we want to use the ellipsoid version
    1237        1317 :         sqlite3_create_function(hDB, "ST_Length", 2, UTF8_INNOCUOUS, nullptr,
    1238             :                                 OGR2SQLITE_ST_GeodesicLength, nullptr, nullptr);
    1239             : 
    1240          61 :         static bool gbRegisterMakeValid = [bSpatialiteAvailable, hDB]()
    1241             :         {
    1242          21 :             bool bRegisterMakeValid = false;
    1243          21 :             if (bSpatialiteAvailable)
    1244             :             {
    1245             :                 // ST_MakeValid() only available (at time of writing) in
    1246             :                 // Spatialite builds against (GPL) liblwgeom
    1247             :                 // In the future, if they use GEOS 3.8 MakeValid, we could
    1248             :                 // get rid of this.
    1249          20 :                 int l_rc = sqlite3_exec(
    1250             :                     hDB, "SELECT ST_MakeValid(ST_GeomFromText('POINT (0 0)'))",
    1251             :                     nullptr, nullptr, nullptr);
    1252             : 
    1253             :                 /* Reset error flag */
    1254          20 :                 sqlite3_exec(hDB, "SELECT 1", nullptr, nullptr, nullptr);
    1255             : 
    1256          20 :                 bRegisterMakeValid = (l_rc != SQLITE_OK);
    1257             :             }
    1258             :             else
    1259             :             {
    1260           1 :                 bRegisterMakeValid = true;
    1261             :             }
    1262          21 :             if (bRegisterMakeValid)
    1263             :             {
    1264          21 :                 return OGRGeometryFactory::haveGEOS();
    1265             :             }
    1266           0 :             return false;
    1267        1317 :         }();
    1268        1317 :         if (gbRegisterMakeValid)
    1269             :         {
    1270        1317 :             REGISTER_ST_op(1, MakeValid);
    1271             :         }
    1272             :     }
    1273             : 
    1274        1317 :     return pData;
    1275             : }

Generated by: LCOV version 1.14