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

Generated by: LCOV version 1.14