Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL TileDB Driver
4 : * Purpose: Include tiledb headers
5 : * Author: TileDB, Inc
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2019, TileDB, Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef TILEDB_HEADERS_H
14 : #define TILEDB_HEADERS_H
15 :
16 : #include <algorithm>
17 : #include <list>
18 : #include <variant>
19 :
20 : #include "cpl_port.h"
21 : #include "cpl_string.h"
22 : #include "gdal_frmts.h"
23 : #include "gdal_pam.h"
24 : #include "ogrsf_frmts.h"
25 :
26 : #include "include_tiledb.h"
27 :
28 : #if TILEDB_VERSION_MAJOR > 2 || \
29 : (TILEDB_VERSION_MAJOR == 2 && TILEDB_VERSION_MINOR >= 17)
30 : struct gdal_tiledb_vector_of_bool
31 : {
32 : size_t m_size = 0;
33 : size_t m_capacity = 0;
34 : bool *m_v = nullptr;
35 :
36 : gdal_tiledb_vector_of_bool() = default;
37 :
38 : ~gdal_tiledb_vector_of_bool()
39 : {
40 : std::free(m_v);
41 : }
42 :
43 : gdal_tiledb_vector_of_bool(gdal_tiledb_vector_of_bool &&other)
44 : : m_size(other.m_size), m_capacity(other.m_capacity),
45 : m_v(std::move(other.m_v))
46 : {
47 : other.m_size = 0;
48 : other.m_capacity = 0;
49 : other.m_v = nullptr;
50 : }
51 :
52 : gdal_tiledb_vector_of_bool(const gdal_tiledb_vector_of_bool &) = delete;
53 : gdal_tiledb_vector_of_bool &
54 : operator=(const gdal_tiledb_vector_of_bool &) = delete;
55 : gdal_tiledb_vector_of_bool &
56 : operator=(gdal_tiledb_vector_of_bool &&) = delete;
57 :
58 : size_t size() const
59 : {
60 : return m_size;
61 : }
62 :
63 : const bool *data() const
64 : {
65 : return m_v;
66 : }
67 :
68 : bool *data()
69 : {
70 : return m_v;
71 : }
72 :
73 : bool &operator[](size_t idx)
74 : {
75 : return m_v[idx];
76 : }
77 :
78 : bool operator[](size_t idx) const
79 : {
80 : return m_v[idx];
81 : }
82 :
83 : void resize(size_t new_size)
84 : {
85 : if (new_size > m_capacity)
86 : {
87 : const size_t new_capacity =
88 : std::max<size_t>(new_size, 2 * m_capacity);
89 : bool *new_v = static_cast<bool *>(
90 : std::realloc(m_v, new_capacity * sizeof(bool)));
91 : if (!new_v)
92 : {
93 : throw std::bad_alloc();
94 : }
95 : m_v = new_v;
96 : m_capacity = new_capacity;
97 : }
98 : if (new_size > m_size)
99 : memset(m_v + m_size, 0, (new_size - m_size) * sizeof(bool));
100 : m_size = new_size;
101 : }
102 :
103 : void clear()
104 : {
105 : resize(0);
106 : }
107 :
108 : size_t capacity() const
109 : {
110 : return m_capacity;
111 : }
112 :
113 : void push_back(uint8_t v)
114 : {
115 : resize(size() + 1);
116 : m_v[size() - 1] = static_cast<bool>(v);
117 : }
118 : };
119 :
120 : #define VECTOR_OF_BOOL gdal_tiledb_vector_of_bool
121 : #define VECTOR_OF_BOOL_IS_NOT_UINT8_T
122 : #else
123 : #define VECTOR_OF_BOOL std::vector<uint8_t>
124 : #endif
125 :
126 : typedef enum
127 : {
128 : BAND = 0,
129 : PIXEL = 1,
130 : ATTRIBUTES = 2
131 : } TILEDB_INTERLEAVE_MODE;
132 :
133 : #define DEFAULT_TILE_CAPACITY 10000
134 :
135 : #define DEFAULT_BATCH_SIZE 500000
136 :
137 : constexpr const char *TILEDB_VALUES = "TDB_VALUES";
138 :
139 : constexpr const char *GDAL_ATTRIBUTE_NAME = "_gdal";
140 :
141 : constexpr const char *DATASET_TYPE_ATTRIBUTE_NAME = "dataset_type";
142 : // Potential values for dataset_type metadata:
143 : constexpr const char *RASTER_DATASET_TYPE = "raster";
144 : constexpr const char *GEOMETRY_DATASET_TYPE = "geometry";
145 :
146 : /************************************************************************/
147 : /* ==================================================================== */
148 : /* TileRasterBand */
149 : /* ==================================================================== */
150 : /************************************************************************/
151 :
152 : class TileDBRasterBand;
153 :
154 : /************************************************************************/
155 : /* ==================================================================== */
156 : /* TileDBDataset */
157 : /* ==================================================================== */
158 : /************************************************************************/
159 :
160 337 : class TileDBDataset /* non final */ : public GDALPamDataset
161 : {
162 : protected:
163 : std::unique_ptr<tiledb::Context> m_ctx{};
164 :
165 : public:
166 : ~TileDBDataset() override;
167 :
168 : static CPLErr AddFilter(tiledb::Context &ctx,
169 : tiledb::FilterList &filterList,
170 : const char *pszFilterName, const int level);
171 : static int Identify(GDALOpenInfo *);
172 : static CPLErr Delete(const char *pszFilename);
173 : static CPLString VSI_to_tiledb_uri(const char *pszUri);
174 : static bool TileDBObjectExists(tiledb::Context &ctx,
175 : const std::string &osArrayUri);
176 :
177 : static GDALDataset *Open(GDALOpenInfo *);
178 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
179 : int nBands, GDALDataType eType,
180 : CSLConstList papszOptions);
181 : static GDALDataset *CreateCopy(const char *pszFilename,
182 : GDALDataset *poSrcDS, int bStrict,
183 : CSLConstList papszOptions,
184 : GDALProgressFunc pfnProgress,
185 : void *pProgressData);
186 :
187 : static GDALDataset *OpenMultiDimensional(GDALOpenInfo *);
188 : static GDALDataset *
189 : CreateMultiDimensional(const char *pszFilename,
190 : CSLConstList papszRootGroupOptions,
191 : CSLConstList papszOptions);
192 : };
193 :
194 : /************************************************************************/
195 : /* ==================================================================== */
196 : /* TileDRasterDataset */
197 : /* ==================================================================== */
198 : /************************************************************************/
199 :
200 : class TileDBRasterDataset final : public TileDBDataset
201 : {
202 : friend class TileDBRasterBand;
203 :
204 : protected:
205 : std::string m_osConfigFilename{};
206 : std::unique_ptr<tiledb::Context> m_roCtx{};
207 : std::unique_ptr<tiledb::Array> m_array{};
208 : std::unique_ptr<tiledb::Array> m_roArray{};
209 : std::unique_ptr<tiledb::ArraySchema> m_schema{};
210 : std::unique_ptr<tiledb::FilterList> m_filterList{};
211 : bool m_bDatasetInGroup = false;
212 : std::string m_osArrayURI{};
213 : CPLString osMetaDoc{};
214 : TILEDB_INTERLEAVE_MODE eIndexMode = BAND;
215 : int nBitsPerSample = 8;
216 : GDALDataType eDataType = GDT_Unknown;
217 : int nBlockXSize = -1;
218 : int nBlockYSize = -1;
219 : int nBlocksX = 0;
220 : int nBlocksY = 0;
221 : uint64_t nBandStart = 1;
222 : bool m_bHasSubDatasets = false;
223 : CPLStringList m_aosSubdatasetMD{};
224 : CPLXMLTreeCloser m_poSubDatasetsTree{nullptr};
225 : std::list<std::unique_ptr<GDALDataset>> m_lpoAttributeDS = {};
226 : uint64_t nTimestamp = 0;
227 : bool bStats = FALSE;
228 : bool m_bDeferredCreateHasRun = false;
229 : bool m_bDeferredCreateHasBeenSuccessful = false;
230 :
231 : //! Number of overviews declared in _gdal metadata. In theory, it should
232 : // match m_apoOverviewDS.size(), but do not strongly rely on that.
233 : int m_nOverviewCountFromMetadata = 0;
234 :
235 : //! Overview datasets
236 : std::vector<std::unique_ptr<GDALDataset>> m_apoOverviewDS{};
237 :
238 : //! Overview datasets that have been removed per IBuildOverviews(nOverview==0)
239 : std::vector<std::unique_ptr<GDALDataset>> m_apoOverviewDSRemoved{};
240 :
241 : //! Whether LoadOverviews() has already been called.
242 : bool m_bLoadOverviewsDone = false;
243 :
244 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
245 : GDALDataType, int, BANDMAP_TYPE, GSpacing, GSpacing,
246 : GSpacing, GDALRasterIOExtraArg *psExtraArg) override;
247 : CPLErr CreateAttribute(GDALDataType eType, const CPLString &osAttrName,
248 : const int nSubRasterCount, bool bHasFillValue,
249 : double dfFillValue);
250 :
251 : CPLErr AddDimensions(tiledb::Domain &domain, const char *pszAttrName,
252 : tiledb::Dimension &y, tiledb::Dimension &x,
253 : tiledb::Dimension *poBands = nullptr);
254 :
255 : void CreateArray();
256 : bool DeferredCreate(bool bCreateArray);
257 :
258 : tiledb::Array &GetArray(bool bForWrite, tiledb::Context *&ctx);
259 :
260 : static GDALDataset *OpenInternal(GDALOpenInfo *,
261 : tiledb::Object::Type objectType);
262 :
263 : //! Load TileDB overviews from TileDB arrays
264 : void LoadOverviews();
265 :
266 : public:
267 : ~TileDBRasterDataset() override;
268 : CPLErr TryLoadCachedXML(CSLConstList papszSiblingFiles = nullptr,
269 : bool bReload = true);
270 : CPLErr TryLoadXML(CSLConstList papszSiblingFiles = nullptr) override;
271 : CPLErr TrySaveXML() override;
272 : CSLConstList GetMetadata(const char *pszDomain) override;
273 : CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
274 : int CloseDependentDatasets() override;
275 : CPLErr FlushCache(bool bAtClosing) override;
276 :
277 : CPLErr IBuildOverviews(const char *pszResampling, int nOverviews,
278 : const int *panOverviewList, int nListBands,
279 : const int *panBandList, GDALProgressFunc pfnProgress,
280 : void *pProgressData,
281 : CSLConstList papszOptions) override;
282 :
283 : static CPLErr CopySubDatasets(GDALDataset *poSrcDS,
284 : TileDBRasterDataset *poDstDS,
285 : GDALProgressFunc pfnProgress,
286 : void *pProgressData);
287 : static TileDBRasterDataset *CreateLL(const char *pszFilename, int nXSize,
288 : int nYSize, int nBands,
289 : GDALDataType eType,
290 : CSLConstList papszOptions);
291 : static void SetBlockSize(GDALRasterBand *poBand, CPLStringList &aosOptions);
292 :
293 : static GDALDataset *Open(GDALOpenInfo *, tiledb::Object::Type objectType);
294 : static TileDBRasterDataset *Create(const char *pszFilename, int nXSize,
295 : int nYSize, int nBands,
296 : GDALDataType eType,
297 : CSLConstList papszOptions);
298 : static GDALDataset *CreateCopy(const char *pszFilename,
299 : GDALDataset *poSrcDS, int bStrict,
300 : CSLConstList papszOptions,
301 : GDALProgressFunc pfnProgress,
302 : void *pProgressData);
303 : };
304 :
305 : /************************************************************************/
306 : /* OGRTileDBLayer */
307 : /************************************************************************/
308 :
309 : class OGRTileDBDataset;
310 :
311 : class OGRTileDBLayer final : public OGRLayer,
312 : public OGRGetNextFeatureThroughRaw<OGRTileDBLayer>
313 : {
314 : public:
315 : typedef std::variant<std::shared_ptr<std::string>,
316 : #ifdef VECTOR_OF_BOOL_IS_NOT_UINT8_T
317 : std::shared_ptr<VECTOR_OF_BOOL>,
318 : #endif
319 : std::shared_ptr<std::vector<uint8_t>>,
320 : std::shared_ptr<std::vector<int16_t>>,
321 : std::shared_ptr<std::vector<uint16_t>>,
322 : std::shared_ptr<std::vector<int32_t>>,
323 : std::shared_ptr<std::vector<int64_t>>,
324 : std::shared_ptr<std::vector<float>>,
325 : std::shared_ptr<std::vector<double>>>
326 : ArrayType;
327 :
328 : private:
329 : friend OGRTileDBDataset;
330 : GDALDataset *m_poDS = nullptr;
331 : std::string m_osGroupName{};
332 : std::string m_osFilename{};
333 : uint64_t m_nTimestamp = 0;
334 : bool m_bUpdatable = false;
335 : enum class CurrentMode
336 : {
337 : None,
338 : ReadInProgress,
339 : WriteInProgress
340 : };
341 : CurrentMode m_eCurrentMode = CurrentMode::None;
342 : std::unique_ptr<tiledb::Context> m_ctx{};
343 : std::unique_ptr<tiledb::Array> m_array{};
344 : std::unique_ptr<tiledb::ArraySchema> m_schema{};
345 : std::unique_ptr<tiledb::Query> m_query{};
346 : std::unique_ptr<tiledb::FilterList> m_filterList{};
347 : bool m_bAttributeFilterPartiallyTranslated =
348 : false; // for debugging purposes
349 : bool m_bAttributeFilterAlwaysFalse = false;
350 : bool m_bAttributeFilterAlwaysTrue = false;
351 : std::unique_ptr<tiledb::QueryCondition> m_poQueryCondition{};
352 : bool m_bInitializationAttempted = false;
353 : bool m_bInitialized = false;
354 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
355 : std::string m_osFIDColumn{};
356 : GIntBig m_nNextFID = 1;
357 : int64_t m_nTotalFeatureCount = -1;
358 : bool m_bStats = false;
359 : bool m_bQueryComplete = false;
360 : bool m_bGrowBuffers = false;
361 : uint64_t m_nOffsetInResultSet = 0;
362 : uint64_t m_nRowCountInResultSet = 0;
363 : int m_nUseOptimizedAttributeFilter = -1; // uninitialized
364 :
365 : tiledb_datatype_t m_eTileDBStringType = TILEDB_STRING_UTF8;
366 :
367 : std::string m_osXDim = "_X";
368 : std::string m_osYDim = "_Y";
369 : std::string m_osZDim{}; // may be empty
370 :
371 : // Domain extent
372 : double m_dfXStart = 0;
373 : double m_dfYStart = 0;
374 : double m_dfZStart = -10000;
375 : double m_dfXEnd = 0;
376 : double m_dfYEnd = 0;
377 : double m_dfZEnd = 10000;
378 :
379 : // Extent of all features
380 : OGREnvelope m_oLayerExtent{};
381 :
382 : // Boolean shared between the OGRTileDBLayer instance and the
383 : // OGRTileDBArrowArrayPrivateData instances, that are stored in
384 : // ArrowArray::private_data, so ReleaseArrowArray() function knows
385 : // if the OGRLayer is still alive.
386 : std::shared_ptr<bool> m_pbLayerStillAlive{};
387 :
388 : // Flag set to false by GetNextArrowArray() to indicate that the m_anFIDs,
389 : // m_adfXs, m_adfYs, m_adfZs, m_aFieldValues, m_aFieldValueOffsets,
390 : // m_abyGeometries and m_anGeometryOffsets are currently used by a
391 : // ArrowArray returned. If this flag is still set to false when the
392 : // next SetupQuery() is called, we need to re-instanciate new arrays, so
393 : // the ArrowArray's can be used independently of the new state of the layer.
394 : bool m_bArrowBatchReleased = true;
395 :
396 : std::shared_ptr<std::vector<int64_t>> m_anFIDs{};
397 : std::shared_ptr<std::vector<double>> m_adfXs{};
398 : std::shared_ptr<std::vector<double>> m_adfYs{};
399 : std::shared_ptr<std::vector<double>> m_adfZs{};
400 : std::vector<tiledb_datatype_t> m_aeFieldTypes{};
401 : std::vector<int> m_aeFieldTypesInCreateField{};
402 : std::vector<size_t> m_anFieldValuesCapacity{};
403 : std::vector<ArrayType> m_aFieldValues{};
404 : std::vector<std::shared_ptr<std::vector<uint64_t>>> m_aFieldValueOffsets{};
405 : std::vector<std::vector<uint8_t>> m_aFieldValidity{};
406 : size_t m_nGeometriesCapacity = 0;
407 : std::shared_ptr<std::vector<unsigned char>> m_abyGeometries{};
408 : std::shared_ptr<std::vector<uint64_t>> m_anGeometryOffsets{};
409 :
410 : struct OGRTileDBArrowArrayPrivateData
411 : {
412 : OGRTileDBLayer *m_poLayer = nullptr;
413 : std::shared_ptr<bool> m_pbLayerStillAlive{};
414 :
415 : ArrayType valueHolder{};
416 : std::shared_ptr<std::vector<uint8_t>> nullHolder{};
417 : std::shared_ptr<std::vector<uint64_t>> offsetHolder{};
418 : };
419 :
420 : size_t m_nBatchSize = DEFAULT_BATCH_SIZE;
421 : size_t m_nTileCapacity = DEFAULT_TILE_CAPACITY;
422 : double m_dfTileExtent = 0;
423 : double m_dfZTileExtent = 0;
424 : size_t m_nEstimatedWkbSizePerRow = 0;
425 : std::map<std::string, size_t> m_oMapEstimatedSizePerRow{};
426 : double m_dfPadX = 0;
427 : double m_dfPadY = 0;
428 : double m_dfPadZ = 0;
429 :
430 : const char *GetDatabaseGeomColName();
431 : void InitializeSchemaAndArray();
432 : void FlushArrays();
433 : void AllocateNewBuffers();
434 : void ResetBuffers();
435 : void SwitchToReadingMode();
436 : void SwitchToWritingMode();
437 : bool InitFromStorage(tiledb::Context *poCtx, uint64_t nTimestamp,
438 : CSLConstList papszOpenOptions);
439 : void SetReadBuffers(bool bGrowVariableSizeArrays);
440 : bool SetupQuery(tiledb::QueryCondition *queryCondition);
441 : OGRFeature *TranslateCurrentFeature();
442 :
443 : OGRFeature *GetNextRawFeature();
444 : std::unique_ptr<tiledb::QueryCondition>
445 : CreateQueryCondition(const swq_expr_node *poNode, bool &bAlwaysTrue,
446 : bool &bAlwaysFalse);
447 : std::unique_ptr<tiledb::QueryCondition> CreateQueryCondition(
448 : int nOperation, bool bColumnIsLeft, const swq_expr_node *poColumn,
449 : const swq_expr_node *poValue, bool &bAlwaysTrue, bool &bAlwaysFalse);
450 :
451 : static void ReleaseArrowArray(struct ArrowArray *array);
452 : void FillBoolArray(struct ArrowArray *psChild, int iField,
453 : const std::vector<bool> &abyValidityFromFilters);
454 : void SetNullBuffer(struct ArrowArray *psChild, int iField,
455 : const std::vector<bool> &abyValidityFromFilters);
456 : template <typename T>
457 : void FillPrimitiveArray(struct ArrowArray *psChild, int iField,
458 : const std::vector<bool> &abyValidityFromFilters);
459 : void FillBoolListArray(struct ArrowArray *psChild, int iField,
460 : const std::vector<bool> &abyValidityFromFilters);
461 : template <typename T>
462 : void
463 : FillPrimitiveListArray(struct ArrowArray *psChild, int iField,
464 : const std::vector<bool> &abyValidityFromFilters);
465 : template <typename T>
466 : void
467 : FillStringOrBinaryArray(struct ArrowArray *psChild, int iField,
468 : const std::vector<bool> &abyValidityFromFilters);
469 : void FillTimeOrDateArray(struct ArrowArray *psChild, int iField,
470 : const std::vector<bool> &abyValidityFromFilters);
471 : int GetArrowSchema(struct ArrowArrayStream *,
472 : struct ArrowSchema *out_schema) override;
473 : int GetNextArrowArray(struct ArrowArrayStream *,
474 : struct ArrowArray *out_array) override;
475 :
476 : CPL_DISALLOW_COPY_ASSIGN(OGRTileDBLayer)
477 :
478 : public:
479 : OGRTileDBLayer(GDALDataset *poDS, const char *pszFilename,
480 : const char *pszLayerName, const OGRwkbGeometryType eGType,
481 : const OGRSpatialReference *poSRS);
482 : ~OGRTileDBLayer() override;
483 : void ResetReading() override;
484 662 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRTileDBLayer)
485 : OGRFeature *GetFeature(GIntBig nFID) override;
486 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
487 : OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
488 : int TestCapability(const char *) const override;
489 : GIntBig GetFeatureCount(int bForce) override;
490 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
491 : bool bForce) override;
492 :
493 254 : const char *GetFIDColumn() const override
494 : {
495 254 : return m_osFIDColumn.c_str();
496 : }
497 :
498 3551 : const OGRFeatureDefn *GetLayerDefn() const override
499 : {
500 3551 : return m_poFeatureDefn;
501 : }
502 :
503 : OGRErr SetAttributeFilter(const char *pszFilter) override;
504 :
505 : const char *GetMetadataItem(const char *pszName,
506 : const char *pszDomain) override;
507 :
508 19 : GDALDataset *GetDataset() override
509 : {
510 19 : return m_poDS;
511 : }
512 : };
513 :
514 : /************************************************************************/
515 : /* OGRTileDBDataset */
516 : /************************************************************************/
517 :
518 : class OGRTileDBDataset final : public TileDBDataset
519 : {
520 : friend OGRTileDBLayer;
521 : std::string m_osGroupName{};
522 : std::vector<std::unique_ptr<OGRLayer>> m_apoLayers{};
523 :
524 : public:
525 : OGRTileDBDataset();
526 : ~OGRTileDBDataset() override;
527 : OGRLayer *ExecuteSQL(const char *pszSQLCommand,
528 : OGRGeometry *poSpatialFilter,
529 : const char *pszDialect) override;
530 :
531 124 : int GetLayerCount() const override
532 : {
533 124 : return static_cast<int>(m_apoLayers.size());
534 : }
535 :
536 64 : const OGRLayer *GetLayer(int nIdx) const override
537 : {
538 64 : return nIdx >= 0 && nIdx < GetLayerCount() ? m_apoLayers[nIdx].get()
539 64 : : nullptr;
540 : }
541 :
542 : int TestCapability(const char *) const override;
543 :
544 : OGRLayer *ICreateLayer(const char *pszName,
545 : const OGRGeomFieldDefn *poGeomFieldDefn,
546 : CSLConstList papszOptions) override;
547 :
548 : static GDALDataset *Open(GDALOpenInfo *, tiledb::Object::Type objectType);
549 : static GDALDataset *Create(const char *pszFilename,
550 : CSLConstList papszOptions);
551 : };
552 :
553 : #endif // TILEDB_HEADERS_H
|