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