Skip to content

Commit

Permalink
Use macros to generate SQL parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
sa1 committed Oct 13, 2022
1 parent 047f651 commit 77c4faf
Showing 1 changed file with 50 additions and 119 deletions.
169 changes: 50 additions & 119 deletions core/src/parse_sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,124 +18,55 @@ pub fn parse<Sql: AsRef<str>>(sql: Sql) -> Result<Vec<SqlStatement>> {
Parser::parse_sql(&DIALECT, sql.as_ref()).map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_query<Sql: AsRef<str>>(sql_expr: Sql) -> Result<SqlQuery> {
let tokens = Tokenizer::new(&DIALECT, sql_expr.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_query()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
macro_rules! parse_ {
($fn_name: ident, $parse_fn_name: ident, $output_type: ty) => {
pub fn $fn_name<Sql: AsRef<str>>(sql_expr: Sql) -> Result<$output_type> {
let tokens = Tokenizer::new(&DIALECT, sql_expr.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.$parse_fn_name()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}
};
($fn_name: ident, $parse_fn_name: ident, $parse_fn_arg: ident, $output_type: ty) => {
pub fn $fn_name<Sql: AsRef<str>>(sql_expr: Sql) -> Result<$output_type> {
let tokens = Tokenizer::new(&DIALECT, sql_expr.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.$parse_fn_name(Parser::$parse_fn_arg)
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}
};
}

pub fn parse_expr<Sql: AsRef<str>>(sql_expr: Sql) -> Result<SqlExpr> {
let tokens = Tokenizer::new(&DIALECT, sql_expr.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_expr()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_comma_separated_exprs<Sql: AsRef<str>>(sql_exprs: Sql) -> Result<Vec<SqlExpr>> {
let tokens = Tokenizer::new(&DIALECT, sql_exprs.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_comma_separated(Parser::parse_expr)
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_select_item<Sql: AsRef<str>>(sql_select_item: Sql) -> Result<SqlSelectItem> {
let tokens = Tokenizer::new(&DIALECT, sql_select_item.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_select_item()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_select_items<Sql: AsRef<str>>(sql_select_items: Sql) -> Result<Vec<SqlSelectItem>> {
let tokens = Tokenizer::new(&DIALECT, sql_select_items.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_comma_separated(Parser::parse_select_item)
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_interval<Sql: AsRef<str>>(sql_interval: Sql) -> Result<SqlExpr> {
let tokens = Tokenizer::new(&DIALECT, sql_interval.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_interval()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_order_by_expr<Sql: AsRef<str>>(sql_order_by_expr: Sql) -> Result<SqlOrderByExpr> {
let tokens = Tokenizer::new(&DIALECT, sql_order_by_expr.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_order_by_expr()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_order_by_exprs<Sql: AsRef<str>>(
sql_orderby_exprs: Sql,
) -> Result<Vec<SqlOrderByExpr>> {
let tokens = Tokenizer::new(&DIALECT, sql_orderby_exprs.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_comma_separated(Parser::parse_order_by_expr)
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_column_def<Sql: AsRef<str>>(sql_column_def: Sql) -> Result<SqlColumnDef> {
let tokens = Tokenizer::new(&DIALECT, sql_column_def.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_column_def()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_data_type<Sql: AsRef<str>>(sql_data_type: Sql) -> Result<SqlDataType> {
let tokens = Tokenizer::new(&DIALECT, sql_data_type.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_data_type()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_sql_assignment<Sql: AsRef<str>>(sql_assignment: Sql) -> Result<SqlAssignment> {
let tokens = Tokenizer::new(&DIALECT, sql_assignment.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_assignment()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}

pub fn parse_identifiers<Sql: AsRef<str>>(sql_identifiers: Sql) -> Result<Vec<SqlIdent>> {
let tokens = Tokenizer::new(&DIALECT, sql_identifiers.as_ref())
.tokenize()
.map_err(|e| Error::Parser(format!("{:#?}", e)))?;

Parser::new(tokens, &DIALECT)
.parse_identifiers()
.map_err(|e| Error::Parser(format!("{:#?}", e)))
}
parse_!(parse_query, parse_query, SqlQuery);
parse_!(parse_expr, parse_expr, SqlExpr);
parse_!(
parse_comma_separated_exprs,
parse_comma_separated,
parse_expr,
Vec<SqlExpr>
);
parse_!(parse_select_item, parse_select_item, SqlSelectItem);
parse_!(
parse_select_items,
parse_comma_separated,
parse_select_item,
Vec<SqlSelectItem>
);
parse_!(parse_interval, parse_interval, SqlExpr);
parse_!(parse_order_by_expr, parse_order_by_expr, SqlOrderByExpr);
parse_!(
parse_order_by_exprs,
parse_comma_separated,
parse_order_by_expr,
Vec<SqlOrderByExpr>
);
parse_!(parse_column_def, parse_column_def, SqlColumnDef);
parse_!(parse_data_type, parse_data_type, SqlDataType);
parse_!(parse_sql_assignment, parse_assignment, SqlAssignment);
parse_!(parse_identifiers, parse_identifiers, Vec<SqlIdent>);

0 comments on commit 77c4faf

Please sign in to comment.