diff --git a/src/vtab/csvtab.rs b/src/vtab/csvtab.rs index ee87e19..a49800f 100644 --- a/src/vtab/csvtab.rs +++ b/src/vtab/csvtab.rs @@ -1,6 +1,5 @@ //! CSV Virtual Table extern crate csv; -use std::ffi::CStr; use std::fs::File; use std::path::Path; use std::result; @@ -32,14 +31,17 @@ init_module!(CSV_MODULE, csv_column, csv_rowid); +/// An instance of the CSV virtual table #[repr(C)] struct CSVTab { - /// Base class + /// 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: u64, } @@ -56,13 +58,13 @@ impl CSVTab { impl VTab for CSVTab { fn create(db: *mut ffi::sqlite3, _aux: *mut libc::c_void, - args: &[*const libc::c_char]) + args: &[&[u8]]) -> Result { if args.len() < 4 { return Err(Error::ModuleError("no CSV file specified".to_owned())); } // pull out name of csv file (remove quotes) - let mut c_filename = unsafe { CStr::from_ptr(args[3]).to_bytes() }; + let mut c_filename = args[3]; if c_filename[0] == b'\'' { c_filename = &c_filename[1..c_filename.len() - 1]; } @@ -81,8 +83,7 @@ impl VTab for CSVTab { let mut cols: Vec = Vec::new(); let args = &args[4..]; - for c_arg in args { - let c_slice = unsafe { CStr::from_ptr(*c_arg).to_bytes() }; + for c_slice in args { if c_slice.len() == 1 { vtab.delimiter = c_slice[0]; } else if c_slice.len() == 3 && c_slice[0] == b'\'' { @@ -121,7 +122,7 @@ impl VTab for CSVTab { } sql.push('"'); sql.push_str(col); - sql.push('"'); + sql.push_str("\" TEXT"); if i == cols.len() - 1 { sql.push_str(");"); } else { @@ -140,11 +141,12 @@ impl VTab for CSVTab { } } - +/// A cursor for the CSV virtual table #[repr(C)] struct CSVTabCursor { - /// Base class + /// Base class. Must be first base: ffi::sqlite3_vtab_cursor, + /// The CSV reader object reader: csv::Reader, /// Current cursor position row_number: usize, diff --git a/src/vtab/int_array.rs b/src/vtab/int_array.rs index ea5a224..b8730a5 100644 --- a/src/vtab/int_array.rs +++ b/src/vtab/int_array.rs @@ -60,7 +60,7 @@ struct IntArrayVTab { impl VTab for IntArrayVTab { fn create(db: *mut ffi::sqlite3, aux: *mut libc::c_void, - _args: &[*const libc::c_char]) + _args: &[&[u8]]) -> Result { let array = unsafe { mem::transmute(aux) }; let vtab = IntArrayVTab { diff --git a/src/vtab/mod.rs b/src/vtab/mod.rs index 9388aa1..8acc367 100644 --- a/src/vtab/mod.rs +++ b/src/vtab/mod.rs @@ -1,7 +1,6 @@ //! Create virtual tables. //! (See http://sqlite.org/vtab.html) -use std::borrow::Cow; -use std::borrow::Cow::{Borrowed, Owned}; +use std::borrow::Cow::{self, Borrowed, Owned}; use std::ffi::CString; use std::mem; use std::ptr; @@ -45,7 +44,7 @@ pub trait VTab>: Sized { /// The `db` parameter is a pointer to the SQLite database connection that is executing the CREATE VIRTUAL TABLE statement. fn create(db: *mut ffi::sqlite3, aux: *mut libc::c_void, - args: &[*const libc::c_char]) + args: &[&[u8]]) -> Result; /// Determine the best way to access the virtual table. fn best_index(&self, info: *mut ffi::sqlite3_index_info); @@ -186,10 +185,14 @@ unsafe extern "C" fn $create(db: *mut ffi::sqlite3, err_msg: *mut *mut libc::c_char) -> libc::c_int { use std::error::Error as StdError; + use std::ffi::CStr; use std::slice; use vtab::mprintf; let args = slice::from_raw_parts(argv, argc as usize); - match $vtab::create(db, aux, args) { + let vec = args.iter().map(|cs| { + CStr::from_ptr(*cs).to_bytes() + }).collect::>(); + match $vtab::create(db, aux, &vec[..]) { Ok(vtab) => { let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab)); *pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab;