mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 15:34:09 +00:00
Improve parsing performance by reducing token cloning (#1587)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
024a878ee7
commit
df3c5652b1
6 changed files with 344 additions and 244 deletions
|
@ -240,11 +240,14 @@ You can run them with:
|
||||||
```
|
```
|
||||||
git checkout main
|
git checkout main
|
||||||
cd sqlparser_bench
|
cd sqlparser_bench
|
||||||
cargo bench
|
cargo bench -- --save-baseline main
|
||||||
git checkout <your branch>
|
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
|
## Licensing
|
||||||
|
|
||||||
All code in this repository is licensed under the [Apache Software License 2.0](LICENSE.txt).
|
All code in this repository is licensed under the [Apache Software License 2.0](LICENSE.txt).
|
||||||
|
|
|
@ -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.
|
/// Encapsulates the differences between SQL implementations.
|
||||||
///
|
///
|
||||||
/// # SQL Dialects
|
/// # SQL Dialects
|
||||||
|
|
|
@ -245,11 +245,11 @@ impl Dialect for PostgreSqlDialect {
|
||||||
|
|
||||||
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||||
let name = parser.maybe_parse(|parser| -> Result<ObjectName, ParserError> {
|
let name = parser.maybe_parse(|parser| -> Result<ObjectName, ParserError> {
|
||||||
parser.expect_keyword(Keyword::CREATE)?;
|
parser.expect_keyword_is(Keyword::CREATE)?;
|
||||||
parser.expect_keyword(Keyword::TYPE)?;
|
parser.expect_keyword_is(Keyword::TYPE)?;
|
||||||
let name = parser.parse_object_name(false)?;
|
let name = parser.parse_object_name(false)?;
|
||||||
parser.expect_keyword(Keyword::AS)?;
|
parser.expect_keyword_is(Keyword::AS)?;
|
||||||
parser.expect_keyword(Keyword::ENUM)?;
|
parser.expect_keyword_is(Keyword::ENUM)?;
|
||||||
Ok(name)
|
Ok(name)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -273,7 +273,7 @@ pub fn parse_create_table(
|
||||||
match &next_token.token {
|
match &next_token.token {
|
||||||
Token::Word(word) => match word.keyword {
|
Token::Word(word) => match word.keyword {
|
||||||
Keyword::COPY => {
|
Keyword::COPY => {
|
||||||
parser.expect_keyword(Keyword::GRANTS)?;
|
parser.expect_keyword_is(Keyword::GRANTS)?;
|
||||||
builder = builder.copy_grants(true);
|
builder = builder.copy_grants(true);
|
||||||
}
|
}
|
||||||
Keyword::COMMENT => {
|
Keyword::COMMENT => {
|
||||||
|
@ -297,7 +297,7 @@ pub fn parse_create_table(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Keyword::CLUSTER => {
|
Keyword::CLUSTER => {
|
||||||
parser.expect_keyword(Keyword::BY)?;
|
parser.expect_keyword_is(Keyword::BY)?;
|
||||||
parser.expect_token(&Token::LParen)?;
|
parser.expect_token(&Token::LParen)?;
|
||||||
let cluster_by = Some(WrappedCollection::Parentheses(
|
let cluster_by = Some(WrappedCollection::Parentheses(
|
||||||
parser.parse_comma_separated(|p| p.parse_identifier(false))?,
|
parser.parse_comma_separated(|p| p.parse_identifier(false))?,
|
||||||
|
@ -360,14 +360,14 @@ pub fn parse_create_table(
|
||||||
parser.prev_token();
|
parser.prev_token();
|
||||||
}
|
}
|
||||||
Keyword::AGGREGATION => {
|
Keyword::AGGREGATION => {
|
||||||
parser.expect_keyword(Keyword::POLICY)?;
|
parser.expect_keyword_is(Keyword::POLICY)?;
|
||||||
let aggregation_policy = parser.parse_object_name(false)?;
|
let aggregation_policy = parser.parse_object_name(false)?;
|
||||||
builder = builder.with_aggregation_policy(Some(aggregation_policy));
|
builder = builder.with_aggregation_policy(Some(aggregation_policy));
|
||||||
}
|
}
|
||||||
Keyword::ROW => {
|
Keyword::ROW => {
|
||||||
parser.expect_keywords(&[Keyword::ACCESS, Keyword::POLICY])?;
|
parser.expect_keywords(&[Keyword::ACCESS, Keyword::POLICY])?;
|
||||||
let policy = parser.parse_object_name(false)?;
|
let policy = parser.parse_object_name(false)?;
|
||||||
parser.expect_keyword(Keyword::ON)?;
|
parser.expect_keyword_is(Keyword::ON)?;
|
||||||
parser.expect_token(&Token::LParen)?;
|
parser.expect_token(&Token::LParen)?;
|
||||||
let columns = parser.parse_comma_separated(|p| p.parse_identifier(false))?;
|
let columns = parser.parse_comma_separated(|p| p.parse_identifier(false))?;
|
||||||
parser.expect_token(&Token::RParen)?;
|
parser.expect_token(&Token::RParen)?;
|
||||||
|
@ -536,15 +536,15 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||||
let from_stage: ObjectName;
|
let from_stage: ObjectName;
|
||||||
let stage_params: StageParamsObject;
|
let stage_params: StageParamsObject;
|
||||||
|
|
||||||
parser.expect_keyword(Keyword::FROM)?;
|
parser.expect_keyword_is(Keyword::FROM)?;
|
||||||
// check if data load transformations are present
|
// check if data load transformations are present
|
||||||
match parser.next_token().token {
|
match parser.next_token().token {
|
||||||
Token::LParen => {
|
Token::LParen => {
|
||||||
// data load with transformations
|
// data load with transformations
|
||||||
parser.expect_keyword(Keyword::SELECT)?;
|
parser.expect_keyword_is(Keyword::SELECT)?;
|
||||||
from_transformations = parse_select_items_for_data_load(parser)?;
|
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)?;
|
from_stage = parse_snowflake_stage_name(parser)?;
|
||||||
stage_params = parse_stage_params(parser)?;
|
stage_params = parse_stage_params(parser)?;
|
||||||
|
|
||||||
|
@ -860,7 +860,7 @@ fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, Pars
|
||||||
))
|
))
|
||||||
} else if parser.parse_keyword(Keyword::START) {
|
} else if parser.parse_keyword(Keyword::START) {
|
||||||
let seed = parser.parse_number()?;
|
let seed = parser.parse_number()?;
|
||||||
parser.expect_keyword(Keyword::INCREMENT)?;
|
parser.expect_keyword_is(Keyword::INCREMENT)?;
|
||||||
let increment = parser.parse_number()?;
|
let increment = parser.parse_number()?;
|
||||||
|
|
||||||
Some(IdentityPropertyFormatKind::StartAndIncrement(
|
Some(IdentityPropertyFormatKind::StartAndIncrement(
|
||||||
|
|
|
@ -52,11 +52,11 @@ impl Parser<'_> {
|
||||||
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterpolicy.html)
|
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterpolicy.html)
|
||||||
pub fn parse_alter_policy(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_alter_policy(&mut self) -> Result<Statement, ParserError> {
|
||||||
let name = self.parse_identifier(false)?;
|
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)?;
|
let table_name = self.parse_object_name(false)?;
|
||||||
|
|
||||||
if self.parse_keyword(Keyword::RENAME) {
|
if self.parse_keyword(Keyword::RENAME) {
|
||||||
self.expect_keyword(Keyword::TO)?;
|
self.expect_keyword_is(Keyword::TO)?;
|
||||||
let new_name = self.parse_identifier(false)?;
|
let new_name = self.parse_identifier(false)?;
|
||||||
Ok(Statement::AlterPolicy {
|
Ok(Statement::AlterPolicy {
|
||||||
name,
|
name,
|
||||||
|
@ -232,7 +232,7 @@ impl Parser<'_> {
|
||||||
Some(Keyword::BYPASSRLS) => RoleOption::BypassRLS(true),
|
Some(Keyword::BYPASSRLS) => RoleOption::BypassRLS(true),
|
||||||
Some(Keyword::NOBYPASSRLS) => RoleOption::BypassRLS(false),
|
Some(Keyword::NOBYPASSRLS) => RoleOption::BypassRLS(false),
|
||||||
Some(Keyword::CONNECTION) => {
|
Some(Keyword::CONNECTION) => {
|
||||||
self.expect_keyword(Keyword::LIMIT)?;
|
self.expect_keyword_is(Keyword::LIMIT)?;
|
||||||
RoleOption::ConnectionLimit(Expr::Value(self.parse_number_value()?))
|
RoleOption::ConnectionLimit(Expr::Value(self.parse_number_value()?))
|
||||||
}
|
}
|
||||||
Some(Keyword::CREATEDB) => RoleOption::CreateDB(true),
|
Some(Keyword::CREATEDB) => RoleOption::CreateDB(true),
|
||||||
|
@ -256,7 +256,7 @@ impl Parser<'_> {
|
||||||
Some(Keyword::SUPERUSER) => RoleOption::SuperUser(true),
|
Some(Keyword::SUPERUSER) => RoleOption::SuperUser(true),
|
||||||
Some(Keyword::NOSUPERUSER) => RoleOption::SuperUser(false),
|
Some(Keyword::NOSUPERUSER) => RoleOption::SuperUser(false),
|
||||||
Some(Keyword::VALID) => {
|
Some(Keyword::VALID) => {
|
||||||
self.expect_keyword(Keyword::UNTIL)?;
|
self.expect_keyword_is(Keyword::UNTIL)?;
|
||||||
RoleOption::ValidUntil(Expr::Value(self.parse_value()?))
|
RoleOption::ValidUntil(Expr::Value(self.parse_value()?))
|
||||||
}
|
}
|
||||||
_ => self.expected("option", self.peek_token())?,
|
_ => self.expected("option", self.peek_token())?,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue