mirror of
https://github.com/isar/rusqlite.git
synced 2025-01-19 22:20:51 +08:00
Fix CSVTab::create method.
This commit is contained in:
parent
1e6e8115bb
commit
ed5637f513
@ -1,7 +1,9 @@
|
||||
//! CSV Virtual Table
|
||||
extern crate csv;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::mem;
|
||||
use std::str;
|
||||
use libc;
|
||||
|
||||
use {Connection, Error, Result};
|
||||
@ -9,8 +11,6 @@ use ffi;
|
||||
use types::Null;
|
||||
use vtab::{declare_vtab, VTab, VTabCursor};
|
||||
|
||||
use self::csv::Reader;
|
||||
|
||||
pub fn load_module(conn: &Connection) -> Result<()> {
|
||||
let aux: Option<()> = None;
|
||||
conn.create_module("csv", &CSV_MODULE, aux)
|
||||
@ -33,23 +33,77 @@ struct CSVTab {
|
||||
|
||||
impl VTab<CSVTabCursor> for CSVTab {
|
||||
fn create(db: *mut ffi::sqlite3,
|
||||
aux: *mut libc::c_void,
|
||||
argc: libc::c_int,
|
||||
_argv: *const *const libc::c_char)
|
||||
_aux: *mut libc::c_void,
|
||||
args: &[*const libc::c_char])
|
||||
-> Result<CSVTab> {
|
||||
if argc < 4 {
|
||||
if args.len() < 4 {
|
||||
return Err(Error::ModuleError(format!("no CSV file specified")));
|
||||
}
|
||||
//let filename = ;
|
||||
let reader = try!(csv::Reader::from_file("FIXME"));
|
||||
// pull out name of csv file (remove quotes)
|
||||
let mut c_filename = unsafe { CStr::from_ptr(args[3]).to_bytes() };
|
||||
if c_filename[0] == b'\'' {
|
||||
c_filename = &c_filename[1..c_filename.len() - 1];
|
||||
}
|
||||
let filename = try!(str::from_utf8(c_filename));
|
||||
let mut reader = try!(csv::Reader::from_file(filename)).has_headers(false); // TODO flexible ?
|
||||
let mut cols = Vec::new();
|
||||
|
||||
let args = &args[4..];
|
||||
for c_arg in args {
|
||||
let c_slice = unsafe { CStr::from_ptr(*c_arg).to_bytes() };
|
||||
if c_slice.len() == 1 {
|
||||
reader = reader.delimiter(c_slice[0]);
|
||||
} else if c_slice.len() == 3 && c_slice[0] == b'\'' {
|
||||
reader = reader.delimiter(c_slice[1]);
|
||||
} else {
|
||||
let arg = try!(str::from_utf8(c_slice));
|
||||
let uc = arg.to_uppercase();
|
||||
if uc.contains("HEADER") {
|
||||
reader = reader.has_headers(true);
|
||||
} else if uc.contains("NO_QUOTE") {
|
||||
reader = reader.quote(0);
|
||||
} else {
|
||||
cols.push(String::from(arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut offset_first_row = 0;
|
||||
if reader.has_headers {
|
||||
let headers = try!(reader.headers());
|
||||
offset_first_row = reader.byte_offset();
|
||||
// headers ignored if cols is not empty
|
||||
if cols.is_empty() {
|
||||
cols = headers;
|
||||
}
|
||||
}
|
||||
|
||||
if cols.is_empty() {
|
||||
return Err(Error::ModuleError(format!("no column name specified")));
|
||||
}
|
||||
|
||||
let mut sql = String::from("CREATE TABLE x(");
|
||||
for (i, col) in cols.iter().enumerate() {
|
||||
if col.is_empty() {
|
||||
return Err(Error::ModuleError(format!("no column name found")));
|
||||
}
|
||||
sql.push('"');
|
||||
sql.push_str(col);
|
||||
sql.push('"');
|
||||
if i == cols.len() - 1 {
|
||||
sql.push_str(");");
|
||||
} else {
|
||||
sql.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
let vtab = CSVTab {
|
||||
base: Default::default(),
|
||||
reader: reader,
|
||||
offset_first_row: 0,
|
||||
cols: vec![], // FIXME
|
||||
offset_first_row: offset_first_row,
|
||||
cols: cols,
|
||||
};
|
||||
unimplemented!();
|
||||
try!(declare_vtab(db, "CREATE TABLE x FIXME"));
|
||||
try!(declare_vtab(db, &sql));
|
||||
Ok(vtab)
|
||||
}
|
||||
|
||||
@ -102,7 +156,7 @@ impl VTabCursor<CSVTab> for CSVTabCursor {
|
||||
}
|
||||
fn eof(&self) -> bool {
|
||||
let vtab = self.vtab();
|
||||
unsafe { (*vtab).reader.done() }
|
||||
vtab.reader.done()
|
||||
}
|
||||
fn column(&self, ctx: *mut ffi::sqlite3_context, col: libc::c_int) -> Result<()> {
|
||||
use functions::ToResult;
|
||||
|
@ -46,8 +46,7 @@ struct IntArrayVTab {
|
||||
impl VTab<IntArrayVTabCursor> for IntArrayVTab {
|
||||
fn create(db: *mut ffi::sqlite3,
|
||||
aux: *mut libc::c_void,
|
||||
_argc: libc::c_int,
|
||||
_argv: *const *const libc::c_char)
|
||||
_args: &[*const libc::c_char])
|
||||
-> Result<IntArrayVTab> {
|
||||
let array = unsafe { mem::transmute(aux) };
|
||||
let vtab = IntArrayVTab {
|
||||
|
@ -40,10 +40,9 @@ use ffi;
|
||||
pub trait VTab<C: VTabCursor<Self>>: Sized {
|
||||
fn create(db: *mut ffi::sqlite3,
|
||||
aux: *mut libc::c_void,
|
||||
_argc: libc::c_int,
|
||||
_argv: *const *const libc::c_char)
|
||||
args: &[*const libc::c_char])
|
||||
-> Result<Self>;
|
||||
fn best_index(&self, _info: *mut ffi::sqlite3_index_info);
|
||||
fn best_index(&self, info: *mut ffi::sqlite3_index_info);
|
||||
fn open(&self) -> Result<C>;
|
||||
}
|
||||
|
||||
@ -52,7 +51,7 @@ pub trait VTabCursor<V: VTab<Self>>: Sized {
|
||||
fn filter(&mut self) -> Result<()>;
|
||||
fn next(&mut self) -> Result<()>;
|
||||
fn eof(&self) -> bool;
|
||||
fn column(&self, ctx: *mut ffi::sqlite3_context, _i: libc::c_int) -> Result<()>;
|
||||
fn column(&self, ctx: *mut ffi::sqlite3_context, i: libc::c_int) -> Result<()>;
|
||||
fn rowid(&self) -> Result<i64>;
|
||||
}
|
||||
|
||||
@ -156,8 +155,10 @@ 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::slice;
|
||||
use vtab::mprintf;
|
||||
match $vtab::create(db, aux, argc, argv) {
|
||||
let args = slice::from_raw_parts(argv, argc as usize);
|
||||
match $vtab::create(db, aux, args) {
|
||||
Ok(vtab) => {
|
||||
let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab));
|
||||
*pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab;
|
||||
|
Loading…
x
Reference in New Issue
Block a user