Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements Open FileGDB OGR driver.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_OPENFILEGDB_H_INCLUDED
14 : #define OGR_OPENFILEGDB_H_INCLUDED
15 :
16 : #include "ogrsf_frmts.h"
17 : #include "filegdbtable.h"
18 : #include "ogr_swq.h"
19 : #include "cpl_mem_cache.h"
20 : #include "cpl_quad_tree.h"
21 :
22 : #include "gdal_rat.h"
23 :
24 : #include <array>
25 : #include <vector>
26 : #include <map>
27 :
28 : using namespace OpenFileGDB;
29 :
30 : std::string OFGDBGenerateUUID(bool bInit = false);
31 :
32 : int OGROpenFileGDBIsComparisonOp(int op);
33 :
34 : // The FileGeodatabase format does not really allow strings of arbitrary width
35 : // in the XML and .gdbtable header declaration. They must have a non-zero
36 : // maximum width. But if we put it to a huge value (let's say 1 billion), this
37 : // causes crashes in some Esri products (cf #5952, perhaps they allocate
38 : // std::string's to that maximum size?).
39 : // Hence this default of a relative large but not too large
40 : // width when creating a OGR string field width of unspecified width.
41 : // Note that when opening a FileGeodatabase with string fields of that width,
42 : // we do not advertise it in OGRFieldDefn::GetWidth() but we advertise 0 instead,
43 : // to allow round-tripping.
44 : constexpr int DEFAULT_STRING_WIDTH = 65536;
45 :
46 : // UUID of object type
47 : constexpr const char *pszFolderTypeUUID =
48 : "{f3783e6f-65ca-4514-8315-ce3985dad3b1}";
49 : constexpr const char *pszWorkspaceTypeUUID =
50 : "{c673fe0f-7280-404f-8532-20755dd8fc06}";
51 : constexpr const char *pszFeatureDatasetTypeUUID =
52 : "{74737149-DCB5-4257-8904-B9724E32A530}";
53 : constexpr const char *pszFeatureClassTypeUUID =
54 : "{70737809-852c-4a03-9e22-2cecea5b9bfa}";
55 : constexpr const char *pszTableTypeUUID =
56 : "{cd06bc3b-789d-4c51-aafa-a467912b8965}";
57 : constexpr const char *pszRangeDomainTypeUUID =
58 : "{c29da988-8c3e-45f7-8b5c-18e51ee7beb4}";
59 : constexpr const char *pszCodedDomainTypeUUID =
60 : "{8c368b12-a12e-4c7e-9638-c9c64e69e98f}";
61 : constexpr const char *pszRelationshipTypeUUID =
62 : "{b606a7e1-fa5b-439c-849c-6e9c2481537b}";
63 :
64 : // UUID of relationship type
65 : constexpr const char *pszDatasetInFeatureDatasetUUID =
66 : "{a1633a59-46ba-4448-8706-d8abe2b2b02e}";
67 : constexpr const char *pszDatasetInFolderUUID =
68 : "{dc78f1ab-34e4-43ac-ba47-1c4eabd0e7c7}";
69 : constexpr const char *pszDomainInDatasetUUID =
70 : "{17e08adb-2b31-4dcd-8fdd-df529e88f843}";
71 : constexpr const char *pszDatasetsRelatedThroughUUID =
72 : "{725badab-3452-491b-a795-55f32d67229c}";
73 :
74 : /***********************************************************************/
75 : /* FETCH_FIELD_IDX() */
76 : /***********************************************************************/
77 :
78 : #define FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, errorCode) \
79 : const int idxName = oTable.GetFieldIdx(varName); \
80 : if (idxName < 0 || oTable.GetField(idxName)->GetType() != type) \
81 : { \
82 : CPLError(CE_Failure, CPLE_AppDefined, \
83 : "Could not find field %s in table %s", varName, \
84 : oTable.GetFilename().c_str()); \
85 : return errorCode; \
86 : }
87 :
88 : #define FETCH_FIELD_IDX(idxName, varName, type) \
89 : FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, false)
90 :
91 : /************************************************************************/
92 : /* OGROpenFileGDBLayer */
93 : /************************************************************************/
94 :
95 : class OGROpenFileGDBDataSource;
96 : class OGROpenFileGDBGeomFieldDefn;
97 : class OGROpenFileGDBFeatureDefn;
98 :
99 : typedef enum
100 : {
101 : SPI_IN_BUILDING,
102 : SPI_COMPLETED,
103 : SPI_INVALID,
104 : } SPIState;
105 :
106 : class OGROpenFileGDBLayer final : public OGRLayer
107 : {
108 : friend class OGROpenFileGDBGeomFieldDefn;
109 : friend class OGROpenFileGDBFeatureDefn;
110 :
111 : OGROpenFileGDBDataSource *m_poDS = nullptr;
112 : CPLString m_osGDBFilename{};
113 : CPLString m_osName{};
114 : std::string m_osPath{};
115 : std::string m_osThisGUID{};
116 : bool m_bEditable = false;
117 : bool m_bRegisteredTable = true;
118 : CPLStringList m_aosCreationOptions{};
119 : FileGDBTable *m_poLyrTable = nullptr;
120 : OGROpenFileGDBFeatureDefn *m_poFeatureDefn = nullptr;
121 : int m_iGeomFieldIdx = -1;
122 : int m_iAreaField = -1; // index of Shape_Area field
123 : int m_iLengthField = -1; // index of Shape_Length field
124 : int64_t m_iCurFeat = 0;
125 : int m_iFIDAsRegularColumnIndex = -1;
126 : std::string m_osDefinition{};
127 : std::string m_osDocumentation{};
128 : std::string m_osConfigurationKeyword{};
129 : OGRwkbGeometryType m_eGeomType = wkbNone;
130 : bool m_bArcGISPro32OrLater = false;
131 : int m_bValidLayerDefn = -1;
132 : int m_bEOF = false;
133 : bool m_bTimeInUTC = false;
134 : std::string m_osFeatureDatasetGUID{};
135 :
136 : bool m_bWarnedDateNotConvertibleUTC = false;
137 :
138 : bool m_bHasCreatedBackupForTransaction = false;
139 : std::unique_ptr<OGRFeatureDefn> m_poFeatureDefnBackup{};
140 :
141 : int BuildLayerDefinition();
142 : int BuildGeometryColumnGDBv10(const std::string &osParentDefinition);
143 : OGRFeature *GetCurrentFeature();
144 :
145 : std::unique_ptr<FileGDBOGRGeometryConverter> m_poGeomConverter{};
146 :
147 : int m_iFieldToReadAsBinary = -1;
148 :
149 : FileGDBIterator *m_poAttributeIterator = nullptr;
150 : int m_bIteratorSufficientToEvaluateFilter = FALSE;
151 : FileGDBIterator *BuildIteratorFromExprNode(swq_expr_node *poNode);
152 :
153 : FileGDBIterator *m_poIterMinMax = nullptr;
154 :
155 : FileGDBSpatialIndexIterator *m_poSpatialIndexIterator = nullptr;
156 : FileGDBIterator *m_poCombinedIterator = nullptr;
157 :
158 : // Legacy behavior prior to handling of .spx file
159 : // To remove ultimately.
160 : SPIState m_eSpatialIndexState = SPI_IN_BUILDING;
161 : CPLQuadTree *m_pQuadTree = nullptr;
162 : void **m_pahFilteredFeatures = nullptr;
163 : int m_nFilteredFeatureCount = -1;
164 : static void GetBoundsFuncEx(const void *hFeature, CPLRectObj *pBounds,
165 : void *pQTUserData);
166 :
167 : void TryToDetectMultiPatchKind();
168 : void BuildCombinedIterator();
169 : bool RegisterTable();
170 : void RefreshXMLDefinitionInMemory();
171 : bool CreateFeatureDataset(const char *pszFeatureDataset);
172 : std::string GetLaunderedFieldName(const std::string &osNameOri) const;
173 : std::string GetLaunderedLayerName(const std::string &osNameOri) const;
174 :
175 : mutable std::vector<std::string> m_aosTempStrings{};
176 : bool PrepareFileGDBFeature(OGRFeature *poFeature,
177 : std::vector<OGRField> &fields,
178 : const OGRGeometry *&poGeom, bool bUpdate);
179 :
180 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBLayer)
181 :
182 : public:
183 : OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
184 : const char *pszGDBFilename, const char *pszName,
185 : const std::string &osDefinition,
186 : const std::string &osDocumentation, bool bEditable,
187 : OGRwkbGeometryType eGeomType = wkbUnknown,
188 : const std::string &osParentDefinition = std::string());
189 :
190 : OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
191 : const char *pszGDBFilename, const char *pszName,
192 : OGRwkbGeometryType eType, CSLConstList papszOptions);
193 :
194 : virtual ~OGROpenFileGDBLayer();
195 :
196 : bool Create(const OGRGeomFieldDefn *poSrcGeomFieldDefn);
197 : void Close();
198 :
199 35 : const std::string &GetFilename() const
200 : {
201 35 : return m_osGDBFilename;
202 : }
203 :
204 31 : const std::string &GetXMLDefinition()
205 : {
206 31 : return m_osDefinition;
207 : }
208 :
209 20 : const std::string &GetXMLDocumentation()
210 : {
211 20 : return m_osDocumentation;
212 : }
213 :
214 141 : int GetAttrIndexUse()
215 : {
216 257 : return (m_poAttributeIterator == nullptr) ? 0
217 116 : : (m_bIteratorSufficientToEvaluateFilter) ? 2
218 141 : : 1;
219 : }
220 :
221 : const OGRField *GetMinMaxValue(OGRFieldDefn *poFieldDefn, int bIsMin,
222 : int &eOutType);
223 : int GetMinMaxSumCount(OGRFieldDefn *poFieldDefn, double &dfMin,
224 : double &dfMax, double &dfSum, int &nCount);
225 : bool HasIndexForField(const char *pszFieldName);
226 : FileGDBIterator *BuildIndex(const char *pszFieldName, int bAscending,
227 : int op, swq_expr_node *poValue);
228 :
229 12 : SPIState GetSpatialIndexState() const
230 : {
231 12 : return m_eSpatialIndexState;
232 : }
233 :
234 1 : int IsValidLayerDefn()
235 : {
236 1 : return BuildLayerDefinition();
237 : }
238 :
239 : void CreateSpatialIndex();
240 : void CreateIndex(const std::string &osIdxName,
241 : const std::string &osExpression);
242 : bool Repack(GDALProgressFunc pfnProgress, void *pProgressData);
243 : void RecomputeExtent();
244 :
245 : bool CheckFreeListConsistency();
246 :
247 : bool BeginEmulatedTransaction();
248 : bool CommitEmulatedTransaction();
249 : bool RollbackEmulatedTransaction();
250 :
251 : GDALDataset *GetDataset() override;
252 :
253 1235300 : virtual const char *GetName() override
254 : {
255 1235300 : return m_osName.c_str();
256 : }
257 :
258 : virtual OGRwkbGeometryType GetGeomType() override;
259 :
260 : virtual const char *GetFIDColumn() override;
261 :
262 : virtual void ResetReading() override;
263 : virtual OGRFeature *GetNextFeature() override;
264 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
265 : virtual OGRErr SetNextByIndex(GIntBig nIndex) override;
266 :
267 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
268 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
269 : bool bForce) override;
270 :
271 : OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
272 : bool bForce) override;
273 :
274 : virtual OGRFeatureDefn *GetLayerDefn() override;
275 :
276 : virtual OGRErr ISetSpatialFilter(int iGeomField,
277 : const OGRGeometry *poGeom) override;
278 :
279 : virtual OGRErr SetAttributeFilter(const char *pszFilter) override;
280 :
281 : virtual int TestCapability(const char *) override;
282 :
283 : virtual OGRErr Rename(const char *pszNewName) override;
284 :
285 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
286 : int bApproxOK) override;
287 : virtual OGRErr DeleteField(int iFieldToDelete) override;
288 : virtual OGRErr AlterFieldDefn(int iFieldToAlter,
289 : OGRFieldDefn *poNewFieldDefn,
290 : int nFlags) override;
291 : virtual OGRErr
292 : AlterGeomFieldDefn(int iGeomFieldToAlter,
293 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
294 : int nFlagsIn) override;
295 :
296 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
297 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
298 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
299 :
300 : virtual OGRErr SyncToDisk() override;
301 : };
302 :
303 : /************************************************************************/
304 : /* OGROpenFileGDBGeomFieldDefn */
305 : /************************************************************************/
306 6320 : class OGROpenFileGDBGeomFieldDefn : public OGRGeomFieldDefn
307 : {
308 : OGROpenFileGDBLayer *m_poLayer;
309 :
310 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBGeomFieldDefn)
311 :
312 : public:
313 3160 : OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer *poLayer,
314 : const char *pszNameIn,
315 : OGRwkbGeometryType eGeomTypeIn)
316 3160 : : OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
317 : {
318 3160 : }
319 :
320 : ~OGROpenFileGDBGeomFieldDefn() override;
321 :
322 3159 : void UnsetLayer()
323 : {
324 3159 : m_poLayer = nullptr;
325 3159 : }
326 :
327 11361 : virtual const OGRSpatialReference *GetSpatialRef() const override
328 : {
329 11361 : if (poSRS)
330 8378 : return poSRS;
331 2983 : if (m_poLayer != nullptr)
332 440 : (void)m_poLayer->BuildLayerDefinition();
333 2983 : return poSRS;
334 : }
335 : };
336 :
337 : /************************************************************************/
338 : /* OGROpenFileGDBFeatureDefn */
339 : /************************************************************************/
340 22338 : class OGROpenFileGDBFeatureDefn : public OGRFeatureDefn
341 : {
342 : OGROpenFileGDBLayer *m_poLayer;
343 : mutable bool m_bHasBuiltFieldDefn;
344 :
345 273849 : void LazyGeomInit() const
346 : {
347 : /* FileGDB v9 case */
348 160331 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr &&
349 535903 : m_poLayer->m_eGeomType != wkbNone &&
350 101723 : m_poLayer->m_osDefinition.empty())
351 : {
352 260 : m_bHasBuiltFieldDefn = true;
353 260 : (void)m_poLayer->BuildLayerDefinition();
354 : }
355 273849 : }
356 :
357 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBFeatureDefn)
358 :
359 : public:
360 11176 : OGROpenFileGDBFeatureDefn(OGROpenFileGDBLayer *poLayer, const char *pszName,
361 : bool bHasBuiltFieldDefn)
362 11176 : : OGRFeatureDefn(pszName), m_poLayer(poLayer),
363 11176 : m_bHasBuiltFieldDefn(bHasBuiltFieldDefn)
364 : {
365 11176 : }
366 :
367 : ~OGROpenFileGDBFeatureDefn() override;
368 :
369 11169 : void UnsetLayer()
370 : {
371 11169 : if (!apoGeomFieldDefn.empty())
372 : cpl::down_cast<OGROpenFileGDBGeomFieldDefn *>(
373 3159 : apoGeomFieldDefn[0].get())
374 3159 : ->UnsetLayer();
375 11169 : m_poLayer = nullptr;
376 11169 : }
377 :
378 607761 : virtual int GetFieldCount() const override
379 : {
380 607761 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr)
381 : {
382 225121 : m_bHasBuiltFieldDefn = false;
383 225121 : (void)m_poLayer->BuildLayerDefinition();
384 : }
385 607761 : return OGRFeatureDefn::GetFieldCount();
386 : }
387 :
388 229616 : virtual int GetGeomFieldCount() const override
389 : {
390 229616 : LazyGeomInit();
391 229616 : return OGRFeatureDefn::GetGeomFieldCount();
392 : }
393 :
394 43894 : virtual OGRGeomFieldDefn *GetGeomFieldDefn(int i) override
395 : {
396 43894 : LazyGeomInit();
397 43894 : return OGRFeatureDefn::GetGeomFieldDefn(i);
398 : }
399 :
400 339 : virtual const OGRGeomFieldDefn *GetGeomFieldDefn(int i) const override
401 : {
402 339 : LazyGeomInit();
403 339 : return OGRFeatureDefn::GetGeomFieldDefn(i);
404 : }
405 : };
406 :
407 : /************************************************************************/
408 : /* OGROpenFileGDBDataSource */
409 : /************************************************************************/
410 :
411 : class OGROpenFileGDBDataSource final : public GDALDataset
412 : {
413 : friend class OGROpenFileGDBLayer;
414 : friend class GDALOpenFileGDBRasterBand;
415 : friend class GDALOpenFileGDBRasterAttributeTable;
416 :
417 : CPLString m_osDirName{};
418 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoLayers{};
419 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoHiddenLayers{};
420 : char **m_papszFiles = nullptr;
421 : std::map<std::string, int> m_osMapNameToIdx{};
422 : std::shared_ptr<GDALGroup> m_poRootGroup{};
423 : CPLStringList m_aosSubdatasets{};
424 :
425 : std::string m_osRasterLayerName{};
426 : std::map<int, int> m_oMapGDALBandToGDBBandId{};
427 : bool m_bHasGeoTransform = false;
428 : GDALGeoTransform m_gt{};
429 : int m_nShiftBlockX =
430 : 0; // Offset to add to FileGDB col_nbr field to convert from GDAL block numbering to FileGDB one
431 : int m_nShiftBlockY =
432 : 0; // Offset to add to FileGDB row_nbr field to convert from GDAL block numbering to FileGDB one
433 : OGRSpatialReference m_oRasterSRS{};
434 : std::unique_ptr<OGRLayer> m_poBlkLayer{};
435 : enum class Compression
436 : {
437 : NONE,
438 : LZ77,
439 : JPEG,
440 : JPEG2000,
441 : };
442 : Compression m_eRasterCompression = Compression::NONE;
443 :
444 : lru11::Cache<std::string, std::shared_ptr<OGRSpatialReference>>
445 : m_oCacheWKTToSRS{};
446 :
447 : std::string m_osRootGUID{};
448 : std::string m_osGDBSystemCatalogFilename{};
449 : std::string m_osGDBSpatialRefsFilename{};
450 : std::string m_osGDBItemsFilename{};
451 : std::string m_osGDBItemRelationshipsFilename{};
452 : std::map<std::string, std::unique_ptr<GDALRelationship>>
453 : m_osMapRelationships{};
454 :
455 : // Related to transactions
456 : bool m_bInTransaction = false;
457 : bool m_bSystemTablesBackedup = false;
458 : std::string m_osTransactionBackupDirname{};
459 : std::set<OGROpenFileGDBLayer *>
460 : m_oSetLayersCreatedInTransaction{}; // must be vector of raw pointer
461 : std::set<std::unique_ptr<OGROpenFileGDBLayer>>
462 : m_oSetLayersDeletedInTransaction{};
463 :
464 : /* For debugging/testing */
465 : bool bLastSQLUsedOptimizedImplementation;
466 :
467 : bool OpenFileGDBv10(int iGDBItems, int nInterestTable,
468 : const GDALOpenInfo *poOpenInfo,
469 : const std::string &osRasterLayerName,
470 : std::set<int> &oSetIgnoredRasterLayerTableNum,
471 : bool &bRetryFileGDBOut);
472 : int OpenFileGDBv9(int iGDBFeatureClasses, int iGDBObjectClasses,
473 : int nInterestTable, const GDALOpenInfo *poOpenInfo,
474 : const std::string &osRasterLayerName,
475 : std::set<int> &oSetIgnoredRasterLayerTableNum);
476 : bool OpenRaster(const GDALOpenInfo *poOpenInfo,
477 : const std::string &osLayerName,
478 : const std::string &osDefinition,
479 : const std::string &osDocumentation);
480 : void GuessJPEGQuality(int nOverviewCount);
481 : void ReadAuxTable(const std::string &osLayerName);
482 :
483 : int FileExists(const char *pszFilename);
484 : std::unique_ptr<OGROpenFileGDBLayer>
485 : BuildLayerFromName(const char *pszName);
486 : OGRLayer *AddLayer(const CPLString &osName, int nInterestTable,
487 : int &nCandidateLayers, int &nLayersCDF,
488 : const CPLString &osDefinition,
489 : const CPLString &osDocumentation,
490 : OGRwkbGeometryType eGeomType,
491 : const std::string &osParentDefinition);
492 :
493 : static bool IsPrivateLayerName(const CPLString &osName);
494 :
495 : bool CreateGDBSystemCatalog();
496 : bool CreateGDBDBTune();
497 : bool CreateGDBSpatialRefs();
498 : bool CreateGDBItems();
499 : bool CreateGDBItemTypes();
500 : bool CreateGDBItemRelationships();
501 : bool CreateGDBItemRelationshipTypes();
502 :
503 : bool BackupSystemTablesForTransaction();
504 :
505 : CPLErr Close() override;
506 :
507 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBDataSource)
508 :
509 : public:
510 : OGROpenFileGDBDataSource();
511 : virtual ~OGROpenFileGDBDataSource();
512 :
513 : bool Open(const GDALOpenInfo *poOpenInfo, bool &bRetryFileGDBOut);
514 : bool Create(const char *pszName);
515 :
516 : virtual CPLErr FlushCache(bool bAtClosing = false) override;
517 :
518 2 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> &GetLayers()
519 : {
520 2 : return m_apoLayers;
521 : }
522 :
523 1215830 : virtual int GetLayerCount() override
524 : {
525 1215830 : return static_cast<int>(m_apoLayers.size());
526 : }
527 :
528 : virtual OGRLayer *GetLayer(int) override;
529 : virtual OGROpenFileGDBLayer *GetLayerByName(const char *pszName) override;
530 : bool IsLayerPrivate(int) const override;
531 :
532 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
533 : OGRGeometry *poSpatialFilter,
534 : const char *pszDialect) override;
535 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
536 :
537 : virtual int TestCapability(const char *) override;
538 :
539 : OGRLayer *ICreateLayer(const char *pszName,
540 : const OGRGeomFieldDefn *poGeomFieldDefn,
541 : CSLConstList papszOptions) override;
542 :
543 : virtual OGRErr DeleteLayer(int) override;
544 :
545 : virtual char **GetFileList() override;
546 :
547 6 : std::shared_ptr<GDALGroup> GetRootGroup() const override
548 : {
549 6 : return m_poRootGroup;
550 : }
551 :
552 : virtual OGRErr StartTransaction(int bForce) override;
553 : virtual OGRErr CommitTransaction() override;
554 : virtual OGRErr RollbackTransaction() override;
555 :
556 500 : const CPLStringList &GetSubdatasets() const
557 : {
558 500 : return m_aosSubdatasets;
559 : }
560 :
561 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
562 : const OGRSpatialReference *GetSpatialRef() const override;
563 :
564 : char **GetMetadata(const char *pszDomain = "") override;
565 :
566 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
567 : std::string &failureReason) override;
568 :
569 : bool DeleteFieldDomain(const std::string &name,
570 : std::string &failureReason) override;
571 :
572 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
573 : std::string &failureReason) override;
574 :
575 : std::vector<std::string>
576 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
577 :
578 : const GDALRelationship *
579 : GetRelationship(const std::string &name) const override;
580 :
581 : bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
582 : std::string &failureReason) override;
583 :
584 : bool DeleteRelationship(const std::string &name,
585 : std::string &failureReason) override;
586 :
587 : bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
588 : std::string &failureReason) override;
589 :
590 : bool GetExistingSpatialRef(const std::string &osWKT, double dfXOrigin,
591 : double dfYOrigin, double dfXYScale,
592 : double dfZOrigin, double dfZScale,
593 : double dfMOrigin, double dfMScale,
594 : double dfXYTolerance, double dfZTolerance,
595 : double dfMTolerance);
596 :
597 : bool AddNewSpatialRef(const std::string &osWKT, double dfXOrigin,
598 : double dfYOrigin, double dfXYScale, double dfZOrigin,
599 : double dfZScale, double dfMOrigin, double dfMScale,
600 : double dfXYTolerance, double dfZTolerance,
601 : double dfMTolerance);
602 :
603 : bool RegisterLayerInSystemCatalog(const std::string &osLayerName);
604 :
605 : bool RegisterInItemRelationships(const std::string &osOriginGUID,
606 : const std::string &osDestGUID,
607 : const std::string &osTypeGUID);
608 :
609 : bool RegisterRelationshipInItemRelationships(
610 : const std::string &osRelationshipGUID, const std::string &osOriginGUID,
611 : const std::string &osDestGUID);
612 :
613 : bool RemoveRelationshipFromItemRelationships(
614 : const std::string &osRelationshipGUID);
615 :
616 : bool RegisterFeatureDatasetInItems(const std::string &osFeatureDatasetGUID,
617 : const std::string &osName,
618 : const char *pszXMLDefinition);
619 :
620 : bool FindUUIDFromName(const std::string &osFeatureDatasetName,
621 : std::string &osUUIDOut);
622 :
623 : bool RegisterFeatureClassInItems(const std::string &osLayerGUID,
624 : const std::string &osLayerName,
625 : const std::string &osPath,
626 : const FileGDBTable *poLyrTable,
627 : const char *pszXMLDefinition,
628 : const char *pszDocumentation);
629 :
630 : bool RegisterASpatialTableInItems(const std::string &osLayerGUID,
631 : const std::string &osLayerName,
632 : const std::string &osPath,
633 : const char *pszXMLDefinition,
634 : const char *pszDocumentation);
635 :
636 : bool LinkDomainToTable(const std::string &osDomainName,
637 : const std::string &osLayerGUID);
638 : bool UnlinkDomainToTable(const std::string &osDomainName,
639 : const std::string &osLayerGUID);
640 :
641 : bool UpdateXMLDefinition(const std::string &osLayerName,
642 : const char *pszXMLDefinition);
643 :
644 13073 : bool IsInTransaction() const
645 : {
646 13073 : return m_bInTransaction;
647 : }
648 :
649 40 : const std::string &GetBackupDirName() const
650 : {
651 40 : return m_osTransactionBackupDirname;
652 : }
653 :
654 : OGRSpatialReference *BuildSRS(const CPLXMLNode *psInfo);
655 : OGRSpatialReference *BuildSRS(const char *pszWKT);
656 : };
657 :
658 : /************************************************************************/
659 : /* OGROpenFileGDBSingleFeatureLayer */
660 : /************************************************************************/
661 :
662 : class OGROpenFileGDBSingleFeatureLayer final : public OGRLayer
663 : {
664 : private:
665 : char *pszVal;
666 : OGRFeatureDefn *poFeatureDefn;
667 : int iNextShapeId;
668 :
669 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBSingleFeatureLayer)
670 :
671 : public:
672 : OGROpenFileGDBSingleFeatureLayer(const char *pszLayerName,
673 : const char *pszVal);
674 : virtual ~OGROpenFileGDBSingleFeatureLayer();
675 :
676 0 : virtual void ResetReading() override
677 : {
678 0 : iNextShapeId = 0;
679 0 : }
680 :
681 : virtual OGRFeature *GetNextFeature() override;
682 :
683 0 : virtual OGRFeatureDefn *GetLayerDefn() override
684 : {
685 0 : return poFeatureDefn;
686 : }
687 :
688 0 : virtual int TestCapability(const char *) override
689 : {
690 0 : return FALSE;
691 : }
692 : };
693 :
694 : /************************************************************************/
695 : /* GDALOpenFileGDBRasterAttributeTable */
696 : /************************************************************************/
697 :
698 : class GDALOpenFileGDBRasterAttributeTable final
699 : : public GDALRasterAttributeTable
700 : {
701 : std::unique_ptr<OGROpenFileGDBDataSource> m_poDS{};
702 : const std::string m_osVATTableName;
703 : std::unique_ptr<OGRLayer> m_poVATLayer{};
704 : mutable std::string m_osCachedValue{};
705 :
706 : GDALOpenFileGDBRasterAttributeTable(
707 : const GDALOpenFileGDBRasterAttributeTable &) = delete;
708 : GDALOpenFileGDBRasterAttributeTable &
709 : operator=(const GDALOpenFileGDBRasterAttributeTable &) = delete;
710 :
711 : public:
712 2 : GDALOpenFileGDBRasterAttributeTable(
713 : std::unique_ptr<OGROpenFileGDBDataSource> &&poDS,
714 : const std::string &osVATTableName,
715 : std::unique_ptr<OGRLayer> &&poVATLayer)
716 4 : : m_poDS(std::move(poDS)), m_osVATTableName(osVATTableName),
717 2 : m_poVATLayer(std::move(poVATLayer))
718 : {
719 2 : }
720 :
721 : GDALRasterAttributeTable *Clone() const override;
722 :
723 15 : int GetColumnCount() const override
724 : {
725 15 : return m_poVATLayer->GetLayerDefn()->GetFieldCount();
726 : }
727 :
728 3 : int GetRowCount() const override
729 : {
730 3 : return static_cast<int>(m_poVATLayer->GetFeatureCount());
731 : }
732 :
733 10 : const char *GetNameOfCol(int iCol) const override
734 : {
735 10 : if (iCol < 0 || iCol >= GetColumnCount())
736 4 : return nullptr;
737 6 : return m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetNameRef();
738 : }
739 :
740 5 : GDALRATFieldUsage GetUsageOfCol(int iCol) const override
741 : {
742 5 : const char *pszColName = GetNameOfCol(iCol);
743 9 : return pszColName && EQUAL(pszColName, "Value") ? GFU_MinMax
744 4 : : pszColName && EQUAL(pszColName, "Count") ? GFU_PixelCount
745 5 : : GFU_Generic;
746 : }
747 :
748 3 : int GetColOfUsage(GDALRATFieldUsage eUsage) const override
749 : {
750 3 : if (eUsage == GFU_MinMax)
751 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Value");
752 2 : if (eUsage == GFU_PixelCount)
753 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Count");
754 1 : return -1;
755 : }
756 :
757 5 : GDALRATFieldType GetTypeOfCol(int iCol) const override
758 : {
759 5 : if (iCol < 0 || iCol >= GetColumnCount())
760 2 : return GFT_Integer;
761 3 : switch (m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetType())
762 : {
763 1 : case OFTInteger:
764 1 : return GFT_Integer;
765 1 : case OFTReal:
766 1 : return GFT_Real;
767 1 : default:
768 1 : break;
769 : }
770 1 : return GFT_String;
771 : }
772 :
773 7 : const char *GetValueAsString(int iRow, int iField) const override
774 : {
775 : auto poFeat =
776 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
777 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
778 2 : return "";
779 5 : m_osCachedValue = poFeat->GetFieldAsString(iField);
780 5 : return m_osCachedValue.c_str();
781 : }
782 :
783 7 : int GetValueAsInt(int iRow, int iField) const override
784 : {
785 : auto poFeat =
786 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
787 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
788 2 : return 0;
789 5 : return poFeat->GetFieldAsInteger(iField);
790 : }
791 :
792 7 : double GetValueAsDouble(int iRow, int iField) const override
793 : {
794 : auto poFeat =
795 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
796 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
797 2 : return 0;
798 5 : return poFeat->GetFieldAsDouble(iField);
799 : }
800 :
801 1 : CPLErr SetValue(int, int, const char *) override
802 : {
803 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
804 1 : return CE_Failure;
805 : }
806 :
807 1 : CPLErr SetValue(int, int, int) override
808 : {
809 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
810 1 : return CE_Failure;
811 : }
812 :
813 1 : CPLErr SetValue(int, int, double) override
814 : {
815 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
816 1 : return CE_Failure;
817 : }
818 :
819 0 : int ChangesAreWrittenToFile() override
820 : {
821 0 : return false;
822 : }
823 :
824 1 : CPLErr SetTableType(const GDALRATTableType) override
825 : {
826 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetTableType() not supported");
827 1 : return CE_Failure;
828 : }
829 :
830 1 : GDALRATTableType GetTableType() const override
831 : {
832 1 : return GRTT_THEMATIC;
833 : }
834 :
835 0 : void RemoveStatistics() override
836 : {
837 0 : CPLError(CE_Failure, CPLE_NotSupported,
838 : "RemoveStatistics() not supported");
839 0 : }
840 : };
841 :
842 : /************************************************************************/
843 : /* GDALOpenFileGDBRasterBand */
844 : /************************************************************************/
845 :
846 : class GDALOpenFileGDBRasterBand final : public GDALRasterBand
847 : {
848 : friend class OGROpenFileGDBDataSource;
849 : std::vector<GByte> m_abyTmpBuffer{};
850 : int m_nBitWidth = 0;
851 : int m_nOverviewLevel = 0;
852 : std::vector<std::unique_ptr<GDALOpenFileGDBRasterBand>>
853 : m_apoOverviewBands{};
854 : bool m_bIsMask = false;
855 : std::unique_ptr<GDALOpenFileGDBRasterBand> m_poMaskBandOwned{};
856 : GDALOpenFileGDBRasterBand *m_poMainBand = nullptr;
857 : GDALOpenFileGDBRasterBand *m_poMaskBand = nullptr;
858 : bool m_bHasNoData = false;
859 : double m_dfNoData = 0.0;
860 : std::unique_ptr<GDALRasterAttributeTable> m_poRAT{};
861 :
862 : CPL_DISALLOW_COPY_ASSIGN(GDALOpenFileGDBRasterBand)
863 :
864 : public:
865 : GDALOpenFileGDBRasterBand(OGROpenFileGDBDataSource *poDSIn, int nBandIn,
866 : GDALDataType eDT, int nBitWidth, int nBlockWidth,
867 : int nBlockHeight, int nOverviewLevel,
868 : bool bIsMask);
869 :
870 : protected:
871 : CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) override;
872 :
873 12 : int GetOverviewCount() override
874 : {
875 12 : return static_cast<int>(m_apoOverviewBands.size());
876 : }
877 :
878 12 : GDALRasterBand *GetOverview(int i) override
879 : {
880 12 : return (i >= 0 && i < GetOverviewCount()) ? m_apoOverviewBands[i].get()
881 12 : : nullptr;
882 : }
883 :
884 15 : GDALRasterBand *GetMaskBand() override
885 : {
886 15 : return m_poMaskBand ? m_poMaskBand : GDALRasterBand::GetMaskBand();
887 : }
888 :
889 6 : int GetMaskFlags() override
890 : {
891 6 : return m_poMaskBand ? GMF_PER_DATASET : GDALRasterBand::GetMaskFlags();
892 : }
893 :
894 7 : double GetNoDataValue(int *pbHasNoData) override
895 : {
896 7 : if (pbHasNoData)
897 6 : *pbHasNoData = m_bHasNoData;
898 7 : return m_dfNoData;
899 : }
900 :
901 : GDALRasterAttributeTable *GetDefaultRAT() override;
902 : };
903 :
904 : #endif /* ndef OGR_OPENFILEGDB_H_INCLUDED */
|