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: 117 129 90.7 %
Date: 2024-11-21 22:18:42 Functions: 48 52 92.3 %

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

Generated by: LCOV version 1.14