1313use bigdecimal:: BigDecimal ;
1414use std:: fmt;
1515
16+ mod datetime;
17+ pub use datetime:: {
18+ DateTimeField , Interval , IntervalValue , ParsedDate , ParsedDateTime , ParsedTimestamp ,
19+ } ;
20+
21+ #[ derive( Debug ) ]
22+ pub struct ValueError ( String ) ;
23+
24+ impl std:: error:: Error for ValueError { }
25+
26+ impl fmt:: Display for ValueError {
27+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
28+ write ! ( f, "{}" , self . 0 )
29+ }
30+ }
31+
1632/// Primitive SQL values such as number and string
1733#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
1834pub enum Value {
@@ -29,14 +45,14 @@ pub enum Value {
2945 /// Boolean value true or false
3046 Boolean ( bool ) ,
3147 /// `DATE '...'` literals
32- Date ( String ) ,
48+ Date ( String , ParsedDate ) ,
3349 /// `TIME '...'` literals
3450 Time ( String ) ,
3551 /// `TIMESTAMP '...'` literals
36- Timestamp ( String ) ,
52+ Timestamp ( String , ParsedTimestamp ) ,
3753 /// INTERVAL literals, roughly in the following format:
3854 ///
39- /// ```ignore
55+ /// ```text
4056 /// INTERVAL '<value>' <leading_field> [ (<leading_precision>) ]
4157 /// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]
4258 /// ```
@@ -45,47 +61,13 @@ pub enum Value {
4561 /// The parser does not validate the `<value>`, nor does it ensure
4662 /// that the `<leading_field>` units >= the units in `<last_field>`,
4763 /// so the user will have to reject intervals like `HOUR TO YEAR`.
48- Interval {
49- /// The raw [value] that was present in `INTERVAL '[value]'`
50- value : String ,
51- /// The unit of the first field in the interval. `INTERVAL 'T' MINUTE`
52- /// means `T` is in minutes
53- leading_field : DateTimeField ,
54- /// How many digits the leading field is allowed to occupy.
55- ///
56- /// The interval `INTERVAL '1234' MINUTE(3)` is **illegal**, but `INTERVAL
57- /// '123' MINUTE(3)` is fine.
58- ///
59- /// This parser does not do any validation that fields fit.
60- leading_precision : Option < u64 > ,
61- /// How much precision to keep track of
62- ///
63- /// If this is ommitted, then you are supposed to ignore all of the
64- /// non-lead fields. If it is less precise than the final field, you
65- /// are supposed to ignore the final field.
66- ///
67- /// For the following specifications:
68- ///
69- /// * `INTERVAL '1:1:1' HOURS TO SECONDS` the `last_field` gets
70- /// `Some(DateTimeField::Second)` and interpreters should generate an
71- /// interval equivalent to `3661` seconds.
72- /// * In `INTERVAL '1:1:1' HOURS` the `last_field` gets `None` and
73- /// interpreters should generate an interval equivalent to `3600`
74- /// seconds.
75- /// * In `INTERVAL '1:1:1' HOURS TO MINUTES` the interval should be
76- /// equivalent to `3660` seconds.
77- last_field : Option < DateTimeField > ,
78- /// The seconds precision can be specified in SQL source as
79- /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
80- /// will be `Second` and the `last_field` will be `None`),
81- /// or as `__ TO SECOND(x)`.
82- fractional_seconds_precision : Option < u64 > ,
83- } ,
64+ Interval ( IntervalValue ) ,
8465 /// `NULL` value
8566 Null ,
8667}
8768
8869impl fmt:: Display for Value {
70+ #[ allow( clippy:: unneeded_field_pattern) ] // want to be warned if we add another field
8971 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9072 match self {
9173 Value :: Long ( v) => write ! ( f, "{}" , v) ,
@@ -94,16 +76,17 @@ impl fmt::Display for Value {
9476 Value :: NationalStringLiteral ( v) => write ! ( f, "N'{}'" , v) ,
9577 Value :: HexStringLiteral ( v) => write ! ( f, "X'{}'" , v) ,
9678 Value :: Boolean ( v) => write ! ( f, "{}" , v) ,
97- Value :: Date ( v) => write ! ( f, "DATE '{}'" , escape_single_quote_string( v) ) ,
79+ Value :: Date ( v, _ ) => write ! ( f, "DATE '{}'" , escape_single_quote_string( v) ) ,
9880 Value :: Time ( v) => write ! ( f, "TIME '{}'" , escape_single_quote_string( v) ) ,
99- Value :: Timestamp ( v) => write ! ( f, "TIMESTAMP '{}'" , escape_single_quote_string( v) ) ,
100- Value :: Interval {
81+ Value :: Timestamp ( v, _) => write ! ( f, "TIMESTAMP '{}'" , escape_single_quote_string( v) ) ,
82+ Value :: Interval ( IntervalValue {
83+ parsed : _,
10184 value,
10285 leading_field : DateTimeField :: Second ,
10386 leading_precision : Some ( leading_precision) ,
10487 last_field,
10588 fractional_seconds_precision : Some ( fractional_seconds_precision) ,
106- } => {
89+ } ) => {
10790 // When the leading field is SECOND, the parser guarantees that
10891 // the last field is None.
10992 assert ! ( last_field. is_none( ) ) ;
@@ -115,13 +98,14 @@ impl fmt::Display for Value {
11598 fractional_seconds_precision
11699 )
117100 }
118- Value :: Interval {
101+ Value :: Interval ( IntervalValue {
102+ parsed : _,
119103 value,
120104 leading_field,
121105 leading_precision,
122106 last_field,
123107 fractional_seconds_precision,
124- } => {
108+ } ) => {
125109 write ! (
126110 f,
127111 "INTERVAL '{}' {}" ,
@@ -144,29 +128,6 @@ impl fmt::Display for Value {
144128 }
145129}
146130
147- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
148- pub enum DateTimeField {
149- Year ,
150- Month ,
151- Day ,
152- Hour ,
153- Minute ,
154- Second ,
155- }
156-
157- impl fmt:: Display for DateTimeField {
158- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
159- f. write_str ( match self {
160- DateTimeField :: Year => "YEAR" ,
161- DateTimeField :: Month => "MONTH" ,
162- DateTimeField :: Day => "DAY" ,
163- DateTimeField :: Hour => "HOUR" ,
164- DateTimeField :: Minute => "MINUTE" ,
165- DateTimeField :: Second => "SECOND" ,
166- } )
167- }
168- }
169-
170131pub struct EscapeSingleQuoteString < ' a > ( & ' a str ) ;
171132
172133impl < ' a > fmt:: Display for EscapeSingleQuoteString < ' a > {
@@ -185,3 +146,39 @@ impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
185146pub fn escape_single_quote_string ( s : & str ) -> EscapeSingleQuoteString < ' _ > {
186147 EscapeSingleQuoteString ( s)
187148}
149+
150+ #[ cfg( test) ]
151+ mod test {
152+ use super :: * ;
153+
154+ /// An extremely default interval value
155+ fn ivalue ( ) -> IntervalValue {
156+ IntervalValue {
157+ value : "" . into ( ) ,
158+ parsed : ParsedDateTime :: default ( ) ,
159+ leading_field : DateTimeField :: Year ,
160+ leading_precision : None ,
161+ last_field : None ,
162+ fractional_seconds_precision : None ,
163+ }
164+ }
165+
166+ #[ test]
167+ fn interval_values ( ) {
168+ let mut iv = ivalue ( ) ;
169+ iv. parsed . year = None ;
170+ match iv. computed_permissive ( ) {
171+ Err ( ValueError { .. } ) => { }
172+ Ok ( why) => panic ! ( "should not be okay: {:?}" , why) ,
173+ }
174+ }
175+
176+ #[ test]
177+ fn iterate_datetimefield ( ) {
178+ use DateTimeField :: * ;
179+ assert_eq ! (
180+ Year . into_iter( ) . take( 10 ) . collect:: <Vec <_>>( ) ,
181+ vec![ Month , Day , Hour , Minute , Second ]
182+ )
183+ }
184+ }
0 commit comments