LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/filegdb - ogr_fgdb.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 46 57 80.7 %
Date: 2025-01-18 12:42:00 Functions: 21 25 84.0 %

          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 */

Generated by: LCOV version 1.14