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