diff --git a/crates/squawk_parser/src/generated/syntax_kind.rs b/crates/squawk_parser/src/generated/syntax_kind.rs index df0c4b7d..9399826a 100644 --- a/crates/squawk_parser/src/generated/syntax_kind.rs +++ b/crates/squawk_parser/src/generated/syntax_kind.rs @@ -942,7 +942,6 @@ pub enum SyntaxKind { JOIN_USING_CLAUSE, JSON_ARRAY_AGG_FN, JSON_ARRAY_FN, - JSON_BEHAVIOR_CLAUSE, JSON_BEHAVIOR_DEFAULT, JSON_BEHAVIOR_EMPTY_ARRAY, JSON_BEHAVIOR_EMPTY_OBJECT, diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 6a52d609..3423b0e8 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -404,8 +404,11 @@ fn substring_fn(p: &mut Parser<'_>) -> CompletedMarker { } fn opt_json_encoding_clause(p: &mut Parser<'_>) { - if p.eat(ENCODING_KW) { + if p.at(ENCODING_KW) { + let m = p.start(); + p.bump(ENCODING_KW); name_ref(p); + m.complete(p, JSON_ENCODING_CLAUSE); } } @@ -428,6 +431,17 @@ fn opt_json_format_clause(p: &mut Parser<'_>) -> Option { } } +// json_value_expr: +// a_expr json_format_clause_opt +fn json_value_expr(p: &mut Parser<'_>) -> CompletedMarker { + let m = p.start(); + if expr(p).is_none() { + p.error("expected expression"); + } + opt_json_format_clause(p); + m.complete(p, JSON_VALUE_EXPR) +} + // json_returning_clause_opt: // RETURNING Typename json_format_clause_opt // | /* EMPTY */ @@ -707,19 +721,20 @@ fn opt_json_path_clause(p: &mut Parser<'_>) { fn opt_json_array_fn_arg_list(p: &mut Parser<'_>) { // 1, 2, 3, 4 while !p.at(EOF) && !p.at(R_PAREN) && !p.at(RETURNING_KW) { + let m = p.start(); if p.at_ts(SELECT_FIRST) { - if select(p, None, &SelectRestrictions::default(), false).is_none() - || p.at(EOF) - || p.at(R_PAREN) - { + if select(p, None, &SelectRestrictions::default(), false).is_none() { + m.abandon(p); break; } opt_json_format_clause(p); + m.complete(p, JSON_SELECT_FORMAT); } else { if expr(p).is_none() { p.error("expected expression"); } opt_json_format_clause(p); + m.complete(p, JSON_EXPR_FORMAT); } if !p.eat(COMMA) { break; @@ -842,10 +857,7 @@ fn json_arrayagg_fn(p: &mut Parser<'_>) -> CompletedMarker { let m = p.start(); p.expect(JSON_ARRAYAGG_KW); p.expect(L_PAREN); - if expr(p).is_none() { - p.error("expected expression"); - } - opt_json_format_clause(p); + json_value_expr(p); opt_order_by_clause(p); opt_json_null_clause(p); opt_json_returning_clause(p); @@ -2345,10 +2357,7 @@ fn json_key_value(p: &mut Parser) -> Option { m.abandon(p); return None; } - if expr(p).is_none() { - p.error("expected expression"); - } - opt_json_format_clause(p); + json_value_expr(p); Some(m.complete(p, JSON_KEY_VALUE)) } @@ -3300,8 +3309,9 @@ fn data_source(p: &mut Parser<'_>) { } } -fn xml_table_fn(p: &mut Parser<'_>) { +fn xml_table_fn(p: &mut Parser<'_>) -> CompletedMarker { assert!(p.at(XMLTABLE_KW)); + let m = p.start(); p.bump(XMLTABLE_KW); p.expect(L_PAREN); if p.eat(XMLNAMESPACES_KW) { @@ -3311,6 +3321,7 @@ fn xml_table_fn(p: &mut Parser<'_>) { xml_row_passing_clause(p); xmltable_column_list(p); p.expect(R_PAREN); + m.complete(p, XML_TABLE) } fn xml_row_passing_clause(p: &mut Parser<'_>) { diff --git a/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap index b194ca34..3a273b88 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap @@ -1441,8 +1441,9 @@ SOURCE_FILE WHITESPACE " " VALUE_KW "value" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" COMMA "," WHITESPACE " " JSON_KEY_VALUE @@ -1451,8 +1452,9 @@ SOURCE_FILE WHITESPACE " " VALUE_KW "value" WHITESPACE " " - LITERAL - STRING "'b'" + JSON_VALUE_EXPR + LITERAL + STRING "'b'" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1471,8 +1473,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" COMMA "," WHITESPACE " " JSON_KEY_VALUE @@ -1480,8 +1483,9 @@ SOURCE_FILE STRING "'a'" COLON ":" WHITESPACE " " - LITERAL - STRING "'b'" + JSON_VALUE_EXPR + LITERAL + STRING "'b'" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -1500,18 +1504,20 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" - WHITESPACE " " - JSON_KW "json" - WHITESPACE " " - ENCODING_KW "encoding" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " - NAME_REF - IDENT "utf8" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" + WHITESPACE " " + JSON_ENCODING_CLAUSE + ENCODING_KW "encoding" + WHITESPACE " " + NAME_REF + IDENT "utf8" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1530,13 +1536,14 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -1555,8 +1562,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1582,8 +1590,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE ABSENT_KW "absent" @@ -1609,8 +1618,9 @@ SOURCE_FILE STRING "'a'" COLON ":" WHITESPACE " " - LITERAL - INT_NUMBER "1" + JSON_VALUE_EXPR + LITERAL + INT_NUMBER "1" COMMA "," WHITESPACE " " JSON_KEY_VALUE @@ -1618,13 +1628,14 @@ SOURCE_FILE STRING "'b'" COLON ":" WHITESPACE " " - LITERAL - STRING "'1'" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_VALUE_EXPR + LITERAL + STRING "'1'" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" COMMA "," WHITESPACE " " JSON_KEY_VALUE @@ -1633,8 +1644,9 @@ SOURCE_FILE WHITESPACE " " VALUE_KW "value" WHITESPACE " " - LITERAL - STRING "'c'" + JSON_VALUE_EXPR + LITERAL + STRING "'c'" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -1653,8 +1665,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1687,8 +1700,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1719,8 +1733,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1753,8 +1768,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1785,8 +1801,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_RETURNING_CLAUSE RETURNING_KW "returning" @@ -1814,8 +1831,9 @@ SOURCE_FILE STRING "'foo'" COLON ":" WHITESPACE " " - LITERAL - STRING "'bar'" + JSON_VALUE_EXPR + LITERAL + STRING "'bar'" WHITESPACE " " JSON_RETURNING_CLAUSE RETURNING_KW "returning" @@ -1847,8 +1865,9 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" + JSON_EXPR_FORMAT + NAME_REF + IDENT "a" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1862,20 +1881,24 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - LITERAL - INT_NUMBER "1" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "1" COMMA "," WHITESPACE " " - LITERAL - INT_NUMBER "2" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "2" COMMA "," WHITESPACE " " - LITERAL - INT_NUMBER "3" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "3" COMMA "," WHITESPACE " " - LITERAL - INT_NUMBER "4" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "4" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1889,14 +1912,15 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - PAREN_EXPR - L_PAREN "(" + JSON_EXPR_FORMAT PAREN_EXPR L_PAREN "(" - LITERAL - INT_NUMBER "1" + PAREN_EXPR + L_PAREN "(" + LITERAL + INT_NUMBER "1" + R_PAREN ")" R_PAREN ")" - R_PAREN ")" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1910,18 +1934,20 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" - WHITESPACE " " - JSON_KW "json" - WHITESPACE " " - ENCODING_KW "encoding" - WHITESPACE " " + JSON_EXPR_FORMAT NAME_REF - IDENT "utf8" + IDENT "a" + WHITESPACE " " + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" + WHITESPACE " " + JSON_ENCODING_CLAUSE + ENCODING_KW "encoding" + WHITESPACE " " + NAME_REF + IDENT "utf8" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1935,13 +1961,14 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_EXPR_FORMAT + NAME_REF + IDENT "a" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -1955,13 +1982,14 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_EXPR_FORMAT + NAME_REF + IDENT "a" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" WHITESPACE " " JSON_NULL_CLAUSE NULL_KW "null" @@ -1982,8 +2010,9 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - LITERAL - INT_NUMBER "1" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "1" WHITESPACE " " JSON_RETURNING_CLAUSE RETURNING_KW "returning" @@ -2011,8 +2040,9 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" + JSON_EXPR_FORMAT + NAME_REF + IDENT "a" WHITESPACE " " JSON_NULL_CLAUSE ABSENT_KW "absent" @@ -2033,8 +2063,9 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - NAME_REF - IDENT "a" + JSON_EXPR_FORMAT + NAME_REF + IDENT "a" WHITESPACE " " JSON_NULL_CLAUSE ABSENT_KW "absent" @@ -2069,23 +2100,26 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - LITERAL - INT_NUMBER "1" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "1" COMMA "," WHITESPACE " " - LITERAL - TRUE_KW "true" + JSON_EXPR_FORMAT + LITERAL + TRUE_KW "true" COMMA "," WHITESPACE " " - CAST_EXPR - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - JSON_KW "json" - WHITESPACE " " - LITERAL - STRING "'{\"a\":null}'" + JSON_EXPR_FORMAT + CAST_EXPR + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + JSON_KW "json" + WHITESPACE " " + LITERAL + STRING "'{\"a\":null}'" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -2099,25 +2133,29 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - LITERAL - INT_NUMBER "1" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "1" COMMA "," WHITESPACE " " - NAME_REF - IDENT "b" + JSON_EXPR_FORMAT + NAME_REF + IDENT "b" COMMA "," WHITESPACE " " - LITERAL - STRING "'3'" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_EXPR_FORMAT + LITERAL + STRING "'3'" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" COMMA "," WHITESPACE " " - LITERAL - INT_NUMBER "4" + JSON_EXPR_FORMAT + LITERAL + INT_NUMBER "4" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -2133,16 +2171,17 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - FROM_CLAUSE - FROM_KW "from" + JSON_SELECT_FORMAT + SELECT + SELECT_CLAUSE + SELECT_KW "select" WHITESPACE " " - FROM_ITEM - NAME_REF - IDENT "t" + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "t" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -2158,14 +2197,15 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + JSON_SELECT_FORMAT + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -2179,19 +2219,20 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_SELECT_FORMAT + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -2205,19 +2246,20 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - STRING "'true'" - WHITESPACE " " - JSON_FORMAT_CLAUSE - FORMAT_KW "format" + JSON_SELECT_FORMAT + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + STRING "'true'" WHITESPACE " " - JSON_KW "json" + JSON_FORMAT_CLAUSE + FORMAT_KW "format" + WHITESPACE " " + JSON_KW "json" WHITESPACE " " JSON_RETURNING_CLAUSE RETURNING_KW "returning" @@ -2245,14 +2287,15 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - STRING "'true'" + JSON_SELECT_FORMAT + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + STRING "'true'" WHITESPACE " " JSON_RETURNING_CLAUSE RETURNING_KW "returning" @@ -2280,20 +2323,21 @@ SOURCE_FILE JSON_ARRAY_FN JSON_ARRAY_KW "json_array" L_PAREN "(" - PAREN_EXPR - L_PAREN "(" + JSON_EXPR_FORMAT PAREN_EXPR L_PAREN "(" - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + PAREN_EXPR + L_PAREN "(" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" + R_PAREN ")" R_PAREN ")" - R_PAREN ")" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap index 6c5976f5..d87cd3ad 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap @@ -17,183 +17,184 @@ SOURCE_FILE FROM_KW "from" WHITESPACE " " FROM_ITEM - XMLTABLE_KW "xmltable" - L_PAREN "(" - WHITESPACE "\n " - XMLNAMESPACES_KW "xmlnamespaces" - XML_NAMESPACE_LIST + XML_TABLE + XMLTABLE_KW "xmltable" L_PAREN "(" - XML_NAMESPACE - LITERAL - STRING "'http://example.com/books'" - WHITESPACE " " - AS_KW "as" - WHITESPACE " " - NAME - IDENT "bk" - R_PAREN ")" - COMMA "," - WHITESPACE "\n " - XML_ROW_PASSING_CLAUSE - LITERAL - STRING "'/bk:library/bk:book'" WHITESPACE "\n " - PASSING_KW "passing" - WHITESPACE " " - CALL_EXPR - XML_PARSE_FN - XMLPARSE_KW "xmlparse" - L_PAREN "(" - DOCUMENT_KW "document" - WHITESPACE " " + XMLNAMESPACES_KW "xmlnamespaces" + XML_NAMESPACE_LIST + L_PAREN "(" + XML_NAMESPACE LITERAL - STRING "'\n \n the great gatsby\n f. scott fitzgerald\n 1925\n 12.99\n \n \n 1984\n george orwell\n 1949\n 14.99\n \n \n to kill a mockingbird\n harper lee\n 1960\n 13.99\n \n '" - R_PAREN ")" - WHITESPACE "\n " - XML_TABLE_COLUMN_LIST - COLUMNS_KW "columns" - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "row_num" - WHITESPACE " " - FOR_KW "for" - WHITESPACE " " - ORDINALITY_KW "ordinality" - COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "book_id" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - INTEGER_KW "integer" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - PATH_KW "path" - WHITESPACE " " - LITERAL - STRING "'@id'" - COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "title" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - TEXT_KW "text" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - PATH_KW "path" - WHITESPACE " " - LITERAL - STRING "'bk:title'" - COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "author" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - TEXT_KW "text" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - PATH_KW "path" - WHITESPACE " " - LITERAL - STRING "'bk:author'" - COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - YEAR_KW "year" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - INTEGER_KW "integer" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - PATH_KW "path" - WHITESPACE " " - LITERAL - STRING "'bk:year'" - COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "price" - WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - NUMERIC_KW "numeric" - ARG_LIST - L_PAREN "(" - LITERAL - INT_NUMBER "5" - COMMA "," - LITERAL - INT_NUMBER "2" - R_PAREN ")" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - PATH_KW "path" - WHITESPACE " " - LITERAL - STRING "'bk:price'" + STRING "'http://example.com/books'" WHITESPACE " " - XML_COLUMN_OPTION - DEFAULT_KW "default" - WHITESPACE " " - LITERAL - NUMERIC_NUMBER "0.00" + AS_KW "as" + WHITESPACE " " + NAME + IDENT "bk" + R_PAREN ")" COMMA "," - WHITESPACE "\n " - XML_TABLE_COLUMN - NAME - IDENT "discount" + WHITESPACE "\n " + XML_ROW_PASSING_CLAUSE + LITERAL + STRING "'/bk:library/bk:book'" + WHITESPACE "\n " + PASSING_KW "passing" WHITESPACE " " - PATH_TYPE - PATH - PATH_SEGMENT - NAME_REF - NUMERIC_KW "numeric" - ARG_LIST + CALL_EXPR + XML_PARSE_FN + XMLPARSE_KW "xmlparse" L_PAREN "(" + DOCUMENT_KW "document" + WHITESPACE " " LITERAL - INT_NUMBER "5" - COMMA "," - LITERAL - INT_NUMBER "2" + STRING "'\n \n the great gatsby\n f. scott fitzgerald\n 1925\n 12.99\n \n \n 1984\n george orwell\n 1949\n 14.99\n \n \n to kill a mockingbird\n harper lee\n 1960\n 13.99\n \n '" R_PAREN ")" - WHITESPACE " " - XML_COLUMN_OPTION_LIST - XML_COLUMN_OPTION - DEFAULT_KW "default" + WHITESPACE "\n " + XML_TABLE_COLUMN_LIST + COLUMNS_KW "columns" + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "row_num" + WHITESPACE " " + FOR_KW "for" + WHITESPACE " " + ORDINALITY_KW "ordinality" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "book_id" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + INTEGER_KW "integer" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + PATH_KW "path" + WHITESPACE " " + LITERAL + STRING "'@id'" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "title" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + TEXT_KW "text" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + PATH_KW "path" + WHITESPACE " " + LITERAL + STRING "'bk:title'" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "author" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + TEXT_KW "text" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + PATH_KW "path" + WHITESPACE " " + LITERAL + STRING "'bk:author'" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + YEAR_KW "year" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + INTEGER_KW "integer" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + PATH_KW "path" + WHITESPACE " " + LITERAL + STRING "'bk:year'" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "price" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + NUMERIC_KW "numeric" + ARG_LIST + L_PAREN "(" + LITERAL + INT_NUMBER "5" + COMMA "," + LITERAL + INT_NUMBER "2" + R_PAREN ")" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + PATH_KW "path" + WHITESPACE " " + LITERAL + STRING "'bk:price'" WHITESPACE " " - LITERAL - NUMERIC_NUMBER "0.00" + XML_COLUMN_OPTION + DEFAULT_KW "default" + WHITESPACE " " + LITERAL + NUMERIC_NUMBER "0.00" + COMMA "," + WHITESPACE "\n " + XML_TABLE_COLUMN + NAME + IDENT "discount" WHITESPACE " " - XML_COLUMN_OPTION - NULL_KW "null" - WHITESPACE "\n" - R_PAREN ")" + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + NUMERIC_KW "numeric" + ARG_LIST + L_PAREN "(" + LITERAL + INT_NUMBER "5" + COMMA "," + LITERAL + INT_NUMBER "2" + R_PAREN ")" + WHITESPACE " " + XML_COLUMN_OPTION_LIST + XML_COLUMN_OPTION + DEFAULT_KW "default" + WHITESPACE " " + LITERAL + NUMERIC_NUMBER "0.00" + WHITESPACE " " + XML_COLUMN_OPTION + NULL_KW "null" + WHITESPACE "\n" + R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/squawk_syntax/src/ast/generated/nodes.rs b/crates/squawk_syntax/src/ast/generated/nodes.rs index dd15d7e4..9b35717a 100644 --- a/crates/squawk_syntax/src/ast/generated/nodes.rs +++ b/crates/squawk_syntax/src/ast/generated/nodes.rs @@ -4459,6 +4459,26 @@ pub struct CompoundSelect { pub(crate) syntax: SyntaxNode, } impl CompoundSelect { + #[inline] + pub fn fetch_clause(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn limit_clause(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn locking_clauses(&self) -> AstChildren { + support::children(&self.syntax) + } + #[inline] + pub fn offset_clause(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn order_by_clause(&self) -> Option { + support::child(&self.syntax) + } #[inline] pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::SEMICOLON) @@ -11564,8 +11584,16 @@ pub struct GroupingCube { } impl GroupingCube { #[inline] - pub fn expr(&self) -> Option { - support::child(&self.syntax) + pub fn exprs(&self) -> AstChildren { + support::children(&self.syntax) + } + #[inline] + pub fn l_paren_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::L_PAREN) + } + #[inline] + pub fn r_paren_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::R_PAREN) } #[inline] pub fn cube_token(&self) -> Option { @@ -11590,8 +11618,16 @@ pub struct GroupingRollup { } impl GroupingRollup { #[inline] - pub fn expr(&self) -> Option { - support::child(&self.syntax) + pub fn exprs(&self) -> AstChildren { + support::children(&self.syntax) + } + #[inline] + pub fn l_paren_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::L_PAREN) + } + #[inline] + pub fn r_paren_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::R_PAREN) } #[inline] pub fn rollup_token(&self) -> Option { @@ -11605,8 +11641,8 @@ pub struct GroupingSets { } impl GroupingSets { #[inline] - pub fn expr(&self) -> Option { - support::child(&self.syntax) + pub fn group_bys(&self) -> AstChildren { + support::children(&self.syntax) } #[inline] pub fn l_paren_token(&self) -> Option { @@ -12532,20 +12568,20 @@ pub struct JsonArrayAggFn { } impl JsonArrayAggFn { #[inline] - pub fn expr(&self) -> Option { + pub fn json_null_clause(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn json_null_clause(&self) -> Option { + pub fn json_returning_clause(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn json_returning_clause(&self) -> Option { + pub fn json_value_expr(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn json_select_formats(&self) -> AstChildren { - support::children(&self.syntax) + pub fn order_by_clause(&self) -> Option { + support::child(&self.syntax) } #[inline] pub fn l_paren_token(&self) -> Option { @@ -12596,17 +12632,6 @@ impl JsonArrayFn { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct JsonBehaviorClause { - pub(crate) syntax: SyntaxNode, -} -impl JsonBehaviorClause { - #[inline] - pub fn json_behavior(&self) -> Option { - support::child(&self.syntax) - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct JsonBehaviorDefault { pub(crate) syntax: SyntaxNode, @@ -13054,11 +13079,15 @@ impl JsonQueryFn { support::child(&self.syntax) } #[inline] - pub fn json_behavior_clause(&self) -> Option { + pub fn json_format_clause(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn json_format_clause(&self) -> Option { + pub fn json_on_empty_clause(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn json_on_error_clause(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -13380,11 +13409,15 @@ impl JsonValueFn { support::child(&self.syntax) } #[inline] - pub fn json_behavior_clause(&self) -> Option { + pub fn json_format_clause(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn json_format_clause(&self) -> Option { + pub fn json_on_empty_clause(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn json_on_error_clause(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -29273,24 +29306,6 @@ impl AstNode for JsonArrayFn { &self.syntax } } -impl AstNode for JsonBehaviorClause { - #[inline] - fn can_cast(kind: SyntaxKind) -> bool { - kind == SyntaxKind::JSON_BEHAVIOR_CLAUSE - } - #[inline] - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { - Some(Self { syntax }) - } else { - None - } - } - #[inline] - fn syntax(&self) -> &SyntaxNode { - &self.syntax - } -} impl AstNode for JsonBehaviorDefault { #[inline] fn can_cast(kind: SyntaxKind) -> bool { diff --git a/crates/squawk_syntax/src/postgresql.ungram b/crates/squawk_syntax/src/postgresql.ungram index 0cacf572..1c7ff10a 100644 --- a/crates/squawk_syntax/src/postgresql.ungram +++ b/crates/squawk_syntax/src/postgresql.ungram @@ -166,10 +166,10 @@ JsonObjectAggFn = JsonArrayAggFn = 'json_arrayagg' '(' - (JsonSelectFormat (',' JsonSelectFormat)*) - JsonNullClause? - JsonReturningClause? - | Expr JsonReturningClause + JsonValueExpr + OrderByClause? + JsonNullClause? + JsonReturningClause? ')' JsonQueryFn = @@ -182,7 +182,8 @@ JsonQueryFn = JsonReturningClause? JsonWrapperBehaviorClause? JsonQuotesClause? - JsonBehaviorClause? + JsonOnEmptyClause? + JsonOnErrorClause? ')' XmlTable = @@ -234,7 +235,8 @@ JsonValueFn = Expr JsonPassingClause? JsonReturningClause? - JsonBehaviorClause? + JsonOnEmptyClause? + JsonOnErrorClause? ')' SubstringFn = @@ -918,13 +920,13 @@ GroupBy = | GroupingSets GroupingRollup = - 'rollup' Expr + 'rollup' '(' (Expr (',' Expr)*)? ')' GroupingSets = - 'grouping' 'sets' '(' Expr ')' + 'grouping' 'sets' '(' (GroupBy (',' GroupBy)*)? ')' GroupingCube = - 'cube' Expr + 'cube' '(' (Expr (',' Expr)*)? ')' GroupingExpr = Expr @@ -1692,9 +1694,6 @@ JsonOnErrorClause = JsonOnEmptyClause = JsonBehavior 'on' 'empty' -JsonBehaviorClause = - JsonBehavior - JsonPassingArg = Expr 'as' Name @@ -1817,6 +1816,11 @@ CompoundSelect = ('union' | 'intersect' | 'except' ) ('all' | 'distinct')? rhs:SelectVariant + OrderByClause? + LockingClause* + LimitClause? + FetchClause? + OffsetClause? ';'? SelectInto = diff --git a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__select_into_validation.snap b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__select_into_validation.snap index a18712eb..f766cef9 100644 --- a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__select_into_validation.snap +++ b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__select_into_validation.snap @@ -496,24 +496,25 @@ SOURCE_FILE@0..858 JSON_ARRAY_FN@614..646 JSON_ARRAY_KW@614..624 "json_array" L_PAREN@624..625 "(" - SELECT_INTO@625..645 - SELECT_CLAUSE@625..631 - SELECT_KW@625..631 "select" - WHITESPACE@631..632 " " - INTO_CLAUSE@632..638 - INTO_KW@632..636 "into" - WHITESPACE@636..637 " " - PATH@637..638 - PATH_SEGMENT@637..638 - NAME@637..638 - IDENT@637..638 "t" - WHITESPACE@638..639 " " - FROM_CLAUSE@639..645 - FROM_KW@639..643 "from" - WHITESPACE@643..644 " " - FROM_ITEM@644..645 - NAME_REF@644..645 - IDENT@644..645 "u" + JSON_SELECT_FORMAT@625..645 + SELECT_INTO@625..645 + SELECT_CLAUSE@625..631 + SELECT_KW@625..631 "select" + WHITESPACE@631..632 " " + INTO_CLAUSE@632..638 + INTO_KW@632..636 "into" + WHITESPACE@636..637 " " + PATH@637..638 + PATH_SEGMENT@637..638 + NAME@637..638 + IDENT@637..638 "t" + WHITESPACE@638..639 " " + FROM_CLAUSE@639..645 + FROM_KW@639..643 "from" + WHITESPACE@643..644 " " + FROM_ITEM@644..645 + NAME_REF@644..645 + IDENT@644..645 "u" R_PAREN@645..646 ")" SEMICOLON@646..647 ";" WHITESPACE@647..649 "\n\n"