Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL TileDB Driver
4 : * Purpose: Implement GDAL TileDB Support based on https://www.tiledb.io
5 : * Author: TileDB, Inc
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, TileDB, Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #define INCLUDE_ONLY_TILEDB_VERSION
14 : #include "include_tiledb.h"
15 :
16 : #include "gdal_frmts.h"
17 :
18 : #ifdef PLUGIN_FILENAME
19 : #include "gdalplugindriverproxy.h"
20 : #endif
21 :
22 : #include "tiledbdrivercore.h"
23 :
24 : /************************************************************************/
25 : /* TileDBDriverIdentifySimplified() */
26 : /************************************************************************/
27 :
28 73903 : int TileDBDriverIdentifySimplified(GDALOpenInfo *poOpenInfo)
29 :
30 : {
31 73903 : if (poOpenInfo->pszFilename[0] == 0)
32 : {
33 354 : return FALSE;
34 : }
35 73549 : if (STARTS_WITH_CI(poOpenInfo->pszFilename, "TILEDB:"))
36 : {
37 4 : return TRUE;
38 : }
39 :
40 73545 : if (poOpenInfo->IsSingleAllowedDriver("TileDB"))
41 : {
42 113 : return TRUE;
43 : }
44 :
45 : const char *pszConfig =
46 73432 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_CONFIG");
47 :
48 73432 : if (pszConfig != nullptr)
49 : {
50 0 : return TRUE;
51 : }
52 :
53 73432 : if (!poOpenInfo->bIsDirectory &&
54 70312 : !STARTS_WITH_CI(poOpenInfo->pszFilename, "/VSI"))
55 : {
56 30222 : return false;
57 : }
58 :
59 43210 : const bool bIsS3OrGSOrAz =
60 86416 : STARTS_WITH_CI(poOpenInfo->pszFilename, "/VSIS3/") ||
61 86415 : STARTS_WITH_CI(poOpenInfo->pszFilename, "/VSIGS/") ||
62 43205 : STARTS_WITH_CI(poOpenInfo->pszFilename, "/VSIAZ/");
63 : // If this is a /vsi virtual file systems, bail out, except if it is AZ, S3 or GS.
64 43210 : if (bIsS3OrGSOrAz)
65 : {
66 : // HACK: probing a non existing object takes a lot of time, so avoid
67 : // doing that on filenames that are (hopefully) not TileDB.
68 : // So we only accept /vsis3/path/to/something.tdb
69 : // or /vsis3/path/to/something.long_suffix_that_is_not_an_extension
70 6 : const std::string osExt = CPLGetExtensionSafe(poOpenInfo->pszFilename);
71 6 : const size_t nExtLen = osExt.size();
72 6 : if (nExtLen > 0 && nExtLen <= 4 && !EQUAL(osExt.c_str(), "tdb"))
73 6 : return false;
74 : }
75 43204 : else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "/VSI"))
76 : {
77 41856 : return false;
78 : }
79 :
80 1348 : return GDAL_IDENTIFY_UNKNOWN;
81 : }
82 :
83 : /************************************************************************/
84 : /* TileDBDriverSetCommonMetadata() */
85 : /************************************************************************/
86 :
87 : #define XSTRINGIFY(X) #X
88 : #define STRINGIFY(X) XSTRINGIFY(X)
89 :
90 1890 : void TileDBDriverSetCommonMetadata(GDALDriver *poDriver)
91 : {
92 1890 : poDriver->SetDescription(DRIVER_NAME);
93 1890 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
94 1890 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
95 1890 : poDriver->SetMetadataItem(GDAL_DCAP_SUBCREATECOPY, "YES");
96 1890 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "TileDB");
97 1890 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/tiledb.html");
98 1890 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
99 : "Byte UInt16 Int16 UInt32 Int32 Float32 "
100 1890 : "Float64 CInt16 CInt32 CFloat32 CFloat64");
101 1890 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
102 1890 : poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
103 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES, "YES");
104 1890 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
105 1890 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
106 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
107 :
108 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
109 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
110 1890 : poDriver->SetMetadataItem(
111 : GDAL_DMD_CREATIONFIELDDATATYPES,
112 : "Integer Integer64 Real String Date Time DateTime "
113 1890 : "IntegerList Integer64List RealList Binary");
114 1890 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES,
115 1890 : "Boolean Int16 Float32");
116 1890 : poDriver->SetMetadataItem(
117 : GDAL_DMD_CREATIONOPTIONLIST,
118 : "<CreationOptionList>\n"
119 : " <Option name='COMPRESSION' scope='raster' type='string-select' "
120 : "description='image "
121 : "compression to use' default='NONE'>\n"
122 : " <Value>NONE</Value>\n"
123 : " <Value>GZIP</Value>\n"
124 : " <Value>ZSTD</Value>\n"
125 : " <Value>LZ4</Value>\n"
126 : " <Value>RLE</Value>\n"
127 : " <Value>BZIP2</Value>\n"
128 : " <Value>DOUBLE-DELTA</Value>\n"
129 : " <Value>POSITIVE-DELTA</Value>\n"
130 : " </Option>\n"
131 : " <Option name='COMPRESSION_LEVEL' scope='raster' type='int' "
132 : "description='Compression level'/>\n"
133 : " <Option name='BLOCKXSIZE' scope='raster' type='int' "
134 : "description='Tile Width'/>"
135 : " <Option name='BLOCKYSIZE' scope='raster' type='int' "
136 : "description='Tile Height'/>"
137 : " <Option name='STATS' scope='raster' type='boolean' default='false' "
138 : "description='Dump TileDB stats'/>"
139 : " <Option name='TILEDB_CONFIG' type='string' "
140 : "description='location "
141 : "of configuration file for TileDB'/>"
142 : " <Option name='TILEDB_ATTRIBUTE' scope='raster' type='string' "
143 : "description='co-registered file to add as TileDB attributes, only "
144 : "applicable for interleave types of band or pixel'/>"
145 : " <Option name='INTERLEAVE' scope='raster' type='string-select' "
146 : "description='Indexing order' default='BAND'>\n"
147 : " <Value>BAND</Value>\n"
148 : " <Value>PIXEL</Value>\n"
149 : " <Value>ATTRIBUTES</Value>\n"
150 : " </Option>\n"
151 : " <Option name='TILEDB_TIMESTAMP' scope='raster' type='int' "
152 : "description='Create "
153 : "array at this timestamp, the timestamp should be > 0'/>\n"
154 : " <Option name='CREATE_GROUP' type='boolean' "
155 : "description='Whether to create a group for multiple vector layer "
156 : "support (defaults to NO), or raster with overviews "
157 : "(defaults to YES)'/>"
158 1890 : "</CreationOptionList>\n");
159 :
160 : // clang-format off
161 1890 : poDriver->SetMetadataItem(
162 : GDAL_DMD_OPENOPTIONLIST,
163 : "<OpenOptionList>"
164 : " <Option name='STATS' scope='raster' type='boolean' default='false' "
165 : "description='Dump TileDB stats'/>"
166 : " <Option name='TILEDB_ATTRIBUTE' scope='raster' type='string' "
167 : "description='Attribute to read from each band'/>"
168 : " <Option name='TILEDB_CONFIG' type='string' description='location "
169 : "of configuration file for TileDB'/>"
170 : " <Option name='TILEDB_TIMESTAMP' type='int' description='Open array "
171 : "at this timestamp, the timestamp should be > 0'/>"
172 : " <Option name='BATCH_SIZE' scope='vector' type='int' default='"
173 : STRINGIFY(DEFAULT_BATCH_SIZE) "' "
174 : "description='Number of features to fetch/write at once'/>"
175 : " <Option name='DIM_X' type='string' scope='vector' default='_X' "
176 : "description='Name of the X dimension.'/>"
177 : " <Option name='DIM_Y' type='string' scope='vector' default='_Y' "
178 : "description='Name of the Y dimension.'/>"
179 : " <Option name='DIM_Z' type='string' scope='vector' default='_Z' "
180 : "description='Name of the Z dimension.'/>"
181 1890 : "</OpenOptionList>");
182 : // clang-format on
183 :
184 : // clang-format off
185 1890 : poDriver->SetMetadataItem(
186 : GDAL_DS_LAYER_CREATIONOPTIONLIST,
187 : "<LayerCreationOptionList>"
188 : " <Option name='COMPRESSION' type='string-select' description='"
189 : "Compression to use' default='NONE'>\n"
190 : " <Value>NONE</Value>\n"
191 : " <Value>GZIP</Value>\n"
192 : " <Value>ZSTD</Value>\n"
193 : " <Value>LZ4</Value>\n"
194 : " <Value>RLE</Value>\n"
195 : " <Value>BZIP2</Value>\n"
196 : " <Value>DOUBLE-DELTA</Value>\n"
197 : " <Value>POSITIVE-DELTA</Value>\n"
198 : " </Option>\n"
199 : " <Option name='COMPRESSION_LEVEL' type='int' "
200 : "description='Compression level'/>\n"
201 : " <Option name='BATCH_SIZE' type='int' default='"
202 : STRINGIFY(DEFAULT_BATCH_SIZE) "' "
203 : "description='Number of features to write at once'/>"
204 : " <Option name='TILE_CAPACITY' type='int' default='"
205 : STRINGIFY(DEFAULT_TILE_CAPACITY) "' "
206 : "description='Number of non-empty cells stored in a data tile'/>"
207 : " <Option name='BOUNDS' type='string' description='Specify "
208 : "bounds for sparse array, minx, miny, [minz,] maxx, maxy [, maxz]'/>\n"
209 : " <Option name='TILE_EXTENT' type='float' description='Specify "
210 : "square X/Y tile extents for a sparse array'/>\n"
211 : " <Option name='TILE_Z_EXTENT' type='float' description='Specify "
212 : "Z tile extents for a sparse array'/>\n"
213 : " <Option name='ADD_Z_DIM' type='string-select' description='"
214 : "Whether to add a Z dimension' default='AUTO'>"
215 : " <Value>AUTO</Value>"
216 : " <Value>YES</Value>"
217 : " <Value>NO</Value>"
218 : " </Option>"
219 : " <Option name='FID' type='string' description='Feature id column "
220 : "name. Set to empty to disable its creation.' default='FID'/>"
221 : " <Option name='GEOMETRY_NAME' type='string' description='Name "
222 : "of the geometry column that will receive WKB encoded geometries. "
223 : "Set to empty to disable its creation (only for point).' "
224 : "default='wkb_geometry'/>"
225 : " <Option name='TILEDB_TIMESTAMP' type='int' description='Create "
226 : "array at this timestamp, the timestamp should be > 0'/>"
227 : " <Option name='TILEDB_STRING_TYPE' type='string-select' "
228 : "description='Which TileDB type to create string attributes' "
229 : "default='UTF8'"
230 : ">"
231 : " <Value>UTF8</Value>"
232 : " <Value>ASCII</Value>"
233 : " </Option>"
234 : " <Option name='STATS' type='boolean' default='false' "
235 : "description='Dump TileDB stats'/>"
236 1890 : "</LayerCreationOptionList>");
237 : // clang-format on
238 :
239 1890 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
240 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_MULTIDIMENSIONAL, "YES");
241 :
242 1890 : poDriver->SetMetadataItem(
243 : GDAL_DMD_MULTIDIM_DATASET_CREATIONOPTIONLIST,
244 : "<MultiDimDatasetCreationOptionList>"
245 : " <Option name='TILEDB_CONFIG' type='string' description='location "
246 : "of configuration file for TileDB'/>"
247 : " <Option name='TILEDB_TIMESTAMP' type='int' description='Create "
248 : "arrays at this timestamp, the timestamp should be > 0'/>"
249 : " <Option name='STATS' type='boolean' default='false' "
250 : "description='Dump TileDB stats'/>"
251 1890 : "</MultiDimDatasetCreationOptionList>");
252 :
253 1890 : poDriver->SetMetadataItem(
254 : GDAL_DMD_MULTIDIM_ARRAY_OPENOPTIONLIST,
255 : "<MultiDimArrayOpenOptionList>"
256 : " <Option name='TILEDB_TIMESTAMP' type='int' description='Open "
257 : "array at this timestamp, the timestamp should be > 0'/>"
258 1890 : "</MultiDimArrayOpenOptionList>");
259 :
260 1890 : poDriver->SetMetadataItem(
261 : GDAL_DMD_MULTIDIM_ARRAY_CREATIONOPTIONLIST,
262 : "<MultiDimArrayCreationOptionList>"
263 : " <Option name='TILEDB_TIMESTAMP' type='int' description='Create "
264 : "array at this timestamp, the timestamp should be > 0'/>"
265 : " <Option name='BLOCKSIZE' type='int' description='Block size in "
266 : "pixels'/>"
267 : " <Option name='COMPRESSION' type='string-select' description='"
268 : "Compression to use' default='NONE'>\n"
269 : " <Value>NONE</Value>\n"
270 : " <Value>GZIP</Value>\n"
271 : " <Value>ZSTD</Value>\n"
272 : " <Value>LZ4</Value>\n"
273 : " <Value>RLE</Value>\n"
274 : " <Value>BZIP2</Value>\n"
275 : " <Value>DOUBLE-DELTA</Value>\n"
276 : " <Value>POSITIVE-DELTA</Value>\n"
277 : " </Option>\n"
278 : " <Option name='COMPRESSION_LEVEL' type='int' "
279 : "description='Compression level'/>\n"
280 : " <Option name='STATS' type='boolean' default='false' "
281 : "description='Dump TileDB stats'/>"
282 : " <Option name='IN_MEMORY' type='boolean' default='false' "
283 : "description='Whether the array should be only in-memory. Useful to "
284 : "create an indexing variable that is serialized as a dimension label'/>"
285 1890 : "</MultiDimArrayCreationOptionList>");
286 :
287 1890 : poDriver->pfnIdentify = TileDBDriverIdentifySimplified;
288 1890 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
289 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
290 1890 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
291 :
292 1890 : poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
293 1890 : poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS, "RasterValues Features");
294 :
295 1890 : poDriver->SetMetadataItem(
296 : "TILEDB_VERSION",
297 : STRINGIFY(TILEDB_VERSION_MAJOR) "." STRINGIFY(
298 1890 : TILEDB_VERSION_MINOR) "." STRINGIFY(TILEDB_VERSION_PATCH));
299 1890 : }
300 :
301 : /************************************************************************/
302 : /* DeclareDeferredTileDBPlugin() */
303 : /************************************************************************/
304 :
305 : #ifdef PLUGIN_FILENAME
306 2126 : void DeclareDeferredTileDBPlugin()
307 : {
308 2126 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
309 : {
310 263 : return;
311 : }
312 1863 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
313 : #ifdef PLUGIN_INSTALLATION_MESSAGE
314 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
315 : PLUGIN_INSTALLATION_MESSAGE);
316 : #endif
317 1863 : TileDBDriverSetCommonMetadata(poDriver);
318 1863 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
319 : }
320 : #endif
|