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 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "tiledbmultidim.h"
14 :
15 : /************************************************************************/
16 : /* TileDBAttributeHolder::~TileDBAttributeHolder() */
17 : /************************************************************************/
18 :
19 : TileDBAttributeHolder::~TileDBAttributeHolder() = default;
20 :
21 : /************************************************************************/
22 : /* TileDBAttributeHolder::CreateAttributeImpl() */
23 : /************************************************************************/
24 :
25 17 : std::shared_ptr<GDALAttribute> TileDBAttributeHolder::CreateAttributeImpl(
26 : const std::string &osName, const std::vector<GUInt64> &anDimensions,
27 : const GDALExtendedDataType &oDataType, CSLConstList /*papszOptions*/)
28 : {
29 17 : if (!IIsWritable())
30 : {
31 2 : CPLError(CE_Failure, CPLE_NotSupported,
32 : "Dataset not open in update mode");
33 2 : return nullptr;
34 : }
35 :
36 15 : if (!EnsureOpenAs(TILEDB_READ))
37 0 : return nullptr;
38 : try
39 : {
40 : tiledb_datatype_t value_type;
41 30 : if (m_oMapAttributes.find(osName) != m_oMapAttributes.end() ||
42 15 : has_metadata(osName, &value_type))
43 : {
44 0 : CPLError(CE_Failure, CPLE_AppDefined,
45 : "An attribute with same name already exists");
46 0 : return nullptr;
47 : }
48 : }
49 0 : catch (const std::exception &e)
50 : {
51 0 : CPLError(CE_Failure, CPLE_AppDefined, "has_metadata() failed with: %s",
52 0 : e.what());
53 0 : return nullptr;
54 : }
55 15 : if (!EnsureOpenAs(TILEDB_WRITE))
56 0 : return nullptr;
57 :
58 15 : auto poAttr = TileDBAttribute::Create(AsAttributeHolderSharedPtr(), osName,
59 30 : anDimensions, oDataType);
60 15 : if (poAttr)
61 15 : m_oMapAttributes[osName] = poAttr;
62 15 : return poAttr;
63 : }
64 :
65 : /************************************************************************/
66 : /* TileDBAttributeHolder::CreateAttribute() */
67 : /************************************************************************/
68 :
69 : /* static */ std::shared_ptr<GDALAttribute>
70 58 : TileDBAttributeHolder::CreateAttribute(
71 : const std::shared_ptr<TileDBAttributeHolder> &poSelf,
72 : const std::string &osName, tiledb_datatype_t value_type, uint32_t value_num,
73 : const void *value)
74 : {
75 76 : if (value_type == TILEDB_STRING_ASCII || value_type == TILEDB_STRING_UTF8 ||
76 18 : (osName == "_gdal" && value_type == TILEDB_UINT8 && value &&
77 0 : CPLIsUTF8(static_cast<const char *>(value), value_num)))
78 : {
79 : return TileDBAttribute::Create(poSelf, osName, {},
80 40 : GDALExtendedDataType::CreateString());
81 : }
82 : else
83 : {
84 : GDALDataType eDT =
85 18 : TileDBArray::TileDBDataTypeToGDALDataType(value_type);
86 18 : if (eDT == GDT_Unknown)
87 : {
88 0 : const char *pszTypeName = "";
89 0 : tiledb_datatype_to_str(value_type, &pszTypeName);
90 0 : CPLDebug("TILEDB",
91 : "Metadata item %s ignored because of unsupported "
92 : "type %s",
93 : osName.c_str(), pszTypeName);
94 : }
95 : else
96 : {
97 18 : return TileDBAttribute::Create(poSelf, osName, {value_num},
98 18 : GDALExtendedDataType::Create(eDT));
99 : }
100 : }
101 0 : return nullptr;
102 : }
103 :
104 : /************************************************************************/
105 : /* TileDBAttributeHolder::GetAttributeImpl() */
106 : /************************************************************************/
107 :
108 : std::shared_ptr<GDALAttribute>
109 43 : TileDBAttributeHolder::GetAttributeImpl(const std::string &osName) const
110 : {
111 43 : if (!EnsureOpenAs(TILEDB_READ))
112 0 : return nullptr;
113 :
114 43 : auto oIter = m_oMapAttributes.find(osName);
115 43 : if (oIter != m_oMapAttributes.end())
116 7 : return oIter->second;
117 :
118 : try
119 : {
120 : tiledb_datatype_t value_type;
121 : uint32_t value_num;
122 : const void *value;
123 36 : get_metadata(osName, &value_type, &value_num, &value);
124 36 : if (value == nullptr)
125 26 : return nullptr;
126 :
127 0 : auto poAttr = CreateAttribute(AsAttributeHolderSharedPtr(), osName,
128 20 : value_type, value_num, value);
129 10 : if (poAttr)
130 : {
131 10 : m_oMapAttributes[osName] = poAttr;
132 : }
133 10 : return poAttr;
134 : }
135 0 : catch (const std::exception &e)
136 : {
137 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetAttribute() failed with: %s",
138 0 : e.what());
139 0 : return nullptr;
140 : }
141 : }
142 :
143 : /************************************************************************/
144 : /* IsSpecialAttribute() */
145 : /************************************************************************/
146 :
147 48 : static bool IsSpecialAttribute(const std::string &osName)
148 : {
149 138 : return osName == CRS_ATTRIBUTE_NAME || osName == UNIT_ATTRIBUTE_NAME ||
150 84 : osName == DIM_TYPE_ATTRIBUTE_NAME ||
151 138 : osName == DIM_DIRECTION_ATTRIBUTE_NAME ||
152 90 : osName == GDAL_ATTRIBUTE_NAME;
153 : }
154 :
155 : /************************************************************************/
156 : /* TileDBAttributeHolder::GetAttributesImpl() */
157 : /************************************************************************/
158 :
159 : std::vector<std::shared_ptr<GDALAttribute>>
160 44 : TileDBAttributeHolder::GetAttributesImpl(CSLConstList papszOptions) const
161 : {
162 44 : if (!EnsureOpenAs(TILEDB_READ))
163 0 : return {};
164 :
165 : const bool bShowAll =
166 44 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "SHOW_ALL", "NO"));
167 :
168 : try
169 : {
170 88 : std::vector<std::shared_ptr<GDALAttribute>> apoAttributes;
171 44 : const uint64_t nAttributes = metadata_num();
172 88 : auto poSelf = AsAttributeHolderSharedPtr();
173 98 : for (uint64_t i = 0; i < nAttributes; ++i)
174 : {
175 108 : std::string key;
176 : tiledb_datatype_t value_type;
177 : uint32_t value_num;
178 : const void *value;
179 54 : get_metadata_from_index(i, &key, &value_type, &value_num, &value);
180 54 : if (bShowAll || !IsSpecialAttribute(key))
181 : {
182 : auto poAttr =
183 96 : CreateAttribute(poSelf, key, value_type, value_num, value);
184 48 : if (poAttr)
185 : {
186 48 : apoAttributes.emplace_back(std::move(poAttr));
187 48 : m_oMapAttributes[key] = apoAttributes.back();
188 : }
189 : }
190 : }
191 44 : return apoAttributes;
192 : }
193 0 : catch (const std::exception &e)
194 : {
195 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetAttributes() failed with: %s",
196 0 : e.what());
197 0 : return {};
198 : }
199 : }
200 :
201 : /************************************************************************/
202 : /* TileDBAttributeHolder::DeleteAttributeImpl() */
203 : /************************************************************************/
204 :
205 3 : bool TileDBAttributeHolder::DeleteAttributeImpl(const std::string &osName,
206 : CSLConstList /*papszOptions*/)
207 : {
208 3 : if (!IIsWritable())
209 : {
210 1 : CPLError(CE_Failure, CPLE_NotSupported,
211 : "Dataset not open in update mode");
212 1 : return false;
213 : }
214 :
215 2 : if (!EnsureOpenAs(TILEDB_WRITE))
216 0 : return false;
217 :
218 2 : auto oIter = m_oMapAttributes.find(osName);
219 :
220 : try
221 : {
222 2 : delete_metadata(osName);
223 :
224 2 : if (oIter != m_oMapAttributes.end())
225 : {
226 1 : oIter->second->Deleted();
227 1 : m_oMapAttributes.erase(oIter);
228 : }
229 2 : return true;
230 : }
231 0 : catch (const std::exception &e)
232 : {
233 0 : CPLError(CE_Failure, CPLE_AppDefined,
234 0 : "DeleteAttribute() failed with: %s", e.what());
235 0 : return false;
236 : }
237 : }
238 :
239 : /************************************************************************/
240 : /* TileDBAttributeHolder::GetMetadata() */
241 : /************************************************************************/
242 :
243 32 : bool TileDBAttributeHolder::GetMetadata(const std::string &key,
244 : tiledb_datatype_t *value_type,
245 : uint32_t *value_num,
246 : const void **value) const
247 : {
248 32 : if (!EnsureOpenAs(TILEDB_READ))
249 0 : return false;
250 : try
251 : {
252 32 : get_metadata(key, value_type, value_num, value);
253 32 : return *value != nullptr;
254 : }
255 0 : catch (const std::exception &e)
256 : {
257 0 : CPLError(CE_Failure, CPLE_AppDefined, "GetMetadata() failed with: %s",
258 0 : e.what());
259 0 : return false;
260 : }
261 : }
262 :
263 : /************************************************************************/
264 : /* TileDBAttributeHolder::PutMetadata() */
265 : /************************************************************************/
266 :
267 13 : bool TileDBAttributeHolder::PutMetadata(const std::string &key,
268 : tiledb_datatype_t value_type,
269 : uint32_t value_num, const void *value)
270 : {
271 13 : if (!EnsureOpenAs(TILEDB_WRITE))
272 0 : return false;
273 : try
274 : {
275 13 : put_metadata(key, value_type, value_num, value);
276 13 : return true;
277 : }
278 0 : catch (const std::exception &e)
279 : {
280 0 : CPLError(CE_Failure, CPLE_AppDefined, "PutMetadata() failed with: %s",
281 0 : e.what());
282 0 : return false;
283 : }
284 : }
|