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: 153 201 76.1 %
Date: 2025-11-04 19:10:06 Functions: 47 58 81.0 %

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

Generated by: LCOV version 1.14