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
1 change: 1 addition & 0 deletions crates/squawk_parser/src/generated/syntax_kind.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 107 additions & 17 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn paren_select(p: &mut Parser<'_>) -> Option<CompletedMarker> {
}
}
p.expect(R_PAREN);
Some(m.complete(p, PAREN_EXPR))
Some(m.complete(p, PAREN_SELECT))
}

const SELECT_FIRST: TokenSet = TokenSet::new(&[SELECT_KW, TABLE_KW, WITH_KW, VALUES_KW]);
Expand Down Expand Up @@ -889,6 +889,18 @@ fn opt_xml_passing_mech(p: &mut Parser<'_>) -> bool {
}
}

fn xmlexists_arg(p: &mut Parser<'_>) {
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(PASSING_KW);
opt_xml_passing_mech(p);
if expr(p).is_none() {
p.error("expected expression");
}
opt_xml_passing_mech(p);
}

// XMLEXISTS '(' c_expr xmlexists_argument ')'
// xmlexists_argument:
// | PASSING c_expr
Expand All @@ -901,15 +913,7 @@ fn opt_xml_passing_mech(p: &mut Parser<'_>) -> bool {
fn xmlexists_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLEXISTS_KW));
custom_fn(p, XMLEXISTS_KW, |p| {
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(PASSING_KW);
opt_xml_passing_mech(p);
if expr(p).is_none() {
p.error("expected expression");
}
opt_xml_passing_mech(p);
xmlexists_arg(p);
})
}

Expand Down Expand Up @@ -2765,6 +2769,22 @@ fn data_source(p: &mut Parser<'_>) {
json_table_fn(p);
opt_alias(p);
}
XMLTABLE_KW => {
p.bump(XMLTABLE_KW);
p.expect(L_PAREN);
if p.eat(XMLNAMESPACES_KW) {
p.expect(L_PAREN);
xml_namespace_list(p);
p.expect(R_PAREN);
}
if expr(p).is_none() {
p.error("expected expression");
}
xmlexists_arg(p);
p.expect(COLUMNS_KW);
xmltable_column_list(p);
p.expect(R_PAREN);
}
ROWS_KW if p.nth_at(1, FROM_KW) => {
p.bump(ROWS_KW);
p.expect(FROM_KW);
Expand All @@ -2788,7 +2808,79 @@ fn data_source(p: &mut Parser<'_>) {
opt_alias(p);
}
_ if p.at_ts(FROM_ITEM_KEYWORDS_FIRST) => from_item_name(p),
_ => {}

_ => {
p.error("expected table reference");
}
}
}

fn xmltable_column_list(p: &mut Parser<'_>) {
xmltable_column_el(p);
while !p.at(EOF) && p.eat(COMMA) {
xmltable_column_el(p);
}
}

fn xmltable_column_el(p: &mut Parser<'_>) {
name(p);
if p.eat(FOR_KW) {
p.expect(ORDINALITY_KW);
} else {
type_name(p);
opt_xmltable_column_option_list(p);
}
}

fn opt_xmltable_column_option_list(p: &mut Parser<'_>) {
if opt_xmltable_column_option_el(p) {
return;
}
while !p.at(EOF) && p.eat(COMMA) {
if !opt_xmltable_column_option_el(p) {
p.error("expected column option");
}
}
}

fn opt_xmltable_column_option_el(p: &mut Parser<'_>) -> bool {
match p.current() {
DEFAULT_KW | PATH_KW | IDENT => {
p.bump_any();
if expr(p).is_none() {
p.error("expected expression");
}
}
NOT_KW => {
p.bump(NOT_KW);
p.expect(NULL_KW);
}
NULL_KW => {
p.bump(NULL_KW);
}
_ => return false,
}
true
}

fn xml_namespace_list(p: &mut Parser<'_>) {
xml_namespace_element(p);
while !p.at(EOF) && p.eat(COMMA) {
xml_namespace_element(p);
}
}

fn xml_namespace_element(p: &mut Parser<'_>) {
if p.eat(DEFAULT_KW) {
if expr(p).is_none() {
p.error("expected expression");
}
} else {
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(AS_KW);
col_label(p);
}
}

