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