Upgrade to csv 1.0

This commit is contained in:
gwenn 2018-05-13 12:21:58 +02:00
parent 6cbeb6ef59
commit 33b1b19d92
2 changed files with 31 additions and 31 deletions

View File

@ -38,7 +38,7 @@ bitflags = "1.0"
lru-cache = "0.1" lru-cache = "0.1"
chrono = { version = "0.4", optional = true } chrono = { version = "0.4", optional = true }
serde_json = { version = "1.0", optional = true } serde_json = { version = "1.0", optional = true }
csv = { version = "0.15", optional = true } csv = { version = "1.0", optional = true }
[dev-dependencies] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"

View File

@ -61,17 +61,16 @@ struct CSVTab {
delimiter: u8, delimiter: u8,
quote: u8, quote: u8,
/// Offset to start of data /// Offset to start of data
offset_first_row: u64, offset_first_row: csv::Position,
} }
impl CSVTab { impl CSVTab {
fn reader(&self) -> result::Result<csv::Reader<File>, csv::Error> { fn reader(&self) -> result::Result<csv::Reader<File>, csv::Error> {
csv::Reader::from_file(&self.filename).map(|reader| { csv::ReaderBuilder::new()
reader .has_headers(self.has_headers)
.has_headers(self.has_headers) .delimiter(self.delimiter)
.delimiter(self.delimiter) .quote(self.quote)
.quote(self.quote) .from_path(&self.filename)
})
} }
fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> { fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> {
@ -111,7 +110,7 @@ impl VTab for CSVTab {
has_headers: false, has_headers: false,
delimiter: b',', delimiter: b',',
quote: b'"', quote: b'"',
offset_first_row: 0, offset_first_row: csv::Position::new(),
}; };
let mut schema = None; let mut schema = None;
let mut n_col = None; let mut n_col = None;
@ -202,21 +201,25 @@ impl VTab for CSVTab {
if vtab.has_headers || (n_col.is_none() && schema.is_none()) { if vtab.has_headers || (n_col.is_none() && schema.is_none()) {
let mut reader = try!(vtab.reader()); let mut reader = try!(vtab.reader());
if vtab.has_headers { if vtab.has_headers {
let headers = try!(reader.headers()); {
vtab.offset_first_row = reader.byte_offset(); let headers = try!(reader.headers());
// headers ignored if cols is not empty // headers ignored if cols is not empty
if n_col.is_none() && schema.is_none() { if n_col.is_none() && schema.is_none() {
cols = headers cols = headers
.into_iter() .into_iter()
.map(|header| escape_double_quote(&header).into_owned()) .map(|header| escape_double_quote(&header).into_owned())
.collect(); .collect();
}
} }
vtab.offset_first_row = reader.position().clone();
} else { } else {
let mut count = 0; let mut record = csv::ByteRecord::new();
while let Some(col) = reader.next_bytes().into_iter_result() { if try!(reader.read_byte_record(&mut record)) {
try!(col); let mut count = 0;
cols.push(format!("c{}", count)); for _ in record.iter() {
count += 1; cols.push(format!("c{}", count));
count += 1;
}
} }
} }
} }
@ -265,7 +268,7 @@ struct CSVTabCursor {
/// Current cursor position used as rowid /// Current cursor position used as rowid
row_number: usize, row_number: usize,
/// Values of the current row /// Values of the current row
cols: Vec<String>, cols: csv::StringRecord,
eof: bool, eof: bool,
} }
@ -275,7 +278,7 @@ impl CSVTabCursor {
base: Default::default(), base: Default::default(),
reader, reader,
row_number: 0, row_number: 0,
cols: Vec::new(), cols: csv::StringRecord::new(),
eof: false, eof: false,
} }
} }
@ -292,7 +295,7 @@ impl VTabCursor for CSVTabCursor {
// the beginning. // the beginning.
fn filter(&mut self, _idx_num: c_int, _idx_str: Option<&str>, _args: &Values) -> Result<()> { fn filter(&mut self, _idx_num: c_int, _idx_str: Option<&str>, _args: &Values) -> Result<()> {
{ {
let offset_first_row = self.vtab().offset_first_row; let offset_first_row = self.vtab().offset_first_row.clone();
try!(self.reader.seek(offset_first_row)); try!(self.reader.seek(offset_first_row));
} }
self.row_number = 0; self.row_number = 0;
@ -300,15 +303,12 @@ impl VTabCursor for CSVTabCursor {
} }
fn next(&mut self) -> Result<()> { fn next(&mut self) -> Result<()> {
{ {
self.eof = self.reader.done(); self.eof = self.reader.is_done();
if self.eof { if self.eof {
return Ok(()); return Ok(());
} }
self.cols.clear(); self.eof = !try!(self.reader.read_record(&mut self.cols));
while let Some(col) = self.reader.next_str().into_iter_result() {
self.cols.push(String::from(try!(col)));
}
} }
self.row_number += 1; self.row_number += 1;
@ -329,7 +329,7 @@ impl VTabCursor for CSVTabCursor {
return Ok(()); return Ok(());
} }
// TODO Affinity // TODO Affinity
ctx.set_result(&self.cols[col as usize]); ctx.set_result(&self.cols[col as usize].to_owned());
Ok(()) Ok(())
} }
fn rowid(&self) -> Result<i64> { fn rowid(&self) -> Result<i64> {