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

Generated by: LCOV version 1.14