diff --git a/cmake/oxidize.cmake b/cmake/oxidize.cmake index 8d456880140..4dde0cb17b6 100644 --- a/cmake/oxidize.cmake +++ b/cmake/oxidize.cmake @@ -306,10 +306,9 @@ if (TILEDB_RUST) set(bridge_h_src "${bridge_generated_dir}/src/${bridge}.h") set(bridge_cc_src "${bridge_generated_dir}/src/${bridge}.cc") + string(REPLACE "-" "_" bridge_sanitize_relpath ${bridge_sanitize_relpath}) set(bridge_h_dst "${OXIDIZE_INCLUDE_DIR}/tiledb/oxidize/${bridge_sanitize_relpath}.h") set(bridge_cc_dst "${OXIDIZE_INCLUDE_DIR}/tiledb/oxidize/${bridge_sanitize_relpath}.cc") - string(REPLACE "-" "_" bridge_h_dst ${bridge_h_dst}) - string(REPLACE "-" "_" bridge_cc_dst ${bridge_cc_dst}) cmake_path(GET bridge_h_dst PARENT_PATH bridge_sanitize_dirname) diff --git a/test/src/unit-enumerations.cc b/test/src/unit-enumerations.cc index 3a9ad51f113..f9c5dc11a3b 100644 --- a/test/src/unit-enumerations.cc +++ b/test/src/unit-enumerations.cc @@ -1244,7 +1244,7 @@ TEST_CASE_METHOD( auto enmr_name = schema->attribute("attr1")->get_enumeration_name(); REQUIRE(enmr_name.has_value()); - auto enmr_path = schema->get_enumeration_path_name(enmr_name.value()); + auto enmr_path = schema->get_enumeration_path_name(enmr_name.value().get()); auto loaded = ad->load_enumerations_from_paths({enmr_path}, enc_key_, memory_tracker_); @@ -1292,7 +1292,7 @@ TEST_CASE_METHOD( auto ad = get_array_directory(); auto enmr_name = schema->attribute("attr1")->get_enumeration_name(); - auto enmr_path = schema->get_enumeration_path_name(enmr_name.value()); + auto enmr_path = schema->get_enumeration_path_name(enmr_name.value().get()); memory_tracker_->set_budget(memory_tracker_->get_memory_usage() + 1); diff --git a/test/support/src/helpers.cc b/test/support/src/helpers.cc index 50ecec1b068..56650b4017e 100644 --- a/test/support/src/helpers.cc +++ b/test/support/src/helpers.cc @@ -1636,7 +1636,13 @@ void schema_equiv( CHECK(a->name() == b->name()); CHECK(a->type() == b->type()); CHECK(a->nullable() == b->nullable()); - CHECK(a->get_enumeration_name() == b->get_enumeration_name()); + + const auto a_enmr = a->get_enumeration_name(), + b_enmr = b->get_enumeration_name(); + CHECK(a_enmr.has_value() == b_enmr.has_value()); + if (a_enmr.has_value() && b_enmr.has_value()) { + CHECK(a_enmr.value().get() == b_enmr.value().get()); + } } CHECK(schema1.capacity() == schema2.capacity()); CHECK(schema1.cell_order() == schema2.cell_order()); diff --git a/tiledb/api/c_api/array_schema/array_schema_api.cc b/tiledb/api/c_api/array_schema/array_schema_api.cc index e559484d217..f447885343e 100644 --- a/tiledb/api/c_api/array_schema/array_schema_api.cc +++ b/tiledb/api/c_api/array_schema/array_schema_api.cc @@ -250,9 +250,9 @@ capi_return_t tiledb_array_schema_get_enumeration_from_attribute_name( return TILEDB_OK; } - array_schema->load_enumeration(ctx, enumeration_name->c_str()); + array_schema->load_enumeration(ctx, enumeration_name->get().c_str()); - auto ptr = array_schema->get_enumeration(enumeration_name->c_str()); + auto ptr = array_schema->get_enumeration(enumeration_name->get().c_str()); *enumeration = tiledb_enumeration_handle_t::make_handle(ptr); return TILEDB_OK; diff --git a/tiledb/api/c_api/attribute/attribute_api_internal.h b/tiledb/api/c_api/attribute/attribute_api_internal.h index c1782111004..bed94a3c18d 100644 --- a/tiledb/api/c_api/attribute/attribute_api_internal.h +++ b/tiledb/api/c_api/attribute/attribute_api_internal.h @@ -187,7 +187,12 @@ struct tiledb_attribute_handle_t * Facade for `Attribute` function */ [[nodiscard]] std::optional get_enumeration_name() const { - return attr_->get_enumeration_name(); + const auto eref = attr_->get_enumeration_name(); + if (eref.has_value()) { + return eref.value().get(); + } else { + return std::nullopt; + } }; /** * Facade for `Attribute` function diff --git a/tiledb/oxidize/cxx-interface/cc/array_schema.cc b/tiledb/oxidize/cxx-interface/cc/array_schema.cc index a9e78ebc9e4..d397072bfb7 100644 --- a/tiledb/oxidize/cxx-interface/cc/array_schema.cc +++ b/tiledb/oxidize/cxx-interface/cc/array_schema.cc @@ -1,9 +1,25 @@ #include "tiledb/oxidize/cxx-interface/cc/array_schema.h" -namespace tiledb::oxidize { - using namespace tiledb::sm; +namespace tiledb::oxidize::sm { + +namespace attribute { + +const std::string* enumeration_name_cxx(const Attribute& attribute) { + std::optional> e = + attribute.get_enumeration_name(); + if (e.has_value()) { + return &e.value().get(); + } else { + return nullptr; + } +} + +} // namespace attribute + +namespace dimension { + void set_domain(Dimension& dimension, rust::Slice domain) { dimension.set_domain(static_cast(domain.data())); } @@ -12,4 +28,6 @@ void set_tile_extent(Dimension& dimension, rust::Slice domain) { dimension.set_tile_extent(static_cast(domain.data())); } -} // namespace tiledb::oxidize +} // namespace dimension + +} // namespace tiledb::oxidize::sm diff --git a/tiledb/oxidize/cxx-interface/cc/array_schema.h b/tiledb/oxidize/cxx-interface/cc/array_schema.h index 2fb623258ca..5e3dfd3213d 100644 --- a/tiledb/oxidize/cxx-interface/cc/array_schema.h +++ b/tiledb/oxidize/cxx-interface/cc/array_schema.h @@ -4,14 +4,27 @@ #include "tiledb/sm/array_schema/dimension.h" #include "tiledb/sm/array_schema/domain.h" -namespace tiledb::oxidize { +namespace tiledb::oxidize::sm { using namespace tiledb::sm; +namespace attribute { + using ConstAttribute = const Attribute; -using ConstDimension = const Dimension; + +const std::string* enumeration_name_cxx(const Attribute& attribute); + +} // namespace attribute + +namespace dimension { + +using namespace tiledb::sm; + +using ConstDimension = const tiledb::sm::Dimension; void set_domain(Dimension& dimension, rust::Slice domain); void set_tile_extent(Dimension& dimension, rust::Slice domain); -} // namespace tiledb::oxidize +} // namespace dimension + +} // namespace tiledb::oxidize::sm diff --git a/tiledb/oxidize/cxx-interface/src/sm/array_schema/mod.rs b/tiledb/oxidize/cxx-interface/src/sm/array_schema/mod.rs index 686a88eb047..03f3ff92b9d 100644 --- a/tiledb/oxidize/cxx-interface/src/sm/array_schema/mod.rs +++ b/tiledb/oxidize/cxx-interface/src/sm/array_schema/mod.rs @@ -6,7 +6,7 @@ mod ffi { type Layout = crate::sm::enums::Layout; } - #[namespace = "tiledb::oxidize"] + #[namespace = "tiledb::oxidize::sm::attribute"] unsafe extern "C++" { include!("tiledb/oxidize/cxx-interface/cc/array_schema.h"); type ConstAttribute; @@ -26,6 +26,9 @@ mod ffi { #[cxx_name = "type"] fn datatype(&self) -> Datatype; + #[namespace = "tiledb::oxidize::sm::attribute"] + fn enumeration_name_cxx(attr: &Attribute) -> *const CxxString; + fn set_cell_val_num(self: Pin<&mut Attribute>, cell_val_num: u32); } @@ -42,10 +45,10 @@ mod ffi { #[cxx_name = "type"] fn datatype(&self) -> Datatype; - #[namespace = "tiledb::oxidize"] + #[namespace = "tiledb::oxidize::sm::dimension"] fn set_domain(dimension: Pin<&mut Dimension>, domain: &[u8]) -> Result<()>; - #[namespace = "tiledb::oxidize"] + #[namespace = "tiledb::oxidize::sm::dimension"] fn set_tile_extent(dimension: Pin<&mut Dimension>, extent: &[u8]) -> Result<()>; } @@ -63,6 +66,19 @@ mod ffi { fn add_dimension(self: Pin<&mut Domain>, dim: SharedPtr); } + #[namespace = "tiledb::sm"] + unsafe extern "C++" { + include!("tiledb/sm/array_schema/enumeration.h"); + + type Enumeration; + + #[cxx_name = "cell_val_num"] + fn cell_val_num_cxx(&self) -> u32; + + #[cxx_name = "type"] + fn datatype(&self) -> Datatype; + } + #[namespace = "tiledb::sm"] unsafe extern "C++" { include!("tiledb/sm/array_schema/array_schema.h"); @@ -117,7 +133,7 @@ use std::str::Utf8Error; use num_traits::ToBytes; -pub use ffi::{ArraySchema, Attribute, ConstAttribute, Datatype, Dimension, Domain}; +pub use ffi::{ArraySchema, Attribute, ConstAttribute, Datatype, Dimension, Domain, Enumeration}; #[derive(Debug)] pub enum CellValNum { @@ -222,6 +238,19 @@ impl Attribute { // SAFETY: non-zero would have been validated by the ArraySchema CellValNum::from_cxx(cxx).unwrap() } + + pub fn enumeration_name_cxx(&self) -> *const cxx::CxxString { + ffi::enumeration_name_cxx(self) + } + + pub fn enumeration_name(&self) -> Option> { + let ptr = self.enumeration_name_cxx(); + if ptr.is_null() { + return None; + } + let cxx = unsafe { &*ptr }; + Some(cxx.to_str()) + } } impl Debug for Attribute { @@ -274,6 +303,22 @@ impl Field<'_> { Self::Dimension(_) => false, } } + + pub fn enumeration_name(&self) -> Option> { + match self { + Self::Attribute(a) => a.enumeration_name(), + Self::Dimension(_) => None, + } + } +} + +impl Enumeration { + pub fn cell_val_num(&self) -> CellValNum { + let cxx = self.cell_val_num_cxx(); + + // SAFETY: non-zero would have been validated by the ArraySchema + CellValNum::from_cxx(cxx).unwrap() + } } impl ArraySchema { diff --git a/tiledb/oxidize/test-support/cxx-interface/src/lib.rs b/tiledb/oxidize/test-support/cxx-interface/src/lib.rs index 23fae4fc8d0..cb95eb40ade 100644 --- a/tiledb/oxidize/test-support/cxx-interface/src/lib.rs +++ b/tiledb/oxidize/test-support/cxx-interface/src/lib.rs @@ -32,7 +32,7 @@ mod ffi { type ResultTile = tiledb_cxx_interface::sm::query::readers::ResultTile; } - #[namespace = "tiledb::oxidize"] + #[namespace = "tiledb::oxidize::sm::attribute"] extern "C++" { type ConstAttribute = tiledb_cxx_interface::sm::array_schema::ConstAttribute; } diff --git a/tiledb/sm/array_schema/array_schema.cc b/tiledb/sm/array_schema/array_schema.cc index 36a83024ee3..6142ef5688d 100644 --- a/tiledb/sm/array_schema/array_schema.cc +++ b/tiledb/sm/array_schema/array_schema.cc @@ -806,13 +806,13 @@ void ArraySchema::add_attribute( auto enmr_name = attr->get_enumeration_name(); if (enmr_name.has_value()) { - // The referenced enumeration must exist when the attribut is added - auto iter = enumeration_map_.find(enmr_name.value()); + // The referenced enumeration must exist when the attribute is added + auto iter = enumeration_map_.find(enmr_name.value().get()); if (iter == enumeration_map_.end()) { std::string msg = "Cannot add attribute; Attribute refers to an " "unknown enumeration named '" + - enmr_name.value() + "'."; + enmr_name.value().get() + "'."; throw ArraySchemaException(msg); } @@ -835,14 +835,15 @@ void ArraySchema::add_attribute( auto enmr = get_enumeration(enmr_name.value()); if (enmr == nullptr) { throw ArraySchemaException( - "Cannot add attribute referencing enumeration '" + enmr_name.value() + + "Cannot add attribute referencing enumeration '" + + enmr_name.value().get() + "' as the enumeration has not been loaded."); } // The +1 here is because of 0 being a valid index into the enumeration. if (datatype_max_integral_value(attr->type()) <= enmr->elem_count()) { throw ArraySchemaException( - "Unable to use enumeration '" + enmr_name.value() + + "Unable to use enumeration '" + enmr_name.value().get() + "' for attribute '" + attr->name() + "' because the attribute's type is not large enough to represent " "all enumeration values."); @@ -1147,7 +1148,7 @@ void ArraySchema::drop_enumeration(const std::string& enmr_name) { if (!attr_enmr_name.has_value()) { continue; } - if (attr_enmr_name.value() == enmr_name) { + if (attr_enmr_name.value().get() == enmr_name) { throw ArraySchemaException( "Unable to drop enumeration '" + enmr_name + "' as it is used by" + " attribute '" + attr->name() + "'."); diff --git a/tiledb/sm/array_schema/attribute.cc b/tiledb/sm/array_schema/attribute.cc index bea1b896894..d69a9c69688 100644 --- a/tiledb/sm/array_schema/attribute.cc +++ b/tiledb/sm/array_schema/attribute.cc @@ -416,7 +416,8 @@ void Attribute::set_enumeration_name(std::optional enmr_name) { enumeration_name_ = enmr_name; } -std::optional Attribute::get_enumeration_name() const { +std::optional> +Attribute::get_enumeration_name() const { return enumeration_name_; } @@ -496,7 +497,7 @@ std::ostream& operator<<(std::ostream& os, const tiledb::sm::Attribute& a) { } if (a.get_enumeration_name().has_value()) { os << std::endl; - os << "- Enumeration name: " << a.get_enumeration_name().value(); + os << "- Enumeration name: " << a.get_enumeration_name().value().get(); } os << std::endl; diff --git a/tiledb/sm/array_schema/attribute.h b/tiledb/sm/array_schema/attribute.h index 780d20be5fa..ca75df7797e 100644 --- a/tiledb/sm/array_schema/attribute.h +++ b/tiledb/sm/array_schema/attribute.h @@ -284,7 +284,8 @@ class Attribute { void set_enumeration_name(std::optional enmr_name); /** Get the enumeration for this attribute. */ - std::optional get_enumeration_name() const; + std::optional> + get_enumeration_name() const; private: /* ********************************* */ diff --git a/tiledb/sm/query/ast/query_ast.cc b/tiledb/sm/query/ast/query_ast.cc index e3528078d84..2e7ee95d7ea 100644 --- a/tiledb/sm/query/ast/query_ast.cc +++ b/tiledb/sm/query/ast/query_ast.cc @@ -199,7 +199,7 @@ void ASTNodeVal::rewrite_for_schema(const ArraySchema& array_schema) { return; } - auto enumeration = array_schema.get_enumeration(enmr_name.value()); + auto enumeration = array_schema.get_enumeration(enmr_name.value().get()); if (!enumeration) { throw std::logic_error( "Missing required enumeration for field '" + field_name_ + "'"); diff --git a/tiledb/sm/query/query.cc b/tiledb/sm/query/query.cc index 48e6ec01175..0fbd84db127 100644 --- a/tiledb/sm/query/query.cc +++ b/tiledb/sm/query/query.cc @@ -825,7 +825,7 @@ Status Query::process() { } auto enmr_name = attr->get_enumeration_name(); if (enmr_name.has_value()) { - deduped_enmr_names.insert(enmr_name.value()); + deduped_enmr_names.insert(enmr_name.value().get()); } } std::vector enmr_names; diff --git a/tiledb/sm/serialization/array_schema.cc b/tiledb/sm/serialization/array_schema.cc index 5178ae396d9..62f5991fc94 100644 --- a/tiledb/sm/serialization/array_schema.cc +++ b/tiledb/sm/serialization/array_schema.cc @@ -412,7 +412,7 @@ void attribute_to_capnp( auto enmr_name = attribute->get_enumeration_name(); if (enmr_name.has_value()) { - attribute_builder->setEnumerationName(enmr_name.value()); + attribute_builder->setEnumerationName(enmr_name.value().get()); } }