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