cql3: Replace runtime check with a prepared flag
Checking that every PK restriction is an EQ was happening at runtime. This is wasteful, as the result is always the same. Replace that check with a flag computed once at preparation time. Separate the simple-case processing into its own function rather than pass the flag as an extra parameter. Signed-off-by: Dejan Mircevski <dejan@scylladb.com>
This commit is contained in:
@@ -636,19 +636,6 @@ void error_if_exceeds(size_t size, size_t limit) {
|
||||
/// Computes partition-key ranges from expressions, which contains EQ/IN for every partition column.
|
||||
dht::partition_range_vector partition_ranges_from_singles(
|
||||
const std::vector<expr::expression>& expressions, const query_options& options, const schema& schema) {
|
||||
if (std::ranges::all_of(expressions, [] (const expression& e) { return find(e, oper_t::EQ); })) {
|
||||
// Special case to avoid a vector of vectors, which makes for a couple of extra allocations per request.
|
||||
std::vector<managed_bytes> pk_value(schema.partition_key_size());
|
||||
for (const auto& e : expressions) {
|
||||
const auto col = std::get<column_value>(find(e, oper_t::EQ)->lhs).col;
|
||||
const auto vals = std::get<value_list>(possible_lhs_values(col, e, options));
|
||||
if (vals.empty()) { // Case of C=1 AND C=2.
|
||||
return {};
|
||||
}
|
||||
pk_value[schema.position(*col)] = std::move(vals[0]);
|
||||
}
|
||||
return {range_from_bytes(schema, pk_value)};
|
||||
}
|
||||
const size_t size_limit =
|
||||
options.get_cql_config().restrictions.partition_key_restrictions_max_cartesian_product_size;
|
||||
// Each element is a vector of that column's possible values:
|
||||
@@ -679,6 +666,22 @@ dht::partition_range_vector partition_ranges_from_singles(
|
||||
return ranges;
|
||||
}
|
||||
|
||||
/// Computes partition-key ranges from EQ restrictions on each partition column. Returns a single singleton range if
|
||||
/// the EQ restrictions are not mutually conflicting. Otherwise, returns an empty vector.
|
||||
dht::partition_range_vector partition_ranges_from_EQs(
|
||||
const std::vector<expr::expression>& eq_expressions, const query_options& options, const schema& schema) {
|
||||
std::vector<managed_bytes> pk_value(schema.partition_key_size());
|
||||
for (const auto& e : eq_expressions) {
|
||||
const auto col = std::get<column_value>(find(e, oper_t::EQ)->lhs).col;
|
||||
const auto vals = std::get<value_list>(possible_lhs_values(col, e, options));
|
||||
if (vals.empty()) { // Case of C=1 AND C=2.
|
||||
return {};
|
||||
}
|
||||
pk_value[schema.position(*col)] = std::move(vals[0]);
|
||||
}
|
||||
return {range_from_bytes(schema, pk_value)};
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
dht::partition_range_vector statement_restrictions::get_partition_key_ranges(const query_options& options) const {
|
||||
@@ -692,6 +695,9 @@ dht::partition_range_vector statement_restrictions::get_partition_key_ranges(con
|
||||
format("Unexpected size of token restrictions: {}", _partition_range_restrictions.size()));
|
||||
}
|
||||
return partition_ranges_from_token(_partition_range_restrictions[0], options);
|
||||
} else if (_partition_range_is_simple) {
|
||||
// Special case to avoid extra allocations required for a Cartesian product.
|
||||
return partition_ranges_from_EQs(_partition_range_restrictions, options, *_schema);
|
||||
}
|
||||
return partition_ranges_from_singles(_partition_range_restrictions, options, *_schema);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user