LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/openfilegdb - ogr_openfilegdb.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 150 162 92.6 %
Date: 2025-07-01 22:47:05 Functions: 47 52 90.4 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements Open FileGDB OGR driver.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_OPENFILEGDB_H_INCLUDED
      14             : #define OGR_OPENFILEGDB_H_INCLUDED
      15             : 
      16             : #include "ogrsf_frmts.h"
      17             : #include "filegdbtable.h"
      18             : #include "ogr_swq.h"
      19             : #include "cpl_mem_cache.h"
      20             : #include "cpl_quad_tree.h"
      21             : 
      22             : #include "gdal_rat.h"
      23             : 
      24             : #include <array>
      25             : #include <vector>
      26             : #include <map>
      27             : 
      28             : using namespace OpenFileGDB;
      29             : 
      30             : std::string OFGDBGenerateUUID(bool bInit = false);
      31             : 
      32             : int OGROpenFileGDBIsComparisonOp(int op);
      33             : 
      34             : // The FileGeodatabase format does not really allow strings of arbitrary width
      35             : // in the XML and .gdbtable header declaration. They must have a non-zero
      36             : // maximum width. But if we put it to a huge value (let's say 1 billion), this
      37             : // causes crashes in some Esri products (cf #5952, perhaps they allocate
      38             : // std::string's to that maximum size?).
      39             : // Hence this default of a relative large but not too large
      40             : // width when creating a OGR string field width of unspecified width.
      41             : // Note that when opening a FileGeodatabase with string fields of that width,
      42             : // we do not advertise it in OGRFieldDefn::GetWidth() but we advertise 0 instead,
      43             : // to allow round-tripping.
      44             : constexpr int DEFAULT_STRING_WIDTH = 65536;
      45             : 
      46             : // UUID of object type
      47             : constexpr const char *pszFolderTypeUUID =
      48             :     "{f3783e6f-65ca-4514-8315-ce3985dad3b1}";
      49             : constexpr const char *pszWorkspaceTypeUUID =
      50             :     "{c673fe0f-7280-404f-8532-20755dd8fc06}";
      51             : constexpr const char *pszFeatureDatasetTypeUUID =
      52             :     "{74737149-DCB5-4257-8904-B9724E32A530}";
      53             : constexpr const char *pszFeatureClassTypeUUID =
      54             :     "{70737809-852c-4a03-9e22-2cecea5b9bfa}";
      55             : constexpr const char *pszTableTypeUUID =
      56             :     "{cd06bc3b-789d-4c51-aafa-a467912b8965}";
      57             : constexpr const char *pszRangeDomainTypeUUID =
      58             :     "{c29da988-8c3e-45f7-8b5c-18e51ee7beb4}";
      59             : constexpr const char *pszCodedDomainTypeUUID =
      60             :     "{8c368b12-a12e-4c7e-9638-c9c64e69e98f}";
      61             : constexpr const char *pszRelationshipTypeUUID =
      62             :     "{b606a7e1-fa5b-439c-849c-6e9c2481537b}";
      63             : 
      64             : // UUID of relationship type
      65             : constexpr const char *pszDatasetInFeatureDatasetUUID =
      66             :     "{a1633a59-46ba-4448-8706-d8abe2b2b02e}";
      67             : constexpr const char *pszDatasetInFolderUUID =
      68             :     "{dc78f1ab-34e4-43ac-ba47-1c4eabd0e7c7}";
      69             : constexpr const char *pszDomainInDatasetUUID =
      70             :     "{17e08adb-2b31-4dcd-8fdd-df529e88f843}";
      71             : constexpr const char *pszDatasetsRelatedThroughUUID =
      72             :     "{725badab-3452-491b-a795-55f32d67229c}";
      73             : 
      74             : /***********************************************************************/
      75             : /*                       FETCH_FIELD_IDX()                             */
      76             : /***********************************************************************/
      77             : 
      78             : #define FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, errorCode)            \
      79             :     const int idxName = oTable.GetFieldIdx(varName);                           \
      80             :     if (idxName < 0 || oTable.GetField(idxName)->GetType() != type)            \
      81             :     {                                                                          \
      82             :         CPLError(CE_Failure, CPLE_AppDefined,                                  \
      83             :                  "Could not find field %s in table %s", varName,               \
      84             :                  oTable.GetFilename().c_str());                                \
      85             :         return errorCode;                                                      \
      86             :     }
      87             : 
      88             : #define FETCH_FIELD_IDX(idxName, varName, type)                                \
      89             :     FETCH_FIELD_IDX_WITH_RET(idxName, varName, type, false)
      90             : 
      91             : /************************************************************************/
      92             : /*                      OGROpenFileGDBLayer                             */
      93             : /************************************************************************/
      94             : 
      95             : class OGROpenFileGDBDataSource;
      96             : class OGROpenFileGDBGeomFieldDefn;
      97             : class OGROpenFileGDBFeatureDefn;
      98             : 
      99             : typedef enum
     100             : {
     101             :     SPI_IN_BUILDING,
     102             :     SPI_COMPLETED,
     103             :     SPI_INVALID,
     104             : } SPIState;
     105             : 
     106             : class OGROpenFileGDBLayer final : public OGRLayer
     107             : {
     108             :     friend class OGROpenFileGDBGeomFieldDefn;
     109             :     friend class OGROpenFileGDBFeatureDefn;
     110             : 
     111             :     OGROpenFileGDBDataSource *m_poDS = nullptr;
     112             :     CPLString m_osGDBFilename{};
     113             :     CPLString m_osName{};
     114             :     std::string m_osPath{};
     115             :     std::string m_osThisGUID{};
     116             :     bool m_bEditable = false;
     117             :     bool m_bRegisteredTable = true;
     118             :     CPLStringList m_aosCreationOptions{};
     119             :     FileGDBTable *m_poLyrTable = nullptr;
     120             :     OGROpenFileGDBFeatureDefn *m_poFeatureDefn = nullptr;
     121             :     int m_iGeomFieldIdx = -1;
     122             :     int m_iAreaField = -1;    // index of Shape_Area field
     123             :     int m_iLengthField = -1;  // index of Shape_Length field
     124             :     int64_t m_iCurFeat = 0;
     125             :     int m_iFIDAsRegularColumnIndex = -1;
     126             :     std::string m_osDefinition{};
     127             :     std::string m_osDocumentation{};
     128             :     std::string m_osConfigurationKeyword{};
     129             :     OGRwkbGeometryType m_eGeomType = wkbNone;
     130             :     bool m_bArcGISPro32OrLater = false;
     131             :     int m_bValidLayerDefn = -1;
     132             :     int m_bEOF = false;
     133             :     bool m_bTimeInUTC = false;
     134             :     std::string m_osFeatureDatasetGUID{};
     135             : 
     136             :     bool m_bWarnedDateNotConvertibleUTC = false;
     137             : 
     138             :     bool m_bHasCreatedBackupForTransaction = false;
     139             :     std::unique_ptr<OGRFeatureDefn> m_poFeatureDefnBackup{};
     140             : 
     141             :     int BuildLayerDefinition();
     142             :     int BuildGeometryColumnGDBv10(const std::string &osParentDefinition);
     143             :     OGRFeature *GetCurrentFeature();
     144             : 
     145             :     std::unique_ptr<FileGDBOGRGeometryConverter> m_poGeomConverter{};
     146             : 
     147             :     int m_iFieldToReadAsBinary = -1;
     148             : 
     149             :     FileGDBIterator *m_poAttributeIterator = nullptr;
     150             :     int m_bIteratorSufficientToEvaluateFilter = FALSE;
     151             :     FileGDBIterator *BuildIteratorFromExprNode(swq_expr_node *poNode);
     152             : 
     153             :     FileGDBIterator *m_poIterMinMax = nullptr;
     154             : 
     155             :     FileGDBSpatialIndexIterator *m_poSpatialIndexIterator = nullptr;
     156             :     FileGDBIterator *m_poCombinedIterator = nullptr;
     157             : 
     158             :     // Legacy behavior prior to handling of .spx file
     159             :     // To remove ultimately.
     160             :     SPIState m_eSpatialIndexState = SPI_IN_BUILDING;
     161             :     CPLQuadTree *m_pQuadTree = nullptr;
     162             :     void **m_pahFilteredFeatures = nullptr;
     163             :     int m_nFilteredFeatureCount = -1;
     164             :     static void GetBoundsFuncEx(const void *hFeature, CPLRectObj *pBounds,
     165             :                                 void *pQTUserData);
     166             : 
     167             :     void TryToDetectMultiPatchKind();
     168             :     void BuildCombinedIterator();
     169             :     bool RegisterTable();
     170             :     void RefreshXMLDefinitionInMemory();
     171             :     bool CreateFeatureDataset(const char *pszFeatureDataset);
     172             :     std::string GetLaunderedFieldName(const std::string &osNameOri) const;
     173             :     std::string GetLaunderedLayerName(const std::string &osNameOri) const;
     174             : 
     175             :     mutable std::vector<std::string> m_aosTempStrings{};
     176             :     bool PrepareFileGDBFeature(OGRFeature *poFeature,
     177             :                                std::vector<OGRField> &fields,
     178             :                                const OGRGeometry *&poGeom, bool bUpdate);
     179             : 
     180             :     CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBLayer)
     181             : 
     182             :   public:
     183             :     OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
     184             :                         const char *pszGDBFilename, const char *pszName,
     185             :                         const std::string &osDefinition,
     186             :                         const std::string &osDocumentation, bool bEditable,
     187             :                         OGRwkbGeometryType eGeomType = wkbUnknown,
     188             :                         const std::string &osParentDefinition = std::string());
     189             : 
     190             :     OGROpenFileGDBLayer(OGROpenFileGDBDataSource *poDS,
     191             :                         const char *pszGDBFilename, const char *pszName,
     192             :                         OGRwkbGeometryType eType, CSLConstList papszOptions);
     193             : 
     194             :     virtual ~OGROpenFileGDBLayer();
     195             : 
     196             :     bool Create(const OGRGeomFieldDefn *poSrcGeomFieldDefn);
     197             :     void Close();
     198             : 
     199          35 :     const std::string &GetFilename() const
     200             :     {
     201          35 :         return m_osGDBFilename;
     202             :     }
     203             : 
     204          31 :     const std::string &GetXMLDefinition()
     205             :     {
     206          31 :         return m_osDefinition;
     207             :     }
     208             : 
     209          20 :     const std::string &GetXMLDocumentation()
     210             :     {
     211          20 :         return m_osDocumentation;
     212             :     }
     213             : 
     214         141 :     int GetAttrIndexUse()
     215             :     {
     216         257 :         return (m_poAttributeIterator == nullptr)        ? 0
     217         116 :                : (m_bIteratorSufficientToEvaluateFilter) ? 2
     218         141 :                                                          : 1;
     219             :     }
     220             : 
     221             :     const OGRField *GetMinMaxValue(OGRFieldDefn *poFieldDefn, int bIsMin,
     222             :                                    int &eOutType);
     223             :     int GetMinMaxSumCount(OGRFieldDefn *poFieldDefn, double &dfMin,
     224             :                           double &dfMax, double &dfSum, int &nCount);
     225             :     bool HasIndexForField(const char *pszFieldName);
     226             :     FileGDBIterator *BuildIndex(const char *pszFieldName, int bAscending,
     227             :                                 int op, swq_expr_node *poValue);
     228             : 
     229          12 :     SPIState GetSpatialIndexState() const
     230             :     {
     231          12 :         return m_eSpatialIndexState;
     232             :     }
     233             : 
     234           1 :     int IsValidLayerDefn()
     235             :     {
     236           1 :         return BuildLayerDefinition();
     237             :     }
     238             : 
     239             :     void CreateSpatialIndex();
     240             :     void CreateIndex(const std::string &osIdxName,
     241             :                      const std::string &osExpression);
     242             :     bool Repack(GDALProgressFunc pfnProgress, void *pProgressData);
     243             :     void RecomputeExtent();
     244             : 
     245             :     bool CheckFreeListConsistency();
     246             : 
     247             :     bool BeginEmulatedTransaction();
     248             :     bool CommitEmulatedTransaction();
     249             :     bool RollbackEmulatedTransaction();
     250             : 
     251             :     GDALDataset *GetDataset() override;
     252             : 
     253     1235300 :     virtual const char *GetName() override
     254             :     {
     255     1235300 :         return m_osName.c_str();
     256             :     }
     257             : 
     258             :     virtual OGRwkbGeometryType GetGeomType() override;
     259             : 
     260             :     virtual const char *GetFIDColumn() override;
     261             : 
     262             :     virtual void ResetReading() override;
     263             :     virtual OGRFeature *GetNextFeature() override;
     264             :     virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
     265             :     virtual OGRErr SetNextByIndex(GIntBig nIndex) override;
     266             : 
     267             :     virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
     268             :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     269             :                       bool bForce) override;
     270             : 
     271             :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
     272             :                         bool bForce) override;
     273             : 
     274             :     virtual OGRFeatureDefn *GetLayerDefn() override;
     275             : 
     276             :     virtual OGRErr ISetSpatialFilter(int iGeomField,
     277             :                                      const OGRGeometry *poGeom) override;
     278             : 
     279             :     virtual OGRErr SetAttributeFilter(const char *pszFilter) override;
     280             : 
     281             :     virtual int TestCapability(const char *) override;
     282             : 
     283             :     virtual OGRErr Rename(const char *pszNewName) override;
     284             : 
     285             :     virtual OGRErr CreateField(const OGRFieldDefn *poField,
     286             :                                int bApproxOK) override;
     287             :     virtual OGRErr DeleteField(int iFieldToDelete) override;
     288             :     virtual OGRErr AlterFieldDefn(int iFieldToAlter,
     289             :                                   OGRFieldDefn *poNewFieldDefn,
     290             :                                   int nFlags) override;
     291             :     virtual OGRErr
     292             :     AlterGeomFieldDefn(int iGeomFieldToAlter,
     293             :                        const OGRGeomFieldDefn *poNewGeomFieldDefn,
     294             :                        int nFlagsIn) override;
     295             : 
     296             :     virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
     297             :     virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
     298             :     virtual OGRErr DeleteFeature(GIntBig nFID) override;
     299             : 
     300             :     virtual OGRErr SyncToDisk() override;
     301             : };
     302             : 
     303             : /************************************************************************/
     304             : /*                      OGROpenFileGDBGeomFieldDefn                     */
     305             : /************************************************************************/
     306        6320 : class OGROpenFileGDBGeomFieldDefn : public OGRGeomFieldDefn
     307             : {
     308             :     OGROpenFileGDBLayer *m_poLayer;
     309             : 
     310             :     CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBGeomFieldDefn)
     311             : 
     312             :   public:
     313        3160 :     OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer *poLayer,
     314             :                                 const char *pszNameIn,
     315             :                                 OGRwkbGeometryType eGeomTypeIn)
     316        3160 :         : OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
     317             :     {
     318        3160 :     }
     319             : 
     320             :     ~OGROpenFileGDBGeomFieldDefn() override;
     321             : 
     322        3159 :     void UnsetLayer()
     323             :     {
     324        3159 :         m_poLayer = nullptr;
     325        3159 :     }
     326             : 
     327       11361 :     virtual const OGRSpatialReference *GetSpatialRef() const override
     328             :     {
     329       11361 :         if (poSRS)
     330        8378 :             return poSRS;
     331        2983 :         if (m_poLayer != nullptr)
     332         440 :             (void)m_poLayer->BuildLayerDefinition();
     333        2983 :         return poSRS;
     334             :     }
     335             : };
     336             : 
     337             : /************************************************************************/
     338             : /*                      OGROpenFileGDBFeatureDefn                       */
     339             : /************************************************************************/
     340       22338 : class OGROpenFileGDBFeatureDefn : public OGRFeatureDefn
     341             : {
     342             :     OGROpenFileGDBLayer *m_poLayer;
     343             :     mutable bool m_bHasBuiltFieldDefn;
     344             : 
     345      273849 :     void LazyGeomInit() const
     346             :     {
     347             :         /* FileGDB v9 case */
     348      160331 :         if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr &&
     349      535903 :             m_poLayer->m_eGeomType != wkbNone &&
     350      101723 :             m_poLayer->m_osDefinition.empty())
     351             :         {
     352         260 :             m_bHasBuiltFieldDefn = true;
     353         260 :             (void)m_poLayer->BuildLayerDefinition();
     354             :         }
     355      273849 :     }
     356             : 
     357             :     CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBFeatureDefn)
     358             : 
     359             :   public:
     360       11176 :     OGROpenFileGDBFeatureDefn(OGROpenFileGDBLayer *poLayer, const char *pszName,
     361             :                               bool bHasBuiltFieldDefn)
     362       11176 :         : OGRFeatureDefn(pszName), m_poLayer(poLayer),
     363       11176 :           m_bHasBuiltFieldDefn(bHasBuiltFieldDefn)
     364             :     {
     365       11176 :     }
     366             : 
     367             :     ~OGROpenFileGDBFeatureDefn() override;
     368             : 
     369       11169 :     void UnsetLayer()
     370             :     {
     371       11169 :         if (!apoGeomFieldDefn.empty())
     372             :             cpl::down_cast<OGROpenFileGDBGeomFieldDefn *>(
     373        3159 :                 apoGeomFieldDefn[0].get())
     374        3159 :                 ->UnsetLayer();
     375       11169 :         m_poLayer = nullptr;
     376       11169 :     }
     377             : 
     378      607761 :     virtual int GetFieldCount() const override
     379             :     {
     380      607761 :         if (!m_bHasBuiltFieldDefn && m_poLayer != nullptr)
     381             :         {
     382      225121 :             m_bHasBuiltFieldDefn = false;
     383      225121 :             (void)m_poLayer->BuildLayerDefinition();
     384             :         }
     385      607761 :         return OGRFeatureDefn::GetFieldCount();
     386             :     }
     387             : 
     388      229616 :     virtual int GetGeomFieldCount() const override
     389             :     {
     390      229616 :         LazyGeomInit();
     391      229616 :         return OGRFeatureDefn::GetGeomFieldCount();
     392             :     }
     393             : 
     394       43894 :     virtual OGRGeomFieldDefn *GetGeomFieldDefn(int i) override
     395             :     {
     396       43894 :         LazyGeomInit();
     397       43894 :         return OGRFeatureDefn::GetGeomFieldDefn(i);
     398             :     }
     399             : 
     400         339 :     virtual const OGRGeomFieldDefn *GetGeomFieldDefn(int i) const override
     401             :     {
     402         339 :         LazyGeomInit();
     403         339 :         return OGRFeatureDefn::GetGeomFieldDefn(i);
     404             :     }
     405             : };
     406             : 
     407             : /************************************************************************/
     408             : /*                       OGROpenFileGDBDataSource                       */
     409             : /************************************************************************/
     410             : 
     411             : class OGROpenFileGDBDataSource final : public GDALDataset
     412             : {
     413             :     friend class OGROpenFileGDBLayer;
     414             :     friend class GDALOpenFileGDBRasterBand;
     415             :     friend class GDALOpenFileGDBRasterAttributeTable;
     416             : 
     417             :     CPLString m_osDirName{};
     418             :     std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoLayers{};
     419             :     std::vector<std::unique_ptr<OGROpenFileGDBLayer>> m_apoHiddenLayers{};
     420             :     char **m_papszFiles = nullptr;
     421             :     std::map<std::string, int> m_osMapNameToIdx{};
     422             :     std::shared_ptr<GDALGroup> m_poRootGroup{};
     423             :     CPLStringList m_aosSubdatasets{};
     424             : 
     425             :     std::string m_osRasterLayerName{};
     426             :     std::map<int, int> m_oMapGDALBandToGDBBandId{};
     427             :     bool m_bHasGeoTransform = false;
     428             :     GDALGeoTransform m_gt{};
     429             :     int m_nShiftBlockX =
     430             :         0;  // Offset to add to FileGDB col_nbr field to convert from GDAL block numbering to FileGDB one
     431             :     int m_nShiftBlockY =
     432             :         0;  // Offset to add to FileGDB row_nbr field to convert from GDAL block numbering to FileGDB one
     433             :     OGRSpatialReference m_oRasterSRS{};
     434             :     std::unique_ptr<OGRLayer> m_poBlkLayer{};
     435             :     enum class Compression
     436             :     {
     437             :         NONE,
     438             :         LZ77,
     439             :         JPEG,
     440             :         JPEG2000,
     441             :     };
     442             :     Compression m_eRasterCompression = Compression::NONE;
     443             : 
     444             :     lru11::Cache<std::string, std::shared_ptr<OGRSpatialReference>>
     445             :         m_oCacheWKTToSRS{};
     446             : 
     447             :     std::string m_osRootGUID{};
     448             :     std::string m_osGDBSystemCatalogFilename{};
     449             :     std::string m_osGDBSpatialRefsFilename{};
     450             :     std::string m_osGDBItemsFilename{};
     451             :     std::string m_osGDBItemRelationshipsFilename{};
     452             :     std::map<std::string, std::unique_ptr<GDALRelationship>>
     453             :         m_osMapRelationships{};
     454             : 
     455             :     // Related to transactions
     456             :     bool m_bInTransaction = false;
     457             :     bool m_bSystemTablesBackedup = false;
     458             :     std::string m_osTransactionBackupDirname{};
     459             :     std::set<OGROpenFileGDBLayer *>
     460             :         m_oSetLayersCreatedInTransaction{};  // must be vector of raw pointer
     461             :     std::set<std::unique_ptr<OGROpenFileGDBLayer>>
     462             :         m_oSetLayersDeletedInTransaction{};
     463             : 
     464             :     /* For debugging/testing */
     465             :     bool bLastSQLUsedOptimizedImplementation;
     466             : 
     467             :     bool OpenFileGDBv10(int iGDBItems, int nInterestTable,
     468             :                         const GDALOpenInfo *poOpenInfo,
     469             :                         const std::string &osRasterLayerName,
     470             :                         std::set<int> &oSetIgnoredRasterLayerTableNum,
     471             :                         bool &bRetryFileGDBOut);
     472             :     int OpenFileGDBv9(int iGDBFeatureClasses, int iGDBObjectClasses,
     473             :                       int nInterestTable, const GDALOpenInfo *poOpenInfo,
     474             :                       const std::string &osRasterLayerName,
     475             :                       std::set<int> &oSetIgnoredRasterLayerTableNum);
     476             :     bool OpenRaster(const GDALOpenInfo *poOpenInfo,
     477             :                     const std::string &osLayerName,
     478             :                     const std::string &osDefinition,
     479             :                     const std::string &osDocumentation);
     480             :     void GuessJPEGQuality(int nOverviewCount);
     481             :     void ReadAuxTable(const std::string &osLayerName);
     482             : 
     483             :     int FileExists(const char *pszFilename);
     484             :     std::unique_ptr<OGROpenFileGDBLayer>
     485             :     BuildLayerFromName(const char *pszName);
     486             :     OGRLayer *AddLayer(const CPLString &osName, int nInterestTable,
     487             :                        int &nCandidateLayers, int &nLayersCDF,
     488             :                        const CPLString &osDefinition,
     489             :                        const CPLString &osDocumentation,
     490             :                        OGRwkbGeometryType eGeomType,
     491             :                        const std::string &osParentDefinition);
     492             : 
     493             :     static bool IsPrivateLayerName(const CPLString &osName);
     494             : 
     495             :     bool CreateGDBSystemCatalog();
     496             :     bool CreateGDBDBTune();
     497             :     bool CreateGDBSpatialRefs();
     498             :     bool CreateGDBItems();
     499             :     bool CreateGDBItemTypes();
     500             :     bool CreateGDBItemRelationships();
     501             :     bool CreateGDBItemRelationshipTypes();
     502             : 
     503             :     bool BackupSystemTablesForTransaction();
     504             : 
     505             :     CPLErr Close() override;
     506             : 
     507             :     CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBDataSource)
     508             : 
     509             :   public:
     510             :     OGROpenFileGDBDataSource();
     511             :     virtual ~OGROpenFileGDBDataSource();
     512             : 
     513             :     bool Open(const GDALOpenInfo *poOpenInfo, bool &bRetryFileGDBOut);
     514             :     bool Create(const char *pszName);
     515             : 
     516             :     virtual CPLErr FlushCache(bool bAtClosing = false) override;
     517             : 
     518           2 :     std::vector<std::unique_ptr<OGROpenFileGDBLayer>> &GetLayers()
     519             :     {
     520           2 :         return m_apoLayers;
     521             :     }
     522             : 
     523     1215830 :     virtual int GetLayerCount() override
     524             :     {
     525     1215830 :         return static_cast<int>(m_apoLayers.size());
     526             :     }
     527             : 
     528             :     virtual OGRLayer *GetLayer(int) override;
     529             :     virtual OGROpenFileGDBLayer *GetLayerByName(const char *pszName) override;
     530             :     bool IsLayerPrivate(int) const override;
     531             : 
     532             :     virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
     533             :                                  OGRGeometry *poSpatialFilter,
     534             :                                  const char *pszDialect) override;
     535             :     virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
     536             : 
     537             :     virtual int TestCapability(const char *) override;
     538             : 
     539             :     OGRLayer *ICreateLayer(const char *pszName,
     540             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     541             :                            CSLConstList papszOptions) override;
     542             : 
     543             :     virtual OGRErr DeleteLayer(int) override;
     544             : 
     545             :     virtual char **GetFileList() override;
     546             : 
     547           6 :     std::shared_ptr<GDALGroup> GetRootGroup() const override
     548             :     {
     549           6 :         return m_poRootGroup;
     550             :     }
     551             : 
     552             :     virtual OGRErr StartTransaction(int bForce) override;
     553             :     virtual OGRErr CommitTransaction() override;
     554             :     virtual OGRErr RollbackTransaction() override;
     555             : 
     556         500 :     const CPLStringList &GetSubdatasets() const
     557             :     {
     558         500 :         return m_aosSubdatasets;
     559             :     }
     560             : 
     561             :     CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
     562             :     const OGRSpatialReference *GetSpatialRef() const override;
     563             : 
     564             :     char **GetMetadata(const char *pszDomain = "") override;
     565             : 
     566             :     bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
     567             :                         std::string &failureReason) override;
     568             : 
     569             :     bool DeleteFieldDomain(const std::string &name,
     570             :                            std::string &failureReason) override;
     571             : 
     572             :     bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
     573             :                            std::string &failureReason) override;
     574             : 
     575             :     std::vector<std::string>
     576             :     GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
     577             : 
     578             :     const GDALRelationship *
     579             :     GetRelationship(const std::string &name) const override;
     580             : 
     581             :     bool AddRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     582             :                          std::string &failureReason) override;
     583             : 
     584             :     bool DeleteRelationship(const std::string &name,
     585             :                             std::string &failureReason) override;
     586             : 
     587             :     bool UpdateRelationship(std::unique_ptr<GDALRelationship> &&relationship,
     588             :                             std::string &failureReason) override;
     589             : 
     590             :     bool GetExistingSpatialRef(const std::string &osWKT, double dfXOrigin,
     591             :                                double dfYOrigin, double dfXYScale,
     592             :                                double dfZOrigin, double dfZScale,
     593             :                                double dfMOrigin, double dfMScale,
     594             :                                double dfXYTolerance, double dfZTolerance,
     595             :                                double dfMTolerance);
     596             : 
     597             :     bool AddNewSpatialRef(const std::string &osWKT, double dfXOrigin,
     598             :                           double dfYOrigin, double dfXYScale, double dfZOrigin,
     599             :                           double dfZScale, double dfMOrigin, double dfMScale,
     600             :                           double dfXYTolerance, double dfZTolerance,
     601             :                           double dfMTolerance);
     602             : 
     603             :     bool RegisterLayerInSystemCatalog(const std::string &osLayerName);
     604             : 
     605             :     bool RegisterInItemRelationships(const std::string &osOriginGUID,
     606             :                                      const std::string &osDestGUID,
     607             :                                      const std::string &osTypeGUID);
     608             : 
     609             :     bool RegisterRelationshipInItemRelationships(
     610             :         const std::string &osRelationshipGUID, const std::string &osOriginGUID,
     611             :         const std::string &osDestGUID);
     612             : 
     613             :     bool RemoveRelationshipFromItemRelationships(
     614             :         const std::string &osRelationshipGUID);
     615             : 
     616             :     bool RegisterFeatureDatasetInItems(const std::string &osFeatureDatasetGUID,
     617             :                                        const std::string &osName,
     618             :                                        const char *pszXMLDefinition);
     619             : 
     620             :     bool FindUUIDFromName(const std::string &osFeatureDatasetName,
     621             :                           std::string &osUUIDOut);
     622             : 
     623             :     bool RegisterFeatureClassInItems(const std::string &osLayerGUID,
     624             :                                      const std::string &osLayerName,
     625             :                                      const std::string &osPath,
     626             :                                      const FileGDBTable *poLyrTable,
     627             :                                      const char *pszXMLDefinition,
     628             :                                      const char *pszDocumentation);
     629             : 
     630             :     bool RegisterASpatialTableInItems(const std::string &osLayerGUID,
     631             :                                       const std::string &osLayerName,
     632             :                                       const std::string &osPath,
     633             :                                       const char *pszXMLDefinition,
     634             :                                       const char *pszDocumentation);
     635             : 
     636             :     bool LinkDomainToTable(const std::string &osDomainName,
     637             :                            const std::string &osLayerGUID);
     638             :     bool UnlinkDomainToTable(const std::string &osDomainName,
     639             :                              const std::string &osLayerGUID);
     640             : 
     641             :     bool UpdateXMLDefinition(const std::string &osLayerName,
     642             :                              const char *pszXMLDefinition);
     643             : 
     644       13073 :     bool IsInTransaction() const
     645             :     {
     646       13073 :         return m_bInTransaction;
     647             :     }
     648             : 
     649          40 :     const std::string &GetBackupDirName() const
     650             :     {
     651          40 :         return m_osTransactionBackupDirname;
     652             :     }
     653             : 
     654             :     OGRSpatialReference *BuildSRS(const CPLXMLNode *psInfo);
     655             :     OGRSpatialReference *BuildSRS(const char *pszWKT);
     656             : };
     657             : 
     658             : /************************************************************************/
     659             : /*                   OGROpenFileGDBSingleFeatureLayer                   */
     660             : /************************************************************************/
     661             : 
     662             : class OGROpenFileGDBSingleFeatureLayer final : public OGRLayer
     663             : {
     664             :   private:
     665             :     char *pszVal;
     666             :     OGRFeatureDefn *poFeatureDefn;
     667             :     int iNextShapeId;
     668             : 
     669             :     CPL_DISALLOW_COPY_ASSIGN(OGROpenFileGDBSingleFeatureLayer)
     670             : 
     671             :   public:
     672             :     OGROpenFileGDBSingleFeatureLayer(const char *pszLayerName,
     673             :                                      const char *pszVal);
     674             :     virtual ~OGROpenFileGDBSingleFeatureLayer();
     675             : 
     676           0 :     virtual void ResetReading() override
     677             :     {
     678           0 :         iNextShapeId = 0;
     679           0 :     }
     680             : 
     681             :     virtual OGRFeature *GetNextFeature() override;
     682             : 
     683           0 :     virtual OGRFeatureDefn *GetLayerDefn() override
     684             :     {
     685           0 :         return poFeatureDefn;
     686             :     }
     687             : 
     688           0 :     virtual int TestCapability(const char *) override
     689             :     {
     690           0 :         return FALSE;
     691             :     }
     692             : };
     693             : 
     694             : /************************************************************************/
     695             : /*                GDALOpenFileGDBRasterAttributeTable                   */
     696             : /************************************************************************/
     697             : 
     698             : class GDALOpenFileGDBRasterAttributeTable final
     699             :     : public GDALRasterAttributeTable
     700             : {
     701             :     std::unique_ptr<OGROpenFileGDBDataSource> m_poDS{};
     702             :     const std::string m_osVATTableName;
     703             :     std::unique_ptr<OGRLayer> m_poVATLayer{};
     704             :     mutable std::string m_osCachedValue{};
     705             : 
     706             :     GDALOpenFileGDBRasterAttributeTable(
     707             :         const GDALOpenFileGDBRasterAttributeTable &) = delete;
     708             :     GDALOpenFileGDBRasterAttributeTable &
     709             :     operator=(const GDALOpenFileGDBRasterAttributeTable &) = delete;
     710             : 
     711             :   public:
     712           2 :     GDALOpenFileGDBRasterAttributeTable(
     713             :         std::unique_ptr<OGROpenFileGDBDataSource> &&poDS,
     714             :         const std::string &osVATTableName,
     715             :         std::unique_ptr<OGRLayer> &&poVATLayer)
     716           4 :         : m_poDS(std::move(poDS)), m_osVATTableName(osVATTableName),
     717           2 :           m_poVATLayer(std::move(poVATLayer))
     718             :     {
     719           2 :     }
     720             : 
     721             :     GDALRasterAttributeTable *Clone() const override;
     722             : 
     723          15 :     int GetColumnCount() const override
     724             :     {
     725          15 :         return m_poVATLayer->GetLayerDefn()->GetFieldCount();
     726             :     }
     727             : 
     728           3 :     int GetRowCount() const override
     729             :     {
     730           3 :         return static_cast<int>(m_poVATLayer->GetFeatureCount());
     731             :     }
     732             : 
     733          10 :     const char *GetNameOfCol(int iCol) const override
     734             :     {
     735          10 :         if (iCol < 0 || iCol >= GetColumnCount())
     736           4 :             return nullptr;
     737           6 :         return m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetNameRef();
     738             :     }
     739             : 
     740           5 :     GDALRATFieldUsage GetUsageOfCol(int iCol) const override
     741             :     {
     742           5 :         const char *pszColName = GetNameOfCol(iCol);
     743           9 :         return pszColName && EQUAL(pszColName, "Value")   ? GFU_MinMax
     744           4 :                : pszColName && EQUAL(pszColName, "Count") ? GFU_PixelCount
     745           5 :                                                           : GFU_Generic;
     746             :     }
     747             : 
     748           3 :     int GetColOfUsage(GDALRATFieldUsage eUsage) const override
     749             :     {
     750           3 :         if (eUsage == GFU_MinMax)
     751           1 :             return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Value");
     752           2 :         if (eUsage == GFU_PixelCount)
     753           1 :             return m_poVATLayer->GetLayerDefn()->GetFieldIndex("Count");
     754           1 :         return -1;
     755             :     }
     756             : 
     757           5 :     GDALRATFieldType GetTypeOfCol(int iCol) const override
     758             :     {
     759           5 :         if (iCol < 0 || iCol >= GetColumnCount())
     760           2 :             return GFT_Integer;
     761           3 :         switch (m_poVATLayer->GetLayerDefn()->GetFieldDefn(iCol)->GetType())
     762             :         {
     763           1 :             case OFTInteger:
     764           1 :                 return GFT_Integer;
     765           1 :             case OFTReal:
     766           1 :                 return GFT_Real;
     767           1 :             default:
     768           1 :                 break;
     769             :         }
     770           1 :         return GFT_String;
     771             :     }
     772             : 
     773           7 :     const char *GetValueAsString(int iRow, int iField) const override
     774             :     {
     775             :         auto poFeat =
     776          14 :             std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
     777           7 :         if (!poFeat || iField >= poFeat->GetFieldCount())
     778           2 :             return "";
     779           5 :         m_osCachedValue = poFeat->GetFieldAsString(iField);
     780           5 :         return m_osCachedValue.c_str();
     781             :     }
     782             : 
     783           7 :     int GetValueAsInt(int iRow, int iField) const override
     784             :     {
     785             :         auto poFeat =
     786          14 :             std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
     787           7 :         if (!poFeat || iField >= poFeat->GetFieldCount())
     788           2 :             return 0;
     789           5 :         return poFeat->GetFieldAsInteger(iField);
     790             :     }
     791             : 
     792           7 :     double GetValueAsDouble(int iRow, int iField) const override
     793             :     {
     794             :         auto poFeat =
     795          14 :             std::unique_ptr<OGRFeature>(m_poVATLayer->GetFeature(iRow + 1));
     796           7 :         if (!poFeat || iField >= poFeat->GetFieldCount())
     797           2 :             return 0;
     798           5 :         return poFeat->GetFieldAsDouble(iField);
     799             :     }
     800             : 
     801           1 :     CPLErr SetValue(int, int, const char *) override
     802             :     {
     803           1 :         CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
     804           1 :         return CE_Failure;
     805             :     }
     806             : 
     807           1 :     CPLErr SetValue(int, int, int) override
     808             :     {
     809           1 :         CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
     810           1 :         return CE_Failure;
     811             :     }
     812             : 
     813           1 :     CPLErr SetValue(int, int, double) override
     814             :     {
     815           1 :         CPLError(CE_Failure, CPLE_NotSupported, "SetValue() not supported");
     816           1 :         return CE_Failure;
     817             :     }
     818             : 
     819           0 :     int ChangesAreWrittenToFile() override
     820             :     {
     821           0 :         return false;
     822             :     }
     823             : 
     824           1 :     CPLErr SetTableType(const GDALRATTableType) override
     825             :     {
     826           1 :         CPLError(CE_Failure, CPLE_NotSupported, "SetTableType() not supported");
     827           1 :         return CE_Failure;
     828             :     }
     829             : 
     830           1 :     GDALRATTableType GetTableType() const override
     831             :     {
     832           1 :         return GRTT_THEMATIC;
     833             :     }
     834             : 
     835           0 :     void RemoveStatistics() override
     836             :     {
     837           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     838             :                  "RemoveStatistics() not supported");
     839           0 :     }
     840             : };
     841             : 
     842             : /************************************************************************/
     843             : /*                       GDALOpenFileGDBRasterBand                      */
     844             : /************************************************************************/
     845             : 
     846             : class GDALOpenFileGDBRasterBand final : public GDALRasterBand
     847             : {
     848             :     friend class OGROpenFileGDBDataSource;
     849             :     std::vector<GByte> m_abyTmpBuffer{};
     850             :     int m_nBitWidth = 0;
     851             :     int m_nOverviewLevel = 0;
     852             :     std::vector<std::unique_ptr<GDALOpenFileGDBRasterBand>>
     853             :         m_apoOverviewBands{};
     854             :     bool m_bIsMask = false;
     855             :     std::unique_ptr<GDALOpenFileGDBRasterBand> m_poMaskBandOwned{};
     856             :     GDALOpenFileGDBRasterBand *m_poMainBand = nullptr;
     857             :     GDALOpenFileGDBRasterBand *m_poMaskBand = nullptr;
     858             :     bool m_bHasNoData = false;
     859             :     double m_dfNoData = 0.0;
     860             :     std::unique_ptr<GDALRasterAttributeTable> m_poRAT{};
     861             : 
     862             :     CPL_DISALLOW_COPY_ASSIGN(GDALOpenFileGDBRasterBand)
     863             : 
     864             :   public:
     865             :     GDALOpenFileGDBRasterBand(OGROpenFileGDBDataSource *poDSIn, int nBandIn,
     866             :                               GDALDataType eDT, int nBitWidth, int nBlockWidth,
     867             :                               int nBlockHeight, int nOverviewLevel,
     868             :                               bool bIsMask);
     869             : 
     870             :   protected:
     871             :     CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) override;
     872             : 
     873          12 :     int GetOverviewCount() override
     874             :     {
     875          12 :         return static_cast<int>(m_apoOverviewBands.size());
     876             :     }
     877             : 
     878          12 :     GDALRasterBand *GetOverview(int i) override
     879             :     {
     880          12 :         return (i >= 0 && i < GetOverviewCount()) ? m_apoOverviewBands[i].get()
     881          12 :                                                   : nullptr;
     882             :     }
     883             : 
     884          15 :     GDALRasterBand *GetMaskBand() override
     885             :     {
     886          15 :         return m_poMaskBand ? m_poMaskBand : GDALRasterBand::GetMaskBand();
     887             :     }
     888             : 
     889           6 :     int GetMaskFlags() override
     890             :     {
     891           6 :         return m_poMaskBand ? GMF_PER_DATASET : GDALRasterBand::GetMaskFlags();
     892             :     }
     893             : 
     894           7 :     double GetNoDataValue(int *pbHasNoData) override
     895             :     {
     896           7 :         if (pbHasNoData)
     897           6 :             *pbHasNoData = m_bHasNoData;
     898           7 :         return m_dfNoData;
     899             :     }
     900             : 
     901             :     GDALRasterAttributeTable *GetDefaultRAT() override;
     902             : };
     903             : 
     904             : #endif /* ndef OGR_OPENFILEGDB_H_INCLUDED */

Generated by: LCOV version 1.14