Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 34548e8

Browse files
authoredJun 11, 2020
Change Word::keyword to a enum (#193)
This improves performance and paves the way to future API enhancements as discussed in the PR https://github.com/andygrove/sqlparser-rs/pull/193
1 parent 0fe3a8e commit 34548e8

File tree

5 files changed

+395
-342
lines changed

5 files changed

+395
-342
lines changed
 

‎src/ast/mod.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -388,22 +388,6 @@ impl fmt::Display for WindowFrameUnits {
388388
}
389389
}
390390

391-
impl FromStr for WindowFrameUnits {
392-
type Err = ParserError;
393-
394-
fn from_str(s: &str) -> Result<Self, Self::Err> {
395-
match s {
396-
"ROWS" => Ok(WindowFrameUnits::Rows),
397-
"RANGE" => Ok(WindowFrameUnits::Range),
398-
"GROUPS" => Ok(WindowFrameUnits::Groups),
399-
_ => Err(ParserError::ParserError(format!(
400-
"Expected ROWS, RANGE, or GROUPS, found: {}",
401-
s
402-
))),
403-
}
404-
}
405-
}
406-
407391
/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
408392
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
409393
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

‎src/dialect/keywords.rs

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,24 @@ macro_rules! define_keywords {
4141
($(
4242
$ident:ident $(= $string_keyword:expr)?
4343
),*) => {
44-
$(kw_def!($ident $(= $string_keyword)?);)*
44+
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
45+
#[allow(non_camel_case_types)]
46+
pub enum Keyword {
47+
NoKeyword,
48+
$($ident),*
49+
}
4550

51+
pub const ALL_KEYWORDS_INDEX: &[Keyword] = &[
52+
$(Keyword::$ident),*
53+
];
54+
55+
$(kw_def!($ident $(= $string_keyword)?);)*
4656
pub const ALL_KEYWORDS: &[&str] = &[
4757
$($ident),*
4858
];
49-
}
59+
60+
};
61+
5062
}
5163

