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