Skip to content

Commit e98bba5

Browse files
Enable returning errors after creating row writer (jonhoo#20)
Authored-by: Simon Dickson <[email protected]>
1 parent 6acd9b3 commit e98bba5

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

src/resultset.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -347,27 +347,31 @@ where
347347
}
348348

349349
impl<'a, W: Write + 'a> RowWriter<'a, W> {
350-
fn finish_inner(&mut self) -> io::Result<()> {
350+
fn finish_inner(&mut self, complete: bool) -> io::Result<()> {
351351
if self.finished {
352352
return Ok(());
353353
}
354+
354355
self.finished = true;
355356

356357
if !self.columns.is_empty() && self.col != 0 {
357358
self.end_row()?;
358359
}
359360

360-
if self.columns.is_empty() {
361-
// response to no column query is always an OK packet
362-
// we've kept track of the number of rows in col (hacky, I know)
363-
self.result.as_mut().unwrap().last_end = Some(Finalizer::Ok {
364-
rows: self.col as u64,
365-
last_insert_id: 0,
366-
});
367-
} else {
368-
// we wrote out at least one row
369-
self.result.as_mut().unwrap().last_end = Some(Finalizer::EOF);
361+
if complete {
362+
if self.columns.is_empty() {
363+
// response to no column query is always an OK packet
364+
// we've kept track of the number of rows in col (hacky, I know)
365+
self.result.as_mut().unwrap().last_end = Some(Finalizer::Ok {
366+
rows: self.col as u64,
367+
last_insert_id: 0,
368+
});
369+
} else {
370+
// we wrote out at least one row
371+
self.result.as_mut().unwrap().last_end = Some(Finalizer::EOF);
372+
}
370373
}
374+
371375
Ok(())
372376
}
373377

@@ -378,15 +382,26 @@ impl<'a, W: Write + 'a> RowWriter<'a, W> {
378382

379383
/// End this resultset response, and indicate to the client that no more rows are coming.
380384
pub fn finish_one(mut self) -> io::Result<QueryResultWriter<'a, W>> {
381-
self.finish_inner()?;
385+
self.finish_inner(true)?;
386+
382387
// we know that dropping self will see self.finished == true,
383388
// and so Drop won't try to use self.result.
384389
Ok(self.result.take().unwrap())
385390
}
391+
392+
/// End this resultset response, and indicate to the client there was an error.
393+
pub fn finish_error<E>(mut self, kind: ErrorKind, msg: &E) -> io::Result<()>
394+
where
395+
E: Borrow<[u8]>,
396+
{
397+
self.finish_inner(false)?;
398+
399+
self.result.take().unwrap().error(kind, msg)
400+
}
386401
}
387402

388403
impl<'a, W: Write + 'a> Drop for RowWriter<'a, W> {
389404
fn drop(&mut self) {
390-
self.finish_inner().unwrap();
405+
self.finish_inner(true).unwrap();
391406
}
392407
}

tests/main.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,44 @@ fn error_response() {
266266
})
267267
}
268268

269+
#[test]
270+
fn error_in_result_set_response() {
271+
let err = (ErrorKind::ER_NO, "clearly not");
272+
TestingShim::new(
273+
move |_, w| {
274+
let cols = &[Column {
275+
table: String::new(),
276+
column: "a".to_owned(),
277+
coltype: myc::constants::ColumnType::MYSQL_TYPE_SHORT,
278+
colflags: myc::constants::ColumnFlags::empty(),
279+
}];
280+
let mut w = w.start(cols)?;
281+
w.write_col(1024)?;
282+
w.finish_error(err.0, &err.1.as_bytes())
283+
},
284+
|_| unreachable!(),
285+
|_, _, _| unreachable!(),
286+
|_, _| unreachable!(),
287+
)
288+
.test(|db| {
289+
let mut result = db.query_iter("SELECT a FROM foo").unwrap();
290+
let row1 = result.next().unwrap().unwrap().get::<i16, _>(0).unwrap();
291+
assert_eq!(row1, 1024);
292+
if let mysql::Error::MySqlError(e) = result.by_ref().next().unwrap().unwrap_err() {
293+
assert_eq!(
294+
e,
295+
mysql::error::MySqlError {
296+
state: String::from_utf8(err.0.sqlstate().to_vec()).unwrap(),
297+
message: err.1.to_owned(),
298+
code: err.0 as u16,
299+
}
300+
);
301+
} else {
302+
unreachable!()
303+
}
304+
})
305+
}
306+
269307
#[test]
270308
fn empty_on_drop() {
271309
let cols = [Column {

0 commit comments

Comments
 (0)