Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve parsing performance by reducing token cloning #1587

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,14 @@ You can run them with:
```
git checkout main
cd sqlparser_bench
cargo bench
cargo bench -- --save-baseline main
git checkout <your branch>
cargo bench
cargo bench -- --baseline main
```

By adding the `--save-baseline main` and `--baseline main` you can track the
progress of your improvements as you continue working on the feature branch.

## Licensing

All code in this repository is licensed under the [Apache Software License 2.0](LICENSE.txt).
Expand Down
9 changes: 9 additions & 0 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ macro_rules! dialect_of {
};
}

// Similar to above, but for applying directly against an instance of dialect
// instead of a struct member named dialect. This avoids lifetime issues when
// mixing match guards and token references.
macro_rules! dialect_is {
($dialect:ident is $($dialect_type:ty)|+) => {
($($dialect.is::<$dialect_type>())||+)
}
}

/// Encapsulates the differences between SQL implementations.
///
/// # SQL Dialects
Expand Down
8 changes: 4 additions & 4 deletions src/dialect/postgresql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,11 @@ impl Dialect for PostgreSqlDialect {

pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
let name = parser.maybe_parse(|parser| -> Result<ObjectName, ParserError> {
parser.expect_keyword(Keyword::CREATE)?;
parser.expect_keyword(Keyword::TYPE)?;
parser.expect_keyword_is(Keyword::CREATE)?;
parser.expect_keyword_is(Keyword::TYPE)?;
let name = parser.parse_object_name(false)?;
parser.expect_keyword(Keyword::AS)?;
parser.expect_keyword(Keyword::ENUM)?;
parser.expect_keyword_is(Keyword::AS)?;
parser.expect_keyword_is(Keyword::ENUM)?;
Ok(name)
});

Expand Down
16 changes: 8 additions & 8 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ pub fn parse_create_table(
match &next_token.token {
Token::Word(word) => match word.keyword {
Keyword::COPY => {
parser.expect_keyword(Keyword::GRANTS)?;
parser.expect_keyword_is(Keyword::GRANTS)?;
builder = builder.copy_grants(true);
}
Keyword::COMMENT => {
Expand All @@ -293,7 +293,7 @@ pub fn parse_create_table(
break;
}
Keyword::CLUSTER => {
parser.expect_keyword(Keyword::BY)?;
parser.expect_keyword_is(Keyword::BY)?;
parser.expect_token(&Token::LParen)?;
let cluster_by = Some(WrappedCollection::Parentheses(
parser.parse_comma_separated(|p| p.parse_identifier(false))?,
Expand Down Expand Up @@ -356,14 +356,14 @@ pub fn parse_create_table(
parser.prev_token();
}
Keyword::AGGREGATION => {
parser.expect_keyword(Keyword::POLICY)?;
parser.expect_keyword_is(Keyword::POLICY)?;
let aggregation_policy = parser.parse_object_name(false)?;
builder = builder.with_aggregation_policy(Some(aggregation_policy));
}
Keyword::ROW => {
parser.expect_keywords(&[Keyword::ACCESS, Keyword::POLICY])?;
let policy = parser.parse_object_name(false)?;
parser.expect_keyword(Keyword::ON)?;
parser.expect_keyword_is(Keyword::ON)?;
parser.expect_token(&Token::LParen)?;
let columns = parser.parse_comma_separated(|p| p.parse_identifier(false))?;
parser.expect_token(&Token::RParen)?;
Expand Down Expand Up @@ -528,15 +528,15 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
let from_stage: ObjectName;
let stage_params: StageParamsObject;

parser.expect_keyword(Keyword::FROM)?;
parser.expect_keyword_is(Keyword::FROM)?;
// check if data load transformations are present
match parser.next_token().token {
Token::LParen => {
// data load with transformations
parser.expect_keyword(Keyword::SELECT)?;
parser.expect_keyword_is(Keyword::SELECT)?;
from_transformations = parse_select_items_for_data_load(parser)?;

parser.expect_keyword(Keyword::FROM)?;
parser.expect_keyword_is(Keyword::FROM)?;
from_stage = parse_snowflake_stage_name(parser)?;
stage_params = parse_stage_params(parser)?;

Expand Down Expand Up @@ -852,7 +852,7 @@ fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, Pars
))
} else if parser.parse_keyword(Keyword::START) {
let seed = parser.parse_number()?;
parser.expect_keyword(Keyword::INCREMENT)?;
parser.expect_keyword_is(Keyword::INCREMENT)?;
let increment = parser.parse_number()?;

Some(IdentityPropertyFormatKind::StartAndIncrement(
Expand Down
8 changes: 4 additions & 4 deletions src/parser/alter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ impl Parser<'_> {
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterpolicy.html)
pub fn parse_alter_policy(&mut self) -> Result<Statement, ParserError> {
let name = self.parse_identifier(false)?;
self.expect_keyword(Keyword::ON)?;
self.expect_keyword_is(Keyword::ON)?;
let table_name = self.parse_object_name(false)?;

if self.parse_keyword(Keyword::RENAME) {
self.expect_keyword(Keyword::TO)?;
self.expect_keyword_is(Keyword::TO)?;
let new_name = self.parse_identifier(false)?;
Ok(Statement::AlterPolicy {
name,
Expand Down Expand Up @@ -232,7 +232,7 @@ impl Parser<'_> {
Some(Keyword::BYPASSRLS) => RoleOption::BypassRLS(true),
Some(Keyword::NOBYPASSRLS) => RoleOption::BypassRLS(false),
Some(Keyword::CONNECTION) => {
self.expect_keyword(Keyword::LIMIT)?;
self.expect_keyword_is(Keyword::LIMIT)?;
RoleOption::ConnectionLimit(Expr::Value(self.parse_number_value()?))
}
Some(Keyword::CREATEDB) => RoleOption::CreateDB(true),
Expand All @@ -256,7 +256,7 @@ impl Parser<'_> {
Some(Keyword::SUPERUSER) => RoleOption::SuperUser(true),
Some(Keyword::NOSUPERUSER) => RoleOption::SuperUser(false),
Some(Keyword::VALID) => {
self.expect_keyword(Keyword::UNTIL)?;
self.expect_keyword_is(Keyword::UNTIL)?;
RoleOption::ValidUntil(Expr::Value(self.parse_value()?))
}
_ => self.expected("option", self.peek_token())?,
Expand Down
Loading
Loading