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: 2024-11-21 22:18:42 Functions: 64 67 95.5 %

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

Generated by: LCOV version 1.14