Skip to content

Commit

Permalink
copr: always check fsp
Browse files Browse the repository at this point in the history
  • Loading branch information
BusyJay committed Sep 21, 2016
1 parent 4b53bba commit 635df57
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 35 deletions.
28 changes: 8 additions & 20 deletions src/util/codec/mysql/duration.rs
Expand Up @@ -94,35 +94,29 @@ impl Duration {
if self.neg { -nanos } else { nanos }
}

pub fn from_nanos(nanos: i64, fsp: u8) -> Result<Duration> {
pub fn from_nanos(nanos: i64, fsp: i8) -> Result<Duration> {
let neg = nanos < 0;
let nanos = nanos.abs();

let dur = StdDuration::new((nanos / NANOS_PER_SEC) as u64,
(nanos % NANOS_PER_SEC) as u32);
try!(check_dur(&dur));

Ok(Duration {
dur: dur,
neg: neg,
fsp: fsp,
})
Duration::new(dur, neg, fsp)
}

pub fn new(dur: StdDuration, neg: bool, fsp: u8) -> Result<Duration> {
pub fn new(dur: StdDuration, neg: bool, fsp: i8) -> Result<Duration> {
try!(check_dur(&dur));
Ok(Duration {
dur: dur,
neg: neg,
fsp: fsp,
fsp: try!(check_fsp(fsp)),
})
}

// `parse` parses the time form a formatted string with a fractional seconds part,
// returns the duration type Time value.
// See: http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
pub fn parse(mut s: &[u8], fsp: u8) -> Result<Duration> {
try!(check_fsp(fsp));
pub fn parse(mut s: &[u8], fsp: i8) -> Result<Duration> {
let fsp = try!(check_fsp(fsp));

let (mut neg, mut day, mut frac) = (false, None, 0);

Expand Down Expand Up @@ -182,13 +176,7 @@ impl Duration {
}

let dur = StdDuration::new(secs, frac);
try!(check_dur(&dur));

Ok(Duration {
dur: dur,
neg: neg,
fsp: fsp,
})
Duration::new(dur, neg, fsp as i8)
}

pub fn to_decimal(&self) -> Result<Decimal> {
Expand Down Expand Up @@ -262,7 +250,7 @@ mod test {

#[test]
fn test_parse() {
let cases: Vec<(&'static [u8], u8, Option<&'static str>)> = vec![
let cases: Vec<(&'static [u8], i8, Option<&'static str>)> = vec![
(b"10:11:12", 0, Some("10:11:12")),
(b"101112", 0, Some("10:11:12")),
(b"10:11", 0, Some("10:11:00")),
Expand Down
17 changes: 12 additions & 5 deletions src/util/codec/mysql/mod.rs
Expand Up @@ -14,17 +14,24 @@
use util::codec::Result;
use util::escape;

/// `UN_SPECIFIED_FSP` is the unspecified fractional seconds part.
const UN_SPECIFIED_FSP: i8 = -1;
/// `MAX_FSP` is the maximum digit of fractional seconds part.
pub const MAX_FSP: u8 = 6;
pub const MAX_FSP: i8 = 6;
/// `MIN_FSP` is the minimum digit of fractional seconds part.
pub const MIN_FSP: i8 = 0;
/// `DEFAULT_FSP` is the default digit of fractional seconds part.
/// `MySQL` use 0 as the default Fsp.
pub const DEFAULT_FSP: u8 = 0;
pub const DEFAULT_FSP: i8 = 0;

fn check_fsp(fsp: u8) -> Result<()> {
if fsp > MAX_FSP {
fn check_fsp(fsp: i8) -> Result<u8> {
if fsp == UN_SPECIFIED_FSP {
return Ok(DEFAULT_FSP as u8);
}
if fsp > MAX_FSP || fsp < MIN_FSP {
return Err(invalid_type!("Invalid fsp {}", fsp));
}
Ok(())
Ok(fsp as u8)
}

/// Parse string as if it's a fraction part of a number and keep
Expand Down
20 changes: 11 additions & 9 deletions src/util/codec/mysql/time.rs
Expand Up @@ -109,11 +109,11 @@ pub struct Time {
}

impl Time {
pub fn new(time: NaiveDateTime, tp: u8, fsp: u8) -> Result<Time> {
pub fn new(time: NaiveDateTime, tp: u8, fsp: i8) -> Result<Time> {
Ok(Time {
time: time,
tp: tp,
fsp: fsp,
fsp: try!(check_fsp(fsp)),
})
}

Expand Down Expand Up @@ -170,8 +170,8 @@ impl Time {
}
}

pub fn parse_datetime(s: &str, fsp: u8) -> Result<Time> {
try!(check_fsp(fsp));
pub fn parse_datetime(s: &str, fsp: i8) -> Result<Time> {
let fsp = try!(check_fsp(fsp));
let mut frac_str = "";
let mut need_adjust = false;
let parts = Time::parse_datetime_format(s);
Expand Down Expand Up @@ -236,13 +236,14 @@ impl Time {
return Err(box_err!("unsupport year: {}", y));
}
let t = try!(ymd_hms_nanos(y, m, d, h, minute, sec, frac * TEN_POW[9 - fsp as usize]));
Time::new(t, types::DATETIME as u8, fsp)
Time::new(t, types::DATETIME as u8, fsp as i8)
}

pub fn from_packed_u64(t: u64, tp: u8, fsp: u8) -> Result<Time> {
pub fn from_packed_u64(t: u64, tp: u8, fsp: i8) -> Result<Time> {
if t == 0 {
return Time::new(zero_time(), tp, fsp);
}
let fsp = try!(mysql::check_fsp(fsp));
let ymdhms = t >> 24;
let ymd = ymdhms >> 17;
let day = (ymd & ((1 << 5) - 1)) as u32;
Expand All @@ -255,7 +256,7 @@ impl Time {
let hour = (hms >> 12) as u32;
let nanosec = ((t & ((1 << 24) - 1)) * 1000) as u32;
let t = try!(ymd_hms_nanos(year, month, day, hour, minute, second, nanosec));
Time::new(t, tp, fsp)
Time::new(t, tp, fsp as i8)
}

pub fn to_packed_u64(&self) -> u64 {
Expand Down Expand Up @@ -337,7 +338,7 @@ mod test {

use std::cmp::Ordering;

use util::codec::mysql::{MAX_FSP, types};
use util::codec::mysql::{MAX_FSP, UN_SPECIFIED_FSP, types};

#[test]
fn test_parse_datetime() {
Expand All @@ -360,7 +361,7 @@ mod test {
];

for (input, exp) in ok_tables {
let t = Time::parse_datetime(input, 0).unwrap();
let t = Time::parse_datetime(input, UN_SPECIFIED_FSP).unwrap();
assert_eq!(format!("{}", t), exp);
}

Expand Down Expand Up @@ -396,6 +397,7 @@ mod test {
let cases = vec![
("2010-10-10 10:11:11", 0),
("0001-01-01 00:00:00", 0),
("0001-01-01 00:00:00", UN_SPECIFIED_FSP),
("2000-01-01 00:00:00.000000", MAX_FSP),
("2000-01-01 00:00:00.123456", MAX_FSP),
("0001-01-01 00:00:00.123456", MAX_FSP),
Expand Down
2 changes: 1 addition & 1 deletion src/util/codec/table.rs
Expand Up @@ -171,7 +171,7 @@ fn unflatten(datum: Datum, col: &ColumnInfo) -> Result<Datum> {
types::STRING |
types::NEW_DECIMAL => Ok(datum),
types::DATE | types::DATETIME | types::TIMESTAMP => {
let fsp = col.get_decimal() as u8;
let fsp = col.get_decimal() as i8;
let t = try!(Time::from_packed_u64(datum.u64(), col.get_tp() as u8, fsp));
Ok(Datum::Time(t))
}
Expand Down

0 comments on commit 635df57

Please sign in to comment.