-
Notifications
You must be signed in to change notification settings - Fork 557
/
engine.rs
104 lines (92 loc) · 3.93 KB
/
engine.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#![allow(clippy::module_inception)]
use super::Session;
use crate::errinput;
use crate::error::Result;
use crate::sql::types::schema::Table;
use crate::sql::types::{Expression, Row, Rows, Value};
use crate::storage::mvcc;
use std::collections::{HashMap, HashSet};
/// The SQL engine interface.
pub trait Engine<'a>: Sized {
/// The transaction type.
type Transaction: Transaction + Catalog + 'a;
/// Begins a read-write transaction.
fn begin(&self) -> Result<Self::Transaction>;
/// Begins a read-only transaction.
fn begin_read_only(&self) -> Result<Self::Transaction>;
/// Begins a read-only transaction as of a historical version.
fn begin_as_of(&self, version: mvcc::Version) -> Result<Self::Transaction>;
/// Creates a client session for executing SQL statements.
fn session(&'a self) -> Session<'a, Self> {
Session::new(self)
}
}
/// A SQL transaction.
///
/// All methods operate on row batches rather than single rows to amortize the
/// cost. We have to do a Raft roundtrip for every call, and we'd rather not
/// have to do a Raft roundtrip for every row.
pub trait Transaction {
/// The transaction's MVCC version.
fn version(&self) -> mvcc::Version;
/// Whether the transaction is read-only.
fn read_only(&self) -> bool;
/// Commits the transaction.
fn commit(self) -> Result<()>;
/// Rolls back the transaction.
fn rollback(self) -> Result<()>;
/// Deletes table rows by primary key.
fn delete(&self, table: &str, ids: &[Value]) -> Result<()>;
/// Fetches table rows by primary key.
fn get(&self, table: &str, ids: &[Value]) -> Result<Vec<Row>>;
/// Inserts new table rows.
fn insert(&self, table: &str, rows: Vec<Row>) -> Result<()>;
/// Looks up a set of table primary keys by an index value.
/// TODO: should this just return a Vec instead?
fn lookup_index(&self, table: &str, column: &str, values: &[Value]) -> Result<HashSet<Value>>;
/// Scans a table's rows, optionally applying the given filter.
fn scan(&self, table: &str, filter: Option<Expression>) -> Result<Rows>;
/// Scans a column's index entries.
/// TODO: this is only used for tests. Remove it?
fn scan_index(&self, table: &str, column: &str) -> Result<IndexScan>;
/// Updates table rows by primary key.
fn update(&self, table: &str, rows: HashMap<Value, Row>) -> Result<()>;
}
/// An index scan iterator.
pub type IndexScan = Box<dyn Iterator<Item = Result<(Value, HashSet<Value>)>>>;
/// The catalog stores schema information.
pub trait Catalog {
/// Creates a new table.
fn create_table(&self, table: Table) -> Result<()>;
/// Drops a table. Errors if it does not exist, unless if_exists is true.
/// Returns true if the table existed and was deleted.
fn drop_table(&self, table: &str, if_exists: bool) -> Result<bool>;
/// Fetches a table schema.
fn get_table(&self, table: &str) -> Result<Option<Table>>;
/// Lists tables.
fn list_tables(&self) -> Result<Vec<Table>>;
/// Reads a table, errors if it does not exist.
fn must_get_table(&self, table: &str) -> Result<Table> {
self.get_table(table)?.ok_or(errinput!("table {table} does not exist"))
}
/// Returns all references to a table, as table,column pairs.
/// TODO: make this actually be table,column, instead of a column vec.
fn references(&self, table: &str, with_self: bool) -> Result<Vec<(String, Vec<String>)>> {
Ok(self
.list_tables()?
.into_iter()
.filter(|t| with_self || t.name != table)
.map(|t| {
(
t.name,
t.columns
.iter()
.filter(|c| c.references.as_deref() == Some(table))
.map(|c| c.name.clone())
.collect::<Vec<_>>(),
)
})
.filter(|(_, cs)| !cs.is_empty())
.collect())
}
}