LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gpkg - ogr_geopackage.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 105 118 89.0 %
Date: 2026-02-20 18:21:03 Functions: 44 48 91.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GeoPackage Translator
       4             :  * Purpose:  Definition of classes for OGR GeoPackage driver.
       5             :  * Author:   Paul Ramsey, pramsey@boundlessgeo.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2013, Paul Ramsey <pramsey@boundlessgeo.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_GEOPACKAGE_H_INCLUDED
      14             : #define OGR_GEOPACKAGE_H_INCLUDED
      15             : 
      16             : #include "ogrsf_frmts.h"
      17             : #include "ogrsqlitebase.h"
      18             : #include "gpkgmbtilescommon.h"
      19             : #include "ogrsqliteutility.h"
      20             : #include "cpl_threadsafe_queue.hpp"
      21             : #include "ograrrowarrayhelper.h"
      22             : #include "ogr_p.h"
      23             : #include "ogr_wkb.h"
      24             : 
      25             : #include <array>
      26             : #include <condition_variable>
      27             : #include <limits>
      28             : #include <mutex>
      29             : #include <queue>
      30             : #include <vector>
      31             : #include <set>
      32             : #include <thread>
      33             : #include <cctype>
      34             : 
      35             : #define UNKNOWN_SRID -2
      36             : #define DEFAULT_SRID 0
      37             : 
      38             : #define ENABLE_GPKG_OGR_CONTENTS
      39             : 
      40             : #if defined(DEBUG) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) ||     \
      41             :     defined(ALLOW_FORMAT_DUMPS)
      42             : // Enable accepting a SQL dump (starting with a "-- SQL GPKG" line) as a valid
      43             : // file. This makes fuzzer life easier
      44             : #define ENABLE_SQL_GPKG_FORMAT
      45             : #endif
      46             : 
      47             : typedef enum
      48             : {
      49             :     GPKG_ATTRIBUTES,
      50             :     NOT_REGISTERED,
      51             : } GPKGASpatialVariant;
      52             : 
      53             : // Requirement 2
      54             : static const GUInt32 GP10_APPLICATION_ID = 0x47503130U;
      55             : static const GUInt32 GP11_APPLICATION_ID = 0x47503131U;
      56             : static const GUInt32 GPKG_APPLICATION_ID = 0x47504B47U;
      57             : static const GUInt32 GPKG_1_2_VERSION = 10200U;
      58             : static const GUInt32 GPKG_1_3_VERSION = 10300U;
      59             : static const GUInt32 GPKG_1_4_VERSION = 10400U;
      60             : 
      61             : static const size_t knApplicationIdPos = 68;
      62             : static const size_t knUserVersionPos = 60;
      63             : 
      64             : struct GPKGExtensionDesc
      65             : {
      66             :     CPLString osExtensionName{};
      67             :     CPLString osDefinition{};
      68             :     CPLString osScope{};
      69             : };
      70             : 
      71             : struct GPKGContentsDesc
      72             : {
      73             :     CPLString osDataType{};
      74             :     CPLString osIdentifier{};
      75             :     CPLString osDescription{};
      76             :     CPLString osMinX{};
      77             :     CPLString osMinY{};
      78             :     CPLString osMaxX{};
      79             :     CPLString osMaxY{};
      80             : };
      81             : 
      82             : class OGRGeoPackageLayer;
      83             : 
      84             : struct OGRGPKGTableLayerFillArrowArray
      85             : {
      86             :     std::unique_ptr<OGRArrowArrayHelper> psHelper{};
      87             :     int nCountRows = 0;
      88             :     bool bErrorOccurred = false;
      89             :     bool bMemoryLimitReached = false;
      90             :     bool bDateTimeAsString = false;
      91             :     bool bAsynchronousMode = false;
      92             :     bool bIsFinished = false;
      93             :     bool bThreadReady = false;
      94             :     std::string osErrorMsg{};
      95             :     OGRFeatureDefn *poFeatureDefn = nullptr;
      96             :     OGRGeoPackageLayer *poLayer = nullptr;
      97             : 
      98             :     struct tm brokenDown{};
      99             : 
     100             :     sqlite3 *hDB = nullptr;
     101             :     std::mutex oMutex{};
     102             :     std::condition_variable oCV{};
     103             :     GIntBig nCurFID = 0;
     104             :     uint32_t nMemLimit = 0;
     105             :     // For spatial filtering
     106             :     const OGRLayer *poLayerForFilterGeom = nullptr;
     107             : };
     108             : 
     109             : void OGR_GPKG_Intersects_Spatial_Filter(sqlite3_context *pContext, int argc,
     110             :                                         sqlite3_value **argv);
     111             : 
     112             : /************************************************************************/
     113             : /*                        GDALGeoPackageDataset                         */
     114             : /************************************************************************/
     115             : 
     116             : class OGRGeoPackageTableLayer;
     117             : 
     118             : class GDALGeoPackageDataset final : public OGRSQLiteBaseDataSource,
     119             :                                     public GDALGPKGMBTilesLikePseudoDataset
     120             : {
     121             :     friend class GDALGeoPackageRasterBand;
     122             :     friend class OGRGeoPackageLayer;
     123             :     friend class OGRGeoPackageTableLayer;
     124             :     friend void OGRGeoPackageTransform(sqlite3_context *pContext, int argc,
     125             :                                        sqlite3_value **argv);
     126             : 
     127             :     std::string m_osFilenameInZip{};
     128             :     void *m_pSQLFunctionData = nullptr;
     129             :     GUInt32 m_nApplicationId = GPKG_APPLICATION_ID;
     130             :     GUInt32 m_nUserVersion = GPKG_1_4_VERSION;
     131             :     std::vector<std::unique_ptr<OGRGeoPackageTableLayer>> m_apoLayers{};
     132             :     void CheckUnknownExtensions(bool bCheckRasterTable = false);
     133             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     134             :     bool m_bHasGPKGOGRContents = false;
     135             : #endif
     136             :     bool m_bHasGPKGGeometryColumns = false;
     137             :     bool m_bHasDefinition12_063 = false;
     138             :     bool m_bHasEpochColumn =
     139             :         false;  // whether gpkg_spatial_ref_sys has a epoch column
     140             :     bool m_bNonSpatialTablesNonRegisteredInGpkgContentsFound = false;
     141             :     mutable int m_nHasMetadataTables = -1;  // -1 = unknown, 0 = false, 1 = true
     142             :     int m_nCreateMetadataTables = -1;  // -1 = on demand, 0 = false, 1 = true
     143             : 
     144             :     // Set by CreateTileGriddedTable() and used by FinalizeRasterRegistration()
     145             :     std::string m_osSQLInsertIntoGpkg2dGriddedCoverageAncillary{};
     146             : 
     147             :     CPLString m_osIdentifier{};
     148             :     bool m_bIdentifierAsCO = false;
     149             :     CPLString m_osDescription{};
     150             :     bool m_bDescriptionAsCO = false;
     151             :     bool m_bGridCellEncodingAsCO = false;
     152             :     bool m_bHasReadMetadataFromStorage = false;
     153             :     bool m_bMetadataDirty = false;
     154             :     CPLStringList m_aosSubDatasets{};
     155             :     OGRSpatialReference m_oSRS{};
     156             :     bool m_bRecordInsertedInGPKGContent = false;
     157             :     bool m_bGeoTransformValid = false;
     158             :     GDALGeoTransform m_gt{};
     159             :     int m_nSRID = -1;  // Unknown Cartesain
     160             :     double m_dfTMSMinX = 0.0;
     161             :     double m_dfTMSMaxY = 0.0;
     162             :     int m_nBandCountFromMetadata = 0;
     163             :     std::unique_ptr<GDALColorTable> m_poCTFromMetadata{};
     164             :     std::string m_osTFFromMetadata{};
     165             :     std::string m_osNodataValueFromMetadata{};
     166             : 
     167             :     // Used by OGRGeoPackageTransform
     168             :     int m_nLastCachedCTSrcSRId = -1;
     169             :     int m_nLastCachedCTDstSRId = -1;
     170             :     std::unique_ptr<OGRCoordinateTransformation> m_poLastCachedCT{};
     171             :     OGRWKBTransformCache m_oWKBTransformCache{};
     172             :     std::vector<GByte> m_abyWKBTransformCache{};
     173             : 
     174             :     std::vector<std::unique_ptr<GDALGeoPackageDataset>> m_apoOverviewDS{};
     175             :     bool m_bZoomOther = false;
     176             : 
     177             :     bool m_bInFlushCache = false;
     178             : 
     179             :     bool m_bDateTimeWithTZ = true;
     180             : 
     181             :     bool m_bRemoveOGREmptyTable = false;
     182             : 
     183             :     CPLString m_osTilingScheme = "CUSTOM";
     184             : 
     185             :     // To optimize reading table constraints
     186             :     int m_nReadTableDefCount = 0;
     187             :     std::vector<SQLSqliteMasterContent> m_aoSqliteMasterContent{};
     188             : 
     189         949 :     void IncrementReadTableDefCounter()
     190             :     {
     191         949 :         m_nReadTableDefCount++;
     192         949 :     }
     193             : 
     194         941 :     int GetReadTableDefCounter() const
     195             :     {
     196         941 :         return m_nReadTableDefCount;
     197             :     }
     198             : 
     199             :     const std::vector<SQLSqliteMasterContent> &GetSqliteMasterContent();
     200             : 
     201             :     bool ComputeTileAndPixelShifts();
     202             :     bool AllocCachedTiles();
     203             :     bool InitRaster(GDALGeoPackageDataset *poParentDS, const char *pszTableName,
     204             :                     double dfMinX, double dfMinY, double dfMaxX, double dfMaxY,
     205             :                     const char *pszContentsMinX, const char *pszContentsMinY,
     206             :                     const char *pszContentsMaxX, const char *pszContentsMaxY,
     207             :                     CSLConstList papszOpenOptions, const SQLResult &oResult,
     208             :                     int nIdxInResult);
     209             :     bool InitRaster(GDALGeoPackageDataset *poParentDS, const char *pszTableName,
     210             :                     int nZoomLevel, int nBandCount, double dfTMSMinX,
     211             :                     double dfTMSMaxY, double dfPixelXSize, double dfPixelYSize,
     212             :                     int nTileWidth, int nTileHeight, int nTileMatrixWidth,
     213             :                     int nTileMatrixHeight, double dfGDALMinX, double dfGDALMinY,
     214             :                     double dfGDALMaxX, double dfGDALMaxY);
     215             : 
     216             :     bool OpenRaster(const char *pszTableName, const char *pszIdentifier,
     217             :                     const char *pszDescription, int nSRSId, double dfMinX,
     218             :                     double dfMinY, double dfMaxX, double dfMaxY,
     219             :                     const char *pszContentsMinX, const char *pszContentsMinY,
     220             :                     const char *pszContentsMaxX, const char *pszContentsMaxY,
     221             :                     bool bIsTiles, CSLConstList papszOptions);
     222             :     CPLErr FinalizeRasterRegistration();
     223             : 
     224             :     bool RegisterWebPExtension();
     225             :     bool RegisterZoomOtherExtension();
     226             :     void ParseCompressionOptions(CSLConstList papszOptions);
     227             : 
     228             :     bool HasMetadataTables() const;
     229             :     bool CreateMetadataTables();
     230             :     const char *CheckMetadataDomain(const char *pszDomain);
     231             :     void
     232             :     WriteMetadata(CPLXMLNode *psXMLNode, /* will be destroyed by the method */
     233             :                   const char *pszTableName);
     234             :     void FlushMetadata();
     235             : 
     236             :     int FindLayerIndex(const char *pszLayerName);
     237             : 
     238             :     bool HasGriddedCoverageAncillaryTable();
     239             :     bool CreateTileGriddedTable(CSLConstList papszOptions);
     240             : 
     241             :     void RemoveOGREmptyTable();
     242             : 
     243             :     std::map<CPLString, CPLString> m_oMapNameToType{};
     244             :     const std::map<CPLString, CPLString> &GetNameTypeMapFromSQliteMaster();
     245             :     void RemoveTableFromSQLiteMasterCache(const char *pszTableName);
     246             : 
     247             :     bool m_bMapTableToExtensionsBuilt = false;
     248             :     std::map<CPLString, std::vector<GPKGExtensionDesc>>
     249             :         m_oMapTableToExtensions{};
     250             :     const std::map<CPLString, std::vector<GPKGExtensionDesc>> &
     251             :     GetUnknownExtensionsTableSpecific();
     252             : 
     253             :     bool m_bMapTableToContentsBuilt = false;
     254             :     std::map<CPLString, GPKGContentsDesc> m_oMapTableToContents{};
     255             :     const std::map<CPLString, GPKGContentsDesc> &GetContents();
     256             : 
     257             :     std::map<int, OGRSpatialReference *> m_oMapSrsIdToSrs{};
     258             : 
     259             :     OGRErr DeleteLayerCommon(const char *pszLayerName);
     260             :     OGRErr DeleteRasterLayer(const char *pszLayerName);
     261             :     bool DeleteVectorOrRasterLayer(const char *pszLayerName);
     262             :     bool RenameVectorOrRasterLayer(const char *pszLayerName,
     263             :                                    const char *pszNewName);
     264             :     bool RenameRasterLayer(const char *pszLayerName,
     265             :                            const char *pszNewLayerName);
     266             : 
     267             :     bool ConvertGpkgSpatialRefSysToExtensionWkt2(bool bForceEpoch);
     268             :     void DetectSpatialRefSysColumns();
     269             : 
     270             :     std::map<int, bool> m_oSetGPKGLayerWarnings{};
     271             : 
     272             :     void FixupWrongRTreeTrigger();
     273             :     void FixupWrongMedataReferenceColumnNameUpdate();
     274             :     void ClearCachedRelationships();
     275             :     void LoadRelationships() const override;
     276             :     void LoadRelationshipsUsingRelatedTablesExtension() const;
     277             :     static std::string
     278             :     GenerateNameForRelationship(const char *pszBaseTableName,
     279             :                                 const char *pszRelatedTableName,
     280             :                                 const char *pszType);
     281             :     bool ValidateRelationship(const GDALRelationship *poRelationship,
     282             :                               std::string &failureReason);
     283             : 
     284             :     // Used by GDALGeoPackageDataset::GetRasterLayerDataset()
     285             :     std::map<std::string, std::unique_ptr<GDALDataset>> m_oCachedRasterDS{};
     286             : 
     287             :     bool CloseDB();
     288             :     CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
     289             : 
     290             :     CPL_DISALLOW_COPY_ASSIGN(GDALGeoPackageDataset)
     291             : 
     292             :   public:
     293        2674 :     GDALGeoPackageDataset() = default;
     294             :     ~GDALGeoPackageDataset() override;
     295             : 
     296             :     char **GetFileList(void) override;
     297             : 
     298             :     CSLConstList GetMetadata(const char *pszDomain = "") override;
     299             :     virtual const char *GetMetadataItem(const char *pszName,
     300             :                                         const char *pszDomain = "") override;
     301             :     char **GetMetadataDomainList() override;
     302             :     CPLErr SetMetadata(CSLConstList papszMetadata,
     303             :                        const char *pszDomain = "") override;
     304             :     CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     305             :                            const char *pszDomain = "") override;
     306             : 
     307             :     const OGRSpatialReference *GetSpatialRef() const override;
     308             :     const OGRSpatialReference *GetSpatialRefRasterOnly() const override;
     309             :     CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
     310             : 
     311             :     CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
     312             :     CPLErr SetGeoTransform(const GDALGeoTransform &gt) override;
     313             : 
     314             :     CPLErr FlushCache(bool bAtClosing) override;
     315             :     CPLErr IBuildOverviews(const char *, int, const int *, int, const int *,
     316             :                            GDALProgressFunc, void *,
     317             :                            CSLConstList papszOptions) override;
     318             : 
     319       25033 :     int GetLayerCount() const override
     320             :     {
     321       25033 :         return static_cast<int>(m_apoLayers.size());
     322             :     }
     323             : 
     324             :     int Open(GDALOpenInfo *poOpenInfo, const std::string &osFilenameInZip);
     325             :     int Create(const char *pszFilename, int nXSize, int nYSize, int nBands,
     326             :                GDALDataType eDT, CSLConstList papszOptions);
     327             :     const OGRLayer *GetLayer(int iLayer) const override;
     328             :     OGRErr DeleteLayer(int iLayer) override;
     329             :     OGRLayer *ICreateLayer(const char *pszName,
     330             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     331             :                            CSLConstList papszOptions) override;
     332             :     int TestCapability(const char *) const override;
     333             : 
     334             :     std::vector<std::string>
     335             :     GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
     336             :     const OGRFieldDomain *
     337             :     GetFieldDomain(const std::string &name) const override;
     338             :     bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
     339             :                         std::string &failureReason) override;
     340             : 
     341             :     bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
     342             :                            std::string &failureReason) override;
     343             : 
     344             :     bool DeleteFieldDomain(const std::string &name,
     345             :                            std::string &failureReason) override;
     346             : 
     347             :     bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     348             :                          std::string &failureReason) override;
     349             : 
     350             :     bool DeleteRelationship(const std::string &name,
     351             :                             std::string &failureReason) override;
     352             : 
     353             :     bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     354             :                             std::string &failureReason) override;
     355             : 
     356             :     virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     357             :     GetLayerWithGetSpatialWhereByName(const char *pszName) override;
     358             : 
     359             :     OGRLayer *ExecuteSQL(const char *pszSQLCommand,
     360             :                          OGRGeometry *poSpatialFilter,
     361             :                          const char *pszDialect) override;
     362             :     void ReleaseResultSet(OGRLayer *poLayer) override;
     363             : 
     364             :     OGRErr CommitTransaction() override;
     365             :     OGRErr RollbackTransaction() override;
     366             : 
     367        7136 :     inline bool IsInTransaction() const
     368             :     {
     369        7136 :         return m_nSoftTransactionLevel > 0 || m_aosSavepoints.size() > 0;
     370             :     }
     371             : 
     372             :     static std::string LaunderName(const std::string &osStr);
     373             : 
     374             :     // At least 100000 to avoid conflicting with EPSG codes
     375             :     static constexpr int FIRST_CUSTOM_SRSID = 100000;
     376             : 
     377             :     int GetSrsId(const OGRSpatialReference *poSRS);
     378             :     static const char *GetSrsName(const OGRSpatialReference &oSRS);
     379             :     std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>
     380             :     GetSpatialRef(int iSrsId, bool bFallbackToEPSG = false,
     381             :                   bool bEmitErrorIfNotFound = true);
     382             :     OGRErr CreateExtensionsTableIfNecessary();
     383             :     bool HasExtensionsTable();
     384             : 
     385         435 :     void SetMetadataDirty()
     386             :     {
     387         435 :         m_bMetadataDirty = true;
     388         435 :     }
     389             : 
     390             :     bool HasDataColumnsTable() const;
     391             :     bool HasDataColumnConstraintsTable() const;
     392             :     bool HasDataColumnConstraintsTableGPKG_1_0() const;
     393             :     bool CreateColumnsTableAndColumnConstraintsTablesIfNecessary();
     394             :     bool HasGpkgextRelationsTable() const;
     395             :     bool CreateRelationsTableIfNecessary();
     396             :     bool HasQGISLayerStyles() const;
     397             : 
     398          79 :     bool HasNonSpatialTablesNonRegisteredInGpkgContents() const
     399             :     {
     400          79 :         return m_bNonSpatialTablesNonRegisteredInGpkgContentsFound;
     401             :     }
     402             : 
     403             :     const char *GetGeometryTypeString(OGRwkbGeometryType eType);
     404             : 
     405             :     void ResetReadingAllLayers();
     406             :     OGRErr UpdateGpkgContentsLastChange(const char *pszTableName);
     407             : 
     408             :     static GDALDataset *CreateCopy(const char *pszFilename,
     409             :                                    GDALDataset *poSrcDS, int bStrict,
     410             :                                    CSLConstList papszOptions,
     411             :                                    GDALProgressFunc pfnProgress,
     412             :                                    void *pProgressData);
     413             : 
     414             :     static std::string GetCurrentDateEscapedSQL();
     415             : 
     416             :     GDALDataset *GetRasterLayerDataset(const char *pszLayerName);
     417             : 
     418             :   protected:
     419             :     CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
     420             :                      GDALDataType, int, BANDMAP_TYPE, GSpacing, GSpacing,
     421             :                      GSpacing, GDALRasterIOExtraArg *psExtraArg) override;
     422             : 
     423             :     // Coming from GDALGPKGMBTilesLikePseudoDataset
     424             : 
     425             :     CPLErr IFlushCacheWithErrCode(bool bAtClosing) override;
     426             : 
     427       26044 :     int IGetRasterCount() override
     428             :     {
     429       26044 :         return nBands;
     430             :     }
     431             : 
     432       55049 :     GDALRasterBand *IGetRasterBand(int nBand) override
     433             :     {
     434       55049 :         return GetRasterBand(nBand);
     435             :     }
     436             : 
     437       10015 :     sqlite3 *IGetDB() override
     438             :     {
     439       10015 :         return GetDB();
     440             :     }
     441             : 
     442       15934 :     bool IGetUpdate() override
     443             :     {
     444       15934 :         return GetUpdate();
     445             :     }
     446             : 
     447             :     bool ICanIWriteBlock() override;
     448             : 
     449         169 :     OGRErr IStartTransaction() override
     450             :     {
     451         169 :         return SoftStartTransaction();
     452             :     }
     453             : 
     454         169 :     OGRErr ICommitTransaction() override
     455             :     {
     456         169 :         return SoftCommitTransaction();
     457             :     }
     458             : 
     459          26 :     const char *IGetFilename() override
     460             :     {
     461          26 :         return m_pszFilename;
     462             :     }
     463             : 
     464        9789 :     int GetRowFromIntoTopConvention(int nRow) override
     465             :     {
     466        9789 :         return nRow;
     467             :     }
     468             : 
     469             :   private:
     470             :     OGRErr SetApplicationAndUserVersionId();
     471             :     bool ReOpenDB();
     472             :     bool OpenOrCreateDB(int flags);
     473             :     void InstallSQLFunctions();
     474             :     bool HasGDALAspatialExtension();
     475             :     std::string CreateRasterTriggersSQL(const std::string &osTableName);
     476             : };
     477             : 
     478             : /************************************************************************/
     479             : /*                 GPKGTemporaryForeignKeyCheckDisabler                 */
     480             : /************************************************************************/
     481             : 
     482             : //! Instance of that class temporarily disable foreign key checks
     483             : class GPKGTemporaryForeignKeyCheckDisabler
     484             : {
     485             :   public:
     486         262 :     explicit GPKGTemporaryForeignKeyCheckDisabler(GDALGeoPackageDataset *poDS)
     487         262 :         : m_poDS(poDS), m_nPragmaForeignKeysOldValue(SQLGetInteger(
     488         262 :                             m_poDS->GetDB(), "PRAGMA foreign_keys", nullptr))
     489             :     {
     490         262 :         if (m_nPragmaForeignKeysOldValue)
     491             :         {
     492           0 :             CPL_IGNORE_RET_VAL(
     493           0 :                 SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 0"));
     494             :         }
     495         262 :     }
     496             : 
     497         262 :     ~GPKGTemporaryForeignKeyCheckDisabler()
     498         262 :     {
     499         262 :         if (m_nPragmaForeignKeysOldValue)
     500             :         {
     501           0 :             CPL_IGNORE_RET_VAL(
     502           0 :                 SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 1"));
     503             :         }
     504         262 :     }
     505             : 
     506             :   private:
     507             :     CPL_DISALLOW_COPY_ASSIGN(GPKGTemporaryForeignKeyCheckDisabler)
     508             : 
     509             :     GDALGeoPackageDataset *m_poDS = nullptr;
     510             :     int m_nPragmaForeignKeysOldValue = 0;
     511             : };
     512             : 
     513             : /************************************************************************/
     514             : /*                       GDALGeoPackageRasterBand                       */
     515             : /************************************************************************/
     516             : 
     517             : class GDALGeoPackageRasterBand final : public GDALGPKGMBTilesLikeRasterBand
     518             : {
     519             :     // Whether STATISTICS_MINIMUM and/or STATISTICS_MAXIMUM have been computed
     520             :     // from the min, max columns of the gpkg_2d_gridded_tile_ancillary table
     521             :     // (only for non-Byte data)
     522             :     bool m_bMinMaxComputedFromTileAncillary = false;
     523             :     double m_dfStatsMinFromTileAncillary =
     524             :         std::numeric_limits<double>::quiet_NaN();
     525             :     double m_dfStatsMaxFromTileAncillary =
     526             :         std::numeric_limits<double>::quiet_NaN();
     527             :     CPLStringList m_aosMD{};
     528             : 
     529             :     // Whether gpkg_metadata has been read to set initial metadata
     530             :     bool m_bHasReadMetadataFromStorage = false;
     531             : 
     532             :     // Whether STATISTICS_* have been set in this "session"
     533             :     bool m_bStatsMetadataSetInThisSession = false;
     534             : 
     535             :     bool m_bAddImplicitStatistics = true;
     536             : 
     537             :     void LoadBandMetadata();
     538             : 
     539             :   public:
     540             :     GDALGeoPackageRasterBand(GDALGeoPackageDataset *poDS, int nTileWidth,
     541             :                              int nTileHeight);
     542             : 
     543             :     int GetOverviewCount() override;
     544             :     GDALRasterBand *GetOverview(int nIdx) override;
     545             : 
     546             :     CPLErr SetNoDataValue(double dfNoDataValue) override;
     547             : 
     548             :     CSLConstList GetMetadata(const char *pszDomain = "") override;
     549             :     virtual const char *GetMetadataItem(const char *pszName,
     550             :                                         const char *pszDomain = "") override;
     551             :     CPLErr SetMetadata(CSLConstList papszMetadata,
     552             :                        const char *pszDomain = "") override;
     553             :     CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     554             :                            const char *pszDomain = "") override;
     555             : 
     556         498 :     void AddImplicitStatistics(bool b)
     557             :     {
     558         498 :         m_bAddImplicitStatistics = b;
     559         498 :     }
     560             : 
     561         359 :     inline bool HaveStatsMetadataBeenSetInThisSession() const
     562             :     {
     563         359 :         return m_bStatsMetadataSetInThisSession;
     564             :     }
     565             : 
     566             :     void InvalidateStatistics();
     567             : };
     568             : 
     569             : /************************************************************************/
     570             : /*                          OGRGeoPackageLayer                          */
     571             : /************************************************************************/
     572             : 
     573             : class OGRGeoPackageLayer CPL_NON_FINAL : public OGRLayer,
     574             :                                          public IOGRSQLiteGetSpatialWhere
     575             : {
     576             :   protected:
     577             :     friend void OGR_GPKG_FillArrowArray_Step(sqlite3_context *pContext,
     578             :                                              int /*argc*/,
     579             :                                              sqlite3_value **argv);
     580             : 
     581             :     GDALGeoPackageDataset *m_poDS = nullptr;
     582             : 
     583             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
     584             :     GIntBig m_iNextShapeId = 0;
     585             : 
     586             :     sqlite3_stmt *m_poQueryStatement = nullptr;
     587             :     bool m_bDoStep = true;
     588             :     bool m_bEOF = false;
     589             : 
     590             :     char *m_pszFidColumn = nullptr;
     591             : 
     592             :     int m_iFIDCol = -1;
     593             :     int m_iGeomCol = -1;
     594             :     std::vector<int> m_anFieldOrdinals{};
     595             : 
     596             :     //! Whether to call OGRGeometry::SetPrecision() when reading back geometries from the database
     597             :     bool m_bUndoDiscardCoordLSBOnReading = false;
     598             : 
     599             :     void ClearStatement();
     600             :     virtual OGRErr ResetStatement() = 0;
     601             : 
     602             :     void BuildFeatureDefn(const char *pszLayerName, sqlite3_stmt *hStmt);
     603             : 
     604             :     OGRFeature *TranslateFeature(sqlite3_stmt *hStmt);
     605             :     bool ParseDateField(const char *pszTxt, OGRField *psField,
     606             :                         const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     607             :     bool ParseDateField(sqlite3_stmt *hStmt, int iRawField, int nSqlite3ColType,
     608             :                         OGRField *psField, const OGRFieldDefn *poFieldDefn,
     609             :                         GIntBig nFID);
     610             :     bool ParseDateTimeField(const char *pszTxt, OGRField *psField,
     611             :                             const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     612             :     bool ParseDateTimeField(sqlite3_stmt *hStmt, int iRawField,
     613             :                             int nSqlite3ColType, OGRField *psField,
     614             :                             const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     615             : 
     616         192 :     GDALDataset *GetDataset() override
     617             :     {
     618         192 :         return m_poDS;
     619             :     }
     620             : 
     621             :     virtual bool GetArrowStream(struct ArrowArrayStream *out_stream,
     622             :                                 CSLConstList papszOptions = nullptr) override;
     623             :     virtual int GetNextArrowArray(struct ArrowArrayStream *,
     624             :                                   struct ArrowArray *out_array) override;
     625             : 
     626             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageLayer)
     627             : 
     628             :   public:
     629             :     explicit OGRGeoPackageLayer(GDALGeoPackageDataset *poDS);
     630             :     ~OGRGeoPackageLayer() override;
     631             :     /************************************************************************/
     632             :     /* OGR API methods */
     633             : 
     634             :     OGRFeature *GetNextFeature() override;
     635             :     const char *GetFIDColumn() const override;
     636             :     void ResetReading() override;
     637             :     int TestCapability(const char *) const override;
     638             : 
     639         345 :     const OGRFeatureDefn *GetLayerDefn() const override
     640             :     {
     641         345 :         return m_poFeatureDefn;
     642             :     }
     643             : 
     644             :     OGRErr SetIgnoredFields(CSLConstList papszFields) override;
     645             : 
     646           0 :     bool HasFastSpatialFilter(int /*iGeomCol*/) override
     647             :     {
     648           0 :         return false;
     649             :     }
     650             : 
     651           0 :     virtual CPLString GetSpatialWhere(int /*iGeomCol*/,
     652             :                                       OGRGeometry * /*poFilterGeom*/) override
     653             :     {
     654           0 :         return "";
     655             :     }
     656             : };
     657             : 
     658             : /************************************************************************/
     659             : /*                       OGRGeoPackageTableLayer                        */
     660             : /************************************************************************/
     661             : 
     662             : struct OGRGPKGTableLayerFillArrowArray;
     663             : struct sqlite_rtree_bl;
     664             : 
     665             : class OGRGeoPackageTableLayer final : public OGRGeoPackageLayer
     666             : {
     667             :     char *m_pszTableName = nullptr;
     668             :     bool m_bIsTable = true;  // sensible init for creation mode
     669             :     bool m_bIsSpatial = false;
     670             :     bool m_bIsInGpkgContents = false;
     671             :     mutable bool m_bFeatureDefnCompleted = false;
     672             :     int m_iSrs = 0;
     673             :     int m_nZFlag = 0;
     674             :     int m_nMFlag = 0;
     675             :     OGRGeomCoordinateBinaryPrecision m_sBinaryPrecision{};
     676             :     std::unique_ptr<OGREnvelope> m_poExtent{};
     677             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     678             :     GIntBig m_nTotalFeatureCount = -1;
     679             :     bool m_bOGRFeatureCountTriggersEnabled = false;
     680             :     bool m_bAddOGRFeatureCountTriggers = false;
     681             :     bool m_bFeatureCountTriggersDeletedInTransaction = false;
     682             : #endif
     683             :     CPLString m_soColumns{};
     684             :     CPLString m_soFilter{};
     685             :     CPLString osQuery{};
     686             :     mutable CPLString m_osRTreeName{};
     687             :     mutable CPLString m_osFIDForRTree{};
     688             :     bool m_bExtentChanged = false;
     689             :     bool m_bContentChanged = false;
     690             :     sqlite3_stmt *m_poUpdateStatement = nullptr;
     691             :     std::string m_osUpdateStatementSQL{};
     692             :     bool m_bInsertStatementWithFID = false;
     693             :     bool m_bInsertStatementWithUpsert = false;
     694             :     std::string m_osInsertStatementUpsertUniqueColumnName{};
     695             :     sqlite3_stmt *m_poInsertStatement = nullptr;
     696             :     sqlite3_stmt *m_poGetFeatureStatement = nullptr;
     697             :     bool m_bDeferredSpatialIndexCreation = false;
     698             :     // m_bHasSpatialIndex cannot be bool.  -1 is unset.
     699             :     mutable int m_bHasSpatialIndex = -1;
     700             :     bool m_bDropRTreeTable = false;
     701             :     bool m_abHasGeometryExtension[wkbTriangle + 1];
     702             :     bool m_bPreservePrecision = true;
     703             :     bool m_bTruncateFields = false;
     704             :     bool m_bDeferredCreation = false;
     705             :     bool m_bTableCreatedInTransaction = false;
     706             :     bool m_bLaunder = false;
     707             :     int m_iFIDAsRegularColumnIndex = -1;
     708             :     std::string m_osInsertionBuffer{};  // used by FeatureBindParameters to
     709             :                                         // store datetime values
     710             : 
     711             :     CPLString m_osIdentifierLCO{};
     712             :     CPLString m_osDescriptionLCO{};
     713             :     bool m_bHasReadMetadataFromStorage = false;
     714             :     bool m_bHasTriedDetectingFID64 = false;
     715             :     GPKGASpatialVariant m_eASpatialVariant = GPKG_ATTRIBUTES;
     716             :     std::set<OGRwkbGeometryType> m_eSetBadGeomTypeWarned{};
     717             : 
     718             :     int m_nIsCompatOfOptimizedGetNextArrowArray = -1;
     719             :     bool m_bGetNextArrowArrayCalledSinceResetReading = false;
     720             : 
     721             :     int m_nCountInsertInTransactionThreshold = -1;
     722             :     GIntBig m_nCountInsertInTransaction = 0;
     723             :     std::vector<CPLString> m_aoRTreeTriggersSQL{};
     724             :     bool m_bUpdate1TriggerDisabled = false;
     725             :     bool m_bHasUpdate6And7Triggers = false;
     726             :     std::string m_osUpdate1Trigger{};
     727             : 
     728             :     typedef struct
     729             :     {
     730             :         GIntBig nId;
     731             :         float fMinX;
     732             :         float fMinY;
     733             :         float fMaxX;
     734             :         float fMaxY;
     735             :     } GPKGRTreeEntry;
     736             : 
     737             :     std::vector<GPKGRTreeEntry> m_aoRTreeEntries{};
     738             : 
     739             :     // Variables used for background RTree building
     740             :     std::string m_osAsyncDBName{};
     741             :     std::string m_osAsyncDBAttachName{};
     742             :     sqlite3 *m_hAsyncDBHandle = nullptr;
     743             :     sqlite_rtree_bl *m_hRTree = nullptr;
     744             :     cpl::ThreadSafeQueue<std::vector<GPKGRTreeEntry>> m_oQueueRTreeEntries{};
     745             :     bool m_bAllowedRTreeThread = false;
     746             :     bool m_bThreadRTreeStarted = false;
     747             :     bool m_bErrorDuringRTreeThread = false;
     748             :     size_t m_nRTreeBatchSize =
     749             :         10 * 1000;  // maximum size of a std::vector<GPKGRTreeEntry> item in
     750             :                     // m_oQueueRTreeEntries
     751             :     size_t m_nRTreeBatchesBeforeStart =
     752             :         10;  // number of items in m_oQueueRTreeEntries before starting the
     753             :              // thread
     754             :     std::thread m_oThreadRTree{};
     755             : 
     756             :     OGRISO8601Format m_sDateTimeFormat = {OGRISO8601Precision::AUTO};
     757             : 
     758             :     void StartAsyncRTree();
     759             :     void CancelAsyncRTree();
     760             :     void RemoveAsyncRTreeTempDB();
     761             :     void AsyncRTreeThreadFunction();
     762             : 
     763             :     OGRErr ResetStatementInternal(GIntBig nStartIndex);
     764             :     OGRErr ResetStatement() override;
     765             : 
     766             :     void BuildWhere();
     767             :     OGRErr RegisterGeometryColumn();
     768             : 
     769             :     CPLString
     770             :     GetColumnsOfCreateTable(const std::vector<OGRFieldDefn *> &apoFields);
     771             :     CPLString
     772             :     BuildSelectFieldList(const std::vector<OGRFieldDefn *> &apoFields);
     773             :     OGRErr RecreateTable(const CPLString &osColumnsForCreate,
     774             :                          const CPLString &osFieldListForSelect);
     775             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     776             :     void CreateFeatureCountTriggers(const char *pszTableName = nullptr);
     777             :     void DisableFeatureCountTriggers(bool bNullifyFeatureCount = true);
     778             : #endif
     779             : 
     780             :     void CheckGeometryType(const OGRFeature *poFeature);
     781             : 
     782             :     OGRErr ReadTableDefinition();
     783             :     void InitView();
     784             : 
     785             :     bool DoSpecialProcessingForColumnCreation(const OGRFieldDefn *poField);
     786             : 
     787             :     bool StartDeferredSpatialIndexUpdate();
     788             :     bool FlushPendingSpatialIndexUpdate();
     789             :     void WorkaroundUpdate1TriggerIssue();
     790             :     void RevertWorkaroundUpdate1TriggerIssue();
     791             : 
     792             :     OGRErr RenameFieldInAuxiliaryTables(const char *pszOldName,
     793             :                                         const char *pszNewName);
     794             : 
     795             :     OGRErr CreateOrUpsertFeature(OGRFeature *poFeature, bool bUpsert);
     796             : 
     797             :     GIntBig GetTotalFeatureCount();
     798             : 
     799             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageTableLayer)
     800             : 
     801             :     // Used when m_nIsCompatOfOptimizedGetNextArrowArray == TRUE
     802             :     struct ArrowArrayPrefetchTask
     803             :     {
     804             :         std::thread m_oThread{};
     805             :         std::condition_variable m_oCV{};
     806             :         std::mutex m_oMutex{};
     807             :         bool m_bArrayReady = false;
     808             :         bool m_bFetchRows = false;
     809             :         bool m_bStop = false;
     810             :         bool m_bMemoryLimitReached = false;
     811             :         std::string m_osErrorMsg{};
     812             :         std::unique_ptr<GDALGeoPackageDataset> m_poDS{};
     813             :         OGRGeoPackageTableLayer *m_poLayer{};
     814             :         GIntBig m_iStartShapeId = 0;
     815             :         std::unique_ptr<struct ArrowArray> m_psArrowArray = nullptr;
     816             :     };
     817             : 
     818             :     std::queue<std::unique_ptr<ArrowArrayPrefetchTask>>
     819             :         m_oQueueArrowArrayPrefetchTasks{};
     820             : 
     821             :     // Used when m_nIsCompatOfOptimizedGetNextArrowArray == FALSE
     822             :     std::thread m_oThreadNextArrowArray{};
     823             :     std::unique_ptr<OGRGPKGTableLayerFillArrowArray> m_poFillArrowArray{};
     824             :     std::unique_ptr<GDALGeoPackageDataset> m_poOtherDS{};
     825             : 
     826             :     virtual int GetNextArrowArray(struct ArrowArrayStream *,
     827             :                                   struct ArrowArray *out_array) override;
     828             :     int GetNextArrowArrayInternal(struct ArrowArray *out_array,
     829             :                                   std::string &osErrorMsg,
     830             :                                   bool &bMemoryLimitReached);
     831             :     int GetNextArrowArrayAsynchronous(struct ArrowArrayStream *stream,
     832             :                                       struct ArrowArray *out_array);
     833             :     void GetNextArrowArrayAsynchronousWorker();
     834             :     void CancelAsyncNextArrowArray();
     835             : 
     836             :   protected:
     837             :     friend void OGR_GPKG_Intersects_Spatial_Filter(sqlite3_context *pContext,
     838             :                                                    int /*argc*/,
     839             :                                                    sqlite3_value **argv);
     840             : 
     841             :   public:
     842             :     OGRGeoPackageTableLayer(GDALGeoPackageDataset *poDS,
     843             :                             const char *pszTableName);
     844             :     ~OGRGeoPackageTableLayer() override;
     845             : 
     846             :     /************************************************************************/
     847             :     /* OGR API methods */
     848             : 
     849       11722 :     const char *GetName() const override
     850             :     {
     851       11722 :         return GetDescription();
     852             :     }
     853             : 
     854             :     const char *GetFIDColumn() const override;
     855             :     OGRwkbGeometryType GetGeomType() const override;
     856             :     const char *GetGeometryColumn() const override;
     857             :     const OGRFeatureDefn *GetLayerDefn() const override;
     858             :     int TestCapability(const char *) const override;
     859             :     OGRErr CreateField(const OGRFieldDefn *poField,
     860             :                        int bApproxOK = TRUE) override;
     861             :     OGRErr CreateGeomField(const OGRGeomFieldDefn *poGeomFieldIn,
     862             :                            int bApproxOK = TRUE) override;
     863             :     OGRErr DeleteField(int iFieldToDelete) override;
     864             :     virtual OGRErr AlterFieldDefn(int iFieldToAlter,
     865             :                                   OGRFieldDefn *poNewFieldDefn,
     866             :                                   int nFlagsIn) override;
     867             :     virtual OGRErr
     868             :     AlterGeomFieldDefn(int iGeomFieldToAlter,
     869             :                        const OGRGeomFieldDefn *poNewGeomFieldDefn,
     870             :                        int nFlagsIn) override;
     871             :     OGRErr ReorderFields(int *panMap) override;
     872             :     void ResetReading() override;
     873             :     OGRErr SetNextByIndex(GIntBig nIndex) override;
     874             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     875             :     OGRErr ISetFeature(OGRFeature *poFeature) override;
     876             :     OGRErr IUpsertFeature(OGRFeature *poFeature) override;
     877             :     OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
     878             :                           const int *panUpdatedFieldsIdx,
     879             :                           int nUpdatedGeomFieldsCount,
     880             :                           const int *panUpdatedGeomFieldsIdx,
     881             :                           bool bUpdateStyleString) override;
     882             :     OGRErr DeleteFeature(GIntBig nFID) override;
     883             : 
     884             :     OGRErr ISetSpatialFilter(int iGeomField,
     885             :                              const OGRGeometry *poGeom) override;
     886             : 
     887             :     OGRErr SetAttributeFilter(const char *pszQuery) override;
     888             :     OGRErr SyncToDisk() override;
     889             :     OGRFeature *GetNextFeature() override;
     890             :     OGRFeature *GetFeature(GIntBig nFID) override;
     891             :     OGRErr StartTransaction() override;
     892             :     OGRErr CommitTransaction() override;
     893             :     OGRErr RollbackTransaction() override;
     894             :     GIntBig GetFeatureCount(int) override;
     895             : 
     896             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     897             :                       bool bForce) override;
     898             : 
     899             :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
     900             :                         bool bForce) override;
     901             :     OGRGeometryTypeCounter *GetGeometryTypes(int iGeomField, int nFlagsGGT,
     902             :                                              int &nEntryCountOut,
     903             :                                              GDALProgressFunc pfnProgress,
     904             :                                              void *pProgressData) override;
     905             : 
     906             :     void RecomputeExtent();
     907             : 
     908             :     void SetOpeningParameters(const char *pszTableName,
     909             :                               const char *pszObjectType, bool bIsInGpkgContents,
     910             :                               bool bIsSpatial, const char *pszGeomColName,
     911             :                               const char *pszGeomType, bool bHasZ, bool bHasM);
     912             :     void SetCreationParameters(
     913             :         OGRwkbGeometryType eGType, const char *pszGeomColumnName,
     914             :         int bGeomNullable, const OGRSpatialReference *poSRS,
     915             :         const char *pszSRID, const OGRGeomCoordinatePrecision &oCoordPrec,
     916             :         bool bDiscardCoordLSB, bool bUndoDiscardCoordLSBOnReading,
     917             :         const char *pszFIDColumnName, const char *pszIdentifier,
     918             :         const char *pszDescription);
     919             :     void SetDeferredSpatialIndexCreation(bool bFlag);
     920             : 
     921          79 :     void SetASpatialVariant(GPKGASpatialVariant eASpatialVariant)
     922             :     {
     923          79 :         m_eASpatialVariant = eASpatialVariant;
     924          79 :         if (eASpatialVariant == GPKG_ATTRIBUTES)
     925          67 :             m_bIsInGpkgContents = true;
     926          79 :     }
     927             : 
     928          17 :     void SetDateTimePrecision(OGRISO8601Precision ePrecision)
     929             :     {
     930          17 :         m_sDateTimeFormat.ePrecision = ePrecision;
     931          17 :     }
     932             : 
     933             :     void CreateSpatialIndexIfNecessary();
     934             :     void FinishOrDisableThreadedRTree();
     935             :     bool FlushInMemoryRTree(sqlite3 *hRTreeDB, const char *pszRTreeName);
     936             :     bool CreateSpatialIndex(const char *pszTableName = nullptr);
     937             :     bool DropSpatialIndex(bool bCalledFromSQLFunction = false);
     938             :     CPLString ReturnSQLCreateSpatialIndexTriggers(const char *pszTableName,
     939             :                                                   const char *pszGeomColName);
     940             :     CPLString ReturnSQLDropSpatialIndexTriggers();
     941             : 
     942             :     CSLConstList GetMetadata(const char *pszDomain = "") override;
     943             :     virtual const char *GetMetadataItem(const char *pszName,
     944             :                                         const char *pszDomain = "") override;
     945             :     char **GetMetadataDomainList() override;
     946             : 
     947             :     CPLErr SetMetadata(CSLConstList papszMetadata,
     948             :                        const char *pszDomain = "") override;
     949             :     CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     950             :                            const char *pszDomain = "") override;
     951             : 
     952             :     OGRErr Rename(const char *pszDstTableName) override;
     953             : 
     954             :     bool HasFastSpatialFilter(int iGeomCol) override;
     955             :     virtual CPLString GetSpatialWhere(int iGeomCol,
     956             :                                       OGRGeometry *poFilterGeom) override;
     957             : 
     958             :     OGRErr Truncate();
     959             : 
     960             :     bool HasSpatialIndex() const;
     961             : 
     962         890 :     void SetPrecisionFlag(int bFlag)
     963             :     {
     964         890 :         m_bPreservePrecision = CPL_TO_BOOL(bFlag);
     965         890 :     }
     966             : 
     967         890 :     void SetTruncateFieldsFlag(int bFlag)
     968             :     {
     969         890 :         m_bTruncateFields = CPL_TO_BOOL(bFlag);
     970         890 :     }
     971             : 
     972         890 :     void SetLaunder(bool bFlag)
     973             :     {
     974         890 :         m_bLaunder = bFlag;
     975         890 :     }
     976             : 
     977             :     OGRErr RunDeferredCreationIfNecessary();
     978             :     bool RunDeferredDropRTreeTableIfNecessary();
     979             :     bool DoJobAtTransactionCommit();
     980             :     bool DoJobAtTransactionRollback();
     981             :     bool RunDeferredSpatialIndexUpdate();
     982             : 
     983             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     984          36 :     bool GetAddOGRFeatureCountTriggers() const
     985             :     {
     986          36 :         return m_bAddOGRFeatureCountTriggers;
     987             :     }
     988             : 
     989          65 :     void SetAddOGRFeatureCountTriggers(bool b)
     990             :     {
     991          65 :         m_bAddOGRFeatureCountTriggers = b;
     992          65 :     }
     993             : 
     994          36 :     bool GetOGRFeatureCountTriggersDeletedInTransaction() const
     995             :     {
     996          36 :         return m_bFeatureCountTriggersDeletedInTransaction;
     997             :     }
     998             : 
     999           7 :     void SetOGRFeatureCountTriggersEnabled(bool b)
    1000             :     {
    1001           7 :         m_bOGRFeatureCountTriggersEnabled = b;
    1002           7 :     }
    1003             : 
    1004             :     void DisableFeatureCount();
    1005             : #endif
    1006             : 
    1007             :     bool CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType);
    1008             : 
    1009             :     /************************************************************************/
    1010             :     /* GPKG methods */
    1011             : 
    1012             :   private:
    1013             :     bool CheckUpdatableTable(const char *pszOperation);
    1014             :     OGRErr UpdateExtent(const OGREnvelope *poExtent);
    1015             :     OGRErr SaveExtent();
    1016             :     OGRErr SaveTimestamp();
    1017             :     OGRErr BuildColumns();
    1018             :     static bool IsGeomFieldSet(OGRFeature *poFeature);
    1019             :     std::string FeatureGenerateUpdateSQL(const OGRFeature *poFeature) const;
    1020             :     std::string FeatureGenerateUpdateSQL(
    1021             :         const OGRFeature *poFeature, int nUpdatedFieldsCount,
    1022             :         const int *panUpdatedFieldsIdx, int nUpdatedGeomFieldsCount,
    1023             :         const int *panUpdatedGeomFieldsIdx) const;
    1024             :     CPLString
    1025             :     FeatureGenerateInsertSQL(OGRFeature *poFeature, bool bAddFID,
    1026             :                              bool bBindUnsetFields, bool bUpsert,
    1027             :                              const std::string &osUpsertUniqueColumnName);
    1028             :     OGRErr FeatureBindUpdateParameters(OGRFeature *poFeature,
    1029             :                                        sqlite3_stmt *poStmt);
    1030             :     OGRErr FeatureBindInsertParameters(OGRFeature *poFeature,
    1031             :                                        sqlite3_stmt *poStmt, bool bAddFID,
    1032             :                                        bool bBindUnsetFields);
    1033             :     OGRErr FeatureBindParameters(OGRFeature *poFeature, sqlite3_stmt *poStmt,
    1034             :                                  int *pnColCount, bool bAddFID,
    1035             :                                  bool bBindUnsetFields, int nUpdatedFieldsCount,
    1036             :                                  const int *panUpdatedFieldsIdx,
    1037             :                                  int nUpdatedGeomFieldsCount,
    1038             :                                  const int *panUpdatedGeomFieldsIdx);
    1039             : 
    1040             :     void UpdateContentsToNullExtent();
    1041             : 
    1042             :     void CheckUnknownExtensions();
    1043             :     bool CreateGeometryExtensionIfNecessary(const OGRGeometry *poGeom);
    1044             : };
    1045             : 
    1046             : /************************************************************************/
    1047             : /*                       OGRGeoPackageSelectLayer                       */
    1048             : /************************************************************************/
    1049             : 
    1050             : class OGRGeoPackageSelectLayer final : public OGRGeoPackageLayer,
    1051             :                                        public IOGRSQLiteSelectLayer
    1052             : {
    1053             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageSelectLayer)
    1054             : 
    1055             :     OGRSQLiteSelectLayerCommonBehaviour *poBehavior = nullptr;
    1056             : 
    1057             :     OGRErr ResetStatement() override;
    1058             : 
    1059             :   public:
    1060             :     OGRGeoPackageSelectLayer(GDALGeoPackageDataset *, const CPLString &osSQL,
    1061             :                              sqlite3_stmt *,
    1062             :                              bool bUseStatementForGetNextFeature,
    1063             :                              bool bEmptyLayer);
    1064             :     ~OGRGeoPackageSelectLayer() override;
    1065             : 
    1066             :     void ResetReading() override;
    1067             : 
    1068             :     OGRFeature *GetNextFeature() override;
    1069             :     GIntBig GetFeatureCount(int) override;
    1070             : 
    1071             :     OGRErr ISetSpatialFilter(int iGeomField, const OGRGeometry *) override;
    1072             :     OGRErr SetAttributeFilter(const char *) override;
    1073             : 
    1074             :     int TestCapability(const char *) const override;
    1075             : 
    1076             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
    1077             :                       bool bForce) override;
    1078             : 
    1079         345 :     const OGRFeatureDefn *GetLayerDefn() const override
    1080             :     {
    1081         345 :         return OGRGeoPackageLayer::GetLayerDefn();
    1082             :     }
    1083             : 
    1084          95 :     char *&GetAttrQueryString() override
    1085             :     {
    1086          95 :         return m_pszAttrQueryString;
    1087             :     }
    1088             : 
    1089         383 :     OGRFeatureQuery *&GetFeatureQuery() override
    1090             :     {
    1091         383 :         return m_poAttrQuery;
    1092             :     }
    1093             : 
    1094         254 :     OGRGeometry *&GetFilterGeom() override
    1095             :     {
    1096         254 :         return m_poFilterGeom;
    1097             :     }
    1098             : 
    1099          65 :     int &GetIGeomFieldFilter() override
    1100             :     {
    1101          65 :         return m_iGeomFieldFilter;
    1102             :     }
    1103             : 
    1104         112 :     const OGRSpatialReference *GetSpatialRef() const override
    1105             :     {
    1106         112 :         return OGRGeoPackageLayer::GetSpatialRef();
    1107             :     }
    1108             : 
    1109          45 :     int InstallFilter(const OGRGeometry *poGeomIn) override
    1110             :     {
    1111          45 :         return OGRGeoPackageLayer::InstallFilter(poGeomIn);
    1112             :     }
    1113             : 
    1114         181 :     int HasReadFeature() override
    1115             :     {
    1116         181 :         return m_iNextShapeId > 0;
    1117             :     }
    1118             : 
    1119          90 :     void BaseResetReading() override
    1120             :     {
    1121          90 :         OGRGeoPackageLayer::ResetReading();
    1122          90 :     }
    1123             : 
    1124        2026 :     OGRFeature *BaseGetNextFeature() override
    1125             :     {
    1126        2026 :         return OGRGeoPackageLayer::GetNextFeature();
    1127             :     }
    1128             : 
    1129           0 :     OGRErr BaseSetAttributeFilter(const char *pszQuery) override
    1130             :     {
    1131           0 :         return OGRGeoPackageLayer::SetAttributeFilter(pszQuery);
    1132             :     }
    1133             : 
    1134           1 :     GIntBig BaseGetFeatureCount(int bForce) override
    1135             :     {
    1136           1 :         return OGRGeoPackageLayer::GetFeatureCount(bForce);
    1137             :     }
    1138             : 
    1139          25 :     int BaseTestCapability(const char *pszCap) const override
    1140             :     {
    1141          25 :         return OGRGeoPackageLayer::TestCapability(pszCap);
    1142             :     }
    1143             : 
    1144           2 :     virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
    1145             :                                  bool bForce) override
    1146             :     {
    1147           2 :         return OGRGeoPackageLayer::IGetExtent(iGeomField, psExtent, bForce);
    1148             :     }
    1149             : 
    1150             :     bool
    1151           0 :     ValidateGeometryFieldIndexForSetSpatialFilter(int iGeomField,
    1152             :                                                   const OGRGeometry *poGeomIn,
    1153             :                                                   bool bIsSelectLayer) override
    1154             :     {
    1155             :         return OGRGeoPackageLayer::
    1156           0 :             ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField, poGeomIn,
    1157           0 :                                                           bIsSelectLayer);
    1158             :     }
    1159             : };
    1160             : 
    1161             : #endif /* OGR_GEOPACKAGE_H_INCLUDED */

Generated by: LCOV version 1.14