#[derive(VTabModuleDerive)]Expand description
Macro to derive a VTabModule for your extension. This macro will generate the necessary functions to register your module with core. You must implement the VTabModule, VTable, and VTabCursor traits.
ⓘ
#[derive(Debug, VTabModuleDerive)]
struct CsvVTabModule;
impl VTabModule for CsvVTabModule {
type Table = CsvTable;
const NAME: &'static str = "csv_data";
const VTAB_KIND: VTabKind = VTabKind::VirtualTable;
/// Declare your virtual table and its schema
fn create(args: &[Value]) -> Result<(String, Self::Table), ResultCode> {
let schema = "CREATE TABLE csv_data(
name TEXT,
age TEXT,
city TEXT
)".into();
Ok((schema, CsvTable {}))
}
}
struct CsvTable {}
// Implement the VTable trait for your virtual table
impl VTable for CsvTable {
type Cursor = CsvCursor;
type Error = &'static str;
/// Open the virtual table and return a cursor
fn open(&self) -> Result<Self::Cursor, Self::Error> {
let csv_content = fs::read_to_string("data.csv").unwrap_or_default();
let rows: Vec<Vec<String>> = csv_content
.lines()
.skip(1)
.map(|line| {
line.split(',')
.map(|s| s.trim().to_string())
.collect()
})
.collect();
Ok(CsvCursor { rows, index: 0 })
}
/// **Optional** methods for non-readonly tables:
/// Update the row with the provided values, return the new rowid
fn update(&mut self, rowid: i64, args: &[Value]) -> Result<Option<i64>, Self::Error> {
Ok(None)// return Ok(None) for read-only
}
/// Insert a new row with the provided values, return the new rowid
fn insert(&mut self, args: &[Value]) -> Result<(), Self::Error> {
Ok(()) //
}
/// Delete the row with the provided rowid
fn delete(&mut self, rowid: i64) -> Result<(), Self::Error> {
Ok(())
}
/// Destroy the virtual table. Any cleanup logic for when the table is deleted comes heres
fn destroy(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
#[derive(Debug)]
struct CsvCursor {
rows: Vec<Vec<String>>,
index: usize,
}
impl CsvCursor {
/// Returns the value for a given column index.
fn column(&self, idx: u32) -> Result<Value, Self::Error> {
let row = &self.rows[self.index];
if (idx as usize) < row.len() {
Value::from_text(&row[idx as usize])
} else {
Value::null()
}
}
}
// Implement the VTabCursor trait for your virtual cursor
impl VTabCursor for CsvCursor {
type Error = &'static str;
/// Filter the virtual table based on arguments (omitted here for simplicity)
fn filter(&mut self, _args: &[Value], _idx_info: Option<(&str, i32)>) -> ResultCode {
ResultCode::OK
}
/// Move the cursor to the next row
fn next(&mut self) -> ResultCode {
if self.index < self.rows.len() - 1 {
self.index += 1;
ResultCode::OK
} else {
ResultCode::EOF
}
}
fn eof(&self) -> bool {
self.index >= self.rows.len()
}
/// Return the value for a given column index
fn column(&self, idx: u32) -> Result<Value, Self::Error> {
self.column(idx)
}
fn rowid(&self) -> i64 {
self.index as i64
}
}