Skip to content

Commit c5ed9da

Browse files
[c++] Column abstraction: SOMAAttribute, part 2 (#3426)
* Add concrete class wrapper for TileDB attribute * Misc fixes * Add missing `override` * Remove current_domain flag * Replace string_view with string when returning column name, add current domain checks, replace vector with span when selecting points * Update CMake files * Add description and license * Address review comments * Comply with C.128 * Update libtiledbsoma/src/soma/soma_attribute.cc Co-authored-by: Julia Dark <[email protected]> * Update libtiledbsoma/src/soma/soma_attribute.h Co-authored-by: Julia Dark <[email protected]> --------- Co-authored-by: Julia Dark <[email protected]>
1 parent 9e7a461 commit c5ed9da

File tree

5 files changed

+285
-0
lines changed

5 files changed

+285
-0
lines changed

libtiledbsoma/src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_library(TILEDB_SOMA_OBJECTS OBJECT
3434
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_group.cc
3535
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_object.cc
3636
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_column.cc
37+
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_attribute.cc
3738
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_dimension.cc
3839
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_collection.cc
3940
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_experiment.cc
@@ -209,6 +210,7 @@ install(FILES
209210
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_array.h
210211
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_group.h
211212
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_column.h
213+
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_attribute.h
212214
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_dimension.h
213215
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_collection.h
214216
${CMAKE_CURRENT_SOURCE_DIR}/soma/soma_dataframe.h
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* @file soma_attribute.cc
3+
*
4+
* @section LICENSE
5+
*
6+
* The MIT License
7+
*
8+
* @copyright Copyright (c) 2024-2025 TileDB, Inc.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*
28+
* @section DESCRIPTION
29+
*
30+
* This file defines the SOMAAttribute class.
31+
*/
32+
33+
#include "soma_attribute.h"
34+
35+
namespace tiledbsoma {
36+
std::shared_ptr<SOMAAttribute> SOMAAttribute::create(
37+
std::shared_ptr<Context> ctx,
38+
ArrowSchema* schema,
39+
std::string_view type_metadata,
40+
PlatformConfig platform_config) {
41+
auto attribute = ArrowAdapter::tiledb_attribute_from_arrow_schema(
42+
ctx, schema, type_metadata, platform_config);
43+
44+
return std::make_shared<SOMAAttribute>(
45+
SOMAAttribute(attribute.first, attribute.second));
46+
}
47+
48+
void SOMAAttribute::_set_dim_points(
49+
const std::unique_ptr<ManagedQuery>&,
50+
const SOMAContext&,
51+
const std::any&) const {
52+
throw TileDBSOMAError(std::format(
53+
"[SOMAAttribute][_set_dim_points] Column with name {} is not an index "
54+
"column",
55+
name()));
56+
}
57+
58+
void SOMAAttribute::_set_dim_ranges(
59+
const std::unique_ptr<ManagedQuery>&,
60+
const SOMAContext&,
61+
const std::any&) const {
62+
throw TileDBSOMAError(std::format(
63+
"[SOMAAttribute][_set_dim_ranges] Column with name {} is not an index "
64+
"column",
65+
name()));
66+
}
67+
68+
void SOMAAttribute::_set_current_domain_slot(
69+
NDRectangle&, std::span<const std::any>) const {
70+
throw TileDBSOMAError(std::format(
71+
"[SOMAAttribute][_set_current_domain_slot] Column with name {} is not "
72+
"an index column",
73+
name()));
74+
}
75+
76+
std::pair<bool, std::string> SOMAAttribute::_can_set_current_domain_slot(
77+
std::optional<NDRectangle>&, std::span<const std::any>) const {
78+
throw TileDBSOMAError(std::format(
79+
"[SOMAAttribute][_set_current_domain_slot] Column with name {} is not "
80+
"an index column",
81+
name()));
82+
};
83+
84+
std::any SOMAAttribute::_core_domain_slot() const {
85+
throw TileDBSOMAError(std::format(
86+
"[SOMAAttribute][_core_domain_slot] Column with name {} is not an "
87+
"index column",
88+
name()));
89+
}
90+
91+
std::any SOMAAttribute::_non_empty_domain_slot(Array&) const {
92+
throw TileDBSOMAError(std::format(
93+
"[SOMAAttribute][_non_empty_domain_slot] Column with name {} is not an "
94+
"index column",
95+
name()));
96+
}
97+
98+
std::any SOMAAttribute::_core_current_domain_slot(
99+
const SOMAContext&, Array&) const {
100+
throw TileDBSOMAError(std::format(
101+
"[SOMAAttribute][_core_current_domain_slot] Column with name {} is not "
102+
"an index column",
103+
name()));
104+
}
105+
106+
std::any SOMAAttribute::_core_current_domain_slot(NDRectangle&) const {
107+
throw TileDBSOMAError(std::format(
108+
"[SOMAAttribute][_core_current_domain_slot] Column with name {} is not "
109+
"an index column",
110+
name()));
111+
}
112+
113+
ArrowArray* SOMAAttribute::arrow_domain_slot(
114+
const SOMAContext&, Array&, enum Domainish) const {
115+
throw TileDBSOMAError(std::format(
116+
"[SOMAAttribute][arrow_domain_slot] Column with name {} is not an "
117+
"index column",
118+
name()));
119+
}
120+
121+
ArrowSchema* SOMAAttribute::arrow_schema_slot(
122+
const SOMAContext& ctx, Array& array) {
123+
return ArrowAdapter::arrow_schema_from_tiledb_attribute(
124+
attribute, *ctx.tiledb_ctx(), array)
125+
.release();
126+
}
127+
} // namespace tiledbsoma
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/**
2+
* @file soma_attribute.h
3+
*
4+
* @section LICENSE
5+
*
6+
* The MIT License
7+
*
8+
* @copyright Copyright (c) 2024-2025 TileDB, Inc.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*
28+
* @section DESCRIPTION
29+
*
30+
* This file defines the SOMAAttribute class. SOMAAttribute extends SOMAColumn
31+
* and wraps a TileDB Attribute and optionally an enumeration associated with
32+
* the attribute. The purpose of this class is to provide a common interface
33+
* identical to TileDB dimensions and composite columns.
34+
*/
35+
36+
#ifndef SOMA_ATTRIBUTE_H
37+
#define SOMA_ATTRIBUTE_H
38+
39+
#include <algorithm>
40+
#include <vector>
41+
42+
#include <tiledb/tiledb>
43+
#include "soma_column.h"
44+
45+
namespace tiledbsoma {
46+
using namespace tiledb;
47+
48+
class SOMAAttribute : public SOMAColumn {
49+
public:
50+
/**
51+
* Create a ``SOMAAttribute`` shared pointer from an Arrow schema
52+
*/
53+
static std::shared_ptr<SOMAAttribute> create(
54+
std::shared_ptr<Context> ctx,
55+
ArrowSchema* schema,
56+
std::string_view type_metadata,
57+
PlatformConfig platform_config);
58+
59+
SOMAAttribute(
60+
Attribute attribute,
61+
std::optional<Enumeration> enumeration = std::nullopt)
62+
: attribute(attribute)
63+
, enumeration(enumeration) {
64+
}
65+
66+
inline std::string name() const override {
67+
return attribute.name();
68+
}
69+
70+
inline bool isIndexColumn() const override {
71+
return false;
72+
}
73+
74+
inline void select_columns(
75+
const std::unique_ptr<ManagedQuery>& query,
76+
bool if_not_empty = false) const override {
77+
query->select_columns(std::vector({attribute.name()}), if_not_empty);
78+
};
79+
80+
inline soma_column_datatype_t type() const override {
81+
return soma_column_datatype_t::SOMA_COLUMN_ATTRIBUTE;
82+
}
83+
84+
inline std::optional<tiledb_datatype_t> domain_type() const override {
85+
return std::nullopt;
86+
}
87+
88+
inline std::optional<tiledb_datatype_t> data_type() const override {
89+
return attribute.type();
90+
}
91+
92+
inline std::optional<std::vector<Dimension>> tiledb_dimensions() override {
93+
return std::nullopt;
94+
}
95+
96+
inline std::optional<std::vector<Attribute>> tiledb_attributes() override {
97+
return std::vector({attribute});
98+
}
99+
100+
inline std::optional<std::vector<Enumeration>> tiledb_enumerations()
101+
override {
102+
if (!enumeration.has_value()) {
103+
return std::nullopt;
104+
}
105+
106+
return std::vector({enumeration.value()});
107+
}
108+
109+
ArrowArray* arrow_domain_slot(
110+
const SOMAContext& ctx,
111+
Array& array,
112+
enum Domainish kind) const override;
113+
114+
ArrowSchema* arrow_schema_slot(
115+
const SOMAContext& ctx, Array& array) override;
116+
117+
private:
118+
void _set_dim_points(
119+
const std::unique_ptr<ManagedQuery>& query,
120+
const SOMAContext& ctx,
121+
const std::any& points) const override;
122+
123+
void _set_dim_ranges(
124+
const std::unique_ptr<ManagedQuery>& query,
125+
const SOMAContext& ctx,
126+
const std::any& ranges) const override;
127+
128+
void _set_current_domain_slot(
129+
NDRectangle& rectangle,
130+
std::span<const std::any> domain) const override;
131+
132+
std::pair<bool, std::string> _can_set_current_domain_slot(
133+
std::optional<NDRectangle>& rectangle,
134+
std::span<const std::any> new_domain) const override;
135+
136+
std::any _core_domain_slot() const override;
137+
138+
std::any _non_empty_domain_slot(Array& array) const override;
139+
140+
std::any _core_current_domain_slot(
141+
const SOMAContext& ctx, Array& array) const override;
142+
143+
std::any _core_current_domain_slot(NDRectangle& ndrect) const override;
144+
145+
Attribute attribute;
146+
std::optional<Enumeration> enumeration;
147+
};
148+
} // namespace tiledbsoma
149+
150+
#endif

libtiledbsoma/src/tiledbsoma/tiledbsoma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "soma/soma_array.h"
5151
#include "soma/soma_collection.h"
5252
#include "soma/soma_column.h"
53+
#include "soma/soma_attribute.h"
5354
#include "soma/soma_dimension.h"
5455
#include "soma/soma_dataframe.h"
5556
#include "soma/soma_group.h"

libtiledbsoma/test/unit_soma_column.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ TEST_CASE_METHOD(
314314
std::make_shared<SOMADimension>(SOMADimension(dimension)));
315315
}
316316

317+
for (size_t i = 0; i < sdf->tiledb_schema()->attribute_num(); ++i) {
318+
columns.push_back(std::make_shared<SOMAAttribute>(
319+
SOMAAttribute(sdf->tiledb_schema()->attribute(i))));
320+
}
321+
317322
CurrentDomain current_domain = sdf->get_current_domain_for_test();
318323

319324
REQUIRE(!current_domain.is_empty());

0 commit comments

Comments
 (0)