@@ -394,10 +394,21 @@ impl<'a> Tokenizer<'a> {
394394 )
395395 }
396396 }
397- // numbers
398- '0' ..='9' => {
399- // TODO: https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#unsigned-numeric-literal
400- let s = peeking_take_while ( chars, |ch| matches ! ( ch, '0' ..='9' | '.' ) ) ;
397+ // numbers and period
398+ '0' ..='9' | '.' => {
399+ let mut s = peeking_take_while ( chars, |ch| matches ! ( ch, '0' ..='9' ) ) ;
400+ // match one period
401+ if let Some ( '.' ) = chars. peek ( ) {
402+ s. push ( '.' ) ;
403+ chars. next ( ) ;
404+ }
405+ s += & peeking_take_while ( chars, |ch| matches ! ( ch, '0' ..='9' ) ) ;
406+
407+ // No number -> Token::Period
408+ if s == "." {
409+ return Ok ( Some ( Token :: Period ) ) ;
410+ }
411+
401412 let long = if chars. peek ( ) == Some ( & 'L' ) {
402413 chars. next ( ) ;
403414 true
@@ -470,7 +481,6 @@ impl<'a> Tokenizer<'a> {
470481 _ => Ok ( Some ( Token :: Eq ) ) ,
471482 }
472483 }
473- '.' => self . consume_and_return ( chars, Token :: Period ) ,
474484 '!' => {
475485 chars. next ( ) ; // consume
476486 match chars. peek ( ) {
@@ -667,6 +677,22 @@ mod tests {
667677 compare ( expected, tokens) ;
668678 }
669679
680+ #[ test]
681+ fn tokenize_select_float ( ) {
682+ let sql = String :: from ( "SELECT .1" ) ;
683+ let dialect = GenericDialect { } ;
684+ let mut tokenizer = Tokenizer :: new ( & dialect, & sql) ;
685+ let tokens = tokenizer. tokenize ( ) . unwrap ( ) ;
686+
687+ let expected = vec ! [
688+ Token :: make_keyword( "SELECT" ) ,
689+ Token :: Whitespace ( Whitespace :: Space ) ,
690+ Token :: Number ( String :: from( ".1" ) , false ) ,
691+ ] ;
692+
693+ compare ( expected, tokens) ;
694+ }
695+
670696 #[ test]
671697 fn tokenize_scalar_function ( ) {
672698 let sql = String :: from ( "SELECT sqrt(1)" ) ;
0 commit comments