Expand All @@ -2801,20 +2893,18 @@ fn paren_data_source(p: &mut Parser<'_>) -> CompletedMarker {
if p.at_ts(SELECT_FIRST) {
if select(p, None).is_some() {
p.expect(R_PAREN);
return m.complete(p, PAREN_EXPR);
return m.complete(p, PAREN_SELECT);
}
}

// Then try to parse as a FROM_ITEM (which includes table references and joins)
if opt_from_item(p) {
p.expect(R_PAREN);
return m.complete(p, PAREN_EXPR);
} else {
p.error("expected table name or SELECT");
}

// Fall back to general expression parsing
if expr(p).is_none() {
p.error("expected an expression");
}
p.expect(R_PAREN);
m.complete(p, PAREN_EXPR)
}
Expand Down Expand Up @@ -9774,7 +9864,7 @@ fn explain(p: &mut Parser<'_>) -> CompletedMarker {
| CREATE_TABLE_AS
| CREATE_MATERIALIZED_VIEW
// TODO: we need a validation to check inside this
| PAREN_EXPR => (),
| PAREN_SELECT => (),
kind => {
p.error(format!(
"expected SELECT, INSERT, UPDATE, DELETE, MERGE, or VALUES statement, got {:?}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SOURCE_FILE
PAREN_EXPR
L_PAREN "("
FROM_ITEM
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
WHITESPACE " "
SELECT
Expand Down
2 changes: 1 addition & 1 deletion crates/squawk_parser/tests/snapshots/tests__delete_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ SOURCE_FILE
COMMA ","
WHITESPACE "\n "
FROM_ITEM
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand Down
20 changes: 10 additions & 10 deletions crates/squawk_parser/tests/snapshots/tests__explain_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -572,15 +572,15 @@ SOURCE_FILE
WHITESPACE " "
ANALYZE_KW "analyze"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand All @@ -604,15 +604,15 @@ SOURCE_FILE
WHITESPACE " "
ANALYZE_KW "analyze"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
VALUES
VALUES_KW "values"
Expand Down
6 changes: 3 additions & 3 deletions crates/squawk_parser/tests/snapshots/tests__merge_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ SOURCE_FILE
USING_CLAUSE
USING_KW "using"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand Down Expand Up @@ -406,7 +406,7 @@ SOURCE_FILE
USING_CLAUSE
USING_KW "using"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand Down Expand Up @@ -509,7 +509,7 @@ SOURCE_FILE
USING_CLAUSE
USING_KW "using"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ SOURCE_FILE
USING_CLAUSE
USING_KW "USING"
WHITESPACE " "
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
SELECT
SELECT_CLAUSE
Expand Down
4 changes: 2 additions & 2 deletions crates/squawk_parser/tests/snapshots/tests__misc_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5293,7 +5293,7 @@ SOURCE_FILE
FROM_KW "FROM"
WHITESPACE " "
FROM_ITEM
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
WHITESPACE "\n "
SELECT
Expand Down Expand Up @@ -5363,7 +5363,7 @@ SOURCE_FILE
FROM_KW "FROM"
WHITESPACE " "
FROM_ITEM
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
WHITESPACE "\n "
SELECT
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
source: crates/squawk_parser/tests/tests.rs
input_file: crates/squawk_parser/tests/data/ok/precedence.sql
snapshot_kind: text
---
SOURCE_FILE
COMMENT "-- see: https://github.com/postgres/postgres/blob/028b4b21df26fee67b3ce75c6f14fcfd3c7cf2ee/src/backend/parser/gram.y#L12699"
Expand Down Expand Up @@ -108,7 +107,7 @@ SOURCE_FILE
WHITESPACE "\n"
COMMENT "-- equal to:"
WHITESPACE "\n"
PAREN_EXPR
PAREN_SELECT
L_PAREN "("
COMPOUND_SELECT
SELECT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ tests/snapshots/tests__regression_update.snap:29
tests/snapshots/tests__regression_vacuum.snap:15
tests/snapshots/tests__regression_window.snap:72
tests/snapshots/tests__regression_with.snap:9
tests/snapshots/tests__regression_xml.snap:623
tests/snapshots/tests__regression_xml.snap:393
Loading
Loading