@@ -210,6 +210,9 @@ void TileDBVCFDataset::create(const CreationParams& params) {
210210
211211 check_attribute_names (params.extra_attributes );
212212
213+ // Validate the uri is appropriate for the backend it is going to write to
214+ utils::validate_uri (params.uri , ctx);
215+
213216 // Create root group, which creates the root directory
214217 create_group (ctx, params.uri );
215218
@@ -317,29 +320,37 @@ void TileDBVCFDataset::create_empty_metadata(
317320 create_group (ctx, metadata_group_uri (root_uri));
318321 create_sample_header_array (ctx, root_uri, checksum);
319322
320- // Group assets use full paths for tiledb cloud, relative paths otherwise
321- bool relative = !cloud_dataset (root_uri);
323+ if (ctx.data_protocol (root_uri) == tiledb::Context::DataProtocol::v2) {
324+ // Group assets use full paths for tiledb cloud, relative paths otherwise
325+ bool relative = !cloud_dataset (root_uri);
322326
323- // Add arrays to the root group
324- // We add the vcf_header array to the root group to simplify array opening.
325- Group root_group (ctx, root_uri, TILEDB_WRITE );
326- auto array_uri = vcf_headers_uri (root_uri, relative);
327- LOG_DEBUG (
328- " Adding array name='{}' uri='{}' to group uri='{}'" ,
329- VCF_HEADER_ARRAY ,
330- array_uri,
331- root_uri);
332- root_group.add_member (array_uri, relative, VCF_HEADER_ARRAY );
333-
334- // Add the metadata group to the root group, so it will be deleted when the
335- // dataset is deleted.
336- auto group_uri = metadata_group_uri (root_uri, relative);
337- LOG_DEBUG (
338- " Adding group name='{}' uri='{}' to group uri='{}'" ,
339- METADATA_GROUP ,
340- group_uri,
341- root_uri);
342- root_group.add_member (group_uri, relative, METADATA_GROUP );
327+ // Add arrays to the root group
328+ // We add the vcf_header array to the root group to simplify array opening.
329+ // Until 0.38.1 the `vcf_headers` array was created under the `metadata`
330+ // group but registered under to root group. This is incompatible with the
331+ // Carrara data model. Now the `vcf_headers` will be registered under the
332+ // `metadata` group in which physically exists.
333+ Group root_group (ctx, root_uri, TILEDB_WRITE );
334+ Group metadata_group (ctx, metadata_group_uri (root_uri), TILEDB_WRITE );
335+
336+ auto array_uri = vcf_headers_uri_v2 (root_uri, relative);
337+ LOG_DEBUG (
338+ " Adding array name='{}' uri='{}' to group uri='{}'" ,
339+ VCF_HEADER_ARRAY ,
340+ array_uri,
341+ metadata_group_uri (root_uri));
342+ metadata_group.add_member (array_uri, relative, VCF_HEADER_ARRAY );
343+
344+ // Add the metadata group to the root group, so it will be deleted when the
345+ // dataset is deleted.
346+ auto group_uri = metadata_group_uri (root_uri, relative);
347+ LOG_DEBUG (
348+ " Adding group name='{}' uri='{}' to group uri='{}'" ,
349+ METADATA_GROUP ,
350+ group_uri,
351+ root_uri);
352+ root_group.add_member (group_uri, relative, METADATA_GROUP );
353+ }
343354}
344355
345356void TileDBVCFDataset::create_empty_data_array (
@@ -458,17 +469,19 @@ void TileDBVCFDataset::create_empty_data_array(
458469
459470 Array::create (data_array_uri (root_uri), schema);
460471
461- // Add the array to the root group
462- // Group assests use full paths for tiledb cloud, relative paths otherwise
463- bool relative = !cloud_dataset (root_uri);
464- auto array_uri = data_array_uri (root_uri, relative);
465- LOG_DEBUG (
466- " Adding array name='{}' uri='{}' to group uri='{}'" ,
467- DATA_ARRAY ,
468- array_uri,
469- root_uri);
470- Group root_group (ctx, root_uri, TILEDB_WRITE );
471- root_group.add_member (array_uri, relative, DATA_ARRAY );
472+ if (ctx.data_protocol (root_uri) == tiledb::Context::DataProtocol::v2) {
473+ // Add the array to the root group
474+ // Group assests use full paths for tiledb cloud, relative paths otherwise
475+ bool relative = !cloud_dataset (root_uri);
476+ auto array_uri = data_array_uri (root_uri, relative);
477+ LOG_DEBUG (
478+ " Adding array name='{}' uri='{}' to group uri='{}'" ,
479+ DATA_ARRAY ,
480+ array_uri,
481+ root_uri);
482+ Group root_group (ctx, root_uri, TILEDB_WRITE );
483+ root_group.add_member (array_uri, relative, DATA_ARRAY );
484+ }
472485}
473486
474487void TileDBVCFDataset::create_sample_header_array (
@@ -1074,11 +1087,116 @@ std::unique_ptr<tiledb::Array> TileDBVCFDataset::open_array(
10741087
10751088std::unique_ptr<tiledb::Array> TileDBVCFDataset::open_vcf_array (
10761089 tiledb_query_type_t query_type) {
1077- return open_array (
1078- query_type,
1079- VCF_HEADER_ARRAY ,
1080- vcf_headers_uri (root_uri_),
1081- vcf_headers_uri (root_uri_, false , true ));
1090+ std::string array_uri;
1091+
1092+ // Until 0.38.1 `vcf_headers` array was registered under the root group.
1093+ // Now it is registered under `metadata` group in which physically exist.
1094+ std::unique_ptr<tiledb::Group> root_group;
1095+ try {
1096+ root_group = std::make_unique<tiledb::Group>(*ctx_, root_uri_, TILEDB_READ );
1097+ } catch (const tiledb::TileDBError& ex) {
1098+ throw std::runtime_error (
1099+ " Cannot open TileDB-VCF dataset; dataset '" + root_uri_ +
1100+ " ' or its metadata does not exist. TileDB error message: " +
1101+ std::string (ex.what ()));
1102+ }
1103+
1104+ // We are opening a legacy dataset where the `vcf_headers` array is
1105+ // registered under the root group
1106+ if (utils::has_member (*root_group, VCF_HEADER_ARRAY )) {
1107+ if (ctx_->data_protocol (root_uri_) == tiledb::Context::DataProtocol::v3) {
1108+ // This is an legacy dataset registered under TileDB Carrara
1109+ throw std::runtime_error (
1110+ " Cannot open TileDB-VCF dataset; dataset '" + root_uri_ +
1111+ " ' data format is not supported by Carrara. To migrate it remove "
1112+ " the `vcf_headers` array from the root group and add it to the "
1113+ " `metadata` group using the physical path of the dataset." );
1114+ }
1115+
1116+ LOG_WARN (
1117+ " **DEPRECATED** Accessing {} registered under root group. To migrate "
1118+ " it remove the `vcf_headers` array from the root group and add it to "
1119+ " the `metadata` group using the physical path of the dataset." ,
1120+ VCF_HEADER_ARRAY );
1121+ LOG_DEBUG (" Fallback to '{}' registered under root group" , VCF_HEADER_ARRAY );
1122+ return open_array (
1123+ query_type,
1124+ VCF_HEADER_ARRAY ,
1125+ vcf_headers_uri (root_uri_),
1126+ vcf_headers_uri (root_uri_, false , true ));
1127+ } else if (utils::has_member (*root_group, METADATA_GROUP )) {
1128+ // Load the `metadata` group
1129+ std::string metadata_uri;
1130+
1131+ // If the group member uri is a cloud uri and the root uri is not,
1132+ // use the non cloud uri instead of the group member uri
1133+ if (!cloud_dataset (root_uri_) &&
1134+ cloud_dataset (root_group->member (METADATA_GROUP ).uri ())) {
1135+ metadata_uri = metadata_group_uri (root_uri_);
1136+ LOG_DEBUG (
1137+ " Override group uri '{}'. Open '{}' using uri path '{}'" ,
1138+ root_group->member (METADATA_GROUP ).uri (),
1139+ METADATA_GROUP ,
1140+ metadata_uri);
1141+ } else {
1142+ metadata_uri = root_group->member (METADATA_GROUP ).uri ();
1143+ LOG_DEBUG (" Open '{}' using group uri '{}'" , METADATA_GROUP , metadata_uri);
1144+ }
1145+
1146+ Group metadata_group (*ctx_, metadata_uri, TILEDB_READ );
1147+
1148+ if (utils::has_member (metadata_group, VCF_HEADER_ARRAY )) {
1149+ // If the group member uri is a cloud uri and the root uri is not,
1150+ // use the uri_path instead of the group member uri
1151+ if (!cloud_dataset (root_uri_) &&
1152+ cloud_dataset (metadata_group.member (VCF_HEADER_ARRAY ).uri ())) {
1153+ array_uri = vcf_headers_uri (root_uri_);
1154+ LOG_DEBUG (
1155+ " Override group uri '{}'. Open '{}' using uri path '{}'" ,
1156+ metadata_group.member (VCF_HEADER_ARRAY ).uri (),
1157+ VCF_HEADER_ARRAY ,
1158+ array_uri);
1159+ } else {
1160+ array_uri = metadata_group.member (VCF_HEADER_ARRAY ).uri ();
1161+ LOG_DEBUG (
1162+ " Open '{}' using array uri '{}'" , VCF_HEADER_ARRAY , array_uri);
1163+ }
1164+ } else {
1165+ array_uri = vcf_headers_uri (root_uri_);
1166+ LOG_DEBUG (
1167+ " '{}' is not registered under '{}'. Open '{}' using array uri '{}'" ,
1168+ VCF_HEADER_ARRAY ,
1169+ METADATA_GROUP ,
1170+ VCF_HEADER_ARRAY ,
1171+ array_uri);
1172+ }
1173+ } else {
1174+ // The group seems to have to member added. Fallback to absolute path
1175+ array_uri = vcf_headers_uri (root_uri_);
1176+ LOG_DEBUG (
1177+ " '{}' and '{}' not registered under root group. Open '{}' using array "
1178+ " uri '{}'" ,
1179+ VCF_HEADER_ARRAY ,
1180+ METADATA_GROUP ,
1181+ VCF_HEADER_ARRAY ,
1182+ array_uri);
1183+ }
1184+
1185+ try {
1186+ // Open the array with the uri detemined above
1187+ return std::unique_ptr<Array>(new Array (*ctx_, array_uri, query_type));
1188+ } catch (const tiledb::TileDBError& ex) {
1189+ try {
1190+ // Last chance, try the legacy uri to support legacy cloud arrays
1191+ return std::unique_ptr<Array>(new Array (
1192+ *ctx_, vcf_headers_uri (root_uri_, false , true ), query_type));
1193+ } catch (const tiledb::TileDBError& ex) {
1194+ throw std::runtime_error (
1195+ " Cannot open TileDB-VCF dataset; dataset '" + root_uri_ +
1196+ " ' or its metadata does not exist. TileDB error message: " +
1197+ std::string (ex.what ()));
1198+ }
1199+ }
10821200}
10831201
10841202std::shared_ptr<tiledb::Array> TileDBVCFDataset::open_data_array (
@@ -2095,6 +2213,12 @@ std::string TileDBVCFDataset::vcf_headers_uri(
20952213 return utils::uri_join (group, VCF_HEADER_ARRAY , delimiter);
20962214}
20972215
2216+ std::string TileDBVCFDataset::vcf_headers_uri_v2 (
2217+ const std::string& root_uri, bool relative) {
2218+ auto root = relative ? " " : metadata_group_uri (root_uri, relative, false );
2219+ return utils::uri_join (root, VCF_HEADER_ARRAY , ' /' );
2220+ }
2221+
20982222bool TileDBVCFDataset::cloud_dataset (const std::string& root_uri) {
20992223 return utils::starts_with (root_uri, " tiledb://" );
21002224}
0 commit comments