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 68 : CPLString osSanitized(osName);
23 : // Reserved characters on Windows
24 340 : for (char ch : {'<', '>', ':', '"', '/', '\\', '|', '?', '*'})
25 306 : osSanitized.replaceAll(ch, '_');
26 34 : std::string osRet = std::move(osSanitized);
27 68 : return osRet;
28 : }
29 :
30 : /************************************************************************/
31 : /* TileDBArrayGroup::Create() */
32 : /************************************************************************/
33 :
34 1 : std::shared_ptr<GDALGroup> TileDBArrayGroup::Create(
35 : const std::shared_ptr<TileDBSharedResource> &poSharedResource,
36 : const std::string &osArrayPath)
37 : {
38 : auto poTileDBArray = std::make_unique<tiledb::Array>(
39 2 : poSharedResource->GetCtx(), osArrayPath, TILEDB_READ);
40 2 : auto schema = poTileDBArray->schema();
41 1 : const auto nAttributes = schema.attribute_num();
42 2 : const std::string osBaseName(CPLGetFilename(osArrayPath.c_str()));
43 2 : std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
44 1 : if (nAttributes == 1)
45 : {
46 : auto poArray = TileDBArray::OpenFromDisk(poSharedResource, nullptr, "/",
47 0 : osBaseName, std::string(),
48 0 : osArrayPath, nullptr);
49 0 : if (!poArray)
50 0 : return nullptr;
51 0 : apoArrays.emplace_back(poArray);
52 : }
53 : else
54 : {
55 4 : for (uint32_t i = 0; i < nAttributes; ++i)
56 : {
57 : auto poArray = TileDBArray::OpenFromDisk(
58 : poSharedResource, nullptr, "/",
59 6 : osBaseName + "." + schema.attribute(i).name(),
60 12 : schema.attribute(i).name(), osArrayPath, nullptr);
61 3 : if (!poArray)
62 0 : return nullptr;
63 3 : apoArrays.emplace_back(poArray);
64 : }
65 : }
66 1 : return std::make_shared<TileDBArrayGroup>(apoArrays);
67 : }
68 :
69 : /************************************************************************/
70 : /* TileDBArrayGroup::GetMDArrayNames() */
71 : /************************************************************************/
72 :
73 : std::vector<std::string>
74 2 : TileDBArrayGroup::GetMDArrayNames(CSLConstList /*papszOptions*/) const
75 : {
76 2 : std::vector<std::string> aosNames;
77 8 : for (const auto &poArray : m_apoArrays)
78 6 : aosNames.emplace_back(poArray->GetName());
79 2 : return aosNames;
80 : }
81 :
82 : /************************************************************************/
83 : /* TileDBArrayGroup::OpenMDArray() */
84 : /************************************************************************/
85 :
86 : std::shared_ptr<GDALMDArray>
87 1 : TileDBArrayGroup::OpenMDArray(const std::string &osName,
88 : CSLConstList /*papszOptions*/) const
89 : {
90 1 : for (const auto &poArray : m_apoArrays)
91 : {
92 1 : if (poArray->GetName() == osName)
93 1 : return poArray;
94 : }
95 0 : return nullptr;
96 : }
97 :
98 : /************************************************************************/
99 : /* OpenMultiDimensional() */
100 : /************************************************************************/
101 :
102 30 : GDALDataset *TileDBDataset::OpenMultiDimensional(GDALOpenInfo *poOpenInfo)
103 : {
104 : const char *pszConfig =
105 30 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_CONFIG");
106 :
107 30 : std::unique_ptr<tiledb::Context> pCtxt;
108 30 : if (pszConfig != nullptr)
109 : {
110 0 : tiledb::Config cfg(pszConfig);
111 0 : pCtxt.reset(new tiledb::Context(cfg));
112 : }
113 : else
114 : {
115 30 : pCtxt.reset(new tiledb::Context());
116 : }
117 :
118 : const std::string osPath =
119 60 : TileDBDataset::VSI_to_tiledb_uri(poOpenInfo->pszFilename);
120 :
121 30 : const auto eType = tiledb::Object::object(*(pCtxt.get()), osPath).type();
122 :
123 : auto poSharedResource = std::make_shared<TileDBSharedResource>(
124 60 : std::move(pCtxt), poOpenInfo->eAccess == GA_Update);
125 :
126 60 : poSharedResource->SetDumpStats(CPLTestBool(
127 30 : CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "STATS", "FALSE")));
128 :
129 : const char *pszTimestamp =
130 30 : CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILEDB_TIMESTAMP");
131 30 : if (pszTimestamp)
132 0 : poSharedResource->SetTimestamp(
133 0 : std::strtoull(pszTimestamp, nullptr, 10));
134 :
135 30 : std::shared_ptr<GDALGroup> poRG;
136 30 : if (eType == tiledb::Object::Type::Array)
137 : {
138 1 : poRG = TileDBArrayGroup::Create(poSharedResource, osPath);
139 : }
140 : else
141 : {
142 58 : poRG = TileDBGroup::OpenFromDisk(poSharedResource, std::string(), "/",
143 29 : osPath);
144 : }
145 30 : if (!poRG)
146 0 : return nullptr;
147 :
148 30 : auto poDS = new TileDBMultiDimDataset(poRG);
149 30 : poDS->SetDescription(poOpenInfo->pszFilename);
150 30 : return poDS;
151 : }
152 :
153 : /************************************************************************/
154 : /* CreateMultiDimensional() */
155 : /************************************************************************/
156 :
157 : GDALDataset *
158 25 : TileDBDataset::CreateMultiDimensional(const char *pszFilename,
159 : CSLConstList /*papszRootGroupOptions*/,
160 : CSLConstList papszOptions)
161 : {
162 25 : const char *pszConfig = CSLFetchNameValue(papszOptions, "TILEDB_CONFIG");
163 :
164 25 : std::unique_ptr<tiledb::Context> pCtxt;
165 25 : if (pszConfig != nullptr)
166 : {
167 0 : tiledb::Config cfg(pszConfig);
168 0 : pCtxt.reset(new tiledb::Context(cfg));
169 : }
170 : else
171 : {
172 25 : pCtxt.reset(new tiledb::Context());
173 : }
174 :
175 50 : const std::string osPath = TileDBDataset::VSI_to_tiledb_uri(pszFilename);
176 :
177 : auto poSharedResource =
178 50 : std::make_shared<TileDBSharedResource>(std::move(pCtxt), true);
179 :
180 25 : poSharedResource->SetDumpStats(
181 25 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "STATS", "FALSE")));
182 :
183 : const char *pszTimestamp =
184 25 : CSLFetchNameValue(papszOptions, "TILEDB_TIMESTAMP");
185 25 : if (pszTimestamp)
186 0 : poSharedResource->SetTimestamp(
187 0 : std::strtoull(pszTimestamp, nullptr, 10));
188 :
189 : auto poRG =
190 75 : TileDBGroup::CreateOnDisk(poSharedResource, std::string(), "/", osPath);
191 25 : if (!poRG)
192 0 : return nullptr;
193 :
194 25 : auto poDS = new TileDBMultiDimDataset(poRG);
195 25 : poDS->SetDescription(pszFilename);
196 25 : return poDS;
197 : }
|