From b0f8ed6b56dcc534db986fae8840b9381eb37f78 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Wed, 9 Nov 2016 15:15:09 +0000 Subject: [PATCH] Improving parsing of time durations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the number 0 was parsed as 0ns. In addition, it is now not possible to have duration values defined as strings (inside “” or ‘’). However, now values are explicitly marked as a duration only if they have a valid DURATION suffix. Anlything else is either a NUMBER of an IDENT. --- sql/scanner.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/sql/scanner.go b/sql/scanner.go index cb819126..2504f79d 100644 --- a/sql/scanner.go +++ b/sql/scanner.go @@ -578,8 +578,24 @@ func (s *scanner) scanNumber(chp ...rune) (tok Token, lit string, val interface{ } else if isNumber(ch) { buf.WriteRune(ch) } else if isLetter(ch) { - tok = IDENT - buf.WriteRune(ch) + if tok == NUMBER || tok == DOUBLE { + tok = IDENT + buf.WriteRune(ch) + switch ch { + case 's', 'h', 'd', 'w': + tok = DURATION + case 'n', 'u', 'µ', 'm': + if chn := s.next(); chn == 's' { + tok = DURATION + buf.WriteRune(chn) + } else { + s.undo() + } + } + } else { + tok = IDENT + buf.WriteRune(ch) + } } else if ch == '.' { if tok == DOUBLE { tok = IDENT @@ -594,10 +610,6 @@ func (s *scanner) scanNumber(chp ...rune) (tok Token, lit string, val interface{ } } - if val, err := time.ParseDuration(buf.String()); err == nil { - return DURATION, buf.String(), val - } - return tok, buf.String(), nil } @@ -663,10 +675,6 @@ func (s *scanner) scanString(chp ...rune) (tok Token, lit string, val interface{ } } - if val, err := time.ParseDuration(buf.String()); err == nil { - return DURATION, buf.String(), val - } - if val, err := time.Parse(RFCDate, buf.String()); err == nil { return DATE, buf.String(), val.UTC() } @@ -826,7 +834,7 @@ func isNumber(ch rune) bool { // isLetter returns true if the rune is a letter. func isLetter(ch rune) bool { - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == 'µ' } // isIdentChar returns true if the rune is allowed in a IDENT.