mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-29 11:10:40 +00:00
cql3: expr: Add evaluate_IN_list
A list representing IN values might contain NULLs before evaluation. We can remove them during evaluation, because nothing equals NULL. If we don't remove them, there are gonna be errors, because a list can't contain NULLs. Signed-off-by: Jan Ciolek <jan.ciolek@scylladb.com>
This commit is contained in:
@@ -1364,6 +1364,43 @@ constant evaluate(term& term_ref, const query_options& options) {
|
||||
return evaluate(&term_ref, options);
|
||||
}
|
||||
|
||||
constant evaluate_IN_list(term* term_ptr, const query_options& options) {
|
||||
if (term_ptr == nullptr) {
|
||||
return constant::make_null();
|
||||
}
|
||||
|
||||
::shared_ptr<terminal> bound;
|
||||
lists::delayed_value* delayed_list = dynamic_cast<lists::delayed_value*>(term_ptr);
|
||||
if (delayed_list != nullptr) {
|
||||
bound = delayed_list->bind_ignore_null(options);
|
||||
} else {
|
||||
bound = term_ptr->bind(options);
|
||||
}
|
||||
|
||||
if (bound.get() == nullptr) {
|
||||
return constant::make_null();
|
||||
}
|
||||
|
||||
lists::value* list_value = dynamic_cast<lists::value*>(bound.get());
|
||||
if (list_value != nullptr) {
|
||||
// Remove NULL elements from the list
|
||||
std::remove_if(list_value->_elements.begin(), list_value->_elements.end(),
|
||||
[](const managed_bytes_opt& element) { return !element.has_value(); });
|
||||
}
|
||||
|
||||
raw_value raw_val = bound->get(options);
|
||||
data_type val_type = bound->get_value_type();
|
||||
return constant(std::move(raw_val), std::move(val_type));
|
||||
}
|
||||
|
||||
constant evaluate_IN_list(const ::shared_ptr<term>& term_ptr, const query_options& options) {
|
||||
return evaluate_IN_list(term_ptr.get(), options);
|
||||
}
|
||||
|
||||
constant evaluate_IN_list(term& term_ref, const query_options& options) {
|
||||
return evaluate_IN_list(&term_ref, options);
|
||||
}
|
||||
|
||||
cql3::raw_value_view evaluate_to_raw_view(const ::shared_ptr<term>& term_ptr, const query_options& options) {
|
||||
constant value = evaluate(term_ptr, options);
|
||||
return cql3::raw_value_view::make_temporary(std::move(value.value));
|
||||
|
||||
@@ -546,6 +546,12 @@ constant evaluate(const ::shared_ptr<term>&, const query_options&);
|
||||
constant evaluate(term*, const query_options&);
|
||||
constant evaluate(term&, const query_options&);
|
||||
|
||||
// Similar to evaluate(), but ignores any NULL values in the final list value.
|
||||
// In an IN restriction nulls can be ignored, because nothing equals NULL.
|
||||
constant evaluate_IN_list(const ::shared_ptr<term>&, const query_options&);
|
||||
constant evaluate_IN_list(term*, const query_options&);
|
||||
constant evaluate_IN_list(term&, const query_options&);
|
||||
|
||||
// Calls evaluate() on the term and then converts the constant to raw_value_view
|
||||
cql3::raw_value_view evaluate_to_raw_view(const ::shared_ptr<term>&, const query_options&);
|
||||
cql3::raw_value_view evaluate_to_raw_view(term&, const query_options&);
|
||||
|
||||
@@ -149,6 +149,25 @@ lists::delayed_value::bind(const query_options& options) {
|
||||
return ::make_shared<value>(buffers, _my_type);
|
||||
}
|
||||
|
||||
shared_ptr<terminal>
|
||||
lists::delayed_value::bind_ignore_null(const query_options& options) {
|
||||
utils::chunked_vector<managed_bytes_opt> buffers;
|
||||
buffers.reserve(_elements.size());
|
||||
for (auto&& t : _elements) {
|
||||
auto bo = t->bind_and_get(options);
|
||||
|
||||
if (bo.is_null()) {
|
||||
continue;
|
||||
}
|
||||
if (bo.is_unset_value()) {
|
||||
return constants::UNSET_VALUE;
|
||||
}
|
||||
|
||||
buffers.push_back(bo.with_value([] (const FragmentedView auto& v) { return managed_bytes(v); }));
|
||||
}
|
||||
return ::make_shared<value>(buffers, _my_type);
|
||||
}
|
||||
|
||||
::shared_ptr<terminal>
|
||||
lists::marker::bind(const query_options& options) {
|
||||
const auto& value = options.get_value_at(_bind_index);
|
||||
|
||||
@@ -93,6 +93,9 @@ public:
|
||||
virtual bool contains_bind_marker() const override;
|
||||
virtual void fill_prepare_context(prepare_context& ctx) const override;
|
||||
virtual shared_ptr<terminal> bind(const query_options& options) override;
|
||||
|
||||
// Binds the value, but skips all nulls inside the list
|
||||
virtual shared_ptr<terminal> bind_ignore_null(const query_options& options);
|
||||
const std::vector<shared_ptr<term>>& get_elements() const {
|
||||
return _elements;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user