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