5264
// The following keywords should be sorted to be able to match using binary search
@@ -434,20 +446,52 @@ define_keywords!(
434446

435447
/// These keywords can't be used as a table alias, so that `FROM table_name alias`
436448
/// can be parsed unambiguously without looking ahead.
437-
pub const RESERVED_FOR_TABLE_ALIAS: &[&str] = &[
449+
pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
438450
// Reserved as both a table and a column alias:
439-
WITH, SELECT, WHERE, GROUP, HAVING, ORDER, TOP, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
451+
Keyword::WITH,
452+
Keyword::SELECT,
453+
Keyword::WHERE,
454+
Keyword::GROUP,
455+
Keyword::HAVING,
456+
Keyword::ORDER,
457+
Keyword::TOP,
458+
Keyword::LIMIT,
459+
Keyword::OFFSET,
460+
Keyword::FETCH,
461+
Keyword::UNION,
462+
Keyword::EXCEPT,
463+
Keyword::INTERSECT,
440464
// Reserved only as a table alias in the `FROM`/`JOIN` clauses:
441-
ON, JOIN, INNER, CROSS, FULL, LEFT, RIGHT, NATURAL, USING,
465+
Keyword::ON,
466+
Keyword::JOIN,
467+
Keyword::INNER,
468+
Keyword::CROSS,
469+
Keyword::FULL,
470+
Keyword::LEFT,
471+
Keyword::RIGHT,
472+
Keyword::NATURAL,
473+
Keyword::USING,
442474
// for MSSQL-specific OUTER APPLY (seems reserved in most dialects)
443-
OUTER,
475+
Keyword::OUTER,
444476
];
445477

446478
/// Can't be used as a column alias, so that `SELECT <expr> alias`
447479
/// can be parsed unambiguously without looking ahead.
448-
pub const RESERVED_FOR_COLUMN_ALIAS: &[&str] = &[
480+
pub const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
449481
// Reserved as both a table and a column alias:
450-
WITH, SELECT, WHERE, GROUP, HAVING, ORDER, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
451-
// Reserved only as a column alias in the `SELECT` clause:
452-
FROM,
482+
Keyword::WITH,
483+
Keyword::SELECT,
484+
Keyword::WHERE,
485+
Keyword::GROUP,
486+
Keyword::HAVING,
487+
Keyword::ORDER,
488+
Keyword::TOP,
489+
Keyword::LIMIT,
490+
Keyword::OFFSET,
491+
Keyword::FETCH,
492+
Keyword::UNION,
493+
Keyword::EXCEPT,
494+
Keyword::INTERSECT,
495+
// Reserved only as a column alias in the `SELECT` clause
496+
Keyword::FROM,
453497
];

‎src/parser.rs

Lines changed: 329 additions & 305 deletions
Large diffs are not rendered by default.

‎src/tokenizer.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use std::iter::Peekable;
2020
use std::str::Chars;
2121

22-
use super::dialect::keywords::ALL_KEYWORDS;
22+
use super::dialect::keywords::{Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX};
2323
use super::dialect::Dialect;
2424
use std::fmt;
2525

@@ -146,15 +146,14 @@ impl Token {
146146
}
147147
pub fn make_word(word: &str, quote_style: Option<char>) -> Self {
148148
let word_uppercase = word.to_uppercase();
149-
let is_keyword =
150-
quote_style == None && ALL_KEYWORDS.binary_search(&word_uppercase.as_str()).is_ok();
151149
Token::Word(Word {
152150
value: word.to_string(),
153151
quote_style,
154-
keyword: if is_keyword {
155-
word_uppercase
152+
keyword: if quote_style == None {
153+
let keyword = ALL_KEYWORDS.binary_search(&word_uppercase.as_str());
154+
keyword.map_or(Keyword::NoKeyword, |x| ALL_KEYWORDS_INDEX[x])
156155
} else {
157-
"".to_string()
156+
Keyword::NoKeyword
158157
},
159158
})
160159
}
@@ -172,7 +171,7 @@ pub struct Word {
172171
pub quote_style: Option<char>,
173172
/// If the word was not quoted and it matched one of the known keywords,
174173
/// this will have one of the values from dialect::keywords, otherwise empty
175-
pub keyword: String,
174+
pub keyword: Keyword,
176175
}
177176

178177
impl fmt::Display for Word {

‎tests/sqlparser_common.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use matches::assert_matches;
2222

2323
use sqlparser::ast::*;
2424
use sqlparser::dialect::keywords::ALL_KEYWORDS;
25-
use sqlparser::parser::*;
25+
use sqlparser::parser::{Parser, ParserError};
2626
use sqlparser::test_utils::{all_dialects, expr_from_projection, number, only};
2727

2828
#[test]
@@ -1354,10 +1354,12 @@ fn parse_window_functions() {
13541354
avg(bar) OVER (ORDER BY a \
13551355
RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING), \
13561356
max(baz) OVER (ORDER BY a \
1357-
ROWS UNBOUNDED PRECEDING) \
1357+
ROWS UNBOUNDED PRECEDING), \
1358+
sum(qux) OVER (ORDER BY a \
1359+
GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) \
13581360
FROM foo";
13591361
let select = verified_only_select(sql);
1360-
assert_eq!(4, select.projection.len());
1362+
assert_eq!(5, select.projection.len());
13611363
assert_eq!(
13621364
&Expr::Function(Function {
13631365
name: ObjectName(vec![Ident::new("row_number")]),
@@ -2872,7 +2874,7 @@ fn parse_drop_index() {
28722874
}
28732875

28742876
#[test]
2875-
fn keywords_sorted() {
2877+
fn all_keywords_sorted() {
28762878
// assert!(ALL_KEYWORDS.is_sorted())
28772879
let mut copy = Vec::from(ALL_KEYWORDS);
28782880
copy.sort();

0 commit comments

Comments
 (0)
Please sign in to comment.