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 : /* TileDBSingleArrayGroup::SanitizeNameForPath() */
17 : /************************************************************************/
18 :
19 : /* static */
20 34 : std::string TileDBSharedResource::SanitizeNameForPath(const std::string &osName)
21 : {
22 34 : return CPLLaunderForFilenameSafe(osName);
23 : }
24 :
25 : /************************************************************************/
26 : /* TileDBArrayGroup::Create() */
27 : /************************************************************************/
28 :
29 1 : std::shared_ptr<GDALGroup> TileDBArrayGroup::Create(
30 : const std::shared_ptr<TileDBSharedResource> &poSharedResource,
31 : const std::string &osArrayPath)
32 : {
33 : auto poTileDBArray = std::make_unique<tiledb::Array>(
34 2 : poSharedResource->GetCtx(), osArrayPath, TILEDB_READ);
35 2 : auto schema = poTileDBArray->schema();
36 1 : const auto nAttributes = schema.attribute_num();
37 2 : const std::string osBaseName(CPLGetFilename(osArrayPath.c_str()));
38 2 : std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
39 1 : if (nAttributes == 1)
40 : {
41 : // Skip variable_sized attributes
42 0 : if (schema.attribute(0).variable_sized())
43 : {
44 0 : CPLDebug("TileDB",
45 : "Skipping unsupported variable-size "
46 : "attribute '%s'",
47 0 : schema.attribute(0).name().c_str());
48 0 : return std::make_shared<TileDBArrayGroup>(apoArrays);
49 : }
50 : auto poArray = TileDBArray::OpenFromDisk(poSharedResource, nullptr, "/",
51 0 : osBaseName, std::string(),
52 0 : osArrayPath, nullptr);
53 0 : if (!poArray)
54 0 : return nullptr;
55 0 : apoArrays.emplace_back(poArray);
56 : }
57 : else
58 : {
59 4 : for (uint32_t i = 0; i < nAttributes; ++i)
60 : {
61 3 : const auto &attr = schema.attribute(i);
62 :
63 6 : auto osFullName = osBaseName + "." + attr.name();
64 :
65 : // Skip variable_sized attributes
66 3 : if (attr.variable_sized())
67 : {
68 0 : CPLDebug("TileDB",
69 : "Skipping unsupported variable-size "
70 : "attribute '%s'",
71 : osFullName.c_str());
72 0 : continue;
73 : }
74 : auto poArray = TileDBArray::OpenFromDisk(
75 3 : poSharedResource, nullptr, "/", osFullName, attr.name(),
76 6 : osArrayPath, nullptr);
77 3 : if (!poArray)
78 0 : return nullptr;
79 3 : apoArrays.emplace_back(poArray);
80 : }
81 : }
82 1 : return std::make_shared<TileDBArrayGroup>(apoArrays);
83 : }
84 :
85 : /************************************************************************/
86 : /* TileDBArrayGroup::GetMDArrayNames() */
87 : /************************************************************************/
88 :
89 : std::vector<std::string>
90 2 : TileDBArrayGroup::GetMDArrayNames(CSLConstList /*papszOptions*/) const
91 : {
92 2 : std::vector<std::string> aosNames;
93 8 : for (const auto &poArray : m_apoArrays)
94 6 : aosNames.emplace_back(poArray->GetName());
95 2 : return aosNames;
96 : }
97 :
98 : /************************************************************************/
99 : /* TileDBArrayGroup::OpenMDArray() */
100 : /************************************************************************/
101 :
102 : std::shared_ptr<GDALMDArray>
103 1 : TileDBArrayGroup::OpenMDArray(const std::string &osName,
104 : CSLConstList /*papszOptions*/) const
105 : {
106 1 : for (const auto &poArray : m_apoArrays)
107 : {
108 1 : if (poArray->GetName() == osName)
109 1 : return poArray;
110 : }
111 0 : return nullptr;
112 : }
113 :
114 : /************************************************************************/
115 : /* OpenMultiDimensional() */
116 : /************************************************************************/
117 :
118 30 : GDALDataset *TileDBDataset::OpenMultiDimensional(GDALOpenInfo *poOpenInfo)
119 : {
120 : const char *pszConfig =
121 30 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_CONFIG");
122 :
123 30 : std::unique_ptr<tiledb::Context> pCtxt;
124 30 : if (pszConfig != nullptr)
125 : {
126 0 : tiledb::Config cfg(pszConfig);
127 0 : pCtxt.reset(new tiledb::Context(cfg));
128 : }
129 : else
130 : {
131 30 : pCtxt.reset(new tiledb::Context());
132 : }
133 :
134 : const std::string osPath =
135 60 : TileDBDataset::VSI_to_tiledb_uri(poOpenInfo->pszFilename);
136 :
137 30 : const auto eType = tiledb::Object::object(*(pCtxt.get()), osPath).type();
138 :
139 : auto poSharedResource = std::make_shared<TileDBSharedResource>(
140 60 : std::move(pCtxt), poOpenInfo->eAccess == GA_Update);
141 :
142 60 : poSharedResource->SetDumpStats(CPLTestBool(
143 30 : CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "STATS", "FALSE")));
144 :
145 : const char *pszTimestamp =
146 30 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_TIMESTAMP");
147 30 : if (pszTimestamp)
148 0 : poSharedResource->SetTimestamp(
149 0 : std::strtoull(pszTimestamp, nullptr, 10));
150 :
151 30 : std::shared_ptr<GDALGroup> poRG;
152 30 : if (eType == tiledb::Object::Type::Array)
153 : {
154 1 : poRG = TileDBArrayGroup::Create(poSharedResource, osPath);
155 : }
156 : else
157 : {
158 58 : poRG = TileDBGroup::OpenFromDisk(poSharedResource, std::string(), "/",
159 29 : osPath);
160 : }
161 30 : if (!poRG)
162 0 : return nullptr;
163 :
164 30 : auto poDS = new TileDBMultiDimDataset(poRG);
165 30 : poDS->SetDescription(poOpenInfo->pszFilename);
166 30 : return poDS;
167 : }
168 :
169 : /************************************************************************/
170 : /* CreateMultiDimensional() */
171 : /************************************************************************/
172 :
173 : GDALDataset *
174 25 : TileDBDataset::CreateMultiDimensional(const char *pszFilename,
175 : CSLConstList /*papszRootGroupOptions*/,
176 : CSLConstList papszOptions)
177 : {
178 25 : const char *pszConfig = CSLFetchNameValue(papszOptions, "TILEDB_CONFIG");
179 :
180 25 : std::unique_ptr<tiledb::Context> pCtxt;
181 25 : if (pszConfig != nullptr)
182 : {
183 0 : tiledb::Config cfg(pszConfig);
184 0 : pCtxt.reset(new tiledb::Context(cfg));
185 : }
186 : else
187 : {
188 25 : pCtxt.reset(new tiledb::Context());
189 : }
190 :
191 50 : const std::string osPath = TileDBDataset::VSI_to_tiledb_uri(pszFilename);
192 :
193 : auto poSharedResource =
194 50 : std::make_shared<TileDBSharedResource>(std::move(pCtxt), true);
195 :
196 25 : poSharedResource->SetDumpStats(
197 25 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "STATS", "FALSE")));
198 :
199 : const char *pszTimestamp =
200 25 : CSLFetchNameValue(papszOptions, "TILEDB_TIMESTAMP");
201 25 : if (pszTimestamp)
202 0 : poSharedResource->SetTimestamp(
203 0 : std::strtoull(pszTimestamp, nullptr, 10));
204 :
205 : auto poRG =
206 75 : TileDBGroup::CreateOnDisk(poSharedResource, std::string(), "/", osPath);
207 25 : if (!poRG)
208 0 : return nullptr;
209 :
210 25 : auto poDS = new TileDBMultiDimDataset(poRG);
211 25 : poDS->SetDescription(pszFilename);
212 25 : return poDS;
213 : }
214 :
215 : /************************************************************************/
216 : /* TileDBDimension::GetIndexingVariable() */
217 : /************************************************************************/
218 :
219 29 : std::shared_ptr<GDALMDArray> TileDBDimension::GetIndexingVariable() const
220 : {
221 29 : return m_poIndexingVariable;
222 : }
223 :
224 : /************************************************************************/
225 : /* TileDBMultiDimDataset::GetRootGroup() */
226 : /************************************************************************/
227 :
228 58 : std::shared_ptr<GDALGroup> TileDBMultiDimDataset::GetRootGroup() const
229 : {
230 58 : return m_poRG;
231 : }
|