TableMask: comments

This commit is contained in:
Jussi Saurio
2025-05-12 11:15:11 +03:00
parent f12eb25962
commit a90358f669
3 changed files with 37 additions and 3 deletions

View File

@@ -319,7 +319,7 @@ pub fn usable_constraints_for_join_order<'a>(
if other_side_refers_to_self {
break;
}
let lhs_mask = TableMask::from_iter(
let lhs_mask = TableMask::from_table_number_iter(
join_order
.iter()
.take(join_order.len() - 1)

View File

@@ -66,7 +66,7 @@ pub fn join_lhs_and_rhs<'a>(
best_access_methods.push(access_methods_arena.borrow().len() - 1);
let lhs_mask = lhs.map_or(TableMask::new(), |l| {
TableMask::from_iter(l.table_numbers.iter().cloned())
TableMask::from_table_number_iter(l.table_numbers.iter().cloned())
});
// Output cardinality is reduced by the product of the selectivities of the constraints that can be used with this join order.
let output_cardinality_multiplier = rhs_constraints

View File

@@ -588,6 +588,24 @@ pub fn determine_where_to_eval_term(
return determine_where_to_eval_expr(&term.expr, join_order);
}
/// A bitmask representing a set of tables in a query plan.
/// Tables are numbered by their index in [SelectPlan::table_references].
/// In the bitmask, the first bit is unused so that a mask with all zeros
/// can represent "no tables".
///
/// E.g. table 0 is represented by bit index 1, table 1 by bit index 2, etc.
///
/// Usage in Join Optimization
///
/// In join optimization, [TableMask] is used to:
/// - Generate subsets of tables for dynamic programming in join optimization
/// - Ensure tables are joined in valid orders (e.g., respecting LEFT JOIN order)
///
/// Usage with constraints (WHERE clause)
///
/// [TableMask] helps determine:
/// - Which tables are referenced in a constraint
/// - When a constraint can be applied as a join condition (all referenced tables must be on the left side of the table being joined)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TableMask(pub u128);
@@ -598,24 +616,33 @@ impl std::ops::BitOrAssign for TableMask {
}
impl TableMask {
/// Creates a new empty table mask.
///
/// The initial mask represents an empty set of tables.
pub fn new() -> Self {
Self(0)
}
/// Returns true if the mask represents an empty set of tables.
pub fn is_empty(&self) -> bool {
self.0 == 0
}
/// Creates a new mask that is the same as this one but without the specified table.
pub fn without_table(&self, table_no: usize) -> Self {
assert!(table_no < 127, "table_no must be less than 127");
Self(self.0 ^ (1 << (table_no + 1)))
}
/// Creates a table mask from raw bits.
///
/// The bits are shifted left by 1 to maintain the convention that table 0 is at bit 1.
pub fn from_bits(bits: u128) -> Self {
Self(bits << 1)
}
pub fn from_iter(iter: impl Iterator<Item = usize>) -> Self {
/// Creates a table mask from an iterator of table numbers.
pub fn from_table_number_iter(iter: impl Iterator<Item = usize>) -> Self {
iter.fold(Self::new(), |mut mask, table_no| {
assert!(table_no < 127, "table_no must be less than 127");
mask.add_table(table_no);
@@ -623,29 +650,36 @@ impl TableMask {
})
}
/// Adds a table to the mask.
pub fn add_table(&mut self, table_no: usize) {
assert!(table_no < 127, "table_no must be less than 127");
self.0 |= 1 << (table_no + 1);
}
/// Returns true if the mask contains the specified table.
pub fn contains_table(&self, table_no: usize) -> bool {
assert!(table_no < 127, "table_no must be less than 127");
self.0 & (1 << (table_no + 1)) != 0
}
/// Returns true if this mask contains all tables in the other mask.
pub fn contains_all(&self, other: &TableMask) -> bool {
self.0 & other.0 == other.0
}
/// Returns the number of tables in the mask.
pub fn table_count(&self) -> usize {
self.0.count_ones() as usize
}
/// Returns true if this mask shares any tables with the other mask.
pub fn intersects(&self, other: &TableMask) -> bool {
self.0 & other.0 != 0
}
}
/// Returns a [TableMask] representing the tables referenced in the given expression.
/// Used in the optimizer for constraint analysis.
pub fn table_mask_from_expr(expr: &Expr) -> Result<TableMask> {
let mut mask = TableMask::new();
match expr {