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-05-11 14:50:45 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             :     std::string osErrorMsg{};
      92             :     OGRFeatureDefn *poFeatureDefn = nullptr;
      93             :     OGRGeoPackageLayer *poLayer = nullptr;
      94             : 
      95             :     struct tm brokenDown
      96             :     {
      97             :     };
      98             : 
      99             :     sqlite3 *hDB = nullptr;
     100             :     int nMaxBatchSize = 0;
     101             :     bool bAsynchronousMode = false;
     102             :     std::mutex oMutex{};
     103             :     std::condition_variable oCV{};
     104             :     bool bIsFinished = false;
     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             :     std::array<double, 6> m_adfGeoTransform = {0, 0, 0, 0, 0, 0};
     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         825 :     void IncrementReadTableDefCounter()
     192             :     {
     193         825 :         m_nReadTableDefCount++;
     194         825 :     }
     195             : 
     196         817 :     int GetReadTableDefCounter() const
     197             :     {
     198         817 :         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        2373 :     GDALGeoPackageDataset() = default;
     296             :     virtual ~GDALGeoPackageDataset();
     297             : 
     298             :     char **GetFileList(void) override;
     299             : 
     300             :     virtual char **GetMetadata(const char *pszDomain = "") override;
     301             :     virtual const char *GetMetadataItem(const char *pszName,
     302             :                                         const char *pszDomain = "") override;
     303             :     virtual char **GetMetadataDomainList() override;
     304             :     virtual CPLErr SetMetadata(char **papszMetadata,
     305             :                                const char *pszDomain = "") override;
     306             :     virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     307             :                                    const char *pszDomain = "") override;
     308             : 
     309             :     const OGRSpatialReference *GetSpatialRef() const override;
     310             :     CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
     311             : 
     312             :     virtual CPLErr GetGeoTransform(double *padfGeoTransform) override;
     313             :     virtual CPLErr SetGeoTransform(double *padfGeoTransform) override;
     314             : 
     315             :     virtual CPLErr FlushCache(bool bAtClosing) override;
     316             :     virtual CPLErr IBuildOverviews(const char *, int, const int *, int,
     317             :                                    const int *, GDALProgressFunc, void *,
     318             :                                    CSLConstList papszOptions) override;
     319             : 
     320       23533 :     virtual int GetLayerCount() override
     321             :     {
     322       23533 :         return static_cast<int>(m_apoLayers.size());
     323             :     }
     324             : 
     325             :     int Open(GDALOpenInfo *poOpenInfo, const std::string &osFilenameInZip);
     326             :     int Create(const char *pszFilename, int nXSize, int nYSize, int nBands,
     327             :                GDALDataType eDT, char **papszOptions);
     328             :     OGRLayer *GetLayer(int iLayer) override;
     329             :     OGRErr DeleteLayer(int iLayer) override;
     330             :     OGRLayer *ICreateLayer(const char *pszName,
     331             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     332             :                            CSLConstList papszOptions) override;
     333             :     int TestCapability(const char *) override;
     334             : 
     335             :     std::vector<std::string>
     336             :     GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
     337             :     const OGRFieldDomain *
     338             :     GetFieldDomain(const std::string &name) const override;
     339             :     bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
     340             :                         std::string &failureReason) override;
     341             : 
     342             :     bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     343             :                          std::string &failureReason) override;
     344             : 
     345             :     bool DeleteRelationship(const std::string &name,
     346             :                             std::string &failureReason) override;
     347             : 
     348             :     bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     349             :                             std::string &failureReason) override;
     350             : 
     351             :     virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     352             :     GetLayerWithGetSpatialWhereByName(const char *pszName) override;
     353             : 
     354             :     virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
     355             :                                  OGRGeometry *poSpatialFilter,
     356             :                                  const char *pszDialect) override;
     357             :     virtual void ReleaseResultSet(OGRLayer *poLayer) override;
     358             : 
     359             :     virtual OGRErr CommitTransaction() override;
     360             :     virtual OGRErr RollbackTransaction() override;
     361             : 
     362        5258 :     inline bool IsInTransaction() const
     363             :     {
     364        5258 :         return m_nSoftTransactionLevel > 0 || m_aosSavepoints.size() > 0;
     365             :     }
     366             : 
     367             :     static std::string LaunderName(const std::string &osStr);
     368             : 
     369             :     // At least 100000 to avoid conflicting with EPSG codes
     370             :     static constexpr int FIRST_CUSTOM_SRSID = 100000;
     371             : 
     372             :     int GetSrsId(const OGRSpatialReference *poSRS);
     373             :     const char *GetSrsName(const OGRSpatialReference &oSRS);
     374             :     std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>
     375             :     GetSpatialRef(int iSrsId, bool bFallbackToEPSG = false,
     376             :                   bool bEmitErrorIfNotFound = true);
     377             :     OGRErr CreateExtensionsTableIfNecessary();
     378             :     bool HasExtensionsTable();
     379             : 
     380         409 :     void SetMetadataDirty()
     381             :     {
     382         409 :         m_bMetadataDirty = true;
     383         409 :     }
     384             : 
     385             :     bool HasDataColumnsTable() const;
     386             :     bool HasDataColumnConstraintsTable() const;
     387             :     bool HasDataColumnConstraintsTableGPKG_1_0() const;
     388             :     bool CreateColumnsTableAndColumnConstraintsTablesIfNecessary();
     389             :     bool HasGpkgextRelationsTable() const;
     390             :     bool CreateRelationsTableIfNecessary();
     391             :     bool HasQGISLayerStyles() const;
     392             : 
     393          52 :     bool HasNonSpatialTablesNonRegisteredInGpkgContents() const
     394             :     {
     395          52 :         return m_bNonSpatialTablesNonRegisteredInGpkgContentsFound;
     396             :     }
     397             : 
     398             :     const char *GetGeometryTypeString(OGRwkbGeometryType eType);
     399             : 
     400             :     void ResetReadingAllLayers();
     401             :     OGRErr UpdateGpkgContentsLastChange(const char *pszTableName);
     402             : 
     403             :     static GDALDataset *CreateCopy(const char *pszFilename,
     404             :                                    GDALDataset *poSrcDS, int bStrict,
     405             :                                    char **papszOptions,
     406             :                                    GDALProgressFunc pfnProgress,
     407             :                                    void *pProgressData);
     408             : 
     409             :     static std::string GetCurrentDateEscapedSQL();
     410             : 
     411             :     GDALDataset *GetRasterLayerDataset(const char *pszLayerName);
     412             : 
     413             :   protected:
     414             :     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
     415             :                              GDALDataType, int, BANDMAP_TYPE, GSpacing,
     416             :                              GSpacing, GSpacing,
     417             :                              GDALRasterIOExtraArg *psExtraArg) override;
     418             : 
     419             :     // Coming from GDALGPKGMBTilesLikePseudoDataset
     420             : 
     421             :     virtual CPLErr IFlushCacheWithErrCode(bool bAtClosing) override;
     422             : 
     423       26033 :     virtual int IGetRasterCount() override
     424             :     {
     425       26033 :         return nBands;
     426             :     }
     427             : 
     428       54985 :     virtual GDALRasterBand *IGetRasterBand(int nBand) override
     429             :     {
     430       54985 :         return GetRasterBand(nBand);
     431             :     }
     432             : 
     433       10004 :     virtual sqlite3 *IGetDB() override
     434             :     {
     435       10004 :         return GetDB();
     436             :     }
     437             : 
     438       15388 :     virtual bool IGetUpdate() override
     439             :     {
     440       15388 :         return GetUpdate();
     441             :     }
     442             : 
     443             :     virtual bool ICanIWriteBlock() override;
     444             : 
     445         167 :     virtual OGRErr IStartTransaction() override
     446             :     {
     447         167 :         return SoftStartTransaction();
     448             :     }
     449             : 
     450         167 :     virtual OGRErr ICommitTransaction() override
     451             :     {
     452         167 :         return SoftCommitTransaction();
     453             :     }
     454             : 
     455          26 :     virtual const char *IGetFilename() override
     456             :     {
     457          26 :         return m_pszFilename;
     458             :     }
     459             : 
     460        9782 :     virtual int GetRowFromIntoTopConvention(int nRow) override
     461             :     {
     462        9782 :         return nRow;
     463             :     }
     464             : 
     465             :   private:
     466             :     OGRErr SetApplicationAndUserVersionId();
     467             :     bool ReOpenDB();
     468             :     bool OpenOrCreateDB(int flags);
     469             :     void InstallSQLFunctions();
     470             :     bool HasGDALAspatialExtension();
     471             :     std::string CreateRasterTriggersSQL(const std::string &osTableName);
     472             : };
     473             : 
     474             : /************************************************************************/
     475             : /*                   GPKGTemporaryForeignKeyCheckDisabler               */
     476             : /************************************************************************/
     477             : 
     478             : //! Instance of that class temporarily disable foreign key checks
     479             : class GPKGTemporaryForeignKeyCheckDisabler
     480             : {
     481             :   public:
     482         255 :     explicit GPKGTemporaryForeignKeyCheckDisabler(GDALGeoPackageDataset *poDS)
     483         255 :         : m_poDS(poDS), m_nPragmaForeignKeysOldValue(SQLGetInteger(
     484         255 :                             m_poDS->GetDB(), "PRAGMA foreign_keys", nullptr))
     485             :     {
     486         255 :         if (m_nPragmaForeignKeysOldValue)
     487             :         {
     488           0 :             CPL_IGNORE_RET_VAL(
     489           0 :                 SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 0"));
     490             :         }
     491         255 :     }
     492             : 
     493         255 :     ~GPKGTemporaryForeignKeyCheckDisabler()
     494         255 :     {
     495         255 :         if (m_nPragmaForeignKeysOldValue)
     496             :         {
     497           0 :             CPL_IGNORE_RET_VAL(
     498           0 :                 SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 1"));
     499             :         }
     500         255 :     }
     501             : 
     502             :   private:
     503             :     CPL_DISALLOW_COPY_ASSIGN(GPKGTemporaryForeignKeyCheckDisabler)
     504             : 
     505             :     GDALGeoPackageDataset *m_poDS = nullptr;
     506             :     int m_nPragmaForeignKeysOldValue = 0;
     507             : };
     508             : 
     509             : /************************************************************************/
     510             : /*                        GDALGeoPackageRasterBand                      */
     511             : /************************************************************************/
     512             : 
     513             : class GDALGeoPackageRasterBand final : public GDALGPKGMBTilesLikeRasterBand
     514             : {
     515             :     // Whether STATISTICS_MINIMUM and/or STATISTICS_MAXIMUM have been computed
     516             :     // from the min, max columns of the gpkg_2d_gridded_tile_ancillary table
     517             :     // (only for non-Byte data)
     518             :     bool m_bMinMaxComputedFromTileAncillary = false;
     519             :     double m_dfStatsMinFromTileAncillary =
     520             :         std::numeric_limits<double>::quiet_NaN();
     521             :     double m_dfStatsMaxFromTileAncillary =
     522             :         std::numeric_limits<double>::quiet_NaN();
     523             :     CPLStringList m_aosMD{};
     524             : 
     525             :     // Whether gpkg_metadata has been read to set initial metadata
     526             :     bool m_bHasReadMetadataFromStorage = false;
     527             : 
     528             :     // Whether STATISTICS_* have been set in this "session"
     529             :     bool m_bStatsMetadataSetInThisSession = false;
     530             : 
     531             :     bool m_bAddImplicitStatistics = true;
     532             : 
     533             :     void LoadBandMetadata();
     534             : 
     535             :   public:
     536             :     GDALGeoPackageRasterBand(GDALGeoPackageDataset *poDS, int nTileWidth,
     537             :                              int nTileHeight);
     538             : 
     539             :     virtual int GetOverviewCount() override;
     540             :     virtual GDALRasterBand *GetOverview(int nIdx) override;
     541             : 
     542             :     virtual CPLErr SetNoDataValue(double dfNoDataValue) override;
     543             : 
     544             :     virtual char **GetMetadata(const char *pszDomain = "") override;
     545             :     virtual const char *GetMetadataItem(const char *pszName,
     546             :                                         const char *pszDomain = "") override;
     547             :     virtual CPLErr SetMetadata(char **papszMetadata,
     548             :                                const char *pszDomain = "") override;
     549             :     virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     550             :                                    const char *pszDomain = "") override;
     551             : 
     552         494 :     void AddImplicitStatistics(bool b)
     553             :     {
     554         494 :         m_bAddImplicitStatistics = b;
     555         494 :     }
     556             : 
     557         357 :     inline bool HaveStatsMetadataBeenSetInThisSession() const
     558             :     {
     559         357 :         return m_bStatsMetadataSetInThisSession;
     560             :     }
     561             : 
     562             :     void InvalidateStatistics();
     563             : };
     564             : 
     565             : /************************************************************************/
     566             : /*                           OGRGeoPackageLayer                         */
     567             : /************************************************************************/
     568             : 
     569             : class OGRGeoPackageLayer CPL_NON_FINAL : public OGRLayer,
     570             :                                          public IOGRSQLiteGetSpatialWhere
     571             : {
     572             :   protected:
     573             :     friend void OGR_GPKG_FillArrowArray_Step(sqlite3_context *pContext,
     574             :                                              int /*argc*/,
     575             :                                              sqlite3_value **argv);
     576             : 
     577             :     GDALGeoPackageDataset *m_poDS = nullptr;
     578             : 
     579             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
     580             :     GIntBig m_iNextShapeId = 0;
     581             : 
     582             :     sqlite3_stmt *m_poQueryStatement = nullptr;
     583             :     bool m_bDoStep = true;
     584             :     bool m_bEOF = false;
     585             : 
     586             :     char *m_pszFidColumn = nullptr;
     587             : 
     588             :     int m_iFIDCol = -1;
     589             :     int m_iGeomCol = -1;
     590             :     std::vector<int> m_anFieldOrdinals{};
     591             : 
     592             :     //! Whether to call OGRGeometry::SetPrecision() when reading back geometries from the database
     593             :     bool m_bUndoDiscardCoordLSBOnReading = false;
     594             : 
     595             :     void ClearStatement();
     596             :     virtual OGRErr ResetStatement() = 0;
     597             : 
     598             :     void BuildFeatureDefn(const char *pszLayerName, sqlite3_stmt *hStmt);
     599             : 
     600             :     OGRFeature *TranslateFeature(sqlite3_stmt *hStmt);
     601             :     bool ParseDateField(const char *pszTxt, OGRField *psField,
     602             :                         const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     603             :     bool ParseDateField(sqlite3_stmt *hStmt, int iRawField, int nSqlite3ColType,
     604             :                         OGRField *psField, const OGRFieldDefn *poFieldDefn,
     605             :                         GIntBig nFID);
     606             :     bool ParseDateTimeField(const char *pszTxt, OGRField *psField,
     607             :                             const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     608             :     bool ParseDateTimeField(sqlite3_stmt *hStmt, int iRawField,
     609             :                             int nSqlite3ColType, OGRField *psField,
     610             :                             const OGRFieldDefn *poFieldDefn, GIntBig nFID);
     611             : 
     612         165 :     GDALDataset *GetDataset() override
     613             :     {
     614         165 :         return m_poDS;
     615             :     }
     616             : 
     617             :     virtual bool GetArrowStream(struct ArrowArrayStream *out_stream,
     618             :                                 CSLConstList papszOptions = nullptr) override;
     619             :     virtual int GetNextArrowArray(struct ArrowArrayStream *,
     620             :                                   struct ArrowArray *out_array) override;
     621             : 
     622             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageLayer)
     623             : 
     624             :   public:
     625             :     explicit OGRGeoPackageLayer(GDALGeoPackageDataset *poDS);
     626             :     virtual ~OGRGeoPackageLayer();
     627             :     /************************************************************************/
     628             :     /* OGR API methods */
     629             : 
     630             :     OGRFeature *GetNextFeature() override;
     631             :     const char *GetFIDColumn() override;
     632             :     void ResetReading() override;
     633             :     int TestCapability(const char *) override;
     634             : 
     635         465 :     OGRFeatureDefn *GetLayerDefn() override
     636             :     {
     637         465 :         return m_poFeatureDefn;
     638             :     }
     639             : 
     640             :     OGRErr SetIgnoredFields(CSLConstList papszFields) override;
     641             : 
     642           0 :     virtual bool HasFastSpatialFilter(int /*iGeomCol*/) override
     643             :     {
     644           0 :         return false;
     645             :     }
     646             : 
     647           0 :     virtual CPLString GetSpatialWhere(int /*iGeomCol*/,
     648             :                                       OGRGeometry * /*poFilterGeom*/) override
     649             :     {
     650           0 :         return "";
     651             :     }
     652             : };
     653             : 
     654             : /************************************************************************/
     655             : /*                        OGRGeoPackageTableLayer                       */
     656             : /************************************************************************/
     657             : 
     658             : struct OGRGPKGTableLayerFillArrowArray;
     659             : struct sqlite_rtree_bl;
     660             : 
     661             : class OGRGeoPackageTableLayer final : public OGRGeoPackageLayer
     662             : {
     663             :     char *m_pszTableName = nullptr;
     664             :     bool m_bIsTable = true;  // sensible init for creation mode
     665             :     bool m_bIsSpatial = false;
     666             :     bool m_bIsInGpkgContents = false;
     667             :     bool m_bFeatureDefnCompleted = false;
     668             :     int m_iSrs = 0;
     669             :     int m_nZFlag = 0;
     670             :     int m_nMFlag = 0;
     671             :     OGRGeomCoordinateBinaryPrecision m_sBinaryPrecision{};
     672             :     std::unique_ptr<OGREnvelope> m_poExtent{};
     673             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     674             :     GIntBig m_nTotalFeatureCount = -1;
     675             :     bool m_bOGRFeatureCountTriggersEnabled = false;
     676             :     bool m_bAddOGRFeatureCountTriggers = false;
     677             :     bool m_bFeatureCountTriggersDeletedInTransaction = false;
     678             : #endif
     679             :     CPLString m_soColumns{};
     680             :     CPLString m_soFilter{};
     681             :     CPLString osQuery{};
     682             :     CPLString m_osRTreeName{};
     683             :     CPLString m_osFIDForRTree{};
     684             :     bool m_bExtentChanged = false;
     685             :     bool m_bContentChanged = false;
     686             :     sqlite3_stmt *m_poUpdateStatement = nullptr;
     687             :     std::string m_osUpdateStatementSQL{};
     688             :     bool m_bInsertStatementWithFID = false;
     689             :     bool m_bInsertStatementWithUpsert = false;
     690             :     std::string m_osInsertStatementUpsertUniqueColumnName{};
     691             :     sqlite3_stmt *m_poInsertStatement = nullptr;
     692             :     sqlite3_stmt *m_poGetFeatureStatement = nullptr;
     693             :     bool m_bDeferredSpatialIndexCreation = false;
     694             :     // m_bHasSpatialIndex cannot be bool.  -1 is unset.
     695             :     int m_bHasSpatialIndex = -1;
     696             :     bool m_bDropRTreeTable = false;
     697             :     bool m_abHasGeometryExtension[wkbTriangle + 1];
     698             :     bool m_bPreservePrecision = true;
     699             :     bool m_bTruncateFields = false;
     700             :     bool m_bDeferredCreation = false;
     701             :     bool m_bTableCreatedInTransaction = false;
     702             :     bool m_bLaunder = false;
     703             :     int m_iFIDAsRegularColumnIndex = -1;
     704             :     std::string m_osInsertionBuffer{};  // used by FeatureBindParameters to
     705             :                                         // store datetime values
     706             : 
     707             :     CPLString m_osIdentifierLCO{};
     708             :     CPLString m_osDescriptionLCO{};
     709             :     bool m_bHasReadMetadataFromStorage = false;
     710             :     bool m_bHasTriedDetectingFID64 = false;
     711             :     GPKGASpatialVariant m_eASpatialVariant = GPKG_ATTRIBUTES;
     712             :     std::set<OGRwkbGeometryType> m_eSetBadGeomTypeWarned{};
     713             : 
     714             :     int m_nIsCompatOfOptimizedGetNextArrowArray = -1;
     715             :     bool m_bGetNextArrowArrayCalledSinceResetReading = false;
     716             : 
     717             :     int m_nCountInsertInTransactionThreshold = -1;
     718             :     GIntBig m_nCountInsertInTransaction = 0;
     719             :     std::vector<CPLString> m_aoRTreeTriggersSQL{};
     720             :     bool m_bUpdate1TriggerDisabled = false;
     721             :     bool m_bHasUpdate6And7Triggers = false;
     722             :     std::string m_osUpdate1Trigger{};
     723             : 
     724             :     typedef struct
     725             :     {
     726             :         GIntBig nId;
     727             :         float fMinX;
     728             :         float fMinY;
     729             :         float fMaxX;
     730             :         float fMaxY;
     731             :     } GPKGRTreeEntry;
     732             : 
     733             :     std::vector<GPKGRTreeEntry> m_aoRTreeEntries{};
     734             : 
     735             :     // Variables used for background RTree building
     736             :     std::string m_osAsyncDBName{};
     737             :     std::string m_osAsyncDBAttachName{};
     738             :     sqlite3 *m_hAsyncDBHandle = nullptr;
     739             :     sqlite_rtree_bl *m_hRTree = nullptr;
     740             :     cpl::ThreadSafeQueue<std::vector<GPKGRTreeEntry>> m_oQueueRTreeEntries{};
     741             :     bool m_bAllowedRTreeThread = false;
     742             :     bool m_bThreadRTreeStarted = false;
     743             :     bool m_bErrorDuringRTreeThread = false;
     744             :     size_t m_nRTreeBatchSize =
     745             :         10 * 1000;  // maximum size of a std::vector<GPKGRTreeEntry> item in
     746             :                     // m_oQueueRTreeEntries
     747             :     size_t m_nRTreeBatchesBeforeStart =
     748             :         10;  // number of items in m_oQueueRTreeEntries before starting the
     749             :              // thread
     750             :     std::thread m_oThreadRTree{};
     751             : 
     752             :     OGRISO8601Format m_sDateTimeFormat = {OGRISO8601Precision::AUTO};
     753             : 
     754             :     void StartAsyncRTree();
     755             :     void CancelAsyncRTree();
     756             :     void RemoveAsyncRTreeTempDB();
     757             :     void AsyncRTreeThreadFunction();
     758             : 
     759             :     OGRErr ResetStatementInternal(GIntBig nStartIndex);
     760             :     virtual OGRErr ResetStatement() override;
     761             : 
     762             :     void BuildWhere();
     763             :     OGRErr RegisterGeometryColumn();
     764             : 
     765             :     CPLString
     766             :     GetColumnsOfCreateTable(const std::vector<OGRFieldDefn *> &apoFields);
     767             :     CPLString
     768             :     BuildSelectFieldList(const std::vector<OGRFieldDefn *> &apoFields);
     769             :     OGRErr RecreateTable(const CPLString &osColumnsForCreate,
     770             :                          const CPLString &osFieldListForSelect);
     771             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     772             :     void CreateFeatureCountTriggers(const char *pszTableName = nullptr);
     773             :     void DisableFeatureCountTriggers(bool bNullifyFeatureCount = true);
     774             : #endif
     775             : 
     776             :     void CheckGeometryType(const OGRFeature *poFeature);
     777             : 
     778             :     OGRErr ReadTableDefinition();
     779             :     void InitView();
     780             : 
     781             :     bool DoSpecialProcessingForColumnCreation(const OGRFieldDefn *poField);
     782             : 
     783             :     bool StartDeferredSpatialIndexUpdate();
     784             :     bool FlushPendingSpatialIndexUpdate();
     785             :     void WorkaroundUpdate1TriggerIssue();
     786             :     void RevertWorkaroundUpdate1TriggerIssue();
     787             : 
     788             :     OGRErr RenameFieldInAuxiliaryTables(const char *pszOldName,
     789             :                                         const char *pszNewName);
     790             : 
     791             :     OGRErr CreateOrUpsertFeature(OGRFeature *poFeature, bool bUpsert);
     792             : 
     793             :     GIntBig GetTotalFeatureCount();
     794             : 
     795             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageTableLayer)
     796             : 
     797             :     // Used when m_nIsCompatOfOptimizedGetNextArrowArray == TRUE
     798             :     struct ArrowArrayPrefetchTask
     799             :     {
     800             :         std::thread m_oThread{};
     801             :         std::condition_variable m_oCV{};
     802             :         std::mutex m_oMutex{};
     803             :         bool m_bArrayReady = false;
     804             :         bool m_bFetchRows = false;
     805             :         bool m_bStop = false;
     806             :         bool m_bMemoryLimitReached = false;
     807             :         std::string m_osErrorMsg{};
     808             :         std::unique_ptr<GDALGeoPackageDataset> m_poDS{};
     809             :         OGRGeoPackageTableLayer *m_poLayer{};
     810             :         GIntBig m_iStartShapeId = 0;
     811             :         std::unique_ptr<struct ArrowArray> m_psArrowArray = nullptr;
     812             :     };
     813             : 
     814             :     std::queue<std::unique_ptr<ArrowArrayPrefetchTask>>
     815             :         m_oQueueArrowArrayPrefetchTasks{};
     816             : 
     817             :     // Used when m_nIsCompatOfOptimizedGetNextArrowArray == FALSE
     818             :     std::thread m_oThreadNextArrowArray{};
     819             :     std::unique_ptr<OGRGPKGTableLayerFillArrowArray> m_poFillArrowArray{};
     820             :     std::unique_ptr<GDALGeoPackageDataset> m_poOtherDS{};
     821             : 
     822             :     virtual int GetNextArrowArray(struct ArrowArrayStream *,
     823             :                                   struct ArrowArray *out_array) override;
     824             :     int GetNextArrowArrayInternal(struct ArrowArray *out_array,
     825             :                                   std::string &osErrorMsg,
     826             :                                   bool &bMemoryLimitReached);
     827             :     int GetNextArrowArrayAsynchronous(struct ArrowArrayStream *stream,
     828             :                                       struct ArrowArray *out_array);
     829             :     void GetNextArrowArrayAsynchronousWorker();
     830             :     void CancelAsyncNextArrowArray();
     831             : 
     832             :   protected:
     833             :     friend void OGR_GPKG_Intersects_Spatial_Filter(sqlite3_context *pContext,
     834             :                                                    int /*argc*/,
     835             :                                                    sqlite3_value **argv);
     836             : 
     837             :   public:
     838             :     OGRGeoPackageTableLayer(GDALGeoPackageDataset *poDS,
     839             :                             const char *pszTableName);
     840             :     virtual ~OGRGeoPackageTableLayer();
     841             : 
     842             :     /************************************************************************/
     843             :     /* OGR API methods */
     844             : 
     845       11428 :     const char *GetName() override
     846             :     {
     847       11428 :         return GetDescription();
     848             :     }
     849             : 
     850             :     const char *GetFIDColumn() override;
     851             :     OGRwkbGeometryType GetGeomType() override;
     852             :     const char *GetGeometryColumn() override;
     853             :     OGRFeatureDefn *GetLayerDefn() override;
     854             :     int TestCapability(const char *) override;
     855             :     OGRErr CreateField(const OGRFieldDefn *poField,
     856             :                        int bApproxOK = TRUE) override;
     857             :     OGRErr CreateGeomField(const OGRGeomFieldDefn *poGeomFieldIn,
     858             :                            int bApproxOK = TRUE) override;
     859             :     virtual OGRErr DeleteField(int iFieldToDelete) override;
     860             :     virtual OGRErr AlterFieldDefn(int iFieldToAlter,
     861             :                                   OGRFieldDefn *poNewFieldDefn,
     862             :                                   int nFlagsIn) override;
     863             :     virtual OGRErr
     864             :     AlterGeomFieldDefn(int iGeomFieldToAlter,
     865             :                        const OGRGeomFieldDefn *poNewGeomFieldDefn,
     866             :                        int nFlagsIn) override;
     867             :     virtual OGRErr ReorderFields(int *panMap) override;
     868             :     void ResetReading() override;
     869             :     OGRErr SetNextByIndex(GIntBig nIndex) override;
     870             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     871             :     OGRErr ISetFeature(OGRFeature *poFeature) override;
     872             :     OGRErr IUpsertFeature(OGRFeature *poFeature) override;
     873             :     OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
     874             :                           const int *panUpdatedFieldsIdx,
     875             :                           int nUpdatedGeomFieldsCount,
     876             :                           const int *panUpdatedGeomFieldsIdx,
     877             :                           bool bUpdateStyleString) override;
     878             :     OGRErr DeleteFeature(GIntBig nFID) override;
     879             : 
     880             :     OGRErr ISetSpatialFilter(int iGeomField,
     881             :                              const OGRGeometry *poGeom) override;
     882             : 
     883             :     OGRErr SetAttributeFilter(const char *pszQuery) override;
     884             :     OGRErr SyncToDisk() override;
     885             :     OGRFeature *GetNextFeature() override;
     886             :     OGRFeature *GetFeature(GIntBig nFID) override;
     887             :     OGRErr StartTransaction() override;
     888             :     OGRErr CommitTransaction() override;
     889             :     OGRErr RollbackTransaction() override;
     890             :     GIntBig GetFeatureCount(int) override;
     891             : 
     892             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     893             :                       bool bForce) override;
     894             : 
     895             :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
     896             :                         bool bForce) override;
     897             :     OGRGeometryTypeCounter *GetGeometryTypes(int iGeomField, int nFlagsGGT,
     898             :                                              int &nEntryCountOut,
     899             :                                              GDALProgressFunc pfnProgress,
     900             :                                              void *pProgressData) override;
     901             : 
     902             :     void RecomputeExtent();
     903             : 
     904             :     void SetOpeningParameters(const char *pszTableName,
     905             :                               const char *pszObjectType, bool bIsInGpkgContents,
     906             :                               bool bIsSpatial, const char *pszGeomColName,
     907             :                               const char *pszGeomType, bool bHasZ, bool bHasM);
     908             :     void SetCreationParameters(
     909             :         OGRwkbGeometryType eGType, const char *pszGeomColumnName,
     910             :         int bGeomNullable, const OGRSpatialReference *poSRS,
     911             :         const char *pszSRID, const OGRGeomCoordinatePrecision &oCoordPrec,
     912             :         bool bDiscardCoordLSB, bool bUndoDiscardCoordLSBOnReading,
     913             :         const char *pszFIDColumnName, const char *pszIdentifier,
     914             :         const char *pszDescription);
     915             :     void SetDeferredSpatialIndexCreation(bool bFlag);
     916             : 
     917          52 :     void SetASpatialVariant(GPKGASpatialVariant eASpatialVariant)
     918             :     {
     919          52 :         m_eASpatialVariant = eASpatialVariant;
     920          52 :         if (eASpatialVariant == GPKG_ATTRIBUTES)
     921          40 :             m_bIsInGpkgContents = true;
     922          52 :     }
     923             : 
     924          17 :     void SetDateTimePrecision(OGRISO8601Precision ePrecision)
     925             :     {
     926          17 :         m_sDateTimeFormat.ePrecision = ePrecision;
     927          17 :     }
     928             : 
     929             :     void CreateSpatialIndexIfNecessary();
     930             :     void FinishOrDisableThreadedRTree();
     931             :     bool FlushInMemoryRTree(sqlite3 *hRTreeDB, const char *pszRTreeName);
     932             :     bool CreateSpatialIndex(const char *pszTableName = nullptr);
     933             :     bool DropSpatialIndex(bool bCalledFromSQLFunction = false);
     934             :     CPLString ReturnSQLCreateSpatialIndexTriggers(const char *pszTableName,
     935             :                                                   const char *pszGeomColName);
     936             :     CPLString ReturnSQLDropSpatialIndexTriggers();
     937             : 
     938             :     virtual char **GetMetadata(const char *pszDomain = "") override;
     939             :     virtual const char *GetMetadataItem(const char *pszName,
     940             :                                         const char *pszDomain = "") override;
     941             :     virtual char **GetMetadataDomainList() override;
     942             : 
     943             :     virtual CPLErr SetMetadata(char **papszMetadata,
     944             :                                const char *pszDomain = "") override;
     945             :     virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     946             :                                    const char *pszDomain = "") override;
     947             : 
     948             :     virtual OGRErr Rename(const char *pszDstTableName) override;
     949             : 
     950             :     virtual bool HasFastSpatialFilter(int iGeomCol) override;
     951             :     virtual CPLString GetSpatialWhere(int iGeomCol,
     952             :                                       OGRGeometry *poFilterGeom) override;
     953             : 
     954             :     OGRErr Truncate();
     955             : 
     956             :     bool HasSpatialIndex();
     957             : 
     958         732 :     void SetPrecisionFlag(int bFlag)
     959             :     {
     960         732 :         m_bPreservePrecision = CPL_TO_BOOL(bFlag);
     961         732 :     }
     962             : 
     963         732 :     void SetTruncateFieldsFlag(int bFlag)
     964             :     {
     965         732 :         m_bTruncateFields = CPL_TO_BOOL(bFlag);
     966         732 :     }
     967             : 
     968         732 :     void SetLaunder(bool bFlag)
     969             :     {
     970         732 :         m_bLaunder = bFlag;
     971         732 :     }
     972             : 
     973             :     OGRErr RunDeferredCreationIfNecessary();
     974             :     bool RunDeferredDropRTreeTableIfNecessary();
     975             :     bool DoJobAtTransactionCommit();
     976             :     bool DoJobAtTransactionRollback();
     977             :     bool RunDeferredSpatialIndexUpdate();
     978             : 
     979             : #ifdef ENABLE_GPKG_OGR_CONTENTS
     980          36 :     bool GetAddOGRFeatureCountTriggers() const
     981             :     {
     982          36 :         return m_bAddOGRFeatureCountTriggers;
     983             :     }
     984             : 
     985          65 :     void SetAddOGRFeatureCountTriggers(bool b)
     986             :     {
     987          65 :         m_bAddOGRFeatureCountTriggers = b;
     988          65 :     }
     989             : 
     990          36 :     bool GetOGRFeatureCountTriggersDeletedInTransaction() const
     991             :     {
     992          36 :         return m_bFeatureCountTriggersDeletedInTransaction;
     993             :     }
     994             : 
     995           7 :     void SetOGRFeatureCountTriggersEnabled(bool b)
     996             :     {
     997           7 :         m_bOGRFeatureCountTriggersEnabled = b;
     998           7 :     }
     999             : 
    1000             :     void DisableFeatureCount();
    1001             : #endif
    1002             : 
    1003             :     bool CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType);
    1004             : 
    1005             :     /************************************************************************/
    1006             :     /* GPKG methods */
    1007             : 
    1008             :   private:
    1009             :     bool CheckUpdatableTable(const char *pszOperation);
    1010             :     OGRErr UpdateExtent(const OGREnvelope *poExtent);
    1011             :     OGRErr SaveExtent();
    1012             :     OGRErr SaveTimestamp();
    1013             :     OGRErr BuildColumns();
    1014             :     bool IsGeomFieldSet(OGRFeature *poFeature);
    1015             :     std::string FeatureGenerateUpdateSQL(const OGRFeature *poFeature) const;
    1016             :     std::string FeatureGenerateUpdateSQL(
    1017             :         const OGRFeature *poFeature, int nUpdatedFieldsCount,
    1018             :         const int *panUpdatedFieldsIdx, int nUpdatedGeomFieldsCount,
    1019             :         const int *panUpdatedGeomFieldsIdx) const;
    1020             :     CPLString
    1021             :     FeatureGenerateInsertSQL(OGRFeature *poFeature, bool bAddFID,
    1022             :                              bool bBindUnsetFields, bool bUpsert,
    1023             :                              const std::string &osUpsertUniqueColumnName);
    1024             :     OGRErr FeatureBindUpdateParameters(OGRFeature *poFeature,
    1025             :                                        sqlite3_stmt *poStmt);
    1026             :     OGRErr FeatureBindInsertParameters(OGRFeature *poFeature,
    1027             :                                        sqlite3_stmt *poStmt, bool bAddFID,
    1028             :                                        bool bBindUnsetFields);
    1029             :     OGRErr FeatureBindParameters(OGRFeature *poFeature, sqlite3_stmt *poStmt,
    1030             :                                  int *pnColCount, bool bAddFID,
    1031             :                                  bool bBindUnsetFields, int nUpdatedFieldsCount,
    1032             :                                  const int *panUpdatedFieldsIdx,
    1033             :                                  int nUpdatedGeomFieldsCount,
    1034             :                                  const int *panUpdatedGeomFieldsIdx);
    1035             : 
    1036             :     void UpdateContentsToNullExtent();
    1037             : 
    1038             :     void CheckUnknownExtensions();
    1039             :     bool CreateGeometryExtensionIfNecessary(const OGRGeometry *poGeom);
    1040             : };
    1041             : 
    1042             : /************************************************************************/
    1043             : /*                         OGRGeoPackageSelectLayer                     */
    1044             : /************************************************************************/
    1045             : 
    1046             : class OGRGeoPackageSelectLayer final : public OGRGeoPackageLayer,
    1047             :                                        public IOGRSQLiteSelectLayer
    1048             : {
    1049             :     CPL_DISALLOW_COPY_ASSIGN(OGRGeoPackageSelectLayer)
    1050             : 
    1051             :     OGRSQLiteSelectLayerCommonBehaviour *poBehavior = nullptr;
    1052             : 
    1053             :     virtual OGRErr ResetStatement() override;
    1054             : 
    1055             :   public:
    1056             :     OGRGeoPackageSelectLayer(GDALGeoPackageDataset *, const CPLString &osSQL,
    1057             :                              sqlite3_stmt *,
    1058             :                              bool bUseStatementForGetNextFeature,
    1059             :                              bool bEmptyLayer);
    1060             :     virtual ~OGRGeoPackageSelectLayer();
    1061             : 
    1062             :     virtual void ResetReading() override;
    1063             : 
    1064             :     virtual OGRFeature *GetNextFeature() override;
    1065             :     virtual GIntBig GetFeatureCount(int) override;
    1066             : 
    1067             :     OGRErr ISetSpatialFilter(int iGeomField, const OGRGeometry *) override;
    1068             :     virtual OGRErr SetAttributeFilter(const char *) override;
    1069             : 
    1070             :     virtual int TestCapability(const char *) override;
    1071             : 
    1072             :     virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
    1073             :                               bool bForce) override;
    1074             : 
    1075         465 :     virtual OGRFeatureDefn *GetLayerDefn() override
    1076             :     {
    1077         465 :         return OGRGeoPackageLayer::GetLayerDefn();
    1078             :     }
    1079             : 
    1080          95 :     virtual char *&GetAttrQueryString() override
    1081             :     {
    1082          95 :         return m_pszAttrQueryString;
    1083             :     }
    1084             : 
    1085         381 :     virtual OGRFeatureQuery *&GetFeatureQuery() override
    1086             :     {
    1087         381 :         return m_poAttrQuery;
    1088             :     }
    1089             : 
    1090         253 :     virtual OGRGeometry *&GetFilterGeom() override
    1091             :     {
    1092         253 :         return m_poFilterGeom;
    1093             :     }
    1094             : 
    1095          65 :     virtual int &GetIGeomFieldFilter() override
    1096             :     {
    1097          65 :         return m_iGeomFieldFilter;
    1098             :     }
    1099             : 
    1100         112 :     virtual OGRSpatialReference *GetSpatialRef() override
    1101             :     {
    1102         112 :         return OGRGeoPackageLayer::GetSpatialRef();
    1103             :     }
    1104             : 
    1105          45 :     virtual int InstallFilter(const OGRGeometry *poGeomIn) override
    1106             :     {
    1107          45 :         return OGRGeoPackageLayer::InstallFilter(poGeomIn);
    1108             :     }
    1109             : 
    1110         177 :     virtual int HasReadFeature() override
    1111             :     {
    1112         177 :         return m_iNextShapeId > 0;
    1113             :     }
    1114             : 
    1115          88 :     virtual void BaseResetReading() override
    1116             :     {
    1117          88 :         OGRGeoPackageLayer::ResetReading();
    1118          88 :     }
    1119             : 
    1120        1963 :     virtual OGRFeature *BaseGetNextFeature() override
    1121             :     {
    1122        1963 :         return OGRGeoPackageLayer::GetNextFeature();
    1123             :     }
    1124             : 
    1125           0 :     virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) override
    1126             :     {
    1127           0 :         return OGRGeoPackageLayer::SetAttributeFilter(pszQuery);
    1128             :     }
    1129             : 
    1130           1 :     virtual GIntBig BaseGetFeatureCount(int bForce) override
    1131             :     {
    1132           1 :         return OGRGeoPackageLayer::GetFeatureCount(bForce);
    1133             :     }
    1134             : 
    1135          24 :     virtual int BaseTestCapability(const char *pszCap) override
    1136             :     {
    1137          24 :         return OGRGeoPackageLayer::TestCapability(pszCap);
    1138             :     }
    1139             : 
    1140           2 :     virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
    1141             :                                  bool bForce) override
    1142             :     {
    1143           2 :         return OGRGeoPackageLayer::IGetExtent(iGeomField, psExtent, bForce);
    1144             :     }
    1145             : 
    1146             :     bool
    1147           0 :     ValidateGeometryFieldIndexForSetSpatialFilter(int iGeomField,
    1148             :                                                   const OGRGeometry *poGeomIn,
    1149             :                                                   bool bIsSelectLayer) override
    1150             :     {
    1151             :         return OGRGeoPackageLayer::
    1152           0 :             ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField, poGeomIn,
    1153           0 :                                                           bIsSelectLayer);
    1154             :     }
    1155             : };
    1156             : 
    1157             : #endif /* OGR_GEOPACKAGE_H_INCLUDED */

Generated by: LCOV version 1.14