mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
Initial virtual table implementation
This commit is contained in:
parent
da4b72eeef
commit
f5f77c0bd1
23 changed files with 1015 additions and 113 deletions
74
core/lib.rs
74
core/lib.rs
|
@ -25,12 +25,13 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|||
use fallible_iterator::FallibleIterator;
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use libloading::{Library, Symbol};
|
||||
use limbo_ext::{ExtensionApi, ExtensionEntryPoint};
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use limbo_ext::{ExtensionApi, ExtensionEntryPoint, ResultCode};
|
||||
use limbo_ext::{VTabModuleImpl, Value as ExtValue};
|
||||
use log::trace;
|
||||
use parking_lot::RwLock;
|
||||
use schema::Schema;
|
||||
use sqlite3_parser::ast;
|
||||
use sqlite3_parser::{ast::Cmd, lexer::sql::Parser};
|
||||
use schema::{Column, Schema};
|
||||
use sqlite3_parser::{ast, ast::Cmd, lexer::sql::Parser};
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZero;
|
||||
|
@ -44,9 +45,11 @@ use storage::pager::allocate_page;
|
|||
use storage::sqlite3_ondisk::{DatabaseHeader, DATABASE_HEADER_SIZE};
|
||||
pub use storage::wal::WalFile;
|
||||
pub use storage::wal::WalFileShared;
|
||||
use types::OwnedValue;
|
||||
pub use types::Value;
|
||||
use util::parse_schema_rows;
|
||||
use vdbe::builder::QueryMode;
|
||||
use vdbe::VTabOpaqueCursor;
|
||||
|
||||
pub use error::LimboError;
|
||||
use translate::select::prepare_select_plan;
|
||||
|
@ -82,6 +85,7 @@ pub struct Database {
|
|||
schema: Rc<RefCell<Schema>>,
|
||||
header: Rc<RefCell<DatabaseHeader>>,
|
||||
syms: Rc<RefCell<SymbolTable>>,
|
||||
vtab_modules: HashMap<String, Rc<VTabModuleImpl>>,
|
||||
// Shared structures of a Database are the parts that are common to multiple threads that might
|
||||
// create DB connections.
|
||||
_shared_page_cache: Arc<RwLock<DumbLruPageCache>>,
|
||||
|
@ -144,6 +148,7 @@ impl Database {
|
|||
_shared_page_cache: _shared_page_cache.clone(),
|
||||
_shared_wal: shared_wal.clone(),
|
||||
syms,
|
||||
vtab_modules: HashMap::new(),
|
||||
};
|
||||
if let Err(e) = db.register_builtins() {
|
||||
return Err(LimboError::ExtensionError(e));
|
||||
|
@ -506,10 +511,70 @@ pub type Row = types::Record;
|
|||
|
||||
pub type StepResult = vdbe::StepResult;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VirtualTable {
|
||||
name: String,
|
||||
pub implementation: Rc<VTabModuleImpl>,
|
||||
columns: Vec<Column>,
|
||||
}
|
||||
|
||||
impl VirtualTable {
|
||||
pub fn open(&self) -> VTabOpaqueCursor {
|
||||
let cursor = unsafe { (self.implementation.open)() };
|
||||
VTabOpaqueCursor::new(cursor)
|
||||
}
|
||||
|
||||
pub fn filter(
|
||||
&self,
|
||||
cursor: &VTabOpaqueCursor,
|
||||
arg_count: usize,
|
||||
args: Vec<OwnedValue>,
|
||||
) -> Result<()> {
|
||||
let mut filter_args = Vec::with_capacity(arg_count);
|
||||
for i in 0..arg_count {
|
||||
let ownedvalue_arg = args.get(i).unwrap();
|
||||
let extvalue_arg: ExtValue = match ownedvalue_arg {
|
||||
OwnedValue::Null => Ok(ExtValue::null()),
|
||||
OwnedValue::Integer(i) => Ok(ExtValue::from_integer(*i)),
|
||||
OwnedValue::Float(f) => Ok(ExtValue::from_float(*f)),
|
||||
OwnedValue::Text(t) => Ok(ExtValue::from_text((*t.value).clone())),
|
||||
OwnedValue::Blob(b) => Ok(ExtValue::from_blob((**b).clone())),
|
||||
other => Err(LimboError::ExtensionError(format!(
|
||||
"Unsupported value type: {:?}",
|
||||
other
|
||||
))),
|
||||
}?;
|
||||
filter_args.push(extvalue_arg);
|
||||
}
|
||||
let rc = unsafe {
|
||||
(self.implementation.filter)(cursor.as_ptr(), arg_count as i32, filter_args.as_ptr())
|
||||
};
|
||||
match rc {
|
||||
ResultCode::OK => Ok(()),
|
||||
_ => Err(LimboError::ExtensionError("Filter failed".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn column(&self, cursor: &VTabOpaqueCursor, column: usize) -> Result<OwnedValue> {
|
||||
let val = unsafe { (self.implementation.column)(cursor.as_ptr(), column as u32) };
|
||||
OwnedValue::from_ffi(&val)
|
||||
}
|
||||
|
||||
pub fn next(&self, cursor: &VTabOpaqueCursor) -> Result<bool> {
|
||||
let rc = unsafe { (self.implementation.next)(cursor.as_ptr()) };
|
||||
match rc {
|
||||
ResultCode::OK => Ok(true),
|
||||
ResultCode::EOF => Ok(false),
|
||||
_ => Err(LimboError::ExtensionError("Next failed".to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct SymbolTable {
|
||||
pub functions: HashMap<String, Rc<function::ExternalFunc>>,
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
extensions: Vec<(Library, *const ExtensionApi)>,
|
||||
pub vtabs: HashMap<String, VirtualTable>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SymbolTable {
|
||||
|
@ -551,6 +616,7 @@ impl SymbolTable {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
functions: HashMap::new(),
|
||||
vtabs: HashMap::new(),
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
extensions: Vec::new(),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue