LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitesqlfunctions.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 263 319 82.4 %
Date: 2024-04-29 15:10:10 Functions: 15 16 93.8 %

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

Generated by: LCOV version 1.14