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 : 21 : /* GDAL string utilities */ 22 : #include "cpl_string.h" 23 : 24 : /* GDAL XML handler */ 25 : #include "cpl_minixml.h" 26 : 27 : /* FGDB API headers through our own inclusion file */ 28 : #include "filegdbsdk_headers.h" 29 : 30 : /* Workaround needed for Linux, at least for FileGDB API 1.1 (#4455) */ 31 : #if defined(__linux__) 32 : #define EXTENT_WORKAROUND 33 : #endif 34 : 35 : /************************************************************************ 36 : * Default layer creation options 37 : */ 38 : 39 : #define FGDB_FEATURE_DATASET ""; 40 : #define FGDB_GEOMETRY_NAME "SHAPE" 41 : #define FGDB_OID_NAME "OBJECTID" 42 : constexpr const char *pszRelationshipTypeUUID = 43 : "{B606A7E1-FA5B-439C-849C-6E9C2481537B}"; 44 : 45 : /* The ESRI FGDB API namespace */ 46 : using namespace FileGDBAPI; 47 : 48 : class FGdbDriver; 49 : 50 : /************************************************************************/ 51 : /* FGdbBaseLayer */ 52 : /************************************************************************/ 53 : 54 : class FGdbBaseLayer CPL_NON_FINAL : public OGRLayer 55 : { 56 : protected: 57 : FGdbBaseLayer(); 58 : virtual ~FGdbBaseLayer(); 59 : 60 : OGRFeatureDefn *m_pFeatureDefn; 61 : OGRSpatialReference *m_pSRS; 62 : 63 : EnumRows *m_pEnumRows; 64 : 65 : std::vector<std::wstring> 66 : m_vOGRFieldToESRIField; // OGR Field Index to ESRI Field Name Mapping 67 : std::vector<std::string> 68 : m_vOGRFieldToESRIFieldType; // OGR Field Index to ESRI Field Type 69 : // Mapping 70 : 71 : bool m_suppressColumnMappingError; 72 : bool m_forceMulti; 73 : bool m_bTimeInUTC = false; 74 : 75 : bool OGRFeatureFromGdbRow(Row *pRow, OGRFeature **ppFeature); 76 : 77 : virtual void CloseGDBObjects(); 78 : 79 : public: 80 : virtual OGRFeature *GetNextFeature() override; 81 : }; 82 : 83 : /************************************************************************/ 84 : /* FGdbLayer */ 85 : /************************************************************************/ 86 : 87 : class FGdbDataSource; 88 : 89 : class FGdbLayer final : public FGdbBaseLayer 90 : { 91 : friend class FGdbDataSource; 92 : 93 : bool m_bWorkaroundCrashOnCDFWithBinaryField = false; 94 : 95 : virtual void CloseGDBObjects() override; 96 : 97 : #ifdef EXTENT_WORKAROUND 98 : OGREnvelope sLayerEnvelope; 99 : bool m_bLayerEnvelopeValid; 100 : void WorkAroundExtentProblem(); 101 : bool UpdateRowWithGeometry(Row &row, OGRGeometry *poGeom); 102 : #endif 103 : 104 : std::vector<ByteArray *> m_apoByteArrays; 105 : OGRErr PopulateRowWithFeature(Row &row, OGRFeature *poFeature); 106 : OGRErr GetRow(EnumRows &enumRows, Row &row, GIntBig nFID); 107 : 108 : public: 109 : FGdbLayer(); 110 : virtual ~FGdbLayer(); 111 : 112 : // Internal used by FGDB driver */ 113 : bool Initialize(FGdbDataSource *pParentDataSource, Table *pTable, 114 : const std::wstring &wstrTablePath, 115 : const std::wstring &wstrType); 116 : 117 : // virtual const char *GetName(); 118 368 : virtual const char *GetFIDColumn() override 119 : { 120 368 : return m_strOIDFieldName.c_str(); 121 : } 122 : 123 : virtual void ResetReading() override; 124 : virtual OGRFeature *GetNextFeature() override; 125 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override; 126 : 127 : Table *GetTable() 128 : { 129 : return m_pTable; 130 : } 131 : 132 : std::wstring GetTablePath() const 133 : { 134 : return m_wstrTablePath; 135 : } 136 : 137 : std::wstring GetType() const 138 : { 139 : return m_wstrType; 140 : } 141 : 142 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent, 143 : bool bForce) override; 144 : 145 : virtual GIntBig GetFeatureCount(int bForce) override; 146 : virtual OGRErr SetAttributeFilter(const char *pszQuery) override; 147 : 148 : OGRErr ISetSpatialFilter(int iGeomField, 149 : const OGRGeometry *poGeom) override; 150 : 151 10718 : OGRFeatureDefn *GetLayerDefn() override 152 : { 153 10718 : return m_pFeatureDefn; 154 : } 155 : 156 : virtual int TestCapability(const char *) override; 157 : 158 : // Access the XML directly. The 2 following methods are not currently used 159 : // by the driver, but can be used by external code for specific purposes. 160 : OGRErr GetLayerXML(char **poXml); 161 : OGRErr GetLayerMetadataXML(char **poXmlMeta); 162 : 163 : virtual const char *GetMetadataItem(const char *pszName, 164 : const char *pszDomain) override; 165 : 166 : GDALDataset *GetDataset() override; 167 : 168 : protected: 169 : bool GDBToOGRFields(CPLXMLNode *psFields); 170 : bool ParseGeometryDef(const CPLXMLNode *psGeometryDef); 171 : 172 : static bool ParseSpatialReference(const CPLXMLNode *psSpatialRefNode, 173 : std::string *pOutWkt, 174 : std::string *pOutWKID, 175 : std::string *pOutLatestWKID); 176 : 177 : FGdbDataSource *m_pDS; 178 : Table *m_pTable; 179 : 180 : std::string 181 : m_strName; // contains underlying FGDB table name (not catalog name) 182 : 183 : std::string m_strOIDFieldName; 184 : std::string m_strShapeFieldName; 185 : 186 : std::wstring m_wstrTablePath; 187 : std::wstring m_wstrType; // the type: "Table" or "Feature Class" 188 : 189 : std::wstring m_wstrSubfields; 190 : std::wstring m_wstrWhereClause; 191 : 192 : bool m_bFilterDirty; // optimization to avoid multiple calls to search 193 : // until necessary 194 : 195 : bool m_bLaunderReservedKeywords; 196 : }; 197 : 198 : /************************************************************************/ 199 : /* FGdbResultLayer */ 200 : /************************************************************************/ 201 : 202 : class FGdbResultLayer final : public FGdbBaseLayer 203 : { 204 : public: 205 : FGdbResultLayer(FGdbDataSource *pParentDataSource, const char *pszStatement, 206 : EnumRows *pEnumRows); 207 : virtual ~FGdbResultLayer(); 208 : 209 : virtual void ResetReading() override; 210 : 211 0 : OGRFeatureDefn *GetLayerDefn() override 212 : { 213 0 : return m_pFeatureDefn; 214 : } 215 : 216 : virtual int TestCapability(const char *) override; 217 : 218 : protected: 219 : FGdbDataSource *m_pDS; 220 : CPLString osSQL; 221 : }; 222 : 223 : /************************************************************************/ 224 : /* FGdbDataSource */ 225 : /************************************************************************/ 226 : 227 : class FGdbDatabaseConnection; 228 : class OGRFileGDBGroup; 229 : 230 : class FGdbDataSource final : public GDALDataset 231 : { 232 : CPLString m_osFSName; 233 : CPLString m_osPublicName; 234 : std::set<OGRLayer *> m_oSetSelectLayers; 235 : std::shared_ptr<GDALGroup> m_poRootGroup{}; 236 : std::map<std::string, std::unique_ptr<GDALRelationship>> 237 : m_osMapRelationships{}; 238 : 239 : public: 240 : FGdbDataSource(bool bUseDriverMutex, FGdbDatabaseConnection *pConnection, 241 : bool bUseOpenFileGDB); 242 : virtual ~FGdbDataSource(); 243 : 244 : int Open(const char *pszFSName, int bUpdate, const char *pszPublicName); 245 : 246 130 : const char *GetFSName() 247 : { 248 130 : return m_osFSName.c_str(); 249 : } 250 : 251 4278 : int GetLayerCount() override 252 : { 253 4278 : return static_cast<int>(m_layers.size()); 254 : } 255 : 256 : OGRLayer *GetLayer(int) override; 257 : 258 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand, 259 : OGRGeometry *poSpatialFilter, 260 : const char *pszDialect) override; 261 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override; 262 : 263 : int TestCapability(const char *) override; 264 : 265 : const OGRFieldDomain * 266 : GetFieldDomain(const std::string &name) const override; 267 : std::vector<std::string> 268 : GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override; 269 : 270 : std::vector<std::string> 271 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override; 272 : 273 : const GDALRelationship * 274 : GetRelationship(const std::string &name) const override; 275 : 276 1 : std::shared_ptr<GDALGroup> GetRootGroup() const override 277 : { 278 1 : return m_poRootGroup; 279 : } 280 : 281 132 : Geodatabase *GetGDB() 282 : { 283 132 : return m_pGeodatabase; 284 : } 285 : 286 : FGdbDatabaseConnection *GetConnection() 287 : { 288 : return m_pConnection; 289 : } 290 : 291 : GDALDriver *GetOpenFileGDBDrv() 292 : { 293 : return m_poOpenFileGDBDrv; 294 : } 295 : 296 : int HasSelectLayers() 297 : { 298 : return !m_oSetSelectLayers.empty(); 299 : } 300 : 301 : int CloseInternal(int bCloseGeodatabase = FALSE); 302 : 303 132 : bool UseOpenFileGDB() const 304 : { 305 132 : return m_bUseOpenFileGDB; 306 : } 307 : 308 : /* 309 : protected: 310 : 311 : void EnumerateSpatialTables(); 312 : void OpenSpatialTable( const char* pszTableName ); 313 : */ 314 : protected: 315 : bool LoadLayers(const std::wstring &parent); 316 : bool OpenFGDBTables(OGRFileGDBGroup *group, const std::wstring &type, 317 : const std::vector<std::wstring> &layers); 318 : 319 : bool m_bUseDriverMutex = true; 320 : FGdbDatabaseConnection *m_pConnection; 321 : std::vector<OGRLayer *> m_layers; 322 : Geodatabase *m_pGeodatabase; 323 : GDALDriver *m_poOpenFileGDBDrv; 324 : std::unique_ptr<GDALDataset> m_poOpenFileGDBDS; 325 : bool m_bUseOpenFileGDB = false; 326 : }; 327 : 328 : /************************************************************************/ 329 : /* FGdbDriver */ 330 : /************************************************************************/ 331 : 332 : class FGdbDatabaseConnection 333 : { 334 : public: 335 32 : FGdbDatabaseConnection(const std::string &osName, Geodatabase *pGeodatabase) 336 32 : : m_osName(osName), m_pGeodatabase(pGeodatabase), m_nRefCount(1), 337 32 : m_bLocked(FALSE) 338 : { 339 32 : } 340 : 341 : std::string m_osName; 342 : Geodatabase *m_pGeodatabase; 343 : int m_nRefCount; 344 : int m_bLocked; 345 : 346 36 : Geodatabase *GetGDB() 347 : { 348 36 : return m_pGeodatabase; 349 : } 350 : 351 : void SetLocked(int bLockedIn) 352 : { 353 : m_bLocked = bLockedIn; 354 : } 355 : 356 : int GetRefCount() const 357 : { 358 : return m_nRefCount; 359 : } 360 : 361 : int IsLocked() const 362 : { 363 : return m_bLocked; 364 : } 365 : 366 : int OpenGeodatabase(const char *pszOverriddenName); 367 : void CloseGeodatabase(); 368 : }; 369 : 370 : class FGdbDriver final : public GDALDriver 371 : { 372 : public: 373 : static void Release(const char *pszName); 374 : 375 : static CPLMutex *hMutex; 376 : }; 377 : 378 : CPL_C_START 379 : void CPL_DLL RegisterOGRFileGDB(); 380 : CPL_C_END 381 : 382 : #endif /* ndef _OGR_PG_H_INCLUDED */