Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements Open FileGDB OGR driver.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_OPENFILEGDB_H_INCLUDED
14 : #define OGR_OPENFILEGDB_H_INCLUDED
15 :
16 : #include "ogrsf_frmts.h"
17 : #include "filegdbtable.h"
18 : #include "ogr_swq.h"
19 : #include "cpl_mem_cache.h"
20 : #include "cpl_quad_tree.h"
21 :
22 : #include "gdal_rat.h"
23 :
24 : #include <array>
25 : #include <vector>
26 : #include <map>
27 :
28 : using namespace OpenFileGDB;
29 :
30 : std::string OFGDBGenerateUUID(bool bInit = false);
31 :
32 : int OGROpenFileGDBIsComparisonOp(int op);
33 :
34 : // The FileGeodatabase format does not really allow strings of arbitrary width
35 : // in the XML and .gdbtable header declaration. They must have a non-zero
36 : // maximum width. But if we put it to a huge value (let's say 1 billion), this
37 : // causes crashes in some Esri products (cf #5952, perhaps they allocate
38 : // std::string's to that maximum size?).
39 : // Hence this default of a relative large but not too large
40 : // width when creating a OGR string field width of unspecified width.
41 : // Note that when opening a FileGeodatabase with string fields of that width,
42 : // we do not advertise it in OGRFieldDefn::GetWidth() but we advertise 0 instead,
43 : // to allow round-tripping.
44 : constexpr int DEFAULT_STRING_WIDTH = 65536;
45 :
46 : // UUID of object type
47 : constexpr const char *pszFolderTypeUUID =
48 : "{f3783e6f-65ca-4514-8315-ce3985dad3b1}";
49 : constexpr const char *pszWorkspaceTypeUUID =
50 : "{c673fe0f-7280-404f-8532-20755dd8fc06}";
51 : constexpr const char *pszFeatureDatasetTypeUUID =
52 : "{74737149-DCB5-4257-8904-B9724E32A530}";
53 : constexpr const char *pszFeatureClassTypeUUID =
54 : "{70737809-852c-4a03-9e22-2cecea5b9bfa}";
55 : constexpr const char *pszTableTypeUUID =
56 : "{cd06bc3b-789d-4c51-aafa-a467912b8965}";
57 : constexpr const char *pszRangeDomainTypeUUID =
58 : "{c29da988-8c3e-45f7-8b5c-18e51ee7beb4}";
59 : constexpr const char *pszCodedDomainTypeUUID =
60 : "{8c368b12-a12e-4c7e-9638-c9c64e69e98f}";
61 : constexpr const char *pszRelationshipTypeUUID =
62 : "{b606a7e1-fa5b-439c-849c-6e9c2481537b}";
63 :
64 : // UUID of relationship type
65 : constexpr const char *pszDatasetInFeatureDatasetUUID =
66 : "{a1633a59-46ba-4448-8706-d8abe2b2b02e}";
67 : constexpr const char *pszDatasetInFolderUUID =
68 : "{dc78f1ab-34e4-43ac-ba47-1c4eabd0e7c7}";
69 : constexpr const char *pszDomainInDatasetUUID =
70 : "{17e08adb-2b31-4dcd-8fdd-df529e88f843}";
71 : constexpr const char *pszDatasetsRelatedThroughUUID =
72 : "{725badab-3452-491b-a795-55f32d67229c}";
73 :
74 : /***********************************************************************/
75 : /* FETCH_FIELD_IDX() */
76 : /***********************************************************************/
77 :
78 : #define FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, errorCode) \
79 : const int idxName = oTable.GetFieldIdx(varName); \
80 : if (idxName < 0 || oTable.GetField(idxName)->GetType() != type) \
81 : { \
82 : CPLError(CE_Failure, CPLE_AppDefined, \
83 : "Could not find field %s in table %s", varName, \
84 : oTable.GetFilename().c_str()); \
85 : return errorCode; \
86 : }
87 :
88 : #define FETCH_FIELD_IDX(idxName, varName, type) \
89 : FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, false)
90 :
91 : /************************************************************************/
92 : /* OGROpenFileGDBLayer */
93 : /************************************************************************/
94 :
95 : class OGROpenFileGDBDataSource;
96 : class OGROpenFileGDBGeomFieldDefn;
97 : class OGROpenFileGDBFeatureDefn;
98 :
99 : typedef enum
100 : {
101 : SPI_IN_BUILDING,
102 : SPI_COMPLETED,
103 : SPI_INVALID,
104 : } SPIState;
105 :
106 : class OGROpenFileGDBLayer final : public OGRLayer
107 : {
108 : friend class OGROpenFileGDBGeomFieldDefn;
109 : friend class OGROpenFileGDBFeatureDefn;
110 :
111 : OGROpenFileGDBDataSource *m_poDS = nullptr;
112 : CPLString m_osGDBFilename{};
113 : CPLString m_osName{};
114 : std::string m_osPath{};
115 : std::string m_osThisGUID{};
116 : bool m_bEditable = false;
117 : bool m_bRegisteredTable = true;
118 : CPLStringList m_aosCreationOptions{};
119 : FileGDBTable *m_poLyrTable = nullptr;
120 : OGROpenFileGDBFeatureDefn *m_poFeatureDefn = nullptr;
121 : int m_iGeomFieldIdx = -1;
122 : int m_iAreaField = -1; // index of Shape_Area field
123 : int m_iLengthField = -1; // index of Shape_Length field
124 : int64_t m_iCurFeat = 0;
125 : int m_iFIDAsRegularColumnIndex = -1;
126 : std::string m_osDefinition{};
127 : std::string m_osDocumentation{};
128 : std::string m_osConfigurationKeyword{};
129 : OGRwkbGeometryType m_eGeomType = wkbNone;
130 : bool m_bArcGISPro32OrLater = false;
131 : int m_bValidLayerDefn = -1;
132 : int m_bEOF = false;
133 : bool m_bTimeInUTC = false;
134 : std::string m_osFeatureDatasetGUID{};
135 :
136 : bool m_bWarnedDateNotConvertibleUTC = false;
137 :
138 : bool m_bHasCreatedBackupForTransaction = false;
139 : std::unique_ptr<OGRFeatureDefn> m_poFeatureDefnBackup{};
140 :
141 : int BuildLayerDefinition();
142 : int BuildGeometryColumnGDBv10(const std::string &osParentDefinition);
143 : OGRFeature *GetCurrentFeature();
144 :
145 : std::unique_ptr<FileGDBOGRGeometryConverter> m_poGeomConverter{};
146 :
147 : int m_iFieldToReadAsBinary = -1;
148 :
149 : FileGDBIterator *m_poAttributeIterator = nullptr;
150 : int m_bIteratorSufficientToEvaluateFilter = FALSE;
151 : FileGDBIterator *BuildIteratorFromExprNode(swq_expr_node *poNode);
152 :
153 : FileGDBIterator *m_poIterMinMax = nullptr;
154 :
155 : FileGDBSpatialIndexIterator *m_poSpatialIndexIterator = nullptr;
156 : FileGDBIterator *m_poCombinedIterator = nullptr;
157 :
158 : // Legacy behavior prior to handling of .spx file
159 : // To remove ultimately.
160 : SPIState m_eSpatialIndexState = SPI_IN_BUILDING;
161 : CPLQuadTree *m_pQuadTree = nullptr;
162 : void **m_pahFilteredFeatures = nullptr;
163 : int m_nFilteredFeatureCount = -1;
164 : static void GetBoundsFuncEx(const void *hFeature, CPLRectObj *pBounds,
165 : void *pQTUserData);
166 :
167 : void TryToDetectMultiPatchKind();
168 : void BuildCombinedIterator();
169 : bool RegisterTable();
170 : void RefreshXMLDefinitionInMemory();
171 : bool CreateFeatureDataset(const char *pszFeatureDataset);
172 : std::string GetLaunderedFieldName(const std::string &osNameOri) const;
173 : std::string GetLaunderedLayerName(const std::string &osNameOri) const;
174 :
175 : mutable std::vector<std::string> m_aosTempStrings{};
176 : bool PrepareFileGDBFeature(OGRFeature *poFeature,
177 : std::vector<OGRField> &fields,
178 : const OGRGeometry *&poGeom, bool bUpdate);
179 :
180 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBLayer)
181 :
182 : public:
183 : OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
184 : const char *pszGDBFilename, const char *pszName,
185 : const std::string &osDefinition,
186 : const std::string &osDocumentation, bool bEditable,
187 : OGRwkbGeometryType eGeomType = wkbUnknown,
188 : const std::string &osParentDefinition = std::string());
189 :
190 : OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
191 : const char *pszGDBFilename, const char *pszName,
192 : OGRwkbGeometryType eType, CSLConstList papszOptions);
193 :
194 : virtual ~OGROpenFileGDBLayer();
195 :
196 : bool Create(const OGRGeomFieldDefn *poSrcGeomFieldDefn);
197 : void Close();
198 :
199 35 : const std::string &GetFilename() const
200 : {
201 35 : return m_osGDBFilename;
202 : }
203 :
204 31 : const std::string &GetXMLDefinition()
205 : {
206 31 : return m_osDefinition;
207 : }
208 :
209 20 : const std::string &GetXMLDocumentation()
210 : {
211 20 : return m_osDocumentation;
212 : }
213 :
214 141 : int GetAttrIndexUse()
215 : {
216 257 : return (m_poAttributeIterator == nullptr) ? 0
217 116 : : (m_bIteratorSufficientToEvaluateFilter) ? 2
218 141 : : 1;
219 : }
220 :
221 : const OGRField *GetMinMaxValue(OGRFieldDefn *poFieldDefn, int bIsMin,
222 : int &eOutType);
223 : int GetMinMaxSumCount(OGRFieldDefn *poFieldDefn, double &dfMin,
224 : double &dfMax, double &dfSum, int &nCount);
225 : bool HasIndexForField(const char *pszFieldName);
226 : FileGDBIterator *BuildIndex(const char *pszFieldName, int bAscending,
227 : int op, swq_expr_node *poValue);
228 :
229 12 : SPIState GetSpatialIndexState() const
230 : {
231 12 : return m_eSpatialIndexState;
232 : }
233 :
234 1 : int IsValidLayerDefn()
235 : {
236 1 : return BuildLayerDefinition();
237 : }
238 :
239 : void CreateSpatialIndex();
240 : void CreateIndex(const std::string &osIdxName,
241 : const std::string &osExpression);
242 : bool Repack(GDALProgressFunc pfnProgress, void *pProgressData);
243 : void RecomputeExtent();
244 :
245 : bool CheckFreeListConsistency();
246 :
247 : bool BeginEmulatedTransaction();
248 : bool CommitEmulatedTransaction();
249 : bool RollbackEmulatedTransaction();
250 :
251 : GDALDataset *GetDataset() override;
252 :
253 1235270 : virtual const char *GetName() override
254 : {
255 1235270 : 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 3160 : OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer *poLayer,
314 : const char *pszNameIn,
315 : OGRwkbGeometryType eGeomTypeIn)
316 3160 : : OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
317 : {
318 3160 : }
319 :
320 6320 : ~OGROpenFileGDBGeomFieldDefn()
321 3160 : {
322 6320 : }
323 :
324 3159 : void UnsetLayer()
325 : {
326 3159 : m_poLayer = nullptr;
327 3159 : }
328 :
329 11361 : virtual const OGRSpatialReference *GetSpatialRef() const override
330 : {
331 11361 : if (poSRS)
332 8378 : 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 273835 : void LazyGeomInit() const
348 : {
349 : /* FileGDB v9 case */
350 160320 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr &&
351 535877 : m_poLayer->m_eGeomType != wkbNone &&
352 101722 : m_poLayer->m_osDefinition.empty())
353 : {
354 259 : m_bHasBuiltFieldDefn = true;
355 259 : (void)m_poLayer->BuildLayerDefinition();
356 : }
357 273835 : }
358 :
359 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBFeatureDefn)
360 :
361 : public:
362 11173 : OGROpenFileGDBFeatureDefn(OGROpenFileGDBLayer *poLayer, const char *pszName,
363 : bool bHasBuiltFieldDefn)
364 11173 : : OGRFeatureDefn(pszName), m_poLayer(poLayer),
365 11173 : m_bHasBuiltFieldDefn(bHasBuiltFieldDefn)
366 : {
367 11173 : }
368 :
369 22332 : ~OGROpenFileGDBFeatureDefn()
370 11166 : {
371 22332 : }
372 :
373 11166 : void UnsetLayer()
374 : {
375 11166 : if (!apoGeomFieldDefn.empty())
376 : cpl::down_cast<OGROpenFileGDBGeomFieldDefn *>(
377 3159 : apoGeomFieldDefn[0].get())
378 3159 : ->UnsetLayer();
379 11166 : m_poLayer = nullptr;
380 11166 : }
381 :
382 607707 : virtual int GetFieldCount() const override
383 : {
384 607707 : if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr)
385 : {
386 225099 : m_bHasBuiltFieldDefn = false;
387 225099 : (void)m_poLayer->BuildLayerDefinition();
388 : }
389 607707 : return OGRFeatureDefn::GetFieldCount();
390 : }
391 :
392 229602 : virtual int GetGeomFieldCount() const override
393 : {
394 229602 : LazyGeomInit();
395 229602 : return OGRFeatureDefn::GetGeomFieldCount();
396 : }
397 :
398 43894 : virtual OGRGeomFieldDefn *GetGeomFieldDefn(int i) override
399 : {
400 43894 : LazyGeomInit();
401 43894 : return OGRFeatureDefn::GetGeomFieldDefn(i);
402 : }
403 :
404 339 : virtual const OGRGeomFieldDefn *GetGeomFieldDefn(int i) const override
405 : {
406 339 : LazyGeomInit();
407 339 : 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 2 : std::vector<std::unique_ptr<OGROpenFileGDBLayer>> &GetLayers()
523 : {
524 2 : return m_apoLayers;
525 : }
526 :
527 1215770 : virtual int GetLayerCount() override
528 : {
529 1215770 : return static_cast<int>(m_apoLayers.size());
530 : }
531 :
532 : virtual OGRLayer *GetLayer(int) override;
533 : virtual OGROpenFileGDBLayer *GetLayerByName(const char *pszName) override;
534 : bool IsLayerPrivate(int) const override;
535 :
536 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
537 : OGRGeometry *poSpatialFilter,
538 : const char *pszDialect) override;
539 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
540 :
541 : virtual int TestCapability(const char *) override;
542 :
543 : OGRLayer *ICreateLayer(const char *pszName,
544 : const OGRGeomFieldDefn *poGeomFieldDefn,
545 : CSLConstList papszOptions) override;
546 :
547 : virtual OGRErr DeleteLayer(int) override;
548 :
549 : virtual char **GetFileList() override;
550 :
551 6 : std::shared_ptr<GDALGroup> GetRootGroup() const override
552 : {
553 6 : return m_poRootGroup;
554 : }
555 :
556 : virtual OGRErr StartTransaction(int bForce) override;
557 : virtual OGRErr CommitTransaction() override;
558 : virtual OGRErr RollbackTransaction() override;
559 :
560 498 : const CPLStringList &GetSubdatasets() const
561 : {
562 498 : return m_aosSubdatasets;
563 : }
564 :
565 : CPLErr GetGeoTransform(double *padfGeoTransform) override;
566 : const OGRSpatialReference *GetSpatialRef() const override;
567 :
568 : char **GetMetadata(const char *pszDomain = "") override;
569 :
570 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
571 : std::string &failureReason) override;
572 :
573 : bool DeleteFieldDomain(const std::string &name,
574 : std::string &failureReason) override;
575 :
576 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
577 : std::string &failureReason) override;
578 :
579 : std::vector<std::string>
580 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
581 :
582 : const GDALRelationship *
583 : GetRelationship(const std::string &name) const override;
584 :
585 : bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
586 : std::string &failureReason) override;
587 :
588 : bool DeleteRelationship(const std::string &name,
589 : std::string &failureReason) override;
590 :
591 : bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
592 : std::string &failureReason) override;
593 :
594 : bool GetExistingSpatialRef(const std::string &osWKT, double dfXOrigin,
595 : double dfYOrigin, double dfXYScale,
596 : double dfZOrigin, double dfZScale,
597 : double dfMOrigin, double dfMScale,
598 : double dfXYTolerance, double dfZTolerance,
599 : double dfMTolerance);
600 :
601 : bool AddNewSpatialRef(const std::string &osWKT, double dfXOrigin,
602 : double dfYOrigin, double dfXYScale, double dfZOrigin,
603 : double dfZScale, double dfMOrigin, double dfMScale,
604 : double dfXYTolerance, double dfZTolerance,
605 : double dfMTolerance);
606 :
607 : bool RegisterLayerInSystemCatalog(const std::string &osLayerName);
608 :
609 : bool RegisterInItemRelationships(const std::string &osOriginGUID,
610 : const std::string &osDestGUID,
611 : const std::string &osTypeGUID);
612 :
613 : bool RegisterRelationshipInItemRelationships(
614 : const std::string &osRelationshipGUID, const std::string &osOriginGUID,
615 : const std::string &osDestGUID);
616 :
617 : bool RemoveRelationshipFromItemRelationships(
618 : const std::string &osRelationshipGUID);
619 :
620 : bool RegisterFeatureDatasetInItems(const std::string &osFeatureDatasetGUID,
621 : const std::string &osName,
622 : const char *pszXMLDefinition);
623 :
624 : bool FindUUIDFromName(const std::string &osFeatureDatasetName,
625 : std::string &osUUIDOut);
626 :
627 : bool RegisterFeatureClassInItems(const std::string &osLayerGUID,
628 : const std::string &osLayerName,
629 : const std::string &osPath,
630 : const FileGDBTable *poLyrTable,
631 : const char *pszXMLDefinition,
632 : const char *pszDocumentation);
633 :
634 : bool RegisterASpatialTableInItems(const std::string &osLayerGUID,
635 : const std::string &osLayerName,
636 : const std::string &osPath,
637 : const char *pszXMLDefinition,
638 : const char *pszDocumentation);
639 :
640 : bool LinkDomainToTable(const std::string &osDomainName,
641 : const std::string &osLayerGUID);
642 : bool UnlinkDomainToTable(const std::string &osDomainName,
643 : const std::string &osLayerGUID);
644 :
645 : bool UpdateXMLDefinition(const std::string &osLayerName,
646 : const char *pszXMLDefinition);
647 :
648 13071 : bool IsInTransaction() const
649 : {
650 13071 : return m_bInTransaction;
651 : }
652 :
653 40 : const std::string &GetBackupDirName() const
654 : {
655 40 : return m_osTransactionBackupDirname;
656 : }
657 :
658 : OGRSpatialReference *BuildSRS(const CPLXMLNode *psInfo);
659 : OGRSpatialReference *BuildSRS(const char *pszWKT);
660 : };
661 :
662 : /************************************************************************/
663 : /* OGROpenFileGDBSingleFeatureLayer */
664 : /************************************************************************/
665 :
666 : class OGROpenFileGDBSingleFeatureLayer final : public OGRLayer
667 : {
668 : private:
669 : char *pszVal;
670 : OGRFeatureDefn *poFeatureDefn;
671 : int iNextShapeId;
672 :
673 : CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBSingleFeatureLayer)
674 :
675 : public:
676 : OGROpenFileGDBSingleFeatureLayer(const char *pszLayerName,
677 : const char *pszVal);
678 : virtual ~OGROpenFileGDBSingleFeatureLayer();
679 :
680 0 : virtual void ResetReading() override
681 : {
682 0 : iNextShapeId = 0;
683 0 : }
684 :
685 : virtual OGRFeature *GetNextFeature() override;
686 :
687 0 : virtual OGRFeatureDefn *GetLayerDefn() override
688 : {
689 0 : return poFeatureDefn;
690 : }
691 :
692 0 : virtual int TestCapability(const char *) override
693 : {
694 0 : return FALSE;
695 : }
696 : };
697 :
698 : /************************************************************************/
699 : /* GDALOpenFileGDBRasterAttributeTable */
700 : /************************************************************************/
701 :
702 : class GDALOpenFileGDBRasterAttributeTable final
703 : : public GDALRasterAttributeTable
704 : {
705 : std::unique_ptr<OGROpenFileGDBDataSource> m_poDS{};
706 : const std::string m_osVATTableName;
707 : std::unique_ptr<OGRLayer> m_poVATLayer{};
708 : mutable std::string m_osCachedValue{};
709 :
710 : GDALOpenFileGDBRasterAttributeTable(
711 : const GDALOpenFileGDBRasterAttributeTable &) = delete;
712 : GDALOpenFileGDBRasterAttributeTable &
713 : operator=(const GDALOpenFileGDBRasterAttributeTable &) = delete;
714 :
715 : public:
716 2 : GDALOpenFileGDBRasterAttributeTable(
717 : std::unique_ptr<OGROpenFileGDBDataSource> &&poDS,
718 : const std::string &osVATTableName,
719 : std::unique_ptr<OGRLayer> &&poVATLayer)
720 4 : : m_poDS(std::move(poDS)), m_osVATTableName(osVATTableName),
721 2 : m_poVATLayer(std::move(poVATLayer))
722 : {
723 2 : }
724 :
725 1 : GDALRasterAttributeTable *Clone() const override
726 : {
727 2 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
728 2 : GDALOpenInfo oOpenInfo(m_poDS->m_osDirName.c_str(), GA_ReadOnly);
729 1 : bool bRetryFileGDBUnused = false;
730 1 : if (!poDS->Open(&oOpenInfo, bRetryFileGDBUnused))
731 0 : return nullptr;
732 2 : auto poVatLayer = poDS->BuildLayerFromName(m_osVATTableName.c_str());
733 1 : if (!poVatLayer)
734 0 : return nullptr;
735 : return new GDALOpenFileGDBRasterAttributeTable(
736 1 : std::move(poDS), m_osVATTableName, std::move(poVatLayer));
737 : }
738 :
739 15 : int GetColumnCount() const override
740 : {
741 15 : return m_poVATLayer->GetLayerDefn()->GetFieldCount();
742 : }
743 :
744 3 : int GetRowCount() const override
745 : {
746 3 : return static_cast<int>(m_poVATLayer->GetFeatureCount());
747 : }
748 :
749 10 : const char *GetNameOfCol(int iCol) const override
750 : {
751 10 : if (iCol < 0 || iCol >= GetColumnCount())
752 4 : return nullptr;
753 6 : return m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetNameRef();
754 : }
755 :
756 5 : GDALRATFieldUsage GetUsageOfCol(int iCol) const override
757 : {
758 5 : const char *pszColName = GetNameOfCol(iCol);
759 9 : return pszColName && EQUAL(pszColName, "Value") ? GFU_MinMax
760 4 : : pszColName && EQUAL(pszColName, "Count") ? GFU_PixelCount
761 5 : : GFU_Generic;
762 : }
763 :
764 3 : int GetColOfUsage(GDALRATFieldUsage eUsage) const override
765 : {
766 3 : if (eUsage == GFU_MinMax)
767 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Value");
768 2 : if (eUsage == GFU_PixelCount)
769 1 : return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Count");
770 1 : return -1;
771 : }
772 :
773 5 : GDALRATFieldType GetTypeOfCol(int iCol) const override
774 : {
775 5 : if (iCol < 0 || iCol >= GetColumnCount())
776 2 : return GFT_Integer;
777 3 : switch (m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetType())
778 : {
779 1 : case OFTInteger:
780 1 : return GFT_Integer;
781 1 : case OFTReal:
782 1 : return GFT_Real;
783 1 : default:
784 1 : break;
785 : }
786 1 : return GFT_String;
787 : }
788 :
789 7 : const char *GetValueAsString(int iRow, int iField) const override
790 : {
791 : auto poFeat =
792 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
793 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
794 2 : return "";
795 5 : m_osCachedValue = poFeat->GetFieldAsString(iField);
796 5 : return m_osCachedValue.c_str();
797 : }
798 :
799 7 : int GetValueAsInt(int iRow, int iField) const override
800 : {
801 : auto poFeat =
802 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
803 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
804 2 : return 0;
805 5 : return poFeat->GetFieldAsInteger(iField);
806 : }
807 :
808 7 : double GetValueAsDouble(int iRow, int iField) const override
809 : {
810 : auto poFeat =
811 14 : std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
812 7 : if (!poFeat || iField >= poFeat->GetFieldCount())
813 2 : return 0;
814 5 : return poFeat->GetFieldAsDouble(iField);
815 : }
816 :
817 1 : CPLErr SetValue(int, int, const char *) override
818 : {
819 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
820 1 : return CE_Failure;
821 : }
822 :
823 1 : CPLErr SetValue(int, int, int) override
824 : {
825 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
826 1 : return CE_Failure;
827 : }
828 :
829 1 : CPLErr SetValue(int, int, double) override
830 : {
831 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
832 1 : return CE_Failure;
833 : }
834 :
835 0 : int ChangesAreWrittenToFile() override
836 : {
837 0 : return false;
838 : }
839 :
840 1 : CPLErr SetTableType(const GDALRATTableType) override
841 : {
842 1 : CPLError(CE_Failure, CPLE_NotSupported, "SetTableType() not supported");
843 1 : return CE_Failure;
844 : }
845 :
846 1 : GDALRATTableType GetTableType() const override
847 : {
848 1 : return GRTT_THEMATIC;
849 : }
850 :
851 0 : void RemoveStatistics() override
852 : {
853 0 : CPLError(CE_Failure, CPLE_NotSupported,
854 : "RemoveStatistics() not supported");
855 0 : }
856 : };
857 :
858 : /************************************************************************/
859 : /* GDALOpenFileGDBRasterBand */
860 : /************************************************************************/
861 :
862 : class GDALOpenFileGDBRasterBand final : public GDALRasterBand
863 : {
864 : friend class OGROpenFileGDBDataSource;
865 : std::vector<GByte> m_abyTmpBuffer{};
866 : int m_nBitWidth = 0;
867 : int m_nOverviewLevel = 0;
868 : std::vector<std::unique_ptr<GDALOpenFileGDBRasterBand>>
869 : m_apoOverviewBands{};
870 : bool m_bIsMask = false;
871 : std::unique_ptr<GDALOpenFileGDBRasterBand> m_poMaskBandOwned{};
872 : GDALOpenFileGDBRasterBand *m_poMainBand = nullptr;
873 : GDALOpenFileGDBRasterBand *m_poMaskBand = nullptr;
874 : bool m_bHasNoData = false;
875 : double m_dfNoData = 0.0;
876 : std::unique_ptr<GDALRasterAttributeTable> m_poRAT{};
877 :
878 : CPL_DISALLOW_COPY_ASSIGN(GDALOpenFileGDBRasterBand)
879 :
880 : public:
881 : GDALOpenFileGDBRasterBand(OGROpenFileGDBDataSource *poDSIn, int nBandIn,
882 : GDALDataType eDT, int nBitWidth, int nBlockWidth,
883 : int nBlockHeight, int nOverviewLevel,
884 : bool bIsMask);
885 :
886 : protected:
887 : CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) override;
888 :
889 12 : int GetOverviewCount() override
890 : {
891 12 : return static_cast<int>(m_apoOverviewBands.size());
892 : }
893 :
894 12 : GDALRasterBand *GetOverview(int i) override
895 : {
896 12 : return (i >= 0 && i < GetOverviewCount()) ? m_apoOverviewBands[i].get()
897 12 : : nullptr;
898 : }
899 :
900 15 : GDALRasterBand *GetMaskBand() override
901 : {
902 15 : return m_poMaskBand ? m_poMaskBand : GDALRasterBand::GetMaskBand();
903 : }
904 :
905 6 : int GetMaskFlags() override
906 : {
907 6 : return m_poMaskBand ? GMF_PER_DATASET : GDALRasterBand::GetMaskFlags();
908 : }
909 :
910 7 : double GetNoDataValue(int *pbHasNoData) override
911 : {
912 7 : if (pbHasNoData)
913 6 : *pbHasNoData = m_bHasNoData;
914 7 : return m_dfNoData;
915 : }
916 :
917 : GDALRasterAttributeTable *GetDefaultRAT() override;
918 : };
919 :
920 : #endif /* ndef OGR_OPENFILEGDB_H_INCLUDED */
|