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