Skip to content

Commit f140148

Browse files
committed
sql-parser: select result-columns parser
1 parent bc7137f commit f140148

17 files changed

+413
-139
lines changed

src/ast/expression.rs

+7
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,15 @@ pub enum LiteralValue {
8989
pub enum Identifier {
9090
/// A single identifier
9191
Single(String),
92+
9293
/// A compound identifier
9394
Compound(Vec<String>),
95+
96+
/// A wildcard
97+
Wildcard,
98+
99+
/// A table or column name with wildcard
100+
NameWithWildcard(String),
94101
}
95102

96103
/// A binary operation

src/ast/select.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ pub enum SelectStatementType {
1212
/// An AST for [SELECT](https://www.sqlite.org/lang_select.html) SQL statement.
1313
#[derive(Debug, PartialEq, Default, Clone)]
1414
pub struct SelectStatement {
15-
/// Whether the SELECT statement is a VALUES statement
16-
pub values: bool,
17-
1815
/// Whether the SELECT statement is distinct
19-
pub distinct: bool,
20-
21-
/// Whether the SELECT statement is all
22-
pub all: bool,
16+
pub distinct_type: DistinctType,
2317

2418
/// The list of columns to select
2519
pub columns: Vec<SelectItem>,
@@ -46,6 +40,15 @@ pub struct SelectStatement {
4640
pub limit: Option<LimitClause>,
4741
}
4842

43+
/// An enum representing the possible distinct types
44+
#[derive(Debug, PartialEq, Clone, Default)]
45+
pub enum DistinctType {
46+
Distinct,
47+
All,
48+
#[default]
49+
None,
50+
}
51+
4952
/// An enum representing the possible items in a SELECT statement
5053
#[derive(Debug, PartialEq, Clone)]
5154
pub enum SelectItem {
@@ -54,12 +57,6 @@ pub enum SelectItem {
5457

5558
/// An expression with an alias
5659
ExpressionWithAlias(Expression, String),
57-
58-
/// A wildcard (*), which matches all columns
59-
Wildcard,
60-
61-
/// A table name with a wildcard
62-
TableNameWithWildcard(String),
6360
}
6461

6562
/// An AST for representing a FROM clause

src/parser/expression/between_expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mod between_expression_tests {
7777

7878
#[test]
7979
fn test_expression_between_basic() {
80-
run_sunny_day_test(
80+
run_sunny_day_expression_test(
8181
"SELECT 1 BETWEEN 2 AND 3;",
8282
&between_expression(
8383
numeric_literal_expression("1"),
@@ -90,7 +90,7 @@ mod between_expression_tests {
9090

9191
#[test]
9292
fn test_expression_between_with_expression() {
93-
run_sunny_day_test(
93+
run_sunny_day_expression_test(
9494
"SELECT 1 + 2 BETWEEN 3 AND 4;",
9595
&between_expression(
9696
binary_op_expression(
@@ -107,7 +107,7 @@ mod between_expression_tests {
107107

108108
#[test]
109109
fn test_expression_not_between_with_expression() {
110-
run_sunny_day_test(
110+
run_sunny_day_expression_test(
111111
"SELECT 1 + 2 NOT BETWEEN 3 AND 4;",
112112
&between_expression(
113113
binary_op_expression(

src/parser/expression/case_expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mod case_expression_tests {
7777
}];
7878
let else_expression = Some(Box::new(numeric_literal_expression("3")));
7979

80-
run_sunny_day_test(
80+
run_sunny_day_expression_test(
8181
"SELECT CASE WHEN 1 THEN 2 ELSE 3 END;",
8282
&case_expression(expression, when_expressions, else_expression),
8383
);
@@ -98,7 +98,7 @@ mod case_expression_tests {
9898
];
9999
let else_expression = Some(Box::new(numeric_literal_expression("5")));
100100

101-
run_sunny_day_test(
101+
run_sunny_day_expression_test(
102102
"SELECT CASE WHEN 1 THEN 2 WHEN 3 THEN 4 ELSE 5 END;",
103103
&case_expression(expression, when_expressions, else_expression),
104104
);
@@ -117,7 +117,7 @@ mod case_expression_tests {
117117
}];
118118
let else_expression = Some(Box::new(numeric_literal_expression("2")));
119119

120-
run_sunny_day_test(
120+
run_sunny_day_expression_test(
121121
"SELECT CASE 1 == 1 WHEN TRUE THEN 1 ELSE 2 END;",
122122
&case_expression(expression, when_expressions, else_expression),
123123
);

src/parser/expression/cast_expr.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod cast_expression_tests {
3131

3232
#[test]
3333
fn test_expression_cast_basic() {
34-
run_sunny_day_test(
34+
run_sunny_day_expression_test(
3535
"SELECT CAST(1 AS INTEGER);",
3636
&cast_expression(
3737
numeric_literal_expression("1"),
@@ -42,7 +42,7 @@ mod cast_expression_tests {
4242

4343
#[test]
4444
fn test_expression_cast_expression() {
45-
run_sunny_day_test(
45+
run_sunny_day_expression_test(
4646
"SELECT CAST(1 + 2 AS INTEGER);",
4747
&cast_expression(
4848
binary_op_expression(
@@ -57,7 +57,7 @@ mod cast_expression_tests {
5757

5858
#[test]
5959
fn test_expression_cast_with_null() {
60-
run_sunny_day_test(
60+
run_sunny_day_expression_test(
6161
"SELECT CAST(NULL AS INTEGER);",
6262
&cast_expression(
6363
null_literal_expression(),
@@ -68,7 +68,7 @@ mod cast_expression_tests {
6868

6969
#[test]
7070
fn test_expression_cast_with_complex_type() {
71-
run_sunny_day_test(
71+
run_sunny_day_expression_test(
7272
"SELECT CAST(1 AS VARCHAR(10));",
7373
&cast_expression(
7474
numeric_literal_expression("1"),
@@ -79,7 +79,7 @@ mod cast_expression_tests {
7979

8080
#[test]
8181
fn test_expression_cast_with_complex_type2() {
82-
run_sunny_day_test(
82+
run_sunny_day_expression_test(
8383
"SELECT CAST(1 AS VARCHAR(1, 10));",
8484
&cast_expression(
8585
numeric_literal_expression("1"),

src/parser/expression/collate_expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ mod collate_expression_tests {
3737

3838
#[test]
3939
fn test_expression_collate_basic() {
40-
run_sunny_day_test(
40+
run_sunny_day_expression_test(
4141
"SELECT 1 COLLATE 'utf8';",
4242
&collate_expression(numeric_literal_expression("1"), "'utf8'".to_string()),
4343
);
4444
}
4545

4646
#[test]
4747
fn test_expression_collate_with_expression() {
48-
run_sunny_day_test(
48+
run_sunny_day_expression_test(
4949
"SELECT 1 + 2 COLLATE 'utf8';",
5050
&collate_expression(
5151
binary_op_expression(

src/parser/expression/exists_expr.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,14 @@ mod exists_expression_tests {
3939

4040
fn select_statement(columns: Vec<SelectItem>) -> SelectStatementType {
4141
SelectStatementType::Select(SelectStatement {
42-
distinct: false,
43-
all: false,
4442
columns,
4543
..Default::default()
4644
})
4745
}
4846

4947
#[test]
5048
fn test_expression_exists() {
51-
run_sunny_day_test(
49+
run_sunny_day_expression_test(
5250
"SELECT EXISTS (SELECT 1);",
5351
&exist_expression(
5452
false,
@@ -61,7 +59,7 @@ mod exists_expression_tests {
6159

6260
#[test]
6361
fn test_expression_not_exists() {
64-
run_sunny_day_test(
62+
run_sunny_day_expression_test(
6563
"SELECT NOT EXISTS (SELECT 1);",
6664
&exist_expression(
6765
true,
@@ -74,7 +72,7 @@ mod exists_expression_tests {
7472

7573
#[test]
7674
fn test_expression_not_exists_without_exists_keyword() {
77-
run_sunny_day_test(
75+
run_sunny_day_expression_test(
7876
"SELECT NOT (SELECT 21);",
7977
&exist_expression(
8078
true,

src/parser/expression/function_expr.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ mod function_expression_tests {
381381

382382
#[test]
383383
fn test_expression_function_basic_empty_args() {
384-
run_sunny_day_test(
384+
run_sunny_day_expression_test(
385385
"SELECT abc();",
386386
&function_expression("abc", FunctionArg::default(), None, None),
387387
);
@@ -393,7 +393,7 @@ mod function_expression_tests {
393393
distinct: false,
394394
arguments: vec![FunctionArgType::Wildcard],
395395
};
396-
run_sunny_day_test(
396+
run_sunny_day_expression_test(
397397
"SELECT abc(*);",
398398
&function_expression("abc", expected_arg, None, None),
399399
);
@@ -405,7 +405,7 @@ mod function_expression_tests {
405405
distinct: false,
406406
arguments: vec![FunctionArgType::Expression(numeric_literal_expression("1"))],
407407
};
408-
run_sunny_day_test(
408+
run_sunny_day_expression_test(
409409
"SELECT abc(1);",
410410
&function_expression("abc", expected_arg, None, None),
411411
);
@@ -417,7 +417,7 @@ mod function_expression_tests {
417417
distinct: true,
418418
arguments: vec![FunctionArgType::Expression(numeric_literal_expression("1"))],
419419
};
420-
run_sunny_day_test(
420+
run_sunny_day_expression_test(
421421
"SELECT abc(distinct 1);",
422422
&function_expression("abc", expected_arg, None, None),
423423
);
@@ -432,7 +432,7 @@ mod function_expression_tests {
432432
FunctionArgType::Expression(numeric_literal_expression("2")),
433433
],
434434
};
435-
run_sunny_day_test(
435+
run_sunny_day_expression_test(
436436
"SELECT abc(1, 2);",
437437
&function_expression("abc", expected_arg, None, None),
438438
);
@@ -459,7 +459,7 @@ mod function_expression_tests {
459459
)),
460460
],
461461
};
462-
run_sunny_day_test(
462+
run_sunny_day_expression_test(
463463
"SELECT abc(1 + 2, 4 + 5 / 6);",
464464
&function_expression("abc", expected_arg, None, None),
465465
);
@@ -478,7 +478,7 @@ mod function_expression_tests {
478478
}],
479479
)],
480480
};
481-
run_sunny_day_test(
481+
run_sunny_day_expression_test(
482482
"SELECT abc(1 order by 2);",
483483
&function_expression("abc", expected_arg, None, None),
484484
);
@@ -514,7 +514,7 @@ mod function_expression_tests {
514514
],
515515
)],
516516
};
517-
run_sunny_day_test(
517+
run_sunny_day_expression_test(
518518
"SELECT abc(1 order by 2 asc, 3 desc, 4 nulls first, 5 desc nulls last);",
519519
&function_expression("abc", expected_arg, None, None),
520520
);
@@ -533,7 +533,7 @@ mod function_expression_tests {
533533
numeric_literal_expression("3"),
534534
);
535535

536-
run_sunny_day_test(
536+
run_sunny_day_expression_test(
537537
"SELECT abc(1) filter (where 2 > 3);",
538538
&function_expression("abc", expected_arg, Some(Box::new(filter_clause)), None),
539539
);
@@ -553,7 +553,7 @@ mod function_expression_tests {
553553
frame_spec: None,
554554
};
555555

556-
run_sunny_day_test(
556+
run_sunny_day_expression_test(
557557
"SELECT abc(1) over a;",
558558
&function_expression("abc", expected_arg, None, Some(over_clause)),
559559
);
@@ -573,7 +573,7 @@ mod function_expression_tests {
573573
frame_spec: None,
574574
};
575575

576-
run_sunny_day_test(
576+
run_sunny_day_expression_test(
577577
"SELECT abc(1) over (partition by 1);",
578578
&function_expression("abc", expected_arg, None, Some(over_clause)),
579579
);
@@ -597,7 +597,7 @@ mod function_expression_tests {
597597
frame_spec: None,
598598
};
599599

600-
run_sunny_day_test(
600+
run_sunny_day_expression_test(
601601
"SELECT abc(1) over (order by 1 asc nulls last);",
602602
&function_expression("abc", expected_arg, None, Some(over_clause)),
603603
);
@@ -626,7 +626,7 @@ mod function_expression_tests {
626626
}),
627627
};
628628

629-
run_sunny_day_test(
629+
run_sunny_day_expression_test(
630630
"SELECT abc(1) over (a groups between 1 preceding and current row exclude current row);",
631631
&function_expression("abc", expected_arg, None, Some(over_clause)),
632632
);

src/parser/expression/identifier.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,47 @@ impl<'a> IdentifierParser for Parser<'a> {
1010
fn parse_identifier(&mut self) -> Result<Identifier, ParsingError> {
1111
let mut components = Vec::new();
1212

13-
while let Ok(identifier) = self.peek_as_id() {
13+
let mut expected_next_identifier = false;
14+
while let Ok(identifier) = self.peek_as_id_or_star() {
1415
components.push(identifier.to_string());
1516
// Consume the identifier token
16-
self.consume_as_id()?;
17+
self.consume_token()?;
18+
expected_next_identifier = false;
1719

18-
if self.consume_as(TokenType::Dot).is_err() {
20+
if self.consume_as(TokenType::Dot).is_ok() {
21+
expected_next_identifier = true;
22+
} else {
1923
break;
2024
}
2125
}
2226

27+
dbg!("Expected next identifier: {}", expected_next_identifier);
28+
if expected_next_identifier {
29+
return Err(ParsingError::UnexpectedToken(
30+
"Expected identifier".to_string(),
31+
));
32+
}
33+
34+
dbg!("Parsed components: {:?}", &components);
2335
match components.len() {
2436
0 => Err(ParsingError::UnexpectedToken(
2537
"Expected identifier".to_string(),
2638
)),
27-
1 => Ok(Identifier::Single(components[0].to_string())),
39+
1 => {
40+
if components[0] == "*" {
41+
Ok(Identifier::Wildcard)
42+
} else {
43+
Ok(Identifier::Single(components[0].to_string()))
44+
}
45+
}
46+
2 => {
47+
if components[1] == "*" {
48+
dbg!("Parsed table name with wildcard {}", &components[0]);
49+
Ok(Identifier::NameWithWildcard(components[0].to_string()))
50+
} else {
51+
Ok(Identifier::Compound(components))
52+
}
53+
}
2854
_ => Ok(Identifier::Compound(components)),
2955
}
3056
}
@@ -36,12 +62,12 @@ mod identifier_expression_tests {
3662

3763
#[test]
3864
fn test_expression_identifier_valid() {
39-
run_sunny_day_test("SELECT id;", &identifier_expression(&["id"]));
40-
run_sunny_day_test(
65+
run_sunny_day_expression_test("SELECT id;", &identifier_expression(&["id"]));
66+
run_sunny_day_expression_test(
4167
"SELECT table1.column1;",
4268
&identifier_expression(&["table1", "column1"]),
4369
);
44-
run_sunny_day_test(
70+
run_sunny_day_expression_test(
4571
"SELECT schema1.table1.column1;",
4672
&identifier_expression(&["schema1", "table1", "column1"]),
4773
);

0 commit comments

Comments
 (0)