LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitebase.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 26 26 100.0 %
Date: 2025-07-09 17:50:03 Functions: 16 18 88.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Definition of classes and functions used by SQLite and GPKG drivers
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2021, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_SQLITE_BASE_H_INCLUDED
      14             : #define OGR_SQLITE_BASE_H_INCLUDED
      15             : 
      16             : #include "cpl_vsi.h"
      17             : #include "cpl_string.h"
      18             : #include "gdal_pam.h"
      19             : #include "ogrsf_frmts.h"
      20             : 
      21             : #include <sqlite3.h>
      22             : 
      23             : // to avoid -Wold-style-cast with some compilers
      24             : #undef SQLITE_TRANSIENT
      25             : #define SQLITE_TRANSIENT reinterpret_cast<sqlite3_destructor_type>(-1)
      26             : 
      27             : #include <map>
      28             : #include <utility>
      29             : #include <vector>
      30             : 
      31             : /************************************************************************/
      32             : /*      Format used to store geometry data in the database.             */
      33             : /************************************************************************/
      34             : 
      35             : enum OGRSQLiteGeomFormat
      36             : {
      37             :     OSGF_None = 0,
      38             :     OSGF_WKT = 1,
      39             :     OSGF_WKB = 2,
      40             :     OSGF_FGF = 3,
      41             :     OSGF_SpatiaLite = 4
      42             : };
      43             : 
      44             : /************************************************************************/
      45             : /*                        OGRSQLiteGeomFieldDefn                        */
      46             : /************************************************************************/
      47             : 
      48        1798 : class OGRSQLiteGeomFieldDefn final : public OGRGeomFieldDefn
      49             : {
      50             :   public:
      51         899 :     OGRSQLiteGeomFieldDefn(const char *pszNameIn, int iGeomColIn)
      52         899 :         : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
      53             :     {
      54         899 :     }
      55             : 
      56             :     ~OGRSQLiteGeomFieldDefn() override;
      57             : 
      58             :     int m_nSRSId = -1;
      59             :     int m_iCol; /* ordinal of geometry field in SQL statement */
      60             :     bool m_bTriedAsSpatiaLite = false;
      61             :     OGRSQLiteGeomFormat m_eGeomFormat = OSGF_None;
      62             :     OGREnvelope m_oCachedExtent{};
      63             :     bool m_bCachedExtentIsValid = false;
      64             :     bool m_bHasSpatialIndex = false;
      65             :     bool m_bHasCheckedSpatialIndexTable = false;
      66             :     std::vector<std::pair<CPLString, CPLString>> m_aosDisabledTriggers{};
      67             : };
      68             : 
      69             : /************************************************************************/
      70             : /*                        OGRSQLiteFeatureDefn                          */
      71             : /************************************************************************/
      72             : 
      73        7266 : class OGRSQLiteFeatureDefn final : public OGRFeatureDefn
      74             : {
      75             :   public:
      76        3633 :     explicit OGRSQLiteFeatureDefn(const char *pszName = nullptr)
      77        3633 :         : OGRFeatureDefn(pszName)
      78             :     {
      79        3633 :         SetGeomType(wkbNone);
      80        3633 :     }
      81             : 
      82             :     ~OGRSQLiteFeatureDefn() override;
      83             : 
      84        7762 :     OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
      85             :     {
      86        7762 :         return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
      87             :     }
      88             : };
      89             : 
      90             : /************************************************************************/
      91             : /*                       IOGRSQLiteGetSpatialWhere                      */
      92             : /************************************************************************/
      93             : 
      94        7967 : class IOGRSQLiteGetSpatialWhere
      95             : {
      96             :   public:
      97             :     virtual ~IOGRSQLiteGetSpatialWhere();
      98             : 
      99             :     virtual bool HasFastSpatialFilter(int iGeomCol) = 0;
     100             :     virtual CPLString GetSpatialWhere(int iGeomCol,
     101             :                                       OGRGeometry *poFilterGeom) = 0;
     102             : };
     103             : 
     104             : /************************************************************************/
     105             : /*                       OGRSQLiteBaseDataSource                        */
     106             : /************************************************************************/
     107             : 
     108             : /* Used by both OGRSQLiteDataSource and OGRGeoPackageDataSource */
     109        3703 : class OGRSQLiteBaseDataSource CPL_NON_FINAL : public GDALPamDataset
     110             : {
     111             :   protected:
     112             :     char *m_pszFilename = nullptr;
     113             :     std::string
     114             :         m_osFilenameForSQLiteOpen{};  // generally m_pszFilename, but can be
     115             :                                       // also file:{m_pszFilename}?nolock=1
     116             :     bool m_bNoLock = false;
     117             :     std::string
     118             :         m_osFinalFilename{};  // use when generating a network hosted file with
     119             :                               // CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE=YES
     120             :     bool m_bCallUndeclareFileNotToOpen = false;
     121             : 
     122             :     sqlite3 *hDB = nullptr;
     123             : 
     124             :     sqlite3_vfs *pMyVFS = nullptr;
     125             : 
     126             :     VSILFILE *fpMainFile =
     127             :         nullptr; /* Set by the VFS layer when it opens the DB */
     128             :                  /* Must *NOT* be closed by the datasource explicitly. */
     129             : 
     130             :     bool OpenOrCreateDB(int flags, bool bRegisterOGR2SQLiteExtensions,
     131             :                         bool bLoadExtensions);
     132             :     bool SetSynchronous();
     133             :     bool SetCacheSize();
     134             :     void LoadExtensions();
     135             : 
     136             :     bool CloseDB();
     137             : 
     138             :     std::map<CPLString, OGREnvelope> oMapSQLEnvelope{};
     139             : 
     140             :     mutable bool m_bHasPopulatedRelationships = false;
     141             :     mutable std::map<std::string, std::unique_ptr<GDALRelationship>>
     142             :         m_osMapRelationships{};
     143             : 
     144             :     void *hSpatialiteCtxt = nullptr;
     145             :     bool InitSpatialite();
     146             :     void FinishSpatialite();
     147             : 
     148             :     int m_bUserTransactionActive = FALSE;
     149             :     int m_nSoftTransactionLevel = 0;
     150             :     std::vector<std::string> m_aosSavepoints{};
     151             :     // The transaction was implicitly started by SAVEPOINT
     152             :     bool m_bImplicitTransactionOpened = false;
     153             : 
     154             :     OGRErr DoTransactionCommand(const char *pszCommand);
     155             : 
     156             :     bool DealWithOgrSchemaOpenOption(CSLConstList papszOpenOptionsIn);
     157             : 
     158             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteBaseDataSource)
     159             : 
     160             :   public:
     161             :     OGRSQLiteBaseDataSource();
     162             :     virtual ~OGRSQLiteBaseDataSource();
     163             : 
     164        1630 :     std::string GetCurrentSavepoint() const
     165             :     {
     166        1630 :         return m_aosSavepoints.empty() ? "" : m_aosSavepoints.back();
     167             :     }
     168             : 
     169             :     std::string GetFirstSavepoint() const
     170             :     {
     171             :         return m_aosSavepoints.empty() ? "" : m_aosSavepoints.front();
     172             :     }
     173             : 
     174             :     bool IsInTransaction() const;
     175             : 
     176      319502 :     sqlite3 *GetDB()
     177             :     {
     178      319502 :         return hDB;
     179             :     }
     180             : 
     181          72 :     sqlite3_vfs *GetVFS()
     182             :     {
     183          72 :         return pMyVFS;
     184             :     }
     185             : 
     186      300306 :     inline bool GetUpdate() const
     187             :     {
     188      300306 :         return eAccess == GA_Update;
     189             :     }
     190             : 
     191           3 :     VSILFILE *GetVSILFILE() const
     192             :     {
     193           3 :         return fpMainFile;
     194             :     }
     195             : 
     196             :     void NotifyFileOpened(const char *pszFilename, VSILFILE *fp);
     197             : 
     198             :     const OGREnvelope *GetEnvelopeFromSQL(const CPLString &osSQL);
     199             :     void SetEnvelopeForSQL(const CPLString &osSQL,
     200             :                            const OGREnvelope &oEnvelope);
     201             : 
     202             :     virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     203             :     GetLayerWithGetSpatialWhereByName(const char *pszName) = 0;
     204             : 
     205             :     virtual OGRErr AbortSQL() override;
     206             :     bool SetQueryLoggerFunc(GDALQueryLoggerFunc pfnQueryLoggerFuncIn,
     207             :                             void *poQueryLoggerArgIn) override;
     208             : 
     209             :     virtual OGRErr StartTransaction(int bForce = FALSE) override;
     210             :     virtual OGRErr CommitTransaction() override;
     211             :     virtual OGRErr RollbackTransaction() override;
     212             : 
     213             :     virtual int TestCapability(const char *) override;
     214             : 
     215             :     virtual void *GetInternalHandle(const char *) override;
     216             : 
     217             :     OGRErr SoftStartTransaction();
     218             :     OGRErr SoftCommitTransaction();
     219             :     OGRErr SoftRollbackTransaction();
     220             :     OGRErr StartSavepoint(const std::string &osName);
     221             :     OGRErr ReleaseSavepoint(const std::string &osName);
     222             :     OGRErr RollbackToSavepoint(const std::string &osName);
     223             : 
     224             :     /**
     225             :      *  Execute a SQL transaction command (BEGIN, COMMIT, ROLLBACK, SAVEPOINT)
     226             :      *  @return TRUE if the osSQLCommand was recognized as a transaction command
     227             :      */
     228             :     bool ProcessTransactionSQL(const std::string &osSQLCommand);
     229             : 
     230             :     OGRErr PragmaCheck(const char *pszPragma, const char *pszExpected,
     231             :                        int nRowsExpected);
     232             : 
     233             :     virtual void LoadRelationships() const;
     234             :     void LoadRelationshipsFromForeignKeys(
     235             :         const std::vector<std::string> &excludedTables) const;
     236             :     std::vector<std::string>
     237             :     GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
     238             :     const GDALRelationship *
     239             :     GetRelationship(const std::string &name) const override;
     240             : 
     241             :     bool IsSpatialiteLoaded();
     242             : 
     243       10638 :     static int MakeSpatialiteVersionNumber(int x, int y, int z)
     244             :     {
     245       10638 :         return x * 10000 + y * 100 + z;
     246             :     }
     247             : 
     248             :     int GetSpatialiteVersionNumber();
     249             : 
     250             :     bool SpatialiteRequiresTrustedSchemaOn();
     251             :     bool AreSpatialiteTriggersSafe();
     252             : 
     253             :     // sqlite3_prepare_v2 error logging wrapper
     254             :     int
     255             :     prepareSql(sqlite3 *db,           /* Database handle */
     256             :                const char *zSql,      /* SQL statement, UTF-8 encoded */
     257             :                int nByte,             /* Maximum length of zSql in bytes. */
     258             :                sqlite3_stmt **ppStmt, /* OUT: Statement handle */
     259             :                const char **pzTail /* OUT: Pointer to unused portion of zSql */
     260             :     );
     261             : 
     262             :     GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
     263             :     void *poQueryLoggerArg = nullptr;
     264             : };
     265             : 
     266             : /************************************************************************/
     267             : /*                         IOGRSQLiteSelectLayer                        */
     268             : /************************************************************************/
     269             : 
     270        2217 : class IOGRSQLiteSelectLayer
     271             : {
     272             :   public:
     273             :     virtual ~IOGRSQLiteSelectLayer();
     274             : 
     275             :     virtual char *&GetAttrQueryString() = 0;
     276             :     virtual OGRFeatureQuery *&GetFeatureQuery() = 0;
     277             :     virtual OGRGeometry *&GetFilterGeom() = 0;
     278             :     virtual int &GetIGeomFieldFilter() = 0;
     279             :     virtual OGRSpatialReference *GetSpatialRef() = 0;
     280             :     virtual OGRFeatureDefn *GetLayerDefn() = 0;
     281             :     virtual int InstallFilter(const OGRGeometry *) = 0;
     282             :     virtual int HasReadFeature() = 0;
     283             :     virtual void BaseResetReading() = 0;
     284             :     virtual OGRFeature *BaseGetNextFeature() = 0;
     285             :     virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) = 0;
     286             :     virtual GIntBig BaseGetFeatureCount(int bForce) = 0;
     287             :     virtual int BaseTestCapability(const char *) = 0;
     288             :     virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
     289             :                                  bool bForce) = 0;
     290             :     virtual bool ValidateGeometryFieldIndexForSetSpatialFilter(
     291             :         int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer) = 0;
     292             : };
     293             : 
     294             : /************************************************************************/
     295             : /*                   OGRSQLiteSelectLayerCommonBehaviour                */
     296             : /************************************************************************/
     297             : 
     298             : class OGRSQLiteSelectLayerCommonBehaviour
     299             : {
     300             :     OGRSQLiteBaseDataSource *m_poDS = nullptr;
     301             :     IOGRSQLiteSelectLayer *m_poLayer = nullptr;
     302             : 
     303             :     CPLString m_osSQLBase{};
     304             : 
     305             :     bool m_bEmptyLayer = false;
     306             :     bool m_bAllowResetReadingEvenIfIndexAtZero = false;
     307             :     bool m_bSpatialFilterInSQL = true;
     308             : 
     309             :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> GetBaseLayer(size_t &i);
     310             :     int BuildSQL();
     311             : 
     312             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSelectLayerCommonBehaviour)
     313             : 
     314             :   public:
     315             :     CPLString m_osSQLCurrent{};
     316             : 
     317             :     OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource *poDS,
     318             :                                         IOGRSQLiteSelectLayer *poBaseLayer,
     319             :                                         const CPLString &osSQL,
     320             :                                         bool bEmptyLayer);
     321             : 
     322             :     void ResetReading();
     323             :     OGRFeature *GetNextFeature();
     324             :     GIntBig GetFeatureCount(int);
     325             :     OGRErr SetSpatialFilter(int iGeomField, const OGRGeometry *);
     326             :     OGRErr SetAttributeFilter(const char *);
     327             :     int TestCapability(const char *);
     328             :     OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce);
     329             : };
     330             : 
     331             : /************************************************************************/
     332             : /*                   OGRSQLiteSingleFeatureLayer                        */
     333             : /************************************************************************/
     334             : 
     335             : class OGRSQLiteSingleFeatureLayer final : public OGRLayer
     336             : {
     337             :   private:
     338             :     int nVal;
     339             :     char *pszVal;
     340             :     OGRFeatureDefn *poFeatureDefn;
     341             :     int iNextShapeId;
     342             : 
     343             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSingleFeatureLayer)
     344             : 
     345             :   public:
     346             :     OGRSQLiteSingleFeatureLayer(const char *pszLayerName, int nVal);
     347             :     OGRSQLiteSingleFeatureLayer(const char *pszLayerName, const char *pszVal);
     348             :     virtual ~OGRSQLiteSingleFeatureLayer();
     349             : 
     350             :     virtual void ResetReading() override;
     351             :     virtual OGRFeature *GetNextFeature() override;
     352             :     virtual OGRFeatureDefn *GetLayerDefn() override;
     353             :     virtual int TestCapability(const char *) override;
     354             : };
     355             : 
     356             : /************************************************************************/
     357             : /* Functions                                                            */
     358             : /************************************************************************/
     359             : 
     360             : OGRErr OGRSQLiteGetSpatialiteGeometryHeader(const GByte *pabyData, int nBytes,
     361             :                                             int *pnSRID,
     362             :                                             OGRwkbGeometryType *peType,
     363             :                                             bool *pbIsEmpty, double *pdfMinX,
     364             :                                             double *pdfMinY, double *pdfMaxX,
     365             :                                             double *pdfMaxY);
     366             : // CPL_DLL just for spatialite_geom_import_fuzzer
     367             : OGRErr CPL_DLL OGRSQLiteImportSpatiaLiteGeometry(const GByte *, int,
     368             :                                                  OGRGeometry **,
     369             :                                                  int *pnSRID = nullptr);
     370             : OGRErr OGRSQLiteExportSpatiaLiteGeometry(const OGRGeometry *, GInt32,
     371             :                                          OGRwkbByteOrder, bool bSpatialite2D,
     372             :                                          bool bUseComprGeom, GByte **, int *);
     373             : #endif  // OGR_SQLITE_BASE_H_INCLUDED

Generated by: LCOV version 1.14