risingwave_sqlparser/
test_utils.rs1use std::fmt::Debug;
19
20use crate::ast::*;
21use crate::parser::{Parser, ParserError};
22use crate::tokenizer::Tokenizer;
23
24pub fn run_parser_method<F, T: Debug + PartialEq>(sql: &str, f: F) -> T
25where
26 F: Fn(&mut Parser<'_>) -> T,
27{
28 let mut tokenizer = Tokenizer::new(sql);
29 let tokens = tokenizer.tokenize_with_location().unwrap();
30 f(&mut Parser(&tokens))
31}
32
33pub fn parse_sql_statements(sql: &str) -> Result<Vec<Statement>, ParserError> {
34 Parser::parse_sql(sql)
35 }
38
39#[track_caller]
46pub fn one_statement_parses_to(sql: &str, canonical: &str) -> Statement {
47 let mut statements = parse_sql_statements(sql).unwrap();
48 assert_eq!(statements.len(), 1);
49
50 if !canonical.is_empty() && sql != canonical {
51 assert_eq!(parse_sql_statements(canonical).unwrap(), statements);
52 }
53
54 let only_statement = statements.pop().unwrap();
55 if !canonical.is_empty() {
56 assert_eq!(canonical, only_statement.to_string())
57 }
58 only_statement
59}
60
61#[track_caller]
64pub fn verified_stmt(query: &str) -> Statement {
65 one_statement_parses_to(query, query)
66}
67
68#[track_caller]
71pub fn verified_query(sql: &str) -> Query {
72 match verified_stmt(sql) {
73 Statement::Query(query) => *query,
74 _ => panic!("Expected Query"),
75 }
76}
77
78#[track_caller]
79pub fn query(sql: &str, canonical: &str) -> Query {
80 match one_statement_parses_to(sql, canonical) {
81 Statement::Query(query) => *query,
82 _ => panic!("Expected Query"),
83 }
84}
85
86#[track_caller]
89pub fn verified_only_select(query: &str) -> Select {
90 match verified_query(query).body {
91 SetExpr::Select(s) => *s,
92 _ => panic!("Expected SetExpr::Select"),
93 }
94}
95
96pub fn verified_expr(sql: &str) -> Expr {
99 let ast = run_parser_method(sql, |parser| parser.parse_expr()).unwrap();
100 assert_eq!(sql, &ast.to_string(), "round-tripping without changes");
101 ast
102}
103
104pub fn only<T>(v: impl IntoIterator<Item = T>) -> T {
105 let mut iter = v.into_iter();
106 match (iter.next(), iter.next()) {
107 (Some(item), None) => item,
108 _ => {
109 panic!("only called on collection without exactly one item")
110 }
111 }
112}
113
114pub fn expr_from_projection(item: &SelectItem) -> &Expr {
115 match item {
116 SelectItem::UnnamedExpr(expr) => expr,
117 _ => panic!("Expected UnnamedExpr"),
118 }
119}
120
121pub fn number(n: &'static str) -> Value {
122 Value::Number(n.parse().unwrap())
123}
124
125pub fn table_alias(name: impl Into<String>) -> Option<TableAlias> {
126 Some(TableAlias {
127 name: Ident::new_unchecked(name),
128 columns: vec![],
129 })
130}
131
132pub fn table(name: impl Into<String>) -> TableFactor {
133 TableFactor::Table {
134 name: ObjectName(vec![Ident::new_unchecked(name.into())]),
135 as_of: None,
136 alias: None,
137 }
138}
139
140pub fn join(relation: TableFactor) -> Join {
141 Join {
142 relation,
143 join_operator: JoinOperator::Inner(JoinConstraint::Natural),
144 }
145}