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