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