Coverage Report

Created: 2026-02-14 09:00

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