cartel-sqlite 0.30.0

SQLite driver for the dope runtime
use crate::common::plan;
use cartel_sqlite::{
    Budget, Busy, Cache, Connection, Limits, Lookaside, Memory, OpenOptions, Parameters, Program,
    Progress, Results, Scan, Table, Work, dsl::query, runtime::Runtime,
};
use dope_runtime::{executor, executor::session};
use dope_test::fibers;
use std::{num::NonZero, time::Duration};

cartel_sqlite::catalog! {
pub CapacityDatabase;

#[derive(Table)]
#[table_name("entries")]
pub struct Entry<T = String> {
    pub(crate) id: i64,
    pub(crate) name: T,
}

#[query]
pub fn all_entries() -> Vec<Entry> {
    Entry::filter(|_entry| true).rows()
        .order_by(|entry| entry.id)
        .all()
}

#[query]
pub fn scan_entries() -> query::Stream<Entry> {
    Entry::filter(|_entry| true).rows()
        .order_by(|entry| entry.id)
        .stream()
}

#[query]
pub fn entries_named(name: String) -> Vec<Entry> {
    Entry::filter(|entry| entry.name == name).rows().all()
}

pub const COMMANDS: &[&str] = &["CREATE TABLE entries (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"];

statements! {
    INSERT_ENTRY(2, 0) = "INSERT INTO entries (id, name) VALUES (?1, ?2)",
    RECURSIVE_SUM(0, 1) = "WITH RECURSIVE count(x) AS (\
        VALUES(0) UNION ALL SELECT x + 1 FROM count WHERE x < 1000000\
        ) SELECT sum(x) FROM count",
    EXACT_ROW(0, 2) = "SELECT 7, 'abc'",
    WIDE_INTEGER(0, 1) = "SELECT 2147483648",
    ALL_COLUMNS(0, 2) = "SELECT * FROM entries",
    ADD_COLUMN(0, 0) = "ALTER TABLE entries ADD COLUMN extra INTEGER",
}

pub fn try_settings(
    params: usize,
    scan: usize,
    row_size: usize,
    rows: usize,
    bytes: usize,
    quanta: u64,
) -> Result<(Limits, Memory), plan::Error> {
    let mut work = Work::uniform(Budget {
        progress: Progress::new(NonZero::new(quanta).ok_or(plan::Error::Progress)?),
        busy: Busy {
            window: Duration::from_millis(1),
            interval: Duration::from_millis(1),
            retries: NonZero::<u32>::MIN,
        },
    });
    // The varying quota targets calls and cleanup, after this fixed catalog opens.
    work.open.progress = Progress::new(NonZero::new(100).ok_or(plan::Error::Progress)?);
    Ok((
        Limits {
            parameters: Parameters {
                items: 8,
                bytes: params,
            },
            scan: Scan {
                rows: scan,
                row_bytes: row_size,
            },
            savepoints: 16,
            program: Program::new(NonZero::new(1_000_000).ok_or(plan::Error::Program)?),
            work,
        },
        Memory {
            sqlite_bytes: 4 << 20,
            results: Results {
                rows,
                bytes,
            },
            statement_bytes: 128 << 10,
            cache: Cache {
                main_bytes: 1 << 20,
                temporary_bytes: 1 << 20,
            },
            lookaside: Lookaside::try_new(128, 64).ok_or(plan::Error::Lookaside)?,
        },
    ))
}

pub fn open<'sql>(runtime: Runtime) -> Result<cartel_sqlite::database::Target<'sql>, plan::Error> {
    OpenOptions::new()
        .open_memory(runtime)
        .map_err(plan::Error::Client)?
        .commands(COMMANDS)
        .map_err(plan::Error::Client)
}

}

pub struct NativeParams;

impl cartel_sqlite::TypedQuery for NativeParams {
    const SQL: &str = "SELECT ?1";
    const PARAMETERS: usize = usize::MAX;
    const COLUMNS: usize = 1;
}

impl cartel_sqlite::Catalog for NativeParams {
    const STATEMENTS: &[cartel_sqlite::Entry<'_>] = &[cartel_sqlite::Entry::of::<Self>()];
}

impl cartel_sqlite::HasQuery<NativeParams> for NativeParams {
    const SLOT: usize = 0;
}

pub fn try_seed<'app, 'local: 'app, 'd: 'local, D>(
    database: &mut Connection<'app, 'local, 'd, CapacityDatabase>,
    names: &[String],
    driver: &mut session::App<'app, '_, 'd, D>,
) -> Result<(), plan::Error>
where
    D: executor::raw::App<'d>,
{
    for (index, name) in names.iter().enumerate() {
        fibers::TEST
            .try_run(
                driver,
                database
                    .query()
                    .run_no_rows(CapacityDatabase::INSERT_ENTRY, (index as i64, (name, ()))),
            )
            .map_err(plan::Error::Run)?
            .map_err(plan::Error::Call)?;
    }
    Ok(())
}