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:
Dejan Mircevski
2021-04-28 16:44:48 -04:00
parent 4661aa0269
commit 57fa66a0a7

View File

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