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 : 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 :
175 : static GDALDataset *Open(GDALOpenInfo *);
176 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
177 : int nBands, GDALDataType eType,
178 : char **papszOptions);
179 : static GDALDataset *CreateCopy(const char *pszFilename,
180 : GDALDataset *poSrcDS, int bStrict,
181 : char **papszOptions,
182 : GDALProgressFunc pfnProgress,
183 : void *pProgressData);
184 :
185 : static GDALDataset *OpenMultiDimensional(GDALOpenInfo *);
186 : static GDALDataset *
187 : CreateMultiDimensional(const char *pszFilename,
188 : CSLConstList papszRootGroupOptions,
189 : CSLConstList papszOptions);
190 : };
191 :
192 : /************************************************************************/
193 : /* ==================================================================== */
194 : /* TileDRasterDataset */
195 : /* ==================================================================== */
196 : /************************************************************************/
197 :
198 : class TileDBRasterDataset final : public TileDBDataset
199 : {
200 : friend class TileDBRasterBand;
201 :
202 : protected:
203 : std::string m_osConfigFilename{};
204 : std::unique_ptr<tiledb::Context> m_roCtx{};
205 : std::unique_ptr<tiledb::Array> m_array{};
206 : std::unique_ptr<tiledb::Array> m_roArray{};
207 : std::unique_ptr<tiledb::ArraySchema> m_schema{};
208 : std::unique_ptr<tiledb::FilterList> m_filterList{};
209 : bool m_bDatasetInGroup = false;
210 : std::string m_osArrayURI{};
211 : CPLString osMetaDoc{};
212 : TILEDB_INTERLEAVE_MODE eIndexMode = BAND;
213 : int nBitsPerSample = 8;
214 : GDALDataType eDataType = GDT_Unknown;
215 : int nBlockXSize = -1;
216 : int nBlockYSize = -1;
217 : int nBlocksX = 0;
218 : int nBlocksY = 0;
219 : uint64_t nBandStart = 1;
220 : bool m_bHasSubDatasets = false;
221 : CPLStringList m_aosSubdatasetMD{};
222 : CPLXMLTreeCloser m_poSubDatasetsTree{nullptr};
223 : std::list<std::unique_ptr<GDALDataset>> m_lpoAttributeDS = {};
224 : uint64_t nTimestamp = 0;
225 : bool bStats = FALSE;
226 : bool m_bDeferredCreateHasRun = false;
227 : bool m_bDeferredCreateHasBeenSuccessful = false;
228 :
229 : //! Number of overviews declared in _gdal metadata. In theory, it should
230 : // match m_apoOverviewDS.size(), but do not strongly rely on that.
231 : int m_nOverviewCountFromMetadata = 0;
232 :
233 : //! Overview datasets
234 : std::vector<std::unique_ptr<GDALDataset>> m_apoOverviewDS{};
235 :
236 : //! Overview datasets that have been removed per IBuildOverviews(nOverview==0)
237 : std::vector<std::unique_ptr<GDALDataset>> m_apoOverviewDSRemoved{};
238 :
239 : //! Whether LoadOverviews() has already been called.
240 : bool m_bLoadOverviewsDone = false;
241 :
242 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
243 : GDALDataType, int, BANDMAP_TYPE, GSpacing, GSpacing,
244 : GSpacing, GDALRasterIOExtraArg *psExtraArg) override;
245 : CPLErr CreateAttribute(GDALDataType eType, const CPLString &osAttrName,
246 : const int nSubRasterCount, bool bHasFillValue,
247 : double dfFillValue);
248 :
249 : CPLErr AddDimensions(tiledb::Domain &domain, const char *pszAttrName,
250 : tiledb::Dimension &y, tiledb::Dimension &x,
251 : tiledb::Dimension *poBands = nullptr);
252 :
253 : void CreateArray();
254 : bool DeferredCreate(bool bCreateArray);
255 :
256 : tiledb::Array &GetArray(bool bForWrite, tiledb::Context *&ctx);
257 :
258 : static GDALDataset *OpenInternal(GDALOpenInfo *,
259 : tiledb::Object::Type objectType);
260 :
261 : //! Load TileDB overviews from TileDB arrays
262 : void LoadOverviews();
263 :
264 : public:
265 : ~TileDBRasterDataset();
266 : CPLErr TryLoadCachedXML(CSLConstList papszSiblingFiles = nullptr,
267 : bool bReload = true);
268 : CPLErr TryLoadXML(CSLConstList papszSiblingFiles = nullptr) override;
269 : CPLErr TrySaveXML() override;
270 : char **GetMetadata(const char *pszDomain) override;
271 : CPLErr Close() override;
272 : int CloseDependentDatasets() override;
273 : virtual CPLErr FlushCache(bool bAtClosing) override;
274 :
275 : CPLErr IBuildOverviews(const char *pszResampling, int nOverviews,
276 : const int *panOverviewList, int nListBands,
277 : const int *panBandList, GDALProgressFunc pfnProgress,
278 : void *pProgressData,
279 : CSLConstList papszOptions) override;
280 :
281 : static CPLErr CopySubDatasets(GDALDataset *poSrcDS,
282 : TileDBRasterDataset *poDstDS,
283 : GDALProgressFunc pfnProgress,
284 : void *pProgressData);
285 : static TileDBRasterDataset *CreateLL(const char *pszFilename, int nXSize,
286 : int nYSize, int nBands,
287 : GDALDataType eType,
288 : CSLConstList papszOptions);
289 : static void SetBlockSize(GDALRasterBand *poBand, CPLStringList &aosOptions);
290 :
291 : static GDALDataset *Open(GDALOpenInfo *, tiledb::Object::Type objectType);
292 : static TileDBRasterDataset *Create(const char *pszFilename, int nXSize,
293 : int nYSize, int nBands,
294 : GDALDataType eType, char **papszOptions);
295 : static GDALDataset *CreateCopy(const char *pszFilename,
296 : GDALDataset *poSrcDS, int bStrict,
297 : char **papszOptions,
298 : GDALProgressFunc pfnProgress,
299 : void *pProgressData);
300 : };
301 :
302 : /************************************************************************/
303 : /* OGRTileDBLayer */
304 : /************************************************************************/
305 :
306 : class OGRTileDBDataset;
307 :
308 : class OGRTileDBLayer final : public OGRLayer,
309 : public OGRGetNextFeatureThroughRaw<OGRTileDBLayer>
310 : {
311 : public:
312 : typedef std::variant<std::shared_ptr<std::string>,
313 : #ifdef VECTOR_OF_BOOL_IS_NOT_UINT8_T
314 : std::shared_ptr<VECTOR_OF_BOOL>,
315 : #endif
316 : std::shared_ptr<std::vector<uint8_t>>,
317 : std::shared_ptr<std::vector<int16_t>>,
318 : std::shared_ptr<std::vector<uint16_t>>,
319 : std::shared_ptr<std::vector<int32_t>>,
320 : std::shared_ptr<std::vector<int64_t>>,
321 : std::shared_ptr<std::vector<float>>,
322 : std::shared_ptr<std::vector<double>>>
323 : ArrayType;
324 :
325 : private:
326 : friend OGRTileDBDataset;
327 : GDALDataset *m_poDS = nullptr;
328 : std::string m_osGroupName{};
329 : std::string m_osFilename{};
330 : uint64_t m_nTimestamp = 0;
331 : bool m_bUpdatable = false;
332 : enum class CurrentMode
333 : {
334 : None,
335 : ReadInProgress,
336 : WriteInProgress
337 : };
338 : CurrentMode m_eCurrentMode = CurrentMode::None;
339 : std::unique_ptr<tiledb::Context> m_ctx{};
340 : std::unique_ptr<tiledb::Array> m_array{};
341 : std::unique_ptr<tiledb::ArraySchema> m_schema{};
342 : std::unique_ptr<tiledb::Query> m_query{};
343 : std::unique_ptr<tiledb::FilterList> m_filterList{};
344 : bool m_bAttributeFilterPartiallyTranslated =
345 : false; // for debugging purposes
346 : bool m_bAttributeFilterAlwaysFalse = false;
347 : bool m_bAttributeFilterAlwaysTrue = false;
348 : std::unique_ptr<tiledb::QueryCondition> m_poQueryCondition{};
349 : bool m_bInitializationAttempted = false;
350 : bool m_bInitialized = false;
351 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
352 : std::string m_osFIDColumn{};
353 : GIntBig m_nNextFID = 1;
354 : int64_t m_nTotalFeatureCount = -1;
355 : bool m_bStats = false;
356 : bool m_bQueryComplete = false;
357 : bool m_bGrowBuffers = false;
358 : uint64_t m_nOffsetInResultSet = 0;
359 : uint64_t m_nRowCountInResultSet = 0;
360 : int m_nUseOptimizedAttributeFilter = -1; // uninitialized
361 :
362 : tiledb_datatype_t m_eTileDBStringType = TILEDB_STRING_UTF8;
363 :
364 : std::string m_osXDim = "_X";
365 : std::string m_osYDim = "_Y";
366 : std::string m_osZDim{}; // may be empty
367 :
368 : // Domain extent
369 : double m_dfXStart = 0;
370 : double m_dfYStart = 0;
371 : double m_dfZStart = -10000;
372 : double m_dfXEnd = 0;
373 : double m_dfYEnd = 0;
374 : double m_dfZEnd = 10000;
375 :
376 : // Extent of all features
377 : OGREnvelope m_oLayerExtent{};
378 :
379 : // Boolean shared between the OGRTileDBLayer instance and the
380 : // OGRTileDBArrowArrayPrivateData instances, that are stored in
381 : // ArrowArray::private_data, so ReleaseArrowArray() function knows
382 : // if the OGRLayer is still alive.
383 : std::shared_ptr<bool> m_pbLayerStillAlive{};
384 :
385 : // Flag set to false by GetNextArrowArray() to indicate that the m_anFIDs,
386 : // m_adfXs, m_adfYs, m_adfZs, m_aFieldValues, m_aFieldValueOffsets,
387 : // m_abyGeometries and m_anGeometryOffsets are currently used by a
388 : // ArrowArray returned. If this flag is still set to false when the
389 : // next SetupQuery() is called, we need to re-instanciate new arrays, so
390 : // the ArrowArray's can be used independently of the new state of the layer.
391 : bool m_bArrowBatchReleased = true;
392 :
393 : std::shared_ptr<std::vector<int64_t>> m_anFIDs{};
394 : std::shared_ptr<std::vector<double>> m_adfXs{};
395 : std::shared_ptr<std::vector<double>> m_adfYs{};
396 : std::shared_ptr<std::vector<double>> m_adfZs{};
397 : std::vector<tiledb_datatype_t> m_aeFieldTypes{};
398 : std::vector<int> m_aeFieldTypesInCreateField{};
399 : std::vector<size_t> m_anFieldValuesCapacity{};
400 : std::vector<ArrayType> m_aFieldValues{};
401 : std::vector<std::shared_ptr<std::vector<uint64_t>>> m_aFieldValueOffsets{};
402 : std::vector<std::vector<uint8_t>> m_aFieldValidity{};
403 : size_t m_nGeometriesCapacity = 0;
404 : std::shared_ptr<std::vector<unsigned char>> m_abyGeometries{};
405 : std::shared_ptr<std::vector<uint64_t>> m_anGeometryOffsets{};
406 :
407 : struct OGRTileDBArrowArrayPrivateData
408 : {
409 : OGRTileDBLayer *m_poLayer = nullptr;
410 : std::shared_ptr<bool> m_pbLayerStillAlive{};
411 :
412 : ArrayType valueHolder{};
413 : std::shared_ptr<std::vector<uint8_t>> nullHolder{};
414 : std::shared_ptr<std::vector<uint64_t>> offsetHolder{};
415 : };
416 :
417 : size_t m_nBatchSize = DEFAULT_BATCH_SIZE;
418 : size_t m_nTileCapacity = DEFAULT_TILE_CAPACITY;
419 : double m_dfTileExtent = 0;
420 : double m_dfZTileExtent = 0;
421 : size_t m_nEstimatedWkbSizePerRow = 0;
422 : std::map<std::string, size_t> m_oMapEstimatedSizePerRow{};
423 : double m_dfPadX = 0;
424 : double m_dfPadY = 0;
425 : double m_dfPadZ = 0;
426 :
427 : const char *GetDatabaseGeomColName();
428 : void InitializeSchemaAndArray();
429 : void FlushArrays();
430 : void AllocateNewBuffers();
431 : void ResetBuffers();
432 : void SwitchToReadingMode();
433 : void SwitchToWritingMode();
434 : bool InitFromStorage(tiledb::Context *poCtx, uint64_t nTimestamp,
435 : CSLConstList papszOpenOptions);
436 : void SetReadBuffers(bool bGrowVariableSizeArrays);
437 : bool SetupQuery(tiledb::QueryCondition *queryCondition);
438 : OGRFeature *TranslateCurrentFeature();
439 :
440 : OGRFeature *GetNextRawFeature();
441 : std::unique_ptr<tiledb::QueryCondition>
442 : CreateQueryCondition(const swq_expr_node *poNode, bool &bAlwaysTrue,
443 : bool &bAlwaysFalse);
444 : std::unique_ptr<tiledb::QueryCondition> CreateQueryCondition(
445 : int nOperation, bool bColumnIsLeft, const swq_expr_node *poColumn,
446 : const swq_expr_node *poValue, bool &bAlwaysTrue, bool &bAlwaysFalse);
447 :
448 : static void ReleaseArrowArray(struct ArrowArray *array);
449 : void FillBoolArray(struct ArrowArray *psChild, int iField,
450 : const std::vector<bool> &abyValidityFromFilters);
451 : void SetNullBuffer(struct ArrowArray *psChild, int iField,
452 : const std::vector<bool> &abyValidityFromFilters);
453 : template <typename T>
454 : void FillPrimitiveArray(struct ArrowArray *psChild, int iField,
455 : const std::vector<bool> &abyValidityFromFilters);
456 : void FillBoolListArray(struct ArrowArray *psChild, int iField,
457 : const std::vector<bool> &abyValidityFromFilters);
458 : template <typename T>
459 : void
460 : FillPrimitiveListArray(struct ArrowArray *psChild, int iField,
461 : const std::vector<bool> &abyValidityFromFilters);
462 : template <typename T>
463 : void
464 : FillStringOrBinaryArray(struct ArrowArray *psChild, int iField,
465 : const std::vector<bool> &abyValidityFromFilters);
466 : void FillTimeOrDateArray(struct ArrowArray *psChild, int iField,
467 : const std::vector<bool> &abyValidityFromFilters);
468 : int GetArrowSchema(struct ArrowArrayStream *,
469 : struct ArrowSchema *out_schema) override;
470 : int GetNextArrowArray(struct ArrowArrayStream *,
471 : struct ArrowArray *out_array) override;
472 :
473 : CPL_DISALLOW_COPY_ASSIGN(OGRTileDBLayer)
474 :
475 : public:
476 : OGRTileDBLayer(GDALDataset *poDS, const char *pszFilename,
477 : const char *pszLayerName, const OGRwkbGeometryType eGType,
478 : const OGRSpatialReference *poSRS);
479 : ~OGRTileDBLayer();
480 : void ResetReading() override;
481 648 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRTileDBLayer)
482 : OGRFeature *GetFeature(GIntBig nFID) override;
483 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
484 : OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
485 : int TestCapability(const char *) override;
486 : GIntBig GetFeatureCount(int bForce) override;
487 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
488 : bool bForce) override;
489 :
490 254 : const char *GetFIDColumn() override
491 : {
492 254 : return m_osFIDColumn.c_str();
493 : }
494 :
495 5494 : OGRFeatureDefn *GetLayerDefn() override
496 : {
497 5494 : return m_poFeatureDefn;
498 : }
499 :
500 : OGRErr SetAttributeFilter(const char *pszFilter) override;
501 :
502 : const char *GetMetadataItem(const char *pszName,
503 : const char *pszDomain) override;
504 :
505 19 : GDALDataset *GetDataset() override
506 : {
507 19 : return m_poDS;
508 : }
509 : };
510 :
511 : /************************************************************************/
512 : /* OGRTileDBDataset */
513 : /************************************************************************/
514 :
515 : class OGRTileDBDataset final : public TileDBDataset
516 : {
517 : friend OGRTileDBLayer;
518 : std::string m_osGroupName{};
519 : std::vector<std::unique_ptr<OGRLayer>> m_apoLayers{};
520 :
521 : public:
522 : OGRTileDBDataset();
523 : ~OGRTileDBDataset();
524 : OGRLayer *ExecuteSQL(const char *pszSQLCommand,
525 : OGRGeometry *poSpatialFilter,
526 : const char *pszDialect) override;
527 :
528 102 : int GetLayerCount() override
529 : {
530 102 : return static_cast<int>(m_apoLayers.size());
531 : }
532 :
533 64 : OGRLayer *GetLayer(int nIdx) override
534 : {
535 64 : return nIdx >= 0 && nIdx < GetLayerCount() ? m_apoLayers[nIdx].get()
536 64 : : nullptr;
537 : }
538 :
539 : int TestCapability(const char *) override;
540 :
541 : OGRLayer *ICreateLayer(const char *pszName,
542 : const OGRGeomFieldDefn *poGeomFieldDefn,
543 : CSLConstList papszOptions) override;
544 :
545 : static GDALDataset *Open(GDALOpenInfo *, tiledb::Object::Type objectType);
546 : static GDALDataset *Create(const char *pszFilename,
547 : CSLConstList papszOptions);
548 : };
549 :
550 : #endif // TILEDB_HEADERS_H
|