Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Standard includes and class definitions ArcObjects OGR driver.
5 : * Author: Ragi Yaser Burhum, ragi@burhum.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2009, Ragi Yaser Burhum
9 : * Copyright (c) 2011-2014, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef OGR_FGDB_H_INCLUDED
15 : #define OGR_FGDB_H_INCLUDED
16 :
17 : #include <vector>
18 : #include <set>
19 : #include "ogrsf_frmts.h"
20 : #include "ogremulatedtransaction.h"
21 :
22 : /* GDAL string utilities */
23 : #include "cpl_string.h"
24 :
25 : /* GDAL XML handler */
26 : #include "cpl_minixml.h"
27 :
28 : /* FGDB API headers through our own inclusion file */
29 : #include "filegdbsdk_headers.h"
30 :
31 : /* Workaround needed for Linux, at least for FileGDB API 1.1 (#4455) */
32 : #if defined(__linux__)
33 : #define EXTENT_WORKAROUND
34 : #endif
35 :
36 : /************************************************************************
37 : * Default layer creation options
38 : */
39 :
40 : #define FGDB_FEATURE_DATASET "";
41 : #define FGDB_GEOMETRY_NAME "SHAPE"
42 : #define FGDB_OID_NAME "OBJECTID"
43 : constexpr const char *pszRelationshipTypeUUID =
44 : "{B606A7E1-FA5B-439C-849C-6E9C2481537B}";
45 :
46 : /* The ESRI FGDB API namespace */
47 : using namespace FileGDBAPI;
48 :
49 : class FGdbDriver;
50 :
51 : /************************************************************************/
52 : /* FGdbBaseLayer */
53 : /************************************************************************/
54 :
55 : class FGdbBaseLayer CPL_NON_FINAL : public OGRLayer
56 : {
57 : protected:
58 : FGdbBaseLayer();
59 : virtual ~FGdbBaseLayer();
60 :
61 : OGRFeatureDefn *m_pFeatureDefn;
62 : OGRSpatialReference *m_pSRS;
63 :
64 : EnumRows *m_pEnumRows;
65 :
66 : std::vector<std::wstring>
67 : m_vOGRFieldToESRIField; // OGR Field Index to ESRI Field Name Mapping
68 : std::vector<std::string>
69 : m_vOGRFieldToESRIFieldType; // OGR Field Index to ESRI Field Type
70 : // Mapping
71 :
72 : bool m_suppressColumnMappingError;
73 : bool m_forceMulti;
74 : bool m_bTimeInUTC = false;
75 :
76 : bool OGRFeatureFromGdbRow(Row *pRow, OGRFeature **ppFeature);
77 :
78 : virtual void CloseGDBObjects();
79 :
80 : public:
81 : virtual OGRFeature *GetNextFeature() override;
82 : };
83 :
84 : /************************************************************************/
85 : /* FGdbLayer */
86 : /************************************************************************/
87 :
88 : class FGdbDataSource;
89 :
90 : class FGdbLayer final : public FGdbBaseLayer
91 : {
92 : friend class FGdbDataSource;
93 :
94 : bool m_bWorkaroundCrashOnCDFWithBinaryField = false;
95 :
96 : int m_bBulkLoadAllowed;
97 : int m_bBulkLoadInProgress;
98 :
99 : virtual void CloseGDBObjects() override;
100 : int EditIndexesForFIDHack(const char *pszRadixTablename);
101 : int EditGDBTablX(const CPLString &osGDBTablX,
102 : const CPLString &osNewGDBTablX);
103 : int EditATXOrSPX(const CPLString &osIndex);
104 : int EditATXOrSPX(VSILFILE *fp, int nThisPage, int &nLastPageVisited,
105 : int nDepth, int nSizeIndexedValue,
106 : GByte *pabyLastIndexedValue, int &bIndexedValueIsValid,
107 : int &nFirstIndexAtThisValue,
108 : std::vector<int> &anPagesAtThisValue, int &bSortThisValue,
109 : int &bInvalidateIndex);
110 :
111 : void StartBulkLoad();
112 : void EndBulkLoad();
113 :
114 : #ifdef EXTENT_WORKAROUND
115 : bool m_bLayerJustCreated;
116 : OGREnvelope sLayerEnvelope;
117 : bool m_bLayerEnvelopeValid;
118 : void WorkAroundExtentProblem();
119 : bool UpdateRowWithGeometry(Row &row, OGRGeometry *poGeom);
120 : #endif
121 :
122 : std::vector<ByteArray *> m_apoByteArrays;
123 : OGRErr PopulateRowWithFeature(Row &row, OGRFeature *poFeature);
124 : OGRErr GetRow(EnumRows &enumRows, Row &row, GIntBig nFID);
125 :
126 : char **m_papszOptions;
127 :
128 : int m_bCreateMultipatch;
129 :
130 : std::map<int, int> m_oMapOGRFIDToFGDBFID;
131 : std::map<int, int> m_oMapFGDBFIDToOGRFID;
132 : int m_nResyncThreshold;
133 : void ResyncIDs();
134 :
135 : int m_bSymlinkFlag;
136 : int CreateRealCopy();
137 :
138 : char *CreateFieldDefn(OGRFieldDefn &oField, int bApproxOK,
139 : std::string &fieldname_clean,
140 : std::string &gdbFieldType);
141 :
142 : public:
143 : FGdbLayer();
144 : virtual ~FGdbLayer();
145 :
146 : // Internal used by FGDB driver */
147 : bool Initialize(FGdbDataSource *pParentDataSource, Table *pTable,
148 : const std::wstring &wstrTablePath,
149 : const std::wstring &wstrType);
150 : bool Create(FGdbDataSource *pParentDataSource, const char *pszLayerName,
151 : const OGRGeomFieldDefn *poSrcGeomFieldDefn,
152 : CSLConstList papszOptions);
153 : static bool CreateFeatureDataset(FGdbDataSource *pParentDataSource,
154 : const std::string &feature_dataset_name,
155 : const OGRGeomFieldDefn *poSrcGeomFieldDefn,
156 : CSLConstList papszOptions);
157 :
158 : // virtual const char *GetName();
159 683 : virtual const char *GetFIDColumn() override
160 : {
161 683 : return m_strOIDFieldName.c_str();
162 : }
163 :
164 : virtual void ResetReading() override;
165 : virtual OGRFeature *GetNextFeature() override;
166 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
167 :
168 : Table *GetTable()
169 : {
170 : return m_pTable;
171 : }
172 :
173 2 : std::wstring GetTablePath() const
174 : {
175 2 : return m_wstrTablePath;
176 : }
177 :
178 2 : std::wstring GetType() const
179 : {
180 2 : return m_wstrType;
181 : }
182 :
183 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
184 : int bApproxOK) override;
185 : virtual OGRErr DeleteField(int iFieldToDelete) override;
186 : #ifdef AlterFieldDefn_implemented_but_not_working
187 : virtual OGRErr AlterFieldDefn(int iFieldToAlter,
188 : OGRFieldDefn *poNewFieldDefn, int nFlags);
189 : #endif
190 :
191 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
192 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
193 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
194 :
195 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce) override;
196 :
197 68 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
198 : int bForce) override
199 : {
200 68 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
201 : }
202 :
203 : virtual GIntBig GetFeatureCount(int bForce) override;
204 : virtual OGRErr SetAttributeFilter(const char *pszQuery) override;
205 :
206 : virtual void SetSpatialFilter(OGRGeometry *) override;
207 :
208 213 : virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
209 : {
210 213 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
211 213 : }
212 :
213 : // virtual OGRErr StartTransaction( );
214 : // virtual OGRErr CommitTransaction( );
215 : // virtual OGRErr RollbackTransaction( );
216 :
217 21702 : OGRFeatureDefn *GetLayerDefn() override
218 : {
219 21702 : return m_pFeatureDefn;
220 : }
221 :
222 : virtual int TestCapability(const char *) override;
223 :
224 : // Access the XML directly. The 2 following methods are not currently used
225 : // by the driver, but can be used by external code for specific purposes.
226 : OGRErr GetLayerXML(char **poXml);
227 : OGRErr GetLayerMetadataXML(char **poXmlMeta);
228 :
229 0 : void SetSymlinkFlag()
230 : {
231 0 : m_bSymlinkFlag = TRUE;
232 0 : }
233 :
234 : virtual const char *GetMetadataItem(const char *pszName,
235 : const char *pszDomain) override;
236 :
237 : virtual OGRErr Rename(const char *pszNewName) override;
238 :
239 : GDALDataset *GetDataset() override;
240 :
241 : protected:
242 : bool GDBToOGRFields(CPLXMLNode *psFields);
243 : bool ParseGeometryDef(const CPLXMLNode *psGeometryDef);
244 :
245 : static bool ParseSpatialReference(const CPLXMLNode *psSpatialRefNode,
246 : std::string *pOutWkt,
247 : std::string *pOutWKID,
248 : std::string *pOutLatestWKID);
249 :
250 : FGdbDataSource *m_pDS;
251 : Table *m_pTable;
252 :
253 : std::string
254 : m_strName; // contains underlying FGDB table name (not catalog name)
255 :
256 : std::string m_strOIDFieldName;
257 : std::string m_strShapeFieldName;
258 :
259 : std::wstring m_wstrTablePath;
260 : std::wstring m_wstrType; // the type: "Table" or "Feature Class"
261 :
262 : std::wstring m_wstrSubfields;
263 : std::wstring m_wstrWhereClause;
264 :
265 : bool m_bFilterDirty; // optimization to avoid multiple calls to search
266 : // until necessary
267 :
268 : bool m_bLaunderReservedKeywords;
269 : };
270 :
271 : /************************************************************************/
272 : /* FGdbResultLayer */
273 : /************************************************************************/
274 :
275 : class FGdbResultLayer final : public FGdbBaseLayer
276 : {
277 : public:
278 : FGdbResultLayer(FGdbDataSource *pParentDataSource, const char *pszStatement,
279 : EnumRows *pEnumRows);
280 : virtual ~FGdbResultLayer();
281 :
282 : virtual void ResetReading() override;
283 :
284 0 : OGRFeatureDefn *GetLayerDefn() override
285 : {
286 0 : return m_pFeatureDefn;
287 : }
288 :
289 : virtual int TestCapability(const char *) override;
290 :
291 : protected:
292 : FGdbDataSource *m_pDS;
293 : CPLString osSQL;
294 : };
295 :
296 : /************************************************************************/
297 : /* FGdbDataSource */
298 : /************************************************************************/
299 :
300 : class FGdbDatabaseConnection;
301 : class OGRFileGDBGroup;
302 :
303 : class FGdbDataSource final : public GDALDataset
304 : {
305 : CPLString m_osFSName;
306 : CPLString m_osPublicName;
307 : std::set<OGRLayer *> m_oSetSelectLayers;
308 : std::shared_ptr<GDALGroup> m_poRootGroup{};
309 : std::map<std::string, std::unique_ptr<GDALRelationship>>
310 : m_osMapRelationships{};
311 :
312 : int FixIndexes();
313 : int bPerLayerCopyingForTransaction;
314 :
315 : public:
316 : FGdbDataSource(bool bUseDriverMutex, FGdbDatabaseConnection *pConnection,
317 : bool bUseOpenFileGDB);
318 : virtual ~FGdbDataSource();
319 :
320 : int Open(const char *pszFSName, int bUpdate, const char *pszPublicName);
321 :
322 406 : const char *GetFSName()
323 : {
324 406 : return m_osFSName.c_str();
325 : }
326 :
327 9029 : int GetLayerCount() override
328 : {
329 9029 : return static_cast<int>(m_layers.size());
330 : }
331 :
332 : OGRLayer *GetLayer(int) override;
333 :
334 : OGRLayer *ICreateLayer(const char *pszName,
335 : const OGRGeomFieldDefn *poGeomFieldDefn,
336 : CSLConstList papszOptions) override;
337 :
338 : virtual OGRErr DeleteLayer(int) override;
339 :
340 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
341 : OGRGeometry *poSpatialFilter,
342 : const char *pszDialect) override;
343 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
344 :
345 : int TestCapability(const char *) override;
346 :
347 : const OGRFieldDomain *
348 : GetFieldDomain(const std::string &name) const override;
349 : std::vector<std::string>
350 : GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
351 :
352 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
353 : std::string &failureReason) override;
354 :
355 : bool DeleteFieldDomain(const std::string &name,
356 : std::string &failureReason) override;
357 :
358 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
359 : std::string &failureReason) override;
360 :
361 : std::vector<std::string>
362 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
363 :
364 : const GDALRelationship *
365 : GetRelationship(const std::string &name) const override;
366 :
367 1 : std::shared_ptr<GDALGroup> GetRootGroup() const override
368 : {
369 1 : return m_poRootGroup;
370 : }
371 :
372 567 : Geodatabase *GetGDB()
373 : {
374 567 : return m_pGeodatabase;
375 : }
376 :
377 3129 : bool GetUpdate()
378 : {
379 3129 : return m_bUpdate;
380 : }
381 :
382 2 : FGdbDatabaseConnection *GetConnection()
383 : {
384 2 : return m_pConnection;
385 : }
386 :
387 1 : GDALDriver *GetOpenFileGDBDrv()
388 : {
389 1 : return m_poOpenFileGDBDrv;
390 : }
391 :
392 1 : int HasSelectLayers()
393 : {
394 1 : return !m_oSetSelectLayers.empty();
395 : }
396 :
397 : int CloseInternal(int bCloseGeodatabase = FALSE);
398 : int ReOpen();
399 :
400 : int HasPerLayerCopyingForTransaction();
401 :
402 0 : void SetPerLayerCopyingForTransaction(int bFlag)
403 : {
404 0 : bPerLayerCopyingForTransaction = bFlag;
405 0 : }
406 :
407 : void SetSymlinkFlagOnAllLayers();
408 :
409 408 : bool UseOpenFileGDB() const
410 : {
411 408 : return m_bUseOpenFileGDB;
412 : }
413 :
414 : /*
415 : protected:
416 :
417 : void EnumerateSpatialTables();
418 : void OpenSpatialTable( const char* pszTableName );
419 : */
420 : protected:
421 : bool LoadLayers(const std::wstring &parent);
422 : bool OpenFGDBTables(OGRFileGDBGroup *group, const std::wstring &type,
423 : const std::vector<std::wstring> &layers);
424 :
425 : bool m_bUseDriverMutex = true;
426 : FGdbDatabaseConnection *m_pConnection;
427 : std::vector<OGRLayer *> m_layers;
428 : Geodatabase *m_pGeodatabase;
429 : bool m_bUpdate;
430 : GDALDriver *m_poOpenFileGDBDrv;
431 : std::unique_ptr<GDALDataset> m_poOpenFileGDBDS;
432 : bool m_bUseOpenFileGDB = false;
433 : };
434 :
435 : /************************************************************************/
436 : /* FGdbDriver */
437 : /************************************************************************/
438 :
439 : class FGdbDatabaseConnection
440 : {
441 : public:
442 76 : FGdbDatabaseConnection(const std::string &osName, Geodatabase *pGeodatabase)
443 76 : : m_osName(osName), m_pGeodatabase(pGeodatabase), m_nRefCount(1),
444 76 : m_bLocked(FALSE), m_bFIDHackInProgress(FALSE)
445 : {
446 76 : }
447 :
448 : std::string m_osName;
449 : Geodatabase *m_pGeodatabase;
450 : int m_nRefCount;
451 : int m_bLocked;
452 : int m_bFIDHackInProgress;
453 :
454 88 : Geodatabase *GetGDB()
455 : {
456 88 : return m_pGeodatabase;
457 : }
458 :
459 0 : void SetLocked(int bLockedIn)
460 : {
461 0 : m_bLocked = bLockedIn;
462 0 : }
463 :
464 1 : int GetRefCount() const
465 : {
466 1 : return m_nRefCount;
467 : }
468 :
469 87 : int IsLocked() const
470 : {
471 87 : return m_bLocked;
472 : }
473 :
474 231 : int IsFIDHackInProgress() const
475 : {
476 231 : return m_bFIDHackInProgress;
477 : }
478 :
479 2 : void SetFIDHackInProgress(int bFlag)
480 : {
481 2 : m_bFIDHackInProgress = bFlag;
482 2 : }
483 :
484 : int OpenGeodatabase(const char *pszOverriddenName);
485 : void CloseGeodatabase();
486 : };
487 :
488 : class FGdbTransactionManager final : public IOGRTransactionBehaviour
489 : {
490 : public:
491 : virtual OGRErr StartTransaction(GDALDataset *&poDSInOut,
492 : int &bOutHasReopenedDS) override;
493 : virtual OGRErr CommitTransaction(GDALDataset *&poDSInOut,
494 : int &bOutHasReopenedDS) override;
495 : virtual OGRErr RollbackTransaction(GDALDataset *&poDSInOut,
496 : int &bOutHasReopenedDS) override;
497 : };
498 :
499 : class FGdbDriver final : public GDALDriver
500 : {
501 : public:
502 : static void Release(const char *pszName);
503 :
504 : static FGdbTransactionManager *GetTransactionManager();
505 :
506 : static CPLMutex *hMutex;
507 : static FGdbTransactionManager *m_poTransactionManager;
508 : };
509 :
510 : CPL_C_START
511 : void CPL_DLL RegisterOGRFileGDB();
512 : CPL_C_END
513 :
514 : #endif /* ndef _OGR_PG_H_INCLUDED */
|