cql3: Fix partition key bind indices for prepared statements
Fix the CQL front-end to populate the partition key bind index array in result message prepared metadata, which is needed for CQL binary protocol v4 to function correctly. Fixes #2355. Message-Id: <1494247871-3148-1-git-send-email-penberg@scylladb.com>
This commit is contained in:
@@ -414,8 +414,18 @@ std::unique_ptr<prepared_statement>
|
||||
batch_statement::prepare(database& db, cql_stats& stats) {
|
||||
auto&& bound_names = get_bound_variables();
|
||||
|
||||
stdx::optional<sstring> first_ks;
|
||||
stdx::optional<sstring> first_cf;
|
||||
bool have_multiple_cfs = false;
|
||||
|
||||
std::vector<shared_ptr<cql3::statements::modification_statement>> statements;
|
||||
for (auto&& parsed : _parsed_statements) {
|
||||
if (!first_ks) {
|
||||
first_ks = parsed->keyspace();
|
||||
first_cf = parsed->column_family();
|
||||
} else {
|
||||
have_multiple_cfs = first_ks.value() != parsed->keyspace() || first_cf.value() != parsed->column_family();
|
||||
}
|
||||
statements.push_back(parsed->prepare(db, bound_names, stats));
|
||||
}
|
||||
|
||||
@@ -425,8 +435,13 @@ batch_statement::prepare(database& db, cql_stats& stats) {
|
||||
cql3::statements::batch_statement batch_statement_(bound_names->size(), _type, std::move(statements), std::move(prep_attrs), stats);
|
||||
batch_statement_.validate();
|
||||
|
||||
std::vector<uint16_t> partition_key_bind_indices;
|
||||
if (!have_multiple_cfs && batch_statement_.get_statements().size() > 0) {
|
||||
partition_key_bind_indices = bound_names->get_partition_key_bind_indexes(batch_statement_.get_statements()[0]->s);
|
||||
}
|
||||
return std::make_unique<prepared>(make_shared(std::move(batch_statement_)),
|
||||
bound_names->get_specifications());
|
||||
bound_names->get_specifications(),
|
||||
std::move(partition_key_bind_indices));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -516,9 +516,11 @@ namespace raw {
|
||||
|
||||
std::unique_ptr<prepared_statement>
|
||||
modification_statement::modification_statement::prepare(database& db, cql_stats& stats) {
|
||||
schema_ptr schema = validation::validate_column_family(db, keyspace(), column_family());
|
||||
auto bound_names = get_bound_variables();
|
||||
auto statement = prepare(db, bound_names, stats);
|
||||
return std::make_unique<prepared>(std::move(statement), *bound_names);
|
||||
auto partition_key_bind_indices = bound_names->get_partition_key_bind_indexes(schema);
|
||||
return std::make_unique<prepared>(std::move(statement), *bound_names, std::move(partition_key_bind_indices));
|
||||
}
|
||||
|
||||
::shared_ptr<cql3::statements::modification_statement>
|
||||
|
||||
@@ -67,21 +67,22 @@ bool parsed_statement::uses_function(const sstring& ks_name, const sstring& func
|
||||
|
||||
}
|
||||
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, std::vector<::shared_ptr<column_specification>> bound_names_)
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, std::vector<::shared_ptr<column_specification>> bound_names_, std::vector<uint16_t> partition_key_bind_indices)
|
||||
: statement(std::move(statement_))
|
||||
, bound_names(std::move(bound_names_))
|
||||
, partition_key_bind_indices(std::move(partition_key_bind_indices))
|
||||
{ }
|
||||
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, const variable_specifications& names)
|
||||
: prepared_statement(statement_, names.get_specifications())
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, const variable_specifications& names, const std::vector<uint16_t>& partition_key_bind_indices)
|
||||
: prepared_statement(statement_, names.get_specifications(), partition_key_bind_indices)
|
||||
{ }
|
||||
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, variable_specifications&& names)
|
||||
: prepared_statement(statement_, std::move(names).get_specifications())
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement> statement_, variable_specifications&& names, std::vector<uint16_t>&& partition_key_bind_indices)
|
||||
: prepared_statement(statement_, std::move(names).get_specifications(), std::move(partition_key_bind_indices))
|
||||
{ }
|
||||
|
||||
prepared_statement::prepared_statement(::shared_ptr<cql_statement>&& statement_)
|
||||
: prepared_statement(statement_, std::vector<::shared_ptr<column_specification>>())
|
||||
: prepared_statement(statement_, std::vector<::shared_ptr<column_specification>>(), std::vector<uint16_t>())
|
||||
{ }
|
||||
|
||||
}
|
||||
|
||||
@@ -71,12 +71,13 @@ public:
|
||||
sstring raw_cql_statement;
|
||||
const ::shared_ptr<cql_statement> statement;
|
||||
const std::vector<::shared_ptr<column_specification>> bound_names;
|
||||
std::vector<uint16_t> partition_key_bind_indices;
|
||||
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, std::vector<::shared_ptr<column_specification>> bound_names_);
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, std::vector<::shared_ptr<column_specification>> bound_names_, std::vector<uint16_t> partition_key_bind_indices);
|
||||
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, const variable_specifications& names);
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, const variable_specifications& names, const std::vector<uint16_t>& partition_key_bind_indices);
|
||||
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, variable_specifications&& names);
|
||||
prepared_statement(::shared_ptr<cql_statement> statement_, variable_specifications&& names, std::vector<uint16_t>&& partition_key_bind_indices);
|
||||
|
||||
prepared_statement(::shared_ptr<cql_statement>&& statement_);
|
||||
|
||||
|
||||
@@ -460,7 +460,9 @@ std::unique_ptr<prepared_statement> select_statement::prepare(database& db, cql_
|
||||
prepare_limit(db, bound_names),
|
||||
stats);
|
||||
|
||||
return std::make_unique<prepared>(std::move(stmt), std::move(*bound_names));
|
||||
auto partition_key_bind_indices = bound_names->get_partition_key_bind_indexes(schema);
|
||||
|
||||
return std::make_unique<prepared>(std::move(stmt), std::move(*bound_names), std::move(partition_key_bind_indices));
|
||||
}
|
||||
|
||||
::shared_ptr<restrictions::statement_restrictions>
|
||||
|
||||
@@ -80,6 +80,26 @@ public:
|
||||
return std::move(_specs);
|
||||
}
|
||||
|
||||
std::vector<uint16_t> get_partition_key_bind_indexes(schema_ptr schema) const {
|
||||
auto count = schema->partition_key_columns().size();
|
||||
std::vector<uint16_t> partition_key_positions(count, uint16_t(0));
|
||||
std::vector<bool> set(count, false);
|
||||
for (size_t i = 0; i < _specs.size(); i++) {
|
||||
auto& target_column = _specs[i];
|
||||
const auto* cdef = schema->get_column_definition(target_column->name->name());
|
||||
if (cdef && cdef->is_partition_key()) {
|
||||
partition_key_positions[cdef->position()] = i;
|
||||
set[cdef->position()] = true;
|
||||
}
|
||||
}
|
||||
for (bool b : set) {
|
||||
if (!b) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return partition_key_positions;
|
||||
}
|
||||
|
||||
void add(int32_t bind_index, ::shared_ptr<column_specification> spec) {
|
||||
auto name = _variable_names[bind_index];
|
||||
// Use the user name, if there is one
|
||||
|
||||
@@ -43,8 +43,7 @@ private:
|
||||
protected:
|
||||
prepared(cql3::statements::prepared_statement::checked_weak_ptr prepared)
|
||||
: _prepared(std::move(prepared))
|
||||
// FIXME: Populate partition key bind indices for prepared_metadata.
|
||||
, _metadata{::make_shared<cql3::prepared_metadata>(_prepared->bound_names, std::vector<uint16_t>())}
|
||||
, _metadata{::make_shared<cql3::prepared_metadata>(_prepared->bound_names, _prepared->partition_key_bind_indices)}
|
||||
, _result_metadata{extract_result_metadata(_prepared->statement)}
|
||||
{ }
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user