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();
243 : void RecomputeExtent();
244 :
245 : bool CheckFreeListConsistency();
246 :
247 : bool BeginEmulatedTransaction();
248 : bool CommitEmulatedTransaction();
249 : bool RollbackEmulatedTransaction();
250 :
251 : GDALDataset *GetDataset() override;
252 :
253 1233730 : virtual const char *GetName() override
254 : {
255 1233730 : 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 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
269 :
270 334 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
271 : int bForce) override
272 : {
273 334 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
274 : }
275 :
276 : OGRErr GetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
277 : int bForce) override;
278 :
279 : virtual OGRFeatureDefn *GetLayerDefn() override;
280 :
281 : virtual void SetSpatialFilter(OGRGeometry *) override;
282 :
283 979 : virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
284 : {
285 979 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
286 979 : }
287 :
288 : virtual OGRErr SetAttributeFilter(const char *pszFilter) override;
289 :
290 : virtual int TestCapability(const char *) override;
291 :
292 : virtual OGRErr Rename(const char *pszNewName) override;
293 :
294 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
295 : int bApproxOK) override;
296 : virtual OGRErr DeleteField(int iFieldToDelete) override;
297 : virtual OGRErr AlterFieldDefn(int iFieldToAlter,
298 : OGRFieldDefn *poNewFieldDefn,
299 : int nFlags) override;
300 : virtual OGRErr
301 : AlterGeomFieldDefn(int iGeomFieldToAlter,
302 : const OGRGeomFieldDefn *poNewGeomFieldDefn,
303 : int nFlagsIn) override;
304 :
305 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
306 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
307 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
308 :
309 : virtual OGRErr SyncToDisk() override;
310 : };
311 :
312 : /************************************************************************/
313 : /* OGROpenFileGDBGeomFieldDefn */
314 : /************************************************************************/
315 : class OGROpenFileGDBGeomFieldDefn : public OGRGeomFieldDefn
316 : {
317 : OGROpenFileGDBLayer *m_poLayer;
318 :
319 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBGeomFieldDefn)
320 :
321 : public:
322 3113 : OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer *poLayer,
323 : const char *pszNameIn,
324 : OGRwkbGeometryType eGeomTypeIn)
325 3113 : : OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
326 : {
327 3113 : }
328 :
329 6226 : ~OGROpenFileGDBGeomFieldDefn()
330 3113 : {
331 6226 : }
332 :
333 3112 : void UnsetLayer()
334 : {
335 3112 : m_poLayer = nullptr;
336 3112 : }
337 :
338 10593 : virtual const OGRSpatialReference *GetSpatialRef() const override
339 : {
340 10593 : if (poSRS)
341 7902 : return poSRS;
342 2691 : if (m_poLayer != nullptr)
343 420 : (void)m_poLayer->BuildLayerDefinition();
344 2691 : return poSRS;
345 : }
346 : };
347 :
348 : /************************************************************************/
349 : /* OGROpenFileGDBFeatureDefn */
350 : /************************************************************************/
351 : class OGROpenFileGDBFeatureDefn : public OGRFeatureDefn
352 : {
353 : OGROpenFileGDBLayer *m_poLayer;
354 : mutable bool m_bHasBuiltFieldDefn;
355 :
356 259691 : void LazyGeomInit() const
357 : {
358 : /* FileGDB v9 case */
359 152349 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr &&
360 505939 : m_poLayer->m_eGeomType != wkbNone &&
361 93899 : m_poLayer->m_osDefinition.empty())
362 : {
363 294 : m_bHasBuiltFieldDefn = true;
364 294 : (void)m_poLayer->BuildLayerDefinition();
365 : }
366 259691 : }
367 :
368 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBFeatureDefn)
369 :
370 : public:
371 11057 : OGROpenFileGDBFeatureDefn(OGROpenFileGDBLayer *poLayer, const char *pszName,
372 : bool bHasBuiltFieldDefn)
373 11057 : : OGRFeatureDefn(pszName), m_poLayer(poLayer),
374 11057 : m_bHasBuiltFieldDefn(bHasBuiltFieldDefn)
375 : {
376 11057 : }
377 :
378 22114 : ~OGROpenFileGDBFeatureDefn()
379 11057 : {
380 22114 : }
381 :
382 11057 : void UnsetLayer()
383 : {
384 11057 : if (!apoGeomFieldDefn.empty())
385 : cpl::down_cast<OGROpenFileGDBGeomFieldDefn *>(
386 3112 : apoGeomFieldDefn[0].get())
387 3112 : ->UnsetLayer();
388 11057 : m_poLayer = nullptr;
389 11057 : }
390 :
391 545803 : virtual int GetFieldCount() const override
392 : {
393 545803 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr)
394 : {
395 222441 : m_bHasBuiltFieldDefn = false;
396 222441 : (void)m_poLayer->BuildLayerDefinition();
397 : }
398 545803 : return OGRFeatureDefn::GetFieldCount();
399 : }
400 :
401 219514 : virtual int GetGeomFieldCount() const override
402 : {
403 219514 : LazyGeomInit();
404 219514 : return OGRFeatureDefn::GetGeomFieldCount();
405 : }
406 :
407 39842 : virtual OGRGeomFieldDefn *GetGeomFieldDefn(int i) override
408 : {
409 39842 : LazyGeomInit();
410 39842 : return OGRFeatureDefn::GetGeomFieldDefn(i);
411 : }
412 :
413 335 : virtual const OGRGeomFieldDefn *GetGeomFieldDefn(int i) const override
414 : {
415 335 : LazyGeomInit();
416 335 : return OGRFeatureDefn::GetGeomFieldDefn(i);
417 : }
418 : };
419 :
420 : /************************************************************************/
421 : /* OGROpenFileGDBDataSource */
422 : /************************************************************************/
423 :
424 : class OGROpenFileGDBDataSource final : public GDALDataset
425 : {
426 : friend class OGROpenFileGDBLayer;
427 : friend class GDALOpenFileGDBRasterBand;
428 : friend class GDALOpenFileGDBRasterAttributeTable;
429 :
430 : CPLString m_osDirName{};
431 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoLayers{};
432 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoHiddenLayers{};
433 : char **m_papszFiles = nullptr;
434 : std::map<std::string, int> m_osMapNameToIdx{};
435 : std::shared_ptr<GDALGroup> m_poRootGroup{};
436 : CPLStringList m_aosSubdatasets{};
437 :
438 : std::string m_osRasterLayerName{};
439 : std::map<int, int> m_oMapGDALBandToGDBBandId{};
440 : bool m_bHasGeoTransform = false;
441 : std::array<double, 6> m_adfGeoTransform = {{0.0, 1.0, 0, 0.0, 0.0, 1.0}};
442 : int m_nShiftBlockX =
443 : 0; // Offset to add to FileGDB col_nbr field to convert from GDAL block numbering to FileGDB one
444 : int m_nShiftBlockY =
445 : 0; // Offset to add to FileGDB row_nbr field to convert from GDAL block numbering to FileGDB one
446 : OGRSpatialReference m_oRasterSRS{};
447 : std::unique_ptr<OGRLayer> m_poBlkLayer{};
448 : enum class Compression
449 : {
450 : NONE,
451 : LZ77,
452 : JPEG,
453 : JPEG2000,
454 : };
455 : Compression m_eRasterCompression = Compression::NONE;
456 :
457 : lru11::Cache<std::string, std::shared_ptr<OGRSpatialReference>>
458 : m_oCacheWKTToSRS{};
459 :
460 : std::string m_osRootGUID{};
461 : std::string m_osGDBSystemCatalogFilename{};
462 : std::string m_osGDBSpatialRefsFilename{};
463 : std::string m_osGDBItemsFilename{};
464 : std::string m_osGDBItemRelationshipsFilename{};
465 : std::map<std::string, std::unique_ptr<GDALRelationship>>
466 : m_osMapRelationships{};
467 :
468 : // Related to transactions
469 : bool m_bInTransaction = false;
470 : bool m_bSystemTablesBackedup = false;
471 : std::string m_osTransactionBackupDirname{};
472 : std::set<OGROpenFileGDBLayer *>
473 : m_oSetLayersCreatedInTransaction{}; // must be vector of raw pointer
474 : std::set<std::unique_ptr<OGROpenFileGDBLayer>>
475 : m_oSetLayersDeletedInTransaction{};
476 :
477 : /* For debugging/testing */
478 : bool bLastSQLUsedOptimizedImplementation;
479 :
480 : bool OpenFileGDBv10(int iGDBItems, int nInterestTable,
481 : const GDALOpenInfo *poOpenInfo,
482 : const std::string &osRasterLayerName,
483 : std::set<int> &oSetIgnoredRasterLayerTableNum,
484 : bool &bRetryFileGDBOut);
485 : int OpenFileGDBv9(int iGDBFeatureClasses, int iGDBObjectClasses,
486 : int nInterestTable, const GDALOpenInfo *poOpenInfo,
487 : const std::string &osRasterLayerName,
488 : std::set<int> &oSetIgnoredRasterLayerTableNum);
489 : bool OpenRaster(const GDALOpenInfo *poOpenInfo,
490 : const std::string &osLayerName,
491 : const std::string &osDefinition,
492 : const std::string &osDocumentation);
493 : void GuessJPEGQuality(int nOverviewCount);
494 : void ReadAuxTable(const std::string &osLayerName);
495 :
496 : int FileExists(const char *pszFilename);
497 : std::unique_ptr<OGROpenFileGDBLayer>
498 : BuildLayerFromName(const char *pszName);
499 : OGRLayer *AddLayer(const CPLString &osName, int nInterestTable,
500 : int &nCandidateLayers, int &nLayersCDF,
501 : const CPLString &osDefinition,
502 : const CPLString &osDocumentation,
503 : OGRwkbGeometryType eGeomType,
504 : const std::string &osParentDefinition);
505 :
506 : static bool IsPrivateLayerName(const CPLString &osName);
507 :
508 : bool CreateGDBSystemCatalog();
509 : bool CreateGDBDBTune();
510 : bool CreateGDBSpatialRefs();
511 : bool CreateGDBItems();
512 : bool CreateGDBItemTypes();
513 : bool CreateGDBItemRelationships();
514 : bool CreateGDBItemRelationshipTypes();
515 :
516 : bool BackupSystemTablesForTransaction();
517 :
518 : CPLErr Close() override;
519 :
520 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBDataSource)
521 :
522 : public:
523 : OGROpenFileGDBDataSource();
524 : virtual ~OGROpenFileGDBDataSource();
525 :
526 : bool Open(const GDALOpenInfo *poOpenInfo, bool &bRetryFileGDBOut);
527 : bool Create(const char *pszName);
528 :
529 : virtual CPLErr FlushCache(bool bAtClosing = false) override;
530 :
531 1215800 : virtual int GetLayerCount() override
532 : {
533 1215800 : return static_cast<int>(m_apoLayers.size());
534 : }
535 :
536 : virtual OGRLayer *GetLayer(int) override;
537 : virtual OGROpenFileGDBLayer *GetLayerByName(const char *pszName) override;
538 : bool IsLayerPrivate(int) const override;
539 :
540 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
541 : OGRGeometry *poSpatialFilter,
542 : const char *pszDialect) override;
543 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
544 :
545 : virtual int TestCapability(const char *) override;
546 :
547 : OGRLayer *ICreateLayer(const char *pszName,
548 : const OGRGeomFieldDefn *poGeomFieldDefn,
549 : CSLConstList papszOptions) override;
550 :
551 : virtual OGRErr DeleteLayer(int) override;
552 :
553 : virtual char **GetFileList() override;
554 :
555 7 : std::shared_ptr<GDALGroup> GetRootGroup() const override
556 : {
557 7 : return m_poRootGroup;
558 : }
559 :
560 : virtual OGRErr StartTransaction(int bForce) override;
561 : virtual OGRErr CommitTransaction() override;
562 : virtual OGRErr RollbackTransaction() override;
563 :
564 550 : const CPLStringList &GetSubdatasets() const
565 : {
566 550 : return m_aosSubdatasets;
567 : }
568 :
569 : CPLErr GetGeoTransform(double *padfGeoTransform) override;
570 : const OGRSpatialReference *GetSpatialRef() const override;
571 :
572 : char **GetMetadata(const char *pszDomain = "") override;
573 :
574 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
575 : std::string &failureReason) override;
576 :
577 : bool DeleteFieldDomain(const std::string &name,
578 : std::string &failureReason) override;
579 :
580 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
581 : std::string &failureReason) override;
582 :
583 : std::vector<std::string>
584 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
585 :
586 : const GDALRelationship *
587 : GetRelationship(const std::string &name) const override;
588 :
589 : bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
590 : std::string &failureReason) override;
591 :
592 : bool DeleteRelationship(const std::string &name,
593 : std::string &failureReason) override;
594 :
595 : bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
596 : std::string &failureReason) override;
597 :
598 : bool GetExistingSpatialRef(const std::string &osWKT, double dfXOrigin,
599 : double dfYOrigin, double dfXYScale,
600 : double dfZOrigin, double dfZScale,
601 : double dfMOrigin, double dfMScale,
602 : double dfXYTolerance, double dfZTolerance,
603 : double dfMTolerance);
604 :
605 : bool AddNewSpatialRef(const std::string &osWKT, double dfXOrigin,
606 : double dfYOrigin, double dfXYScale, double dfZOrigin,
607 : double dfZScale, double dfMOrigin, double dfMScale,
608 : double dfXYTolerance, double dfZTolerance,
609 : double dfMTolerance);
610 :
611 : bool RegisterLayerInSystemCatalog(const std::string &osLayerName);
612 :
613 : bool RegisterInItemRelationships(const std::string &osOriginGUID,
614 : const std::string &osDestGUID,
615 : const std::string &osTypeGUID);
616 :
617 : bool RegisterRelationshipInItemRelationships(
618 : const std::string &osRelationshipGUID, const std::string &osOriginGUID,
619 : const std::string &osDestGUID);
620 :
621 : bool RemoveRelationshipFromItemRelationships(
622 : const std::string &osRelationshipGUID);
623 :
624 : bool RegisterFeatureDatasetInItems(const std::string &osFeatureDatasetGUID,
625 : const std::string &osName,
626 : const char *pszXMLDefinition);
627 :
628 : bool FindUUIDFromName(const std::string &osFeatureDatasetName,
629 : std::string &osUUIDOut);
630 :
631 : bool RegisterFeatureClassInItems(const std::string &osLayerGUID,
632 : const std::string &osLayerName,
633 : const std::string &osPath,
634 : const FileGDBTable *poLyrTable,
635 : const char *pszXMLDefinition,
636 : const char *pszDocumentation);
637 :
638 : bool RegisterASpatialTableInItems(const std::string &osLayerGUID,
639 : const std::string &osLayerName,
640 : const std::string &osPath,
641 : const char *pszXMLDefinition,
642 : const char *pszDocumentation);
643 :
644 : bool LinkDomainToTable(const std::string &osDomainName,
645 : const std::string &osLayerGUID);
646 : bool UnlinkDomainToTable(const std::string &osDomainName,
647 : const std::string &osLayerGUID);
648 :
649 : bool UpdateXMLDefinition(const std::string &osLayerName,
650 : const char *pszXMLDefinition);
651 :
652 12352 : bool IsInTransaction() const
653 : {
654 12352 : return m_bInTransaction;
655 : }
656 :
657 40 : const std::string &GetBackupDirName() const
658 : {
659 40 : return m_osTransactionBackupDirname;
660 : }
661 :
662 : OGRSpatialReference *BuildSRS(const CPLXMLNode *psInfo);
663 : OGRSpatialReference *BuildSRS(const char *pszWKT);
664 : };
665 :
666 : /************************************************************************/
667 : /* OGROpenFileGDBSingleFeatureLayer */
668 : /************************************************************************/
669 :
670 : class OGROpenFileGDBSingleFeatureLayer final : public OGRLayer
671 : {
672 : private:
673 : char *pszVal;
674 : OGRFeatureDefn *poFeatureDefn;
675 : int iNextShapeId;
676 :
677 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBSingleFeatureLayer)
678 :
679 : public:
680 : OGROpenFileGDBSingleFeatureLayer(const char *pszLayerName,
681 : const char *pszVal);
682 : virtual ~OGROpenFileGDBSingleFeatureLayer();
683 :
684 0 : virtual void ResetReading() override
685 : {
686 0 : iNextShapeId = 0;
687 0 : }
688 :
689 : virtual OGRFeature *GetNextFeature() override;
690 :
691 0 : virtual OGRFeatureDefn *GetLayerDefn() override
692 : {
693 0 : return poFeatureDefn;
694 : }
695 :
696 0 : virtual int TestCapability(const char *) override
697 : {
698 0 : return FALSE;
699 : }
700 : };
701 :
702 : /************************************************************************/
703 : /* GDALOpenFileGDBRasterAttributeTable */
704 : /************************************************************************/
705 :
706 : class GDALOpenFileGDBRasterAttributeTable final
707 : : public GDALRasterAttributeTable
708 : {
709 : std::unique_ptr<OGROpenFileGDBDataSource> m_poDS{};
710 : const std::string m_osVATTableName;
711 : std::unique_ptr<OGRLayer> m_poVATLayer{};
712 : mutable std::string m_osCachedValue{};
713 :
714 : GDALOpenFileGDBRasterAttributeTable(
715 : const GDALOpenFileGDBRasterAttributeTable &) = delete;
716 : GDALOpenFileGDBRasterAttributeTable &
717 : operator=(const GDALOpenFileGDBRasterAttributeTable &) = delete;
718 :
719 : public:
720 2 : GDALOpenFileGDBRasterAttributeTable(
721 : std::unique_ptr<OGROpenFileGDBDataSource> &&poDS,
722 : const std::string &osVATTableName,
723 : std::unique_ptr<OGRLayer> &&poVATLayer)
724 4 : : m_poDS(std::move(poDS)), m_osVATTableName(osVATTableName),
725 2 : m_poVATLayer(std::move(poVATLayer))
726 : {
727 2 : }
728 :
729 1 : GDALRasterAttributeTable *Clone() const override
730 : {
731 2 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
732 2 : GDALOpenInfo oOpenInfo(m_poDS->m_osDirName.c_str(), GA_ReadOnly);
733 1 : bool bRetryFileGDBUnused = false;
734 1 : if (!poDS->Open(&oOpenInfo, bRetryFileGDBUnused))
735 0 : return nullptr;
736 2 : auto poVatLayer = poDS->BuildLayerFromName(m_osVATTableName.c_str());
737 1 : if (!poVatLayer)
738 0 : return nullptr;
739 : return new GDALOpenFileGDBRasterAttributeTable(
740 1 : std::move(poDS), m_osVATTableName, std::move(poVatLayer));
741 : }
742 :
743 15 : int GetColumnCount() const override
744 : {
745 15 : return m_poVATLayer->GetLayerDefn()->GetFieldCount();
746 : }
747 :
748 3 : int GetRowCount() const override
749 : {
750 3 : return static_cast<int>(m_poVATLayer->GetFeatureCount());
751 : }
752 :
753 10 : const char *GetNameOfCol(int iCol) const override
754 : {
755 10 : if (iCol < 0 || iCol >= GetColumnCount())
756 4 : return nullptr;
757 6 : return m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetNameRef();
758 : }
759 :
760 5 : GDALRATFieldUsage GetUsageOfCol(int iCol) const override
761 : {
762 5 : const char *pszColName = GetNameOfCol(iCol);
763 9 : return pszColName && EQUAL(pszColName, "Value") ? GFU_MinMax
764 4 : : pszColName && EQUAL(pszColName, "Count") ? GFU_PixelCount
765 5 : : GFU_Generic;
766 : }
767 :
768 3 : int GetColOfUsage(GDALRATFieldUsage eUsage) const override
769 : {
770 3 : if (eUsage == GFU_MinMax)
771 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Value");
772 2 : if (eUsage == GFU_PixelCount)
773 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Count");
774 1 : return -1;
775 : }
776 :
777 5 : GDALRATFieldType GetTypeOfCol(int iCol) const override
778 : {
779 5 : if (iCol < 0 || iCol >= GetColumnCount())
780 2 : return GFT_Integer;
781 3 : switch (m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetType())
782 : {
783 1 : case OFTInteger:
784 1 : return GFT_Integer;
785 1 : case OFTReal:
786 1 : return GFT_Real;
787 1 : default:
788 1 : break;
789 : }
790 1 : return GFT_String;
791 : }
792 :
793 7 : const char *GetValueAsString(int iRow, int iField) const override
794 : {
795 : auto poFeat =
796 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
797 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
798 2 : return "";
799 5 : m_osCachedValue = poFeat->GetFieldAsString(iField);
800 5 : return m_osCachedValue.c_str();
801 : }
802 :
803 7 : int GetValueAsInt(int iRow, int iField) const override
804 : {
805 : auto poFeat =
806 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
807 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
808 2 : return 0;
809 5 : return poFeat->GetFieldAsInteger(iField);
810 : }
811 :
812 7 : double GetValueAsDouble(int iRow, int iField) const override
813 : {
814 : auto poFeat =
815 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
816 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
817 2 : return 0;
818 5 : return poFeat->GetFieldAsDouble(iField);
819 : }
820 :
821 1 : void SetValue(int, int, const char *) override
822 : {
823 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
824 1 : }
825 :
826 1 : void SetValue(int, int, int) override
827 : {
828 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
829 1 : }
830 :
831 1 : void SetValue(int, int, double) override
832 : {
833 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
834 1 : }
835 :
836 0 : int ChangesAreWrittenToFile() override
837 : {
838 0 : return false;
839 : }
840 :
841 1 : CPLErr SetTableType(const GDALRATTableType) override
842 : {
843 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetTableType() not supported");
844 1 : return CE_Failure;
845 : }
846 :
847 1 : GDALRATTableType GetTableType() const override
848 : {
849 1 : return GRTT_THEMATIC;
850 : }
851 :
852 0 : void RemoveStatistics() override
853 : {
854 0 : CPLError(CE_Failure, CPLE_NotSupported,
855 : "RemoveStatistics() not supported");
856 0 : }
857 : };
858 :
859 : /************************************************************************/
860 : /* GDALOpenFileGDBRasterBand */
861 : /************************************************************************/
862 :
863 : class GDALOpenFileGDBRasterBand final : public GDALRasterBand
864 : {
865 : friend class OGROpenFileGDBDataSource;
866 : std::vector<GByte> m_abyTmpBuffer{};
867 : int m_nBitWidth = 0;
868 : int m_nOverviewLevel = 0;
869 : std::vector<std::unique_ptr<GDALOpenFileGDBRasterBand>>
870 : m_apoOverviewBands{};
871 : bool m_bIsMask = false;
872 : std::unique_ptr<GDALOpenFileGDBRasterBand> m_poMaskBandOwned{};
873 : GDALOpenFileGDBRasterBand *m_poMainBand = nullptr;
874 : GDALOpenFileGDBRasterBand *m_poMaskBand = nullptr;
875 : bool m_bHasNoData = false;
876 : double m_dfNoData = 0.0;
877 : std::unique_ptr<GDALRasterAttributeTable> m_poRAT{};
878 :
879 : CPL_DISALLOW_COPY_ASSIGN(GDALOpenFileGDBRasterBand)
880 :
881 : public:
882 : GDALOpenFileGDBRasterBand(OGROpenFileGDBDataSource *poDSIn, int nBandIn,
883 : GDALDataType eDT, int nBitWidth, int nBlockWidth,
884 : int nBlockHeight, int nOverviewLevel,
885 : bool bIsMask);
886 :
887 : protected:
888 : CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) override;
889 :
890 12 : int GetOverviewCount() override
891 : {
892 12 : return static_cast<int>(m_apoOverviewBands.size());
893 : }
894 :
895 12 : GDALRasterBand *GetOverview(int i) override
896 : {
897 12 : return (i >= 0 && i < GetOverviewCount()) ? m_apoOverviewBands[i].get()
898 12 : : nullptr;
899 : }
900 :
901 15 : GDALRasterBand *GetMaskBand() override
902 : {
903 15 : return m_poMaskBand ? m_poMaskBand : GDALRasterBand::GetMaskBand();
904 : }
905 :
906 6 : int GetMaskFlags() override
907 : {
908 6 : return m_poMaskBand ? GMF_PER_DATASET : GDALRasterBand::GetMaskFlags();
909 : }
910 :
911 7 : double GetNoDataValue(int *pbHasNoData) override
912 : {
913 7 : if (pbHasNoData)
914 6 : *pbHasNoData = m_bHasNoData;
915 7 : return m_dfNoData;
916 : }
917 :
918 : GDALRasterAttributeTable *GetDefaultRAT() override;
919 : };
920 :
921 : #endif /* ndef OGR_OPENFILEGDB_H_INCLUDED */
|