mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-02 14:54:23 +01:00
Add comments and address PR review
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user