Add comments and address PR review

This commit is contained in:
PThorpe92
2025-04-09 11:06:26 -04:00
parent 528a9b6c7e
commit e17fd7edc4
4 changed files with 38 additions and 15 deletions

View File

@@ -291,8 +291,7 @@ pub fn open_loop(
});
}
} else if let Some(vtab) = table.virtual_table() {
// Collect usable constraints and track which predicate each came from
// Virtual tables may be used either as VTab or TVF, distinguished by vtab.name.
// Virtual tables may be used either as VTab or TVF
let (start_reg, count, maybe_idx_str, maybe_idx_int) = if vtab
.kind
.eq(&VTabKind::VirtualTable)
@@ -308,13 +307,14 @@ pub fn open_loop(
}
let constraints: Vec<_> =
converted_constraints.iter().map(|(c, _)| *c).collect();
let order_by = vec![OrderByInfo {
let order_by = [OrderByInfo {
column_index: *t_ctx
.result_column_indexes_in_orderby_sorter
.first()
.unwrap_or(&0) as u32,
desc: matches!(iter_dir, IterationDirection::Backwards),
}];
// Call xBestIndex method on the underlying vtable.
let index_info = vtab.best_index(&constraints, &order_by);
// Determine the number of VFilter arguments (constraints with an argv_index).
@@ -330,7 +330,7 @@ pub fn open_loop(
if let Some(argv_index) = usage.argv_index {
if let Some((_, pred)) = converted_constraints.get(i) {
if let ast::Expr::Binary(lhs, _, rhs) = &pred.expr {
let literal_expr = match (&**lhs, &**rhs) {
let expr = match (&**lhs, &**rhs) {
(ast::Expr::Column { .. }, lit) => lit,
(lit, ast::Expr::Column { .. }) => lit,
_ => continue,
@@ -340,7 +340,7 @@ pub fn open_loop(
translate_expr(
program,
Some(tables),
literal_expr,
expr,
target_reg,
&t_ctx.resolver,
)?;
@@ -359,7 +359,6 @@ pub fn open_loop(
} else {
None
};
// Record (in t_ctx) the indices of predicates that best_index tells us to omit.
// Here we insert directly into t_ctx.omit_predicates
for (j, usage) in index_info.constraint_usages.iter().enumerate() {

View File

@@ -79,6 +79,10 @@ impl WhereTerm {
use crate::ast::{Expr, Operator};
// This function takes an operator and returns the operator you would obtain if the operands were swapped.
// e.g. "literal < column"
// which is not the canonical order for constraint pushdown.
// This function will return > so that the expression can be treated as if it were written "column > literal"
fn reverse_operator(op: &Operator) -> Option<Operator> {
match op {
Operator::Equals => Some(Operator::Equals),
@@ -97,7 +101,7 @@ fn reverse_operator(op: &Operator) -> Option<Operator> {
/// It determines whether or not it involves the given table and whether or not it can
/// be converted into a ConstraintInfo which can be passed to the vtab module's xBestIndex
/// method, which will possibly calculate some information to improve the query plan, that we can send
/// back to it as arguments for the VFilter operation. Perhaps we should save the exact Expr for which a relevant column
/// back to it as arguments for the VFilter operation.
/// is going to be filtered against: e.g:
/// 'SELECT key, value FROM vtab WHERE key = 'some_key';
/// we need to send the OwnedValue('some_key') as an argument to VFilter, and possibly omit it from
@@ -126,6 +130,8 @@ pub fn try_convert_to_constraint_info(
if table != &table_index {
return None;
}
// if the column is on the rhs, swap the operands and possibly
// the operator if it's a logical comparison.
(rhs, lhs, &reverse_operator(op).unwrap_or(*op))
}
_ => {

View File

@@ -566,10 +566,11 @@ pub fn columns_from_create_table_body(body: &ast::CreateTableBody) -> crate::Res
.collect::<Vec<_>>())
}
/// This function checks if a given expression is a constant value that can be pushed down to the database engine.
/// It is expected to be called with the other half of a binary expression with an Expr::Column
pub fn can_pushdown_predicate(expr: &Expr) -> bool {
match expr {
Expr::Literal(_) => true,
Expr::Column { .. } => true,
Expr::Binary(lhs, _, rhs) => can_pushdown_predicate(lhs) && can_pushdown_predicate(rhs),
Expr::Parenthesized(exprs) => can_pushdown_predicate(exprs.first().unwrap()),
Expr::Unary(_, expr) => can_pushdown_predicate(expr),
@@ -589,11 +590,6 @@ pub fn can_pushdown_predicate(expr: &Expr) -> bool {
&& can_pushdown_predicate(start)
&& can_pushdown_predicate(end)
}
Expr::Id(_) => true,
Expr::Name(_) => true,
Expr::Qualified(_, _) => true,
Expr::DoublyQualified(_, _, _) => true,
Expr::InTable { lhs, .. } => can_pushdown_predicate(lhs),
_ => false,
}
}

View File

@@ -158,19 +158,30 @@ pub enum ConstraintOp {
#[repr(C)]
#[derive(Copy, Clone)]
/// Describes an ORDER BY clause in a query involving a virtual table.
/// Passed along with the constraints to xBestIndex.
pub struct OrderByInfo {
/// The index of the column referenced in the ORDER BY clause.
pub column_index: u32,
/// Whether or not the clause is in descending order.
pub desc: bool,
}
/// The internal (core) representation of an 'index' on a virtual table.
/// Returned from xBestIndex and then processed and passed to VFilter.
#[derive(Debug, Clone)]
pub struct IndexInfo {
/// The index number, used to identify the index internally by the VTab
pub idx_num: i32,
/// Optional index name. these are passed to vfilter in a tuple (idx_num, idx_str)
pub idx_str: Option<String>,
/// Whether the index is used for order by
pub order_by_consumed: bool,
/// TODO: for eventual cost based query planning
pub estimated_cost: f64,
/// Estimated number of rows that the query will return
pub estimated_rows: u32,
/// List of constraints that can be used to optimize the query.
pub constraint_usages: Vec<ConstraintUsage>,
}
impl Default for IndexInfo {
@@ -245,6 +256,7 @@ impl IndexInfo {
#[repr(C)]
#[derive(Clone, Debug)]
/// FFI representation of IndexInfo.
pub struct ExtIndexInfo {
pub idx_num: i32,
pub idx_str: *const u8,
@@ -256,17 +268,27 @@ pub struct ExtIndexInfo {
pub constraint_usage_len: usize,
}
/// Returned from xBestIndex to describe how the virtual table
/// can use the constraints in the WHERE clause of a query.
#[derive(Debug, Clone, Copy)]
pub struct ConstraintUsage {
pub argv_index: Option<u32>, // 1-based index into VFilter args
pub omit: bool, // if true, core skips checking it again
/// 1 based index of the argument in the WHERE clause.
pub argv_index: Option<u32>,
/// If true, core can omit this constraint in the vdbe layer.
pub omit: bool,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
/// The primary argument to xBestIndex, which describes a constraint
/// in a query involving a virtual table.
pub struct ConstraintInfo {
/// The index of the column referenced in the WHERE clause.
pub column_index: u32,
/// The operator used in the clause.
pub op: ConstraintOp,
/// Whether or not constraint is garaunteed to be enforced.
pub usable: bool,
///
pub pred_idx: usize,
}