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 : 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 949 : void IncrementReadTableDefCounter()
190 : {
191 949 : m_nReadTableDefCount++;
192 949 : }
193 :
194 941 : int GetReadTableDefCounter() const
195 : {
196 941 : return m_nReadTableDefCount;
197 : }
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 2674 : 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 >) const override;
312 : CPLErr SetGeoTransform(const GDALGeoTransform >) 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 25033 : int GetLayerCount() const override
320 : {
321 25033 : return static_cast<int>(m_apoLayers.size());
322 : }
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 7136 : inline bool IsInTransaction() const
368 : {
369 7136 : return m_nSoftTransactionLevel > 0 || m_aosSavepoints.size() > 0;
370 : }
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 435 : void SetMetadataDirty()
386 : {
387 435 : m_bMetadataDirty = true;
388 435 : }
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 79 : bool HasNonSpatialTablesNonRegisteredInGpkgContents() const
399 : {
400 79 : return m_bNonSpatialTablesNonRegisteredInGpkgContentsFound;
401 : }
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 26044 : int IGetRasterCount() override
428 : {
429 26044 : return nBands;
430 : }
431 :
432 55049 : GDALRasterBand *IGetRasterBand(int nBand) override
433 : {
434 55049 : return GetRasterBand(nBand);
435 : }
436 :
437 10015 : sqlite3 *IGetDB() override
438 : {
439 10015 : return GetDB();
440 : }
441 :
442 15934 : bool IGetUpdate() override
443 : {
444 15934 : return GetUpdate();
445 : }
446 :
447 : bool ICanIWriteBlock() override;
448 :
449 169 : OGRErr IStartTransaction() override
450 : {
451 169 : return SoftStartTransaction();
452 : }
453 :
454 169 : OGRErr ICommitTransaction() override
455 : {
456 169 : return SoftCommitTransaction();
457 : }
458 :
459 26 : const char *IGetFilename() override
460 : {
461 26 : return m_pszFilename;
462 : }
463 :
464 9789 : int GetRowFromIntoTopConvention(int nRow) override
465 : {
466 9789 : return nRow;
467 : }
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 262 : explicit GPKGTemporaryForeignKeyCheckDisabler(GDALGeoPackageDataset *poDS)
487 262 : : m_poDS(poDS), m_nPragmaForeignKeysOldValue(SQLGetInteger(
488 262 : m_poDS->GetDB(), "PRAGMA foreign_keys", nullptr))
489 : {
490 262 : if (m_nPragmaForeignKeysOldValue)
491 : {
492 0 : CPL_IGNORE_RET_VAL(
493 0 : SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 0"));
494 : }
495 262 : }
496 :
497 262 : ~GPKGTemporaryForeignKeyCheckDisabler()
498 262 : {
499 262 : if (m_nPragmaForeignKeysOldValue)
500 : {
501 0 : CPL_IGNORE_RET_VAL(
502 0 : SQLCommand(m_poDS->GetDB(), "PRAGMA foreign_keys = 1"));
503 : }
504 262 : }
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 498 : void AddImplicitStatistics(bool b)
557 : {
558 498 : m_bAddImplicitStatistics = b;
559 498 : }
560 :
561 359 : inline bool HaveStatsMetadataBeenSetInThisSession() const
562 : {
563 359 : return m_bStatsMetadataSetInThisSession;
564 : }
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 192 : GDALDataset *GetDataset() override
617 : {
618 192 : return m_poDS;
619 : }
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 345 : const OGRFeatureDefn *GetLayerDefn() const override
640 : {
641 345 : return m_poFeatureDefn;
642 : }
643 :
644 : OGRErr SetIgnoredFields(CSLConstList papszFields) override;
645 :
646 0 : bool HasFastSpatialFilter(int /*iGeomCol*/) override
647 : {
648 0 : return false;
649 : }
650 :
651 0 : virtual CPLString GetSpatialWhere(int /*iGeomCol*/,
652 : OGRGeometry * /*poFilterGeom*/) override
653 : {
654 0 : return "";
655 : }
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 11722 : const char *GetName() const override
850 : {
851 11722 : return GetDescription();
852 : }
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 79 : void SetASpatialVariant(GPKGASpatialVariant eASpatialVariant)
922 : {
923 79 : m_eASpatialVariant = eASpatialVariant;
924 79 : if (eASpatialVariant == GPKG_ATTRIBUTES)
925 67 : m_bIsInGpkgContents = true;
926 79 : }
927 :
928 17 : void SetDateTimePrecision(OGRISO8601Precision ePrecision)
929 : {
930 17 : m_sDateTimeFormat.ePrecision = ePrecision;
931 17 : }
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 890 : void SetPrecisionFlag(int bFlag)
963 : {
964 890 : m_bPreservePrecision = CPL_TO_BOOL(bFlag);
965 890 : }
966 :
967 890 : void SetTruncateFieldsFlag(int bFlag)
968 : {
969 890 : m_bTruncateFields = CPL_TO_BOOL(bFlag);
970 890 : }
971 :
972 890 : void SetLaunder(bool bFlag)
973 : {
974 890 : m_bLaunder = bFlag;
975 890 : }
976 :
977 : OGRErr RunDeferredCreationIfNecessary();
978 : bool RunDeferredDropRTreeTableIfNecessary();
979 : bool DoJobAtTransactionCommit();
980 : bool DoJobAtTransactionRollback();
981 : bool RunDeferredSpatialIndexUpdate();
982 :
983 : #ifdef ENABLE_GPKG_OGR_CONTENTS
984 36 : bool GetAddOGRFeatureCountTriggers() const
985 : {
986 36 : return m_bAddOGRFeatureCountTriggers;
987 : }
988 :
989 65 : void SetAddOGRFeatureCountTriggers(bool b)
990 : {
991 65 : m_bAddOGRFeatureCountTriggers = b;
992 65 : }
993 :
994 36 : bool GetOGRFeatureCountTriggersDeletedInTransaction() const
995 : {
996 36 : return m_bFeatureCountTriggersDeletedInTransaction;
997 : }
998 :
999 7 : void SetOGRFeatureCountTriggersEnabled(bool b)
1000 : {
1001 7 : m_bOGRFeatureCountTriggersEnabled = b;
1002 7 : }
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 345 : const OGRFeatureDefn *GetLayerDefn() const override
1080 : {
1081 345 : return OGRGeoPackageLayer::GetLayerDefn();
1082 : }
1083 :
1084 95 : char *&GetAttrQueryString() override
1085 : {
1086 95 : return m_pszAttrQueryString;
1087 : }
1088 :
1089 383 : OGRFeatureQuery *&GetFeatureQuery() override
1090 : {
1091 383 : return m_poAttrQuery;
1092 : }
1093 :
1094 254 : OGRGeometry *&GetFilterGeom() override
1095 : {
1096 254 : return m_poFilterGeom;
1097 : }
1098 :
1099 65 : int &GetIGeomFieldFilter() override
1100 : {
1101 65 : return m_iGeomFieldFilter;
1102 : }
1103 :
1104 112 : const OGRSpatialReference *GetSpatialRef() const override
1105 : {
1106 112 : return OGRGeoPackageLayer::GetSpatialRef();
1107 : }
1108 :
1109 45 : int InstallFilter(const OGRGeometry *poGeomIn) override
1110 : {
1111 45 : return OGRGeoPackageLayer::InstallFilter(poGeomIn);
1112 : }
1113 :
1114 181 : int HasReadFeature() override
1115 : {
1116 181 : return m_iNextShapeId > 0;
1117 : }
1118 :
1119 90 : void BaseResetReading() override
1120 : {
1121 90 : OGRGeoPackageLayer::ResetReading();
1122 90 : }
1123 :
1124 2026 : OGRFeature *BaseGetNextFeature() override
1125 : {
1126 2026 : return OGRGeoPackageLayer::GetNextFeature();
1127 : }
1128 :
1129 0 : OGRErr BaseSetAttributeFilter(const char *pszQuery) override
1130 : {
1131 0 : return OGRGeoPackageLayer::SetAttributeFilter(pszQuery);
1132 : }
1133 :
1134 1 : GIntBig BaseGetFeatureCount(int bForce) override
1135 : {
1136 1 : return OGRGeoPackageLayer::GetFeatureCount(bForce);
1137 : }
1138 :
1139 25 : int BaseTestCapability(const char *pszCap) const override
1140 : {
1141 25 : return OGRGeoPackageLayer::TestCapability(pszCap);
1142 : }
1143 :
1144 2 : virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
1145 : bool bForce) override
1146 : {
1147 2 : return OGRGeoPackageLayer::IGetExtent(iGeomField, psExtent, bForce);
1148 : }
1149 :
1150 : bool
1151 0 : ValidateGeometryFieldIndexForSetSpatialFilter(int iGeomField,
1152 : const OGRGeometry *poGeomIn,
1153 : bool bIsSelectLayer) override
1154 : {
1155 : return OGRGeoPackageLayer::
1156 0 : ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField, poGeomIn,
1157 0 : bIsSelectLayer);
1158 : }
1159 : };
1160 :
1161 : #endif /* OGR_GEOPACKAGE_H_INCLUDED */
|