mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 00:39:20 +08:00
Introduce Module trait to make create_module type safe
This commit is contained in:
parent
2a684384fd
commit
afeb5d4d47
@ -6,7 +6,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use types::{ToSql, ToSqlOutput, Value};
|
use types::{ToSql, ToSqlOutput, Value};
|
||||||
use vtab::{self, declare_vtab, Context, IndexInfo, VTab, VTabCursor, Values};
|
use vtab::{self, declare_vtab, Context, IndexInfo, Module, VTab, VTabCursor, Values};
|
||||||
use {Connection, Error, Result};
|
use {Connection, Error, Result};
|
||||||
|
|
||||||
// http://sqlite.org/bindptr.html
|
// http://sqlite.org/bindptr.html
|
||||||
@ -28,11 +28,12 @@ impl ToSql for Array {
|
|||||||
/// Register the "rarray" module.
|
/// Register the "rarray" module.
|
||||||
pub fn load_module(conn: &Connection) -> Result<()> {
|
pub fn load_module(conn: &Connection) -> Result<()> {
|
||||||
let aux: Option<()> = None;
|
let aux: Option<()> = None;
|
||||||
conn.create_module("rarray", &ARRAY_MODULE, aux)
|
conn.create_module("rarray", ArrayModule(&ARRAY_MODULE), aux)
|
||||||
}
|
}
|
||||||
|
|
||||||
eponymous_module!(
|
eponymous_module!(
|
||||||
ARRAY_MODULE,
|
ARRAY_MODULE,
|
||||||
|
ArrayModule,
|
||||||
ArrayTab,
|
ArrayTab,
|
||||||
(),
|
(),
|
||||||
ArrayTabCursor,
|
ArrayTabCursor,
|
||||||
@ -50,6 +51,30 @@ eponymous_module!(
|
|||||||
array_rowid
|
array_rowid
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct ArrayModule(&'static ffi::sqlite3_module);
|
||||||
|
|
||||||
|
impl Module for ArrayModule {
|
||||||
|
type Aux = ();
|
||||||
|
type Table = ArrayTab;
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *const ffi::sqlite3_module {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn connect(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
_aux: Option<&()>,
|
||||||
|
_args: &[&[u8]],
|
||||||
|
) -> Result<ArrayTab> {
|
||||||
|
let vtab = ArrayTab {
|
||||||
|
base: Default::default(),
|
||||||
|
};
|
||||||
|
try!(declare_vtab(db, "CREATE TABLE x(value,pointer hidden)"));
|
||||||
|
Ok(vtab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Column numbers
|
// Column numbers
|
||||||
// const CARRAY_COLUMN_VALUE : c_int = 0;
|
// const CARRAY_COLUMN_VALUE : c_int = 0;
|
||||||
const CARRAY_COLUMN_POINTER: c_int = 1;
|
const CARRAY_COLUMN_POINTER: c_int = 1;
|
||||||
@ -62,17 +87,8 @@ struct ArrayTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VTab for ArrayTab {
|
impl VTab for ArrayTab {
|
||||||
type Aux = ();
|
|
||||||
type Cursor = ArrayTabCursor;
|
type Cursor = ArrayTabCursor;
|
||||||
|
|
||||||
unsafe fn connect(db: *mut ffi::sqlite3, _aux: *mut (), _args: &[&[u8]]) -> Result<ArrayTab> {
|
|
||||||
let vtab = ArrayTab {
|
|
||||||
base: Default::default(),
|
|
||||||
};
|
|
||||||
try!(declare_vtab(db, "CREATE TABLE x(value,pointer hidden)"));
|
|
||||||
Ok(vtab)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
||||||
// Index of the pointer= constraint
|
// Index of the pointer= constraint
|
||||||
let mut ptr_idx = None;
|
let mut ptr_idx = None;
|
||||||
|
@ -10,7 +10,7 @@ use std::str;
|
|||||||
use ffi;
|
use ffi;
|
||||||
use types::Null;
|
use types::Null;
|
||||||
use vtab::{
|
use vtab::{
|
||||||
declare_vtab, dequote, escape_double_quote, parse_boolean, Context, IndexInfo, VTab,
|
declare_vtab, dequote, escape_double_quote, parse_boolean, Context, IndexInfo, Module, VTab,
|
||||||
VTabCursor, Values,
|
VTabCursor, Values,
|
||||||
};
|
};
|
||||||
use {Connection, Error, Result};
|
use {Connection, Error, Result};
|
||||||
@ -28,11 +28,12 @@ use {Connection, Error, Result};
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn load_module(conn: &Connection) -> Result<()> {
|
pub fn load_module(conn: &Connection) -> Result<()> {
|
||||||
let aux: Option<()> = None;
|
let aux: Option<()> = None;
|
||||||
conn.create_module("csv", &CSV_MODULE, aux)
|
conn.create_module("csv", CSVModule(&CSV_MODULE), aux)
|
||||||
}
|
}
|
||||||
|
|
||||||
init_module!(
|
init_module!(
|
||||||
CSV_MODULE,
|
CSV_MODULE,
|
||||||
|
CSVModule,
|
||||||
CSVTab,
|
CSVTab,
|
||||||
(),
|
(),
|
||||||
CSVTabCursor,
|
CSVTabCursor,
|
||||||
@ -50,29 +51,9 @@ init_module!(
|
|||||||
csv_rowid
|
csv_rowid
|
||||||
);
|
);
|
||||||
|
|
||||||
/// An instance of the CSV virtual table
|
struct CSVModule(&'static ffi::sqlite3_module);
|
||||||
#[repr(C)]
|
|
||||||
struct CSVTab {
|
|
||||||
/// Base class. Must be first
|
|
||||||
base: ffi::sqlite3_vtab,
|
|
||||||
/// Name of the CSV file
|
|
||||||
filename: String,
|
|
||||||
has_headers: bool,
|
|
||||||
delimiter: u8,
|
|
||||||
quote: u8,
|
|
||||||
/// Offset to start of data
|
|
||||||
offset_first_row: csv::Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CSVTab {
|
|
||||||
fn reader(&self) -> result::Result<csv::Reader<File>, csv::Error> {
|
|
||||||
csv::ReaderBuilder::new()
|
|
||||||
.has_headers(self.has_headers)
|
|
||||||
.delimiter(self.delimiter)
|
|
||||||
.quote(self.quote)
|
|
||||||
.from_path(&self.filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl CSVModule {
|
||||||
fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> {
|
fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> {
|
||||||
let arg = try!(str::from_utf8(c_slice)).trim();
|
let arg = try!(str::from_utf8(c_slice)).trim();
|
||||||
let mut split = arg.split('=');
|
let mut split = arg.split('=');
|
||||||
@ -95,11 +76,15 @@ impl CSVTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VTab for CSVTab {
|
impl Module for CSVModule {
|
||||||
type Aux = ();
|
type Aux = ();
|
||||||
type Cursor = CSVTabCursor;
|
type Table = CSVTab;
|
||||||
|
|
||||||
unsafe fn connect(db: *mut ffi::sqlite3, _aux: *mut (), args: &[&[u8]]) -> Result<CSVTab> {
|
fn as_ptr(&self) -> *const ffi::sqlite3_module {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn connect(db: *mut ffi::sqlite3, _aux: Option<&()>, args: &[&[u8]]) -> Result<CSVTab> {
|
||||||
if args.len() < 4 {
|
if args.len() < 4 {
|
||||||
return Err(Error::ModuleError("no CSV file specified".to_owned()));
|
return Err(Error::ModuleError("no CSV file specified".to_owned()));
|
||||||
}
|
}
|
||||||
@ -117,7 +102,7 @@ impl VTab for CSVTab {
|
|||||||
|
|
||||||
let args = &args[3..];
|
let args = &args[3..];
|
||||||
for c_slice in args {
|
for c_slice in args {
|
||||||
let (param, value) = try!(CSVTab::parameter(c_slice));
|
let (param, value) = try!(CSVModule::parameter(c_slice));
|
||||||
match param {
|
match param {
|
||||||
"filename" => {
|
"filename" => {
|
||||||
if !Path::new(value).exists() {
|
if !Path::new(value).exists() {
|
||||||
@ -161,7 +146,7 @@ impl VTab for CSVTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"delimiter" => {
|
"delimiter" => {
|
||||||
if let Some(b) = CSVTab::parse_byte(value) {
|
if let Some(b) = CSVModule::parse_byte(value) {
|
||||||
vtab.delimiter = b;
|
vtab.delimiter = b;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
@ -171,7 +156,7 @@ impl VTab for CSVTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"quote" => {
|
"quote" => {
|
||||||
if let Some(b) = CSVTab::parse_byte(value) {
|
if let Some(b) = CSVModule::parse_byte(value) {
|
||||||
if b == b'0' {
|
if b == b'0' {
|
||||||
vtab.quote = 0;
|
vtab.quote = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -248,6 +233,34 @@ impl VTab for CSVTab {
|
|||||||
try!(declare_vtab(db, &schema.unwrap()));
|
try!(declare_vtab(db, &schema.unwrap()));
|
||||||
Ok(vtab)
|
Ok(vtab)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An instance of the CSV virtual table
|
||||||
|
#[repr(C)]
|
||||||
|
struct CSVTab {
|
||||||
|
/// Base class. Must be first
|
||||||
|
base: ffi::sqlite3_vtab,
|
||||||
|
/// Name of the CSV file
|
||||||
|
filename: String,
|
||||||
|
has_headers: bool,
|
||||||
|
delimiter: u8,
|
||||||
|
quote: u8,
|
||||||
|
/// Offset to start of data
|
||||||
|
offset_first_row: csv::Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CSVTab {
|
||||||
|
fn reader(&self) -> result::Result<csv::Reader<File>, csv::Error> {
|
||||||
|
csv::ReaderBuilder::new()
|
||||||
|
.has_headers(self.has_headers)
|
||||||
|
.delimiter(self.delimiter)
|
||||||
|
.quote(self.quote)
|
||||||
|
.from_path(&self.filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VTab for CSVTab {
|
||||||
|
type Cursor = CSVTabCursor;
|
||||||
|
|
||||||
// Only a forward full table scan is supported.
|
// Only a forward full table scan is supported.
|
||||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
||||||
|
@ -40,20 +40,36 @@ use {str_to_cstring, Connection, Error, InnerConnection, Result};
|
|||||||
// \-> if not eof { cursor.column or xrowid } else { cursor.xclose }
|
// \-> if not eof { cursor.column or xrowid } else { cursor.xclose }
|
||||||
//
|
//
|
||||||
|
|
||||||
/// Virtual table instance trait.
|
/// Module instance trait
|
||||||
pub trait VTab: Sized {
|
pub trait Module {
|
||||||
type Aux;
|
type Aux;
|
||||||
type Cursor: VTabCursor;
|
type Table: VTab;
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *const ffi::sqlite3_module;
|
||||||
|
|
||||||
/// Create a new instance of a virtual table in response to a CREATE VIRTUAL TABLE statement.
|
/// Create a new instance of a virtual table in response to a CREATE VIRTUAL TABLE statement.
|
||||||
/// The `db` parameter is a pointer to the SQLite database connection that is executing
|
/// The `db` parameter is a pointer to the SQLite database connection that is executing
|
||||||
/// the CREATE VIRTUAL TABLE statement.
|
/// the CREATE VIRTUAL TABLE statement.
|
||||||
unsafe fn create(db: *mut ffi::sqlite3, aux: *mut Self::Aux, args: &[&[u8]]) -> Result<Self> {
|
unsafe fn create(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
aux: Option<&Self::Aux>,
|
||||||
|
args: &[&[u8]],
|
||||||
|
) -> Result<Self::Table> {
|
||||||
Self::connect(db, aux, args)
|
Self::connect(db, aux, args)
|
||||||
}
|
}
|
||||||
/// Similar to `create`. The difference is that `connect` is called to establish a new connection
|
/// Similar to `create`. The difference is that `connect` is called to establish a new connection
|
||||||
/// to an _existing_ virtual table whereas `create` is called to create a new virtual table from scratch.
|
/// to an _existing_ virtual table whereas `create` is called to create a new virtual table from scratch.
|
||||||
unsafe fn connect(db: *mut ffi::sqlite3, aux: *mut Self::Aux, args: &[&[u8]]) -> Result<Self>;
|
unsafe fn connect(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
aux: Option<&Self::Aux>,
|
||||||
|
args: &[&[u8]],
|
||||||
|
) -> Result<Self::Table>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Virtual table instance trait.
|
||||||
|
pub trait VTab: Sized {
|
||||||
|
type Cursor: VTabCursor;
|
||||||
|
|
||||||
/// Determine the best way to access the virtual table.
|
/// Determine the best way to access the virtual table.
|
||||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()>;
|
fn best_index(&self, info: &mut IndexInfo) -> Result<()>;
|
||||||
/// Create a new cursor used for accessing a virtual table.
|
/// Create a new cursor used for accessing a virtual table.
|
||||||
@ -291,34 +307,34 @@ impl<'a> Iterator for ValueIter<'a> {
|
|||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
/// Register a virtual table implementation.
|
/// Register a virtual table implementation.
|
||||||
pub fn create_module<A>(
|
pub fn create_module<M: Module>(
|
||||||
&self,
|
&self,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
module: *const ffi::sqlite3_module,
|
module: M,
|
||||||
aux: Option<A>,
|
aux: Option<M::Aux>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.db.borrow_mut().create_module(module_name, module, aux)
|
self.db.borrow_mut().create_module(module_name, module, aux)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerConnection {
|
impl InnerConnection {
|
||||||
fn create_module<A>(
|
fn create_module<M: Module>(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
module: *const ffi::sqlite3_module,
|
module: M,
|
||||||
aux: Option<A>,
|
aux: Option<M::Aux>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let c_name = try!(str_to_cstring(module_name));
|
let c_name = try!(str_to_cstring(module_name));
|
||||||
let r = match aux {
|
let r = match aux {
|
||||||
Some(aux) => {
|
Some(aux) => {
|
||||||
let boxed_aux: *mut A = Box::into_raw(Box::new(aux));
|
let boxed_aux: *mut M::Aux = Box::into_raw(Box::new(aux));
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::sqlite3_create_module_v2(
|
ffi::sqlite3_create_module_v2(
|
||||||
self.db(),
|
self.db(),
|
||||||
c_name.as_ptr(),
|
c_name.as_ptr(),
|
||||||
module,
|
module.as_ptr(),
|
||||||
boxed_aux as *mut c_void,
|
boxed_aux as *mut c_void,
|
||||||
Some(free_boxed_value::<A>),
|
Some(free_boxed_value::<M::Aux>),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +342,7 @@ impl InnerConnection {
|
|||||||
ffi::sqlite3_create_module_v2(
|
ffi::sqlite3_create_module_v2(
|
||||||
self.db(),
|
self.db(),
|
||||||
c_name.as_ptr(),
|
c_name.as_ptr(),
|
||||||
module,
|
module.as_ptr(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@ -401,6 +417,7 @@ unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
|
|||||||
macro_rules! init_module {
|
macro_rules! init_module {
|
||||||
(
|
(
|
||||||
$module_name:ident,
|
$module_name:ident,
|
||||||
|
$module:ident,
|
||||||
$vtab:ident,
|
$vtab:ident,
|
||||||
$aux:ty,
|
$aux:ty,
|
||||||
$cursor:ty,
|
$cursor:ty,
|
||||||
@ -445,8 +462,9 @@ macro_rules! init_module {
|
|||||||
|
|
||||||
// The xConnect and xCreate methods do the same thing, but they must be
|
// The xConnect and xCreate methods do the same thing, but they must be
|
||||||
// different so that the virtual table is not an eponymous virtual table.
|
// different so that the virtual table is not an eponymous virtual table.
|
||||||
create_or_connect!($vtab, $aux, $create, create);
|
create_or_connect!($module, $vtab, $aux, $create, create);
|
||||||
common_decl!(
|
common_decl!(
|
||||||
|
$module,
|
||||||
$vtab,
|
$vtab,
|
||||||
$aux,
|
$aux,
|
||||||
$cursor,
|
$cursor,
|
||||||
@ -469,6 +487,7 @@ macro_rules! init_module {
|
|||||||
macro_rules! eponymous_module {
|
macro_rules! eponymous_module {
|
||||||
(
|
(
|
||||||
$module_name:ident,
|
$module_name:ident,
|
||||||
|
$module:ident,
|
||||||
$vtab:ident,
|
$vtab:ident,
|
||||||
$aux:ty,
|
$aux:ty,
|
||||||
$cursor:ty,
|
$cursor:ty,
|
||||||
@ -513,6 +532,7 @@ macro_rules! eponymous_module {
|
|||||||
};
|
};
|
||||||
|
|
||||||
common_decl!(
|
common_decl!(
|
||||||
|
$module,
|
||||||
$vtab,
|
$vtab,
|
||||||
$aux,
|
$aux,
|
||||||
$cursor,
|
$cursor,
|
||||||
@ -532,7 +552,7 @@ macro_rules! eponymous_module {
|
|||||||
} // eponymous_module macro end
|
} // eponymous_module macro end
|
||||||
|
|
||||||
macro_rules! create_or_connect {
|
macro_rules! create_or_connect {
|
||||||
($vtab:ident, $aux:ty, $create_or_connect:ident, $vtab_func:ident) => {
|
($module:ident, $vtab:ident, $aux:ty, $create_or_connect:ident, $module_func:ident) => {
|
||||||
unsafe extern "C" fn $create_or_connect(
|
unsafe extern "C" fn $create_or_connect(
|
||||||
db: *mut ffi::sqlite3,
|
db: *mut ffi::sqlite3,
|
||||||
aux: *mut c_void,
|
aux: *mut c_void,
|
||||||
@ -550,9 +570,9 @@ macro_rules! create_or_connect {
|
|||||||
let args = slice::from_raw_parts(argv, argc as usize);
|
let args = slice::from_raw_parts(argv, argc as usize);
|
||||||
let vec = args
|
let vec = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&cs| CStr::from_ptr(cs).to_bytes())
|
.map(|&cs| CStr::from_ptr(cs).to_bytes()) // FIXME .to_str() -> Result<&str, Utf8Error>
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
match $vtab::$vtab_func(db, aux, &vec[..]) {
|
match $module::$module_func(db, aux.as_ref(), &vec[..]) {
|
||||||
Ok(vtab) => {
|
Ok(vtab) => {
|
||||||
let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab));
|
let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab));
|
||||||
*pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab;
|
*pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab;
|
||||||
@ -575,6 +595,7 @@ macro_rules! create_or_connect {
|
|||||||
|
|
||||||
macro_rules! common_decl {
|
macro_rules! common_decl {
|
||||||
(
|
(
|
||||||
|
$module:ident,
|
||||||
$vtab:ident,
|
$vtab:ident,
|
||||||
$aux:ty,
|
$aux:ty,
|
||||||
$cursor:ty,
|
$cursor:ty,
|
||||||
@ -590,7 +611,7 @@ macro_rules! common_decl {
|
|||||||
$column:ident,
|
$column:ident,
|
||||||
$rowid:ident
|
$rowid:ident
|
||||||
) => {
|
) => {
|
||||||
create_or_connect!($vtab, $aux, $connect, connect);
|
create_or_connect!($module, $vtab, $aux, $connect, connect);
|
||||||
unsafe extern "C" fn $best_index(
|
unsafe extern "C" fn $best_index(
|
||||||
vtab: *mut ffi::sqlite3_vtab,
|
vtab: *mut ffi::sqlite3_vtab,
|
||||||
info: *mut ffi::sqlite3_index_info,
|
info: *mut ffi::sqlite3_index_info,
|
||||||
|
@ -5,17 +5,18 @@ use std::os::raw::{c_char, c_int, c_void};
|
|||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use types::Type;
|
use types::Type;
|
||||||
use vtab::{self, declare_vtab, Context, IndexInfo, VTab, VTabCursor, Values};
|
use vtab::{self, declare_vtab, Context, IndexInfo, Module, VTab, VTabCursor, Values};
|
||||||
use {Connection, Error, Result};
|
use {Connection, Error, Result};
|
||||||
|
|
||||||
/// Register the "generate_series" module.
|
/// Register the "generate_series" module.
|
||||||
pub fn load_module(conn: &Connection) -> Result<()> {
|
pub fn load_module(conn: &Connection) -> Result<()> {
|
||||||
let aux: Option<()> = None;
|
let aux: Option<()> = None;
|
||||||
conn.create_module("generate_series", &SERIES_MODULE, aux)
|
conn.create_module("generate_series", Series(&SERIES_MODULE), aux)
|
||||||
}
|
}
|
||||||
|
|
||||||
eponymous_module!(
|
eponymous_module!(
|
||||||
SERIES_MODULE,
|
SERIES_MODULE,
|
||||||
|
Series,
|
||||||
SeriesTab,
|
SeriesTab,
|
||||||
(),
|
(),
|
||||||
SeriesTabCursor,
|
SeriesTabCursor,
|
||||||
@ -33,6 +34,33 @@ eponymous_module!(
|
|||||||
series_rowid
|
series_rowid
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct Series(&'static ffi::sqlite3_module);
|
||||||
|
|
||||||
|
impl Module for Series {
|
||||||
|
type Aux = ();
|
||||||
|
type Table = SeriesTab;
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *const ffi::sqlite3_module {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn connect(
|
||||||
|
db: *mut ffi::sqlite3,
|
||||||
|
_aux: Option<&()>,
|
||||||
|
_args: &[&[u8]],
|
||||||
|
) -> Result<SeriesTab> {
|
||||||
|
let vtab = SeriesTab {
|
||||||
|
base: Default::default(),
|
||||||
|
};
|
||||||
|
try!(declare_vtab(
|
||||||
|
db,
|
||||||
|
"CREATE TABLE x(value,start hidden,stop hidden,step hidden)"
|
||||||
|
));
|
||||||
|
Ok(vtab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Column numbers
|
// Column numbers
|
||||||
// const SERIES_COLUMN_VALUE : c_int = 0;
|
// const SERIES_COLUMN_VALUE : c_int = 0;
|
||||||
const SERIES_COLUMN_START: c_int = 1;
|
const SERIES_COLUMN_START: c_int = 1;
|
||||||
@ -63,20 +91,8 @@ struct SeriesTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VTab for SeriesTab {
|
impl VTab for SeriesTab {
|
||||||
type Aux = ();
|
|
||||||
type Cursor = SeriesTabCursor;
|
type Cursor = SeriesTabCursor;
|
||||||
|
|
||||||
unsafe fn connect(db: *mut ffi::sqlite3, _aux: *mut (), _args: &[&[u8]]) -> Result<SeriesTab> {
|
|
||||||
let vtab = SeriesTab {
|
|
||||||
base: Default::default(),
|
|
||||||
};
|
|
||||||
try!(declare_vtab(
|
|
||||||
db,
|
|
||||||
"CREATE TABLE x(value,start hidden,stop hidden,step hidden)"
|
|
||||||
));
|
|
||||||
Ok(vtab)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
||||||
// The query plan bitmask
|
// The query plan bitmask
|
||||||
let mut idx_num: QueryPlanFlags = QueryPlanFlags::empty();
|
let mut idx_num: QueryPlanFlags = QueryPlanFlags::empty();
|
||||||
|
Loading…
Reference in New Issue
Block a user