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:
Pekka Enberg
2017-05-08 15:51:11 +03:00
committed by Avi Kivity
parent 9e67bd5aac
commit dfee4d2bb0
7 changed files with 54 additions and 14 deletions

View File

@@ -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));
}
}

View File

@@ -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>

View File

@@ -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>())
{ }
}

View File

@@ -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_);

View File

@@ -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>

View File

@@ -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

View File

@@ -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: