Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL TileDB Driver
4 : * Purpose: Implement GDAL TileDB multidimensional support based on https://www.tiledb.io
5 : * Author: TileDB, Inc
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, TileDB, Inc
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "tiledbmultidim.h"
30 :
31 : /************************************************************************/
32 : /* TileDBAttributeHolder::~TileDBAttributeHolder() */
33 : /************************************************************************/
34 :
35 : TileDBAttributeHolder::~TileDBAttributeHolder() = default;
36 :
37 : /************************************************************************/
38 : /* TileDBAttributeHolder::CreateAttributeImpl() */
39 : /************************************************************************/
40 :
41 17 : std::shared_ptr<GDALAttribute> TileDBAttributeHolder::CreateAttributeImpl(
42 : const std::string &osName, const std::vector<GUInt64> &anDimensions,
43 : const GDALExtendedDataType &oDataType, CSLConstList /*papszOptions*/)
44 : {
45 17 : if (!IIsWritable())
46 : {
47 2 : CPLError(CE_Failure, CPLE_NotSupported,
48 : "Dataset not open in update mode");
49 2 : return nullptr;
50 : }
51 :
52 15 : if (!EnsureOpenAs(TILEDB_READ))
53 0 : return nullptr;
54 : try
55 : {
56 : tiledb_datatype_t value_type;
57 30 : if (m_oMapAttributes.find(osName) != m_oMapAttributes.end() ||
58 15 : has_metadata(osName, &value_type))
59 : {
60 0 : CPLError(CE_Failure, CPLE_AppDefined,
61 : "An attribute with same name already exists");
62 0 : return nullptr;
63 : }
64 : }
65 0 : catch (const std::exception &e)
66 : {
67 0 : CPLError(CE_Failure, CPLE_AppDefined, "has_metadata() failed with: %s",
68 0 : e.what());
69 0 : return nullptr;
70 : }
71 15 : if (!EnsureOpenAs(TILEDB_WRITE))
72 0 : return nullptr;
73 :
74 15 : auto poAttr = TileDBAttribute::Create(AsAttributeHolderSharedPtr(), osName,
75 30 : anDimensions, oDataType);
76 15 : if (poAttr)
77 15 : m_oMapAttributes[osName] = poAttr;
78 15 : return poAttr;
79 : }
80 :
81 : /************************************************************************/
82 : /* TileDBAttributeHolder::CreateAttribute() */
83 : /************************************************************************/
84 :
85 : /* static */ std::shared_ptr<GDALAttribute>
86 58 : TileDBAttributeHolder::CreateAttribute(
87 : const std::shared_ptr<TileDBAttributeHolder> &poSelf,
88 : const std::string &osName, tiledb_datatype_t value_type, uint32_t value_num,
89 : const void *value)
90 : {
91 76 : if (value_type == TILEDB_STRING_ASCII || value_type == TILEDB_STRING_UTF8 ||
92 18 : (osName == "_gdal" && value_type == TILEDB_UINT8 && value &&
93 0 : CPLIsUTF8(static_cast<const char *>(value), value_num)))
94 : {
95 : return TileDBAttribute::Create(poSelf, osName, {},
96 40 : GDALExtendedDataType::CreateString());
97 : }
98 : else
99 : {
100 : GDALDataType eDT =
101 18 : TileDBArray::TileDBDataTypeToGDALDataType(value_type);
102 18 : if (eDT == GDT_Unknown)
103 : {
104 0 : const char *pszTypeName = "";
105 0 : tiledb_datatype_to_str(value_type, &pszTypeName);
106 0 : CPLDebug("TILEDB",
107 : "Metadata item %s ignored because of unsupported "
108 : "type %s",
109 : osName.c_str(), pszTypeName);
110 : }
111 : else
112 : {
113 18 : return TileDBAttribute::Create(poSelf, osName, {value_num},
114 18 : GDALExtendedDataType::Create(eDT));
115 : }
116 : }
117 0 : return nullptr;
118 : }
119 :
120 : /************************************************************************/
121 : /* TileDBAttributeHolder::GetAttributeImpl() */
122 : /************************************************************************/
123 :
124 : std::shared_ptr<GDALAttribute>
125 43 : TileDBAttributeHolder::GetAttributeImpl(const std::string &osName) const
126 : {
127 43 : if (!EnsureOpenAs(TILEDB_READ))
128 0 : return nullptr;
129 :
130 43 : auto oIter = m_oMapAttributes.find(osName);
131 43 : if (oIter != m_oMapAttributes.end())
132 7 : return oIter->second;
133 :
134 : try
135 : {
136 : tiledb_datatype_t value_type;
137 : uint32_t value_num;
138 : const void *value;
139 36 : get_metadata(osName, &value_type, &value_num, &value);
140 36 : if (value == nullptr)
141 26 : return nullptr;
142 :
143 0 : auto poAttr = CreateAttribute(AsAttributeHolderSharedPtr(), osName,
144 20 : value_type, value_num, value);
145 10 : if (poAttr)
146 : {
147 10 : m_oMapAttributes[osName] = poAttr;
148 : }
149 10 : return poAttr;
150 : }
151 0 : catch (const std::exception &e)
152 : {
153 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetAttribute() failed with: %s",
154 0 : e.what());
155 0 : return nullptr;
156 : }
157 : }
158 :
159 : /************************************************************************/
160 : /* IsSpecialAttribute() */
161 : /************************************************************************/
162 :
163 48 : static bool IsSpecialAttribute(const std::string &osName)
164 : {
165 138 : return osName == CRS_ATTRIBUTE_NAME || osName == UNIT_ATTRIBUTE_NAME ||
166 84 : osName == DIM_TYPE_ATTRIBUTE_NAME ||
167 138 : osName == DIM_DIRECTION_ATTRIBUTE_NAME ||
168 90 : osName == GDAL_ATTRIBUTE_NAME;
169 : }
170 :
171 : /************************************************************************/
172 : /* TileDBAttributeHolder::GetAttributesImpl() */
173 : /************************************************************************/
174 :
175 : std::vector<std::shared_ptr<GDALAttribute>>
176 44 : TileDBAttributeHolder::GetAttributesImpl(CSLConstList papszOptions) const
177 : {
178 44 : if (!EnsureOpenAs(TILEDB_READ))
179 0 : return {};
180 :
181 : const bool bShowAll =
182 44 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "SHOW_ALL", "NO"));
183 :
184 : try
185 : {
186 88 : std::vector<std::shared_ptr<GDALAttribute>> apoAttributes;
187 44 : const uint64_t nAttributes = metadata_num();
188 88 : auto poSelf = AsAttributeHolderSharedPtr();
189 98 : for (uint64_t i = 0; i < nAttributes; ++i)
190 : {
191 108 : std::string key;
192 : tiledb_datatype_t value_type;
193 : uint32_t value_num;
194 : const void *value;
195 54 : get_metadata_from_index(i, &key, &value_type, &value_num, &value);
196 54 : if (bShowAll || !IsSpecialAttribute(key))
197 : {
198 : auto poAttr =
199 96 : CreateAttribute(poSelf, key, value_type, value_num, value);
200 48 : if (poAttr)
201 : {
202 48 : apoAttributes.emplace_back(std::move(poAttr));
203 48 : m_oMapAttributes[key] = apoAttributes.back();
204 : }
205 : }
206 : }
207 44 : return apoAttributes;
208 : }
209 0 : catch (const std::exception &e)
210 : {
211 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetAttributes() failed with: %s",
212 0 : e.what());
213 0 : return {};
214 : }
215 : }
216 :
217 : /************************************************************************/
218 : /* TileDBAttributeHolder::DeleteAttributeImpl() */
219 : /************************************************************************/
220 :
221 3 : bool TileDBAttributeHolder::DeleteAttributeImpl(const std::string &osName,
222 : CSLConstList /*papszOptions*/)
223 : {
224 3 : if (!IIsWritable())
225 : {
226 1 : CPLError(CE_Failure, CPLE_NotSupported,
227 : "Dataset not open in update mode");
228 1 : return false;
229 : }
230 :
231 2 : if (!EnsureOpenAs(TILEDB_WRITE))
232 0 : return false;
233 :
234 2 : auto oIter = m_oMapAttributes.find(osName);
235 :
236 : try
237 : {
238 2 : delete_metadata(osName);
239 :
240 2 : if (oIter != m_oMapAttributes.end())
241 : {
242 1 : oIter->second->Deleted();
243 1 : m_oMapAttributes.erase(oIter);
244 : }
245 2 : return true;
246 : }
247 0 : catch (const std::exception &e)
248 : {
249 0 : CPLError(CE_Failure, CPLE_AppDefined,
250 0 : "DeleteAttribute() failed with: %s", e.what());
251 0 : return false;
252 : }
253 : }
254 :
255 : /************************************************************************/
256 : /* TileDBAttributeHolder::GetMetadata() */
257 : /************************************************************************/
258 :
259 32 : bool TileDBAttributeHolder::GetMetadata(const std::string &key,
260 : tiledb_datatype_t *value_type,
261 : uint32_t *value_num,
262 : const void **value) const
263 : {
264 32 : if (!EnsureOpenAs(TILEDB_READ))
265 0 : return false;
266 : try
267 : {
268 32 : get_metadata(key, value_type, value_num, value);
269 32 : return *value != nullptr;
270 : }
271 0 : catch (const std::exception &e)
272 : {
273 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetMetadata() failed with: %s",
274 0 : e.what());
275 0 : return false;
276 : }
277 : }
278 :
279 : /************************************************************************/
280 : /* TileDBAttributeHolder::PutMetadata() */
281 : /************************************************************************/
282 :
283 13 : bool TileDBAttributeHolder::PutMetadata(const std::string &key,
284 : tiledb_datatype_t value_type,
285 : uint32_t value_num, const void *value)
286 : {
287 13 : if (!EnsureOpenAs(TILEDB_WRITE))
288 0 : return false;
289 : try
290 : {
291 13 : put_metadata(key, value_type, value_num, value);
292 13 : return true;
293 : }
294 0 : catch (const std::exception &e)
295 : {
296 0 : CPLError(CE_Failure, CPLE_AppDefined, "PutMetadata() failed with: %s",
297 0 : e.what());
298 0 : return false;
299 : }
300 : }
|