mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-09 02:04:22 +01:00
Merge 'Simplify PseudoCursor implementation' from Levy A.
Removes unnecessary allocations and unreachable code paths. Reviewed-by: Pere Diaz Bou <pere-altea@homail.com> Closes #1903
This commit is contained in:
@@ -136,7 +136,6 @@ impl Schema {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Table {
|
||||
BTree(Rc<BTreeTable>),
|
||||
Pseudo(Rc<PseudoTable>),
|
||||
Virtual(Rc<VirtualTable>),
|
||||
FromClauseSubquery(FromClauseSubquery),
|
||||
}
|
||||
@@ -145,7 +144,6 @@ impl Table {
|
||||
pub fn get_root_page(&self) -> usize {
|
||||
match self {
|
||||
Table::BTree(table) => table.root_page,
|
||||
Table::Pseudo(_) => unimplemented!(),
|
||||
Table::Virtual(_) => unimplemented!(),
|
||||
Table::FromClauseSubquery(_) => unimplemented!(),
|
||||
}
|
||||
@@ -154,7 +152,6 @@ impl Table {
|
||||
pub fn get_name(&self) -> &str {
|
||||
match self {
|
||||
Self::BTree(table) => &table.name,
|
||||
Self::Pseudo(_) => "",
|
||||
Self::Virtual(table) => &table.name,
|
||||
Self::FromClauseSubquery(from_clause_subquery) => &from_clause_subquery.name,
|
||||
}
|
||||
@@ -163,7 +160,6 @@ impl Table {
|
||||
pub fn get_column_at(&self, index: usize) -> Option<&Column> {
|
||||
match self {
|
||||
Self::BTree(table) => table.columns.get(index),
|
||||
Self::Pseudo(table) => table.columns.get(index),
|
||||
Self::Virtual(table) => table.columns.get(index),
|
||||
Self::FromClauseSubquery(from_clause_subquery) => {
|
||||
from_clause_subquery.columns.get(index)
|
||||
@@ -174,7 +170,6 @@ impl Table {
|
||||
pub fn columns(&self) -> &Vec<Column> {
|
||||
match self {
|
||||
Self::BTree(table) => &table.columns,
|
||||
Self::Pseudo(table) => &table.columns,
|
||||
Self::Virtual(table) => &table.columns,
|
||||
Self::FromClauseSubquery(from_clause_subquery) => &from_clause_subquery.columns,
|
||||
}
|
||||
@@ -183,7 +178,6 @@ impl Table {
|
||||
pub fn btree(&self) -> Option<Rc<BTreeTable>> {
|
||||
match self {
|
||||
Self::BTree(table) => Some(table.clone()),
|
||||
Self::Pseudo(_) => None,
|
||||
Self::Virtual(_) => None,
|
||||
Self::FromClauseSubquery(_) => None,
|
||||
}
|
||||
@@ -201,7 +195,6 @@ impl PartialEq for Table {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::BTree(a), Self::BTree(b)) => Rc::ptr_eq(a, b),
|
||||
(Self::Pseudo(a), Self::Pseudo(b)) => Rc::ptr_eq(a, b),
|
||||
(Self::Virtual(a), Self::Virtual(b)) => Rc::ptr_eq(a, b),
|
||||
_ => false,
|
||||
}
|
||||
@@ -291,41 +284,20 @@ impl BTreeTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PseudoTable {
|
||||
pub columns: Vec<Column>,
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct PseudoCursorType {
|
||||
pub column_count: usize,
|
||||
}
|
||||
|
||||
impl PseudoTable {
|
||||
impl PseudoCursorType {
|
||||
pub fn new() -> Self {
|
||||
Self { columns: vec![] }
|
||||
Self { column_count: 0 }
|
||||
}
|
||||
|
||||
pub fn new_with_columns(columns: Vec<Column>) -> Self {
|
||||
Self { columns }
|
||||
}
|
||||
|
||||
pub fn add_column(&mut self, name: &str, ty: Type, primary_key: bool) {
|
||||
self.columns.push(Column {
|
||||
name: Some(normalize_ident(name)),
|
||||
ty,
|
||||
ty_str: ty.to_string().to_uppercase(),
|
||||
primary_key,
|
||||
is_rowid_alias: false,
|
||||
notnull: false,
|
||||
default: None,
|
||||
unique: false,
|
||||
collation: None,
|
||||
});
|
||||
}
|
||||
pub fn get_column(&self, name: &str) -> Option<(usize, &Column)> {
|
||||
let name = normalize_ident(name);
|
||||
for (i, column) in self.columns.iter().enumerate() {
|
||||
if column.name.as_ref().map_or(false, |n| *n == name) {
|
||||
return Some((i, column));
|
||||
}
|
||||
pub fn new_with_columns(columns: impl AsRef<[Column]>) -> Self {
|
||||
Self {
|
||||
column_count: columns.as_ref().len(),
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,8 +552,8 @@ fn create_table(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn _build_pseudo_table(columns: &[ResultColumn]) -> PseudoTable {
|
||||
let table = PseudoTable::new();
|
||||
pub fn _build_pseudo_table(columns: &[ResultColumn]) -> PseudoCursorType {
|
||||
let table = PseudoCursorType::new();
|
||||
for column in columns {
|
||||
match column {
|
||||
ResultColumn::Expr(expr, _as_name) => {
|
||||
|
||||
@@ -321,9 +321,7 @@ impl ToSqlString for JoinedTable {
|
||||
) -> String {
|
||||
let table_or_subquery =
|
||||
match &self.table {
|
||||
Table::BTree(..) | Table::Pseudo(..) | Table::Virtual(..) => {
|
||||
self.table.get_name().to_string()
|
||||
}
|
||||
Table::BTree(..) | Table::Virtual(..) => self.table.get_name().to_string(),
|
||||
Table::FromClauseSubquery(from_clause_subquery) => {
|
||||
// Could possibly merge the contexts together here
|
||||
format!(
|
||||
|
||||
@@ -1930,7 +1930,6 @@ pub fn translate_expr(
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
Table::Pseudo(_) => panic!("Column access on pseudo table"),
|
||||
}
|
||||
}
|
||||
ast::Expr::RowId {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use turso_sqlite3_parser::ast;
|
||||
|
||||
use crate::translate::expr::{walk_expr, WalkControl};
|
||||
use crate::translate::plan::ResultSetColumn;
|
||||
use crate::{
|
||||
function::AggFunc,
|
||||
schema::{Column, PseudoTable},
|
||||
schema::PseudoCursorType,
|
||||
translate::collate::CollationSeq,
|
||||
util::exprs_are_equivalent,
|
||||
vdbe::{
|
||||
@@ -304,30 +302,11 @@ pub fn group_by_create_pseudo_table(
|
||||
program: &mut ProgramBuilder,
|
||||
sorter_column_count: usize,
|
||||
) -> usize {
|
||||
// Create pseudo-columns for the pseudo-table
|
||||
// (these are placeholders as we only care about structure, not semantics)
|
||||
let ty = crate::schema::Type::Null;
|
||||
let pseudo_columns = (0..sorter_column_count)
|
||||
.map(|_| Column {
|
||||
name: None,
|
||||
primary_key: false,
|
||||
ty,
|
||||
ty_str: ty.to_string().to_uppercase(),
|
||||
is_rowid_alias: false,
|
||||
notnull: false,
|
||||
default: None,
|
||||
unique: false,
|
||||
collation: None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Create a pseudo-table to read one row at a time from the sorter
|
||||
// This allows us to use standard table access operations on the sorted data
|
||||
let pseudo_table = Rc::new(PseudoTable {
|
||||
columns: pseudo_columns,
|
||||
});
|
||||
|
||||
program.alloc_cursor_id(CursorType::Pseudo(pseudo_table.clone()))
|
||||
program.alloc_cursor_id(CursorType::Pseudo(PseudoCursorType {
|
||||
column_count: sorter_column_count,
|
||||
}))
|
||||
}
|
||||
|
||||
/// In case sorting is needed for GROUP BY, sorts the rows in the GROUP BY sorter
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::vdbe::insn::CmpInsFlags;
|
||||
use crate::{
|
||||
schema::{BTreeTable, Column, Index, IndexColumn, PseudoTable, Schema},
|
||||
schema::{BTreeTable, Column, Index, IndexColumn, PseudoCursorType, Schema},
|
||||
storage::pager::CreateBTreeFlags,
|
||||
util::normalize_ident,
|
||||
vdbe::{
|
||||
@@ -83,8 +83,9 @@ pub fn translate_create_index(
|
||||
let btree_cursor_id = program.alloc_cursor_id(CursorType::BTreeIndex(idx.clone()));
|
||||
let table_cursor_id = program.alloc_cursor_id(CursorType::BTreeTable(tbl.clone()));
|
||||
let sorter_cursor_id = program.alloc_cursor_id(CursorType::Sorter);
|
||||
let pseudo_table = PseudoTable::new_with_columns(tbl.columns.clone());
|
||||
let pseudo_cursor_id = program.alloc_cursor_id(CursorType::Pseudo(pseudo_table.into()));
|
||||
let pseudo_cursor_id = program.alloc_cursor_id(CursorType::Pseudo(PseudoCursorType {
|
||||
column_count: tbl.columns.len(),
|
||||
}));
|
||||
|
||||
// Create a new B-Tree and store the root page index in a register
|
||||
let root_page_reg = program.alloc_register();
|
||||
|
||||
@@ -563,7 +563,6 @@ pub fn open_loop(
|
||||
end_offset: loop_end,
|
||||
});
|
||||
}
|
||||
Table::Pseudo(_) => panic!("Pseudo tables should not loop"),
|
||||
}
|
||||
|
||||
if let Some(table_cursor_id) = table_cursor_id {
|
||||
@@ -1042,7 +1041,6 @@ pub fn close_loop(
|
||||
target_pc: loop_labels.loop_start,
|
||||
});
|
||||
}
|
||||
other => unreachable!("Unsupported table reference type: {:?}", other),
|
||||
}
|
||||
program.preassign_label_to_next_insn(loop_labels.loop_end);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder};
|
||||
|
||||
use crate::{
|
||||
schema::{Column, PseudoTable},
|
||||
schema::PseudoCursorType,
|
||||
translate::collate::CollationSeq,
|
||||
util::exprs_are_equivalent,
|
||||
vdbe::{
|
||||
@@ -87,54 +85,17 @@ pub fn emit_order_by(
|
||||
let sort_loop_start_label = program.allocate_label();
|
||||
let sort_loop_next_label = program.allocate_label();
|
||||
let sort_loop_end_label = program.allocate_label();
|
||||
let mut pseudo_columns = vec![];
|
||||
for _ in 0..order_by.len() {
|
||||
let ty = crate::schema::Type::Null;
|
||||
pseudo_columns.push(Column {
|
||||
// Names don't matter. We are tracking which result column is in which position in the ORDER BY clause in m.result_column_indexes_in_orderby_sorter.
|
||||
name: None,
|
||||
primary_key: false,
|
||||
ty,
|
||||
ty_str: ty.to_string().to_uppercase(),
|
||||
is_rowid_alias: false,
|
||||
notnull: false,
|
||||
default: None,
|
||||
unique: false,
|
||||
collation: None,
|
||||
});
|
||||
}
|
||||
for i in 0..result_columns.len() {
|
||||
// If any result columns are not in the ORDER BY sorter, it's because they are equal to a sort key and were already added to the pseudo columns above.
|
||||
if let Some(ref v) = t_ctx.result_columns_to_skip_in_orderby_sorter {
|
||||
if v.contains(&i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let ty = crate::schema::Type::Null;
|
||||
pseudo_columns.push(Column {
|
||||
name: None,
|
||||
primary_key: false,
|
||||
ty,
|
||||
ty_str: ty.to_string().to_uppercase(),
|
||||
is_rowid_alias: false,
|
||||
notnull: false,
|
||||
default: None,
|
||||
unique: false,
|
||||
collation: None,
|
||||
});
|
||||
}
|
||||
|
||||
let num_columns_in_sorter = order_by.len() + result_columns.len()
|
||||
let sorter_column_count = order_by.len() + result_columns.len()
|
||||
- t_ctx
|
||||
.result_columns_to_skip_in_orderby_sorter
|
||||
.as_ref()
|
||||
.map(|v| v.len())
|
||||
.unwrap_or(0);
|
||||
|
||||
let pseudo_table = Rc::new(PseudoTable {
|
||||
columns: pseudo_columns,
|
||||
});
|
||||
let pseudo_cursor = program.alloc_cursor_id(CursorType::Pseudo(pseudo_table.clone()));
|
||||
let pseudo_cursor = program.alloc_cursor_id(CursorType::Pseudo(PseudoCursorType {
|
||||
column_count: sorter_column_count,
|
||||
}));
|
||||
let SortMetadata {
|
||||
sort_cursor,
|
||||
reg_sorter_data,
|
||||
@@ -143,7 +104,7 @@ pub fn emit_order_by(
|
||||
program.emit_insn(Insn::OpenPseudo {
|
||||
cursor_id: pseudo_cursor,
|
||||
content_reg: reg_sorter_data,
|
||||
num_fields: num_columns_in_sorter,
|
||||
num_fields: sorter_column_count,
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::SorterSort {
|
||||
|
||||
@@ -989,7 +989,6 @@ impl JoinedTable {
|
||||
let index_cursor_id = None;
|
||||
Ok((table_cursor_id, index_cursor_id))
|
||||
}
|
||||
Table::Pseudo(_) => Ok((None, None)),
|
||||
Table::FromClauseSubquery(..) => Ok((None, None)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +749,6 @@ pub fn translate_drop_table(
|
||||
db: 0, // TODO change this for multiple databases
|
||||
});
|
||||
}
|
||||
Table::Pseudo(..) => unimplemented!(),
|
||||
Table::FromClauseSubquery(..) => panic!("FromClauseSubquery can't be dropped"),
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use turso_sqlite3_parser::ast::{self, TableInternalId};
|
||||
use crate::{
|
||||
numeric::Numeric,
|
||||
parameters::Parameters,
|
||||
schema::{BTreeTable, Index, PseudoTable, Table},
|
||||
schema::{BTreeTable, Index, PseudoCursorType, Table},
|
||||
translate::{
|
||||
collate::CollationSeq,
|
||||
emitter::TransactionMode,
|
||||
@@ -116,7 +116,7 @@ pub struct ProgramBuilder {
|
||||
pub enum CursorType {
|
||||
BTreeTable(Rc<BTreeTable>),
|
||||
BTreeIndex(Arc<Index>),
|
||||
Pseudo(Rc<PseudoTable>),
|
||||
Pseudo(PseudoCursorType),
|
||||
Sorter,
|
||||
VirtualTable(Rc<VirtualTable>),
|
||||
}
|
||||
|
||||
@@ -539,10 +539,7 @@ pub fn insn_to_str(
|
||||
let name = &index.columns.get(*column).unwrap().name;
|
||||
Some(name)
|
||||
}
|
||||
CursorType::Pseudo(pseudo_table) => {
|
||||
let name = pseudo_table.columns.get(*column).unwrap().name.as_ref();
|
||||
name
|
||||
}
|
||||
CursorType::Pseudo(_) => None,
|
||||
CursorType::Sorter => None,
|
||||
CursorType::VirtualTable(v) => v.columns.get(*column).unwrap().name.as_ref(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user