Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn opt_paren_select(p: &mut Parser<'_>, m: Option<Marker>) -> Option<CompletedMa
let cm = m.complete(p, PAREN_SELECT);
Some(compound_select(p, cm))
} else {
select_trailing_clauses(p);
opt_select_trailing_clauses(p);
Some(m.complete(p, PAREN_SELECT))
}
}
Expand Down Expand Up @@ -2701,7 +2701,7 @@ fn compound_select(p: &mut Parser<'_>, cm: CompletedMarker) -> CompletedMarker {
p.error("expected start of a select statement")
}
}
select_trailing_clauses(p);
opt_select_trailing_clauses(p);
m.complete(p, COMPOUND_SELECT)
}

Expand Down Expand Up @@ -2757,12 +2757,19 @@ fn select(p: &mut Parser, m: Option<Marker>, r: &SelectRestrictions) -> Option<C
return Some(compound_select(p, cm));
}
if r.trailing_clauses {
select_trailing_clauses(p);
opt_select_trailing_clauses(p);
}
Some(m.complete(p, out_kind))
}

fn select_trailing_clauses(p: &mut Parser<'_>) {
const SELECT_TRAILING_CLAUSES_FIRST: TokenSet =
TokenSet::new(&[ORDER_KW, FOR_KW, LIMIT_KW, OFFSET_KW, FETCH_KW]);

fn opt_select_trailing_clauses(p: &mut Parser<'_>) -> bool {
if !p.at_ts(SELECT_TRAILING_CLAUSES_FIRST) {
return false;
}

opt_order_by_clause(p);
let mut has_locking_clause = false;
while p.at(FOR_KW) {
Expand All @@ -2780,6 +2787,7 @@ fn select_trailing_clauses(p: &mut Parser<'_>) {
opt_locking_clause(p);
}
}
true
}

// INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] new_table
Expand Down Expand Up @@ -3337,6 +3345,16 @@ fn paren_data_source(p: &mut Parser<'_>) -> Option<CompletedMarker> {
p.bump(L_PAREN);
// Then try to parse as a FROM_ITEM (which includes table references and joins)
if opt_from_item(p) {
if p.at_ts(COMPOUND_SELECT_FIRST) {
let cm = m.complete(p, PAREN_SELECT);
let cm = compound_select(p, cm);
p.expect(R_PAREN);
return Some(cm.precede(p).complete(p, PAREN_SELECT));
}
if opt_select_trailing_clauses(p) {
p.expect(R_PAREN);
return Some(m.complete(p, PAREN_SELECT));
}
p.expect(R_PAREN);
return Some(m.complete(p, PAREN_EXPR));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ table t union table t;

values (1), (2) union values (3), (4);

(((((select 1))) union select 1));

select * from (((((select 1))) union select 1));

select * from (((select 1) union select 2) limit 1) as t;

Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,151 @@ SOURCE_FILE
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n\n"
PAREN_SELECT
L_PAREN "("
PAREN_SELECT
L_PAREN "("
COMPOUND_SELECT
PAREN_SELECT
L_PAREN "("
PAREN_SELECT
L_PAREN "("
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "1"
R_PAREN ")"
R_PAREN ")"
R_PAREN ")"
WHITESPACE " "
UNION_KW "union"
WHITESPACE " "
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "1"
R_PAREN ")"
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n\n"
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
STAR "*"
WHITESPACE " "
FROM_CLAUSE
FROM_KW "from"
WHITESPACE " "
FROM_ITEM
PAREN_EXPR
L_PAREN "("
FROM_ITEM
PAREN_SELECT
COMPOUND_SELECT
PAREN_SELECT
L_PAREN "("
FROM_ITEM
PAREN_EXPR
L_PAREN "("
FROM_ITEM
PAREN_EXPR
L_PAREN "("
FROM_ITEM
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "1"
R_PAREN ")"
R_PAREN ")"
R_PAREN ")"
WHITESPACE " "
UNION_KW "union"
WHITESPACE " "
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "1"
R_PAREN ")"
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n\n"
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
STAR "*"
WHITESPACE " "
FROM_CLAUSE
FROM_KW "from"
WHITESPACE " "
FROM_ITEM
PAREN_SELECT
L_PAREN "("
FROM_ITEM
PAREN_EXPR
L_PAREN "("
FROM_ITEM
COMPOUND_SELECT
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "1"
R_PAREN ")"
WHITESPACE " "
UNION_KW "union"
WHITESPACE " "
SELECT
SELECT_CLAUSE
SELECT_KW "select"
WHITESPACE " "
TARGET_LIST
TARGET
LITERAL
INT_NUMBER "2"
R_PAREN ")"
WHITESPACE " "
LIMIT_CLAUSE
LIMIT_KW "limit"
WHITESPACE " "
LITERAL
INT_NUMBER "1"
R_PAREN ")"
WHITESPACE " "
ALIAS
AS_KW "as"
WHITESPACE " "
NAME
IDENT "t"
SEMICOLON ";"
WHITESPACE "\n\n"
Loading