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