Skip to content

Commit

Permalink
Make select prepared statement reusable.
Browse files Browse the repository at this point in the history
This also simplify lifetime annotations.
  • Loading branch information
kawasin73 committed Sep 29, 2023
1 parent f241b09 commit 7f147b5
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 58 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ let mut conn = Connection::open(Path::new("path/to/sqlite.db")).unwrap();
let mut stmt = conn.prepare("INSERT INTO example (col) VALUES (1), (2);").unwrap();
assert_eq!(stmt.execute().unwrap(), 2);

let mut stmt = conn.prepare("SELECT * FROM example WHERE col = 1;").unwrap();
let stmt = conn.prepare("SELECT * FROM example WHERE col = 1;").unwrap();
let mut rows = stmt.query().unwrap();

let row = rows.next_row().unwrap().unwrap();
Expand Down
24 changes: 11 additions & 13 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ use crate::utils::i64_to_u64;
use crate::utils::put_varint;
use crate::value::ValueCmp;

pub struct BtreePayload<'a, 'pager> {
pager: &'pager Pager,
pub struct BtreePayload<'a> {
pager: &'a Pager,
local_payload_buffer: PageBuffer<'a>,
payload_info: PayloadInfo,
}

impl<'a, 'pager> BtreePayload<'a, 'pager> {
impl<'a> BtreePayload<'a> {
/// The size of the payload.
pub fn size(&self) -> i32 {
self.payload_info.payload_size
Expand Down Expand Up @@ -139,19 +139,19 @@ impl CursorPage {
/// This does not support creating multiple cursors for the same btree.
/// Otherwise, [BtreeCursor::insert()] fails to get a writable buffer from the
/// pager.
pub struct BtreeCursor<'ctx, 'pager> {
pager: &'pager Pager,
btree_ctx: &'ctx BtreeContext,
pub struct BtreeCursor<'a> {
pager: &'a Pager,
btree_ctx: &'a BtreeContext,
current_page: CursorPage,
parent_pages: Vec<CursorPage>,
initialized: bool,
}

impl<'ctx, 'pager> BtreeCursor<'ctx, 'pager> {
impl<'a> BtreeCursor<'a> {
pub fn new(
root_page_id: PageId,
pager: &'pager Pager,
btree_ctx: &'ctx BtreeContext,
pager: &'a Pager,
btree_ctx: &'a BtreeContext,
) -> anyhow::Result<Self> {
let mem = pager.get_page(root_page_id)?;
let page = CursorPage::new(mem);
Expand Down Expand Up @@ -497,9 +497,7 @@ impl<'ctx, 'pager> BtreeCursor<'ctx, 'pager> {
Ok(Some(key))
}

pub fn get_table_payload<'a>(
&'a self,
) -> anyhow::Result<Option<(i64, BtreePayload<'a, 'pager>)>> {
pub fn get_table_payload(&self) -> anyhow::Result<Option<(i64, BtreePayload)>> {
if !self.initialized {
bail!("cursor is not initialized");
}
Expand Down Expand Up @@ -528,7 +526,7 @@ impl<'ctx, 'pager> BtreeCursor<'ctx, 'pager> {
)))
}

pub fn get_index_payload<'a>(&'a self) -> anyhow::Result<Option<BtreePayload<'a, 'pager>>> {
pub fn get_index_payload(&self) -> anyhow::Result<Option<BtreePayload>> {
if !self.initialized {
bail!("cursor is not initialized");
}
Expand Down
12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ pub enum Statement<'conn> {
}

impl<'conn> Statement<'conn> {
pub fn query(&'conn mut self) -> anyhow::Result<Rows<'conn>> {
pub fn query(&'conn self) -> anyhow::Result<Rows<'conn>> {
match self {
Self::Query(stmt) => stmt.query(),
Self::Execution(_) => bail!("execute statement not support query"),
Expand Down Expand Up @@ -717,7 +717,7 @@ impl<'conn> SelectStatement<'conn> {
}
}

pub fn query(&'conn mut self) -> anyhow::Result<Rows<'conn>> {
pub fn query(&'conn self) -> anyhow::Result<Rows<'conn>> {
// TODO: ReadLock table/schema.
// TODO: check schema version.
let mut cursor =
Expand Down Expand Up @@ -758,8 +758,8 @@ impl<'conn> SelectStatement<'conn> {

pub struct Rows<'conn> {
stmt: &'conn SelectStatement<'conn>,
cursor: BtreeCursor<'conn, 'conn>,
index_cursor: Option<BtreeCursor<'conn, 'conn>>,
cursor: BtreeCursor<'conn>,
index_cursor: Option<BtreeCursor<'conn>>,
is_first_row: bool,
completed: bool,
}
Expand Down Expand Up @@ -899,7 +899,7 @@ const STATIC_NULL_VALUE: Value = Value::Null;

struct RowData<'a> {
rowid: i64,
payload: BtreePayload<'a, 'a>,
payload: BtreePayload<'a>,
headers: Vec<(SerialType, i32)>,
content_offset: i32,
use_local_buffer: bool,
Expand Down Expand Up @@ -975,7 +975,7 @@ pub struct InsertStatement<'conn> {
records: Vec<InsertRecord>,
}

impl InsertStatement<'_> {
impl<'conn> InsertStatement<'conn> {
pub fn execute(&mut self) -> anyhow::Result<usize> {
// TODO: Lock table/schema.
let mut cursor =
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn main() {
}
};
match stmt {
Statement::Query(mut stmt) => {
Statement::Query(stmt) => {
let mut rows = stmt.query().expect("execute statement");
loop {
let row = match rows.next_row() {
Expand Down
1 change: 0 additions & 1 deletion src/pager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ impl Pager {
Ok(PageBufferMut(raw_page))
}

#[allow(dead_code)]
pub fn commit(&self) -> anyhow::Result<()> {
for (page_id, page) in self.cache.map.borrow().iter() {
let raw_page = page.borrow();
Expand Down
8 changes: 4 additions & 4 deletions src/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub trait RecordPayload {
///
/// TODO: This abstraction was introduced for FakePayload in tests. Consider
/// better abstraction.
pub struct BtreeRecordPayload<'a>(&'a BtreePayload<'a, 'a>);
pub struct BtreeRecordPayload<'a>(&'a BtreePayload<'a>);

impl RecordPayload for BtreeRecordPayload<'_> {
#[inline]
Expand All @@ -151,8 +151,8 @@ impl RecordPayload for BtreeRecordPayload<'_> {
}
}

impl<'a> From<&'a BtreePayload<'a, 'a>> for BtreeRecordPayload<'a> {
fn from(payload: &'a BtreePayload<'a, 'a>) -> Self {
impl<'a> From<&'a BtreePayload<'a>> for BtreeRecordPayload<'a> {
fn from(payload: &'a BtreePayload<'a>) -> Self {
Self(payload)
}
}
Expand All @@ -165,7 +165,7 @@ pub struct Record<P: RecordPayload> {

#[inline]
pub fn parse_record<'a>(
payload: &'a BtreePayload<'a, 'a>,
payload: &'a BtreePayload<'a>,
) -> anyhow::Result<Record<BtreeRecordPayload<'a>>> {
Record::parse(payload.into())
}
Expand Down
2 changes: 1 addition & 1 deletion src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Schema {
}

pub fn generate(stmt: SelectStatement, schema_table: Table) -> anyhow::Result<Schema> {
let mut stmt = stmt;
let stmt = stmt;
let mut rows = stmt.query()?;
let mut tables = HashMap::new();
let mut indexes = HashMap::new();
Expand Down
22 changes: 15 additions & 7 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn create_sqlite_database(queries: &[&str]) -> NamedTempFile {

#[allow(dead_code)]
pub fn load_rowids(conn: &mut Connection, query: &str) -> Vec<i64> {
let mut stmt = conn.prepare(query).unwrap();
let stmt = conn.prepare(query).unwrap();
let mut rows = stmt.query().unwrap();
let mut results = Vec::new();
while let Some(row) = rows.next_row().unwrap() {
Expand All @@ -55,6 +55,18 @@ pub fn load_test_rowids(conn: &rusqlite::Connection, query: &str) -> Vec<i64> {
results
}

#[macro_export]
macro_rules! assert_same_result_prsqlite {
($rows:ident, $result:expr, $msg:expr) => {
let row = $rows.next_row().unwrap().unwrap();
let columns = row.parse().unwrap();
for (idx, e) in $result.iter().enumerate() {
assert_eq!(columns.get(idx), e, "idx: {}, {}", idx, $msg);
}
drop(row);
};
}

#[allow(dead_code)]
pub fn assert_same_results(
expected: &[&[Value]],
Expand All @@ -78,13 +90,9 @@ pub fn assert_same_results(
}
}

let mut stmt = conn.prepare(query).unwrap();
let stmt = conn.prepare(query).unwrap();
let mut rows = stmt.query().unwrap();
for (i, e) in expected.iter().enumerate() {
let row = rows.next_row().unwrap().unwrap();
let columns = row.parse().unwrap();
for (j, e) in e.iter().enumerate() {
assert_eq!(columns.get(j), e, "i: {}, j: {}, query: {}", i, j, query);
}
assert_same_result_prsqlite!(rows, e, format!("i: {i}, query: {query}"));
}
}
Loading

0 comments on commit 7f147b5

Please sign in to comment.