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