LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitebase.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 29 29 100.0 %
Date: 2025-09-10 17:48:50 Functions: 17 19 89.5 %

          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        1816 : class OGRSQLiteGeomFieldDefn final : public OGRGeomFieldDefn
      49             : {
      50             :   public:
      51         908 :     OGRSQLiteGeomFieldDefn(const char *pszNameIn, int iGeomColIn)
      52         908 :         : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
      53             :     {
      54         908 :     }
      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        7296 : class OGRSQLiteFeatureDefn final : public OGRFeatureDefn
      74             : {
      75             :   public:
      76        3648 :     explicit OGRSQLiteFeatureDefn(const char *pszName = nullptr)
      77        3648 :         : OGRFeatureDefn(pszName)
      78             :     {
      79        3648 :         SetGeomType(wkbNone);
      80        3648 :     }
      81             : 
      82             :     ~OGRSQLiteFeatureDefn() override;
      83             : 
      84       27875 :     OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
      85             :     {
      86       27875 :         return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
      87             :     }
      88             : 
      89           6 :     const OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i) const
      90             :     {
      91           6 :         return cpl::down_cast<const OGRSQLiteGeomFieldDefn *>(
      92          12 :             GetGeomFieldDefn(i));
      93             :     }
      94             : };
      95             : 
      96             : /************************************************************************/
      97             : /*                       IOGRSQLiteGetSpatialWhere                      */
      98             : /************************************************************************/
      99             : 
     100        8104 : class IOGRSQLiteGetSpatialWhere /* non final */
     101             : {
     102             :   public:
     103             :     virtual ~IOGRSQLiteGetSpatialWhere();
     104             : 
     105             :     virtual bool HasFastSpatialFilter(int iGeomCol) = 0;
     106             :     virtual CPLString GetSpatialWhere(int iGeomCol,
     107             :                                       OGRGeometry *poFilterGeom) = 0;
     108             : };
     109             : 
     110             : /************************************************************************/
     111             : /*                       OGRSQLiteBaseDataSource                        */
     112             : /************************************************************************/
     113             : 
     114             : /* Used by both OGRSQLiteDataSource and OGRGeoPackageDataSource */
     115        3839 : class OGRSQLiteBaseDataSource CPL_NON_FINAL : public GDALPamDataset
     116             : {
     117             :   protected:
     118             :     char *m_pszFilename = nullptr;
     119             :     std::string
     120             :         m_osFilenameForSQLiteOpen{};  // generally m_pszFilename, but can be
     121             :                                       // also file:{m_pszFilename}?nolock=1
     122             :     bool m_bNoLock = false;
     123             :     std::string
     124             :         m_osFinalFilename{};  // use when generating a network hosted file with
     125             :                               // CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE=YES
     126             :     bool m_bCallUndeclareFileNotToOpen = false;
     127             : 
     128             :     sqlite3 *hDB = nullptr;
     129             : 
     130             :     sqlite3_vfs *pMyVFS = nullptr;
     131             : 
     132             :     VSILFILE *fpMainFile =
     133             :         nullptr; /* Set by the VFS layer when it opens the DB */
     134             :                  /* Must *NOT* be closed by the datasource explicitly. */
     135             : 
     136             :     bool OpenOrCreateDB(int flags, bool bRegisterOGR2SQLiteExtensions,
     137             :                         bool bLoadExtensions);
     138             :     bool SetSynchronous();
     139             :     bool SetCacheSize();
     140             :     void LoadExtensions();
     141             : 
     142             :     bool CloseDB();
     143             : 
     144             :     std::map<CPLString, OGREnvelope> oMapSQLEnvelope{};
     145             : 
     146             :     mutable bool m_bHasPopulatedRelationships = false;
     147             :     mutable std::map<std::string, std::unique_ptr<GDALRelationship>>
     148             :         m_osMapRelationships{};
     149             : 
     150             :     void *hSpatialiteCtxt = nullptr;
     151             :     bool InitSpatialite();
     152             :     void FinishSpatialite();
     153             : 
     154             :     int m_bUserTransactionActive = FALSE;
     155             :     int m_nSoftTransactionLevel = 0;
     156             :     std::vector<std::string> m_aosSavepoints{};
     157             :     // The transaction was implicitly started by SAVEPOINT
     158             :     bool m_bImplicitTransactionOpened = false;
     159             : 
     160             :     OGRErr DoTransactionCommand(const char *pszCommand);
     161             : 
     162             :     bool DealWithOgrSchemaOpenOption(CSLConstList papszOpenOptionsIn);
     163             : 
     164             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteBaseDataSource)
     165             : 
     166             :   public:
     167             :     OGRSQLiteBaseDataSource();
     168             :     ~OGRSQLiteBaseDataSource() override;
     169             : 
     170        1639 :     std::string GetCurrentSavepoint() const
     171             :     {
     172        1639 :         return m_aosSavepoints.empty() ? "" : m_aosSavepoints.back();
     173             :     }
     174             : 
     175             :     std::string GetFirstSavepoint() const
     176             :     {
     177             :         return m_aosSavepoints.empty() ? "" : m_aosSavepoints.front();
     178             :     }
     179             : 
     180             :     bool IsInTransaction() const;
     181             : 
     182      342836 :     sqlite3 *GetDB()
     183             :     {
     184      342836 :         return hDB;
     185             :     }
     186             : 
     187          72 :     sqlite3_vfs *GetVFS()
     188             :     {
     189          72 :         return pMyVFS;
     190             :     }
     191             : 
     192      318592 :     inline bool GetUpdate() const
     193             :     {
     194      318592 :         return eAccess == GA_Update;
     195             :     }
     196             : 
     197           3 :     VSILFILE *GetVSILFILE() const
     198             :     {
     199           3 :         return fpMainFile;
     200             :     }
     201             : 
     202             :     void NotifyFileOpened(const char *pszFilename, VSILFILE *fp);
     203             : 
     204             :     const OGREnvelope *GetEnvelopeFromSQL(const CPLString &osSQL);
     205             :     void SetEnvelopeForSQL(const CPLString &osSQL,
     206             :                            const OGREnvelope &oEnvelope);
     207             : 
     208             :     virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     209             :     GetLayerWithGetSpatialWhereByName(const char *pszName) = 0;
     210             : 
     211             :     OGRErr AbortSQL() override;
     212             :     bool SetQueryLoggerFunc(GDALQueryLoggerFunc pfnQueryLoggerFuncIn,
     213             :                             void *poQueryLoggerArgIn) override;
     214             : 
     215             :     OGRErr StartTransaction(int bForce = FALSE) override;
     216             :     OGRErr CommitTransaction() override;
     217             :     OGRErr RollbackTransaction() override;
     218             : 
     219             :     int TestCapability(const char *) const override;
     220             : 
     221             :     void *GetInternalHandle(const char *) override;
     222             : 
     223             :     OGRErr SoftStartTransaction();
     224             :     OGRErr SoftCommitTransaction();
     225             :     OGRErr SoftRollbackTransaction();
     226             :     OGRErr StartSavepoint(const std::string &osName);
     227             :     OGRErr ReleaseSavepoint(const std::string &osName);
     228             :     OGRErr RollbackToSavepoint(const std::string &osName);
     229             : 
     230             :     /**
     231             :      *  Execute a SQL transaction command (BEGIN, COMMIT, ROLLBACK, SAVEPOINT)
     232             :      *  @return TRUE if the osSQLCommand was recognized as a transaction command
     233             :      */
     234             :     bool ProcessTransactionSQL(const std::string &osSQLCommand);
     235             : 
     236             :     OGRErr PragmaCheck(const char *pszPragma, const char *pszExpected,
     237             :                        int nRowsExpected);
     238             : 
     239             :     virtual void LoadRelationships() const;
     240             :     void LoadRelationshipsFromForeignKeys(
     241             :         const std::vector<std::string> &excludedTables) const;
     242             :     std::vector<std::string>
     243             :     GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
     244             :     const GDALRelationship *
     245             :     GetRelationship(const std::string &name) const override;
     246             : 
     247             :     bool IsSpatialiteLoaded();
     248             : 
     249       10695 :     static int MakeSpatialiteVersionNumber(int x, int y, int z)
     250             :     {
     251       10695 :         return x * 10000 + y * 100 + z;
     252             :     }
     253             : 
     254             :     int GetSpatialiteVersionNumber();
     255             : 
     256             :     bool SpatialiteRequiresTrustedSchemaOn();
     257             :     bool AreSpatialiteTriggersSafe();
     258             : 
     259             :     // sqlite3_prepare_v2 error logging wrapper
     260             :     int
     261             :     prepareSql(sqlite3 *db,           /* Database handle */
     262             :                const char *zSql,      /* SQL statement, UTF-8 encoded */
     263             :                int nByte,             /* Maximum length of zSql in bytes. */
     264             :                sqlite3_stmt **ppStmt, /* OUT: Statement handle */
     265             :                const char **pzTail /* OUT: Pointer to unused portion of zSql */
     266             :     );
     267             : 
     268             :     GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
     269             :     void *poQueryLoggerArg = nullptr;
     270             : };
     271             : 
     272             : /************************************************************************/
     273             : /*                         IOGRSQLiteSelectLayer                        */
     274             : /************************************************************************/
     275             : 
     276        2222 : class IOGRSQLiteSelectLayer /* non final */
     277             : {
     278             :   public:
     279             :     virtual ~IOGRSQLiteSelectLayer();
     280             : 
     281             :     virtual char *&GetAttrQueryString() = 0;
     282             :     virtual OGRFeatureQuery *&GetFeatureQuery() = 0;
     283             :     virtual OGRGeometry *&GetFilterGeom() = 0;
     284             :     virtual int &GetIGeomFieldFilter() = 0;
     285             :     virtual const OGRSpatialReference *GetSpatialRef() const = 0;
     286             :     virtual const OGRFeatureDefn *GetLayerDefn() const = 0;
     287             :     virtual int InstallFilter(const OGRGeometry *) = 0;
     288             :     virtual int HasReadFeature() = 0;
     289             :     virtual void BaseResetReading() = 0;
     290             :     virtual OGRFeature *BaseGetNextFeature() = 0;
     291             :     virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) = 0;
     292             :     virtual GIntBig BaseGetFeatureCount(int bForce) = 0;
     293             :     virtual int BaseTestCapability(const char *) const = 0;
     294             :     virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
     295             :                                  bool bForce) = 0;
     296             :     virtual bool ValidateGeometryFieldIndexForSetSpatialFilter(
     297             :         int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer) = 0;
     298             : };
     299             : 
     300             : /************************************************************************/
     301             : /*                   OGRSQLiteSelectLayerCommonBehaviour                */
     302             : /************************************************************************/
     303             : 
     304             : class OGRSQLiteSelectLayerCommonBehaviour final
     305             : {
     306             :     OGRSQLiteBaseDataSource *m_poDS = nullptr;
     307             :     IOGRSQLiteSelectLayer *m_poLayer = nullptr;
     308             : 
     309             :     CPLString m_osSQLBase{};
     310             : 
     311             :     bool m_bEmptyLayer = false;
     312             :     bool m_bAllowResetReadingEvenIfIndexAtZero = false;
     313             :     bool m_bSpatialFilterInSQL = true;
     314             : 
     315             :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     316             :     GetBaseLayer(size_t &i) const;
     317             :     int BuildSQL();
     318             : 
     319             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSelectLayerCommonBehaviour)
     320             : 
     321             :   public:
     322             :     CPLString m_osSQLCurrent{};
     323             : 
     324             :     OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource *poDS,
     325             :                                         IOGRSQLiteSelectLayer *poBaseLayer,
     326             :                                         const CPLString &osSQL,
     327             :                                         bool bEmptyLayer);
     328             : 
     329             :     void ResetReading();
     330             :     OGRFeature *GetNextFeature();
     331             :     GIntBig GetFeatureCount(int);
     332             :     OGRErr SetSpatialFilter(int iGeomField, const OGRGeometry *);
     333             :     OGRErr SetAttributeFilter(const char *);
     334             :     int TestCapability(const char *) const;
     335             :     OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce);
     336             : };
     337             : 
     338             : /************************************************************************/
     339             : /*                   OGRSQLiteSingleFeatureLayer                        */
     340             : /************************************************************************/
     341             : 
     342             : class OGRSQLiteSingleFeatureLayer final : public OGRLayer
     343             : {
     344             :   private:
     345             :     int nVal;
     346             :     char *pszVal;
     347             :     OGRFeatureDefn *poFeatureDefn;
     348             :     int iNextShapeId;
     349             : 
     350             :     CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSingleFeatureLayer)
     351             : 
     352             :   public:
     353             :     OGRSQLiteSingleFeatureLayer(const char *pszLayerName, int nVal);
     354             :     OGRSQLiteSingleFeatureLayer(const char *pszLayerName, const char *pszVal);
     355             :     ~OGRSQLiteSingleFeatureLayer() override;
     356             : 
     357             :     void ResetReading() override;
     358             :     OGRFeature *GetNextFeature() override;
     359             :     const OGRFeatureDefn *GetLayerDefn() const override;
     360             :     int TestCapability(const char *) const override;
     361             : };
     362             : 
     363             : /************************************************************************/
     364             : /* Functions                                                            */
     365             : /************************************************************************/
     366             : 
     367             : OGRErr OGRSQLiteGetSpatialiteGeometryHeader(const GByte *pabyData, int nBytes,
     368             :                                             int *pnSRID,
     369             :                                             OGRwkbGeometryType *peType,
     370             :                                             bool *pbIsEmpty, double *pdfMinX,
     371             :                                             double *pdfMinY, double *pdfMaxX,
     372             :                                             double *pdfMaxY);
     373             : // CPL_DLL just for spatialite_geom_import_fuzzer
     374             : OGRErr CPL_DLL OGRSQLiteImportSpatiaLiteGeometry(const GByte *, int,
     375             :                                                  OGRGeometry **,
     376             :                                                  int *pnSRID = nullptr);
     377             : OGRErr OGRSQLiteExportSpatiaLiteGeometry(const OGRGeometry *, GInt32,
     378             :                                          OGRwkbByteOrder, bool bSpatialite2D,
     379             :                                          bool bUseComprGeom, GByte **, int *);
     380             : #endif  // OGR_SQLITE_BASE_H_INCLUDED

Generated by: LCOV version 1.14