/* * Copyright (C) 2015-present ScyllaDB * * Modified by ScyllaDB */ /* * SPDX-License-Identifier: (LicenseRef-ScyllaDB-Source-Available-1.0 and Apache-2.0) */ #include #include "utils/assert.hh" #include "utils/hashers.hh" #include "cql3/result_set.hh" namespace cql3 { metadata::metadata(std::vector> names_) : _flags(flag_enum_set()) , _column_info(make_lw_shared(std::move(names_))) { if (!_column_info->_names.empty() && column_specification::all_in_same_table(_column_info->_names)) { _flags.set(); } } metadata::metadata(flag_enum_set flags, std::vector> names_, uint32_t column_count, lw_shared_ptr paging_state) : _flags(flags) , _column_info(make_lw_shared(std::move(names_), column_count)) , _paging_state(std::move(paging_state)) { if (!_column_info->_names.empty() && column_specification::all_in_same_table(_column_info->_names)) { _flags.set(); } } // The maximum number of values that the ResultSet can hold. This can be bigger than columnCount due to CASSANDRA-4911 uint32_t metadata::value_count() const { return _flags.contains() ? _column_info->_column_count : _column_info->_names.size(); } void metadata::add_non_serialized_column(lw_shared_ptr name) { // See comment above. Because columnCount doesn't account the newly added name, it // won't be serialized. _column_info->_names.emplace_back(std::move(name)); } void metadata::set_paging_state(lw_shared_ptr paging_state) { _flags.set(); _paging_state = std::move(paging_state); } void metadata::maybe_set_paging_state(lw_shared_ptr paging_state) { SCYLLA_ASSERT(paging_state); if (paging_state->get_remaining() > 0) { set_paging_state(std::move(paging_state)); } else { _flags.remove(); _paging_state = nullptr; } } void metadata::set_skip_metadata() { _flags.set(); } metadata::flag_enum_set metadata::flags() const { return _flags; } lw_shared_ptr metadata::paging_state() const { return _paging_state; } // Metadata_id is a checksum computed from given metadata to track schema changes in prepared statements. // Originally introduced in CQLv5. cql3::cql_metadata_id_type metadata::calculate_metadata_id() const { auto h = sha256_hasher(); for (uint32_t i = 0; i < _column_info->_column_count; ++i) { feed_hash(h, _column_info->_names[i]->name->name()); feed_hash(h, _column_info->_names[i]->type->name()); } // Return first 16 bytes to have the same length as Cassandra's MD5 return cql_metadata_id_type(h.finalize().substr(0, 16)); } prepared_metadata::prepared_metadata(const std::vector>& names, const std::vector& partition_key_bind_indices, bool is_conditional) : _names{names} , _partition_key_bind_indices{partition_key_bind_indices} { if (!names.empty() && column_specification::all_in_same_table(_names)) { _flags.set(); } if (is_conditional) { _flags.set(); } } prepared_metadata::flag_enum_set prepared_metadata::flags() const { return _flags; } const std::vector>& prepared_metadata::names() const { return _names; } const std::vector& prepared_metadata::partition_key_bind_indices() const { return _partition_key_bind_indices; } result_set::result_set(std::vector> metadata_) : _metadata(::make_shared(std::move(metadata_))) { } result_set::result_set(::shared_ptr metadata) : _metadata(std::move(metadata)) { } size_t result_set::size() const { return _rows.size(); } bool result_set::empty() const { return _rows.empty(); } void result_set::add_row(std::vector row) { SCYLLA_ASSERT(row.size() == _metadata->value_count()); _rows.emplace_back(std::move(row)); } void result_set::add_row(std::vector row) { row_type new_row; new_row.reserve(row.size()); for (auto& bo : row) { new_row.emplace_back(bo ? managed_bytes_opt(*bo) : managed_bytes_opt()); } add_row(std::move(new_row)); } void result_set::add_column_value(managed_bytes_opt value) { if (_rows.empty() || _rows.back().size() == _metadata->value_count()) { std::vector row; row.reserve(_metadata->value_count()); _rows.emplace_back(std::move(row)); } _rows.back().emplace_back(std::move(value)); } void result_set::add_column_value(bytes_opt value) { add_column_value(to_managed_bytes_opt(value)); } void result_set::reverse() { std::reverse(_rows.begin(), _rows.end()); } void result_set::trim(size_t limit) { if (_rows.size() > limit) { _rows.resize(limit); } } metadata& result_set::get_metadata() { return *_metadata; } const metadata& result_set::get_metadata() const { return *_metadata; } const utils::chunked_vector>& result_set::rows() const { return _rows; } shared_ptr make_empty_metadata() { static thread_local shared_ptr empty_metadata_cache = [] { auto result = ::make_shared(std::vector>{}); result->set_skip_metadata(); return result; }(); return empty_metadata_cache; } }