statements/cas_request: fix crash on empty clustering range in LWT
LWT queries with empty clustering range used to cause a crash. For example in: ```cql UPDATE tab SET r = 9000 WHERE p = 1 AND c = 2 AND c = 2000 IF r = 3 ``` The range of `c` is empty - there are no valid values. This caused a segfault when accessing the `first` range: ```c++ op.ranges.front() ``` To fix it let's throw en exception when the clustering range is empty. Cassandra also rejects queries with `c = 1 AND c = 2`. There's also a check for empty partition range, as it used to crash in the past, can't really hurt to add it. Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
This commit is contained in:
@@ -123,6 +123,9 @@ std::optional<mutation> cas_request::apply(foreign_ptr<lw_shared_ptr<query::resu
|
||||
|
||||
cas_request::old_row cas_request::find_old_row(const cas_row_update& op) const {
|
||||
static const clustering_key empty_ckey = clustering_key::make_empty();
|
||||
if (_key.empty()) {
|
||||
throw exceptions::invalid_request_exception("Empty partition key range");
|
||||
}
|
||||
const partition_key& pkey = _key.front().start()->value().key().value();
|
||||
// We must ignore statement clustering column restriction when
|
||||
// choosing a row to check the conditions. If there is no
|
||||
@@ -134,6 +137,9 @@ cas_request::old_row cas_request::find_old_row(const cas_row_update& op) const {
|
||||
// CREATE TABLE t(p int, c int, s int static, v int, PRIMARY KEY(p, c));
|
||||
// INSERT INTO t(p, s) VALUES(1, 1);
|
||||
// UPDATE t SET v=1 WHERE p=1 AND c=1 IF s=1;
|
||||
if (op.ranges.empty()) {
|
||||
throw exceptions::invalid_request_exception("Empty clustering range");
|
||||
}
|
||||
const clustering_key& ckey = op.ranges.front().start() ? op.ranges.front().start()->value() : empty_ckey;
|
||||
auto row = _rows.find_row(pkey, ckey);
|
||||
auto ckey_ptr = &ckey;
|
||||
|
||||
@@ -73,7 +73,6 @@ def test_lwt_empty_partition_range(cql, table1):
|
||||
# Generate an LWT update where there is no value for the clustering key,
|
||||
# as the WHERE restricts it using `c = 2 AND c = 3`.
|
||||
# Such queries are rejected.
|
||||
@pytest.mark.skip(reason="crashes scylla, see issue #13129")
|
||||
def test_lwt_empty_clustering_range(cql, table1):
|
||||
with pytest.raises(InvalidRequest):
|
||||
cql.execute(f"UPDATE {table1} SET r = 9000 WHERE p = 1 AND c = 2 AND c = 2000 IF r = 3")
|
||||
|
||||
Reference in New Issue
Block a user