LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/openfilegdb - filegdbtable.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 124 126 98.4 %
Date: 2025-07-01 22:47:05 Functions: 64 69 92.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements reading of FileGDB tables
       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 FILEGDBTABLE_H_INCLUDED
      14             : #define FILEGDBTABLE_H_INCLUDED
      15             : 
      16             : #include "ogr_core.h"
      17             : #include "cpl_progress.h"
      18             : #include "cpl_vsi.h"
      19             : #include "ogr_geometry.h"
      20             : 
      21             : #include <limits>
      22             : #include <string>
      23             : #include <vector>
      24             : 
      25             : namespace OpenFileGDB
      26             : {
      27             : constexpr uint64_t OFFSET_MINUS_ONE = static_cast<uint64_t>(-1);
      28             : constexpr int MAX_CAR_COUNT_INDEXED_STR = 80;
      29             : 
      30             : /************************************************************************/
      31             : /*                        FileGDBTableGeometryType                      */
      32             : /************************************************************************/
      33             : 
      34             : /* FGTGT = (F)ile(G)DB(T)able(G)eometry(T)ype */
      35             : typedef enum
      36             : {
      37             :     FGTGT_NONE = 0,
      38             :     FGTGT_POINT = 1,
      39             :     FGTGT_MULTIPOINT = 2,
      40             :     FGTGT_LINE = 3,
      41             :     FGTGT_POLYGON = 4,
      42             :     FGTGT_MULTIPATCH = 9
      43             : } FileGDBTableGeometryType;
      44             : 
      45             : /************************************************************************/
      46             : /*                          FileGDBFieldType                            */
      47             : /************************************************************************/
      48             : 
      49             : /* FGFT = (F)ile(G)DB(F)ield(T)ype */
      50             : typedef enum
      51             : {
      52             :     FGFT_UNDEFINED = -1,
      53             :     FGFT_INT16 = 0,
      54             :     FGFT_INT32 = 1,
      55             :     FGFT_FLOAT32 = 2,
      56             :     FGFT_FLOAT64 = 3,
      57             :     FGFT_STRING = 4,
      58             :     FGFT_DATETIME = 5,
      59             :     FGFT_OBJECTID = 6,
      60             :     FGFT_GEOMETRY = 7,
      61             :     FGFT_BINARY = 8,
      62             :     FGFT_RASTER = 9,
      63             :     FGFT_GUID = 10,
      64             :     FGFT_GLOBALID = 11,
      65             :     FGFT_XML = 12,
      66             :     FGFT_INT64 = 13,                 // added in ArcGIS Pro 3.2
      67             :     FGFT_DATE = 14,                  // added in ArcGIS Pro 3.2
      68             :     FGFT_TIME = 15,                  // added in ArcGIS Pro 3.2
      69             :     FGFT_DATETIME_WITH_OFFSET = 16,  // added in ArcGIS Pro 3.2
      70             : } FileGDBFieldType;
      71             : 
      72             : /************************************************************************/
      73             : /*                          FileGDBField                                */
      74             : /************************************************************************/
      75             : 
      76             : class FileGDBTable;
      77             : class FileGDBIndex;
      78             : 
      79             : class FileGDBField
      80             : {
      81             :     friend class FileGDBTable;
      82             : 
      83             :     FileGDBTable *m_poParent = nullptr;
      84             : 
      85             :     std::string m_osName{};
      86             :     std::string m_osAlias{};
      87             :     FileGDBFieldType m_eType = FGFT_UNDEFINED;
      88             : 
      89             :     bool m_bNullable = false;  // Bit 1 of flag field
      90             :     bool m_bRequired =
      91             :         false;  // Bit 2 of flag field. Set for ObjectID, geometry field and Shape_Area/Shape_Length
      92             :     bool m_bEditable = false;       // Bit 3 of flag field.
      93             :     bool m_bHighPrecision = false;  // for FGFT_DATETIME
      94             :     bool m_bReadAsDouble =
      95             :         false;           // used by FileGDBTable::CreateAttributeIndex()
      96             :     int m_nMaxWidth = 0; /* for string */
      97             : 
      98             :     OGRField m_sDefault{};
      99             : 
     100             :     FileGDBIndex *m_poIndex = nullptr;
     101             : 
     102             :     FileGDBField(const FileGDBField &) = delete;
     103             :     FileGDBField &operator=(const FileGDBField &) = delete;
     104             : 
     105             :   public:
     106             :     static const OGRField UNSET_FIELD;
     107             :     static constexpr int BIT_NULLABLE = 0;
     108             :     static constexpr int BIT_REQUIRED = 1;
     109             :     static constexpr int BIT_EDITABLE = 2;
     110             :     static constexpr int MASK_NULLABLE = 1 << BIT_NULLABLE;
     111             :     static constexpr int MASK_REQUIRED = 1 << BIT_REQUIRED;
     112             :     static constexpr int MASK_EDITABLE = 1 << BIT_EDITABLE;
     113             : 
     114             :     explicit FileGDBField(FileGDBTable *m_poParent);
     115             :     FileGDBField(const std::string &osName, const std::string &osAlias,
     116             :                  FileGDBFieldType eType, bool bNullable, bool bRequired,
     117             :                  bool bEditable, int nMaxWidth, const OGRField &sDefault);
     118             :     virtual ~FileGDBField();
     119             : 
     120       14461 :     void SetParent(FileGDBTable *poParent)
     121             :     {
     122       14461 :         m_poParent = poParent;
     123       14461 :     }
     124             : 
     125      305265 :     const std::string &GetName() const
     126             :     {
     127      305265 :         return m_osName;
     128             :     }
     129             : 
     130       23415 :     const std::string &GetAlias() const
     131             :     {
     132       23415 :         return m_osAlias;
     133             :     }
     134             : 
     135      377716 :     FileGDBFieldType GetType() const
     136             :     {
     137      377716 :         return m_eType;
     138             :     }
     139             : 
     140      152869 :     bool IsNullable() const
     141             :     {
     142      152869 :         return m_bNullable;
     143             :     }
     144             : 
     145       19230 :     bool IsRequired() const
     146             :     {
     147       19230 :         return m_bRequired;
     148             :     }
     149             : 
     150       19230 :     bool IsEditable() const
     151             :     {
     152       19230 :         return m_bEditable;
     153             :     }
     154             : 
     155        8988 :     int GetMaxWidth() const
     156             :     {
     157        8988 :         return m_nMaxWidth;
     158             :     }
     159             : 
     160       23657 :     const OGRField *GetDefault() const
     161             :     {
     162       23657 :         return &m_sDefault;
     163             :     }
     164             : 
     165           2 :     void SetHighPrecision()
     166             :     {
     167           2 :         m_bHighPrecision = true;
     168           2 :     }
     169             : 
     170       12006 :     bool IsHighPrecision() const
     171             :     {
     172       12006 :         return m_bHighPrecision;
     173             :     }
     174             : 
     175             :     int HasIndex();
     176             :     FileGDBIndex *GetIndex();
     177             : };
     178             : 
     179             : /************************************************************************/
     180             : /*                         FileGDBGeomField                             */
     181             : /************************************************************************/
     182             : 
     183        6341 : class FileGDBGeomField : public FileGDBField
     184             : {
     185             :     friend class FileGDBTable;
     186             : 
     187             :     static const double ESRI_NAN;
     188             : 
     189             :     std::string m_osWKT{};
     190             :     int m_bHasZOriginScaleTolerance = 0;
     191             :     int m_bHasMOriginScaleTolerance = 0;
     192             :     double m_dfXOrigin = 0;
     193             :     double m_dfYOrigin = 0;
     194             :     double m_dfXYScale = 0;
     195             :     double m_dfMOrigin = 0;
     196             :     double m_dfMScale = 0;
     197             :     double m_dfZOrigin = 0;
     198             :     double m_dfZScale = 0;
     199             :     double m_dfXYTolerance = 0;
     200             :     double m_dfMTolerance = 0;
     201             :     double m_dfZTolerance = 0;
     202             :     double m_dfXMin = ESRI_NAN;
     203             :     double m_dfYMin = ESRI_NAN;
     204             :     double m_dfZMin = ESRI_NAN;
     205             :     double m_dfMMin = ESRI_NAN;
     206             :     double m_dfXMax = ESRI_NAN;
     207             :     double m_dfYMax = ESRI_NAN;
     208             :     double m_dfZMax = ESRI_NAN;
     209             :     double m_dfMMax = ESRI_NAN;
     210             :     std::vector<double> m_adfSpatialIndexGridResolution{};
     211             : 
     212             :   public:
     213             :     explicit FileGDBGeomField(FileGDBTable *m_poParent);
     214             :     FileGDBGeomField(const std::string &osName, const std::string &osAlias,
     215             :                      bool bNullable, const std::string &osWKT, double dfXOrigin,
     216             :                      double dfYOrigin, double dfXYScale, double dfXYTolerance,
     217             :                      const std::vector<double> &adfSpatialIndexGridResolution);
     218             : 
     219             :     virtual ~FileGDBGeomField();
     220             : 
     221        2859 :     const std::string &GetWKT() const
     222             :     {
     223        2859 :         return m_osWKT;
     224             :     }
     225             : 
     226       13266 :     double GetXMin() const
     227             :     {
     228       13266 :         return m_dfXMin;
     229             :     }
     230             : 
     231        7022 :     double GetYMin() const
     232             :     {
     233        7022 :         return m_dfYMin;
     234             :     }
     235             : 
     236        4047 :     double GetZMin() const
     237             :     {
     238        4047 :         return m_dfZMin;
     239             :     }  // only valid for m_bGeomTypeHasZ
     240             : 
     241          25 :     double GetMMin() const
     242             :     {
     243          25 :         return m_dfMMin;
     244             :     }  // only valid for m_bGeomTypeHasM
     245             : 
     246        7022 :     double GetXMax() const
     247             :     {
     248        7022 :         return m_dfXMax;
     249             :     }
     250             : 
     251        7022 :     double GetYMax() const
     252             :     {
     253        7022 :         return m_dfYMax;
     254             :     }
     255             : 
     256        4041 :     double GetZMax() const
     257             :     {
     258        4041 :         return m_dfZMax;
     259             :     }  // only valid for m_bGeomTypeHasZ
     260             : 
     261          25 :     double GetMMax() const
     262             :     {
     263          25 :         return m_dfMMax;
     264             :     }  // only valid for m_bGeomTypeHasM
     265             : 
     266             :     void SetXYMinMax(double dfXMin, double dfYMin, double dfXMax,
     267             :                      double dfYMax);
     268             :     void SetZMinMax(double dfZMin, double dfZMax);
     269             :     void SetMMinMax(double dfMMin, double dfMMax);
     270             : 
     271        1806 :     int HasZOriginScaleTolerance() const
     272             :     {
     273        1806 :         return m_bHasZOriginScaleTolerance;
     274             :     }
     275             : 
     276        1806 :     int HasMOriginScaleTolerance() const
     277             :     {
     278        1806 :         return m_bHasMOriginScaleTolerance;
     279             :     }
     280             : 
     281       65762 :     double GetXOrigin() const
     282             :     {
     283       65762 :         return m_dfXOrigin;
     284             :     }
     285             : 
     286       65762 :     double GetYOrigin() const
     287             :     {
     288       65762 :         return m_dfYOrigin;
     289             :     }
     290             : 
     291      130307 :     double GetXYScale() const
     292             :     {
     293      130307 :         return m_dfXYScale;
     294             :     }
     295             : 
     296        1773 :     double GetXYTolerance() const
     297             :     {
     298        1773 :         return m_dfXYTolerance;
     299             :     }
     300             : 
     301       22634 :     double GetZOrigin() const
     302             :     {
     303       22634 :         return m_dfZOrigin;
     304             :     }
     305             : 
     306        5895 :     double GetZScale() const
     307             :     {
     308        5895 :         return m_dfZScale;
     309             :     }
     310             : 
     311        1773 :     double GetZTolerance() const
     312             :     {
     313        1773 :         return m_dfZTolerance;
     314             :     }
     315             : 
     316             :     void SetZOriginScaleTolerance(double dfZOrigin, double dfZScale,
     317             :                                   double dfZTolerance);
     318             : 
     319        2919 :     double GetMOrigin() const
     320             :     {
     321        2919 :         return m_dfMOrigin;
     322             :     }
     323             : 
     324        2209 :     double GetMScale() const
     325             :     {
     326        2209 :         return m_dfMScale;
     327             :     }
     328             : 
     329        1773 :     double GetMTolerance() const
     330             :     {
     331        1773 :         return m_dfMTolerance;
     332             :     }
     333             : 
     334             :     void SetMOriginScaleTolerance(double dfMOrigin, double dfMScale,
     335             :                                   double dfMTolerance);
     336             : 
     337        1209 :     const std::vector<double> &GetSpatialIndexGridResolution() const
     338             :     {
     339        1209 :         return m_adfSpatialIndexGridResolution;
     340             :     }
     341             : };
     342             : 
     343             : /************************************************************************/
     344             : /*                         FileGDBRasterField                           */
     345             : /************************************************************************/
     346             : 
     347           6 : class FileGDBRasterField : public FileGDBGeomField
     348             : {
     349             :   public:
     350             :     enum class Type
     351             :     {
     352             :         EXTERNAL,
     353             :         MANAGED,
     354             :         INLINE,
     355             :     };
     356             : 
     357             :   private:
     358             :     friend class FileGDBTable;
     359             : 
     360             :     std::string m_osRasterColumnName{};
     361             : 
     362             :     Type m_eRasterType = Type::EXTERNAL;
     363             : 
     364             :     FileGDBRasterField(const FileGDBRasterField &) = delete;
     365             :     FileGDBRasterField &operator=(const FileGDBRasterField &) = delete;
     366             : 
     367             :   public:
     368           3 :     explicit FileGDBRasterField(FileGDBTable *poParentIn)
     369           3 :         : FileGDBGeomField(poParentIn)
     370             :     {
     371           3 :     }
     372             : 
     373             :     virtual ~FileGDBRasterField();
     374             : 
     375             :     const std::string &GetRasterColumnName() const
     376             :     {
     377             :         return m_osRasterColumnName;
     378             :     }
     379             : 
     380           1 :     Type GetRasterType() const
     381             :     {
     382           1 :         return m_eRasterType;
     383             :     }
     384             : };
     385             : 
     386             : /************************************************************************/
     387             : /*                           FileGDBIndex                               */
     388             : /************************************************************************/
     389             : 
     390        1246 : class FileGDBIndex
     391             : {
     392             :     friend class FileGDBTable;
     393             :     std::string m_osIndexName{};
     394             :     std::string m_osExpression{};
     395             : 
     396             :   public:
     397        1246 :     FileGDBIndex() = default;
     398             : 
     399             :     ~FileGDBIndex();
     400             : 
     401        1503 :     const std::string &GetIndexName() const
     402             :     {
     403        1503 :         return m_osIndexName;
     404             :     }
     405             : 
     406        1181 :     const std::string &GetExpression() const
     407             :     {
     408        1181 :         return m_osExpression;
     409             :     }
     410             : 
     411             :     std::string GetFieldName() const;
     412             :     int GetMaxWidthInBytes(const FileGDBTable *poTable) const;
     413             : 
     414             :     static std::string
     415             :     GetFieldNameFromExpression(const std::string &osExpression);
     416             : };
     417             : 
     418             : /************************************************************************/
     419             : /*                           FileGDBTable                               */
     420             : /************************************************************************/
     421             : 
     422             : class FileGDBTable
     423             : {
     424             :     VSILFILE *m_fpTable = nullptr;
     425             :     VSILFILE *m_fpTableX = nullptr;
     426             : 
     427             :     enum class GDBTableVersion
     428             :     {
     429             :         V3 = 3,  // 32-bit object id
     430             :         V4 = 4,  // 64-bit object id (ince ArcGIS Pro 3.2)
     431             :     };
     432             :     GDBTableVersion m_eGDBTableVersion = GDBTableVersion::V3;
     433             :     vsi_l_offset m_nFileSize = 0; /* only read when needed */
     434             :     bool m_bUpdate = false;
     435             :     bool m_bReliableObjectID = true;  // can be set to false on some V4 files
     436             : 
     437             :     //! This flag is set when we detect that a corruption of m_nHeaderBufferMaxSize
     438             :     // prior to fix needs to  fdf39012788b1110b3bf0ae6b8422a528f0ae8b6 to be
     439             :     // repaired
     440             :     bool m_bHasWarnedAboutHeaderRepair = false;
     441             : 
     442             :     std::string m_osFilename{};
     443             :     std::string m_osFilenameWithLayerName{};
     444             :     bool m_bIsV9 = false;
     445             :     std::vector<std::unique_ptr<FileGDBField>> m_apoFields{};
     446             :     int m_iObjectIdField = -1;
     447             : 
     448             :     int m_bHasReadGDBIndexes = FALSE;
     449             :     std::vector<std::unique_ptr<FileGDBIndex>> m_apoIndexes{};
     450             : 
     451             :     int m_nHasSpatialIndex = -1;
     452             : 
     453             :     bool m_bDirtyHeader = false;
     454             :     bool m_bDirtyFieldDescriptors = false;
     455             :     bool m_bDirtyIndices = false;
     456             :     bool m_bDirtyGdbIndexesFile = false;
     457             : 
     458             :     uint32_t m_nHeaderBufferMaxSize = 0;
     459             :     GUIntBig m_nOffsetFieldDesc = 0;
     460             :     GUInt32 m_nFieldDescLength = 0;
     461             :     bool m_bDirtyGeomFieldBBox = false;
     462             :     bool m_bDirtyGeomFieldSpatialIndexGridRes = false;
     463             :     uint32_t m_nGeomFieldBBoxSubOffset =
     464             :         0;  // offset of geometry field bounding box
     465             :             // relative to m_nOffsetFieldDesc
     466             :     uint32_t m_nGeomFieldSpatialIndexGridResSubOffset =
     467             :         0;  // offset of geometry field spatial index grid resolution
     468             :             // relative to m_nOffsetFieldDesc
     469             : 
     470             :     GUInt32 m_nTablxOffsetSize =
     471             :         0;  // 4 (4 GB limit), 5 (1 TB limit), 6 (256 TB limit)
     472             :     std::vector<vsi_l_offset>
     473             :         m_anFeatureOffsets{}; /* MSb set marks deleted feature. Only used when
     474             :                                  no .gdbtablx file */
     475             : 
     476             :     uint64_t m_nOffsetTableXTrailer = 0;
     477             :     uint64_t m_n1024BlocksPresent = 0;
     478             :     std::vector<GByte> m_abyTablXBlockMap{};
     479             :     int m_nCountBlocksBeforeIBlockIdx = 0;   /* optimization */
     480             :     int m_nCountBlocksBeforeIBlockValue = 0; /* optimization */
     481             :     bool m_bDirtyTableXHeader = false;
     482             :     bool m_bDirtyTableXTrailer = false;
     483             : 
     484             :     int m_nHasFreeList = -1;
     485             :     bool m_bFreelistCanBeDeleted = false;
     486             : 
     487             :     char m_achGUIDBuffer[32 + 6 + 1]{0};
     488             :     int m_nChSaved = -1;
     489             : 
     490             :     int m_bError = FALSE;
     491             :     int64_t m_nCurRow = -1;
     492             :     int m_bHasDeletedFeaturesListed = FALSE;
     493             :     bool m_bIsDeleted = false;
     494             :     int m_nLastCol = -1;
     495             :     GByte *m_pabyIterVals = nullptr;
     496             :     int m_iAccNullable = 0;
     497             :     GUInt32 m_nRowBlobLength = 0;
     498             :     OGRField m_sCurField{};
     499             : 
     500             :     FileGDBTableGeometryType m_eTableGeomType = FGTGT_NONE;
     501             :     bool m_bGeomTypeHasZ = false;
     502             :     bool m_bGeomTypeHasM = false;
     503             :     bool m_bStringsAreUTF8 = true;  // if false, UTF16
     504             :     std::string m_osTempString{};   // used as a temporary to store strings
     505             :                                     // recoded from UTF16 to UTF8
     506             :     int64_t m_nValidRecordCount = 0;
     507             :     int64_t m_nTotalRecordCount = 0;
     508             :     int m_iGeomField = -1;
     509             :     int m_nCountNullableFields = 0;
     510             :     unsigned m_nNullableFieldsSizeInBytes = 0;
     511             : 
     512             :     std::vector<double> m_adfSpatialIndexGridResolution{};
     513             : 
     514             :     GUInt32 m_nRowBufferMaxSize = 0;
     515             :     std::vector<GByte> m_abyBuffer{};
     516             :     std::vector<GByte> m_abyGeomBuffer{};
     517             :     std::vector<GByte> m_abyCurvePart{};
     518             :     std::vector<uint32_t> m_anNumberPointsPerPart{};
     519             :     std::vector<double> m_adfX{};
     520             :     std::vector<double> m_adfY{};
     521             :     std::vector<double> m_adfZ{};
     522             :     std::vector<double> m_adfM{};
     523             : 
     524             :     std::string m_osCacheRasterFieldPath{};
     525             : 
     526             :     GUIntBig m_nFilterXMin = 0, m_nFilterXMax = 0, m_nFilterYMin = 0,
     527             :              m_nFilterYMax = 0;
     528             : 
     529             :     class WholeFileRewriter
     530             :     {
     531             :         FileGDBTable &m_oTable;
     532             :         bool m_bModifyInPlace = false;
     533             :         std::string m_osGdbTablx{};
     534             :         std::string m_osBackupValidFilename{};
     535             :         std::string m_osBackupGdbTable{};
     536             :         std::string m_osBackupGdbTablx{};
     537             :         std::string m_osTmpGdbTable{};
     538             :         std::string m_osTmpGdbTablx{};
     539             :         bool m_bOldDirtyIndices = false;
     540             :         uint64_t m_nOldFileSize = 0;
     541             :         uint64_t m_nOldOffsetFieldDesc = 0;
     542             :         uint32_t m_nOldFieldDescLength = 0;
     543             :         bool m_bIsInit = false;
     544             : 
     545             :         WholeFileRewriter(const WholeFileRewriter &) = delete;
     546             :         WholeFileRewriter &operator=(const WholeFileRewriter &) = delete;
     547             : 
     548             :       public:
     549             :         VSILFILE *m_fpOldGdbtable = nullptr;
     550             :         VSILFILE *m_fpOldGdbtablx = nullptr;
     551             :         VSILFILE *m_fpTable = nullptr;
     552             :         VSILFILE *m_fpTableX = nullptr;
     553             : 
     554          45 :         explicit WholeFileRewriter(FileGDBTable &oTable) : m_oTable(oTable)
     555             :         {
     556          45 :         }
     557             : 
     558             :         ~WholeFileRewriter();
     559             : 
     560             :         bool Begin();
     561             :         bool Commit();
     562             :         void Rollback();
     563             :     };
     564             : 
     565             :     bool WriteHeader(VSILFILE *fpTable);
     566             :     bool WriteHeaderX(VSILFILE *fpTableX);
     567             : 
     568             :     bool ReadTableXHeaderV3();
     569             :     bool ReadTableXHeaderV4();
     570             :     int IsLikelyFeatureAtOffset(vsi_l_offset nOffset, GUInt32 *pnSize,
     571             :                                 int *pbDeletedRecord);
     572             :     bool GuessFeatureLocations();
     573             :     bool WriteFieldDescriptors(VSILFILE *fpTable);
     574             :     bool SeekIntoTableXForNewFeature(int nObjectID);
     575             :     uint64_t ReadFeatureOffset(const GByte *pabyBuffer);
     576             :     void WriteFeatureOffset(uint64_t nFeatureOffset, GByte *pabyBuffer);
     577             :     bool WriteFeatureOffset(uint64_t nFeatureOffset);
     578             :     bool EncodeFeature(const std::vector<OGRField> &asRawFields,
     579             :                        const OGRGeometry *poGeom, int iSkipField);
     580             :     bool EncodeGeometry(const FileGDBGeomField *poGeomField,
     581             :                         const OGRGeometry *poGeom);
     582             :     bool RewriteTableToAddLastAddedField();
     583             :     void CreateGdbIndexesFile();
     584             :     void RemoveIndices();
     585             :     void RefreshIndices();
     586             :     bool CreateAttributeIndex(const FileGDBIndex *poIndex);
     587             :     uint64_t GetOffsetOfFreeAreaFromFreeList(uint32_t nSize);
     588             :     void AddEntryToFreelist(uint64_t nOffset, uint32_t nSize);
     589             : 
     590             :     FileGDBTable(const FileGDBTable &) = delete;
     591             :     FileGDBTable &operator=(const FileGDBTable &) = delete;
     592             : 
     593             :   public:
     594             :     FileGDBTable();
     595             :     ~FileGDBTable();
     596             : 
     597             :     bool Open(const char *pszFilename, bool bUpdate,
     598             :               const char *pszLayerName = nullptr);
     599             : 
     600             :     bool Create(const char *pszFilename, int nTablxOffsetSize,
     601             :                 FileGDBTableGeometryType eTableGeomType, bool bGeomTypeHasZ,
     602             :                 bool bGeomTypeHasM);
     603             :     bool SetTextUTF16();
     604             : 
     605             :     bool Sync(VSILFILE *fpTable = nullptr, VSILFILE *fpTableX = nullptr);
     606             :     bool Repack(GDALProgressFunc pfnProgress, void *pProgressData);
     607             :     void RecomputeExtent();
     608             : 
     609             :     //! Object should no longer be used after Close()
     610             :     void Close();
     611             : 
     612         194 :     bool IsFileGDBV9() const
     613             :     {
     614         194 :         return m_bIsV9;
     615             :     }
     616             : 
     617        1690 :     const std::string &GetFilename() const
     618             :     {
     619        1690 :         return m_osFilename;
     620             :     }
     621             : 
     622        5414 :     FileGDBTableGeometryType GetGeometryType() const
     623             :     {
     624        5414 :         return m_eTableGeomType;
     625             :     }
     626             : 
     627         127 :     bool GetGeomTypeHasZ() const
     628             :     {
     629         127 :         return m_bGeomTypeHasZ;
     630             :     }
     631             : 
     632         127 :     bool GetGeomTypeHasM() const
     633             :     {
     634         127 :         return m_bGeomTypeHasM;
     635             :     }
     636             : 
     637        4087 :     int64_t GetValidRecordCount() const
     638             :     {
     639        4087 :         return m_nValidRecordCount;
     640             :     }
     641             : 
     642     1606080 :     int64_t GetTotalRecordCount() const
     643             :     {
     644     1606080 :         return m_nTotalRecordCount;
     645             :     }
     646             : 
     647      240161 :     int GetFieldCount() const
     648             :     {
     649      240161 :         return static_cast<int>(m_apoFields.size());
     650             :     }
     651             : 
     652       56625 :     FileGDBField *GetField(int i) const
     653             :     {
     654       56625 :         return m_apoFields[i].get();
     655             :     }
     656             : 
     657        1107 :     int GetGeomFieldIdx() const
     658             :     {
     659        1107 :         return m_iGeomField;
     660             :     }
     661             : 
     662        2065 :     const FileGDBGeomField *GetGeomField() const
     663             :     {
     664        4129 :         return (m_iGeomField >= 0) ? cpl::down_cast<FileGDBGeomField *>(
     665        2064 :                                          m_apoFields[m_iGeomField].get())
     666        2065 :                                    : nullptr;
     667             :     }
     668             : 
     669      173487 :     int GetObjectIdFieldIdx() const
     670             :     {
     671      173487 :         return m_iObjectIdField;
     672             :     }
     673             : 
     674             :     int GetFieldIdx(const std::string &osName) const;
     675             : 
     676             :     int GetIndexCount();
     677             : 
     678             :     const FileGDBIndex *GetIndex(int i) const
     679             :     {
     680             :         return m_apoIndexes[i].get();
     681             :     }
     682             : 
     683             :     /** Return if we can use attribute or spatial indices.
     684             :      * This can be false for some sparse tables with 64-bit ObjectID since
     685             :      * the format of the sparse bitmap isn't fully understood yet.
     686             :      */
     687        1004 :     bool CanUseIndices() const
     688             :     {
     689        1004 :         return m_bReliableObjectID;
     690             :     }
     691             : 
     692             :     bool HasSpatialIndex();
     693             :     bool CreateIndex(const std::string &osIndexName,
     694             :                      const std::string &osExpression);
     695             :     void ComputeOptimalSpatialIndexGridResolution();
     696             :     bool CreateSpatialIndex();
     697             : 
     698             :     vsi_l_offset
     699             :     GetOffsetInTableForRow(int64_t iRow,
     700             :                            vsi_l_offset *pnOffsetInTableX = nullptr);
     701             : 
     702       28322 :     int HasDeletedFeaturesListed() const
     703             :     {
     704       28322 :         return m_bHasDeletedFeaturesListed;
     705             :     }
     706             : 
     707             :     /* Next call to SelectRow() or GetFieldValue() invalidates previously
     708             :      * returned values */
     709             :     bool SelectRow(int64_t iRow);
     710             :     int64_t GetAndSelectNextNonEmptyRow(int64_t iRow);
     711             : 
     712     1781160 :     int HasGotError() const
     713             :     {
     714     1781160 :         return m_bError;
     715             :     }
     716             : 
     717       38559 :     int64_t GetCurRow() const
     718             :     {
     719       38559 :         return m_nCurRow;
     720             :     }
     721             : 
     722           0 :     bool IsCurRowDeleted() const
     723             :     {
     724           0 :         return m_bIsDeleted;
     725             :     }
     726             : 
     727             :     const OGRField *GetFieldValue(int iCol);
     728             :     std::vector<OGRField> GetAllFieldValues();
     729             :     void FreeAllFieldValues(std::vector<OGRField> &asFields);
     730             : 
     731             :     int GetFeatureExtent(const OGRField *psGeomField,
     732             :                          OGREnvelope *psOutFeatureEnvelope);
     733             : 
     734       27589 :     const std::vector<double> &GetSpatialIndexGridResolution() const
     735             :     {
     736       27589 :         return m_adfSpatialIndexGridResolution;
     737             :     }
     738             : 
     739             :     void InstallFilterEnvelope(const OGREnvelope *psFilterEnvelope);
     740             :     int DoesGeometryIntersectsFilterEnvelope(const OGRField *psGeomField);
     741             : 
     742             :     void GetMinMaxProjYForSpatialIndex(double &dfYMin, double &dfYMax) const;
     743             : 
     744             :     bool CreateField(std::unique_ptr<FileGDBField> &&psField);
     745             :     bool DeleteField(int iField);
     746             :     bool AlterField(int iField, const std::string &osName,
     747             :                     const std::string &osAlias, FileGDBFieldType eType,
     748             :                     bool bNullable, int nMaxWidth, const OGRField &sDefault);
     749             :     bool AlterGeomField(const std::string &osName, const std::string &osAlias,
     750             :                         bool bNullable, const std::string &osWKT);
     751             : 
     752             :     bool CreateFeature(const std::vector<OGRField> &asRawFields,
     753             :                        const OGRGeometry *poGeom, int *pnFID = nullptr);
     754             :     bool UpdateFeature(int64_t nFID, const std::vector<OGRField> &asRawFields,
     755             :                        const OGRGeometry *poGeom);
     756             :     bool DeleteFeature(int64_t nFID);
     757             : 
     758             :     bool CheckFreeListConsistency();
     759             :     void DeleteFreeList();
     760             : };
     761             : 
     762             : /************************************************************************/
     763             : /*                           FileGDBSQLOp                               */
     764             : /************************************************************************/
     765             : 
     766             : typedef enum
     767             : {
     768             :     FGSO_ISNOTNULL,
     769             :     FGSO_LT,
     770             :     FGSO_LE,
     771             :     FGSO_EQ,
     772             :     FGSO_GE,
     773             :     FGSO_GT,
     774             :     FGSO_ILIKE
     775             : } FileGDBSQLOp;
     776             : 
     777             : /************************************************************************/
     778             : /*                           FileGDBIterator                            */
     779             : /************************************************************************/
     780             : 
     781             : class FileGDBIterator
     782             : {
     783             :   public:
     784         891 :     virtual ~FileGDBIterator()
     785         891 :     {
     786         891 :     }
     787             : 
     788             :     virtual FileGDBTable *GetTable() = 0;
     789             :     virtual void Reset() = 0;
     790             :     virtual int64_t GetNextRowSortedByFID() = 0;
     791             :     virtual int64_t GetRowCount();
     792             : 
     793             :     /* Only available on a BuildIsNotNull() iterator */
     794             :     virtual const OGRField *GetMinValue(int &eOutOGRFieldType);
     795             :     virtual const OGRField *GetMaxValue(int &eOutOGRFieldType);
     796             :     /* will reset the iterator */
     797             :     virtual bool GetMinMaxSumCount(double &dfMin, double &dfMax, double &dfSum,
     798             :                                    int &nCount);
     799             : 
     800             :     /* Only available on a BuildIsNotNull() or Build() iterator */
     801             :     virtual int64_t GetNextRowSortedByValue();
     802             : 
     803             :     static FileGDBIterator *Build(FileGDBTable *poParent, int nFieldIdx,
     804             :                                   int bAscending, FileGDBSQLOp op,
     805             :                                   OGRFieldType eOGRFieldType,
     806             :                                   const OGRField *psValue);
     807             :     static FileGDBIterator *BuildIsNotNull(FileGDBTable *poParent,
     808             :                                            int nFieldIdx, int bAscending);
     809             :     static FileGDBIterator *BuildNot(FileGDBIterator *poIterBase);
     810             :     static FileGDBIterator *BuildAnd(FileGDBIterator *poIter1,
     811             :                                      FileGDBIterator *poIter2,
     812             :                                      bool bTakeOwnershipOfIterators);
     813             :     static FileGDBIterator *BuildOr(FileGDBIterator *poIter1,
     814             :                                     FileGDBIterator *poIter2,
     815             :                                     int bIteratorAreExclusive = FALSE);
     816             : };
     817             : 
     818             : /************************************************************************/
     819             : /*                      FileGDBSpatialIndexIterator                     */
     820             : /************************************************************************/
     821             : 
     822         361 : class FileGDBSpatialIndexIterator : virtual public FileGDBIterator
     823             : {
     824             :   public:
     825             :     virtual bool SetEnvelope(const OGREnvelope &sFilterEnvelope) = 0;
     826             : 
     827             :     ~FileGDBSpatialIndexIterator() override;
     828             : 
     829             :     static FileGDBSpatialIndexIterator *
     830             :     Build(FileGDBTable *poParent, const OGREnvelope &sFilterEnvelope);
     831             : };
     832             : 
     833             : /************************************************************************/
     834             : /*                       FileGDBOGRGeometryConverter                    */
     835             : /************************************************************************/
     836             : 
     837         968 : class FileGDBOGRGeometryConverter
     838             : {
     839             :   public:
     840             :     virtual ~FileGDBOGRGeometryConverter();
     841             : 
     842             :     virtual OGRGeometry *GetAsGeometry(const OGRField *psField) = 0;
     843             : 
     844             :     static FileGDBOGRGeometryConverter *
     845             :     BuildConverter(const FileGDBGeomField *poGeomField);
     846             :     static OGRwkbGeometryType
     847             :     GetGeometryTypeFromESRI(const char *pszESRIGeometryType);
     848             : };
     849             : 
     850             : int FileGDBDoubleDateToOGRDate(double dfVal, bool bHighPrecision,
     851             :                                OGRField *psField);
     852             : int FileGDBDoubleTimeToOGRTime(double dfVal, OGRField *psField);
     853             : int FileGDBDateTimeWithOffsetToOGRDate(double dfVal, int16_t nUTCOffset,
     854             :                                        OGRField *psField);
     855             : 
     856             : } /* namespace OpenFileGDB */
     857             : 
     858             : #endif /* ndef FILEGDBTABLE_H_INCLUDED */

Generated by: LCOV version 1.14