LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/openfilegdb - filegdbtable.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 133 135 98.5 %
Date: 2025-01-18 12:42:00 Functions: 64 67 95.5 %

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

Generated by: LCOV version 1.14