cql/query_options: add a check for missing bind marker name
There was a missing check in validation of named
bind markers.
Let's say that a user prepares a query like:
```cql
INSERT INTO ks.tab (pk, ck, v) VALUES (:pk, :ck, :v)
```
Then they execute the query, but specify only
values for `:pk` and `:ck`.
We should detect that a value for :v is missing
and throw an invalid_request_exception.
Until now there was no such check, in case of a missing variable
invalid `query_options` were created and Scylla crashed.
Sadly it's impossible to create a regression test
using `cql-pytest` or `boost`.
`cql-pytest` uses the python driver, which silently
ignores mising named bind variables, deciding
that the user meant to send an UNSET_VALUE for them.
When given values like `{'pk': 1, 'ck': 2}`, it will automaticaly
extend them to `{'pk': 1, 'ck': 2, 'v': UNSET_VALUE}`.
In `boost` I tried to use `cql_test_env`,
but it only has methods which take valid `query_options`
as a parameter. I could create a separate unit tests
for the creation and validation of `query_options`
but it won't be a true end-to-end test like `cql-pytest`.
The bug was found using the rust driver,
the reproducer is available in the issue description.
Fixes: #12727
Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
Closes #12730
(cherry picked from commit 2a5ed115ca)
This commit is contained in:
@@ -135,12 +135,21 @@ void query_options::prepare(const std::vector<lw_shared_ptr<column_specification
|
||||
ordered_values.reserve(specs.size());
|
||||
for (auto&& spec : specs) {
|
||||
auto& spec_name = spec->name->text();
|
||||
bool found_value_for_name = false;
|
||||
for (size_t j = 0; j < names.size(); j++) {
|
||||
if (names[j] == spec_name) {
|
||||
ordered_values.emplace_back(_value_views[j]);
|
||||
found_value_for_name = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No bound value was found with the name `spec_name`.
|
||||
// This means that the user forgot to include a bound value with such name.
|
||||
if (!found_value_for_name) {
|
||||
throw exceptions::invalid_request_exception(
|
||||
format("Missing value for bind marker with name: {}", spec_name));
|
||||
}
|
||||
}
|
||||
_value_views = std::move(ordered_values);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user