diff --git a/alternator/executor.cc b/alternator/executor.cc index b706e856ec..fbeb902bbb 100644 --- a/alternator/executor.cc +++ b/alternator/executor.cc @@ -669,6 +669,58 @@ std::unordered_set calculate_attrs_to_get(const Json::Value& req) { return {}; } +static std::optional describe_single_item(schema_ptr schema, const query::partition_slice& slice, const cql3::selection::selection& selection, foreign_ptr> query_result, std::unordered_set&& attrs_to_get) { + Json::Value item(Json::objectValue); + + cql3::selection::result_set_builder builder(selection, gc_clock::now(), cql_serialization_format::latest()); + query::result_view::consume(*query_result, slice, cql3::selection::result_set_builder::visitor(builder, *schema, selection)); + + auto result_set = builder.build(); + if (result_set->empty()) { + // If there is no matching item, we're supposed to return an empty + // object without an Item member - not one with an empty Item member + return {}; + } + // FIXME: I think this can't really be a loop, there should be exactly + // one result after above we handled the 0 result case + for (auto& result_row : result_set->rows()) { + const auto& columns = selection.get_columns(); + auto column_it = columns.begin(); + for (const bytes_opt& cell : result_row) { + std::string column_name = (*column_it)->name_as_text(); + if (cell && column_name != executor::ATTRS_COLUMN_NAME) { + if (attrs_to_get.empty() || attrs_to_get.count(column_name) > 0) { + Json::Value& field = item[column_name.c_str()]; + field[type_to_string((*column_it)->type)] = json_key_column_value(*cell, **column_it); + } + } else if (cell) { + auto deserialized = attrs_type()->deserialize(*cell, cql_serialization_format::latest()); + auto keys_and_values = value_cast(deserialized); + for (auto entry : keys_and_values) { + std::string attr_name = value_cast(entry.first); + if (attrs_to_get.empty() || attrs_to_get.count(attr_name) > 0) { + bytes value = value_cast(entry.second); + item[attr_name] = deserialize_item(value); + } + } + } + ++column_it; + } + } + return item; +} + +static Json::Value describe_item(schema_ptr schema, const query::partition_slice& slice, const cql3::selection::selection& selection, foreign_ptr> query_result, std::unordered_set&& attrs_to_get) { + std::optional opt_item = describe_single_item(std::move(schema), slice, selection, std::move(query_result), std::move(attrs_to_get)); + if (!opt_item) { + // If there is no matching item, we're supposed to return an empty + // object without an Item member - not one with an empty Item member + return Json::objectValue; + } + Json::Value item_descr(Json::objectValue); + item_descr["Item"] = *opt_item; + return item_descr; +} future executor::update_item(std::string content) { _stats.api_operations.update_item++; @@ -791,58 +843,6 @@ future executor::update_item(std::string content) { }); } -static std::optional describe_single_item(schema_ptr schema, const query::partition_slice& slice, const cql3::selection::selection& selection, foreign_ptr> query_result, std::unordered_set&& attrs_to_get) { - Json::Value item(Json::objectValue); - - cql3::selection::result_set_builder builder(selection, gc_clock::now(), cql_serialization_format::latest()); - query::result_view::consume(*query_result, slice, cql3::selection::result_set_builder::visitor(builder, *schema, selection)); - - auto result_set = builder.build(); - if (result_set->empty()) { - // If there is no matching item, we're supposed to return an empty - // object without an Item member - not one with an empty Item member - return {}; - } - // FIXME: I think this can't really be a loop, there should be exactly - // one result after above we handled the 0 result case - for (auto& result_row : result_set->rows()) { - const auto& columns = selection.get_columns(); - auto column_it = columns.begin(); - for (const bytes_opt& cell : result_row) { - std::string column_name = (*column_it)->name_as_text(); - if (cell && column_name != executor::ATTRS_COLUMN_NAME) { - if (attrs_to_get.empty() || attrs_to_get.count(column_name) > 0) { - Json::Value& field = item[column_name.c_str()]; - field[type_to_string((*column_it)->type)] = json_key_column_value(*cell, **column_it); - } - } else if (cell) { - auto deserialized = attrs_type()->deserialize(*cell, cql_serialization_format::latest()); - auto keys_and_values = value_cast(deserialized); - for (auto entry : keys_and_values) { - std::string attr_name = value_cast(entry.first); - if (attrs_to_get.empty() || attrs_to_get.count(attr_name) > 0) { - bytes value = value_cast(entry.second); - item[attr_name] = deserialize_item(value); - } - } - } - ++column_it; - } - } - return item; -} -static Json::Value describe_item(schema_ptr schema, const query::partition_slice& slice, const cql3::selection::selection& selection, foreign_ptr> query_result, std::unordered_set&& attrs_to_get) { - std::optional opt_item = describe_single_item(std::move(schema), slice, selection, std::move(query_result), std::move(attrs_to_get)); - if (!opt_item) { - // If there is no matching item, we're supposed to return an empty - // object without an Item member - not one with an empty Item member - return Json::objectValue; - } - Json::Value item_descr(Json::objectValue); - item_descr["Item"] = *opt_item; - return item_descr; -} - // Check according to the request's "ConsistentRead" field, which consistency // level we need to use for the read. The field can be True for strongly // consistent reads, or False for eventually consistent reads, or if this