From 831b5b03ba4e57a62b96e0307f0457e6fab0f9eb Mon Sep 17 00:00:00 2001 From: Robert Bindar Date: Fri, 20 Oct 2023 19:05:05 +0300 Subject: [PATCH] Query aggregates REST support (#4415) Add rest support for query aggregates. Notes to reviewers: - At this stage we should pay special attention to the capnp specification, make sure it's as generic as possible according to the aggregates design document. - I tested this manually with a local rest server and serialization paths seem to work as expected, but overall the feature doesn't currently work because we need Go support on the REST side which I'll file as followup (When the REST server deserializes the query, the query buffers are set to `nullptr` and their sizes to the correct sizes passed by the user. The Go code is supposed to allocate memory and set the buffers again before the query is submitted "locally". The tests work because in the serialization wrappers we emulate this allocation with some stack allocated buffers, see changes in `helpers.cc`) --- TYPE: NO_HISTORY | FEATURE DESC: Query aggregates REST support --------- Co-authored-by: Luc Rancourt Co-authored-by: KiterLuc <67824247+KiterLuc@users.noreply.github.com> --- test/support/src/helpers.cc | 28 +- tiledb/CMakeLists.txt | 4 + .../query_aggregate/query_aggregate_api.cc | 106 +--- .../query_aggregate_api_internal.h | 90 +-- .../c_api/query_aggregate/test/CMakeLists.txt | 7 +- .../test/unit_capi_query_aggregate.cc | 160 ++++- .../api/c_api/query_field/query_field_api.cc | 3 +- tiledb/sm/misc/constants.h | 21 + tiledb/sm/query/query.cc | 24 +- tiledb/sm/query/query.h | 42 +- .../query/readers/aggregators/CMakeLists.txt | 2 +- .../readers/aggregators/count_aggregator.cc | 6 +- .../readers/aggregators/count_aggregator.h | 15 +- .../query/readers/aggregators/iaggregator.h | 9 +- .../aggregators/input_field_validator.h | 93 +++ .../readers/aggregators/mean_aggregator.cc | 13 +- .../readers/aggregators/mean_aggregator.h | 16 +- .../readers/aggregators/min_max_aggregator.cc | 12 +- .../readers/aggregators/min_max_aggregator.h | 26 +- .../sm/query/readers/aggregators/operation.cc | 53 ++ .../sm/query/readers/aggregators/operation.h | 209 +++++++ .../query/readers/aggregators/query_channel.h | 90 +++ .../readers/aggregators/sum_aggregator.cc | 13 +- .../readers/aggregators/sum_aggregator.h | 16 +- .../aggregators/test/unit_aggregators.cc | 18 +- tiledb/sm/serialization/query.cc | 42 +- tiledb/sm/serialization/query_aggregates.cc | 132 ++++ tiledb/sm/serialization/query_aggregates.h | 66 ++ tiledb/sm/serialization/tiledb-rest.capnp | 31 + tiledb/sm/serialization/tiledb-rest.capnp.c++ | 330 +++++++--- tiledb/sm/serialization/tiledb-rest.capnp.h | 575 +++++++++++++++++- 31 files changed, 1924 insertions(+), 328 deletions(-) create mode 100644 tiledb/sm/query/readers/aggregators/input_field_validator.h create mode 100644 tiledb/sm/query/readers/aggregators/operation.cc create mode 100644 tiledb/sm/query/readers/aggregators/operation.h create mode 100644 tiledb/sm/query/readers/aggregators/query_channel.h create mode 100644 tiledb/sm/serialization/query_aggregates.cc create mode 100644 tiledb/sm/serialization/query_aggregates.h diff --git a/test/support/src/helpers.cc b/test/support/src/helpers.cc index 45982c3df10..44611033b3b 100644 --- a/test/support/src/helpers.cc +++ b/test/support/src/helpers.cc @@ -1850,7 +1850,9 @@ int submit_query_wrapper( // 4. Server -> Client : Send query response std::vector serialized2; rc = serialize_query(server_ctx, server_deser_query, &serialized2, 0); - REQUIRE(rc == TILEDB_OK); + if (rc != TILEDB_OK) { + return rc; + } if (!refactored_query_v2) { // Close array and clean up @@ -1950,13 +1952,31 @@ void allocate_query_buffers_server_side( tiledb_query_t* query, ServerQueryBuffers& query_buffers) { int rc = 0; - const auto buffer_names = query->query_->buffer_names(); + auto buffer_names = query->query_->buffer_names(); + const auto aggregate_names = query->query_->aggregate_buffer_names(); + buffer_names.insert( + buffer_names.end(), aggregate_names.begin(), aggregate_names.end()); + for (uint64_t i = 0; i < buffer_names.size(); i++) { const auto& name = buffer_names[i]; const auto& buff = query->query_->buffer(name); const auto& schema = query->query_->array_schema(); - auto var_size = schema.var_size(name); - auto nullable = schema.is_nullable(name); + + // TODO: This is yet another instance where there needs to be a common + // mechanism for reporting the common properties of a field. + // Refactor to use query_field_t. + bool var_size = false; + bool nullable = false; + if (query->query_->is_aggregate(name)) { + var_size = + query->query_->get_aggregate(name).value()->aggregation_var_sized(); + nullable = + query->query_->get_aggregate(name).value()->aggregation_nullable(); + } else { + var_size = schema.var_size(name); + nullable = schema.is_nullable(name); + } + if (var_size && buff.buffer_var_ == nullptr) { // Variable-sized buffer query_buffers.attr_or_dim_data.emplace_back(*buff.buffer_var_size_); diff --git a/tiledb/CMakeLists.txt b/tiledb/CMakeLists.txt index 9b0e32ec540..07acc6d27cf 100644 --- a/tiledb/CMakeLists.txt +++ b/tiledb/CMakeLists.txt @@ -255,6 +255,7 @@ set(TILEDB_CORE_SOURCES ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/count_aggregator.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/mean_aggregator.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/min_max_aggregator.cc + ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/operation.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/output_buffer_validator.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/safe_sum.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/readers/aggregators/sum_aggregator.cc @@ -286,6 +287,7 @@ set(TILEDB_CORE_SOURCES ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/fragments.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/group.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query.cc + ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query_aggregates.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/consolidation.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/vacuum.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/stats/global_stats.cc @@ -338,6 +340,7 @@ if (TILEDB_SERIALIZATION) ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/fragments.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/group.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query.cc + ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query_aggregates.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/consolidation.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/vacuum.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/tiledb-rest.capnp.c++ @@ -359,6 +362,7 @@ if (TILEDB_SERIALIZATION) ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/fragments.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/group.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query.cc + ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/query_aggregates.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/consolidation.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/vacuum.cc ${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/serialization/tiledb-rest.capnp.c++ diff --git a/tiledb/api/c_api/query_aggregate/query_aggregate_api.cc b/tiledb/api/c_api/query_aggregate/query_aggregate_api.cc index a06597b6e17..c26cf14ed79 100644 --- a/tiledb/api/c_api/query_aggregate/query_aggregate_api.cc +++ b/tiledb/api/c_api/query_aggregate/query_aggregate_api.cc @@ -36,41 +36,21 @@ #include "tiledb/api/c_api/query/query_api_internal.h" #include "tiledb/api/c_api/query_field/query_field_api_external_experimental.h" #include "tiledb/api/c_api_support/c_api_support.h" -#include "tiledb/type/apply_with_type.h" +// const tiledb_channel_operator_handle_t* tiledb_channel_operator_sum = tiledb_channel_operator_handle_t::make_handle( - TILEDB_QUERY_CHANNEL_OPERATOR_SUM, "SUM"); + tiledb::sm::constants::aggregate_sum_str); const tiledb_channel_operator_handle_t* tiledb_channel_operator_min = tiledb_channel_operator_handle_t::make_handle( - TILEDB_QUERY_CHANNEL_OPERATOR_MIN, "MIN"); + tiledb::sm::constants::aggregate_min_str); const tiledb_channel_operator_handle_t* tiledb_channel_operator_max = tiledb_channel_operator_handle_t::make_handle( - TILEDB_QUERY_CHANNEL_OPERATOR_MAX, "MAX"); + tiledb::sm::constants::aggregate_max_str); const tiledb_channel_operation_handle_t* tiledb_aggregate_count = tiledb_channel_operation_handle_t::make_handle( - std::make_shared()); - -shared_ptr tiledb_channel_operator_handle_t::make_operation( - const tiledb::sm::FieldInfo& fi) const { - switch (this->value()) { - case TILEDB_QUERY_CHANNEL_OPERATOR_SUM: { - return std::make_shared(fi, this); - } - case TILEDB_QUERY_CHANNEL_OPERATOR_MIN: { - return std::make_shared(fi, this); - } - case TILEDB_QUERY_CHANNEL_OPERATOR_MAX: { - return std::make_shared(fi, this); - } - default: - throw tiledb::api::CAPIStatusException( - "operator has unsupported value: " + - std::to_string(static_cast(this->value()))); - break; - } -} + std::make_shared()); namespace tiledb::api { @@ -260,6 +240,12 @@ capi_return_t tiledb_query_channel_free( } // namespace tiledb::api +shared_ptr +tiledb_channel_operator_handle_t::make_operation( + const tiledb::sm::FieldInfo& fi) const { + return tiledb::sm::Operation::make_operation(this->name(), fi); +} + using tiledb::api::api_entry_with_context; capi_return_t tiledb_channel_operator_sum_get( @@ -324,73 +310,3 @@ capi_return_t tiledb_query_channel_free( return tiledb::api::api_entry_with_context< tiledb::api::tiledb_query_channel_free>(ctx, channel); } - -MaxOperation::MaxOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op) { - auto g = [&](auto T) { - if constexpr (tiledb::type::TileDBFundamental) { - if constexpr (tiledb::type::TileDBNumeric) { - ensure_aggregate_numeric_field(op, fi); - } - - // This is a min/max on strings, should be refactored out once we - // change (STRING_ASCII,CHAR) mapping in apply_with_type - if constexpr (std::is_same_v) { - aggregator_ = - std::make_shared>(fi); - } else { - aggregator_ = - std::make_shared>(fi); - } - } else { - throw std::logic_error( - "MAX aggregates can only be requested on numeric and string " - "types"); - } - }; - apply_with_type(g, fi.type_); -} - -MinOperation::MinOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op) { - auto g = [&](auto T) { - if constexpr (tiledb::type::TileDBFundamental) { - if constexpr (tiledb::type::TileDBNumeric) { - ensure_aggregate_numeric_field(op, fi); - } - - // This is a min/max on strings, should be refactored out once we - // change (STRING_ASCII,CHAR) mapping in apply_with_type - if constexpr (std::is_same_v) { - aggregator_ = - std::make_shared>(fi); - } else { - aggregator_ = - std::make_shared>(fi); - } - } else { - throw std::logic_error( - "MIN aggregates can only be requested on numeric and string " - "types"); - } - }; - apply_with_type(g, fi.type_); -} - -SumOperation::SumOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op) { - auto g = [&](auto T) { - if constexpr (tiledb::type::TileDBNumeric) { - ensure_aggregate_numeric_field(op, fi); - aggregator_ = - std::make_shared>(fi); - } else { - throw std::logic_error( - "SUM aggregates can only be requested on numeric types"); - } - }; - apply_with_type(g, fi.type_); -} diff --git a/tiledb/api/c_api/query_aggregate/query_aggregate_api_internal.h b/tiledb/api/c_api/query_aggregate/query_aggregate_api_internal.h index 93e45b4da69..1c736f077b0 100644 --- a/tiledb/api/c_api/query_aggregate/query_aggregate_api_internal.h +++ b/tiledb/api/c_api/query_aggregate/query_aggregate_api_internal.h @@ -38,64 +38,7 @@ #include "tiledb/api/c_api_support/handle/handle.h" #include "tiledb/sm/c_api/tiledb_struct_def.h" #include "tiledb/sm/query/query.h" -#include "tiledb/sm/query/readers/aggregators/count_aggregator.h" -#include "tiledb/sm/query/readers/aggregators/min_max_aggregator.h" -#include "tiledb/sm/query/readers/aggregators/sum_aggregator.h" - -enum QueryChannelOperator { - TILEDB_QUERY_CHANNEL_OPERATOR_COUNT = 0, - TILEDB_QUERY_CHANNEL_OPERATOR_SUM, - TILEDB_QUERY_CHANNEL_OPERATOR_MIN, - TILEDB_QUERY_CHANNEL_OPERATOR_MAX -}; - -class Operation { - protected: - shared_ptr aggregator_ = nullptr; - - public: - [[nodiscard]] virtual shared_ptr aggregator() const { - return aggregator_; - } - - virtual ~Operation(){}; -}; - -class MinOperation : public Operation { - public: - MinOperation() = delete; - explicit MinOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op); -}; - -class MaxOperation : public Operation { - public: - MaxOperation() = delete; - explicit MaxOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op); -}; - -class SumOperation : public Operation { - public: - SumOperation() = delete; - explicit SumOperation( - const tiledb::sm::FieldInfo& fi, - const tiledb_channel_operator_handle_t* op); -}; - -class CountOperation : public Operation { - public: - CountOperation() = default; - - // For count operations we have a constant handle, create the aggregator when - // requested so that we get a different object for each query. - [[nodiscard]] shared_ptr aggregator() - const override { - return std::make_shared(); - } -}; +#include "tiledb/sm/query/readers/aggregators/operation.h" struct tiledb_channel_operation_handle_t : public tiledb::api::CAPIHandle { @@ -106,7 +49,7 @@ struct tiledb_channel_operation_handle_t "tiledb_channel_operation_t"}; private: - std::shared_ptr operation_; + std::shared_ptr operation_; public: /** @@ -119,7 +62,7 @@ struct tiledb_channel_operation_handle_t * @param operation An internal operation object */ explicit tiledb_channel_operation_handle_t( - const shared_ptr& operation) + const shared_ptr& operation) : operation_{operation} { } @@ -176,7 +119,6 @@ struct tiledb_channel_operator_handle_t "tiledb_channel_operator_handle_t"}; private: - QueryChannelOperator value_; std::string name_; public: @@ -190,36 +132,16 @@ struct tiledb_channel_operator_handle_t * @param op An enum specifying the type of operator * @param name A string representation of the operator */ - explicit tiledb_channel_operator_handle_t( - QueryChannelOperator op, const std::string& name) - : value_{op} - , name_{name} { - } - - [[nodiscard]] inline QueryChannelOperator value() const { - return value_; + explicit tiledb_channel_operator_handle_t(const std::string& name) + : name_{name} { } [[nodiscard]] inline std::string name() const { return name_; } - [[nodiscard]] std::shared_ptr make_operation( + [[nodiscard]] std::shared_ptr make_operation( const tiledb::sm::FieldInfo& fi) const; }; -inline void ensure_aggregate_numeric_field( - const tiledb_channel_operator_t* op, const tiledb::sm::FieldInfo& fi) { - if (fi.var_sized_) { - throw tiledb::api::CAPIStatusException( - op->name() + " aggregates are not supported for var sized attributes."); - } - if (fi.cell_val_num_ != 1) { - throw tiledb::api::CAPIStatusException( - op->name() + - " aggregates are not supported for attributes with cell_val_num " - "greater than one."); - } -} - #endif // TILEDB_CAPI_QUERY_AGGREGATE_INTERNAL_H diff --git a/tiledb/api/c_api/query_aggregate/test/CMakeLists.txt b/tiledb/api/c_api/query_aggregate/test/CMakeLists.txt index ffd39b7b68b..f4e73844784 100644 --- a/tiledb/api/c_api/query_aggregate/test/CMakeLists.txt +++ b/tiledb/api/c_api/query_aggregate/test/CMakeLists.txt @@ -30,7 +30,12 @@ commence(unit_test capi_query_aggregate) this_target_sources(unit_capi_query_aggregate.cc) this_target_object_libraries(capi_query_aggregate) if (NOT MSVC) - target_compile_options(unit_capi_query_aggregate PRIVATE -Wno-deprecated-declarations) + target_compile_options(unit_capi_query_aggregate PRIVATE -Wno-deprecated-declarations) endif() this_target_link_libraries(tiledb_test_support_lib) + + if (TILEDB_SERIALIZATION) + add_definitions(-DTILEDB_SERIALIZATION) + endif() + conclude(unit_test) diff --git a/tiledb/api/c_api/query_aggregate/test/unit_capi_query_aggregate.cc b/tiledb/api/c_api/query_aggregate/test/unit_capi_query_aggregate.cc index 284f8a428cb..fa7f5533311 100644 --- a/tiledb/api/c_api/query_aggregate/test/unit_capi_query_aggregate.cc +++ b/tiledb/api/c_api/query_aggregate/test/unit_capi_query_aggregate.cc @@ -31,6 +31,7 @@ */ #include +#include "test/support/src/helpers.h" #include "test/support/src/vfs_helpers.h" #include "tiledb/api/c_api/config/config_api_internal.h" #include "tiledb/api/c_api/context/context_api_internal.h" @@ -40,6 +41,11 @@ using namespace tiledb::test; struct QueryAggregateFx : TemporaryDirectoryFixture { + // Serialization parameters + bool serialize_ = false; + bool refactored_query_v2_ = false; + ServerQueryBuffers server_buffers_; + QueryAggregateFx() : array_name_(temp_dir_ + "queryaggregate_array") { CHECK( @@ -327,6 +333,15 @@ TEST_CASE_METHOD( QueryAggregateFx, "C API: Query aggregates COUNT test", "[capi][query_aggregate][count]") { + SECTION("- No serialization") { + serialize_ = false; + } +#ifdef TILEDB_SERIALIZATION + SECTION("- Serialization") { + serialize_ = true; + } +#endif + tiledb_array_t* array; REQUIRE(tiledb_array_alloc(ctx, array_name_.c_str(), &array) == TILEDB_OK); REQUIRE(tiledb_array_open(ctx, array, TILEDB_READ) == TILEDB_OK); @@ -354,7 +369,16 @@ TEST_CASE_METHOD( tiledb_query_set_data_buffer(ctx, query, "Count", &count, &size) == TILEDB_OK); - REQUIRE(tiledb_query_submit(ctx, query) == TILEDB_OK); + int rc = submit_query_wrapper( + ctx, + array_name_.c_str(), + &query, + server_buffers_, + serialize_, + false, + false); + REQUIRE(rc == 0); + CHECK(count == 9); // Clean up @@ -368,6 +392,15 @@ TEST_CASE_METHOD( QueryAggregateFx, "C API: Query aggregates SUM test", "[capi][query_aggregate][sum]") { + SECTION("- No serialization") { + serialize_ = false; + } +#ifdef TILEDB_SERIALIZATION + SECTION("- Serialization") { + serialize_ = true; + } +#endif + tiledb_array_t* array; REQUIRE(tiledb_array_alloc(ctx, array_name_.c_str(), &array) == TILEDB_OK); REQUIRE(tiledb_array_open(ctx, array, TILEDB_READ) == TILEDB_OK); @@ -399,7 +432,16 @@ TEST_CASE_METHOD( tiledb_query_set_data_buffer(ctx, query, "Sum", &sum, &size) == TILEDB_OK); - REQUIRE(tiledb_query_submit(ctx, query) == TILEDB_OK); + int rc = submit_query_wrapper( + ctx, + array_name_.c_str(), + &query, + server_buffers_, + serialize_, + false, + false); + REQUIRE(rc == 0); + CHECK(sum == 55); // Clean up @@ -414,6 +456,15 @@ TEST_CASE_METHOD( QueryAggregateFx, "C API: Query aggregates MIN test", "[capi][query_aggregate][min]") { + SECTION("- No serialization") { + serialize_ = false; + } +#ifdef TILEDB_SERIALIZATION + SECTION("- Serialization") { + serialize_ = true; + } +#endif + tiledb_array_t* array; REQUIRE(tiledb_array_alloc(ctx, array_name_.c_str(), &array) == TILEDB_OK); REQUIRE(tiledb_array_open(ctx, array, TILEDB_READ) == TILEDB_OK); @@ -445,7 +496,15 @@ TEST_CASE_METHOD( tiledb_query_set_data_buffer(ctx, query, "Min", &min, &size) == TILEDB_OK); - REQUIRE(tiledb_query_submit(ctx, query) == TILEDB_OK); + int rc = submit_query_wrapper( + ctx, + array_name_.c_str(), + &query, + server_buffers_, + serialize_, + false, + false); + REQUIRE(rc == 0); CHECK(min == 1); @@ -461,6 +520,15 @@ TEST_CASE_METHOD( QueryAggregateFx, "C API: Query aggregates MAX test", "[capi][query_aggregate][max]") { + SECTION("- No serialization") { + serialize_ = false; + } +#ifdef TILEDB_SERIALIZATION + SECTION("- Serialization") { + serialize_ = true; + } +#endif + tiledb_array_t* array; REQUIRE(tiledb_array_alloc(ctx, array_name_.c_str(), &array) == TILEDB_OK); REQUIRE(tiledb_array_open(ctx, array, TILEDB_READ) == TILEDB_OK); @@ -492,7 +560,16 @@ TEST_CASE_METHOD( tiledb_query_set_data_buffer(ctx, query, "Max", &max, &size) == TILEDB_OK); - REQUIRE(tiledb_query_submit(ctx, query) == TILEDB_OK); + int rc = submit_query_wrapper( + ctx, + array_name_.c_str(), + &query, + server_buffers_, + serialize_, + false, + false); + REQUIRE(rc == 0); + CHECK(max == 10); // Clean up @@ -598,3 +675,78 @@ TEST_CASE_METHOD( tiledb_array_free(&array); tiledb_query_free(&query); } + +TEST_CASE_METHOD( + QueryAggregateFx, + "C API: Query aggregates serialization test", + "[capi][query_aggregate][serialization][incompletes]") { + SECTION("- No serialization") { + serialize_ = false; + } +#ifdef TILEDB_SERIALIZATION + SECTION("- Serialization") { + serialize_ = true; + } +#endif + + tiledb_array_t* array; + REQUIRE(tiledb_array_alloc(ctx, array_name_.c_str(), &array) == TILEDB_OK); + REQUIRE(tiledb_array_open(ctx, array, TILEDB_READ) == TILEDB_OK); + + tiledb_query_t* query; + REQUIRE(tiledb_query_alloc(ctx, array, TILEDB_READ, &query) == TILEDB_OK); + + REQUIRE(tiledb_query_set_layout(ctx, query, TILEDB_UNORDERED) == TILEDB_OK); + + int64_t dom[] = {1, 10, 1, 1}; + REQUIRE(tiledb_query_set_subarray(ctx, query, &dom) == TILEDB_OK); + + tiledb_query_channel_t* default_channel; + REQUIRE( + tiledb_query_get_default_channel(ctx, query, &default_channel) == + TILEDB_OK); + + tiledb_channel_operation_t* sum_op; + REQUIRE( + tiledb_create_unary_aggregate( + ctx, query, tiledb_channel_operator_sum, "a", &sum_op) == TILEDB_OK); + REQUIRE( + tiledb_channel_apply_aggregate(ctx, default_channel, "Sum", sum_op) == + TILEDB_OK); + + uint64_t sum = 0; + uint64_t size = 8; + REQUIRE( + tiledb_query_set_data_buffer(ctx, query, "Sum", &sum, &size) == + TILEDB_OK); + + uint64_t a_size = 1; + int32_t a; + REQUIRE( + tiledb_query_set_data_buffer(ctx, query, "a", &a, &a_size) == TILEDB_OK); + + int rc = submit_query_wrapper( + ctx, + array_name_.c_str(), + &query, + server_buffers_, + serialize_, + false, + false); + + if (serialize_) { + CHECK(rc != 0); + } else { + tiledb_query_status_t status; + REQUIRE(tiledb_query_get_status(ctx, query, &status) == TILEDB_OK); + REQUIRE(status == TILEDB_INCOMPLETE); + CHECK(rc == 0); + } + + // Clean up + CHECK(tiledb_aggregate_free(ctx, &sum_op) == TILEDB_OK); + CHECK(tiledb_query_channel_free(ctx, &default_channel) == TILEDB_OK); + CHECK(tiledb_array_close(ctx, array) == TILEDB_OK); + tiledb_array_free(&array); + tiledb_query_free(&query); +} diff --git a/tiledb/api/c_api/query_field/query_field_api.cc b/tiledb/api/c_api/query_field/query_field_api.cc index 25bfc88774c..78355dfee2c 100644 --- a/tiledb/api/c_api/query_field/query_field_api.cc +++ b/tiledb/api/c_api/query_field/query_field_api.cc @@ -76,7 +76,8 @@ tiledb_query_field_handle_t::tiledb_query_field_handle_t( field_origin_ = std::make_shared(); auto aggregate = query_->get_aggregate(field_name_).value(); type_ = aggregate->output_datatype(); - cell_val_num_ = aggregate->var_sized() ? tiledb::sm::constants::var_num : 1; + cell_val_num_ = + aggregate->aggregation_var_sized() ? tiledb::sm::constants::var_num : 1; } else { throw tiledb::api::CAPIStatusException("There is no field " + field_name_); } diff --git a/tiledb/sm/misc/constants.h b/tiledb/sm/misc/constants.h index 194e2918b29..7afdea1e3a0 100644 --- a/tiledb/sm/misc/constants.h +++ b/tiledb/sm/misc/constants.h @@ -49,6 +49,27 @@ enum class SerializationType : uint8_t; namespace constants { +// The following aggregate constants are declared static to avoid a SIOF +// issue with constant aggregate operator handles with extern linkage. + +/** The name of COUNT aggregator. */ +static const std::string aggregate_count_str = "COUNT"; + +/** The name of SUM aggregator. */ +static const std::string aggregate_sum_str = "SUM"; + +/** The name of MIN aggregator. */ +static const std::string aggregate_min_str = "MIN"; + +/** The name of MAX aggregator. */ +static const std::string aggregate_max_str = "MAX"; + +/** The name of NULL_COUNT aggregator. */ +static const std::string aggregate_null_count_str = "NULL_COUNT"; + +/** The name of MEAN aggregator. */ +static const std::string aggregate_mean_str = "MEAN"; + /** * Reduction factor (must be in [0.0, 1.0]) for the multi_range subarray * split by the partitioner. If the number is equal to 0.3, then this diff --git a/tiledb/sm/query/query.cc b/tiledb/sm/query/query.cc index 55aff280373..a969311f79b 100644 --- a/tiledb/sm/query/query.cc +++ b/tiledb/sm/query/query.cc @@ -417,6 +417,16 @@ std::vector Query::dimension_label_buffer_names() const { return ret; } +std::vector Query::aggregate_buffer_names() const { + std::vector buffer_names; + buffer_names.reserve(aggregate_buffers_.size()); + + for (const auto& buffer : aggregate_buffers_) { + buffer_names.push_back(buffer.first); + } + return buffer_names; +} + std::vector Query::unwritten_buffer_names() const { std::vector ret; for (auto& name : buffer_names()) { @@ -445,6 +455,12 @@ QueryBuffer Query::buffer(const std::string& name) const { if (buf != label_buffers_.end()) { return buf->second; } + } else if (is_aggregate(name)) { + // Aggregate buffer + auto buf = aggregate_buffers_.find(name); + if (buf != aggregate_buffers_.end()) { + return buf->second; + } } else { // Attribute or dimension auto buf = buffers_.find(name); @@ -1043,7 +1059,8 @@ Status Query::set_data_buffer( // If this is an aggregate buffer, set it and return. if (is_aggregate(name)) { - const bool is_var = default_channel_aggregates_[name]->var_sized(); + const bool is_var = + default_channel_aggregates_[name]->aggregation_var_sized(); if (!is_var) { // Fixed size data buffer aggregate_buffers_[name].set_data_buffer(buffer, buffer_size); @@ -2190,11 +2207,6 @@ void Query::reset_coords_markers() { } void Query::copy_aggregates_data_to_user_buffer() { - if (array_->is_remote() && !default_channel_aggregates_.empty()) { - throw QueryStatusException( - "Cannot submit query; Query aggregates are not supported in REST yet"); - } - for (auto& default_channel_aggregate : default_channel_aggregates_) { default_channel_aggregate.second->copy_to_user_buffer( default_channel_aggregate.first, aggregate_buffers_); diff --git a/tiledb/sm/query/query.h b/tiledb/sm/query/query.h index 5a43e6c0eab..49fb0d9f7e3 100644 --- a/tiledb/sm/query/query.h +++ b/tiledb/sm/query/query.h @@ -51,6 +51,7 @@ #include "tiledb/sm/query/query_condition.h" #include "tiledb/sm/query/query_remote_buffer_storage.h" #include "tiledb/sm/query/readers/aggregators/iaggregator.h" +#include "tiledb/sm/query/readers/aggregators/query_channel.h" #include "tiledb/sm/query/update_value.h" #include "tiledb/sm/query/validity_vector.h" #include "tiledb/sm/storage_manager/storage_manager_declaration.h" @@ -227,6 +228,9 @@ class Query { /** Returns the names of dimension label buffers for the query. */ std::vector dimension_label_buffer_names() const; + /** Returns the names of aggregate buffers for the query. */ + std::vector aggregate_buffer_names() const; + /** * Returns the names of the buffers set by the user for the query not already * written by a previous partial attribute write. @@ -234,7 +238,7 @@ class Query { std::vector unwritten_buffer_names() const; /** - * Gets the query buffer for the input attribute/dimension. + * Gets the query buffer for the input field. * An empty string means the special default attribute. */ QueryBuffer buffer(const std::string& name) const; @@ -739,10 +743,46 @@ class Query { default_channel_aggregates_.emplace(output_field_name, aggregator); } + /** + * Get all aggregates from the default channel. + */ + std::unordered_map> + get_default_channel_aggregates() { + return default_channel_aggregates_; + } + /** Returns an aggregate based on the output field. */ std::optional> get_aggregate( std::string output_field_name) const; + /** + * Get a list of all channels and their aggregates + */ + std::vector get_channels() { + // Currently only the default channel is supported + return {QueryChannel(true, default_channel_aggregates_)}; + } + + /** + * Add a channel to the query + */ + void add_channel(const QueryChannel& channel) { + if (channel.is_default()) { + default_channel_aggregates_ = channel.aggregates(); + return; + } + throw std::logic_error( + "We currently only support a default channel for queries"); + } + + /** + * Returns true if the query has any aggregates on any channels + */ + bool has_aggregates() { + // We only need to check the default channel for now + return default_channel_aggregates_.empty(); + } + private: /* ********************************* */ /* PRIVATE ATTRIBUTES */ diff --git a/tiledb/sm/query/readers/aggregators/CMakeLists.txt b/tiledb/sm/query/readers/aggregators/CMakeLists.txt index 0ed74a6a736..d4df7081b37 100644 --- a/tiledb/sm/query/readers/aggregators/CMakeLists.txt +++ b/tiledb/sm/query/readers/aggregators/CMakeLists.txt @@ -31,7 +31,7 @@ include(object_library) # `aggregators` object library # commence(object_library aggregators) - this_target_sources(count_aggregator.cc mean_aggregator.cc min_max_aggregator.cc output_buffer_validator.cc safe_sum.cc sum_aggregator.cc) + this_target_sources(count_aggregator.cc mean_aggregator.cc min_max_aggregator.cc operation.cc output_buffer_validator.cc safe_sum.cc sum_aggregator.cc) this_target_object_libraries(baseline array_schema) conclude(object_library) diff --git a/tiledb/sm/query/readers/aggregators/count_aggregator.cc b/tiledb/sm/query/readers/aggregators/count_aggregator.cc index 1dcf824218f..7193976b0ed 100644 --- a/tiledb/sm/query/readers/aggregators/count_aggregator.cc +++ b/tiledb/sm/query/readers/aggregators/count_aggregator.cc @@ -91,11 +91,7 @@ void CountAggregatorBase::copy_to_user_buffer( NullCountAggregator::NullCountAggregator(FieldInfo field_info) : CountAggregatorBase(field_info) , field_info_(field_info) { - if (!field_info_.is_nullable_) { - throw CountAggregatorStatusException( - "NullCount aggregates must only be requested for nullable " - "attributes."); - } + ensure_field_nullable(field_info); } // Explicit template instantiations diff --git a/tiledb/sm/query/readers/aggregators/count_aggregator.h b/tiledb/sm/query/readers/aggregators/count_aggregator.h index 7df272d3403..3299ccaff4c 100644 --- a/tiledb/sm/query/readers/aggregators/count_aggregator.h +++ b/tiledb/sm/query/readers/aggregators/count_aggregator.h @@ -60,10 +60,15 @@ class CountAggregatorBase : public OutputBufferValidator, public IAggregator { /* ********************************* */ /** Returns if the aggregation is var sized or not. */ - bool var_sized() override { + bool aggregation_var_sized() override { return false; }; + /** Returns if the aggregation is nullable or not. */ + bool aggregation_nullable() override { + return false; + } + /** Returns if the aggregate needs to be recomputed on overflow. */ bool need_recompute_on_overflow() override { return true; @@ -96,6 +101,11 @@ class CountAggregatorBase : public OutputBufferValidator, public IAggregator { std::string output_field_name, std::unordered_map& buffers) override; + /** Returns name of the aggregate. */ + std::string aggregate_name() override { + return constants::aggregate_count_str; + } + /** Returns the TileDB datatype of the output field for the aggregate. */ Datatype output_datatype() override { return Datatype::UINT64; @@ -134,7 +144,8 @@ class CountAggregator : public CountAggregatorBase { } }; -class NullCountAggregator : public CountAggregatorBase { +class NullCountAggregator : public CountAggregatorBase, + public InputFieldValidator { public: /* ********************************* */ /* CONSTRUCTORS & DESTRUCTORS */ diff --git a/tiledb/sm/query/readers/aggregators/iaggregator.h b/tiledb/sm/query/readers/aggregators/iaggregator.h index 535bb3c560b..61ebb71d381 100644 --- a/tiledb/sm/query/readers/aggregators/iaggregator.h +++ b/tiledb/sm/query/readers/aggregators/iaggregator.h @@ -35,6 +35,7 @@ #include "tiledb/common/common.h" #include "tiledb/sm/misc/constants.h" +#include "tiledb/sm/query/readers/aggregators/input_field_validator.h" #include "tiledb/sm/query/readers/aggregators/output_buffer_validator.h" namespace tiledb::sm { @@ -65,7 +66,10 @@ class IAggregator { virtual bool need_recompute_on_overflow() = 0; /** Returns if the aggregation is var sized or not. */ - virtual bool var_sized() = 0; + virtual bool aggregation_var_sized() = 0; + + /** Returns if the aggregation is nullable or not. */ + virtual bool aggregation_nullable() = 0; /** * Validate the result buffer. @@ -94,6 +98,9 @@ class IAggregator { std::string output_field_name, std::unordered_map& buffers) = 0; + /** Returns name of the aggregate, e.g. COUNT, MIN, SUM. */ + virtual std::string aggregate_name() = 0; + /** Returns the TileDB datatype of the output field for the aggregate. */ virtual Datatype output_datatype() = 0; }; diff --git a/tiledb/sm/query/readers/aggregators/input_field_validator.h b/tiledb/sm/query/readers/aggregators/input_field_validator.h new file mode 100644 index 00000000000..86e73cb1244 --- /dev/null +++ b/tiledb/sm/query/readers/aggregators/input_field_validator.h @@ -0,0 +1,93 @@ +/** + * @file input_field_validator.h + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file defines class InputFieldValidator. + */ + +#ifndef TILEDB_INPUT_FIELD_VALIDATOR_H +#define TILEDB_INPUT_FIELD_VALIDATOR_H + +#include "tiledb/sm/query/readers/aggregators/aggregate_buffer.h" +#include "tiledb/sm/query/readers/aggregators/field_info.h" + +namespace tiledb::sm { + +class InputFieldValidatorStatusException : public StatusException { + public: + explicit InputFieldValidatorStatusException(const std::string& message) + : StatusException("InputFieldValidator", message) { + } +}; + +class InputFieldValidator { + protected: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + + InputFieldValidator() { + } + + /* ********************************* */ + /* API */ + /* ********************************* */ + + /** + * Ensure the input field is numeric. + * + * @param field_info Field info. + */ + inline static void ensure_field_numeric(const FieldInfo& field_info) { + if (field_info.var_sized_) { + throw InputFieldValidatorStatusException( + "Aggregate is not supported for var sized non-string fields."); + } + if (field_info.cell_val_num_ != 1) { + throw InputFieldValidatorStatusException( + "Aggregate is not supported for non-string fields with cell_val_num " + "greater than one."); + } + } + + /** + * Ensure the input field is nullable. + * + * @param field_info Field info. + */ + inline static void ensure_field_nullable(const FieldInfo& field_info) { + if (!field_info.is_nullable_) { + throw InputFieldValidatorStatusException( + "Aggregate must only be requested for nullable fields."); + } + } +}; + +} // namespace tiledb::sm + +#endif // TILEDB_INPUT_FIELD_VALIDATOR_H diff --git a/tiledb/sm/query/readers/aggregators/mean_aggregator.cc b/tiledb/sm/query/readers/aggregators/mean_aggregator.cc index 44ae0b329b0..4f4d845630b 100644 --- a/tiledb/sm/query/readers/aggregators/mean_aggregator.cc +++ b/tiledb/sm/query/readers/aggregators/mean_aggregator.cc @@ -54,18 +54,7 @@ MeanAggregator::MeanAggregator(const FieldInfo field_info) , validity_value_( field_info_.is_nullable_ ? std::make_optional(0) : nullopt) , sum_overflowed_(false) { - // TODO: These argument validation can be merged for mean/sum and possibly - // other aggregates. (sc-33763). - if (field_info_.var_sized_) { - throw MeanAggregatorStatusException( - "Mean aggregates are not supported for var sized attributes."); - } - - if (field_info_.cell_val_num_ != 1) { - throw MeanAggregatorStatusException( - "Mean aggregates are not supported for attributes with cell_val_num " - "greater than one."); - } + ensure_field_numeric(field_info_); } template diff --git a/tiledb/sm/query/readers/aggregators/mean_aggregator.h b/tiledb/sm/query/readers/aggregators/mean_aggregator.h index 9fbd6fb58f9..96e38504188 100644 --- a/tiledb/sm/query/readers/aggregators/mean_aggregator.h +++ b/tiledb/sm/query/readers/aggregators/mean_aggregator.h @@ -46,7 +46,9 @@ namespace tiledb::sm { class QueryBuffer; template -class MeanAggregator : public OutputBufferValidator, public IAggregator { +class MeanAggregator : public InputFieldValidator, + public OutputBufferValidator, + public IAggregator { public: /* ********************************* */ /* CONSTRUCTORS & DESTRUCTORS */ @@ -74,10 +76,15 @@ class MeanAggregator : public OutputBufferValidator, public IAggregator { } /** Returns if the aggregation is var sized or not. */ - bool var_sized() override { + bool aggregation_var_sized() override { return false; }; + /** Returns if the aggregation is nullable or not. */ + bool aggregation_nullable() override { + return field_info_.is_nullable_; + } + /** Returns if the aggregate needs to be recomputed on overflow. */ bool need_recompute_on_overflow() override { return true; @@ -110,6 +117,11 @@ class MeanAggregator : public OutputBufferValidator, public IAggregator { std::string output_field_name, std::unordered_map& buffers) override; + /** Returns name of the aggregate. */ + std::string aggregate_name() override { + return constants::aggregate_mean_str; + } + /** Returns the TileDB datatype of the output field for the aggregate. */ Datatype output_datatype() override { return Datatype::FLOAT64; diff --git a/tiledb/sm/query/readers/aggregators/min_max_aggregator.cc b/tiledb/sm/query/readers/aggregators/min_max_aggregator.cc index 972e740e68b..f732c40c685 100644 --- a/tiledb/sm/query/readers/aggregators/min_max_aggregator.cc +++ b/tiledb/sm/query/readers/aggregators/min_max_aggregator.cc @@ -120,16 +120,8 @@ ComparatorAggregator::ComparatorAggregator(const FieldInfo& field_info) : ComparatorAggregatorBase(field_info) , OutputBufferValidator(field_info) , aggregate_with_count_(field_info) { - if (field_info.var_sized_ && !std::is_same::value) { - throw MinMaxAggregatorStatusException( - "Min/max aggregates are not supported for var sized non-string " - "attributes."); - } - - if (field_info.cell_val_num_ != 1 && !std::is_same::value) { - throw MinMaxAggregatorStatusException( - "Min/max aggregates are not supported for attributes with cell_val_num " - "greater than one."); + if constexpr (!std::is_same::value) { + ensure_field_numeric(field_info); } } diff --git a/tiledb/sm/query/readers/aggregators/min_max_aggregator.h b/tiledb/sm/query/readers/aggregators/min_max_aggregator.h index e202445b04a..57ac4292fee 100644 --- a/tiledb/sm/query/readers/aggregators/min_max_aggregator.h +++ b/tiledb/sm/query/readers/aggregators/min_max_aggregator.h @@ -104,6 +104,7 @@ class ComparatorAggregatorBase { template class ComparatorAggregator : public ComparatorAggregatorBase, + public InputFieldValidator, public OutputBufferValidator, public IAggregator { protected: @@ -137,10 +138,15 @@ class ComparatorAggregator : public ComparatorAggregatorBase, } /** Returns if the aggregation is var sized or not. */ - bool var_sized() override { + bool aggregation_var_sized() override { return ComparatorAggregatorBase::field_info_.var_sized_; }; + /** Returns if the aggregation is nullable or not. */ + bool aggregation_nullable() override { + return ComparatorAggregatorBase::field_info_.is_nullable_; + } + /** Returns if the aggregate needs to be recomputed on overflow. */ bool need_recompute_on_overflow() override { return false; @@ -215,6 +221,15 @@ class MinAggregator : public ComparatorAggregator< DISABLE_COPY_AND_COPY_ASSIGN(MinAggregator); DISABLE_MOVE_AND_MOVE_ASSIGN(MinAggregator); + + /* ********************************* */ + /* API */ + /* ********************************* */ + + /** Returns name of the aggregate. */ + std::string aggregate_name() override { + return constants::aggregate_min_str; + } }; template @@ -240,6 +255,15 @@ class MaxAggregator : public ComparatorAggregator< DISABLE_COPY_AND_COPY_ASSIGN(MaxAggregator); DISABLE_MOVE_AND_MOVE_ASSIGN(MaxAggregator); + + /* ********************************* */ + /* API */ + /* ********************************* */ + + /** Returns name of the aggregate, e.g. COUNT, MIN, SUM. */ + std::string aggregate_name() override { + return constants::aggregate_max_str; + } }; } // namespace tiledb::sm diff --git a/tiledb/sm/query/readers/aggregators/operation.cc b/tiledb/sm/query/readers/aggregators/operation.cc new file mode 100644 index 00000000000..14634b29367 --- /dev/null +++ b/tiledb/sm/query/readers/aggregators/operation.cc @@ -0,0 +1,53 @@ +/** + * @file operation.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file implements class Operation. + */ + +#include "tiledb/sm/query/readers/aggregators/operation.h" + +namespace tiledb::sm { + +shared_ptr Operation::make_operation( + const std::string& name, const std::optional& fi) { + if (name == constants::aggregate_sum_str) { + return common::make_shared(HERE(), fi.value()); + } else if (name == constants::aggregate_min_str) { + return common::make_shared(HERE(), fi.value()); + } else if (name == constants::aggregate_max_str) { + return common::make_shared(HERE(), fi.value()); + } else if (name == constants::aggregate_count_str) { + return common::make_shared(HERE()); + } + + throw std::logic_error( + "Unable to create and aggregate operation using name: " + name); +} + +} // namespace tiledb::sm \ No newline at end of file diff --git a/tiledb/sm/query/readers/aggregators/operation.h b/tiledb/sm/query/readers/aggregators/operation.h new file mode 100644 index 00000000000..cf1867962fc --- /dev/null +++ b/tiledb/sm/query/readers/aggregators/operation.h @@ -0,0 +1,209 @@ +/** + * @file operation.h + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file defines class Operation and its derivates. + */ + +#ifndef TILEDB_OPERATION_H +#define TILEDB_OPERATION_H + +#include "tiledb/common/common.h" +#include "tiledb/sm/enums/datatype.h" +#include "tiledb/sm/query/readers/aggregators/count_aggregator.h" +#include "tiledb/sm/query/readers/aggregators/min_max_aggregator.h" +#include "tiledb/sm/query/readers/aggregators/sum_aggregator.h" +#include "tiledb/sm/query/readers/aggregators/sum_type.h" +#include "tiledb/type/apply_with_type.h" + +namespace tiledb::sm { + +class Operation : public InputFieldValidator { + public: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + virtual ~Operation(){}; + + /* ********************************* */ + /* API */ + /* ********************************* */ + /** + * @return a shared pointer to the internal aggregator object + */ + [[nodiscard]] virtual shared_ptr aggregator() const { + return aggregator_; + } + + /** + * Create the right operation based on the aggregator name + * + * @param name The name of the aggregator e.g. SUM, MIN + * @param fi A FieldInfo object describing the input field or nullopt for + * nullary operations + * @return The appropriate operation for the name + */ + static shared_ptr make_operation( + const std::string& name, const std::optional& fi); + + /* ********************************* */ + /* PROTECTED ATTRIBUTES */ + /* ********************************* */ + protected: + shared_ptr aggregator_ = nullptr; +}; + +class MinOperation : public Operation { + public: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + MinOperation() = delete; + + /** + * Construct the operation where the internal aggregator object + * is instantiated to the correct type given the input field type. + * @param fi The FieldInfo for the input field + */ + explicit MinOperation(const tiledb::sm::FieldInfo& fi) { + auto g = [&](auto T) { + if constexpr (tiledb::type::TileDBFundamental) { + if constexpr (tiledb::type::TileDBNumeric) { + ensure_field_numeric(fi); + } + + // This is a min/max on strings, should be refactored out once we + // change (STRING_ASCII,CHAR) mapping in apply_with_type + if constexpr (std::is_same_v) { + aggregator_ = + tdb::make_shared>( + HERE(), fi); + } else { + aggregator_ = + tdb::make_shared>( + HERE(), fi); + } + } else { + throw std::logic_error( + "MIN aggregates can only be requested on numeric and string " + "types"); + } + }; + type::apply_with_type(g, fi.type_); + } +}; + +class MaxOperation : public Operation { + public: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + MaxOperation() = delete; + + /** + * Construct the operation where the internal aggregator object + * is instantiated to the correct type given the input field type. + * @param fi The FieldInfo for the input field + */ + explicit MaxOperation(const tiledb::sm::FieldInfo& fi) { + auto g = [&](auto T) { + if constexpr (tiledb::type::TileDBFundamental) { + if constexpr (tiledb::type::TileDBNumeric) { + ensure_field_numeric(fi); + } + + // This is a min/max on strings, should be refactored out once we + // change (STRING_ASCII,CHAR) mapping in apply_with_type + if constexpr (std::is_same_v) { + aggregator_ = + tdb::make_shared>( + HERE(), fi); + } else { + aggregator_ = + tdb::make_shared>( + HERE(), fi); + } + } else { + throw std::logic_error( + "MAX aggregates can only be requested on numeric and string " + "types"); + } + }; + type::apply_with_type(g, fi.type_); + } +}; + +class SumOperation : public Operation { + public: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + SumOperation() = delete; + + /** + * Construct the operation where the internal aggregator object + * is instantiated to the correct type given the input field type. + * @param fi The FieldInfo for the input field + */ + explicit SumOperation(const tiledb::sm::FieldInfo& fi) { + auto g = [&](auto T) { + if constexpr (tiledb::type::TileDBNumeric) { + ensure_field_numeric(fi); + aggregator_ = tdb::make_shared>( + HERE(), fi); + } else { + throw std::logic_error( + "SUM aggregates can only be requested on numeric types"); + } + }; + type::apply_with_type(g, fi.type_); + } +}; + +class CountOperation : public Operation { + public: + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + /** Default constructor */ + CountOperation() = default; + + /* ********************************* */ + /* API */ + /* ********************************* */ + // For count operations we have a constant handle, create the aggregator when + // requested so that we get a different object for each query. + [[nodiscard]] shared_ptr aggregator() + const override { + return common::make_shared(HERE()); + } +}; + +} // namespace tiledb::sm + +#endif // TILEDB_OPERATION_H diff --git a/tiledb/sm/query/readers/aggregators/query_channel.h b/tiledb/sm/query/readers/aggregators/query_channel.h new file mode 100644 index 00000000000..62d87c15395 --- /dev/null +++ b/tiledb/sm/query/readers/aggregators/query_channel.h @@ -0,0 +1,90 @@ +/** + * @file query_channel.h + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file defines class QueryChannel. + */ + +#ifndef TILEDB_QUERY_CHANNEL_H +#define TILEDB_QUERY_CHANNEL_H + +#include "tiledb/common/common.h" +#include "tiledb/sm/enums/datatype.h" +#include "tiledb/sm/query/readers/aggregators/iaggregator.h" + +namespace tiledb::sm { + +class QueryChannel { + public: + using ChannelAggregates = + std::unordered_map>; + + /* ********************************* */ + /* CONSTRUCTORS & DESTRUCTORS */ + /* ********************************* */ + + /** + * Construct a QueryChannel + * + * @param is_default If true, this is the default query channel + * @param aggregates A map of aggregators by output field name + */ + QueryChannel(bool is_default, const ChannelAggregates& aggregates) + : default_(is_default) + , aggregates_{aggregates} { + } + + /* ********************************* */ + /* API */ + /* ********************************* */ + + /** + * @return true if this is the default query channel + */ + bool is_default() const { + return default_; + } + + /** + * @return the map of aggregator pointers + */ + const ChannelAggregates& aggregates() const { + return aggregates_; + } + + private: + /* ********************************* */ + /* PRIVATE ATTRIBUTES */ + /* ********************************* */ + bool default_; + ChannelAggregates aggregates_; +}; + +} // namespace tiledb::sm + +#endif // TILEDB_QUERY_CHANNEL_H diff --git a/tiledb/sm/query/readers/aggregators/sum_aggregator.cc b/tiledb/sm/query/readers/aggregators/sum_aggregator.cc index 8d349ab5771..53a0384fc8a 100644 --- a/tiledb/sm/query/readers/aggregators/sum_aggregator.cc +++ b/tiledb/sm/query/readers/aggregators/sum_aggregator.cc @@ -53,18 +53,7 @@ SumAggregator::SumAggregator(const FieldInfo field_info) , validity_value_( field_info_.is_nullable_ ? std::make_optional(0) : nullopt) , sum_overflowed_(false) { - // TODO: These argument validation can be merged for mean/sum and possibly - // other aggregates. (sc-33763). - if (field_info_.var_sized_) { - throw SumAggregatorStatusException( - "Sum aggregates are not supported for var sized attributes."); - } - - if (field_info_.cell_val_num_ != 1) { - throw SumAggregatorStatusException( - "Sum aggregates are not supported for attributes with cell_val_num " - "greater than one."); - } + ensure_field_numeric(field_info_); } template diff --git a/tiledb/sm/query/readers/aggregators/sum_aggregator.h b/tiledb/sm/query/readers/aggregators/sum_aggregator.h index 9676fe81ef8..0088f50fc38 100644 --- a/tiledb/sm/query/readers/aggregators/sum_aggregator.h +++ b/tiledb/sm/query/readers/aggregators/sum_aggregator.h @@ -45,7 +45,9 @@ namespace tiledb::sm { class QueryBuffer; template -class SumAggregator : public OutputBufferValidator, public IAggregator { +class SumAggregator : public InputFieldValidator, + public OutputBufferValidator, + public IAggregator { public: /* ********************************* */ /* CONSTRUCTORS & DESTRUCTORS */ @@ -73,10 +75,15 @@ class SumAggregator : public OutputBufferValidator, public IAggregator { } /** Returns if the aggregation is var sized or not. */ - bool var_sized() override { + bool aggregation_var_sized() override { return false; }; + /** Returns if the aggregation is nullable or not. */ + bool aggregation_nullable() override { + return field_info_.is_nullable_; + } + /** Returns if the aggregate needs to be recomputed on overflow. */ bool need_recompute_on_overflow() override { return true; @@ -109,6 +116,11 @@ class SumAggregator : public OutputBufferValidator, public IAggregator { std::string output_field_name, std::unordered_map& buffers) override; + /** Returns name of the aggregate, e.g. COUNT, MIN, SUM. */ + std::string aggregate_name() override { + return constants::aggregate_sum_str; + } + /** Returns the TileDB datatype of the output field for the aggregate. */ Datatype output_datatype() override { return sum_type_data::tiledb_datatype; diff --git a/tiledb/sm/query/readers/aggregators/test/unit_aggregators.cc b/tiledb/sm/query/readers/aggregators/test/unit_aggregators.cc index 0b8f3b94b0f..354f8905652 100644 --- a/tiledb/sm/query/readers/aggregators/test/unit_aggregators.cc +++ b/tiledb/sm/query/readers/aggregators/test/unit_aggregators.cc @@ -54,17 +54,15 @@ TEMPLATE_LIST_TEST_CASE( SECTION("Var size") { CHECK_THROWS_WITH( TestType(FieldInfo("a1", true, false, 1)), - Catch::Matchers::EndsWith( - "aggregates are not supported for var sized attributes.") || - Catch::Matchers::EndsWith("aggregates are not supported for var " - "sized non-string attributes.")); + "InputFieldValidator: Aggregate is not supported for var sized " + "non-string fields."); } SECTION("Invalid cell val num") { CHECK_THROWS_WITH( TestType(FieldInfo("a1", false, false, 2)), - Catch::Matchers::EndsWith("aggregates are not supported for attributes " - "with cell_val_num greater than one.")); + "InputFieldValidator: Aggregate is not supported for non-string fields " + "with cell_val_num greater than one."); } } @@ -74,8 +72,8 @@ TEST_CASE( SECTION("Non nullable") { CHECK_THROWS_WITH( NullCountAggregator(FieldInfo("a1", false, false, 1)), - "CountAggregator: NullCount aggregates must only be requested for " - "nullable attributes."); + "InputFieldValidator: Aggregate must only be requested for nullable " + "fields."); } } @@ -99,11 +97,11 @@ typedef tuple< TEMPLATE_LIST_TEST_CASE( "Aggregator: var sized", "[aggregator][var-sized]", AggUnderTest) { auto aggregator{make_aggregator(FieldInfo("a1", false, true, 1))}; - CHECK(aggregator.var_sized() == false); + CHECK(aggregator.aggregation_var_sized() == false); if constexpr (std::is_same>::value) { MinAggregator aggregator2(FieldInfo("a1", true, false, 1)); - CHECK(aggregator2.var_sized() == true); + CHECK(aggregator2.aggregation_var_sized() == true); } } diff --git a/tiledb/sm/serialization/query.cc b/tiledb/sm/serialization/query.cc index 05c43207dca..44e8dabc693 100644 --- a/tiledb/sm/serialization/query.cc +++ b/tiledb/sm/serialization/query.cc @@ -41,6 +41,7 @@ #include "tiledb/sm/serialization/array.h" #include "tiledb/sm/serialization/array_schema.h" #include "tiledb/sm/serialization/capnp_utils.h" +#include "tiledb/sm/serialization/query_aggregates.h" #endif // clang-format on @@ -1414,6 +1415,17 @@ Status query_to_capnp( buffer_names.insert( buffer_names.end(), dim_label_names.begin(), dim_label_names.end()); + // Add aggregate buffers + const auto aggregate_names = query.aggregate_buffer_names(); + buffer_names.insert( + buffer_names.end(), aggregate_names.begin(), aggregate_names.end()); + + // TODO: add API in query to get all buffers in one go + // Deserialization gets the list of buffers from wire then call + // set_data_buffer which knows on which structure to set. We should have a + // function here as well that gets all buffer names or even better, all + // buffers + uint64_t total_fixed_len_bytes = 0; uint64_t total_var_len_bytes = 0; uint64_t total_validity_len_bytes = 0; @@ -1582,6 +1594,16 @@ Status query_to_capnp( } } + // The server should throw if it's about to serialize an incomplete query + // that has aggregates on it, this behavior is currently not supported. + if (!client_side && query.status() == QueryStatus::INCOMPLETE && + !query.has_aggregates()) { + throw Status_SerializationError( + "Aggregates are not currently supported in incomplete remote " + "queries"); + } + query_channels_to_capnp(query, query_builder); + return Status::Ok(); } @@ -1654,6 +1676,11 @@ Status query_from_capnp( } } + // It's important that deserialization of query channels/aggregates happens + // before deserializing buffers. set_data_buffer won't know whether a buffer + // is aggregate or not if the list of aggregates per channel is not populated. + query_channels_from_capnp(query_reader, query); + const auto& schema = query->array_schema(); // Deserialize and set attribute buffers. if (!query_reader.hasAttributeBufferHeaders()) { @@ -1686,8 +1713,19 @@ Status query_from_capnp( uint8_t* existing_validity_buffer = nullptr; uint64_t existing_validity_buffer_size = 0; - auto var_size = schema.var_size(name); - auto nullable = schema.is_nullable(name); + // TODO: This is yet another instance where there needs to be a common + // mechanism for reporting the common properties of a field. + // Refactor to use query_field_t. + bool var_size = false; + bool nullable = false; + auto aggregate = query->get_aggregate(name); + if (aggregate.has_value()) { + var_size = aggregate.value()->aggregation_var_sized(); + nullable = aggregate.value()->aggregation_nullable(); + } else { + var_size = schema.var_size(name); + nullable = schema.is_nullable(name); + } const QueryBuffer& query_buffer = query->buffer(name); if (type == QueryType::READ) { // We use the query_buffer directly in order to get the original buffer diff --git a/tiledb/sm/serialization/query_aggregates.cc b/tiledb/sm/serialization/query_aggregates.cc new file mode 100644 index 00000000000..036139baadb --- /dev/null +++ b/tiledb/sm/serialization/query_aggregates.cc @@ -0,0 +1,132 @@ +/** + * @file query_aggregates.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file declares serialization functions for Query aggregates. + */ + +#include "tiledb/sm/serialization/query_aggregates.h" +#include "tiledb/sm/query/query.h" +#include "tiledb/sm/query/readers/aggregators/operation.h" + +namespace tiledb::sm::serialization { + +#ifdef TILEDB_SERIALIZATION + +void query_channels_to_capnp( + Query& query, capnp::Query::Builder* query_builder) { + // Here, don't serialize if we don't have channels or if the default channel + // has no aggregates on it. + auto channels = query.get_channels(); + if (channels.empty() || (channels.size() == 1 && channels[0].is_default() && + channels[0].aggregates().empty())) { + return; + } + auto channels_builder = query_builder->initChannels(channels.size()); + for (const auto& channel : channels) { + auto channel_builder = channels_builder[0]; + channel_builder.setDefault(channel.is_default()); + + auto& aggregates = channel.aggregates(); + if (aggregates.empty()) { + continue; + } + + auto aggregates_builder = channel_builder.initAggregates(aggregates.size()); + size_t i = 0; + for (const auto& agg : aggregates) { + auto aggregate_builder = aggregates_builder[i]; + aggregate_builder.setOutputFieldName(agg.first); + aggregate_builder.setName(agg.second->aggregate_name()); + // TODO: Currently COUNT reports that its field name is + // constants::count_of_rows. This causes deserialization code to crash + // because an input field is always assumed to exist, so deserialization + // calls some array schema functions on it. This should be fixed in a + // followup work item by making the aggregators interface return an + // optional field_name + if (agg.second->aggregate_name() != constants::aggregate_count_str) { + aggregate_builder.setInputFieldName(agg.second->field_name()); + } + ++i; + } + } +} + +void query_channels_from_capnp( + const capnp::Query::Reader& query_reader, Query* const query) { + // We might not have channels if the default channel had no aggregates. + if (query_reader.hasChannels()) { + auto channels_reader = query_reader.getChannels(); + // Only the query default channel is on the wire for now + for (size_t i = 0; i < channels_reader.size(); ++i) { + auto channel_reader = channels_reader[i]; + + if (channel_reader.hasAggregates()) { + QueryChannel::ChannelAggregates aggregates; + + auto aggregates_reader = channel_reader.getAggregates(); + for (const auto& aggregate : aggregates_reader) { + if (aggregate.hasOutputFieldName() && aggregate.hasName()) { + auto output_field = aggregate.getOutputFieldName(); + auto name = aggregate.getName(); + + // TODO: Currently COUNT reports that its field name is + // constants::count_of_rows. This causes deserialization code to + // crash because an input field is always assumed to exist, so + // deserialization calls some array schema functions on it. This + // should be fixed in a followup work item by making the aggregators + // interface return an optional field_name + std::optional fi; + if (aggregate.hasInputFieldName()) { + auto input_field = aggregate.getInputFieldName(); + auto& schema = query->array_schema(); + + fi.emplace(tiledb::sm::FieldInfo( + input_field, + schema.var_size(input_field), + schema.is_nullable(input_field), + schema.cell_val_num(input_field), + schema.type(input_field))); + } + + auto operation = Operation::make_operation(name, fi); + aggregates.emplace(output_field, operation->aggregator()); + } + } + if (!aggregates.empty()) { + query->add_channel( + QueryChannel{channel_reader.getDefault(), aggregates}); + } + } + } + } +} + +#endif // TILEDB_SERIALIZATION + +} // namespace tiledb::sm::serialization \ No newline at end of file diff --git a/tiledb/sm/serialization/query_aggregates.h b/tiledb/sm/serialization/query_aggregates.h new file mode 100644 index 00000000000..774c9439c2d --- /dev/null +++ b/tiledb/sm/serialization/query_aggregates.h @@ -0,0 +1,66 @@ +/** + * @file query_aggregates.h + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file declares serialization functions for Query aggregates. + */ + +#ifndef TILEDB_SERIALIZATION_QUERY_AGGREGATES_H +#define TILEDB_SERIALIZATION_QUERY_AGGREGATES_H + +#ifdef TILEDB_SERIALIZATION +#include "tiledb/sm/serialization/capnp_utils.h" +#endif + +namespace tiledb::sm::serialization { + +#ifdef TILEDB_SERIALIZATION + +/** + * Convert query channels to Cap'n Proto message + * + * @param query A TileDB query + * @param query_builder cap'n proto class + */ +void query_channels_to_capnp( + Query& query, capnp::Query::Builder* query_builder); + +/** + * Deserialize query channels from Cap'n Proto message + * + * @param query_reader capnp reader + * @param query deserialized TileDB query + */ +void query_channels_from_capnp( + const capnp::Query::Reader& query_reader, Query* const query); + +#endif + +} // namespace tiledb::sm::serialization + +#endif // TILEDB_SERIALIZATION_QUERY_AGGREGATES_H \ No newline at end of file diff --git a/tiledb/sm/serialization/tiledb-rest.capnp b/tiledb/sm/serialization/tiledb-rest.capnp index f76b4107e57..77fb19c6886 100644 --- a/tiledb/sm/serialization/tiledb-rest.capnp +++ b/tiledb/sm/serialization/tiledb-rest.capnp @@ -772,6 +772,10 @@ struct Query { orderedDimLabelReader @20 :QueryReader; # orderedDimLabelReader contains data needed for dense dimension label reads. + + channels @21 :List(QueryChannel); + # channels contains the list of channels (streams of data) within a read + # query. It always contains at least one element, the default channel. } struct NonEmptyDomain { @@ -1253,3 +1257,30 @@ struct LoadArraySchemaResponse { schema @0 :ArraySchema; # The loaded ArraySchema } + +struct QueryChannel { + # structure representing a query channel, that is a stream of data within + # a TileDB query. Such channels can be generated for the purpose of avoiding + # processing result items multiple times in more complex queries such as e.g. + # grouping queries. + + default @0 :Bool; + # True if a channel is the default query channel + + aggregates @1 :List(Aggregate); + # a list of the aggregate operations applied on this channel +} + +struct Aggregate { + # structure representing a query aggregate operation + + outputFieldName @0 :Text; + # name of the result query buffers + + inputFieldName @1 :Text; + # name of the input field the aggregate is applied on + + name @2 :Text; + # the name of aggregate, e.g. COUNT, MEAN, SUM used for constructing the + # correct object during deserialization +} diff --git a/tiledb/sm/serialization/tiledb-rest.capnp.c++ b/tiledb/sm/serialization/tiledb-rest.capnp.c++ index 2a5a77c3f80..5e6afe2644a 100644 --- a/tiledb/sm/serialization/tiledb-rest.capnp.c++ +++ b/tiledb/sm/serialization/tiledb-rest.capnp.c++ @@ -5397,171 +5397,178 @@ const ::capnp::_::RawSchema s_9b9a5fc7713a8692 = { 4, 5, i_9b9a5fc7713a8692, nullptr, nullptr, { &s_9b9a5fc7713a8692, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE -static const ::capnp::_::AlignedData<367> b_96ba49d0f8b23ccc = { +static const ::capnp::_::AlignedData<387> b_96ba49d0f8b23ccc = { { 0, 0, 0, 0, 5, 0, 6, 0, 204, 60, 178, 248, 208, 73, 186, 150, 18, 0, 0, 0, 1, 0, 4, 0, 127, 216, 135, 181, 36, 146, 125, 181, - 16, 0, 7, 0, 0, 0, 0, 0, + 17, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 0, 0, 0, 159, 4, 0, 0, + 25, 0, 0, 0, 215, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 105, 108, 101, 100, 98, 45, 114, 101, 115, 116, 46, 99, 97, 112, 110, 112, 58, 81, 117, 101, 114, 121, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 84, 0, 0, 0, 3, 0, 4, 0, + 88, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 61, 2, 0, 0, 186, 0, 0, 0, + 89, 2, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 64, 2, 0, 0, 3, 0, 1, 0, - 92, 2, 0, 0, 2, 0, 1, 0, + 92, 2, 0, 0, 3, 0, 1, 0, + 120, 2, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 89, 2, 0, 0, 58, 0, 0, 0, + 117, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 2, 0, 0, 3, 0, 1, 0, - 96, 2, 0, 0, 2, 0, 1, 0, + 112, 2, 0, 0, 3, 0, 1, 0, + 124, 2, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 93, 2, 0, 0, 58, 0, 0, 0, + 121, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 88, 2, 0, 0, 3, 0, 1, 0, - 100, 2, 0, 0, 2, 0, 1, 0, + 116, 2, 0, 0, 3, 0, 1, 0, + 128, 2, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 97, 2, 0, 0, 42, 0, 0, 0, + 125, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 92, 2, 0, 0, 3, 0, 1, 0, - 104, 2, 0, 0, 2, 0, 1, 0, + 120, 2, 0, 0, 3, 0, 1, 0, + 132, 2, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 2, 0, 0, 58, 0, 0, 0, + 129, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 96, 2, 0, 0, 3, 0, 1, 0, - 108, 2, 0, 0, 2, 0, 1, 0, + 124, 2, 0, 0, 3, 0, 1, 0, + 136, 2, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 105, 2, 0, 0, 58, 0, 0, 0, + 133, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 100, 2, 0, 0, 3, 0, 1, 0, - 112, 2, 0, 0, 2, 0, 1, 0, + 128, 2, 0, 0, 3, 0, 1, 0, + 140, 2, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 109, 2, 0, 0, 50, 0, 0, 0, + 137, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 104, 2, 0, 0, 3, 0, 1, 0, - 116, 2, 0, 0, 2, 0, 1, 0, + 132, 2, 0, 0, 3, 0, 1, 0, + 144, 2, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 113, 2, 0, 0, 226, 0, 0, 0, + 141, 2, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 120, 2, 0, 0, 3, 0, 1, 0, - 132, 2, 0, 0, 2, 0, 1, 0, + 148, 2, 0, 0, 3, 0, 1, 0, + 160, 2, 0, 0, 2, 0, 1, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 2, 0, 0, 186, 0, 0, 0, + 157, 2, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 132, 2, 0, 0, 3, 0, 1, 0, - 144, 2, 0, 0, 2, 0, 1, 0, + 160, 2, 0, 0, 3, 0, 1, 0, + 172, 2, 0, 0, 2, 0, 1, 0, 9, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 141, 2, 0, 0, 202, 0, 0, 0, + 169, 2, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 148, 2, 0, 0, 3, 0, 1, 0, - 160, 2, 0, 0, 2, 0, 1, 0, + 176, 2, 0, 0, 3, 0, 1, 0, + 188, 2, 0, 0, 2, 0, 1, 0, 10, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 157, 2, 0, 0, 122, 0, 0, 0, + 185, 2, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 156, 2, 0, 0, 3, 0, 1, 0, - 168, 2, 0, 0, 2, 0, 1, 0, + 184, 2, 0, 0, 3, 0, 1, 0, + 196, 2, 0, 0, 2, 0, 1, 0, 11, 0, 0, 0, 192, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 165, 2, 0, 0, 210, 0, 0, 0, + 193, 2, 0, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 172, 2, 0, 0, 3, 0, 1, 0, - 184, 2, 0, 0, 2, 0, 1, 0, + 200, 2, 0, 0, 3, 0, 1, 0, + 212, 2, 0, 0, 2, 0, 1, 0, 12, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 181, 2, 0, 0, 146, 0, 0, 0, + 209, 2, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 184, 2, 0, 0, 3, 0, 1, 0, - 196, 2, 0, 0, 2, 0, 1, 0, + 212, 2, 0, 0, 3, 0, 1, 0, + 224, 2, 0, 0, 2, 0, 1, 0, 13, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 193, 2, 0, 0, 58, 0, 0, 0, + 221, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 188, 2, 0, 0, 3, 0, 1, 0, - 200, 2, 0, 0, 2, 0, 1, 0, + 216, 2, 0, 0, 3, 0, 1, 0, + 228, 2, 0, 0, 2, 0, 1, 0, 14, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 197, 2, 0, 0, 50, 0, 0, 0, + 225, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 192, 2, 0, 0, 3, 0, 1, 0, - 204, 2, 0, 0, 2, 0, 1, 0, + 220, 2, 0, 0, 3, 0, 1, 0, + 232, 2, 0, 0, 2, 0, 1, 0, 15, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 201, 2, 0, 0, 98, 0, 0, 0, + 229, 2, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 200, 2, 0, 0, 3, 0, 1, 0, - 212, 2, 0, 0, 2, 0, 1, 0, + 228, 2, 0, 0, 3, 0, 1, 0, + 240, 2, 0, 0, 2, 0, 1, 0, 16, 0, 0, 0, 11, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 209, 2, 0, 0, 98, 0, 0, 0, + 237, 2, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 208, 2, 0, 0, 3, 0, 1, 0, - 220, 2, 0, 0, 2, 0, 1, 0, + 236, 2, 0, 0, 3, 0, 1, 0, + 248, 2, 0, 0, 2, 0, 1, 0, 17, 0, 0, 0, 12, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 217, 2, 0, 0, 58, 0, 0, 0, + 245, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 212, 2, 0, 0, 3, 0, 1, 0, - 224, 2, 0, 0, 2, 0, 1, 0, + 240, 2, 0, 0, 3, 0, 1, 0, + 252, 2, 0, 0, 2, 0, 1, 0, 18, 0, 0, 0, 13, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 221, 2, 0, 0, 162, 0, 0, 0, + 249, 2, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 224, 2, 0, 0, 3, 0, 1, 0, - 252, 2, 0, 0, 2, 0, 1, 0, + 252, 2, 0, 0, 3, 0, 1, 0, + 24, 3, 0, 0, 2, 0, 1, 0, 19, 0, 0, 0, 14, 0, 0, 0, 0, 0, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 249, 2, 0, 0, 122, 0, 0, 0, + 21, 3, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 248, 2, 0, 0, 3, 0, 1, 0, - 20, 3, 0, 0, 2, 0, 1, 0, + 20, 3, 0, 0, 3, 0, 1, 0, + 48, 3, 0, 0, 2, 0, 1, 0, 20, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 17, 3, 0, 0, 178, 0, 0, 0, + 45, 3, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 20, 3, 0, 0, 3, 0, 1, 0, - 32, 3, 0, 0, 2, 0, 1, 0, + 48, 3, 0, 0, 3, 0, 1, 0, + 60, 3, 0, 0, 2, 0, 1, 0, + 21, 0, 0, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 57, 3, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 56, 3, 0, 0, 3, 0, 1, 0, + 84, 3, 0, 0, 2, 0, 1, 0, 97, 116, 116, 114, 105, 98, 117, 116, 101, 66, 117, 102, 102, 101, 114, 72, 101, 97, 100, 101, 114, 115, 0, 0, @@ -5763,6 +5770,19 @@ static const ::capnp::_::AlignedData<367> b_96ba49d0f8b23ccc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 99, 104, 97, 110, 110, 101, 108, 115, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 217, 229, 74, 254, 11, 77, 45, 202, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; @@ -5775,15 +5795,16 @@ static const ::capnp::_::RawSchema* const d_96ba49d0f8b23ccc[] = { &s_a736c51d292ca752, &s_b6c95b4b8111ad36, &s_c7e036a11506a1a4, + &s_ca2d4d0bfe4ae5d9, &s_d20a578112fa92a2, &s_d74f5fed155d316c, &s_e19754f813ccf79c, }; -static const uint16_t m_96ba49d0f8b23ccc[] = {6, 0, 13, 17, 16, 1, 20, 5, 15, 14, 2, 7, 9, 8, 3, 11, 12, 10, 4, 19, 18}; -static const uint16_t i_96ba49d0f8b23ccc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; +static const uint16_t m_96ba49d0f8b23ccc[] = {6, 0, 21, 13, 17, 16, 1, 20, 5, 15, 14, 2, 7, 9, 8, 3, 11, 12, 10, 4, 19, 18}; +static const uint16_t i_96ba49d0f8b23ccc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; const ::capnp::_::RawSchema s_96ba49d0f8b23ccc = { - 0x96ba49d0f8b23ccc, b_96ba49d0f8b23ccc.words, 367, d_96ba49d0f8b23ccc, m_96ba49d0f8b23ccc, - 9, 21, i_96ba49d0f8b23ccc, nullptr, nullptr, { &s_96ba49d0f8b23ccc, nullptr, nullptr, 0, 0, nullptr }, true + 0x96ba49d0f8b23ccc, b_96ba49d0f8b23ccc.words, 387, d_96ba49d0f8b23ccc, m_96ba49d0f8b23ccc, + 10, 22, i_96ba49d0f8b23ccc, nullptr, nullptr, { &s_96ba49d0f8b23ccc, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<69> b_9df6f2a42c4e5f0b = { @@ -9733,6 +9754,149 @@ const ::capnp::_::RawSchema s_ebe17f59ac9a1df1 = { 1, 1, i_ebe17f59ac9a1df1, nullptr, nullptr, { &s_ebe17f59ac9a1df1, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE +static const ::capnp::_::AlignedData<53> b_ca2d4d0bfe4ae5d9 = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 217, 229, 74, 254, 11, 77, 45, 202, + 18, 0, 0, 0, 1, 0, 1, 0, + 127, 216, 135, 181, 36, 146, 125, 181, + 1, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 250, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 105, 108, 101, 100, 98, 45, 114, + 101, 115, 116, 46, 99, 97, 112, 110, + 112, 58, 81, 117, 101, 114, 121, 67, + 104, 97, 110, 110, 101, 108, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 8, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 3, 0, 1, 0, + 48, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 3, 0, 1, 0, + 72, 0, 0, 0, 2, 0, 1, 0, + 100, 101, 102, 97, 117, 108, 116, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 103, 103, 114, 101, 103, 97, 116, + 101, 115, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 46, 16, 159, 90, 244, 241, 147, 225, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_ca2d4d0bfe4ae5d9 = b_ca2d4d0bfe4ae5d9.words; +#if !CAPNP_LITE +static const ::capnp::_::RawSchema* const d_ca2d4d0bfe4ae5d9[] = { + &s_e193f1f45a9f102e, +}; +static const uint16_t m_ca2d4d0bfe4ae5d9[] = {1, 0}; +static const uint16_t i_ca2d4d0bfe4ae5d9[] = {0, 1}; +const ::capnp::_::RawSchema s_ca2d4d0bfe4ae5d9 = { + 0xca2d4d0bfe4ae5d9, b_ca2d4d0bfe4ae5d9.words, 53, d_ca2d4d0bfe4ae5d9, m_ca2d4d0bfe4ae5d9, + 1, 2, i_ca2d4d0bfe4ae5d9, nullptr, nullptr, { &s_ca2d4d0bfe4ae5d9, nullptr, nullptr, 0, 0, nullptr }, false +}; +#endif // !CAPNP_LITE +static const ::capnp::_::AlignedData<65> b_e193f1f45a9f102e = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 46, 16, 159, 90, 244, 241, 147, 225, + 18, 0, 0, 0, 1, 0, 0, 0, + 127, 216, 135, 181, 36, 146, 125, 181, + 3, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 226, 0, 0, 0, + 33, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 105, 108, 101, 100, 98, 45, 114, + 101, 115, 116, 46, 99, 97, 112, 110, + 112, 58, 65, 103, 103, 114, 101, 103, + 97, 116, 101, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 69, 0, 0, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 68, 0, 0, 0, 3, 0, 1, 0, + 80, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 3, 0, 1, 0, + 88, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 80, 0, 0, 0, 3, 0, 1, 0, + 92, 0, 0, 0, 2, 0, 1, 0, + 111, 117, 116, 112, 117, 116, 70, 105, + 101, 108, 100, 78, 97, 109, 101, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 110, 112, 117, 116, 70, 105, 101, + 108, 100, 78, 97, 109, 101, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 110, 97, 109, 101, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_e193f1f45a9f102e = b_e193f1f45a9f102e.words; +#if !CAPNP_LITE +static const uint16_t m_e193f1f45a9f102e[] = {1, 2, 0}; +static const uint16_t i_e193f1f45a9f102e[] = {0, 1, 2}; +const ::capnp::_::RawSchema s_e193f1f45a9f102e = { + 0xe193f1f45a9f102e, b_e193f1f45a9f102e.words, 65, nullptr, m_e193f1f45a9f102e, + 0, 3, i_e193f1f45a9f102e, nullptr, nullptr, { &s_e193f1f45a9f102e, nullptr, nullptr, 0, 0, nullptr }, false +}; +#endif // !CAPNP_LITE } // namespace schemas } // namespace capnp @@ -10787,6 +10951,30 @@ constexpr ::capnp::_::RawSchema const* LoadArraySchemaResponse::_capnpPrivate::s #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE +// QueryChannel +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t QueryChannel::_capnpPrivate::dataWordSize; +constexpr uint16_t QueryChannel::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if !CAPNP_LITE +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind QueryChannel::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* QueryChannel::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#endif // !CAPNP_LITE + +// Aggregate +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint16_t Aggregate::_capnpPrivate::dataWordSize; +constexpr uint16_t Aggregate::_capnpPrivate::pointerCount; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#if !CAPNP_LITE +#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr ::capnp::Kind Aggregate::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* Aggregate::_capnpPrivate::schema; +#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL +#endif // !CAPNP_LITE + } // namespace } // namespace diff --git a/tiledb/sm/serialization/tiledb-rest.capnp.h b/tiledb/sm/serialization/tiledb-rest.capnp.h index 0e68ba5f844..f4f8b9694c1 100644 --- a/tiledb/sm/serialization/tiledb-rest.capnp.h +++ b/tiledb/sm/serialization/tiledb-rest.capnp.h @@ -108,6 +108,8 @@ CAPNP_DECLARE_SCHEMA(891a70a671f15cf6); CAPNP_DECLARE_SCHEMA(805c080c10c1e959); CAPNP_DECLARE_SCHEMA(83f094010132ff21); CAPNP_DECLARE_SCHEMA(ebe17f59ac9a1df1); +CAPNP_DECLARE_SCHEMA(ca2d4d0bfe4ae5d9); +CAPNP_DECLARE_SCHEMA(e193f1f45a9f102e); } // namespace schemas } // namespace capnp @@ -1004,7 +1006,7 @@ struct Query { class Pipeline; struct _capnpPrivate { - CAPNP_DECLARE_STRUCT_HEADER(96ba49d0f8b23ccc, 4, 16) + CAPNP_DECLARE_STRUCT_HEADER(96ba49d0f8b23ccc, 4, 17) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; @@ -1685,6 +1687,40 @@ struct LoadArraySchemaResponse { }; }; +struct QueryChannel { + QueryChannel() = delete; + + class Reader; + class Builder; + class Pipeline; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(ca2d4d0bfe4ae5d9, 1, 1) +#if !CAPNP_LITE + static constexpr ::capnp::_::RawBrandedSchema const* brand() { + return &schema->defaultBrand; + } +#endif // !CAPNP_LITE + }; +}; + +struct Aggregate { + Aggregate() = delete; + + class Reader; + class Builder; + class Pipeline; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(e193f1f45a9f102e, 0, 3) +#if !CAPNP_LITE + static constexpr ::capnp::_::RawBrandedSchema const* brand() { + return &schema->defaultBrand; + } +#endif // !CAPNP_LITE + }; +}; + // ======================================================================================= class DomainArray::Reader { @@ -8909,6 +8945,12 @@ class Query::Reader { inline ::tiledb::sm::serialization::capnp::QueryReader::Reader getOrderedDimLabelReader() const; + inline bool hasChannels() const; + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Reader + getChannels() const; + private: ::capnp::_::StructReader _reader; template @@ -9144,6 +9186,27 @@ class Query::Builder { inline ::capnp::Orphan<::tiledb::sm::serialization::capnp::QueryReader> disownOrderedDimLabelReader(); + inline bool hasChannels(); + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Builder + getChannels(); + inline void setChannels(::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Builder + initChannels(unsigned int size); + inline void adoptChannels( + ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>> + disownChannels(); + private: ::capnp::_::StructBuilder _builder; template @@ -14843,6 +14906,241 @@ class LoadArraySchemaResponse::Pipeline { }; #endif // !CAPNP_LITE +class QueryChannel::Reader { + public: + typedef QueryChannel Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base) + : _reader(base) { + } + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } +#endif // !CAPNP_LITE + + inline bool getDefault() const; + + inline bool hasAggregates() const; + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Reader + getAggregates() const; + + private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class QueryChannel::Builder { + public: + typedef QueryChannel Builds; + + Builder() = delete; // Deleted to discourage incorrect usage. + // You can explicitly initialize to nullptr instead. + inline Builder(decltype(nullptr)) { + } + inline explicit Builder(::capnp::_::StructBuilder base) + : _builder(base) { + } + inline operator Reader() const { + return Reader(_builder.asReader()); + } + inline Reader asReader() const { + return *this; + } + + inline ::capnp::MessageSize totalSize() const { + return asReader().totalSize(); + } +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { + return asReader().toString(); + } +#endif // !CAPNP_LITE + + inline bool getDefault(); + inline void setDefault(bool value); + + inline bool hasAggregates(); + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Builder + getAggregates(); + inline void setAggregates(::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Reader value); + inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Builder + initAggregates(unsigned int size); + inline void adoptAggregates(::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>&& value); + inline ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>> + disownAggregates(); + + private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + +#if !CAPNP_LITE +class QueryChannel::Pipeline { + public: + typedef QueryChannel Pipelines; + + inline Pipeline(decltype(nullptr)) + : _typeless(nullptr) { + } + inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) + : _typeless(kj::mv(typeless)) { + } + + private: + ::capnp::AnyPointer::Pipeline _typeless; + friend class ::capnp::PipelineHook; + template + friend struct ::capnp::ToDynamic_; +}; +#endif // !CAPNP_LITE + +class Aggregate::Reader { + public: + typedef Aggregate Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base) + : _reader(base) { + } + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } +#endif // !CAPNP_LITE + + inline bool hasOutputFieldName() const; + inline ::capnp::Text::Reader getOutputFieldName() const; + + inline bool hasInputFieldName() const; + inline ::capnp::Text::Reader getInputFieldName() const; + + inline bool hasName() const; + inline ::capnp::Text::Reader getName() const; + + private: + ::capnp::_::StructReader _reader; + template + friend struct ::capnp::ToDynamic_; + template + friend struct ::capnp::_::PointerHelpers; + template + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class Aggregate::Builder { + public: + typedef Aggregate Builds; + + Builder() = delete; // Deleted to discourage incorrect usage. + // You can explicitly initialize to nullptr instead. + inline Builder(decltype(nullptr)) { + } + inline explicit Builder(::capnp::_::StructBuilder base) + : _builder(base) { + } + inline operator Reader() const { + return Reader(_builder.asReader()); + } + inline Reader asReader() const { + return *this; + } + + inline ::capnp::MessageSize totalSize() const { + return asReader().totalSize(); + } +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { + return asReader().toString(); + } +#endif // !CAPNP_LITE + + inline bool hasOutputFieldName(); + inline ::capnp::Text::Builder getOutputFieldName(); + inline void setOutputFieldName(::capnp::Text::Reader value); + inline ::capnp::Text::Builder initOutputFieldName(unsigned int size); + inline void adoptOutputFieldName(::capnp::Orphan<::capnp::Text>&& value); + inline ::capnp::Orphan<::capnp::Text> disownOutputFieldName(); + + inline bool hasInputFieldName(); + inline ::capnp::Text::Builder getInputFieldName(); + inline void setInputFieldName(::capnp::Text::Reader value); + inline ::capnp::Text::Builder initInputFieldName(unsigned int size); + inline void adoptInputFieldName(::capnp::Orphan<::capnp::Text>&& value); + inline ::capnp::Orphan<::capnp::Text> disownInputFieldName(); + + inline bool hasName(); + inline ::capnp::Text::Builder getName(); + inline void setName(::capnp::Text::Reader value); + inline ::capnp::Text::Builder initName(unsigned int size); + inline void adoptName(::capnp::Orphan<::capnp::Text>&& value); + inline ::capnp::Orphan<::capnp::Text> disownName(); + + private: + ::capnp::_::StructBuilder _builder; + template + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template + friend struct ::capnp::_::PointerHelpers; +}; + +#if !CAPNP_LITE +class Aggregate::Pipeline { + public: + typedef Aggregate Pipelines; + + inline Pipeline(decltype(nullptr)) + : _typeless(nullptr) { + } + inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) + : _typeless(kj::mv(typeless)) { + } + + private: + ::capnp::AnyPointer::Pipeline _typeless; + friend class ::capnp::PipelineHook; + template + friend struct ::capnp::ToDynamic_; +}; +#endif // !CAPNP_LITE + // ======================================================================================= inline bool DomainArray::Reader::hasInt8() const { @@ -24856,6 +25154,80 @@ Query::Builder::disownOrderedDimLabelReader() { _builder.getPointerField(::capnp::bounded<15>() * ::capnp::POINTERS)); } +inline bool Query::Reader::hasChannels() const { + return !_reader.getPointerField(::capnp::bounded<16>() * ::capnp::POINTERS) + .isNull(); +} +inline bool Query::Builder::hasChannels() { + return !_builder.getPointerField(::capnp::bounded<16>() * ::capnp::POINTERS) + .isNull(); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Reader +Query::Reader::getChannels() const { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>::get(_reader + .getPointerField( + ::capnp::bounded<16>() * + ::capnp::POINTERS)); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Builder +Query::Builder::getChannels() { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>::get(_builder + .getPointerField( + ::capnp::bounded<16>() * + ::capnp::POINTERS)); +} +inline void Query::Builder::setChannels( + ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>:: + set(_builder.getPointerField(::capnp::bounded<16>() * ::capnp::POINTERS), + value); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>::Builder +Query::Builder::initChannels(unsigned int size) { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>:: + init( + _builder.getPointerField(::capnp::bounded<16>() * ::capnp::POINTERS), + size); +} +inline void Query::Builder::adoptChannels( + ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>:: + adopt( + _builder.getPointerField(::capnp::bounded<16>() * ::capnp::POINTERS), + kj::mv(value)); +} +inline ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>> +Query::Builder::disownChannels() { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::QueryChannel, + ::capnp::Kind::STRUCT>>::disown(_builder + .getPointerField( + ::capnp::bounded<16>() * + ::capnp::POINTERS)); +} + inline bool NonEmptyDomain::Reader::hasNonEmptyDomain() const { return !_reader.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS) .isNull(); @@ -31587,6 +31959,207 @@ LoadArraySchemaResponse::Builder::disownSchema() { _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS)); } +inline bool QueryChannel::Reader::getDefault() const { + return _reader.getDataField(::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline bool QueryChannel::Builder::getDefault() { + return _builder.getDataField(::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void QueryChannel::Builder::setDefault(bool value) { + _builder.setDataField(::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline bool QueryChannel::Reader::hasAggregates() const { + return !_reader.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS) + .isNull(); +} +inline bool QueryChannel::Builder::hasAggregates() { + return !_builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS) + .isNull(); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Reader +QueryChannel::Reader::getAggregates() const { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>::get(_reader + .getPointerField( + ::capnp::bounded<0>() * + ::capnp::POINTERS)); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Builder +QueryChannel::Builder::getAggregates() { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>::get(_builder + .getPointerField( + ::capnp::bounded<0>() * + ::capnp::POINTERS)); +} +inline void QueryChannel::Builder::setAggregates( + ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Reader value) { + ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>:: + set(_builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + value); +} +inline ::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>::Builder +QueryChannel::Builder::initAggregates(unsigned int size) { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>:: + init( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + size); +} +inline void QueryChannel::Builder::adoptAggregates( + ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>&& value) { + ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>:: + adopt( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + kj::mv(value)); +} +inline ::capnp::Orphan<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>> +QueryChannel::Builder::disownAggregates() { + return ::capnp::_::PointerHelpers<::capnp::List< + ::tiledb::sm::serialization::capnp::Aggregate, + ::capnp::Kind::STRUCT>>::disown(_builder + .getPointerField( + ::capnp::bounded<0>() * + ::capnp::POINTERS)); +} + +inline bool Aggregate::Reader::hasOutputFieldName() const { + return !_reader.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS) + .isNull(); +} +inline bool Aggregate::Builder::hasOutputFieldName() { + return !_builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS) + .isNull(); +} +inline ::capnp::Text::Reader Aggregate::Reader::getOutputFieldName() const { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _reader.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Aggregate::Builder::getOutputFieldName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void Aggregate::Builder::setOutputFieldName( + ::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers<::capnp::Text>::set( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + value); +} +inline ::capnp::Text::Builder Aggregate::Builder::initOutputFieldName( + unsigned int size) { + return ::capnp::_::PointerHelpers<::capnp::Text>::init( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + size); +} +inline void Aggregate::Builder::adoptOutputFieldName( + ::capnp::Orphan<::capnp::Text>&& value) { + ::capnp::_::PointerHelpers<::capnp::Text>::adopt( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS), + kj::mv(value)); +} +inline ::capnp::Orphan<::capnp::Text> +Aggregate::Builder::disownOutputFieldName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::disown( + _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool Aggregate::Reader::hasInputFieldName() const { + return !_reader.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS) + .isNull(); +} +inline bool Aggregate::Builder::hasInputFieldName() { + return !_builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS) + .isNull(); +} +inline ::capnp::Text::Reader Aggregate::Reader::getInputFieldName() const { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _reader.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Aggregate::Builder::getInputFieldName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void Aggregate::Builder::setInputFieldName(::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers<::capnp::Text>::set( + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS), + value); +} +inline ::capnp::Text::Builder Aggregate::Builder::initInputFieldName( + unsigned int size) { + return ::capnp::_::PointerHelpers<::capnp::Text>::init( + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS), + size); +} +inline void Aggregate::Builder::adoptInputFieldName( + ::capnp::Orphan<::capnp::Text>&& value) { + ::capnp::_::PointerHelpers<::capnp::Text>::adopt( + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS), + kj::mv(value)); +} +inline ::capnp::Orphan<::capnp::Text> +Aggregate::Builder::disownInputFieldName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::disown( + _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS)); +} + +inline bool Aggregate::Reader::hasName() const { + return !_reader.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS) + .isNull(); +} +inline bool Aggregate::Builder::hasName() { + return !_builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS) + .isNull(); +} +inline ::capnp::Text::Reader Aggregate::Reader::getName() const { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _reader.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline ::capnp::Text::Builder Aggregate::Builder::getName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::get( + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS)); +} +inline void Aggregate::Builder::setName(::capnp::Text::Reader value) { + ::capnp::_::PointerHelpers<::capnp::Text>::set( + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS), + value); +} +inline ::capnp::Text::Builder Aggregate::Builder::initName(unsigned int size) { + return ::capnp::_::PointerHelpers<::capnp::Text>::init( + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS), + size); +} +inline void Aggregate::Builder::adoptName( + ::capnp::Orphan<::capnp::Text>&& value) { + ::capnp::_::PointerHelpers<::capnp::Text>::adopt( + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS), + kj::mv(value)); +} +inline ::capnp::Orphan<::capnp::Text> Aggregate::Builder::disownName() { + return ::capnp::_::PointerHelpers<::capnp::Text>::disown( + _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS)); +} + } // namespace capnp } // namespace serialization } // namespace sm