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: 165 181 91.2 %
Date: 2024-05-02 22:57:13 Functions: 49 55 89.1 %

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

Generated by: LCOV version 1.14