use crate::{
CompletedMarker, Marker, Parser,
generated::token_sets::{
ALL_KEYWORDS, BARE_LABEL_KEYWORDS, COLUMN_OR_TABLE_KEYWORDS, RESERVED_KEYWORDS,
TYPE_KEYWORDS, UNRESERVED_KEYWORDS,
},
syntax_kind::SyntaxKind::{self, *},
token_set::TokenSet,
};
const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[
R_PAREN, R_BRACK, SEMICOLON,
SELECT_KW,
END_KW,
ELSE_KW, THEN_KW,
]);
fn literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(LITERAL_FIRST) {
return None;
}
let m = p.start();
if p.eat(UNICODE_ESC_STRING) {
if p.eat(UESCAPE_KW) {
p.eat(STRING);
}
}
else if p.eat(STRING) {
while !p.at(EOF) && p.eat(STRING) {}
} else {
p.bump_any();
}
Some(m.complete(p, LITERAL))
}
fn array_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(L_PAREN) || p.at(L_BRACK));
let m = m.unwrap_or_else(|| p.start());
if p.at(L_PAREN) && p.nth_at_ts(1, SELECT_FIRST) {
p.expect(L_PAREN);
select(p, None, &SelectRestrictions::default());
p.expect(R_PAREN);
} else {
let closing = if p.at(L_PAREN) { R_PAREN } else { R_BRACK };
let opening = if p.at(L_PAREN) { L_PAREN } else { L_BRACK };
delimited(
p,
opening,
closing,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
|p| opt_expr(p).is_some(),
);
}
m.complete(p, ARRAY_EXPR)
}
struct SelectRestrictions {
trailing_clauses: bool,
}
impl Default for SelectRestrictions {
fn default() -> Self {
Self {
trailing_clauses: true,
}
}
}
fn opt_paren_select(p: &mut Parser<'_>, m: Option<Marker>) -> Option<CompletedMarker> {
let m = m.unwrap_or_else(|| p.start());
if !p.eat(L_PAREN) {
m.abandon(p);
return None;
}
while !p.at(EOF) && !p.at(R_PAREN) {
if p.at_ts(SELECT_FIRST)
&& (select(p, None, &SelectRestrictions::default()).is_none()
|| p.at(EOF)
|| p.at(R_PAREN))
{
break;
}
if opt_paren_select(p, None).is_none() {
break;
}
if !p.at(R_PAREN) {
break;
}
}
p.expect(R_PAREN);
if p.at_ts(COMPOUND_SELECT_FIRST) {
let cm = m.complete(p, PAREN_SELECT);
Some(compound_select(p, cm))
} else {
opt_select_trailing_clauses(p);
Some(m.complete(p, PAREN_SELECT))
}
}
const SELECT_FIRST: TokenSet = TokenSet::new(&[SELECT_KW, TABLE_KW, WITH_KW, VALUES_KW, FROM_KW]);
const PAREN_SELECT_FIRST: TokenSet = TokenSet::new(&[L_PAREN]).union(SELECT_FIRST);
fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(L_PAREN) || p.at(ROW_KW));
let m = p.start();
p.eat(ROW_KW);
p.expect(L_PAREN);
let mut saw_comma = false;
let mut saw_expr = false;
if p.eat(COMMA) {
p.error("expected expression in tuple_expr");
saw_comma = true;
}
while !p.at(EOF) && !p.at(R_PAREN) {
saw_expr = true;
if p.at_ts(SELECT_FIRST)
&& (select(p, None, &SelectRestrictions::default()).is_none()
|| p.at(EOF)
|| p.at(R_PAREN))
{
break;
}
if expr(p).is_none() {
break;
}
if !p.at(R_PAREN) {
saw_comma = true;
p.expect(COMMA);
}
}
p.expect(R_PAREN);
let cm = m.complete(
p,
if saw_expr && !saw_comma {
PAREN_EXPR
} else {
TUPLE_EXPR
},
);
if p.at_ts(COMPOUND_SELECT_FIRST) {
return compound_select(p, cm);
}
cm
}
fn case_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.expect(CASE_KW);
if !p.at(WHEN_KW) {
expr(p);
}
when_clause_list(p);
opt_else_clause(p);
p.expect(END_KW);
m.complete(p, CASE_EXPR)
}
fn when_clause_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
when_clause(p);
if !p.at(WHEN_KW) {
break;
}
}
m.complete(p, WHEN_CLAUSE_LIST);
}
fn opt_else_clause(p: &mut Parser<'_>) {
if !p.at(ELSE_KW) {
return;
}
let m = p.start();
if p.eat(ELSE_KW) {
expr(p);
}
m.complete(p, ELSE_CLAUSE);
}
fn when_clause(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.expect(WHEN_KW);
expr(p);
p.expect(THEN_KW);
expr(p);
m.complete(p, WHEN_CLAUSE)
}
const EXTRACT_ARG_FIRST_: TokenSet =
TokenSet::new(&[YEAR_KW, MONTH_KW, DAY_KW, HOUR_KW, MINUTE_KW, SECOND_KW]).union(STRING_FIRST);
const EXTRACT_ARG_FIRST: TokenSet = IDENTS.union(EXTRACT_ARG_FIRST_);
fn extract_arg(p: &mut Parser<'_>) {
if p.at_ts(EXTRACT_ARG_FIRST) {
p.bump_any();
} else {
p.error(format!(
"expected ident, year, month, day, hour, minute, second, or string, got {:?}",
p.current()
));
}
}
fn extract_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(EXTRACT_KW));
let m = p.start();
p.expect(EXTRACT_KW);
p.expect(L_PAREN);
extract_arg(p);
p.expect(FROM_KW);
expr(p);
p.expect(R_PAREN);
let m = m.complete(p, EXTRACT_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn overlay_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(OVERLAY_KW));
let m = p.start();
p.expect(OVERLAY_KW);
p.expect(L_PAREN);
if !p.at(R_PAREN) {
expr(p);
if p.eat(PLACING_KW) {
expr(p);
p.expect(FROM_KW);
expr(p);
if p.eat(FOR_KW) {
expr(p);
}
} else if p.eat(COMMA) {
opt_expr_list(p);
}
}
p.expect(R_PAREN);
let m = m.complete(p, OVERLAY_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn position_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(POSITION_KW));
let m = p.start();
p.expect(POSITION_KW);
p.expect(L_PAREN);
b_expr(p);
p.expect(IN_KW);
b_expr(p);
p.expect(R_PAREN);
let m = m.complete(p, POSITION_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn trim_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(TRIM_KW));
let m = p.start();
p.expect(TRIM_KW);
p.expect(L_PAREN);
let _ = p.eat(BOTH_KW) || p.eat(LEADING_KW) || p.eat(TRAILING_KW);
if p.eat(FROM_KW) {
if !opt_expr_list(p) {
p.error("expected expression")
}
} else {
if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(FROM_KW) {
opt_expr_list(p);
} else {
if p.eat(COMMA) {
opt_expr_list(p);
}
}
};
p.expect(R_PAREN);
let m = m.complete(p, TRIM_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn substring_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SUBSTRING_KW));
let m = p.start();
p.expect(SUBSTRING_KW);
p.expect(L_PAREN);
expr(p);
match p.current() {
FOR_KW => {
p.bump(FOR_KW);
expr(p);
if p.eat(FROM_KW) {
expr(p);
}
}
FROM_KW => {
p.bump(FROM_KW);
expr(p);
if p.eat(FOR_KW) {
expr(p);
}
}
SIMILAR_KW => {
p.bump(SIMILAR_KW);
expr(p);
}
_ if p.eat(COMMA) => {
opt_expr_list(p);
}
_ => (),
}
p.expect(R_PAREN);
let m = m.complete(p, SUBSTRING_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn opt_json_encoding_clause(p: &mut Parser<'_>) {
if p.eat(ENCODING_KW) {
name_ref(p);
}
}
fn opt_json_format_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(FORMAT_KW) {
p.expect(JSON_KW);
opt_json_encoding_clause(p);
Some(m.complete(p, JSON_FORMAT_CLAUSE))
} else {
m.abandon(p);
None
}
}
fn opt_json_returning_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(RETURNING_KW) {
type_name(p);
opt_json_format_clause(p);
Some(m.complete(p, JSON_RETURNING_CLAUSE))
} else {
m.abandon(p);
None
}
}
fn opt_json_null_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.at(NULL_KW) || p.at(ABSENT_KW) {
p.bump_any();
p.expect(ON_KW);
p.expect(NULL_KW);
m.complete(p, JSON_NULL_CLAUSE);
} else {
m.abandon(p);
}
}
pub(crate) fn opt_json_keys_unique_clause(p: &mut Parser<'_>) {
if p.at(WITH_KW) || p.at(WITHOUT_KW) {
let m = p.start();
p.bump_any();
p.expect(UNIQUE_KW);
p.eat(KEYS_KW);
m.complete(p, JSON_KEYS_UNIQUE_CLAUSE);
}
}
const JSON_OBJECT_FN_ARG_FOLLOW: TokenSet = TokenSet::new(&[
R_PAREN,
NULL_KW,
ABSENT_KW,
WITH_KW,
WITHOUT_KW,
RETURNING_KW,
]);
fn json_object_fn_arg_list(p: &mut Parser<'_>) {
if p.at(R_PAREN) {
return;
}
if p.at(RETURNING_KW) {
opt_json_returning_clause(p);
return;
}
while !p.at(EOF) && !p.at(R_PAREN) {
json_key_value(p);
if p.at_ts(JSON_OBJECT_FN_ARG_FOLLOW) {
break;
} else if p.at(COMMA) {
if p.nth_at(1, R_PAREN) {
p.error("unexpected closing comma");
}
p.bump(COMMA);
continue;
} else {
p.error("expected a comma");
}
}
opt_json_null_clause(p);
opt_json_keys_unique_clause(p);
opt_json_returning_clause(p);
}
fn json_object_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_OBJECT_KW));
let m = p.start();
p.expect(JSON_OBJECT_KW);
p.expect(L_PAREN);
json_object_fn_arg_list(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_OBJECT_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_objectagg_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_OBJECTAGG_KW));
let m = p.start();
p.expect(JSON_OBJECTAGG_KW);
p.expect(L_PAREN);
json_key_value(p);
opt_json_null_clause(p);
opt_json_keys_unique_clause(p);
opt_json_returning_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_OBJECT_AGG_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_table_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_TABLE_KW));
let m = p.start();
p.bump(JSON_TABLE_KW);
p.expect(L_PAREN);
json_table_arg_list(p);
p.expect(R_PAREN);
m.complete(p, JSON_TABLE)
}
fn json_table_arg_list(p: &mut Parser<'_>) {
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
p.expect(COMMA);
if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(AS_KW) {
name(p);
}
opt_json_passing_clause(p);
json_table_column_list(p);
opt_json_on_error_clause(p);
}
fn json_table_column_list(p: &mut Parser<'_>) {
if p.at(COLUMNS_KW) {
let m = p.start();
p.bump(COLUMNS_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
JSON_TABLE_COLUMN_FIRST,
opt_json_table_column,
);
m.complete(p, JSON_TABLE_COLUMN_LIST);
} else {
p.error("expected json table columns");
}
}
const JSON_TABLE_COLUMN_FIRST: TokenSet = TokenSet::new(&[NESTED_KW]).union(NAME_FIRST);
fn opt_json_table_column(p: &mut Parser<'_>) -> bool {
if !p.at_ts(JSON_TABLE_COLUMN_FIRST) {
return false;
}
let m = p.start();
if p.eat(NESTED_KW) {
p.eat(PATH_KW);
if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(AS_KW) {
name(p);
}
json_table_column_list(p);
} else {
name(p);
if p.eat(FOR_KW) {
p.expect(ORDINALITY_KW);
} else {
type_name(p);
if p.eat(EXISTS_KW) {
opt_json_path_clause(p);
opt_json_behavior_clause(p);
} else {
opt_json_format_clause(p);
opt_json_path_clause(p);
opt_json_wrapper_behavior(p);
opt_json_quotes_clause(p);
opt_json_behavior_clause(p);
}
}
}
m.complete(p, JSON_TABLE_COLUMN);
true
}
fn opt_json_path_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(PATH_KW) {
string_literal(p);
m.complete(p, JSON_PATH_CLAUSE);
} else {
m.abandon(p);
}
}
fn opt_json_array_fn_arg_list(p: &mut Parser<'_>) {
while !p.at(EOF) && !p.at(R_PAREN) && !p.at(RETURNING_KW) {
if p.at_ts(SELECT_FIRST) {
if select(p, None, &SelectRestrictions::default()).is_none()
|| p.at(EOF)
|| p.at(R_PAREN)
{
break;
}
opt_json_format_clause(p);
} else {
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
}
if !p.eat(COMMA) {
break;
}
}
opt_json_null_clause(p);
opt_json_returning_clause(p);
}
fn json_array_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_ARRAY_KW));
let m = p.start();
p.expect(JSON_ARRAY_KW);
p.expect(L_PAREN);
opt_json_array_fn_arg_list(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_ARRAY_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn some_any_all_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SOME_KW) || p.at(ANY_KW) || p.at(ALL_KW));
let m = p.start();
let kind = match p.current() {
SOME_KW => SOME_FN,
ANY_KW => ANY_FN,
ALL_KW => ALL_FN,
_ => unreachable!(),
};
p.bump_any();
p.expect(L_PAREN);
if p.at_ts(SELECT_FIRST) {
select(p, None, &SelectRestrictions::default());
} else {
if expr(p).is_none() {
p.error("expected expression or select");
}
}
p.expect(R_PAREN);
let m = m.complete(p, kind).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn atom_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if let Some(m) = literal(p) {
return Some(m);
}
let done = match (p.current(), p.nth(1)) {
(POSITIONAL_PARAM, _) => {
let m = p.start();
p.bump(POSITIONAL_PARAM);
m.complete(p, LITERAL)
}
(CAST_KW | TREAT_KW, L_PAREN) => {
let m = p.start();
p.bump_any();
p.bump(L_PAREN);
expr(p);
p.expect(AS_KW);
type_name(p);
opt_collate(p);
p.expect(R_PAREN);
m.complete(p, CAST_EXPR)
}
(EXTRACT_KW, L_PAREN) => extract_fn(p),
(JSON_EXISTS_KW, L_PAREN) => json_exists_fn(p),
(JSON_ARRAY_KW, L_PAREN) => json_array_fn(p),
(JSON_OBJECT_KW, L_PAREN) => json_object_fn(p),
(JSON_OBJECTAGG_KW, L_PAREN) => json_objectagg_fn(p),
(JSON_ARRAYAGG_KW, L_PAREN) => json_arrayagg_fn(p),
(JSON_QUERY_KW, L_PAREN) => json_query_fn(p),
(JSON_SCALAR_KW, L_PAREN) => json_scalar_fn(p),
(JSON_SERIALIZE_KW, L_PAREN) => json_serialize_fn(p),
(JSON_VALUE_KW, L_PAREN) => json_value_fn(p),
(JSON_KW, L_PAREN) => json_fn(p),
(SUBSTRING_KW, L_PAREN) => substring_fn(p),
(POSITION_KW, L_PAREN) => position_fn(p),
(OVERLAY_KW, L_PAREN) => overlay_fn(p),
(TRIM_KW, L_PAREN) => trim_fn(p),
(XMLROOT_KW, L_PAREN) => xmlroot_fn(p),
(XMLSERIALIZE_KW, L_PAREN) => xmlserialize_fn(p),
(XMLELEMENT_KW, L_PAREN) => xmlelement_fn(p),
(XMLFOREST_KW, L_PAREN) => xmlforest_fn(p),
(XMLEXISTS_KW, L_PAREN) => xmlexists_fn(p),
(XMLPARSE_KW, L_PAREN) => xmlparse_fn(p),
(XMLPI_KW, L_PAREN) => xmlpi_fn(p),
(SOME_KW | ALL_KW | ANY_KW, L_PAREN) => some_any_all_fn(p),
(EXISTS_KW, L_PAREN) => exists_fn(p),
(COLLATION_KW, FOR_KW) => collation_for_fn(p),
_ if p.at_ts(NAME_REF_FIRST) => name_ref_(p)?,
(L_PAREN, _) => tuple_expr(p),
(ARRAY_KW, L_BRACK | L_PAREN) => {
let m = p.start();
p.bump(ARRAY_KW);
array_expr(p, Some(m))
}
(L_BRACK, _) => array_expr(p, None),
(ROW_KW, L_PAREN) => tuple_expr(p),
(CASE_KW, _) => case_expr(p),
_ => {
p.err_and_bump("expected expression in atom_expr");
return None;
}
};
Some(done)
}
fn json_arrayagg_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_ARRAYAGG_KW));
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);
opt_order_by_clause(p);
opt_json_null_clause(p);
opt_json_returning_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_ARRAY_AGG_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn exists_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(EXISTS_KW));
let m = p.start();
p.bump(EXISTS_KW);
p.expect(L_PAREN);
if p.at_ts(SELECT_FIRST) {
select(p, None, &SelectRestrictions::default());
} else {
p.error("expected select");
}
p.expect(R_PAREN);
let m = m.complete(p, EXISTS_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn collation_for_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(COLLATION_KW) && p.nth_at(1, FOR_KW));
let m = p.start();
p.bump(COLLATION_KW);
p.bump(FOR_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
let m = m.complete(p, COLLATION_FOR_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn xmlpi_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLPI_KW));
let m = p.start();
p.expect(XMLPI_KW);
p.expect(L_PAREN);
p.expect(NAME_KW);
col_label(p);
if p.eat(COMMA) && expr(p).is_none() {
p.error("expected expr");
}
p.expect(R_PAREN);
let m = m.complete(p, XML_PI_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn xmlparse_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLPARSE_KW));
let m = p.start();
p.expect(XMLPARSE_KW);
p.expect(L_PAREN);
if p.at(DOCUMENT_KW) || p.at(CONTENT_KW) {
p.bump_any();
} else {
p.error("expected DOCUMENT or CONTENT");
}
if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(PRESERVE_KW) || p.eat(STRIP_KW) {
p.expect(WHITESPACE_KW);
}
p.expect(R_PAREN);
let m = m.complete(p, XML_PARSE_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn opt_xml_passing_mech(p: &mut Parser<'_>) -> bool {
let m = p.start();
if p.eat(BY_KW) {
if !p.eat(REF_KW) && !p.eat(VALUE_KW) {
p.error("expected REF or VALUE");
}
m.complete(p, XML_PASSING_MECH);
true
} else {
m.abandon(p);
false
}
}
fn xmlexists_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLEXISTS_KW));
let m = p.start();
p.expect(XMLEXISTS_KW);
p.expect(L_PAREN);
xml_row_passing_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, XML_EXISTS_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn xmlelement_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLELEMENT_KW));
let m = p.start();
p.expect(XMLELEMENT_KW);
p.expect(L_PAREN);
p.expect(NAME_KW);
col_label(p);
if p.eat(COMMA) {
if p.eat(XMLATTRIBUTES_KW) {
expr_as_name_list(p);
if p.eat(COMMA) && !opt_expr_list(p) {
p.error("expected expression list");
}
} else if !opt_expr_list(p) {
p.error("expected expression list");
}
}
p.expect(R_PAREN);
let m = m.complete(p, XML_ELEMENT_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn expr_as_name_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
|p| {
let m = p.start();
if opt_expr(p).is_none() {
p.error("expected expression");
m.abandon(p);
return false;
}
if p.eat(AS_KW) {
col_label(p);
}
m.complete(p, EXPR_AS_NAME);
true
},
);
m.complete(p, EXPR_AS_NAME_LIST);
}
fn xmlforest_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLFOREST_KW));
let m = p.start();
p.expect(XMLFOREST_KW);
expr_as_name_list(p);
let m = m.complete(p, XML_FOREST_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn xmlserialize_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLSERIALIZE_KW));
let m = p.start();
p.expect(XMLSERIALIZE_KW);
p.expect(L_PAREN);
if p.at(DOCUMENT_KW) || p.at(CONTENT_KW) {
p.bump_any();
} else {
p.error("expected DOCUMENT or CONTENT");
}
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(AS_KW);
type_name(p);
if p.eat(NO_KW) {
p.expect(INDENT_KW);
} else {
p.eat(INDENT_KW);
}
p.expect(R_PAREN);
let m = m.complete(p, XML_SERIALIZE_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn xmlroot_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(XMLROOT_KW));
let m = p.start();
p.expect(XMLROOT_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(COMMA);
p.expect(VERSION_KW);
if p.eat(NO_KW) {
p.expect(VALUE_KW);
} else if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(COMMA) {
p.expect(STANDALONE_KW);
if p.eat(NO_KW) {
p.eat(VALUE_KW);
} else {
p.expect(YES_KW);
}
}
p.expect(R_PAREN);
let m = m.complete(p, XML_ROOT_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_KW));
let m = p.start();
p.expect(JSON_KW);
p.expect(L_PAREN);
opt_expr(p);
opt_json_format_clause(p);
opt_json_keys_unique_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_scalar_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_SCALAR_KW));
let m = p.start();
p.expect(JSON_SCALAR_KW);
p.expect(L_PAREN);
opt_expr(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_SCALAR_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_value_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_VALUE_KW));
let m = p.start();
p.expect(JSON_VALUE_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
p.expect(COMMA);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_passing_clause(p);
opt_json_returning_clause(p);
opt_json_behavior_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_VALUE_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_serialize_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_SERIALIZE_KW));
let m = p.start();
p.expect(JSON_SERIALIZE_KW);
p.expect(L_PAREN);
opt_expr(p);
opt_json_format_clause(p);
opt_json_returning_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_SERIALIZE_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn json_query_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_QUERY_KW));
let m = p.start();
p.expect(JSON_QUERY_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
p.expect(COMMA);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_passing_clause(p);
opt_json_returning_clause(p);
opt_json_wrapper_behavior(p);
opt_json_quotes_clause(p);
opt_json_behavior_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_QUERY_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn opt_json_quotes_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(KEEP_KW) || p.eat(OMIT_KW) {
p.expect(QUOTES_KW);
if p.eat(ON_KW) {
p.expect(SCALAR_KW);
p.expect(STRING_KW);
}
Some(m.complete(p, JSON_QUOTES_CLAUSE))
} else {
m.abandon(p);
None
}
}
fn opt_json_behavior_clause(p: &mut Parser<'_>) {
let m = p.start();
if opt_json_behavior(p).is_some() {
p.expect(ON_KW);
let kind = if p.eat(ERROR_KW) {
JSON_ON_ERROR_CLAUSE
} else {
p.expect(EMPTY_KW);
JSON_ON_EMPTY_CLAUSE
};
m.complete(p, kind);
opt_json_on_error_clause(p);
} else {
m.abandon(p);
}
}
fn opt_json_wrapper_behavior(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
match (p.current(), p.nth(1)) {
(WITHOUT_KW, WRAPPER_KW) | (WITH_KW, WRAPPER_KW) | (WITHOUT_KW, ARRAY_KW) => {
p.bump_any();
p.bump_any();
}
(WITH_KW, ARRAY_KW) => {
p.bump_any();
p.bump_any();
p.expect(WRAPPER_KW);
}
(WITH_KW, UNCONDITIONAL_KW) | (WITH_KW, CONDITIONAL_KW) => {
p.bump_any();
p.bump_any();
p.eat(ARRAY_KW);
p.expect(WRAPPER_KW);
}
_ => {
m.abandon(p);
return None;
}
}
Some(m.complete(p, JSON_WRAPPER_BEHAVIOR_CLAUSE))
}
fn json_exists_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(JSON_EXISTS_KW));
let m = p.start();
p.expect(JSON_EXISTS_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
p.expect(COMMA);
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_passing_clause(p);
opt_json_on_error_clause(p);
p.expect(R_PAREN);
let m = m.complete(p, JSON_EXISTS_FN).precede(p);
opt_agg_clauses(p);
m.complete(p, CALL_EXPR)
}
fn opt_json_on_error_clause(p: &mut Parser<'_>) {
let m = p.start();
if opt_json_behavior(p).is_some() {
p.expect(ON_KW);
p.expect(ERROR_KW);
m.complete(p, JSON_ON_ERROR_CLAUSE);
} else {
m.abandon(p);
}
}
fn opt_json_behavior(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
let kind = match p.current() {
DEFAULT_KW => {
p.bump(DEFAULT_KW);
if expr(p).is_none() {
p.error("expected expression");
}
JSON_BEHAVIOR_DEFAULT
}
ERROR_KW => {
p.bump(ERROR_KW);
JSON_BEHAVIOR_ERROR
}
NULL_KW => {
p.bump(NULL_KW);
JSON_BEHAVIOR_NULL
}
TRUE_KW => {
p.bump(TRUE_KW);
JSON_BEHAVIOR_TRUE
}
FALSE_KW => {
p.bump(FALSE_KW);
JSON_BEHAVIOR_FALSE
}
UNKNOWN_KW => {
p.bump(UNKNOWN_KW);
JSON_BEHAVIOR_UNKNOWN
}
EMPTY_KW => {
p.bump(EMPTY_KW);
if p.eat(OBJECT_KW) {
JSON_BEHAVIOR_EMPTY_OBJECT
} else {
p.eat(ARRAY_KW);
JSON_BEHAVIOR_EMPTY_ARRAY
}
}
_ => {
m.abandon(p);
return None;
}
};
Some(m.complete(p, kind))
}
fn opt_json_passing_arg(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(EXPR_FIRST) {
return None;
}
let m = p.start();
if expr(p).is_none() {
p.error("expected expr");
}
opt_json_format_clause(p);
p.expect(AS_KW);
col_label(p);
Some(m.complete(p, JSON_PASSING_ARG))
}
fn opt_json_passing_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(PASSING_KW) {
while !p.at(EOF) {
if opt_json_passing_arg(p).is_none() {
break;
}
if !p.eat(COMMA) {
break;
}
}
m.complete(p, JSON_PASSING_CLAUSE);
} else {
m.abandon(p);
}
}
fn lhs(p: &mut Parser<'_>, r: &Restrictions) -> Option<CompletedMarker> {
let m;
let (kind, prefix_bp) = match p.current() {
MINUS | PLUS => {
m = p.start();
p.bump_any();
(PREFIX_EXPR, 13)
}
COLON => {
m = p.start();
p.bump(COLON);
(NON_STANDARD_PARAM, 7)
}
_ if p.at_ts(OPERATOR_FIRST) && p.at(CUSTOM_OP) => {
m = p.start();
p.bump(CUSTOM_OP);
(PREFIX_EXPR, 7)
}
NOT_KW if !r.not_disabled => {
m = p.start();
p.bump_any();
(PREFIX_EXPR, 3)
}
OPERATOR_KW if p.at(OPERATOR_CALL) => {
m = p.start();
p.expect(OPERATOR_CALL);
(PREFIX_EXPR, 7)
}
_ => {
let lhs = atom_expr(p)?;
let cm = postfix_expr(p, lhs, true);
return Some(cm);
}
};
expr_bp(p, prefix_bp, &Restrictions::default());
let cm = m.complete(p, kind);
Some(cm)
}
fn postfix_expr(
p: &mut Parser<'_>,
mut lhs: CompletedMarker,
allow_calls: bool,
) -> CompletedMarker {
loop {
lhs = match p.current() {
NOT_KW if p.nth_at(1, BETWEEN_KW) => between_expr(p),
BETWEEN_KW => between_expr(p),
L_PAREN if allow_calls => call_expr_args(p, lhs),
L_BRACK => index_expr(p, lhs),
DOT => match postfix_dot_expr(p, lhs, allow_calls) {
Ok(it) => it,
Err(it) => {
lhs = it;
break;
}
},
AT_KW if p.nth_at(1, LOCAL_KW) => {
let m = p.start();
p.bump(AT_KW);
p.bump(LOCAL_KW);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
ISNULL_KW => {
let m = p.start();
p.bump(ISNULL_KW);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_NORMALIZED) => {
let m = p.start();
p.bump(IS_NOT_NORMALIZED);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NORMALIZED) => {
let m = p.start();
p.bump(IS_NORMALIZED);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_JSON_OBJECT) => {
let m = p.start();
p.bump(IS_NOT_JSON_OBJECT);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_JSON_ARRAY) => {
let m = p.start();
p.bump(IS_NOT_JSON_ARRAY);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_JSON_VALUE) => {
let m = p.start();
p.bump(IS_NOT_JSON_VALUE);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_JSON_SCALAR) => {
let m = p.start();
p.bump(IS_NOT_JSON_SCALAR);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_NOT_JSON) => {
let m = p.start();
p.bump(IS_NOT_JSON);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_JSON_OBJECT) => {
let m = p.start();
p.bump(IS_JSON_OBJECT);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_JSON_ARRAY) => {
let m = p.start();
p.bump(IS_JSON_ARRAY);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_JSON_VALUE) => {
let m = p.start();
p.bump(IS_JSON_VALUE);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_JSON_SCALAR) => {
let m = p.start();
p.bump(IS_JSON_SCALAR);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
IS_KW if p.at(IS_JSON) => {
let m = p.start();
p.bump(IS_JSON);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
NOTNULL_KW => {
let m = p.start();
p.bump(NOTNULL_KW);
lhs = m.complete(p, POSTFIX_EXPR);
break;
}
_ => break,
};
}
lhs
}
fn delimited(
p: &mut Parser<'_>,
bra: SyntaxKind,
ket: SyntaxKind,
delim: SyntaxKind,
unexpected_delim_message: impl Fn() -> String,
first_set: TokenSet,
mut parser: impl FnMut(&mut Parser<'_>) -> bool,
) {
p.expect(bra);
while !p.at(ket) && !p.at(EOF) {
if p.at(delim) {
let m = p.start();
p.error(unexpected_delim_message());
p.bump(delim);
m.complete(p, ERROR);
continue;
}
if !parser(p) {
break;
}
if p.at(delim) && p.nth_at(1, ket) {
p.err_and_bump("unexpected trailing comma");
break;
}
if !p.eat(delim) {
if p.at_ts(first_set) {
p.error(format!("expected {delim:?}"));
} else {
break;
}
}
}
p.expect(ket);
}
fn separated(
p: &mut Parser<'_>,
delim: SyntaxKind,
unexpected_delim_message: impl Fn() -> String,
first_set: TokenSet,
follow_set: TokenSet,
mut parser: impl FnMut(&mut Parser<'_>) -> bool,
) {
while !p.at(EOF) {
if p.at(delim) {
let m = p.start();
p.error(unexpected_delim_message());
p.bump(delim);
m.complete(p, ERROR);
continue;
}
if !parser(p) {
break;
}
if !p.eat(delim) {
if p.at_ts(first_set) && !p.at_ts(follow_set) {
p.error(format!("expected {delim:?}"));
} else {
break;
}
}
}
}
fn name_ref(p: &mut Parser<'_>) -> Option<CompletedMarker> {
opt_name_ref(p).or_else(|| {
p.error("expected name");
None
})
}
fn opt_name_ref(p: &mut Parser<'_>) -> Option<CompletedMarker> {
name_ref_(p)
}
fn name(p: &mut Parser<'_>) {
if opt_name(p).is_none() {
p.error("expected name");
}
}
fn opt_name(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(NAME_FIRST) {
return None;
}
let m = p.start();
if !opt_ident(p) {
p.bump_any();
}
Some(m.complete(p, NAME))
}
fn path_segment(p: &mut Parser<'_>, kind: SyntaxKind) {
let m = p.start();
if p.at_ts(OPERATOR_FIRST) && !p.at(OPERATOR_KW) && current_operator(p).is_some() {
} else if p.at_ts(COL_LABEL_FIRST) {
let m = p.start();
p.bump_any();
let kind = if p.at(DOT) { NAME_REF } else { kind };
m.complete(p, kind);
} else {
p.error(format!("expected name, got {:?}", p.current()));
m.abandon(p);
return;
}
m.complete(p, PATH_SEGMENT);
}
const PATH_FIRST: TokenSet = NON_RESERVED_WORD;
fn opt_path(p: &mut Parser<'_>, kind: SyntaxKind) -> Option<CompletedMarker> {
if !p.at_ts(PATH_FIRST) {
return None;
}
let m = p.start();
path_segment(p, kind);
let qual = m.complete(p, PATH);
Some(path_for_qualifier(p, qual, kind))
}
fn opt_path_name(p: &mut Parser<'_>) -> Option<CompletedMarker> {
opt_path(p, NAME)
}
fn path_name(p: &mut Parser<'_>) {
if opt_path_name(p).is_none() {
p.error("expected path name");
}
}
fn opt_path_name_ref(p: &mut Parser<'_>) -> Option<CompletedMarker> {
opt_path(p, NAME_REF)
}
fn path_name_ref(p: &mut Parser<'_>) {
if opt_path_name_ref(p).is_none() {
p.error("expected path name");
}
}
fn path_for_qualifier(
p: &mut Parser<'_>,
mut qual: CompletedMarker,
kind: SyntaxKind,
) -> CompletedMarker {
loop {
if p.at(DOT) {
let path = qual.precede(p);
p.bump(DOT);
path_segment(p, kind);
let path = path.complete(p, PATH);
qual = path;
} else {
return qual;
}
}
}
fn opt_percent_type(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(PERCENT) && p.nth_at(1, TYPE_KW) {
let m = p.start();
p.bump(PERCENT);
p.bump(TYPE_KW);
Some(m.complete(p, PERCENT_TYPE_CLAUSE))
} else {
None
}
}
fn opt_array_index(p: &mut Parser<'_>) -> bool {
if p.eat(L_BRACK) {
if !p.at(R_BRACK) {
let _ = expr(p);
}
p.expect(R_BRACK);
true
} else {
false
}
}
fn type_mods(
p: &mut Parser<'_>,
m: Marker,
type_args_enabled: bool,
kind: SyntaxKind,
) -> Option<CompletedMarker> {
if opt_percent_type(p).is_some() {
return Some(m.complete(p, PERCENT_TYPE));
}
if p.at(L_PAREN) && type_args_enabled {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
|p| {
let m = p.start();
if expr(p).is_some() {
m.complete(p, ARG);
true
} else {
m.abandon(p);
false
}
},
);
m.complete(p, ARG_LIST);
}
let cm = m.complete(p, kind);
if !p.at(L_BRACK) && !p.at(ARRAY_KW) {
return Some(cm);
}
let m = cm.precede(p);
if p.eat(ARRAY_KW) {
opt_array_index(p);
} else {
let mut found_one_array_bracks = false;
while !p.at(EOF) && p.at(L_BRACK) {
if opt_array_index(p) {
found_one_array_bracks = true;
}
}
if !found_one_array_bracks {
p.error("expected L_BRACK for ARRAY_TYPE");
}
}
Some(m.complete(p, ARRAY_TYPE))
}
fn char_type(p: &mut Parser<'_>) -> SyntaxKind {
assert!(p.at(CHARACTER_KW) || p.at(CHAR_KW) || p.at(NCHAR_KW) || p.at(VARCHAR_KW));
if p.eat(VARCHAR_KW) {
return CHAR_TYPE;
}
p.bump_any();
p.eat(VARYING_KW);
CHAR_TYPE
}
const TYPE_NAME_FIRST: TokenSet = TokenSet::new(&[
BIT_KW,
NATIONAL_KW,
CHARACTER_KW,
CHAR_KW,
NCHAR_KW,
VARCHAR_KW,
TIMESTAMP_KW,
TIME_KW,
INTERVAL_KW,
DOUBLE_KW,
GENERATED_KW,
IDENT,
])
.union(TYPE_KEYWORDS);
#[must_use]
fn opt_type_name_with(p: &mut Parser<'_>, type_args_enabled: bool) -> Option<CompletedMarker> {
if !p.at_ts(TYPE_NAME_FIRST) {
return None;
}
let m = p.start();
p.eat(SETOF_KW);
let wrapper_type = match p.current() {
BIT_KW => {
p.bump(BIT_KW);
p.eat(VARYING_KW);
BIT_TYPE
}
NATIONAL_KW if matches!(p.nth(1), CHAR_KW | CHARACTER_KW) => {
p.bump(NATIONAL_KW);
char_type(p)
}
CHARACTER_KW | CHAR_KW | NCHAR_KW | VARCHAR_KW => char_type(p),
TIMESTAMP_KW | TIME_KW => {
p.bump_any();
if p.eat(L_PAREN) {
expr(p);
p.expect(R_PAREN);
}
opt_with_timezone(p);
TIME_TYPE
}
INTERVAL_KW => {
p.bump(INTERVAL_KW);
opt_interval_trailing(p);
INTERVAL_TYPE
}
DOUBLE_KW if p.nth_at(1, PRECISION_KW) => {
p.bump(DOUBLE_KW);
p.bump(PRECISION_KW);
DOUBLE_TYPE
}
GENERATED_KW if p.nth_at(1, ALWAYS_KW) => {
m.abandon(p);
return None;
}
_ if p.at_ts(TYPE_KEYWORDS) || p.at(IDENT) => {
path_name_ref(p);
PATH_TYPE
}
_ => {
m.abandon(p);
return None;
}
};
type_mods(p, m, type_args_enabled, wrapper_type)
}
fn opt_with_timezone(p: &mut Parser<'_>) {
let m = p.start();
if p.at(WITH_KW) || p.at(WITHOUT_KW) {
let kind = if p.eat(WITH_KW) {
WITH_TIMEZONE
} else {
p.bump(WITHOUT_KW);
WITHOUT_TIMEZONE
};
p.expect(TIME_KW);
p.expect(ZONE_KW);
m.complete(p, kind);
} else {
m.abandon(p);
}
}
fn opt_type_name(p: &mut Parser<'_>) -> bool {
opt_type_name_with(p, true).is_some()
}
fn type_name(p: &mut Parser<'_>) {
if !opt_type_name(p) {
p.error("expected type name");
}
}
fn simple_type_name(p: &mut Parser<'_>) {
if opt_type_name_with(p, false).is_none() {
p.error("expected simple type name");
}
}
fn arg_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
p.eat(VARIADIC_KW);
let r = Restrictions {
order_by_allowed: true,
as_allowed: true,
..Restrictions::default()
};
expr_bp(p, 1, &r)
}
fn arg_list(p: &mut Parser<'_>) {
assert!(p.at(L_PAREN));
let m = p.start();
if p.nth_at(1, STAR) {
p.bump(L_PAREN);
p.expect(STAR);
p.expect(R_PAREN);
m.complete(p, ARG_LIST);
return;
}
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "expected expression".into(),
EXPR_FIRST,
|p| {
let _ = p.eat(DISTINCT_KW) || p.eat(ALL_KW);
arg_expr(p).is_some()
},
);
m.complete(p, ARG_LIST);
}
fn interval_second(p: &mut Parser<'_>) {
p.expect(SECOND_KW);
if p.eat(L_PAREN) {
if opt_numeric_literal(p).is_none() {
p.error("expected an integer");
}
p.expect(R_PAREN);
}
}
fn opt_interval_trailing(p: &mut Parser<'_>) {
match (p.current(), p.nth(1)) {
(DAY_KW, TO_KW) => {
p.bump(DAY_KW);
p.bump(TO_KW);
match p.current() {
HOUR_KW => {
p.bump(HOUR_KW);
}
MINUTE_KW => {
p.bump(MINUTE_KW);
}
SECOND_KW => {
interval_second(p);
}
_ => p.error("expected HOUR, MINUTE, or SECOND"),
}
}
(DAY_KW, _) => p.bump(DAY_KW),
(HOUR_KW, TO_KW) => {
p.bump(HOUR_KW);
p.bump(TO_KW);
if !p.eat(MINUTE_KW) {
interval_second(p);
}
}
(HOUR_KW, _) => p.bump(HOUR_KW),
(MINUTE_KW, TO_KW) => {
p.bump(MINUTE_KW);
p.bump(TO_KW);
interval_second(p);
}
(MINUTE_KW, _) => p.bump(MINUTE_KW),
(MONTH_KW, _) => p.bump(MONTH_KW),
(YEAR_KW, TO_KW) => {
p.bump(YEAR_KW);
p.bump(TO_KW);
p.expect(MONTH_KW);
}
(YEAR_KW, _) => {
p.bump(YEAR_KW);
}
(SECOND_KW, _) => {
interval_second(p);
}
(L_PAREN, _) => {
p.bump(L_PAREN);
if opt_numeric_literal(p).is_none() {
p.error("expected number")
}
p.bump(R_PAREN);
}
_ => (),
}
}
fn name_ref_(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(NAME_REF_FIRST) {
return None;
}
let m = p.start();
let kind = match p.current() {
TIMESTAMP_KW | TIME_KW => {
p.bump_any();
if p.eat(L_PAREN) {
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
p.expect(R_PAREN);
}
opt_with_timezone(p);
TIME_TYPE
}
BIT_KW => {
p.bump(BIT_KW);
p.eat(VARYING_KW);
BIT_TYPE
}
NATIONAL_KW if matches!(p.nth(1), CHAR_KW | CHARACTER_KW) => {
p.bump(NATIONAL_KW);
char_type(p)
}
DOUBLE_KW if p.nth_at(1, PRECISION_KW) => {
p.bump(DOUBLE_KW);
p.bump(PRECISION_KW);
DOUBLE_TYPE
}
CHARACTER_KW | CHAR_KW | NCHAR_KW | VARCHAR_KW => char_type(p),
INTERVAL_KW => {
p.bump(INTERVAL_KW);
opt_interval_trailing(p);
INTERVAL_TYPE
}
_ => {
if !opt_ident(p) {
p.bump_any();
}
NAME_REF
}
};
let cm = m.complete(p, if p.at(STRING) { kind } else { NAME_REF });
if p.at_ts(STRING_FIRST) {
let cm = if kind == NAME_REF {
let path_segment = cm.precede(p).complete(p, PATH_SEGMENT);
let path = path_segment.precede(p).complete(p, PATH);
path.precede(p).complete(p, PATH_TYPE)
} else {
cm
};
string_literal(p);
if kind == INTERVAL_TYPE {
opt_interval_trailing(p);
}
Some(cm.precede(p).complete(p, CAST_EXPR))
} else {
Some(cm)
}
}
fn between_expr(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(NOT_KW) || p.at(BETWEEN_KW));
let m = p.start();
p.eat(NOT_KW);
p.expect(BETWEEN_KW);
p.eat(SYMMETRIC_KW);
b_expr(p);
p.expect(AND_KW);
b_expr(p);
m.complete(p, BETWEEN_EXPR)
}
fn call_expr_args(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(L_PAREN));
let prev_kind = lhs.kind();
let m = lhs.precede(p);
arg_list(p);
opt_agg_clauses(p);
let mut cm = m.complete(p, CALL_EXPR);
if p.at_ts(STRING_FIRST) {
if prev_kind == FIELD_EXPR {
cm = cm.precede(p).complete(p, EXPR_TYPE);
}
string_literal(p);
cm.precede(p).complete(p, CAST_EXPR)
} else {
cm
}
}
fn opt_agg_clauses(p: &mut Parser<'_>) {
opt_within_clause(p);
opt_filter_clause(p);
opt_over_clause(p);
}
fn opt_filter_clause(p: &mut Parser<'_>) {
if p.at(FILTER_KW) {
let m = p.start();
p.expect(FILTER_KW);
p.expect(L_PAREN);
p.expect(WHERE_KW);
expr(p);
p.expect(R_PAREN);
m.complete(p, FILTER_CLAUSE);
}
}
fn opt_over_clause(p: &mut Parser<'_>) {
if p.at(OVER_KW) || p.at(RESPECT_KW) || p.at(IGNORE_KW) {
let m = p.start();
if p.eat(RESPECT_KW) || p.eat(IGNORE_KW) {
p.expect(NULLS_KW);
}
p.expect(OVER_KW);
if p.eat(L_PAREN) {
window_spec(p);
p.expect(R_PAREN);
} else {
name_ref(p);
}
m.complete(p, OVER_CLAUSE);
}
}
fn opt_within_clause(p: &mut Parser<'_>) {
if p.at(WITHIN_KW) {
let m = p.start();
p.expect(WITHIN_KW);
p.expect(GROUP_KW);
p.expect(L_PAREN);
opt_order_by_clause(p);
p.expect(R_PAREN);
m.complete(p, WITHIN_CLAUSE);
}
}
fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(L_BRACK));
let m = lhs.precede(p);
p.bump(L_BRACK);
if !p.eat(R_BRACK) {
if p.eat(COLON) {
if p.eat(R_BRACK) {
return m.complete(p, SLICE_EXPR);
} else {
expr(p);
p.expect(R_BRACK);
return m.complete(p, SLICE_EXPR);
}
}
expr(p);
if p.eat(COLON) {
if p.eat(R_BRACK) {
return m.complete(p, SLICE_EXPR);
}
expr(p);
p.expect(R_BRACK);
return m.complete(p, SLICE_EXPR);
}
p.expect(R_BRACK);
}
m.complete(p, INDEX_EXPR)
}
fn name_ref_or_index(p: &mut Parser<'_>) {
assert!(p.at(IDENT) || p.at_ts(TYPE_KEYWORDS) || p.at_ts(ALL_KEYWORDS) || p.at(INT_NUMBER));
let m = p.start();
p.bump_any();
m.complete(p, NAME_REF);
}
fn field_expr(
p: &mut Parser<'_>,
lhs: Option<CompletedMarker>,
allow_calls: bool,
) -> Result<CompletedMarker, CompletedMarker> {
assert!(p.at(DOT));
let m = match lhs {
Some(lhs) => lhs.precede(p),
None => p.start(),
};
p.bump(DOT);
if p.at(IDENT) || p.at_ts(TYPE_KEYWORDS) || p.at(INT_NUMBER) || p.at_ts(ALL_KEYWORDS) {
name_ref_or_index(p);
} else if p.at(FLOAT_NUMBER) {
return match p.split_float(m) {
(true, m) => {
let lhs = m.complete(p, FIELD_EXPR);
postfix_dot_expr(p, lhs, allow_calls)
}
(false, m) => Ok(m.complete(p, FIELD_EXPR)),
};
} else if p.eat(STAR) || opt_operator(p) {
} else {
p.error(format!(
"expected field name or number, got {:?}",
p.current()
));
}
Ok(m.complete(p, FIELD_EXPR))
}
fn postfix_dot_expr(
p: &mut Parser<'_>,
lhs: CompletedMarker,
allow_calls: bool,
) -> Result<CompletedMarker, CompletedMarker> {
assert!(p.at(DOT));
field_expr(p, Some(lhs), allow_calls).map(|cm| {
if p.at_ts(STRING_FIRST) {
let cm = cm.precede(p).complete(p, EXPR_TYPE);
string_literal(p);
cm.precede(p).complete(p, CAST_EXPR)
} else {
cm
}
})
}
fn expr(p: &mut Parser) -> Option<CompletedMarker> {
expr_bp(p, 1, &Restrictions::default())
}
fn opt_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(EXPR_FIRST) {
return None;
}
expr(p)
}
fn b_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
expr_bp(
p,
1,
&Restrictions {
in_disabled: true,
is_disabled: true,
not_disabled: true,
and_disabled: true,
..Restrictions::default()
},
)
}
fn json_key_value(p: &mut Parser) -> Option<CompletedMarker> {
let m = p.start();
if expr(p).is_none() {
p.error("expected expression");
}
if !p.eat(VALUE_KW) && !p.eat(COLON) {
m.abandon(p);
return None;
}
if expr(p).is_none() {
p.error("expected expression");
}
opt_json_format_clause(p);
Some(m.complete(p, JSON_KEY_VALUE))
}
enum Associativity {
Left,
Right,
}
fn current_op(p: &Parser<'_>, r: &Restrictions) -> (u8, SyntaxKind, Associativity) {
use Associativity::*;
const NOT_AN_OP: (u8, SyntaxKind, Associativity) = (0, AT, Left);
match p.current() {
OR_KW => (1, OR_KW, Left),
R_ANGLE if p.at(GTEQ) => (5, GTEQ, Left), R_ANGLE if p.next_not_joined_op(0) => (5, R_ANGLE, Left), EQ if p.at(FAT_ARROW) => (7, FAT_ARROW, Right), EQ if p.next_not_joined_op(0) => (5, EQ, Right), IN_KW if !r.in_disabled => (6, IN_KW, Right),
L_ANGLE if p.at(NEQB) => (5, NEQB, Left), L_ANGLE if p.at(LTEQ) => (5, LTEQ, Left), L_ANGLE if p.next_not_joined_op(0) => (5, L_ANGLE, Left), PLUS if p.next_not_joined_op(0) => (8, PLUS, Left), OVERLAPS_KW => (7, OVERLAPS_KW, Left),
ESCAPE_KW => (7, ESCAPE_KW, Left),
LIKE_KW => (6, LIKE_KW, Left),
ILIKE_KW => (6, ILIKE_KW, Left),
NOT_KW if !r.not_disabled && p.at(NOT_SIMILAR_TO) => (6, NOT_SIMILAR_TO, Left),
NOT_KW if !r.not_disabled && p.at(NOT_LIKE) => (6, NOT_LIKE, Left),
NOT_KW if !r.not_disabled && p.at(NOT_ILIKE) => (6, NOT_ILIKE, Left),
NOT_KW if !r.not_disabled && p.at(NOT_IN) => (6, NOT_IN, Left),
IS_KW if !r.is_disabled && p.at(IS_NORMALIZED) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_NOT_NORMALIZED) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_DISTINCT_FROM) => (4, IS_DISTINCT_FROM, Left),
IS_KW if !r.is_disabled && p.at(IS_NOT_DISTINCT_FROM) => (4, IS_NOT_DISTINCT_FROM, Left),
IS_KW if !r.is_disabled && p.at(IS_NOT_JSON) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_NOT_JSON_OBJECT) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_NOT_JSON_ARRAY) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_NOT_JSON_VALUE) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_NOT_JSON_SCALAR) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_JSON_OBJECT) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_JSON_ARRAY) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_JSON_VALUE) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_JSON_SCALAR) => NOT_AN_OP,
IS_KW if !r.is_disabled && p.at(IS_JSON) => NOT_AN_OP,
AT_KW if p.at(AT_TIME_ZONE) => (11, AT_TIME_ZONE, Left),
SIMILAR_KW if p.at(SIMILAR_TO) => (6, SIMILAR_TO, Left),
IS_KW if p.at(IS_NOT) => (4, IS_NOT, Left),
OPERATOR_KW if p.at(OPERATOR_CALL) => (7, OPERATOR_CALL, Left),
IS_KW if !r.is_disabled => (4, IS_KW, Left),
CARET if p.next_not_joined_op(0) => (10, CARET, Left), PERCENT if p.next_not_joined_op(0) => (9, PERCENT, Left), AND_KW if !r.and_disabled => (2, AND_KW, Left),
AS_KW if r.as_allowed => (7, AS_KW, Left),
SLASH if p.next_not_joined_op(0) => (9, SLASH, Left), STAR if p.next_not_joined_op(0) => (9, STAR, Left), BANG if p.at(NEQ) => (5, NEQ, Left), COLLATE_KW => (12, COLLATE_KW, Left),
MINUS if p.next_not_joined_op(0) => (8, MINUS, Left), COLON if p.at(COLON_EQ) => (5, COLON_EQ, Right), COLON if p.at(COLON_COLON) => (15, COLON_COLON, Left), _ if p.at_ts(OPERATOR_FIRST) => (7, CUSTOM_OP, Right),
_ => NOT_AN_OP,
}
}
const OVERLAPPING_TOKENS: TokenSet = TokenSet::new(&[OR_KW, AND_KW, IS_KW, COLLATE_KW]);
#[derive(Default)]
struct Restrictions {
order_by_allowed: bool,
as_allowed: bool,
in_disabled: bool,
is_disabled: bool,
not_disabled: bool,
and_disabled: bool,
}
fn expr_bp(p: &mut Parser<'_>, bp: u8, r: &Restrictions) -> Option<CompletedMarker> {
let m = p.start();
if !p.at_ts(EXPR_FIRST) {
p.err_recover(
&format!("expected an expression, found {:?}", p.current()),
EXPR_RECOVERY_SET,
);
m.abandon(p);
return None;
}
let mut lhs = match lhs(p, r) {
Some(lhs) => lhs.extend_to(p, m),
None => {
m.abandon(p);
return None;
}
};
if p.at_ts(OVERLAPPING_TOKENS)
&& !p.nth_at_ts(1, EXPR_FIRST)
&& !(p.at(IS_KW) && p.nth_at(1, DISTINCT_KW))
{
let m = p.start();
col_label(p);
m.complete(p, AS_NAME);
return Some(lhs);
}
if r.order_by_allowed && p.at(ORDER_KW) {
opt_order_by_clause(p);
}
loop {
let (op_bp, op, associativity) = current_op(p, r);
if op_bp < bp {
break;
}
let m = lhs.precede(p);
p.bump(op);
if matches!(op, COLON_COLON) {
type_name(p);
let cast_expr = m.complete(p, CAST_EXPR);
lhs = postfix_expr(p, cast_expr, true);
continue;
}
let op_bp = match associativity {
Associativity::Left => op_bp + 1,
Associativity::Right => op_bp,
};
let _rhs = expr_bp(p, op_bp, r);
lhs = if matches!(op, FAT_ARROW | COLON_EQ) {
m.complete(p, NAMED_ARG)
} else {
m.complete(p, BIN_EXPR)
};
}
if r.order_by_allowed && p.at(ORDER_KW) {
opt_order_by_clause(p);
}
Some(lhs)
}
fn opt_expr_list(p: &mut Parser) -> bool {
let mut found_expr = false;
while !p.at(COMMA) {
if expr(p).is_none() {
break;
}
found_expr = true;
if !p.eat(COMMA) {
break;
}
}
found_expr
}
const COMPOUND_SELECT_FIRST: TokenSet = TokenSet::new(&[UNION_KW, INTERSECT_KW, EXCEPT_KW]);
fn with_query(p: &mut Parser<'_>) -> CompletedMarker {
if p.at(WITH_KW) {
p.err_and_bump("unexpected WITH");
}
let m = p.start();
name(p);
opt_column_list_with(p, ColumnDefKind::Name);
p.expect(AS_KW);
opt_materialized(p);
p.expect(L_PAREN);
preparable_stmt(p);
p.expect(R_PAREN);
if p.eat(SEARCH_KW) {
if !p.eat(BREADTH_KW) {
p.expect(DEPTH_KW);
}
p.expect(FIRST_KW);
p.expect(BY_KW);
separated(
p,
COMMA,
|| "unexpected comma, expected a column name".to_string(),
NAME_REF_FIRST,
TokenSet::new(&[SET_KW]),
|p| opt_name_ref(p).is_some(),
);
p.expect(SET_KW);
name_ref(p);
}
opt_cycle_clause(p);
m.complete(p, WITH_TABLE)
}
fn opt_cycle_clause(p: &mut Parser<'_>) {
if !p.at(CYCLE_KW) {
return;
}
p.expect(CYCLE_KW);
separated(
p,
COMMA,
|| "unexpected comma, expected a column name".to_string(),
NAME_REF_FIRST,
TokenSet::new(&[SET_KW]),
|p| opt_name_ref(p).is_some(),
);
p.expect(SET_KW);
name_ref(p);
if p.eat(TO_KW) {
expr(p);
p.expect(DEFAULT_KW);
expr(p);
}
p.expect(USING_KW);
name_ref(p);
}
fn opt_materialized(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(NOT_KW) {
p.expect(MATERIALIZED_KW);
m.complete(p, NOT_MATERIALIZED);
} else if p.eat(MATERIALIZED_KW) {
m.complete(p, MATERIALIZED);
} else {
m.abandon(p);
}
}
const WITH_FOLLOW: TokenSet = TokenSet::new(&[
DELETE_KW, SELECT_KW, TABLE_KW, INSERT_KW, UPDATE_KW, MERGE_KW, VALUES_KW,
]);
fn with_query_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
p.expect(WITH_KW);
p.eat(RECURSIVE_KW);
while !p.at(EOF) {
with_query(p);
if p.at(COMMA) && p.nth_at_ts(1, WITH_FOLLOW) {
p.err_and_bump("unexpected comma");
break;
}
if !p.eat(COMMA) {
if p.at_ts(WITH_FOLLOW) || (p.at(L_PAREN) && p.nth_at_ts(1, PAREN_SELECT_FIRST)) {
break;
} else {
p.error("missing comma");
}
}
}
Some(m.complete(p, WITH_CLAUSE))
}
fn select_clause(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.expect(SELECT_KW);
opt_all_or_distinct(p);
opt_target_list(p);
m.complete(p, SELECT_CLAUSE)
}
fn compound_select(p: &mut Parser<'_>, cm: CompletedMarker) -> CompletedMarker {
assert!(p.at_ts(COMPOUND_SELECT_FIRST));
let m = cm.precede(p);
p.bump_any();
if !p.eat(ALL_KW) {
p.eat(DISTINCT_KW);
}
if p.at(L_PAREN) {
opt_paren_select(p, None);
} else {
if p.at_ts(SELECT_FIRST) {
select(
p,
None,
&SelectRestrictions {
trailing_clauses: false,
},
);
} else {
p.error("expected start of a select statement")
}
}
opt_select_trailing_clauses(p);
m.complete(p, COMPOUND_SELECT)
}
fn opt_select_clause(p: &mut Parser<'_>) {
if p.at(SELECT_KW) {
select_clause(p);
}
}
fn select(p: &mut Parser, m: Option<Marker>, r: &SelectRestrictions) -> Option<CompletedMarker> {
assert!(p.at_ts(SELECT_FIRST));
let m = m.unwrap_or_else(|| p.start());
let mut out_kind = SELECT;
if p.at(WITH_KW) {
return with(p, Some(m));
}
if p.at(VALUES_KW) {
let cm = values(p, Some(m));
if p.at_ts(COMPOUND_SELECT_FIRST) {
return Some(compound_select(p, cm));
} else {
return Some(cm);
}
}
if p.eat(TABLE_KW) {
relation_name(p);
out_kind = TABLE;
} else {
if opt_from_clause(p).is_some() {
opt_select_clause(p)
} else {
select_clause(p);
}
}
if opt_into_clause(p).is_some() {
out_kind = SELECT_INTO;
}
opt_from_clause(p);
opt_where_clause(p);
opt_misplaced_joins(p);
opt_group_by_clause(p);
opt_having_clause(p);
opt_window_clause(p);
if p.at_ts(COMPOUND_SELECT_FIRST) {
let cm = m.complete(p, SELECT);
return Some(compound_select(p, cm));
}
if r.trailing_clauses {
opt_select_trailing_clauses(p);
}
Some(m.complete(p, out_kind))
}
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) {
if opt_locking_clause(p).is_some() {
has_locking_clause = true;
}
}
opt_limit_clause(p);
opt_offset_clause(p);
opt_limit_clause(p);
opt_fetch_clause(p);
opt_offset_clause(p);
if !has_locking_clause {
while p.at(FOR_KW) {
opt_locking_clause(p);
}
}
true
}
fn opt_into_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(INTO_KW) {
let m = p.start();
p.bump(INTO_KW);
opt_persistence(p);
p.eat(TABLE_KW);
path_name(p);
Some(m.complete(p, INTO_CLAUSE))
} else {
None
}
}
fn lock_strength(p: &mut Parser<'_>) -> bool {
if p.eat(NO_KW) {
p.expect(KEY_KW);
p.expect(UPDATE_KW)
} else if p.eat(KEY_KW) {
p.expect(SHARE_KW)
} else if !p.eat(SHARE_KW) {
p.expect(UPDATE_KW)
} else {
false
}
}
fn opt_locking_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if !p.eat(FOR_KW) {
m.abandon(p);
return None;
}
lock_strength(p);
if p.eat(OF_KW) {
if !opt_expr_list(p) {
p.error("expected an expression");
}
}
if p.eat(SKIP_KW) {
p.expect(LOCKED_KW)
} else {
p.eat(NOWAIT_KW)
};
Some(m.complete(p, LOCKING_CLAUSE))
}
fn opt_fetch_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(FETCH_KW) {
return None;
}
let m = p.start();
p.bump(FETCH_KW);
if !p.eat(FIRST_KW) && !p.eat(NEXT_KW) {
p.error("expected first or next");
}
if !p.at(ROWS_KW) && !p.at(ROW_KW) {
expr(p);
}
if !p.eat(ROW_KW) {
p.expect(ROWS_KW);
}
if p.eat(WITH_KW) {
p.expect(TIES_KW);
} else {
p.expect(ONLY_KW);
}
Some(m.complete(p, FETCH_CLAUSE))
}
fn opt_order_by_clause(p: &mut Parser<'_>) -> bool {
let m = p.start();
if !p.eat(ORDER_KW) {
m.abandon(p);
return false;
}
p.expect(BY_KW);
sort_by_list(p);
m.complete(p, ORDER_BY_CLAUSE);
true
}
fn sort_by_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
sort_by(p);
if !p.eat(COMMA) {
break;
}
}
m.complete(p, SORT_BY_LIST);
}
fn sort_by(p: &mut Parser<'_>) {
let m = p.start();
expr(p);
opt_sort_order(p);
opt_nulls_order(p);
m.complete(p, SORT_BY);
}
fn opt_sort_order(p: &mut Parser<'_>) {
let m = p.start();
let kind = match p.current() {
ASC_KW => {
p.bump(ASC_KW);
SORT_ASC
}
DESC_KW => {
p.bump(DESC_KW);
SORT_DESC
}
USING_KW => {
p.bump(USING_KW);
operator(p);
SORT_USING
}
_ => {
m.abandon(p);
return;
}
};
m.complete(p, kind);
}
const JOIN_TYPE_FIRST: TokenSet =
TokenSet::new(&[INNER_KW, JOIN_KW, LEFT_KW, RIGHT_KW, FULL_KW, CROSS_KW]);
fn join_type(p: &mut Parser<'_>) -> Option<CompletedMarker> {
assert!(p.at_ts(JOIN_TYPE_FIRST));
let m = p.start();
let kind = match p.current() {
CROSS_KW => {
p.bump(CROSS_KW);
p.expect(JOIN_KW);
JOIN_CROSS
}
INNER_KW | JOIN_KW => {
p.eat(INNER_KW);
p.expect(JOIN_KW);
JOIN_INNER
}
LEFT_KW => {
p.bump(LEFT_KW);
p.eat(OUTER_KW);
p.expect(JOIN_KW);
JOIN_LEFT
}
RIGHT_KW => {
p.bump(RIGHT_KW);
p.eat(OUTER_KW);
p.expect(JOIN_KW);
JOIN_RIGHT
}
FULL_KW => {
p.bump(FULL_KW);
p.eat(OUTER_KW);
p.expect(JOIN_KW);
JOIN_FULL
}
_ => {
p.error("expected join type");
m.abandon(p);
return None;
}
};
Some(m.complete(p, kind))
}
const JOIN_FIRST: TokenSet = TokenSet::new(&[NATURAL_KW, CROSS_KW]).union(JOIN_TYPE_FIRST);
fn opt_from_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if !p.eat(FROM_KW) {
m.abandon(p);
return None;
}
if !opt_from_item(p) {
p.error(format!("expected from item, got {:?}", p.current()));
}
while !p.at(EOF) && p.eat(COMMA) {
if !opt_from_item(p) {
p.error("expected from item");
break;
}
}
Some(m.complete(p, FROM_CLAUSE))
}
const COL_NAME_KEYWORD_FIRST: TokenSet = TokenSet::new(&[
BETWEEN_KW,
BIGINT_KW,
BIT_KW,
BOOLEAN_KW,
CHAR_KW,
CHARACTER_KW,
COALESCE_KW,
DEC_KW,
DECIMAL_KW,
EXISTS_KW,
EXTRACT_KW,
FLOAT_KW,
GREATEST_KW,
GROUPING_KW,
INOUT_KW,
INT_KW,
INTEGER_KW,
INTERVAL_KW,
JSON_KW,
JSON_ARRAY_KW,
JSON_ARRAYAGG_KW,
JSON_EXISTS_KW,
JSON_OBJECT_KW,
JSON_OBJECTAGG_KW,
JSON_QUERY_KW,
JSON_SCALAR_KW,
JSON_SERIALIZE_KW,
JSON_TABLE_KW,
JSON_VALUE_KW,
LEAST_KW,
MERGE_ACTION_KW,
NATIONAL_KW,
NCHAR_KW,
NONE_KW,
NORMALIZE_KW,
NULLIF_KW,
NUMERIC_KW,
OUT_KW,
OVERLAY_KW,
POSITION_KW,
PRECISION_KW,
REAL_KW,
ROW_KW,
SETOF_KW,
SMALLINT_KW,
SUBSTRING_KW,
TIME_KW,
TIMESTAMP_KW,
TREAT_KW,
TRIM_KW,
VALUES_KW,
VARCHAR_KW,
XMLATTRIBUTES_KW,
XMLCONCAT_KW,
XMLELEMENT_KW,
XMLEXISTS_KW,
XMLFOREST_KW,
XMLNAMESPACES_KW,
XMLPARSE_KW,
XMLPI_KW,
XMLROOT_KW,
XMLSERIALIZE_KW,
XMLTABLE_KW,
]);
const FUNC_EXPR_COMMON_SUBEXPR_FIRST: TokenSet = TokenSet::new(&[
CAST_KW,
COALESCE_KW,
COLLATION_KW,
CURRENT_CATALOG_KW,
CURRENT_DATE_KW,
CURRENT_ROLE_KW,
CURRENT_SCHEMA_KW,
CURRENT_TIME_KW,
CURRENT_TIMESTAMP_KW,
CURRENT_USER_KW,
EXTRACT_KW,
GREATEST_KW,
JSON_KW,
JSON_ARRAY_KW,
JSON_ARRAYAGG_KW,
JSON_EXISTS_KW,
JSON_OBJECT_KW,
JSON_OBJECTAGG_KW,
JSON_QUERY_KW,
JSON_SCALAR_KW,
JSON_SERIALIZE_KW,
JSON_TABLE_KW,
JSON_VALUE_KW,
LEAST_KW,
LOCALTIME_KW,
LOCALTIMESTAMP_KW,
MERGE_ACTION_KW,
NORMALIZE_KW,
NULLIF_KW,
OVERLAY_KW,
POSITION_KW,
SESSION_USER_KW,
SUBSTRING_KW,
SYSTEM_USER_KW,
TREAT_KW,
TRIM_KW,
USER_KW,
XMLCONCAT_KW,
XMLELEMENT_KW,
XMLEXISTS_KW,
XMLFOREST_KW,
XMLPARSE_KW,
XMLPI_KW,
XMLROOT_KW,
XMLSERIALIZE_KW,
XMLTABLE_KW,
]);
const FROM_ITEM_KEYWORDS_FIRST: TokenSet = TokenSet::new(&[])
.union(UNRESERVED_KEYWORDS)
.union(COL_NAME_KEYWORD_FIRST)
.union(FUNC_EXPR_COMMON_SUBEXPR_FIRST);
const FROM_ITEM_FIRST: TokenSet = TokenSet::new(&[
ONLY_KW, IDENT, L_PAREN, LATERAL_KW, ROWS_KW, GRAPH_TABLE_KW, ])
.union(FROM_ITEM_KEYWORDS_FIRST);
fn from_item_name(p: &mut Parser<'_>) {
match name_ref_(p).map(|lhs| postfix_expr(p, lhs, true)) {
Some(val) => match val.kind() {
CALL_EXPR => {
if p.eat(WITH_KW) {
p.expect(ORDINALITY_KW);
}
opt_alias(p);
}
NAME_REF | FIELD_EXPR => {
p.eat(STAR);
opt_alias(p);
opt_tablesample_clause(p);
}
got => {
p.error(format!("expected a name, got {got:?}"));
}
},
None => p.error("expected name"),
}
}
fn data_source(p: &mut Parser<'_>) {
p.eat(ONLY_KW);
p.eat(LATERAL_KW);
match p.current() {
L_PAREN => {
paren_data_source(p);
opt_alias(p);
}
JSON_TABLE_KW => {
json_table_fn(p);
opt_alias(p);
}
GRAPH_TABLE_KW => {
graph_table_fn(p);
opt_alias(p);
}
XMLTABLE_KW => {
xml_table_fn(p);
opt_alias(p);
}
ROWS_KW if p.nth_at(1, FROM_KW) => {
p.bump(ROWS_KW);
p.expect(FROM_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
opt_row_from_expr,
);
if p.eat(WITH_KW) {
p.expect(ORDINALITY_KW);
}
opt_alias(p);
}
IDENT => from_item_name(p),
CAST_KW | TREAT_KW => {
if expr(p).is_none() {
p.error("expected expression");
}
opt_alias(p);
}
COLLATION_KW if p.nth_at(1, FOR_KW) => {
collation_for_fn(p);
opt_alias(p);
}
_ if p.at_ts(FROM_ITEM_KEYWORDS_FIRST) => from_item_name(p),
_ => {
p.error("expected table reference");
}
}
}
fn xml_table_fn(p: &mut Parser<'_>) {
assert!(p.at(XMLTABLE_KW));
p.bump(XMLTABLE_KW);
p.expect(L_PAREN);
if p.eat(XMLNAMESPACES_KW) {
xml_namespace_list(p);
p.expect(COMMA);
}
xml_row_passing_clause(p);
xmltable_column_list(p);
p.expect(R_PAREN);
}
fn xml_row_passing_clause(p: &mut Parser<'_>) {
let m = p.start();
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);
m.complete(p, XML_ROW_PASSING_CLAUSE);
}
fn opt_row_from_expr(p: &mut Parser<'_>) -> bool {
if !p.at_ts(EXPR_FIRST) {
return false;
}
call_expr(p);
opt_alias(p);
true
}
fn xmltable_column_list(p: &mut Parser<'_>) {
let m = p.start();
p.expect(COLUMNS_KW);
xmltable_column_el(p);
while !p.at(EOF) && p.eat(COMMA) {
xmltable_column_el(p);
}
m.complete(p, XML_TABLE_COLUMN_LIST);
}
fn xmltable_column_el(p: &mut Parser<'_>) {
let m = p.start();
name(p);
if p.eat(FOR_KW) {
p.expect(ORDINALITY_KW);
} else {
type_name(p);
opt_xmltable_column_option_list(p);
}
m.complete(p, XML_TABLE_COLUMN);
}
fn opt_xmltable_column_option_list(p: &mut Parser<'_>) {
let m = p.start();
if opt_xmltable_column_option_el(p).is_none() {
m.abandon(p);
return;
}
while !p.at(EOF) && opt_xmltable_column_option_el(p).is_some() {}
m.complete(p, XML_COLUMN_OPTION_LIST);
}
fn opt_xmltable_column_option_el(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
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);
}
_ => {
m.abandon(p);
return None;
}
}
Some(m.complete(p, XML_COLUMN_OPTION))
}
fn xml_namespace_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
XML_NAMESPACE_ELEMENT_FIRST,
opt_xml_namespace,
);
m.complete(p, XML_NAMESPACE_LIST);
}
const XML_NAMESPACE_ELEMENT_FIRST: TokenSet = EXPR_FIRST.union(TokenSet::new(&[DEFAULT_KW]));
fn opt_xml_namespace(p: &mut Parser<'_>) -> bool {
if !p.at_ts(XML_NAMESPACE_ELEMENT_FIRST) {
return false;
}
let m = p.start();
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);
}
m.complete(p, XML_NAMESPACE);
true
}
fn paren_data_source(p: &mut Parser<'_>) -> Option<CompletedMarker> {
assert!(p.at(L_PAREN));
if p.at(L_PAREN) && p.nth_at_ts(1, SELECT_FIRST) {
return opt_paren_select(p, None);
}
let m = p.start();
p.bump(L_PAREN);
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 {
p.error("expected table name or SELECT");
}
p.expect(R_PAREN);
Some(m.complete(p, PAREN_EXPR))
}
fn merge_using_clause(p: &mut Parser<'_>) {
let m = p.start();
p.expect(USING_KW);
opt_from_item(p);
if p.at(ON_KW) {
on_clause(p);
} else {
p.error("expected on clause");
}
m.complete(p, USING_ON_CLAUSE);
}
fn opt_from_item(p: &mut Parser<'_>) -> bool {
if !p.at_ts(FROM_ITEM_FIRST) {
return false;
}
let m = p.start();
data_source(p);
let mut cm = m.complete(p, FROM_ITEM);
while p.at_ts(JOIN_FIRST) {
let m = cm.precede(p);
join(p);
cm = m.complete(p, JOIN_EXPR);
}
true
}
fn join(p: &mut Parser<'_>) {
assert!(p.at_ts(JOIN_FIRST));
let m = p.start();
let is_natural = p.eat(NATURAL_KW);
let result = join_type(p);
let join_kind = result.map(|x| x.kind()).unwrap_or(JOIN_INNER);
if !opt_from_item(p) {
p.error("expected from_item");
}
let can_have_on_clause = !is_natural && join_kind != JOIN_CROSS;
if p.at(ON_KW) && can_have_on_clause {
on_clause(p);
} else if p.at(USING_KW) {
join_using_clause(p);
}
m.complete(p, JOIN);
}
fn opt_misplaced_joins(p: &mut Parser<'_>) {
while p.at_ts(JOIN_FIRST) {
let m = p.start();
p.error("JOINs must appear before WHERE");
join(p);
m.complete(p, ERROR);
}
}
fn on_clause(p: &mut Parser<'_>) {
assert!(p.at(ON_KW));
let m = p.start();
p.bump(ON_KW);
clause_expr(p);
m.complete(p, ON_CLAUSE);
}
fn join_using_clause(p: &mut Parser<'_>) {
assert!(p.at(USING_KW));
let m = p.start();
p.expect(USING_KW);
column_ref_list(p);
opt_alias(p);
m.complete(p, JOIN_USING_CLAUSE);
}
#[must_use]
fn opt_numeric_literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at_ts(NUMERIC_FIRST) {
let m = p.start();
p.bump_any();
Some(m.complete(p, LITERAL))
} else if p.at(MINUS) || p.at(PLUS) {
expr(p)
} else {
None
}
}
const SEQUENCE_OPTION_FIRST: TokenSet = TokenSet::new(&[
AS_KW,
CACHE_KW,
INCREMENT_KW,
SEQUENCE_KW,
RESTART_KW,
LOGGED_KW,
UNLOGGED_KW,
START_KW,
OWNED_KW,
OWNED_KW,
MAXVALUE_KW,
MINVALUE_KW,
NO_KW,
CYCLE_KW,
]);
fn opt_sequence_option(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(SEQUENCE_OPTION_FIRST) {
return None;
}
let m = p.start();
match p.current() {
AS_KW => {
p.bump(AS_KW);
type_name(p);
}
INCREMENT_KW => {
p.bump(INCREMENT_KW);
p.eat(BY_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
}
SEQUENCE_KW => {
p.bump(SEQUENCE_KW);
p.expect(NAME_KW);
name_ref(p);
}
RESTART_KW => {
p.bump(RESTART_KW);
if p.eat(WITH_KW) {
if opt_numeric_literal(p).is_none() {
p.error("expected numeric");
}
} else {
let _ = opt_numeric_literal(p);
}
}
LOGGED_KW | UNLOGGED_KW => {
p.bump_any();
}
START_KW => {
p.bump(START_KW);
p.eat(WITH_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric");
}
}
OWNED_KW => {
p.bump(OWNED_KW);
p.expect(BY_KW);
if !p.eat(NONE_KW) {
path_name_ref(p);
}
}
MINVALUE_KW | MAXVALUE_KW | CACHE_KW => {
p.bump_any();
if opt_numeric_literal(p).is_none() {
p.error("expected numeric");
}
}
NO_KW => {
p.bump(NO_KW);
if !p.eat(MINVALUE_KW) && !p.eat(CYCLE_KW) && !p.eat(MAXVALUE_KW) {
p.error("expected MINVALUE, MAXVALUE, or CYCLE");
}
}
CYCLE_KW => {
p.bump(CYCLE_KW);
}
_ => {
m.abandon(p);
return None;
}
}
Some(m.complete(p, SEQUENCE_OPTION))
}
fn opt_sequence_options(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(L_PAREN) {
let m = p.start();
p.bump(L_PAREN);
while !p.at(EOF) {
if opt_sequence_option(p).is_none() {
break;
}
}
p.expect(R_PAREN);
Some(m.complete(p, SEQUENCE_OPTION_LIST))
} else {
None
}
}
#[derive(Clone, Copy)]
enum ColumnDefKind {
Name,
NameRef,
WithData,
}
fn opt_column_list_with(p: &mut Parser<'_>, kind: ColumnDefKind) -> bool {
if !p.at(L_PAREN) ||
!p.nth_at_ts(1, COLUMN_FIRST) && !p.nth_at(1, R_PAREN)
{
return false;
}
let m = p.start();
p.expect(L_PAREN);
while !p.at(EOF) && !p.at(R_PAREN) {
if p.at(COMMA) {
p.err_and_bump("missing column");
continue;
}
if !p.at_ts(COLUMN_FIRST) {
break;
}
column(p, kind);
if p.at(COMMA) && p.nth_at(1, R_PAREN) {
p.err_and_bump("unexpected trailing comma");
}
if !p.eat(COMMA) {
if p.at_ts(COLUMN_FIRST) && !(p.at(WITHOUT_KW) && p.nth_at(1, OVERLAPS_KW)) {
p.error("expected COMMA");
} else {
break;
}
}
}
opt_without_overlaps(p);
p.expect(R_PAREN);
m.complete(p, COLUMN_LIST);
return true;
}
fn column(p: &mut Parser<'_>, kind: ColumnDefKind) -> CompletedMarker {
assert!(p.at_ts(COLUMN_FIRST));
let m = p.start();
match kind {
ColumnDefKind::Name => name(p),
ColumnDefKind::NameRef => {
p.eat(PERIOD_KW);
name_ref(p).map(|lhs| postfix_expr(p, lhs, true));
}
ColumnDefKind::WithData => {
name(p);
if !p.at(COMMA) && !p.at(R_PAREN) {
if !opt_type_name(p) {
return m.complete(p, COLUMN);
}
opt_collate(p);
}
}
}
m.complete(p, COLUMN)
}
fn opt_column_ref_list(p: &mut Parser<'_>) -> bool {
opt_column_list_with(p, ColumnDefKind::NameRef)
}
fn column_ref_list(p: &mut Parser<'_>) {
if !opt_column_ref_list(p) {
p.error("expected column list");
}
}
fn opt_include_columns(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(INCLUDE_KW) {
let m = p.start();
p.bump(INCLUDE_KW);
column_ref_list(p);
Some(m.complete(p, CONSTRAINT_INCLUDE_CLAUSE))
} else {
None
}
}
fn opt_with_params(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(WITH_KW) && p.nth_at(1, L_PAREN) {
let m = p.start();
p.bump(WITH_KW);
attribute_list(p);
Some(m.complete(p, WITH_PARAMS))
} else {
None
}
}
fn opt_index_parameters(p: &mut Parser<'_>) {
opt_include_columns(p);
opt_with_params(p);
if p.at(USING_KW) {
let m = p.start();
p.bump(USING_KW);
p.expect(INDEX_KW);
p.expect(TABLESPACE_KW);
name_ref(p);
m.complete(p, CONSTRAINT_INDEX_TABLESPACE);
}
}
fn referential_action(p: &mut Parser<'_>) {
match p.current() {
NO_KW => {
let m = p.start();
p.bump(NO_KW);
p.expect(ACTION_KW);
m.complete(p, NO_ACTION);
}
CASCADE_KW | RESTRICT_KW => {
opt_cascade_or_restrict(p);
}
SET_KW if p.nth_at(1, NULL_KW) => {
let m = p.start();
p.expect(SET_KW);
p.expect(NULL_KW);
opt_column_ref_list(p);
m.complete(p, SET_NULL_COLUMNS);
}
SET_KW => {
let m = p.start();
p.bump(SET_KW);
p.expect(DEFAULT_KW);
opt_column_ref_list(p);
m.complete(p, SET_DEFAULT_COLUMNS);
}
_ => {
p.error("expected foreign key action");
}
}
}
const COLUMN_CONSTRAINT_FIRST: TokenSet = TokenSet::new(&[
CONSTRAINT_KW,
NOT_KW,
NULL_KW,
CHECK_KW,
DEFAULT_KW,
GENERATED_KW,
UNIQUE_KW,
PRIMARY_KW,
REFERENCES_KW,
]);
fn opt_column_constraint(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(COLUMN_CONSTRAINT_FIRST) {
return None;
}
let m = p.start();
opt_constraint_name(p);
match opt_constraint_inner(p) {
Some(kind) => {
opt_constraint_option_list(p);
Some(m.complete(p, kind))
}
None => {
m.abandon(p);
p.error("expected constraint type");
None
}
}
}
fn opt_column_constraint_list(p: &mut Parser<'_>) {
while !p.at(EOF) {
if opt_column_constraint(p).is_none() {
break;
}
}
}
fn opt_constraint_inner(p: &mut Parser<'_>) -> Option<SyntaxKind> {
let kind = match p.current() {
NOT_KW => {
p.bump(NOT_KW);
p.expect(NULL_KW);
NOT_NULL_CONSTRAINT
}
NULL_KW => {
p.bump(NULL_KW);
NULL_CONSTRAINT
}
CHECK_KW => {
p.bump(CHECK_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
opt_no_inherit(p);
CHECK_CONSTRAINT
}
DEFAULT_KW => {
p.bump(DEFAULT_KW);
if expr(p).is_none() {
p.error("expected expr for default");
}
DEFAULT_CONSTRAINT
}
GENERATED_KW => {
p.bump(GENERATED_KW);
if p.at(ALWAYS_KW) && p.nth_at(1, AS_KW) && p.nth_at(2, L_PAREN) {
p.expect(ALWAYS_KW);
p.expect(AS_KW);
p.expect(L_PAREN);
expr(p);
p.expect(R_PAREN);
opt_virtual_or_stored(p);
GENERATED_CONSTRAINT
} else if p.at(ALWAYS_KW) || p.at(BY_KW) {
if p.eat(BY_KW) {
p.expect(DEFAULT_KW);
} else {
p.expect(ALWAYS_KW);
}
p.expect(AS_KW);
if p.eat(L_PAREN) {
expr(p);
p.expect(R_PAREN);
opt_virtual_or_stored(p);
} else {
p.expect(IDENTITY_KW);
opt_sequence_options(p);
}
GENERATED_CONSTRAINT
} else {
p.error("expected generated type");
return None;
}
}
UNIQUE_KW => {
p.bump(UNIQUE_KW);
opt_nulls_not_distinct(p);
opt_index_parameters(p);
UNIQUE_CONSTRAINT
}
PRIMARY_KW => {
p.bump(PRIMARY_KW);
p.expect(KEY_KW);
opt_index_parameters(p);
PRIMARY_KEY_CONSTRAINT
}
REFERENCES_KW => {
p.bump(REFERENCES_KW);
path_name_ref(p);
if p.eat(L_PAREN) {
name_ref(p);
p.expect(R_PAREN);
}
opt_match_type(p);
opt_foreign_key_actions(p);
REFERENCES_CONSTRAINT
}
_ => {
return None;
}
};
Some(kind)
}
fn opt_match_type(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(MATCH_KW) {
let kind = match p.current() {
FULL_KW => {
p.bump(FULL_KW);
MATCH_FULL
}
PARTIAL_KW => {
p.bump(PARTIAL_KW);
MATCH_PARTIAL
}
SIMPLE_KW => {
p.bump(SIMPLE_KW);
MATCH_SIMPLE
}
_ => {
p.error("expected FULL, PARTIAL, or SIMPLE");
MATCH_SIMPLE
}
};
m.complete(p, kind);
} else {
m.abandon(p);
}
}
fn opt_virtual_or_stored(p: &mut Parser<'_>) {
let _ = p.eat(STORED_KW) || p.eat(VIRTUAL_KW);
}
fn opt_no_inherit(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(NO_KW) {
if p.eat(INHERIT_KW) {
m.complete(p, NO_INHERIT);
}
} else {
m.abandon(p);
}
}
fn opt_foreign_key_actions(p: &mut Parser<'_>) {
if p.at(ON_KW) && p.nth_at(1, DELETE_KW) {
on_delete_action(p);
}
if p.at(ON_KW) && p.nth_at(1, UPDATE_KW) {
on_update_action(p);
}
if p.at(ON_KW) && p.nth_at(1, DELETE_KW) {
on_delete_action(p);
}
}
fn on_update_action(p: &mut Parser<'_>) {
assert!(p.at(ON_KW));
let m = p.start();
p.expect(ON_KW);
p.expect(UPDATE_KW);
referential_action(p);
m.complete(p, ON_UPDATE_ACTION);
}
fn on_delete_action(p: &mut Parser<'_>) {
assert!(p.at(ON_KW));
let m = p.start();
p.expect(ON_KW);
p.expect(DELETE_KW);
referential_action(p);
m.complete(p, ON_DELETE_ACTION);
}
const LIKE_OPTION_FIRST: TokenSet = TokenSet::new(&[
COMMENTS_KW,
COMPRESSION_KW,
CONSTRAINTS_KW,
DEFAULTS_KW,
GENERATED_KW,
IDENTITY_KW,
INDEXES_KW,
STATISTICS_KW,
STORAGE_KW,
ALL_KW,
]);
fn opt_like_option(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(INCLUDING_KW) || p.at(EXCLUDING_KW) {
let m = p.start();
p.bump_any();
if p.at_ts(LIKE_OPTION_FIRST) {
p.bump_any();
} else {
p.err_and_bump(&format!("expected like option, got {:?}", p.current()));
}
Some(m.complete(p, LIKE_OPTION))
} else {
None
}
}
fn opt_index_elem(p: &mut Parser<'_>) -> bool {
if !p.at(L_PAREN) && !p.at_ts(EXPR_FIRST) {
return false;
}
if p.eat(L_PAREN) {
expr(p);
p.expect(R_PAREN);
} else {
if expr(p).is_none() {
p.error("expected expression");
}
}
true
}
fn opt_operator(p: &mut Parser<'_>) -> bool {
let (power, kind, _) = current_op(p, &Restrictions::default());
if power == 0 {
if p.at_ts(OPERATOR_FIRST) {
p.bump_any();
return true;
}
return false;
}
p.eat(kind)
}
fn operator(p: &mut Parser<'_>) {
let m = p.start();
opt_path_name_ref(p);
if !opt_operator(p) {
p.error(format!("expected operator, got {:?}", p.current()));
}
m.complete(p, OP);
}
pub(crate) fn current_operator(p: &Parser<'_>) -> Option<SyntaxKind> {
let (power, kind, _) = current_op(p, &Restrictions::default());
if power == 0 { None } else { Some(kind) }
}
fn using_index(p: &mut Parser<'_>) {
assert!(p.at(USING_KW));
let m = p.start();
p.bump(USING_KW);
p.expect(INDEX_KW);
opt_name_ref(p);
m.complete(p, USING_INDEX);
}
const TABLE_CONSTRAINT_FIRST: TokenSet = TokenSet::new(&[
CONSTRAINT_KW,
CHECK_KW,
UNIQUE_KW,
PRIMARY_KW,
EXCLUDE_KW,
FOREIGN_KW,
NOT_KW,
]);
fn table_constraint(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at_ts(TABLE_CONSTRAINT_FIRST));
let m = p.start();
opt_constraint_name(p);
let kind = match p.current() {
CHECK_KW => {
p.bump(CHECK_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expr");
}
p.expect(R_PAREN);
CHECK_CONSTRAINT
}
UNIQUE_KW => {
p.bump(UNIQUE_KW);
if p.at(USING_KW) {
using_index(p);
} else {
opt_nulls_not_distinct(p);
column_ref_list(p);
opt_index_parameters(p);
}
UNIQUE_CONSTRAINT
}
PRIMARY_KW => {
p.bump(PRIMARY_KW);
p.expect(KEY_KW);
if p.at(USING_KW) {
using_index(p);
} else {
column_ref_list(p);
opt_index_parameters(p);
}
PRIMARY_KEY_CONSTRAINT
}
EXCLUDE_KW => {
p.bump(EXCLUDE_KW);
opt_constraint_index_method(p);
constraint_exclusion_list(p);
opt_index_parameters(p);
opt_constraint_where_clause(p);
EXCLUDE_CONSTRAINT
}
NOT_KW => {
p.bump(NOT_KW);
p.expect(NULL_KW);
name_ref(p);
NOT_NULL_CONSTRAINT
}
_ => {
p.expect(FOREIGN_KW);
p.expect(KEY_KW);
column_ref_list(p);
p.expect(REFERENCES_KW);
path_name_ref(p);
opt_column_ref_list(p);
opt_match_type(p);
opt_foreign_key_actions(p);
FOREIGN_KEY_CONSTRAINT
}
};
let cm = m.complete(p, kind);
opt_constraint_option_list(p);
cm
}
fn opt_nulls_not_distinct(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(NULLS_KW) {
let kind = if p.eat(NOT_KW) {
NULLS_NOT_DISTINCT
} else {
NULLS_DISTINCT
};
p.eat(DISTINCT_KW);
m.complete(p, kind);
} else {
m.abandon(p);
}
}
fn opt_constraint_where_clause(p: &mut Parser<'_>) {
if p.at(WHERE_KW) {
let m = p.start();
p.bump(WHERE_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expr");
}
p.expect(R_PAREN);
m.complete(p, WHERE_CONDITION_CLAUSE);
}
}
const CONSTRAINT_EXCLUSION_FIRST: TokenSet = EXPR_FIRST.union(TokenSet::new(&[L_PAREN]));
fn opt_constraint_exclusion(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if !opt_index_elem(p) {
m.abandon(p);
return None;
}
p.expect(WITH_KW);
operator(p);
Some(m.complete(p, CONSTRAINT_EXCLUSION))
}
fn constraint_exclusion_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
CONSTRAINT_EXCLUSION_FIRST,
|p| opt_constraint_exclusion(p).is_some(),
);
m.complete(p, CONSTRAINT_EXCLUSION_LIST);
}
fn opt_constraint_index_method(p: &mut Parser<'_>) {
if p.at(USING_KW) {
let m = p.start();
p.bump(USING_KW);
name_ref(p);
m.complete(p, CONSTRAINT_INDEX_METHOD);
}
}
fn opt_without_overlaps(p: &mut Parser<'_>) {
if p.eat(WITHOUT_KW) {
p.expect(OVERLAPS_KW);
}
}
fn opt_constraint_option_list(p: &mut Parser<'_>) {
while !p.at(EOF) {
let m = p.start();
let kind = match (p.current(), p.nth(1)) {
(DEFERRABLE_KW, _) => {
p.bump(DEFERRABLE_KW);
DEFERRABLE_CONSTRAINT_OPTION
}
(NOT_KW, DEFERRABLE_KW) => {
p.bump(NOT_KW);
p.bump(DEFERRABLE_KW);
NOT_DEFERRABLE_CONSTRAINT_OPTION
}
(INITIALLY_KW, DEFERRED_KW) => {
p.bump(INITIALLY_KW);
p.bump(DEFERRED_KW);
INITIALLY_DEFERRED_CONSTRAINT_OPTION
}
(INITIALLY_KW, IMMEDIATE_KW) => {
p.bump(INITIALLY_KW);
p.bump(IMMEDIATE_KW);
INITIALLY_IMMEDIATE_CONSTRAINT_OPTION
}
(NOT_KW, VALID_KW) => {
p.bump(NOT_KW);
p.bump(VALID_KW);
NOT_VALID
}
(NO_KW, INHERIT_KW) => {
p.bump(NO_KW);
p.bump(INHERIT_KW);
NO_INHERIT
}
(INHERIT_KW, _) => {
p.bump(INHERIT_KW);
INHERIT
}
(NOT_KW, ENFORCED_KW) => {
p.bump(NOT_KW);
p.bump(ENFORCED_KW);
NOT_ENFORCED
}
(ENFORCED_KW, _) => {
p.bump(ENFORCED_KW);
ENFORCED
}
(_, _) => {
m.abandon(p);
break;
}
};
m.complete(p, kind);
}
}
const COLUMN_NAME_KEYWORDS: TokenSet = TokenSet::new(&[
BETWEEN_KW,
BIGINT_KW,
BIT_KW,
BOOLEAN_KW,
CHAR_KW,
CHARACTER_KW,
COALESCE_KW,
DEC_KW,
DECIMAL_KW,
EXISTS_KW,
EXTRACT_KW,
FLOAT_KW,
GREATEST_KW,
GROUPING_KW,
INOUT_KW,
INT_KW,
INTEGER_KW,
INTERVAL_KW,
JSON_KW,
JSON_ARRAY_KW,
JSON_ARRAYAGG_KW,
JSON_EXISTS_KW,
JSON_OBJECT_KW,
JSON_OBJECTAGG_KW,
JSON_QUERY_KW,
JSON_SCALAR_KW,
JSON_SERIALIZE_KW,
JSON_TABLE_KW,
JSON_VALUE_KW,
LEAST_KW,
MERGE_ACTION_KW,
NATIONAL_KW,
NCHAR_KW,
NONE_KW,
NORMALIZE_KW,
NULLIF_KW,
NUMERIC_KW,
OUT_KW,
OVERLAY_KW,
POSITION_KW,
PRECISION_KW,
REAL_KW,
ROW_KW,
SETOF_KW,
SMALLINT_KW,
SUBSTRING_KW,
TIME_KW,
TIMESTAMP_KW,
TREAT_KW,
TRIM_KW,
VALUES_KW,
VARCHAR_KW,
XMLATTRIBUTES_KW,
XMLCONCAT_KW,
XMLELEMENT_KW,
XMLEXISTS_KW,
XMLFOREST_KW,
XMLNAMESPACES_KW,
XMLPARSE_KW,
XMLPI_KW,
XMLROOT_KW,
XMLSERIALIZE_KW,
XMLTABLE_KW,
]);
const COL_DEF_FIRST: TokenSet = TokenSet::new(&[LIKE_KW])
.union(TABLE_CONSTRAINT_FIRST)
.union(NAME_FIRST);
fn opt_col_def(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(COL_DEF_FIRST) {
return None;
}
if p.at(LIKE_KW) {
return Some(like_clause(p));
}
if p.at_ts(TABLE_CONSTRAINT_FIRST) {
return Some(table_constraint(p));
}
let m = p.start();
name(p);
if opt_type_name(p) {
opt_storage(p);
opt_compression_method(p);
}
opt_with_options(p);
opt_alter_option_list(p);
opt_collate(p);
opt_column_constraint_list(p);
Some(m.complete(p, COLUMN))
}
fn opt_compression_method(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(COMPRESSION_KW) && (p.at(DEFAULT_KW) || p.at(IDENT)) {
if !opt_ident(p) && !p.eat(DEFAULT_KW) {
p.error("expected default or identifier");
}
Some(m.complete(p, COMPRESSION_METHOD))
} else {
m.abandon(p);
None
}
}
fn opt_storage(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(STORAGE_KW) && (p.at(DEFAULT_KW) || p.at(EXTERNAL_KW) || p.at(IDENT)) {
if !opt_ident(p) {
p.bump_any();
}
Some(m.complete(p, STORAGE))
} else {
m.abandon(p);
None
}
}
fn like_clause(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(LIKE_KW));
let m = p.start();
p.bump(LIKE_KW);
path_name_ref(p);
while !p.at(EOF) {
if opt_like_option(p).is_none() {
break;
}
}
m.complete(p, LIKE_CLAUSE)
}
fn opt_alias(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !(p.at(AS_KW) || p.at_ts(NAME_FIRST) || p.at(L_PAREN)) {
return None;
}
let m = p.start();
p.eat(AS_KW);
opt_name(p);
if p.at(L_PAREN) {
if !opt_column_list_with(p, ColumnDefKind::WithData) {
p.error("expected column list");
}
}
Some(m.complete(p, ALIAS))
}
fn opt_tablesample_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(TABLESAMPLE_KW) {
return None;
}
let m = p.start();
p.bump(TABLESAMPLE_KW);
call_expr(p);
opt_repeatable_clause(p);
Some(m.complete(p, TABLESAMPLE_CLAUSE))
}
fn opt_repeatable_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(REPEATABLE_KW) {
return None;
}
let m = p.start();
p.bump(REPEATABLE_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected a seed");
}
p.expect(R_PAREN);
Some(m.complete(p, REPEATABLE_CLAUSE))
}
fn clause_expr(p: &mut Parser<'_>) {
if p.at(AND_KW) || p.at(OR_KW) {
p.err_and_bump(&format!("expected expression but got {:?}", p.current()));
}
expr(p);
}
fn opt_where_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(WHERE_KW) {
return None;
}
let m = p.start();
p.bump(WHERE_KW);
clause_expr(p);
Some(m.complete(p, WHERE_CLAUSE))
}
fn opt_group_by_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if !p.eat(GROUP_KW) {
m.abandon(p);
return None;
}
p.expect(BY_KW);
if p.at(ALL_KW) || p.at(DISTINCT_KW) {
p.bump_any();
}
opt_group_by_list(p);
Some(m.complete(p, GROUP_BY_CLAUSE))
}
fn opt_group_by_list(p: &mut Parser<'_>) {
let m = p.start();
let mut found_item = false;
while !p.at(EOF) {
if opt_group_by_item(p).is_none() {
break;
}
found_item = true;
if !p.eat(COMMA) {
break;
}
}
if found_item {
m.complete(p, GROUP_BY_LIST);
} else {
m.abandon(p);
}
}
const GROUP_BY_ITEM_FIRST: TokenSet =
TokenSet::new(&[ROLLUP_KW, CUBE_KW, GROUPING_KW]).union(EXPR_FIRST);
fn opt_group_by_item(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(GROUP_BY_ITEM_FIRST) {
return None;
}
let m = p.start();
let kind = match p.current() {
ROLLUP_KW => {
p.bump_any();
paren_expr_list(p);
GROUPING_ROLLUP
}
CUBE_KW => {
p.bump_any();
paren_expr_list(p);
GROUPING_CUBE
}
GROUPING_KW if p.nth_at(1, SETS_KW) => {
p.bump(GROUPING_KW);
p.bump(SETS_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
GROUP_BY_ITEM_FIRST,
|p| opt_group_by_item(p).is_some(),
);
GROUPING_SETS
}
_ => {
expr(p);
GROUPING_EXPR
}
};
Some(m.complete(p, kind))
}
fn opt_having_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(HAVING_KW) {
return None;
}
let m = p.start();
p.bump(HAVING_KW);
clause_expr(p);
Some(m.complete(p, HAVING_CLAUSE))
}
fn frame_start_end(p: &mut Parser<'_>) {
match (p.current(), p.nth(1)) {
(CURRENT_KW, ROW_KW) | (UNBOUNDED_KW, PRECEDING_KW | FOLLOWING_KW) => {
p.bump_any();
p.bump_any();
}
_ => {
expr(p);
if p.at(PRECEDING_KW) || p.at(FOLLOWING_KW) {
p.bump_any();
} else {
p.err_and_bump("expected preceding or following");
}
}
}
}
fn opt_frame_exclusion(p: &mut Parser<'_>) -> bool {
if !p.eat(EXCLUDE_KW) {
return false;
}
if p.eat(CURRENT_KW) {
p.expect(ROW_KW)
} else if p.eat(NO_KW) {
p.expect(OTHERS_KW)
} else if p.at(GROUP_KW) || p.at(TIES_KW) {
p.bump_any();
true
} else {
p.err_and_bump("expected `group`, `current row`, `ties`, or `no others`");
false
}
}
const WINDOW_DEF_START: TokenSet =
TokenSet::new(&[IDENT, PARTITION_KW, ORDER_KW, RANGE_KW, ROWS_KW, GROUPS_KW]);
fn window_spec(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(WINDOW_DEF_START) {
return None;
}
let m = p.start();
opt_ident(p);
if p.eat(PARTITION_KW) {
p.expect(BY_KW);
if !opt_expr_list(p) {
p.error("expected expression")
}
}
opt_order_by_clause(p);
opt_frame_clause(p);
Some(m.complete(p, WINDOW_SPEC))
}
fn opt_frame_clause(p: &mut Parser<'_>) {
if p.at(RANGE_KW) || p.at(ROWS_KW) || p.at(GROUPS_KW) {
let m = p.start();
p.bump_any();
if p.eat(BETWEEN_KW) {
frame_start_end(p);
p.expect(AND_KW);
frame_start_end(p);
opt_frame_exclusion(p);
} else {
frame_start_end(p);
opt_frame_exclusion(p);
}
m.complete(p, FRAME_CLAUSE);
}
}
fn opt_window_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(WINDOW_KW) {
return None;
}
let m = p.start();
p.bump(WINDOW_KW);
window_def(p);
while !p.at(EOF) && p.eat(COMMA) {
window_def(p);
}
Some(m.complete(p, WINDOW_CLAUSE))
}
fn window_def(p: &mut Parser<'_>) {
let m = p.start();
name(p);
p.expect(AS_KW);
p.expect(L_PAREN);
window_spec(p);
p.expect(R_PAREN);
m.complete(p, WINDOW_DEF);
}
fn opt_limit_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if !p.eat(LIMIT_KW) {
m.abandon(p);
return None;
}
if !p.eat(ALL_KW) {
expr(p);
}
Some(m.complete(p, LIMIT_CLAUSE))
}
fn opt_offset_clause(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at(OFFSET_KW) {
return None;
}
let m = p.start();
p.bump(OFFSET_KW);
expr(p);
if p.at(ROW_KW) || p.at(ROWS_KW) {
p.bump_any();
}
Some(m.complete(p, OFFSET_CLAUSE))
}
fn opt_all_or_distinct(p: &mut Parser) {
if p.eat(ALL_KW) {
return;
}
let m = p.start();
if p.eat(DISTINCT_KW) {
if p.eat(ON_KW) {
paren_expr_list(p);
}
m.complete(p, DISTINCT_CLAUSE);
} else {
m.abandon(p);
}
}
fn paren_expr_list(p: &mut Parser<'_>) {
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
|p| opt_expr(p).is_some(),
);
}
const COL_LABEL_FIRST: TokenSet = TokenSet::new(&[IDENT])
.union(UNRESERVED_KEYWORDS)
.union(COLUMN_NAME_KEYWORDS)
.union(TYPE_FUNC_NAME_KEYWORDS)
.union(RESERVED_KEYWORDS);
const NAME_FIRST: TokenSet = TokenSet::new(&[IDENT])
.union(UNRESERVED_KEYWORDS)
.union(COLUMN_NAME_KEYWORDS);
const BARE_COL_LABEL_FIRST: TokenSet = TokenSet::new(&[IDENT]).union(BARE_LABEL_KEYWORDS);
const TARGET_LIST_START: TokenSet = TokenSet::new(&[STAR])
.union(COL_LABEL_FIRST)
.union(EXPR_FIRST)
.union(TYPE_KEYWORDS);
const LITERAL_FIRST: TokenSet = TokenSet::new(&[TRUE_KW, FALSE_KW, NULL_KW, DEFAULT_KW])
.union(NUMERIC_FIRST)
.union(STRING_FIRST);
const NUMERIC_FIRST: TokenSet = TokenSet::new(&[INT_NUMBER, FLOAT_NUMBER]);
const STRING_FIRST: TokenSet = TokenSet::new(&[
STRING,
BYTE_STRING,
UNICODE_ESC_STRING,
BIT_STRING,
DOLLAR_QUOTED_STRING,
ESC_STRING,
]);
pub(crate) const OPERATOR_FIRST: TokenSet = TokenSet::new(&[
PLUS, MINUS, STAR, SLASH, L_ANGLE, R_ANGLE, EQ, TILDE, BANG, AT, POUND, PERCENT, CARET, AMP,
PIPE, BACKTICK, QUESTION,
]);
const LHS_FIRST: TokenSet = TokenSet::new(&[
L_PAREN,
L_BRACK,
CAST_KW,
NOT_KW,
IS_KW,
POSITIONAL_PARAM,
CASE_KW,
ARRAY_KW,
ROW_KW,
DEFAULT_KW,
COLON,
ALL_KW,
ANY_KW,
SOME_KW,
])
.union(OPERATOR_FIRST)
.union(LITERAL_FIRST)
.union(TYPE_KEYWORDS)
.union(IDENTS);
const IDENTS: TokenSet = TokenSet::new(&[IDENT]).union(FUNC_KEYWORDS);
const FUNC_KEYWORDS: TokenSet = TokenSet::new(&[
CURRENT_DATE_KW,
CURRENT_TIME_KW,
CURRENT_TIMESTAMP_KW,
LOCALTIME_KW,
LOCALTIMESTAMP_KW,
CURRENT_ROLE_KW,
CURRENT_USER_KW,
SESSION_USER_KW,
SYSTEM_USER_KW,
USER_KW,
CURRENT_CATALOG_KW,
CURRENT_SCHEMA_KW,
]);
const NAME_REF_FIRST: TokenSet = TYPE_KEYWORDS.union(IDENTS);
const EXPR_FIRST: TokenSet = LHS_FIRST;
const TARGET_FOLLOW: TokenSet = TokenSet::new(&[
SELECT_KW,
FROM_KW,
WHERE_KW,
LIMIT_KW,
ORDER_KW,
OFFSET_KW,
GROUP_KW,
INTO_KW,
HAVING_KW,
WINDOW_KW,
HAVING_KW,
FETCH_KW,
FOR_KW,
R_PAREN,
R_BRACK,
RETURNING_KW,
SEMICOLON,
EOF,
CREATE_KW,
DO_KW,
CREATE_KW,
GRANT_KW,
END_KW,
ANALYZE_KW,
ANALYSE_KW,
WITH_KW,
])
.union(COMPOUND_SELECT_FIRST);
const TARGET_FIRST: TokenSet = EXPR_FIRST;
fn opt_target_el(p: &mut Parser) -> Option<CompletedMarker> {
let m = p.start();
if p.at_ts(TARGET_FOLLOW) {
m.abandon(p);
return None;
} else if p.at(STAR) && !p.nth_at_ts(1, OPERATOR_FIRST) {
p.bump(STAR);
} else if expr(p).is_some() {
opt_as_col_label(p);
} else {
m.abandon(p);
p.error(format!(
"expected an expression in target_el, found {:?}",
p.current()
));
return None;
};
Some(m.complete(p, TARGET))
}
fn opt_as_col_label(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(AS_KW) {
if p.at_ts(COL_LABEL_FIRST) {
col_label(p);
m.complete(p, AS_NAME);
} else {
p.err_and_bump(&format!("expected column label, got {:?}", p.current()));
m.abandon(p);
}
} else if p.at(FORMAT_KW) && p.nth_at(1, JSON_KW) {
m.abandon(p);
} else if p.at_ts(BARE_COL_LABEL_FIRST) {
col_label(p);
m.complete(p, AS_NAME);
} else {
m.abandon(p);
}
}
fn opt_target_list(p: &mut Parser) -> Option<CompletedMarker> {
if !p.at_ts(TARGET_LIST_START) || p.at_ts(TARGET_FOLLOW) {
return None;
}
let m = p.start();
while !p.at(EOF) && !p.at(SEMICOLON) {
if opt_target_el(p).is_some() {
if p.at(COMMA) && p.nth_at_ts(1, TARGET_FOLLOW) {
p.err_and_bump("unexpected trailing comma");
break;
}
if !p.eat(COMMA) {
if p.at(FORMAT_KW) && p.nth_at(1, JSON_KW) {
break;
}
if p.at(RETURNING_KW) && p.nth_at(1, TEXT_KW) {
break;
}
if p.at_ts(TARGET_FIRST) {
p.error("missing comma");
} else {
break;
}
}
} else {
break;
}
}
Some(m.complete(p, TARGET_LIST))
}
fn opt_if_not_exists(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(IF_KW) {
let m = p.start();
p.bump(IF_KW);
p.expect(NOT_KW);
p.expect(EXISTS_KW);
Some(m.complete(p, IF_NOT_EXISTS))
} else {
None
}
}
fn opt_if_exists(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(IF_KW) {
let m = p.start();
p.bump(IF_KW);
p.expect(EXISTS_KW);
Some(m.complete(p, IF_EXISTS))
} else {
None
}
}
const DROP_TABLE_FOLLOW: TokenSet = TokenSet::new(&[CASCADE_KW, RESTRICT_KW]);
fn drop_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, TABLE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(TABLE_KW);
opt_if_exists(p);
separated(
p,
COMMA,
|| "unexpected comma, expected a name".to_string(),
PATH_FIRST,
DROP_TABLE_FOLLOW,
|p| opt_path_name_ref(p).is_some(),
);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TABLE)
}
fn partition_item(p: &mut Parser<'_>, allow_extra_params: bool) -> CompletedMarker {
let m = p.start();
if expr(p).is_none() {
p.error("expected expr")
}
opt_collate(p);
opt_ident(p);
if allow_extra_params {
if p.at(L_PAREN) {
attribute_list(p);
}
opt_sort_order(p);
opt_nulls_order(p);
}
m.complete(p, PARTITION_ITEM)
}
fn opt_partition_item(p: &mut Parser<'_>, allow_extra_params: bool) -> Option<CompletedMarker> {
if !p.at_ts(EXPR_FIRST) {
return None;
}
Some(partition_item(p, allow_extra_params))
}
fn opt_nulls_order(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(NULLS_KW) {
let kind = match p.current() {
FIRST_KW => {
p.bump(FIRST_KW);
NULLS_FIRST
}
LAST_KW => {
p.bump(LAST_KW);
NULLS_LAST
}
_ => {
p.error("expected FIRST or LAST");
NULLS_LAST
}
};
m.complete(p, kind);
} else {
m.abandon(p);
}
}
fn table_arg_list(p: &mut Parser<'_>) -> Option<CompletedMarker> {
assert!(p.at(L_PAREN));
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
COL_DEF_FIRST,
|p| opt_col_def(p).is_some(),
);
Some(m.complete(p, TABLE_ARG_LIST))
}
fn partition_option(p: &mut Parser<'_>) {
let m = p.start();
let kind = if p.eat(FOR_KW) {
p.expect(VALUES_KW);
if p.eat(WITH_KW) {
p.expect(L_PAREN);
ident(p);
p.expect(INT_NUMBER);
p.expect(COMMA);
ident(p);
p.expect(INT_NUMBER);
p.expect(R_PAREN);
PARTITION_FOR_VALUES_WITH
} else if p.eat(IN_KW) {
paren_expr_list(p);
PARTITION_FOR_VALUES_IN
} else if p.eat(FROM_KW) {
paren_expr_list(p);
p.expect(TO_KW);
paren_expr_list(p);
PARTITION_FOR_VALUES_FROM
} else {
p.error("expected partition option");
PARTITION_DEFAULT
}
} else {
p.expect(DEFAULT_KW);
PARTITION_DEFAULT
};
m.complete(p, kind);
}
fn opt_inherits_tables(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(INHERITS_KW) {
p.expect(L_PAREN);
path_name_ref_list(p);
p.expect(R_PAREN);
m.complete(p, INHERITS);
} else {
m.abandon(p);
}
}
fn create_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.expect(CREATE_KW);
opt_persistence(p);
p.expect(TABLE_KW);
opt_if_not_exists(p);
path_name(p);
let mut is_partition = false;
if p.at(OF_KW) {
of_type(p);
} else if p.at(PARTITION_KW) {
partition_of(p);
is_partition = true;
}
if p.at(L_PAREN) {
table_arg_list(p);
}
if is_partition {
partition_option(p);
}
opt_inherits_tables(p);
opt_partition_by(p);
opt_using_method(p);
if opt_with_params(p).is_none() {
opt_without_oids(p);
}
opt_on_commit(p);
opt_tablespace(p);
if p.eat(AS_KW) {
match stmt(p, &StmtRestrictions::default()).map(|x| x.kind()) {
Some(
SELECT | COMPOUND_SELECT | SELECT_INTO | PAREN_SELECT | TABLE | VALUES | EXECUTE,
) => (),
_ => {
p.error("expected SELECT, TABLE, VALUES, or EXECUTE");
}
}
opt_with_data(p);
return m.complete(p, CREATE_TABLE_AS);
}
m.complete(p, CREATE_TABLE)
}
fn opt_persistence(p: &mut Parser<'_>) -> bool {
let m = p.start();
if p.eat(UNLOGGED_KW) {
m.complete(p, UNLOGGED);
return true;
}
let require_temp = p.eat(GLOBAL_KW) || p.eat(LOCAL_KW);
if require_temp {
if !opt_temp(p) {
p.error("expected temp or temporary");
}
m.complete(p, TEMP);
true
} else if opt_temp(p) {
m.complete(p, TEMP);
true
} else {
m.abandon(p);
false
}
}
fn of_type(p: &mut Parser<'_>) {
assert!(p.at(OF_KW));
let m = p.start();
p.bump(OF_KW);
simple_type_name(p);
m.complete(p, OF_TYPE);
}
fn partition_of(p: &mut Parser<'_>) {
assert!(p.at(PARTITION_KW));
let m = p.start();
p.bump(PARTITION_KW);
p.expect(OF_KW);
path_name_ref(p);
m.complete(p, PARTITION_OF);
}
fn opt_with_data(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(WITH_KW) {
let kind = if p.eat(NO_KW) {
WITH_NO_DATA
} else {
WITH_DATA
};
p.expect(DATA_KW);
Some(m.complete(p, kind))
} else {
m.abandon(p);
None
}
}
fn rename_to(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(RENAME_KW));
let m = p.start();
p.bump(RENAME_KW);
p.expect(TO_KW);
name(p);
m.complete(p, RENAME_TO)
}
fn owner_to(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(OWNER_KW));
let m = p.start();
p.bump(OWNER_KW);
p.expect(TO_KW);
role_ref(p);
m.complete(p, OWNER_TO)
}
fn opt_tablespace(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(TABLESPACE_KW) {
name_ref(p);
Some(m.complete(p, TABLESPACE))
} else {
m.abandon(p);
None
}
}
fn opt_without_oids(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(WITHOUT_KW) {
p.expect(OIDS_KW);
Some(m.complete(p, WITHOUT_OIDS))
} else {
m.abandon(p);
None
}
}
fn opt_using_method(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(USING_KW) {
name_ref(p);
Some(m.complete(p, USING_METHOD))
} else {
m.abandon(p);
None
}
}
fn opt_partition_by(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(PARTITION_KW) {
p.expect(BY_KW);
if p.at_ts(TYPE_KEYWORDS) || p.at(IDENT) {
if !opt_ident(p) {
p.bump_any();
}
}
partition_items(p, false);
Some(m.complete(p, PARTITION_BY))
} else {
m.abandon(p);
None
}
}
fn on_commit_action(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
let kind = if p.eat(PRESERVE_KW) {
p.expect(ROWS_KW);
PRESERVE_ROWS
} else if p.eat(DELETE_KW) {
p.expect(ROWS_KW);
DELETE_ROWS
} else if p.eat(DROP_KW) {
DROP
} else {
p.error("expected PRESERVE ROWS, DELETE ROWS, or DROP");
m.abandon(p);
return None;
};
Some(m.complete(p, kind))
}
fn opt_on_commit(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(ON_KW) {
p.expect(COMMIT_KW);
on_commit_action(p);
Some(m.complete(p, ON_COMMIT))
} else {
m.abandon(p);
None
}
}
fn commit(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(COMMIT_KW) || p.at(END_KW));
let m = p.start();
p.bump_any();
if p.eat(PREPARED_KW) {
string_literal(p);
} else {
let _ = p.eat(WORK_KW) || p.eat(TRANSACTION_KW);
if p.eat(AND_KW) {
p.eat(NO_KW);
p.expect(CHAIN_KW);
}
}
m.complete(p, COMMIT)
}
const TRANSACTION_MODE_FIRST: TokenSet =
TokenSet::new(&[ISOLATION_KW, READ_KW, NOT_KW, DEFERRABLE_KW]);
fn opt_transaction_mode(p: &mut Parser<'_>) -> bool {
if !p.at_ts(TRANSACTION_MODE_FIRST) {
return false;
}
let m = p.start();
let kind = if p.eat(ISOLATION_KW) {
p.expect(LEVEL_KW);
if p.eat(SERIALIZABLE_KW) {
SERIALIZABLE
} else if p.eat(REPEATABLE_KW) {
p.expect(READ_KW);
REPEATABLE_READ
} else if p.eat(READ_KW) {
if p.eat(UNCOMMITTED_KW) {
READ_UNCOMMITTED
} else {
p.expect(COMMITTED_KW);
READ_COMMITTED
}
} else {
p.error("expected isolation level");
READ_COMMITTED
}
} else if p.eat(READ_KW) {
if p.eat(WRITE_KW) {
READ_WRITE
} else {
p.expect(ONLY_KW);
READ_ONLY
}
} else {
let kind = if p.eat(NOT_KW) {
NOT_DEFERRABLE
} else {
DEFERRABLE
};
p.expect(DEFERRABLE_KW);
kind
};
m.complete(p, kind);
true
}
fn begin(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(BEGIN_KW) || p.at(START_KW));
let m = p.start();
if p.eat(BEGIN_KW) {
let _ = p.eat(WORK_KW) || p.eat(TRANSACTION_KW);
opt_transaction_mode_list(p);
} else {
p.bump(START_KW);
p.expect(TRANSACTION_KW);
opt_transaction_mode_list(p);
}
m.complete(p, BEGIN)
}
fn opt_string_literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at_ts(STRING_FIRST) {
literal(p)
} else {
None
}
}
fn string_literal(p: &mut Parser<'_>) {
if opt_string_literal(p).is_none() {
p.error("expected string literal");
}
}
const BOOL_FIRST: TokenSet = TokenSet::new(&[TRUE_KW, FALSE_KW, OFF_KW, ON_KW, INT_NUMBER]);
fn opt_bool_literal(p: &mut Parser<'_>) -> bool {
let m = p.start();
if p.at_ts(BOOL_FIRST) {
p.bump_any();
m.complete(p, LITERAL);
true
} else {
m.abandon(p);
false
}
}
fn prepare_transaction(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(PREPARE_KW));
let m = p.start();
p.bump(PREPARE_KW);
p.expect(TRANSACTION_KW);
string_literal(p);
m.complete(p, PREPARE_TRANSACTION)
}
fn savepoint(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SAVEPOINT_KW));
let m = p.start();
p.bump(SAVEPOINT_KW);
name(p);
m.complete(p, SAVEPOINT)
}
fn release(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(RELEASE_KW));
let m = p.start();
p.bump(RELEASE_KW);
p.eat(SAVEPOINT_KW);
name_ref(p);
m.complete(p, RELEASE_SAVEPOINT)
}
fn rollback(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ROLLBACK_KW) || p.at(ABORT_KW));
let m = p.start();
let is_rollback = p.at(ROLLBACK_KW);
p.bump_any();
if p.eat(PREPARED_KW) {
string_literal(p);
return m.complete(p, ROLLBACK);
}
let _ = p.eat(WORK_KW) || p.eat(TRANSACTION_KW);
if is_rollback && p.eat(TO_KW) {
p.eat(SAVEPOINT_KW);
name_ref(p);
} else if p.eat(AND_KW) {
p.eat(NO_KW);
p.expect(CHAIN_KW);
}
m.complete(p, ROLLBACK)
}
#[derive(Default)]
struct StmtRestrictions {
begin_end_allowed: bool,
}
fn stmt(p: &mut Parser, r: &StmtRestrictions) -> Option<CompletedMarker> {
match (p.current(), p.nth(1)) {
(ABORT_KW, _) => Some(rollback(p)),
(ALTER_KW, AGGREGATE_KW) => Some(alter_aggregate(p)),
(ALTER_KW, COLLATION_KW) => Some(alter_collation(p)),
(ALTER_KW, CONVERSION_KW) => Some(alter_conversion(p)),
(ALTER_KW, DATABASE_KW) => Some(alter_database(p)),
(ALTER_KW, DEFAULT_KW) if p.nth_at(2, PRIVILEGES_KW) => Some(alter_default_privileges(p)),
(ALTER_KW, DOMAIN_KW) => Some(alter_domain(p)),
(ALTER_KW, EVENT_KW) if p.nth_at(2, TRIGGER_KW) => Some(alter_event_trigger(p)),
(ALTER_KW, EXTENSION_KW) => Some(alter_extension(p)),
(ALTER_KW, FOREIGN_KW) if p.nth_at(2, DATA_KW) => Some(alter_foreign_data_wrapper(p)),
(ALTER_KW, FOREIGN_KW) if p.nth_at(2, TABLE_KW) => Some(alter_foreign_table(p)),
(ALTER_KW, FUNCTION_KW) => Some(alter_function(p)),
(ALTER_KW, GROUP_KW) => Some(alter_group(p)),
(ALTER_KW, INDEX_KW) => Some(alter_index(p)),
(ALTER_KW, LARGE_KW) if p.nth_at(2, OBJECT_KW) => Some(alter_large_object(p)),
(ALTER_KW, MATERIALIZED_KW) if p.nth_at(2, VIEW_KW) => Some(alter_materialized_view(p)),
(ALTER_KW, OPERATOR_KW) if p.nth_at(2, CLASS_KW) => Some(alter_operator_class(p)),
(ALTER_KW, OPERATOR_KW) if p.nth_at(2, FAMILY_KW) => Some(alter_operator_family(p)),
(ALTER_KW, OPERATOR_KW) => Some(alter_operator(p)),
(ALTER_KW, POLICY_KW) => Some(alter_policy(p)),
(ALTER_KW, PROPERTY_KW) => Some(alter_property_graph(p)),
(ALTER_KW, PROCEDURAL_KW | LANGUAGE_KW) => Some(alter_language(p)),
(ALTER_KW, PROCEDURE_KW) => Some(alter_procedure(p)),
(ALTER_KW, PUBLICATION_KW) => Some(alter_publication(p)),
(ALTER_KW, ROLE_KW) => Some(alter_role(p)),
(ALTER_KW, ROUTINE_KW) => Some(alter_routine(p)),
(ALTER_KW, RULE_KW) => Some(alter_rule(p)),
(ALTER_KW, SCHEMA_KW) => Some(alter_schema(p)),
(ALTER_KW, SEQUENCE_KW) => Some(alter_sequence(p)),
(ALTER_KW, SERVER_KW) => Some(alter_server(p)),
(ALTER_KW, STATISTICS_KW) => Some(alter_statistics(p)),
(ALTER_KW, SUBSCRIPTION_KW) => Some(alter_subscription(p)),
(ALTER_KW, SYSTEM_KW) => Some(alter_system(p)),
(ALTER_KW, TABLE_KW) => Some(alter_table(p)),
(ALTER_KW, TABLESPACE_KW) => Some(alter_tablespace(p)),
(ALTER_KW, TEXT_KW) if p.nth_at(2, SEARCH_KW) => match p.nth(3) {
CONFIGURATION_KW => Some(alter_text_search_configuration(p)),
DICTIONARY_KW => Some(alter_text_search_dict(p)),
PARSER_KW => Some(alter_text_search_parser(p)),
TEMPLATE_KW => Some(alter_text_search_template(p)),
_ => {
p.error("expected TEMPLATE, CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE");
None
}
},
(ALTER_KW, TRIGGER_KW) => Some(alter_trigger(p)),
(ALTER_KW, TYPE_KW) => Some(alter_type(p)),
(ALTER_KW, USER_KW) if p.nth_at(2, MAPPING_KW) => Some(alter_user_mapping(p)),
(ALTER_KW, USER_KW) => Some(alter_user(p)),
(ALTER_KW, VIEW_KW) => Some(alter_view(p)),
(ANALYZE_KW | ANALYSE_KW, _) => Some(analyze(p)),
(BEGIN_KW, _) if r.begin_end_allowed => Some(begin(p)),
(CALL_KW, _) => Some(call(p)),
(CHECKPOINT_KW, _) => Some(checkpoint(p)),
(CLOSE_KW, _) => Some(close(p)),
(CLUSTER_KW, _) => Some(cluster(p)),
(COMMENT_KW, _) => Some(comment(p)),
(COMMIT_KW, _) => Some(commit(p)),
(COPY_KW, _) => Some(copy(p)),
(CREATE_KW, ACCESS_KW) => Some(create_access_method(p)),
(CREATE_KW, AGGREGATE_KW) => Some(create_aggregate(p)),
(CREATE_KW, CAST_KW) => Some(create_cast(p)),
(CREATE_KW, COLLATION_KW) => Some(create_collation(p)),
(CREATE_KW, CONVERSION_KW | DEFAULT_KW) => Some(create_conversion(p)),
(CREATE_KW, DATABASE_KW) => Some(create_database(p)),
(CREATE_KW, DOMAIN_KW) => Some(create_domain(p)),
(CREATE_KW, EVENT_KW) => Some(create_event_trigger(p)),
(CREATE_KW, EXTENSION_KW) => Some(create_extension(p)),
(CREATE_KW, FOREIGN_KW) => match p.nth(2) {
DATA_KW => Some(create_foreign_data_wrapper(p)),
_ => Some(create_foreign_table(p)),
},
(CREATE_KW, FUNCTION_KW) => Some(create_function(p)),
(CREATE_KW, GROUP_KW) => Some(create_group(p)),
(CREATE_KW, INDEX_KW | UNIQUE_KW) => Some(create_index(p)),
(CREATE_KW, LANGUAGE_KW) => Some(create_language(p)),
(CREATE_KW, MATERIALIZED_KW) => Some(create_materialized_view(p)),
(CREATE_KW, OPERATOR_KW) => match p.nth(2) {
CLASS_KW => Some(create_operator_class(p)),
FAMILY_KW => Some(create_operator_family(p)),
_ => Some(create_operator(p)),
},
(CREATE_KW, OR_KW) => {
match p.nth(3) {
AGGREGATE_KW => Some(create_aggregate(p)),
CONSTRAINT_KW | TRIGGER_KW => Some(create_trigger(p)),
PROCEDURAL_KW | TRUSTED_KW | LANGUAGE_KW => Some(create_language(p)),
PROCEDURE_KW => Some(create_procedure(p)),
RECURSIVE_KW | TEMP_KW | TEMPORARY_KW | VIEW_KW => Some(create_view(p)),
RULE_KW => Some(create_rule(p)),
TRANSFORM_KW => Some(create_transform(p)),
_ => Some(create_function(p)),
}
}
(CREATE_KW, PROPERTY_KW) => Some(create_property_graph(p)),
(CREATE_KW, POLICY_KW) => Some(create_policy(p)),
(CREATE_KW, PROCEDURE_KW) => Some(create_procedure(p)),
(CREATE_KW, PUBLICATION_KW) => Some(create_publication(p)),
(CREATE_KW, RECURSIVE_KW | VIEW_KW) => Some(create_view(p)),
(CREATE_KW, ROLE_KW) => Some(create_role(p)),
(CREATE_KW, RULE_KW) => Some(create_rule(p)),
(CREATE_KW, SCHEMA_KW) => Some(create_schema(p)),
(CREATE_KW, SEQUENCE_KW) => Some(create_sequence(p)),
(CREATE_KW, SERVER_KW) => Some(create_server(p)),
(CREATE_KW, STATISTICS_KW) => Some(create_statistics(p)),
(CREATE_KW, SUBSCRIPTION_KW) => Some(create_subscription(p)),
(CREATE_KW, UNLOGGED_KW) if p.nth_at(2, PROPERTY_KW) => Some(create_property_graph(p)),
(CREATE_KW, LOCAL_KW | GLOBAL_KW) if p.nth_at(3, PROPERTY_KW) => {
Some(create_property_graph(p))
}
(CREATE_KW, TABLE_KW | GLOBAL_KW | LOCAL_KW | UNLOGGED_KW) if !p.nth_at(2, SEQUENCE_KW) => {
Some(create_table(p))
}
(CREATE_KW, TABLESPACE_KW) => Some(create_tablespace(p)),
(CREATE_KW, TEMP_KW | TEMPORARY_KW) => {
match p.nth(2) {
RECURSIVE_KW | VIEW_KW => Some(create_view(p)),
SEQUENCE_KW => Some(create_sequence(p)),
PROPERTY_KW => Some(create_property_graph(p)),
_ => Some(create_table(p)),
}
}
(CREATE_KW, TEXT_KW) if p.nth_at(2, SEARCH_KW) => match p.nth(3) {
CONFIGURATION_KW => Some(create_text_search_config(p)),
DICTIONARY_KW => Some(create_text_search_dict(p)),
PARSER_KW => Some(create_text_search_parser(p)),
TEMPLATE_KW => Some(create_text_search_template(p)),
_ => {
p.error("expected TEMPLATE, CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE");
None
}
},
(CREATE_KW, TRANSFORM_KW) => Some(create_transform(p)),
(CREATE_KW, TYPE_KW) => Some(create_type(p)),
(CREATE_KW, UNLOGGED_KW) if p.nth_at(2, SEQUENCE_KW) => Some(create_sequence(p)),
(CREATE_KW, USER_KW) if p.nth_at(2, MAPPING_KW) => Some(create_user_mapping(p)),
(CREATE_KW, USER_KW) => Some(create_user(p)),
(CREATE_KW, CONSTRAINT_KW | TRIGGER_KW) => Some(create_trigger(p)),
(DEALLOCATE_KW, _) => Some(deallocate(p)),
(DECLARE_KW, _) => Some(declare(p)),
(DELETE_KW, _) => Some(delete(p, None)),
(DISCARD_KW, _) => Some(discard(p)),
(DO_KW, _) => Some(do_(p)),
(DROP_KW, ACCESS_KW) => Some(drop_access_method(p)),
(DROP_KW, AGGREGATE_KW) => Some(drop_aggregate(p)),
(DROP_KW, CAST_KW) => Some(drop_cast(p)),
(DROP_KW, COLLATION_KW) => Some(drop_collation(p)),
(DROP_KW, CONVERSION_KW) => Some(drop_conversion(p)),
(DROP_KW, DATABASE_KW) => Some(drop_database(p)),
(DROP_KW, DOMAIN_KW) => Some(drop_domain(p)),
(DROP_KW, EVENT_KW) => Some(drop_event_trigger(p)),
(DROP_KW, EXTENSION_KW) => Some(drop_extension(p)),
(DROP_KW, FOREIGN_KW) => match p.nth(2) {
DATA_KW => Some(drop_foreign_data(p)),
TABLE_KW => Some(drop_foreign_table(p)),
_ => {
p.error("expected DATA or TABLE");
None
}
},
(DROP_KW, FUNCTION_KW) => Some(drop_function(p)),
(DROP_KW, GROUP_KW) => Some(drop_group(p)),
(DROP_KW, INDEX_KW) => Some(drop_index(p)),
(DROP_KW, LANGUAGE_KW | PROCEDURAL_KW) => Some(drop_language(p)),
(DROP_KW, MATERIALIZED_KW) => Some(drop_materialized_view(p)),
(DROP_KW, OPERATOR_KW) => match p.nth(2) {
CLASS_KW => Some(drop_operator_class(p)),
FAMILY_KW => Some(drop_operator_family(p)),
_ => Some(drop_operator(p)),
},
(DROP_KW, OWNED_KW) => Some(drop_owned(p)),
(DROP_KW, PROPERTY_KW) => Some(drop_property_graph(p)),
(DROP_KW, POLICY_KW) => Some(drop_policy(p)),
(DROP_KW, PROCEDURE_KW) => Some(drop_procedure(p)),
(DROP_KW, PUBLICATION_KW) => Some(drop_publication(p)),
(DROP_KW, ROLE_KW) => Some(drop_role(p)),
(DROP_KW, ROUTINE_KW) => Some(drop_routine(p)),
(DROP_KW, RULE_KW) => Some(drop_rule(p)),
(DROP_KW, SCHEMA_KW) => Some(drop_schema(p)),
(DROP_KW, SEQUENCE_KW) => Some(drop_sequence(p)),
(DROP_KW, SERVER_KW) => Some(drop_server(p)),
(DROP_KW, STATISTICS_KW) => Some(drop_statistics(p)),
(DROP_KW, SUBSCRIPTION_KW) => Some(drop_subscription(p)),
(DROP_KW, TABLE_KW) => Some(drop_table(p)),
(DROP_KW, TABLESPACE_KW) => Some(drop_tablespace(p)),
(DROP_KW, TEXT_KW) if p.nth_at(2, SEARCH_KW) => match p.nth(3) {
CONFIGURATION_KW => Some(drop_text_search_config(p)),
DICTIONARY_KW => Some(drop_text_search_dict(p)),
PARSER_KW => Some(drop_text_search_parser(p)),
TEMPLATE_KW => Some(drop_text_search_template(p)),
_ => {
p.error("expected TEMPLATE, CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE");
None
}
},
(DROP_KW, TRANSFORM_KW) => Some(drop_transform(p)),
(DROP_KW, TRIGGER_KW) => Some(drop_trigger(p)),
(DROP_KW, TYPE_KW) => Some(drop_type(p)),
(DROP_KW, USER_KW) => {
if p.nth_at(2, MAPPING_KW) {
Some(drop_user_mapping(p))
} else {
Some(drop_user(p))
}
}
(DROP_KW, VIEW_KW) => Some(drop_view(p)),
(END_KW, _) if r.begin_end_allowed => Some(commit(p)),
(EXECUTE_KW, _) => Some(execute(p)),
(EXPLAIN_KW, _) => Some(explain(p)),
(FETCH_KW, _) => Some(fetch(p)),
(GRANT_KW, _) => Some(grant(p)),
(IMPORT_KW, FOREIGN_KW) => Some(import_foreign_schema(p)),
(INSERT_KW, _) => Some(insert(p, None)),
(L_PAREN, _) if p.nth_at_ts(1, PAREN_SELECT_FIRST) => {
opt_paren_select(p, None)
}
(LISTEN_KW, _) => Some(listen(p)),
(LOAD_KW, _) => Some(load(p)),
(LOCK_KW, _) => Some(lock(p)),
(MERGE_KW, _) => Some(merge(p, None)),
(MOVE_KW, _) => Some(move_(p)),
(NOTIFY_KW, _) => Some(notify(p)),
(PREPARE_KW, TRANSACTION_KW) => Some(prepare_transaction(p)),
(PREPARE_KW, _) => Some(prepare(p)),
(REPACK_KW, _) => Some(repack(p)),
(REASSIGN_KW, _) => Some(reassign(p)),
(REFRESH_KW, _) => Some(refresh(p)),
(REINDEX_KW, _) => Some(reindex(p)),
(RELEASE_KW, _) => Some(release(p)),
(RESET_KW, ROLE_KW) => Some(set_role(p)),
(RESET_KW, SESSION_KW) => Some(reset_session_auth(p)),
(RESET_KW, _) => Some(reset(p)),
(REVOKE_KW, _) => Some(revoke(p)),
(ROLLBACK_KW, _) => Some(rollback(p)),
(SAVEPOINT_KW, _) => Some(savepoint(p)),
(SECURITY_KW, LABEL_KW) => Some(security_label(p)),
(SELECT_KW | TABLE_KW | VALUES_KW | FROM_KW, _) => {
select(p, None, &SelectRestrictions::default())
}
(SET_KW, CONSTRAINTS_KW) => Some(set_constraints(p)),
(SET_KW, LOCAL_KW) => match p.nth(2) {
ROLE_KW => Some(set_role(p)),
SESSION_KW => Some(set_session_auth(p)),
_ => Some(set(p)),
},
(SET_KW, ROLE_KW) => Some(set_role(p)),
(SET_KW, SESSION_KW) => match p.nth(2) {
AUTHORIZATION_KW | SESSION_KW => Some(set_session_auth(p)),
CHARACTERISTICS_KW => Some(set_transaction(p)),
ROLE_KW => Some(set_role(p)),
_ => Some(set(p)),
},
(SET_KW, TRANSACTION_KW) => Some(set_transaction(p)),
(SET_KW, TIME_KW | _) => Some(set(p)),
(SHOW_KW, _) => Some(show(p)),
(START_KW, TRANSACTION_KW) => Some(begin(p)),
(TRUNCATE_KW, _) => Some(truncate(p)),
(UNLISTEN_KW, _) => Some(unlisten(p)),
(UPDATE_KW, _) => Some(update(p, None)),
(VACUUM_KW, _) => Some(vacuum(p)),
(WITH_KW, _) => with(p, None),
(command, _) => {
p.err_and_bump(&format!("expected command, found {command:?}"));
None
}
}
}
fn alter_statistics(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, STATISTICS_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(STATISTICS_KW);
path_name_ref(p);
match p.current() {
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
SET_KW => {
p.bump(SET_KW);
if p.eat(STATISTICS_KW) {
if !p.eat(DEFAULT_KW) {
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
}
} else {
p.error("expected SCHEMA or STATISTICS");
}
}
_ => {
p.error("expected OWNER, RENAME, or SET");
}
}
m.complete(p, ALTER_STATISTICS)
}
fn alter_server(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, SERVER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(SERVER_KW);
name_ref(p);
match p.current() {
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
let mut found_option = false;
if p.eat(VERSION_KW) {
string_literal(p);
found_option = true;
}
found_option |= opt_alter_option_list(p);
if !found_option {
p.error("expected ALTER SERVER option");
}
}
}
m.complete(p, ALTER_SERVER)
}
fn alter_sequence(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, SEQUENCE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(SEQUENCE_KW);
opt_if_exists(p);
path_name_ref(p);
match p.current() {
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
SET_KW => {
p.bump(SET_KW);
if !p.eat(LOGGED_KW) && !p.eat(UNLOGGED_KW) {
p.error("LOGGED or UNLOGGED");
}
}
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
let mut found_option = false;
while !p.at(EOF) {
if opt_sequence_option(p).is_none() {
break;
}
found_option = true;
}
if !found_option {
p.error("expected ALTER SEQUENCE option");
}
}
}
m.complete(p, ALTER_SEQUENCE)
}
fn alter_schema(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, SCHEMA_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(SCHEMA_KW);
name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
_ => {
p.error("expected RENAME or OWNER");
}
}
m.complete(p, ALTER_SCHEMA)
}
fn alter_rule(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, RULE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(RULE_KW);
name_ref(p);
on_table(p);
rename_to(p);
m.complete(p, ALTER_RULE)
}
fn alter_routine(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, ROUTINE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(ROUTINE_KW);
function_sig(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
NO_KW | DEPENDS_KW => {
depends_on_extension(p);
}
_ => {
func_option_list(p);
}
}
p.eat(RESTRICT_KW);
m.complete(p, ALTER_ROUTINE)
}
fn alter_role(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, ROLE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(ROLE_KW);
if !p.eat(ALL_KW) {
role_ref(p);
}
match p.current() {
RENAME_KW => {
rename_to(p);
}
IN_KW | SET_KW | RESET_KW => {
if p.eat(IN_KW) {
p.expect(DATABASE_KW);
name_ref(p);
}
if p.at(SET_KW) {
set_configuration_param(p);
} else if p.eat(RESET_KW) {
if !p.eat(ALL_KW) {
path_name_ref(p);
}
}
}
_ => {
opt_role_option_list(p);
}
}
m.complete(p, ALTER_ROLE)
}
fn alter_publication(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, PUBLICATION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(PUBLICATION_KW);
name_ref(p);
match p.current() {
ADD_KW | DROP_KW => {
p.bump_any();
publication_object(p);
while !p.at(EOF) && p.eat(COMMA) {
publication_object(p);
}
}
SET_KW if p.nth_at(1, L_PAREN) => {
set_options(p);
}
SET_KW if p.nth_at(1, ALL_KW) => {
p.bump(SET_KW);
publication_all_object(p);
while !p.at(EOF) && p.eat(COMMA) {
publication_all_object(p);
}
opt_except_table_clause(p);
}
SET_KW => {
p.bump(SET_KW);
publication_object(p);
while !p.at(EOF) && p.eat(COMMA) {
publication_object(p);
}
}
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
p.error("expected ADD, SET, DROP, OWNER, or RENAME");
}
}
m.complete(p, ALTER_PUBLICATION)
}
fn alter_procedure(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, PROCEDURE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(PROCEDURE_KW);
function_sig(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
DEPENDS_KW | NO_KW => {
p.eat(NO_KW);
p.expect(DEPENDS_KW);
p.expect(ON_KW);
p.expect(EXTENSION_KW);
path_name_ref(p);
}
_ => {
func_option_list(p);
p.eat(RESTRICT_KW);
}
}
m.complete(p, ALTER_PROCEDURE)
}
fn alter_policy(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, POLICY_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(POLICY_KW);
name_ref(p);
on_table(p);
if p.at(RENAME_KW) {
rename_to(p);
} else {
if p.eat(TO_KW) {
role_list(p);
}
opt_using_expr_clause(p);
opt_with_check_expr_clause(p);
}
m.complete(p, ALTER_POLICY)
}
fn opt_using_expr_clause(p: &mut Parser<'_>) {
if p.at(USING_KW) {
let m = p.start();
p.bump(USING_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
m.complete(p, USING_EXPR_CLAUSE);
}
}
fn role_list(p: &mut Parser<'_>) {
let m = p.start();
role_ref(p);
while !p.at(EOF) && p.eat(COMMA) {
role_ref(p);
}
m.complete(p, ROLE_REF_LIST);
}
fn alter_operator_family(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, OPERATOR_KW) && p.nth_at(2, FAMILY_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(OPERATOR_KW);
p.bump(FAMILY_KW);
path_name_ref(p);
p.expect(USING_KW);
name_ref(p);
match p.current() {
ADD_KW => {
let m = p.start();
p.bump(ADD_KW);
operator_class_option_list(p);
m.complete(p, ADD_OP_CLASS_OPTIONS);
}
DROP_KW => {
let m = p.start();
p.bump(DROP_KW);
drop_operator_class_option_list(p);
m.complete(p, DROP_OP_CLASS_OPTIONS);
}
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected ADD, DROP, RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_OPERATOR_FAMILY)
}
fn drop_operator_class_option_list(p: &mut Parser<'_>) {
let m = p.start();
operator_drop_class_option(p);
while !p.at(EOF) && p.eat(COMMA) {
operator_drop_class_option(p);
}
m.complete(p, DROP_OP_CLASS_OPTION_LIST);
}
fn operator_class_option_list(p: &mut Parser<'_>) {
let m = p.start();
operator_class_option(p);
while !p.at(EOF) && p.eat(COMMA) {
operator_class_option(p);
}
m.complete(p, OPERATOR_CLASS_OPTION_LIST);
}
fn alter_operator_class(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, OPERATOR_KW) && p.nth_at(2, CLASS_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(OPERATOR_KW);
p.bump(CLASS_KW);
path_name_ref(p);
p.expect(USING_KW);
name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_OPERATOR_CLASS)
}
fn alter_operator(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, OPERATOR_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(OPERATOR_KW);
operator_sig(p);
match p.current() {
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
SET_KW => {
set_options(p);
}
_ => {
p.error("expected OWNER or SET");
}
}
m.complete(p, ALTER_OPERATOR)
}
fn alter_materialized_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, MATERIALIZED_KW) && p.nth_at(2, VIEW_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(MATERIALIZED_KW);
p.bump(VIEW_KW);
if p.eat(ALL_KW) {
p.expect(IN_KW);
p.expect(TABLESPACE_KW);
name_ref(p);
opt_owned_by_roles(p);
p.expect(SET_KW);
p.expect(TABLESPACE_KW);
name(p);
p.eat(NOWAIT_KW);
} else {
opt_if_exists(p);
path_name_ref(p);
match p.current() {
RENAME_KW if p.nth_at(1, TO_KW) => {
rename_to(p);
}
RENAME_KW => {
let m = p.start();
p.bump(RENAME_KW);
p.eat(COLUMN_KW);
name_ref(p);
p.expect(TO_KW);
name(p);
m.complete(p, RENAME_COLUMN);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
DEPENDS_KW | NO_KW => {
depends_on_extension(p);
}
ALTER_KW | CLUSTER_KW | SET_KW | RESET_KW | OWNER_KW => {
opt_alter_table_action_list(p);
}
_ => {
p.error("Expected RENAME, SET SCHEMA, [NO] DEPENDS, or action (ALTER, CLUSTER, SET, RESET, OWNER)");
}
}
}
m.complete(p, ALTER_MATERIALIZED_VIEW)
}
fn depends_on_extension(p: &mut Parser<'_>) {
assert!(p.at(NO_KW) || p.at(DEPENDS_KW));
let m = p.start();
let kind = if p.eat(NO_KW) {
NO_DEPENDS_ON_EXTENSION
} else {
DEPENDS_ON_EXTENSION
};
p.expect(DEPENDS_KW);
p.expect(ON_KW);
p.expect(EXTENSION_KW);
name_ref(p);
m.complete(p, kind);
}
fn opt_alter_table_action_list(p: &mut Parser<'_>) {
while !p.at(EOF) {
if opt_alter_table_action(p).is_none() {
break;
};
if !p.eat(COMMA) {
if p.at_ts(ALTER_TABLE_ACTION_FIRST) {
p.error("missing comma");
} else {
break;
}
}
}
}
fn alter_large_object(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, LARGE_KW) && p.nth_at(2, OBJECT_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(LARGE_KW);
p.bump(OBJECT_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
p.expect(OWNER_KW);
p.expect(TO_KW);
role_ref(p);
m.complete(p, ALTER_LARGE_OBJECT)
}
fn alter_language(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && (p.nth_at(1, PROCEDURAL_KW) || p.nth_at(1, LANGUAGE_KW)));
let m = p.start();
p.bump(ALTER_KW);
p.eat(PROCEDURAL_KW);
p.expect(LANGUAGE_KW);
name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
_ => {
p.error("expected RENAME or OWNER");
}
}
m.complete(p, ALTER_LANGUAGE)
}
fn alter_index(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, INDEX_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(INDEX_KW);
if p.eat(ALL_KW) {
p.expect(IN_KW);
p.expect(TABLESPACE_KW);
path_name_ref(p);
if p.eat(OWNED_KW) {
p.expect(BY_KW);
role_list(p);
}
p.expect(SET_KW);
p.expect(TABLESPACE_KW);
name_ref(p);
p.eat(NOWAIT_KW);
} else {
opt_if_exists(p);
path_name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
SET_KW if p.nth_at(1, L_PAREN) => {
set_options(p);
}
SET_KW => {
let m = p.start();
p.bump(SET_KW);
p.expect(TABLESPACE_KW);
path_name_ref(p);
m.complete(p, SET_TABLESPACE);
}
ATTACH_KW => {
let m = p.start();
p.bump(ATTACH_KW);
p.expect(PARTITION_KW);
path_name_ref(p);
m.complete(p, ATTACH_PARTITION);
}
DEPENDS_KW | NO_KW => {
let m = p.start();
let kind = if p.eat(NO_KW) {
NO_DEPENDS_ON_EXTENSION
} else {
DEPENDS_ON_EXTENSION
};
p.bump(DEPENDS_KW);
p.expect(ON_KW);
p.expect(EXTENSION_KW);
path_name_ref(p);
m.complete(p, kind);
}
RESET_KW => {
reset_options(p);
}
ALTER_KW => {
let m = p.start();
p.bump(ALTER_KW);
p.eat(COLUMN_KW);
if opt_numeric_literal(p).is_none() && opt_name_ref(p).is_none() {
p.error("expected numeric literal or name");
}
if p.at(SET_KW) && p.nth_at(1, L_PAREN) {
set_options(p);
} else {
p.expect(SET_KW);
p.expect(STATISTICS_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
}
m.complete(p, ALTER_SET_STATISTICS);
}
_ => {
p.error("expected RENAME, SET, ATTACH, DEPENDS, RESET, or ALTER");
}
}
}
m.complete(p, ALTER_INDEX)
}
fn alter_group(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, GROUP_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(GROUP_KW);
role_ref(p);
match p.current() {
ADD_KW | DROP_KW => {
p.bump_any();
p.expect(USER_KW);
name_ref_list(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
p.error("expected ADD, DROP, or RENAME");
}
}
m.complete(p, ALTER_GROUP)
}
fn alter_function(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, FUNCTION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(FUNCTION_KW);
function_sig(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
DEPENDS_KW | NO_KW => {
p.eat(NO_KW);
p.expect(DEPENDS_KW);
p.expect(ON_KW);
p.expect(EXTENSION_KW);
name_ref(p);
}
_ => {
func_option_list(p);
}
}
p.eat(RESTRICT_KW);
m.complete(p, ALTER_FUNCTION)
}
fn alter_foreign_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, FOREIGN_KW) && p.nth_at(2, TABLE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(FOREIGN_KW);
p.bump(TABLE_KW);
opt_if_exists(p);
relation_name(p);
match p.current() {
RENAME_KW if p.nth_at(1, TO_KW) => {
rename_to(p);
}
RENAME_KW => {
let m = p.start();
p.bump(RENAME_KW);
p.eat(COLUMN_KW);
name_ref(p);
p.expect(TO_KW);
name(p);
m.complete(p, RENAME_COLUMN);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
_ => {
opt_alter_table_action_list(p);
}
}
m.complete(p, ALTER_FOREIGN_TABLE)
}
fn alter_foreign_data_wrapper(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(ALTER_KW)
&& p.nth_at(1, FOREIGN_KW)
&& p.nth_at(2, DATA_KW)
&& p.nth_at(3, WRAPPER_KW)
);
let m = p.start();
p.bump(ALTER_KW);
p.bump(FOREIGN_KW);
p.bump(DATA_KW);
p.bump(WRAPPER_KW);
name_ref(p);
let found_option = match p.current() {
OWNER_KW => {
owner_to(p);
true
}
RENAME_KW => {
rename_to(p);
true
}
_ => opt_fdw_option_list(p).is_some(),
};
if !found_option {
p.error("Missing alter foreign data wrapper option or action.")
}
m.complete(p, ALTER_FOREIGN_DATA_WRAPPER)
}
fn alter_event_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, EVENT_KW) && p.nth_at(2, TRIGGER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(EVENT_KW);
p.bump(TRIGGER_KW);
name_ref(p);
match p.current() {
DISABLE_KW => {
p.bump(DISABLE_KW);
}
ENABLE_KW => {
p.bump(ENABLE_KW);
let _ = p.eat(REPLICA_KW) || p.eat(ALWAYS_KW);
}
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
p.error("expected DISABLE, ENABLE, OWNER, or RENAME");
}
}
m.complete(p, ALTER_EVENT_TRIGGER)
}
fn alter_extension(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, EXTENSION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(EXTENSION_KW);
name_ref(p);
match p.current() {
UPDATE_KW => {
p.bump(UPDATE_KW);
if p.eat(TO_KW) {
if p.at_ts(NON_RESERVED_WORD) {
p.bump_any();
} else {
string_literal(p);
}
}
}
SET_KW => {
set_schema(p);
}
ADD_KW | DROP_KW => {
p.bump_any();
match p.current() {
SCHEMA_KW | DOMAIN_KW | TABLE_KW | TYPE_KW | EXTENSION_KW | PUBLICATION_KW
| SERVER_KW | DATABASE_KW | ROLE_KW | SUBSCRIPTION_KW | TABLESPACE_KW => {
p.bump_any();
name_ref(p);
}
COLLATION_KW | CONVERSION_KW | SEQUENCE_KW | VIEW_KW | INDEX_KW | STATISTICS_KW => {
p.bump_any();
path_name_ref(p);
}
ACCESS_KW => {
p.bump(ACCESS_KW);
p.expect(METHOD_KW);
name_ref(p);
}
AGGREGATE_KW => {
p.bump(AGGREGATE_KW);
aggregate(p);
}
CAST_KW => {
p.bump(CAST_KW);
cast_sig(p);
}
EVENT_KW => {
p.bump(EVENT_KW);
p.expect(TRIGGER_KW);
name_ref(p);
}
FOREIGN_KW => {
p.bump(FOREIGN_KW);
if p.eat(DATA_KW) {
p.expect(WRAPPER_KW);
name_ref(p);
} else {
p.expect(TABLE_KW);
path_name_ref(p);
}
}
FUNCTION_KW | PROCEDURE_KW | ROUTINE_KW => {
p.bump_any();
function_sig(p);
}
MATERIALIZED_KW => {
p.bump(MATERIALIZED_KW);
p.expect(VIEW_KW);
path_name_ref(p);
}
OPERATOR_KW => {
p.bump(OPERATOR_KW);
match p.current() {
CLASS_KW => {
p.bump(CLASS_KW);
name_ref(p);
p.expect(USING_KW);
name_ref(p);
}
FAMILY_KW => {
p.bump(FAMILY_KW);
name_ref(p);
p.expect(USING_KW);
name_ref(p);
}
_ => {
operator(p);
p.expect(L_PAREN);
type_name(p);
p.expect(COMMA);
type_name(p);
p.expect(R_PAREN);
}
}
}
LANGUAGE_KW | PROCEDURAL_KW => {
p.eat(PROCEDURAL_KW);
p.bump(LANGUAGE_KW);
name_ref(p);
}
TEXT_KW => {
p.bump(TEXT_KW);
p.expect(SEARCH_KW);
match p.current() {
CONFIGURATION_KW => {
p.bump(CONFIGURATION_KW);
path_name_ref(p);
}
DICTIONARY_KW => {
p.bump(DICTIONARY_KW);
path_name_ref(p);
}
PARSER_KW => {
p.bump(PARSER_KW);
path_name_ref(p);
}
TEMPLATE_KW => {
p.bump(TEMPLATE_KW);
path_name_ref(p);
}
_ => {
p.error("expected CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE after TEXT SEARCH");
}
}
}
TRANSFORM_KW => {
p.bump(TRANSFORM_KW);
p.expect(FOR_KW);
name_ref(p);
p.expect(LANGUAGE_KW);
name_ref(p);
}
_ => {
p.error("expected valid extension member object type");
}
}
}
_ => {
p.error("expected UPDATE, SET, ADD, or DROP");
}
}
m.complete(p, ALTER_EXTENSION)
}
fn alter_domain(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, DOMAIN_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(DOMAIN_KW);
path_name_ref(p);
alter_domain_action(p);
m.complete(p, ALTER_DOMAIN)
}
fn alter_domain_action(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
let action = match p.current() {
SET_KW if p.nth_at(1, SCHEMA_KW) => {
m.abandon(p);
return Some(set_schema(p));
}
SET_KW => {
p.bump(SET_KW);
match p.current() {
DEFAULT_KW => {
p.bump(DEFAULT_KW);
if expr(p).is_none() {
p.error("expected expression");
}
SET_DEFAULT
}
NOT_KW => {
p.bump(NOT_KW);
p.expect(NULL_KW);
SET_NOT_NULL
}
_ => {
p.error("expected DEFAULT, NOT, or SCHEMA");
m.abandon(p);
return None;
}
}
}
DROP_KW => {
p.bump(DROP_KW);
match p.current() {
DEFAULT_KW => {
p.bump(DEFAULT_KW);
DROP_DEFAULT
}
NOT_KW => {
p.bump(NOT_KW);
p.expect(NULL_KW);
DROP_NOT_NULL
}
CONSTRAINT_KW => {
p.bump(CONSTRAINT_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
DROP_CONSTRAINT
}
_ => {
p.error("expected DEFAULT, NOT, or CONSTRAINT");
m.abandon(p);
return None;
}
}
}
ADD_KW => {
p.bump(ADD_KW);
domain_constraint(p);
opt_constraint_option_list(p);
ADD_CONSTRAINT
}
RENAME_KW if p.nth_at(1, TO_KW) => {
m.abandon(p);
return Some(rename_to(p));
}
RENAME_KW => {
p.bump(RENAME_KW);
p.expect(CONSTRAINT_KW);
name_ref(p);
p.expect(TO_KW);
name(p);
RENAME_CONSTRAINT
}
VALIDATE_KW => {
p.bump(VALIDATE_KW);
p.expect(CONSTRAINT_KW);
name_ref(p);
VALIDATE_CONSTRAINT
}
OWNER_KW => {
m.abandon(p);
return Some(owner_to(p));
}
_ => {
p.error("expected SET, DROP, ADD, RENAME, VALIDATE, or OWNER");
m.abandon(p);
return None;
}
};
Some(m.complete(p, action))
}
fn domain_constraint(p: &mut Parser<'_>) {
let m = p.start();
opt_constraint_name(p);
if p.eat(NOT_KW) {
p.expect(NULL_KW);
m.complete(p, NOT_NULL_CONSTRAINT);
} else if p.eat(CHECK_KW) {
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
m.complete(p, CHECK_CONSTRAINT);
} else {
p.error("expected NOT NULL or CHECK constraint");
m.abandon(p);
}
}
fn opt_constraint_name(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(CONSTRAINT_KW) {
name(p);
m.complete(p, CONSTRAINT_NAME);
} else {
m.abandon(p);
}
}
fn alter_default_privileges(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, DEFAULT_KW) && p.nth_at(2, PRIVILEGES_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(DEFAULT_KW);
p.bump(PRIVILEGES_KW);
if p.eat(FOR_KW) {
if !p.eat(ROLE_KW) && !p.eat(USER_KW) {
p.error("expected ROLE or USER");
}
role_list(p);
}
if p.eat(IN_KW) {
p.expect(SCHEMA_KW);
name_ref_list(p);
}
match p.current() {
GRANT_KW => {
let m = p.start();
p.bump(GRANT_KW);
privileges(p);
p.expect(ON_KW);
privilege_target_type(p);
p.expect(TO_KW);
role_list(p);
if p.eat(WITH_KW) {
p.expect(GRANT_KW);
p.expect(OPTION_KW);
}
m.complete(p, GRANT_DEFAULT_PRIVILEGES);
}
REVOKE_KW => {
let m = p.start();
p.bump(REVOKE_KW);
if p.eat(GRANT_KW) {
p.eat(OPTION_KW);
p.eat(FOR_KW);
}
privileges(p);
p.expect(ON_KW);
privilege_target_type(p);
p.expect(FROM_KW);
role_list(p);
opt_cascade_or_restrict(p);
m.complete(p, REVOKE_DEFAULT_PRIVILEGES);
}
_ => {
p.error("expected GRANT or REVOKE");
}
}
m.complete(p, ALTER_DEFAULT_PRIVILEGES)
}
fn privilege_target_type(p: &mut Parser<'_>) {
match p.current() {
LARGE_KW => {
let m = p.start();
p.bump(LARGE_KW);
p.expect(OBJECTS_KW);
m.complete(p, PRIVILEGE_TARGET);
}
TABLES_KW | FUNCTIONS_KW | ROUTINES_KW | SEQUENCES_KW | TYPES_KW | SCHEMAS_KW => {
let m = p.start();
p.bump_any();
m.complete(p, PRIVILEGE_TARGET);
}
_ => p.error(
"expected privilege target, TABLES, FUNCTIONS, ROUTINES, SEQEUNCES, TYPES, SCHEMAS, LARGE OBJECTS",
),
}
}
fn alter_database(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, DATABASE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(DATABASE_KW);
name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, TABLESPACE_KW) => {
set_tablespace(p);
}
SET_KW => {
set_configuration_param(p);
}
RESET_KW => {
let m = p.start();
p.bump(RESET_KW);
if !p.eat(ALL_KW) {
path_name_ref(p);
}
m.complete(p, RESET_CONFIG_PARAM);
}
REFRESH_KW => {
let m = p.start();
p.bump(REFRESH_KW);
p.expect(COLLATION_KW);
p.expect(VERSION_KW);
m.complete(p, REFRESH_COLLATION_VERSION);
}
_ => {
opt_create_database_option_list(p);
}
}
m.complete(p, ALTER_DATABASE)
}
fn set_tablespace(p: &mut Parser<'_>) {
assert!(p.at(SET_KW) && p.nth_at(1, TABLESPACE_KW));
let m = p.start();
p.bump(SET_KW);
p.bump(TABLESPACE_KW);
name_ref(p);
m.complete(p, SET_TABLESPACE);
}
fn opt_create_database_option_list(p: &mut Parser<'_>) {
let m = p.start();
p.eat(WITH_KW);
while !p.at(EOF) {
if !opt_create_database_option(p) {
break;
}
}
m.complete(p, CREATE_DATABASE_OPTION_LIST);
}
fn alter_conversion(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, CONVERSION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(CONVERSION_KW);
path_name_ref(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_CONVERSION)
}
fn alter_collation(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, COLLATION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(COLLATION_KW);
path_name_ref(p);
match p.current() {
REFRESH_KW => {
refresh_version(p);
}
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected REFRESH, RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_COLLATION)
}
fn refresh_version(p: &mut Parser<'_>) {
assert!(p.at(REFRESH_KW));
let m = p.start();
p.bump(REFRESH_KW);
p.expect(VERSION_KW);
m.complete(p, REFRESH_VERSION);
}
fn set_schema(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
p.expect(SCHEMA_KW);
name_ref(p);
m.complete(p, SET_SCHEMA)
}
fn alter_aggregate(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, AGGREGATE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(AGGREGATE_KW);
aggregate(p);
match p.current() {
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_AGGREGATE)
}
fn alter_subscription(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, SUBSCRIPTION_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(SUBSCRIPTION_KW);
name_ref(p);
match p.current() {
CONNECTION_KW => {
p.bump(CONNECTION_KW);
string_literal(p);
}
SERVER_KW => {
p.bump(SERVER_KW);
name_ref(p);
}
SET_KW if p.nth_at(1, L_PAREN) => {
set_options(p);
}
SET_KW | ADD_KW => {
p.bump_any();
p.expect(PUBLICATION_KW);
name_list(p);
opt_with_options_list(p);
}
DROP_KW => {
p.bump(DROP_KW);
p.expect(PUBLICATION_KW);
name_ref_list(p);
opt_with_options_list(p);
}
REFRESH_KW => {
p.bump(REFRESH_KW);
p.expect(PUBLICATION_KW);
opt_with_options_list(p);
}
ENABLE_KW | DISABLE_KW => {
p.bump_any();
}
SKIP_KW => {
p.bump(SKIP_KW);
attribute_list(p);
}
OWNER_KW => {
owner_to(p);
}
RENAME_KW => {
rename_to(p);
}
_ => {
p.error(
"expected CONNECTION, SERVER, SET, ADD, DROP, REFRESH, ENABLE, DISABLE, SKIP, OWNER or RENAME",
);
}
}
m.complete(p, ALTER_SUBSCRIPTION)
}
fn name_list(p: &mut Parser<'_>) {
name(p);
while !p.at(EOF) && p.eat(COMMA) {
name(p);
}
}
fn opt_with_options_list(p: &mut Parser<'_>) {
if p.eat(WITH_KW) {
attribute_list(p);
}
}
fn alter_system(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, SYSTEM_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(SYSTEM_KW);
if p.at(SET_KW) {
set_configuration_param(p);
} else if p.eat(RESET_KW) {
if !p.eat(ALL_KW) {
path_name_ref(p);
}
} else {
p.error("expected SET or RESET after ALTER SYSTEM");
}
m.complete(p, ALTER_SYSTEM)
}
fn alter_tablespace(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, TABLESPACE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(TABLESPACE_KW);
path_name_ref(p);
if p.at(RENAME_KW) {
rename_to(p);
} else if p.at(OWNER_KW) {
owner_to(p);
} else if p.at(SET_KW) {
set_options(p);
} else if p.at(RESET_KW) {
reset_options(p);
} else {
p.error("expected RENAME, OWNER, SET, or RESET after tablespace name");
}
m.complete(p, ALTER_TABLESPACE)
}
fn reset_options(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(RESET_KW));
let m = p.start();
p.bump(RESET_KW);
attribute_list(p);
m.complete(p, RESET_OPTIONS)
}
fn set_options(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
attribute_list(p);
m.complete(p, SET_OPTIONS)
}
fn alter_text_search_parser(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(ALTER_KW) && p.nth_at(1, TEXT_KW) && p.nth_at(2, SEARCH_KW) && p.nth_at(3, PARSER_KW)
);
let m = p.start();
p.bump(ALTER_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(PARSER_KW);
path_name_ref(p);
if p.at(RENAME_KW) {
rename_to(p);
} else if p.at(SET_KW) {
set_schema(p);
} else {
p.error("expected RENAME TO or SET SCHEMA");
}
m.complete(p, ALTER_TEXT_SEARCH_PARSER)
}
fn alter_text_search_dict(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(ALTER_KW)
&& p.nth_at(1, TEXT_KW)
&& p.nth_at(2, SEARCH_KW)
&& p.nth_at(3, DICTIONARY_KW)
);
let m = p.start();
p.bump(ALTER_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(DICTIONARY_KW);
path_name_ref(p);
if p.at(L_PAREN) {
attribute_list(p);
} else if p.at(RENAME_KW) {
rename_to(p);
} else if p.at(OWNER_KW) {
owner_to(p);
} else if p.at(SET_KW) {
set_schema(p);
} else {
p.error("expected '(', RENAME, OWNER, or SET");
}
m.complete(p, ALTER_TEXT_SEARCH_DICTIONARY)
}
fn alter_text_search_configuration(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(ALTER_KW)
&& p.nth_at(1, TEXT_KW)
&& p.nth_at(2, SEARCH_KW)
&& p.nth_at(3, CONFIGURATION_KW)
);
let m = p.start();
p.bump(ALTER_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(CONFIGURATION_KW);
path_name_ref(p);
match p.current() {
ADD_KW => {
p.bump(ADD_KW);
p.expect(MAPPING_KW);
p.expect(FOR_KW);
name_ref_list(p);
p.expect(WITH_KW);
path_name_ref_list(p);
}
ALTER_KW => {
p.bump(ALTER_KW);
p.expect(MAPPING_KW);
if p.eat(FOR_KW) {
name_ref_list(p);
if p.eat(WITH_KW) {
path_name_ref_list(p);
} else if p.eat(REPLACE_KW) {
path_name_ref(p);
p.expect(WITH_KW);
path_name_ref(p);
} else {
p.error("expected WITH or REPLACE");
}
} else if p.eat(REPLACE_KW) {
path_name_ref(p);
p.expect(WITH_KW);
path_name_ref(p);
} else {
p.error("expected FOR or REPLACE");
}
}
DROP_KW => {
p.bump(DROP_KW);
p.expect(MAPPING_KW);
opt_if_exists(p);
p.expect(FOR_KW);
name_ref_list(p);
}
RENAME_KW => {
rename_to(p);
}
OWNER_KW => {
owner_to(p);
}
SET_KW => {
set_schema(p);
}
_ => {
p.error("expected ADD, ALTER, DROP, RENAME, OWNER, or SET");
}
}
m.complete(p, ALTER_TEXT_SEARCH_CONFIGURATION)
}
fn name_ref_list(p: &mut Parser<'_>) {
name_ref(p);
while !p.at(EOF) && p.eat(COMMA) {
name_ref(p);
}
}
fn path_name_ref_list(p: &mut Parser<'_>) {
path_name_ref(p);
while !p.at(EOF) && p.eat(COMMA) {
path_name_ref(p);
}
}
fn alter_text_search_template(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(ALTER_KW)
&& p.nth_at(1, TEXT_KW)
&& p.nth_at(2, SEARCH_KW)
&& p.nth_at(3, TEMPLATE_KW)
);
let m = p.start();
p.bump(ALTER_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(TEMPLATE_KW);
path_name_ref(p);
if p.at(RENAME_KW) {
rename_to(p);
} else if p.at(SET_KW) {
set_schema(p);
} else {
p.error("expected RENAME TO or SET SCHEMA");
}
m.complete(p, ALTER_TEXT_SEARCH_TEMPLATE)
}
fn alter_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, TRIGGER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(TRIGGER_KW);
name_ref(p);
on_table(p);
if p.at(RENAME_KW) {
rename_to(p);
} else {
if p.at(NO_KW) || p.at(DEPENDS_KW) {
depends_on_extension(p);
} else {
p.error(format!("expected NO or DEPENDS, found {:?}", p.current()));
}
}
m.complete(p, ALTER_TRIGGER)
}
fn alter_type_action(p: &mut Parser<'_>) {
let m = p.start();
let kind = if p.eat(ADD_KW) {
p.expect(ATTRIBUTE_KW);
name(p);
type_name(p);
opt_collate(p);
opt_cascade_or_restrict(p);
ADD_ATTRIBUTE
} else if p.eat(DROP_KW) {
p.expect(ATTRIBUTE_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
DROP_ATTRIBUTE
} else {
p.expect(ALTER_KW);
p.expect(ATTRIBUTE_KW);
name_ref(p);
if p.eat(SET_KW) {
p.eat(DATA_KW);
}
p.expect(TYPE_KW);
type_name(p);
opt_collate(p);
opt_cascade_or_restrict(p);
ALTER_ATTRIBUTE
};
m.complete(p, kind);
}
fn alter_type(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, TYPE_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(TYPE_KW);
path_name_ref(p);
match p.current() {
ADD_KW | DROP_KW | ALTER_KW if p.nth_at(1, ATTRIBUTE_KW) => {
alter_type_action(p);
while !p.at(EOF) && p.eat(COMMA) {
alter_type_action(p);
}
}
OWNER_KW => {
owner_to(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
SET_KW => {
set_options(p);
}
RENAME_KW if p.nth_at(1, TO_KW) => {
rename_to(p);
}
RENAME_KW => {
let m = p.start();
p.bump(RENAME_KW);
if p.eat(ATTRIBUTE_KW) {
name_ref(p);
p.expect(TO_KW);
name(p);
opt_cascade_or_restrict(p);
m.complete(p, RENAME_ATTRIBUTE);
} else if p.eat(VALUE_KW) {
string_literal(p);
p.expect(TO_KW);
string_literal(p);
m.complete(p, RENAME_VALUE);
} else {
p.error("expected TO, ATTRIBUTE, or VALUE");
m.abandon(p);
}
}
ADD_KW => {
let m = p.start();
p.bump(ADD_KW);
p.expect(VALUE_KW);
opt_if_not_exists(p);
string_literal(p);
opt_value_position(p);
m.complete(p, ADD_VALUE);
}
_ => p.error("expected ALTER TYPE option"),
}
m.complete(p, ALTER_TYPE)
}
fn opt_value_position(p: &mut Parser<'_>) {
let m = p.start();
let kind = if p.eat(BEFORE_KW) {
BEFORE_VALUE
} else if p.eat(AFTER_KW) {
AFTER_VALUE
} else {
m.abandon(p);
return;
};
string_literal(p);
m.complete(p, kind);
}
fn alter_user(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, USER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(USER_KW);
if !p.eat(ALL_KW) {
role_ref(p);
}
if p.at(WITH_KW) || (p.at_ts(ROLE_OPTION_FIRST) && !p.nth_at(1, DATABASE_KW)) {
opt_role_option_list(p);
return m.complete(p, ALTER_USER);
}
if p.at(RENAME_KW) {
rename_to(p);
return m.complete(p, ALTER_USER);
}
if p.eat(IN_KW) {
p.expect(DATABASE_KW);
name_ref(p);
}
match p.current() {
SET_KW => {
set_configuration_param(p);
}
RESET_KW => {
p.bump(RESET_KW);
if !p.eat(ALL_KW) {
name_ref(p);
}
}
_ => p.error("expected SET or RESET"),
}
m.complete(p, ALTER_USER)
}
fn alter_user_mapping(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, USER_KW) && p.nth_at(2, MAPPING_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(USER_KW);
p.bump(MAPPING_KW);
p.expect(FOR_KW);
role_ref(p);
server_name(p);
if !opt_alter_option_list(p) {
p.error("expected options");
}
m.complete(p, ALTER_USER_MAPPING)
}
fn server_name(p: &mut Parser<'_>) {
let m = p.start();
p.expect(SERVER_KW);
name_ref(p);
m.complete(p, SERVER_NAME);
}
const ALTER_OPTION_FIRST: TokenSet =
TokenSet::new(&[DROP_KW, ADD_KW, SET_KW]).union(COL_LABEL_FIRST);
fn opt_alter_option(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(ALTER_OPTION_FIRST) {
return None;
}
let m = p.start();
let arg_required = match p.current() {
DROP_KW => {
p.bump(DROP_KW);
false
}
ADD_KW | SET_KW => {
p.bump_any();
true
}
_ => true,
};
col_label(p);
if arg_required {
string_literal(p);
}
Some(m.complete(p, ALTER_OPTION))
}
fn alter_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW) && p.nth_at(1, VIEW_KW));
let m = p.start();
p.bump(ALTER_KW);
p.bump(VIEW_KW);
opt_if_exists(p);
path_name_ref(p);
match p.current() {
ALTER_KW => {
p.bump(ALTER_KW);
p.eat(COLUMN_KW);
name_ref(p);
if p.eat(SET_KW) {
p.expect(DEFAULT_KW);
if expr(p).is_none() {
p.error("expected expression")
}
} else if p.eat(DROP_KW) {
p.expect(DEFAULT_KW);
} else {
p.error("expected SET or DROP");
}
}
OWNER_KW => {
owner_to(p);
}
RENAME_KW if p.nth_at(1, TO_KW) => {
rename_to(p);
}
RENAME_KW => {
p.bump(RENAME_KW);
p.eat(COLUMN_KW);
name_ref(p);
p.expect(TO_KW);
name(p);
}
SET_KW if p.nth_at(1, SCHEMA_KW) => {
set_schema(p);
}
SET_KW => {
set_options(p);
}
RESET_KW => {
reset_options(p);
}
_ => p.error("expected ALTER, OWNER, RENAME, or SET"),
}
m.complete(p, ALTER_VIEW)
}
fn analyze(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ANALYZE_KW) || p.at(ANALYSE_KW));
let m = p.start();
p.bump_any();
if !p.eat(VERBOSE_KW) {
opt_option_list(p);
}
opt_table_and_columns_list(p);
m.complete(p, ANALYZE)
}
fn opt_option_list(p: &mut Parser<'_>) {
if !p.at(L_PAREN) {
return;
}
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
OPTION_FIRST,
opt_option,
);
m.complete(p, OPTION_ITEM_LIST);
}
fn comment(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(COMMENT_KW));
let m = p.start();
p.bump(COMMENT_KW);
p.expect(ON_KW);
match p.current() {
ACCESS_KW => {
p.bump_any();
p.expect(METHOD_KW);
path_name_ref(p);
}
AGGREGATE_KW => {
p.bump_any();
aggregate(p);
}
CAST_KW => {
p.bump_any();
cast_sig(p);
}
COLLATION_KW | COLUMN_KW | CONVERSION_KW | DATABASE_KW | DOMAIN_KW | EXTENSION_KW
| INDEX_KW | LANGUAGE_KW | PUBLICATION_KW | ROLE_KW | SCHEMA_KW | SEQUENCE_KW
| SERVER_KW | STATISTICS_KW | SUBSCRIPTION_KW | TABLE_KW | TABLESPACE_KW | TYPE_KW
| VIEW_KW => {
p.bump_any();
path_name_ref(p);
}
CONSTRAINT_KW => {
p.bump_any();
name_ref(p);
p.expect(ON_KW);
p.eat(DOMAIN_KW);
path_name_ref(p);
}
EVENT_KW => {
p.bump_any();
p.expect(TRIGGER_KW);
path_name_ref(p);
}
FOREIGN_KW if p.nth_at(1, DATA_KW) => {
p.bump_any();
p.bump(DATA_KW);
p.expect(WRAPPER_KW);
path_name_ref(p);
}
FOREIGN_KW => {
p.bump_any();
p.expect(TABLE_KW);
path_name_ref(p);
}
FUNCTION_KW | PROCEDURE_KW | ROUTINE_KW => {
p.bump_any();
function_sig(p);
}
LARGE_KW => {
p.bump_any();
p.expect(OBJECT_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected object oid");
}
}
MATERIALIZED_KW => {
p.bump_any();
p.expect(VIEW_KW);
path_name_ref(p);
}
OPERATOR_KW if matches!(p.nth(1), CLASS_KW | FAMILY_KW) => {
p.bump_any();
p.bump_any();
path_name_ref(p);
opt_using_method(p);
}
OPERATOR_KW => {
p.bump_any();
operator(p);
p.eat(L_PAREN);
type_name(p);
p.expect(COMMA);
type_name(p);
p.eat(R_PAREN);
}
POLICY_KW | RULE_KW | TRIGGER_KW => {
p.bump_any();
name_ref(p);
p.expect(ON_KW);
path_name_ref(p);
}
PROPERTY_KW => {
p.bump_any();
p.expect(GRAPH_KW);
path_name_ref(p);
}
PROCEDURAL_KW => {
p.bump_any();
p.expect(LANGUAGE_KW);
path_name_ref(p);
}
TEXT_KW => {
p.bump_any();
p.expect(SEARCH_KW);
match p.current() {
CONFIGURATION_KW | DICTIONARY_KW | PARSER_KW | TEMPLATE_KW => {
p.bump_any();
path_name_ref(p);
}
_ => p.error("expected CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE"),
}
}
TRANSFORM_KW => {
p.bump_any();
p.expect(FOR_KW);
type_name(p);
p.expect(LANGUAGE_KW);
name_ref(p);
}
_ => p.err_and_bump("unexpected token"),
}
p.expect(IS_KW);
if !p.eat(NULL_KW) && opt_string_literal(p).is_none() {
p.error("expected string literal or NULL");
}
m.complete(p, COMMENT_ON)
}
fn cluster(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CLUSTER_KW));
let m = p.start();
p.bump(CLUSTER_KW);
if p.eat(VERBOSE_KW) {
} else {
opt_option_list(p);
}
let has_name = opt_path_name_ref(p).is_some();
if has_name && p.eat(ON_KW) {
path_name_ref(p);
}
opt_using_method(p);
m.complete(p, CLUSTER)
}
fn repack(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(REPACK_KW));
let m = p.start();
p.bump(REPACK_KW);
opt_option_list(p);
opt_table_and_columns_list(p);
if p.at(USING_KW) {
using_index(p);
}
m.complete(p, REPACK)
}
fn create_property_graph(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_persistence(p);
p.expect(PROPERTY_KW);
p.expect(GRAPH_KW);
path_name(p);
opt_vertex_tables(p);
opt_edge_tables(p);
m.complete(p, CREATE_PROPERTY_GRAPH)
}
fn opt_vertex_tables(p: &mut Parser<'_>) -> bool {
if !p.at(VERTEX_KW) && !p.at(NODE_KW) {
return false;
}
let m = p.start();
p.bump_any(); p.expect(TABLES_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
VERTEX_TABLE_DEF_FIRST,
opt_vertex_table_def,
);
m.complete(p, VERTEX_TABLES);
true
}
const VERTEX_TABLE_DEF_FIRST: TokenSet = PATH_FIRST;
fn opt_vertex_table_def(p: &mut Parser<'_>) -> bool {
if !p.at_ts(PATH_FIRST) {
return false;
}
let m = p.start();
path_name_ref(p);
if p.eat(AS_KW) {
name(p);
}
opt_key_columns(p);
opt_element_table_label_and_properties(p);
m.complete(p, VERTEX_TABLE_DEF);
true
}
fn opt_key_columns(p: &mut Parser<'_>) {
if p.eat(KEY_KW) {
opt_column_list_with(p, ColumnDefKind::NameRef);
}
}
fn opt_element_table_label_and_properties(p: &mut Parser<'_>) {
if !opt_element_table_properties_clause(p) {
opt_label_and_properties_list(p);
}
}
fn opt_label_and_properties_list(p: &mut Parser<'_>) {
if !p.at(DEFAULT_KW) && !p.at(LABEL_KW) {
return;
}
let m = p.start();
label_and_properties(p);
while p.at(DEFAULT_KW) || p.at(LABEL_KW) {
label_and_properties(p);
}
m.complete(p, LABEL_AND_PROPERTIES_LIST);
}
fn label_and_properties(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(DEFAULT_KW) {
p.expect(LABEL_KW);
} else {
p.expect(LABEL_KW);
name(p);
}
opt_element_table_properties_clause(p);
m.complete(p, LABEL_AND_PROPERTIES);
}
fn opt_element_table_properties_clause(p: &mut Parser<'_>) -> bool {
if !p.at(NO_KW) && !p.at(PROPERTIES_KW) {
return false;
}
let m = p.start();
let kind = if p.eat(NO_KW) {
p.expect(PROPERTIES_KW);
NO_PROPERTIES
} else {
p.expect(PROPERTIES_KW);
if p.eat(ALL_KW) {
p.expect(COLUMNS_KW);
ALL_PROPERTIES
} else {
expr_as_name_list(p);
PROPERTIES
}
};
m.complete(p, kind);
true
}
fn opt_edge_tables(p: &mut Parser<'_>) {
if !p.at(EDGE_KW) && !p.at(RELATIONSHIP_KW) {
return;
}
let m = p.start();
p.bump_any();
p.expect(TABLES_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EDGE_TABLE_DEF_FIRST,
opt_edge_table_def,
);
m.complete(p, EDGE_TABLES);
}
const EDGE_TABLE_DEF_FIRST: TokenSet = PATH_FIRST;
fn opt_edge_table_def(p: &mut Parser<'_>) -> bool {
if !p.at_ts(EDGE_TABLE_DEF_FIRST) {
return false;
}
let m = p.start();
path_name_ref(p);
if p.eat(AS_KW) {
name(p);
}
opt_key_columns(p);
source_vertex_table(p);
dest_vertex_table(p);
opt_element_table_label_and_properties(p);
m.complete(p, EDGE_TABLE_DEF);
true
}
fn references_table(p: &mut Parser<'_>) {
let m = p.start();
p.expect(REFERENCES_KW);
name_ref(p);
opt_column_list_with(p, ColumnDefKind::NameRef);
m.complete(p, REFERENCES_TABLE);
}
fn source_vertex_table(p: &mut Parser<'_>) {
let m = p.start();
p.expect(SOURCE_KW);
if p.eat(KEY_KW) {
opt_column_list_with(p, ColumnDefKind::NameRef);
references_table(p);
} else {
name_ref(p);
}
m.complete(p, SOURCE_VERTEX_TABLE);
}
fn dest_vertex_table(p: &mut Parser<'_>) {
let m = p.start();
p.expect(DESTINATION_KW);
if p.eat(KEY_KW) {
opt_column_list_with(p, ColumnDefKind::NameRef);
references_table(p);
} else {
name_ref(p);
}
m.complete(p, DEST_VERTEX_TABLE);
}
fn alter_property_graph(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.expect(PROPERTY_KW);
p.expect(GRAPH_KW);
opt_if_exists(p);
path_name_ref(p);
alter_property_graph_action(p);
m.complete(p, ALTER_PROPERTY_GRAPH)
}
const VERTEX: TokenSet = TokenSet::new(&[VERTEX_KW, NODE_KW]);
const EDGE: TokenSet = TokenSet::new(&[EDGE_KW, RELATIONSHIP_KW]);
const VERTEX_OR_EDGE: TokenSet = VERTEX.union(EDGE);
fn alter_property_graph_action(p: &mut Parser<'_>) {
if p.at(RENAME_KW) {
rename_to(p);
} else if p.at(OWNER_KW) {
owner_to(p);
} else if p.at(SET_KW) {
set_schema(p);
} else if p.at(ADD_KW) {
add_vertex_edge_tables(p);
} else if p.at(DROP_KW) && p.nth_at_ts(1, VERTEX) {
drop_vertex_tables(p);
} else if p.at(DROP_KW) && p.nth_at_ts(1, EDGE) {
drop_edge_tables(p);
} else if p.at(ALTER_KW) && p.nth_at_ts(1, VERTEX_OR_EDGE) {
alter_vertex_edge_table(p);
} else {
p.error("expected alter property graph action");
}
}
fn alter_vertex_edge_table(p: &mut Parser<'_>) {
assert!(p.at(ALTER_KW) && p.nth_at_ts(1, VERTEX_OR_EDGE));
let m = p.start();
p.bump(ALTER_KW);
p.bump_any();
p.expect(TABLE_KW);
path_name_ref(p);
let kind = alter_element_table_actions(p);
m.complete(p, kind);
}
fn drop_edge_tables(p: &mut Parser<'_>) {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump_any(); p.expect(TABLES_KW);
p.expect(L_PAREN);
path_name_ref(p);
while p.eat(COMMA) {
path_name_ref(p);
}
p.expect(R_PAREN);
opt_cascade_or_restrict(p);
m.complete(p, DROP_EDGE_TABLES);
}
fn drop_vertex_tables(p: &mut Parser<'_>) {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump_any(); p.expect(TABLES_KW);
p.expect(L_PAREN);
path_name_ref(p);
while p.eat(COMMA) {
path_name_ref(p);
}
p.expect(R_PAREN);
opt_cascade_or_restrict(p);
m.complete(p, DROP_VERTEX_TABLES);
}
fn add_vertex_edge_tables(p: &mut Parser<'_>) {
assert!(p.at(ADD_KW));
let m = p.start();
p.bump(ADD_KW);
let is_vertex = opt_vertex_tables(p);
if p.eat(ADD_KW) || !is_vertex {
opt_edge_tables(p);
}
m.complete(p, ADD_VERTEX_EDGE_TABLES);
}
fn alter_element_table_actions(p: &mut Parser<'_>) -> SyntaxKind {
if p.at(ADD_KW) {
add_label(p);
while p.at(ADD_KW) {
add_label(p);
}
ALTER_VERTEX_EDGE_LABELS
} else if p.at(DROP_KW) && (p.nth_at(1, LABEL_KW) || p.nth_at(1, PROPERTIES_KW)) {
p.bump(DROP_KW);
if p.eat(LABEL_KW) {
name_ref(p);
DROP_VERTEX_EDGE_LABEL
} else {
p.expect(PROPERTIES_KW);
if !opt_paren_name_ref_list(p) {
p.error("expected name ref list")
}
DROP_VERTEX_EDGE_LABEL_PROPERTIES
}
} else {
p.expect(ALTER_KW);
p.expect(LABEL_KW);
name_ref(p);
if p.eat(ADD_KW) {
p.expect(PROPERTIES_KW);
expr_as_name_list(p);
ADD_VERTEX_EDGE_LABEL_PROPERTIES
} else {
p.expect(DROP_KW);
p.expect(PROPERTIES_KW);
if !opt_paren_name_ref_list(p) {
p.error("expected name ref list")
}
opt_cascade_or_restrict(p);
DROP_VERTEX_EDGE_LABEL_PROPERTIES
}
}
}
fn add_label(p: &mut Parser<'_>) {
assert!(p.at(ADD_KW));
let m = p.start();
p.bump(ADD_KW);
p.expect(LABEL_KW);
name(p);
opt_element_table_properties_clause(p);
m.complete(p, ADD_LABEL);
}
fn drop_property_graph(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.expect(PROPERTY_KW);
p.expect(GRAPH_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_PROPERTY_GRAPH)
}
fn graph_table_fn(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(GRAPH_TABLE_KW));
let m = p.start();
p.bump(GRAPH_TABLE_KW);
p.expect(L_PAREN);
path_name_ref(p);
p.expect(MATCH_KW);
path_pattern_list(p);
opt_where_clause(p);
p.expect(COLUMNS_KW);
expr_as_name_list(p);
p.expect(R_PAREN);
m.complete(p, GRAPH_TABLE_FN)
}
fn path_pattern_list(p: &mut Parser<'_>) {
let m = p.start();
if p.at(L_PAREN) || p.at(MINUS) || p.at(L_ANGLE) {
path_pattern(p);
while p.eat(COMMA) {
path_pattern(p);
}
}
m.complete(p, PATH_PATTERN_LIST);
}
fn path_pattern(p: &mut Parser<'_>) {
let m = p.start();
path_factor(p);
while p.at_ts(PATH_FACTOR_FIRST) {
path_factor(p);
}
m.complete(p, PATH_PATTERN);
}
const PATH_FACTOR_FIRST: TokenSet = TokenSet::new(&[L_PAREN, MINUS, L_ANGLE]);
fn path_factor(p: &mut Parser<'_>) {
let m = p.start();
path_primary(p);
opt_graph_pattern_qualifier(p);
m.complete(p, PATH_FACTOR);
}
fn path_primary(p: &mut Parser<'_>) {
if p.at(L_PAREN) {
if p.nth_at_ts(1, PATH_FACTOR_FIRST) {
paren_graph_pattern(p);
} else {
vertex_pattern(p);
}
} else if p.at(L_ANGLE) {
edge_left(p);
} else if p.at(MINUS) {
if p.nth_at(1, L_BRACK) {
edge_with_bracket(p);
} else if p.nth_at(1, R_ANGLE) {
let m = p.start();
p.bump(MINUS);
p.bump(R_ANGLE);
m.complete(p, EDGE_RIGHT);
} else {
let m = p.start();
p.bump(MINUS);
m.complete(p, EDGE_ANY);
}
}
}
fn vertex_pattern(p: &mut Parser<'_>) {
let m = p.start();
p.expect(L_PAREN);
opt_name(p);
opt_is_label(p);
opt_where_clause(p);
p.expect(R_PAREN);
m.complete(p, VERTEX_PATTERN);
}
fn opt_is_label(p: &mut Parser<'_>) {
if p.at(IS_KW) {
let m = p.start();
p.bump(IS_KW);
if expr(p).is_none() {
p.error("expected expression");
}
m.complete(p, IS_LABEL);
}
}
fn edge_left(p: &mut Parser<'_>) {
assert!(p.at(L_ANGLE));
let m = p.start();
p.bump(L_ANGLE);
p.expect(MINUS);
if p.eat(L_BRACK) {
opt_edge_pattern_inner(p);
p.expect(R_BRACK);
p.expect(MINUS);
}
m.complete(p, EDGE_LEFT);
}
fn edge_with_bracket(p: &mut Parser<'_>) {
assert!(p.at(MINUS) && p.nth_at(1, L_BRACK));
let m = p.start();
p.bump(MINUS);
p.bump(L_BRACK);
opt_edge_pattern_inner(p);
p.expect(R_BRACK);
p.expect(MINUS);
let kind = if p.eat(R_ANGLE) { EDGE_RIGHT } else { EDGE_ANY };
m.complete(p, kind);
}
fn opt_edge_pattern_inner(p: &mut Parser<'_>) {
opt_name(p);
opt_is_label(p);
opt_where_clause(p);
}
fn paren_graph_pattern(p: &mut Parser<'_>) {
let m = p.start();
p.expect(L_PAREN);
path_pattern(p);
opt_where_clause(p);
p.expect(R_PAREN);
m.complete(p, PAREN_GRAPH_PATTERN);
}
fn opt_graph_pattern_qualifier(p: &mut Parser<'_>) {
if !p.at(L_CURLY) {
return;
}
let m = p.start();
p.expect(L_CURLY);
if p.eat(COMMA) {
if expr(p).is_none() {
p.error("expected expression");
}
} else {
if expr(p).is_none() {
p.error("expected expression");
}
if p.eat(COMMA) {
if expr(p).is_none() {
p.error("expected expression");
}
}
}
p.expect(R_CURLY);
m.complete(p, GRAPH_PATTERN_QUALIFIER);
}
const OPTION_FIRST: TokenSet =
TokenSet::new(&[ANALYSE_KW, ANALYZE_KW, FORMAT_KW]).union(NON_RESERVED_WORD);
fn opt_option(p: &mut Parser<'_>) -> bool {
if !p.at_ts(OPTION_FIRST) {
return false;
}
let m = p.start();
p.bump_any();
opt_option_value(p);
m.complete(p, OPTION_ITEM);
true
}
fn create_access_method(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.expect(ACCESS_KW);
p.expect(METHOD_KW);
path_name(p);
p.expect(TYPE_KW);
if !p.eat(TABLE_KW) && !p.eat(INDEX_KW) {
p.error("expected TABLE or INDEX");
}
handler_clause(p);
m.complete(p, CREATE_ACCESS_METHOD)
}
fn handler_clause(p: &mut Parser<'_>) {
let m = p.start();
p.expect(HANDLER_KW);
path_name(p);
m.complete(p, HANDLER_CLAUSE);
}
fn create_aggregate(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.expect(AGGREGATE_KW);
path_name(p);
let at_old_syntax = p.at(L_PAREN) && p.nth_at(1, IDENT) && p.nth_at(2, EQ);
if !at_old_syntax {
aggregate_arg_list(p);
}
attribute_list(p);
m.complete(p, CREATE_AGGREGATE)
}
fn create_cast(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, CAST_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(CAST_KW);
cast_sig(p);
if p.eat(WITH_KW) {
if !p.eat(INOUT_KW) {
p.expect(FUNCTION_KW);
function_sig(p);
}
} else {
p.expect(WITHOUT_KW);
p.expect(FUNCTION_KW);
}
if p.eat(AS_KW) {
if !p.eat(ASSIGNMENT_KW) && !p.eat(IMPLICIT_KW) {
p.error("expected ASSIGNMENT or IMPLICIT");
}
}
m.complete(p, CREATE_CAST)
}
fn create_collation(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, COLLATION_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(COLLATION_KW);
opt_if_not_exists(p);
path_name(p);
if p.eat(FROM_KW) {
path_name_ref(p);
} else {
attribute_list(p);
}
m.complete(p, CREATE_COLLATION)
}
fn create_conversion(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.eat(DEFAULT_KW);
p.expect(CONVERSION_KW);
path_name(p);
p.expect(FOR_KW);
string_literal(p);
p.expect(TO_KW);
string_literal(p);
p.expect(FROM_KW);
path_name(p);
m.complete(p, CREATE_CONVERSION)
}
fn opt_option_value(p: &mut Parser<'_>) -> bool {
if opt_numeric_literal(p).is_none()
&& opt_string_literal(p).is_none()
&& !opt_bool_literal(p)
&& !p.eat(DEFAULT_KW)
{
if p.at_ts(NON_RESERVED_WORD) {
p.bump_any();
return true;
} else {
return false;
}
}
true
}
fn opt_create_database_option(p: &mut Parser<'_>) -> bool {
let m = p.start();
match p.current() {
OWNER_KW | TEMPLATE_KW | ENCODING_KW | IDENT | TABLESPACE_KW => {
p.bump_any();
}
CONNECTION_KW => {
p.bump(CONNECTION_KW);
p.expect(LIMIT_KW);
}
_ => {
m.abandon(p);
return false;
}
}
p.eat(EQ);
if !opt_option_value(p) {
p.error("expected create database option value");
m.complete(p, CREATE_DATABASE_OPTION);
return false;
}
m.complete(p, CREATE_DATABASE_OPTION);
true
}
fn create_database(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, DATABASE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(DATABASE_KW);
name(p);
opt_create_database_option_list(p);
m.complete(p, CREATE_DATABASE)
}
fn create_domain(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, DOMAIN_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(DOMAIN_KW);
path_name(p);
p.eat(AS_KW);
type_name(p);
opt_collate(p);
opt_column_constraint_list(p);
m.complete(p, CREATE_DOMAIN)
}
fn event_trigger_when(p: &mut Parser<'_>) {
let m = p.start();
name_ref(p);
p.expect(IN_KW);
p.expect(L_PAREN);
string_literal(p);
while !p.at(EOF) && p.eat(COMMA) {
string_literal(p);
}
p.expect(R_PAREN);
m.complete(p, EVENT_TRIGGER_WHEN);
}
fn create_event_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, EVENT_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(EVENT_KW);
p.expect(TRIGGER_KW);
name(p);
p.expect(ON_KW);
name_ref(p);
opt_event_trigger_when_clause(p);
p.expect(EXECUTE_KW);
if !p.eat(FUNCTION_KW) && !p.eat(PROCEDURE_KW) {
p.error("expected FUNCTION or PROCEDURE");
}
call_expr(p);
m.complete(p, CREATE_EVENT_TRIGGER)
}
fn opt_event_trigger_when_clause(p: &mut Parser<'_>) {
if p.at(WHEN_KW) {
let m = p.start();
p.bump(WHEN_KW);
event_trigger_when(p);
while !p.at(EOF) && p.eat(AND_KW) {
event_trigger_when(p);
}
m.complete(p, EVENT_TRIGGER_WHEN_CLAUSE);
}
}
fn create_foreign_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, FOREIGN_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(FOREIGN_KW);
p.expect(TABLE_KW);
opt_if_not_exists(p);
path_name(p);
if p.eat(PARTITION_KW) {
p.expect(OF_KW);
path_name_ref(p);
if p.at(L_PAREN) {
table_arg_list(p);
}
partition_option(p);
} else {
if p.at(L_PAREN) {
table_arg_list(p);
} else {
p.error("expected table arg list");
}
opt_inherits_tables(p);
}
server_name(p);
opt_alter_option_list(p);
m.complete(p, CREATE_FOREIGN_TABLE)
}
fn opt_with_options(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(WITH_KW) {
let m = p.start();
p.bump(WITH_KW);
p.expect(OPTIONS_KW);
Some(m.complete(p, WITH_OPTIONS))
} else {
None
}
}
fn create_foreign_data_wrapper(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, FOREIGN_KW) && p.nth_at(2, DATA_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(FOREIGN_KW);
p.bump(DATA_KW);
p.expect(WRAPPER_KW);
name(p);
opt_fdw_option_list(p);
opt_alter_option_list(p);
m.complete(p, CREATE_FOREIGN_DATA_WRAPPER)
}
fn opt_fdw_option_list(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
let mut found = false;
while !p.at(EOF) {
if !opt_fdw_option(p) {
break;
} else {
found = true;
}
}
if found {
Some(m.complete(p, FDW_OPTION_LIST))
} else {
m.abandon(p);
None
}
}
fn opt_fdw_option(p: &mut Parser<'_>) -> bool {
let m = p.start();
let ret = match p.current() {
OPTIONS_KW => {
if !opt_alter_option_list(p) {
p.error("expected options");
}
true
}
CONNECTION_KW | HANDLER_KW | VALIDATOR_KW => {
p.bump_any();
path_name_ref(p);
true
}
NO_KW => {
p.bump(NO_KW);
if !p.eat(CONNECTION_KW) && !p.eat(HANDLER_KW) && !p.eat(VALIDATOR_KW) {
p.error("expected CONNECTION, HANDLER or VALIDATOR")
}
true
}
_ => {
m.abandon(p);
return false;
}
};
m.complete(p, FDW_OPTION);
ret
}
fn create_group(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, GROUP_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(GROUP_KW);
name(p);
opt_role_option_list(p);
m.complete(p, CREATE_GROUP)
}
fn create_language(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.eat(TRUSTED_KW);
p.eat(PROCEDURAL_KW);
p.eat(LANGUAGE_KW);
name(p);
if p.eat(HANDLER_KW) {
path_name_ref(p);
if p.eat(INLINE_KW) {
path_name_ref(p);
}
if p.eat(VALIDATOR_KW) {
path_name_ref(p);
}
}
m.complete(p, CREATE_LANGUAGE)
}
fn create_materialized_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, MATERIALIZED_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(MATERIALIZED_KW);
p.expect(VIEW_KW);
opt_if_not_exists(p);
path_name(p);
opt_column_list_with(p, ColumnDefKind::Name);
opt_using_method(p);
opt_with_params(p);
opt_tablespace(p);
p.expect(AS_KW);
let statement = stmt(p, &StmtRestrictions::default());
match statement.map(|x| x.kind()) {
Some(SELECT | SELECT_INTO | COMPOUND_SELECT | PAREN_SELECT | TABLE | VALUES) => (),
Some(kind) => {
p.error(format!(
"expected SELECT, TABLE, or VALUES statement, got {kind:?}"
));
}
None => {
p.error("expected SELECT, TABLE, or VALUES statement");
}
}
opt_with_data(p);
m.complete(p, CREATE_MATERIALIZED_VIEW)
}
fn create_operator(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, OPERATOR_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(OPERATOR_KW);
operator(p);
attribute_list(p);
m.complete(p, CREATE_OPERATOR)
}
fn create_operator_class(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, OPERATOR_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(OPERATOR_KW);
p.expect(CLASS_KW);
path_name(p);
p.eat(DEFAULT_KW);
p.expect(FOR_KW);
p.expect(TYPE_KW);
type_name(p);
p.expect(USING_KW);
name_ref(p);
if p.eat(FAMILY_KW) {
path_name_ref(p);
}
p.expect(AS_KW);
operator_class_option_list(p);
m.complete(p, CREATE_OPERATOR_CLASS)
}
fn operator_class_option(p: &mut Parser<'_>) {
let m = p.start();
match p.current() {
OPERATOR_KW => {
p.bump(OPERATOR_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected number");
}
operator(p);
if p.eat(L_PAREN) {
type_name(p);
p.expect(COMMA);
type_name(p);
p.expect(R_PAREN);
}
if p.eat(FOR_KW) {
if p.eat(ORDER_KW) {
p.expect(BY_KW);
path_name_ref(p);
} else if p.eat(SEARCH_KW) {
} else {
p.error("expected SEARCH or ORDER BY");
}
}
m.complete(p, OP_CLASS_OPTION);
}
FUNCTION_KW => {
p.bump(FUNCTION_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected number");
}
opt_param_list(p, ParamKind::TypeOnly);
function_sig(p);
m.complete(p, OP_CLASS_OPTION);
}
STORAGE_KW => {
p.bump(STORAGE_KW);
type_name(p);
m.complete(p, OP_CLASS_OPTION);
}
_ => {
p.error("expected OPERATOR, FUNCTION, or STORAGE");
m.abandon(p);
}
}
}
fn operator_drop_class_option(p: &mut Parser<'_>) {
match p.current() {
OPERATOR_KW | FUNCTION_KW => {
let m = p.start();
p.bump_any();
if opt_numeric_literal(p).is_none() {
p.error("expected number");
}
opt_param_list(p, ParamKind::TypeOnly);
m.complete(p, DROP_OP_CLASS_OPTION);
}
_ => p.error("expected OPERATOR, or FUNCTION"),
}
}
fn create_operator_family(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, OPERATOR_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(OPERATOR_KW);
p.expect(FAMILY_KW);
path_name(p);
p.expect(USING_KW);
name_ref(p);
m.complete(p, CREATE_OPERATOR_FAMILY)
}
fn create_policy(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, POLICY_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(POLICY_KW);
name(p);
on_table(p);
opt_as_policy_type(p);
if p.eat(FOR_KW) {
let _ = p.eat(ALL_KW)
|| p.eat(SELECT_KW)
|| p.eat(INSERT_KW)
|| p.eat(UPDATE_KW)
|| p.eat(DELETE_KW);
}
if p.eat(TO_KW) {
role_list(p);
}
opt_using_expr_clause(p);
opt_with_check_expr_clause(p);
m.complete(p, CREATE_POLICY)
}
fn opt_as_policy_type(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(AS_KW) {
ident(p);
m.complete(p, AS_POLICY_TYPE);
} else {
m.abandon(p);
}
}
fn opt_with_check_expr_clause(p: &mut Parser<'_>) {
if p.at(WITH_KW) {
let m = p.start();
p.bump(WITH_KW);
p.expect(CHECK_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
m.complete(p, WITH_CHECK_EXPR_CLAUSE);
}
}
fn create_procedure(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.expect(PROCEDURE_KW);
path_name(p);
param_list(p, ParamKind::All);
func_option_list(p);
m.complete(p, CREATE_PROCEDURE)
}
fn publication_object(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(TABLES_KW) {
p.expect(IN_KW);
p.expect(SCHEMA_KW);
if !p.eat(CURRENT_SCHEMA_KW) {
name_ref(p);
}
opt_constraint_where_clause(p);
} else if p.eat(CURRENT_SCHEMA_KW) {
} else {
p.eat(TABLE_KW);
p.eat(ONLY_KW);
if p.eat(L_PAREN) {
path_name_ref(p);
p.expect(R_PAREN);
} else {
path_name_ref(p);
}
p.eat(STAR);
opt_column_ref_list(p);
opt_constraint_where_clause(p);
}
m.complete(p, PUBLICATION_OBJECT);
}
fn create_publication(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, PUBLICATION_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(PUBLICATION_KW);
name(p);
if p.eat(FOR_KW) {
if p.at(ALL_KW) {
publication_all_object(p);
while !p.at(EOF) && p.eat(COMMA) {
publication_all_object(p);
}
opt_except_table_clause(p);
} else {
publication_object(p);
while !p.at(EOF) && p.eat(COMMA) {
publication_object(p);
}
}
}
opt_with_params(p);
m.complete(p, CREATE_PUBLICATION)
}
fn publication_all_object(p: &mut Parser<'_>) {
p.expect(ALL_KW);
if !p.eat(TABLES_KW) && !p.eat(SEQUENCES_KW) {
p.error(format!(
"expected TABLES or SEQUENCES, got {:?}",
p.current()
));
}
}
fn opt_except_table_clause(p: &mut Parser<'_>) {
if !p.at(EXCEPT_KW) {
return;
}
let m = p.start();
p.bump(EXCEPT_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
RELATION_NAME_FIRST.union(TokenSet::new(&[TABLE_KW])),
|p| {
p.eat(TABLE_KW);
opt_relation_name(p).is_some()
},
);
m.complete(p, EXCEPT_TABLE_CLAUSE);
}
fn create_role(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, ROLE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(ROLE_KW);
name(p);
opt_role_option_list(p);
m.complete(p, CREATE_ROLE)
}
fn select_insert_delete_update_or_notify(p: &mut Parser<'_>) {
let statement = stmt(p, &StmtRestrictions::default());
if let Some(statement) = statement {
match statement.kind() {
SELECT | VALUES | INSERT | UPDATE | DELETE | NOTIFY => (),
kind => {
p.error(format!(
"expected SELECT, INSERT, UPDATE, DELETE, NOTIFY, or VALUES statement, got {kind:?}"
));
}
}
} else {
p.error("expected SELECT, INSERT, UPDATE, DELETE, NOTIFY, or VALUES statement");
}
}
fn create_rule(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && matches!(p.nth(1), OR_KW | RULE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.expect(RULE_KW);
name(p);
p.expect(AS_KW);
p.expect(ON_KW);
if p.at(SELECT_KW) || p.at(INSERT_KW) || p.at(UPDATE_KW) || p.at(DELETE_KW) {
p.bump_any();
} else {
p.error("expected SELECT, INSERT, UPDATE, or DELETE");
}
p.expect(TO_KW);
path_name_ref(p);
opt_where_clause(p);
p.expect(DO_KW);
let _ = p.eat(ALSO_KW) || p.eat(INSTEAD_KW);
if p.eat(L_PAREN) {
while !p.at(EOF) && !p.at(R_PAREN) {
select_insert_delete_update_or_notify(p);
if !p.eat(SEMICOLON) {
break;
}
}
p.expect(R_PAREN);
} else if p.eat(NOTHING_KW) {
} else {
select_insert_delete_update_or_notify(p);
}
m.complete(p, CREATE_RULE)
}
fn create_sequence(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(CREATE_KW) && matches!(p.nth(1), TEMPORARY_KW | TEMP_KW | UNLOGGED_KW | SEQUENCE_KW)
);
let m = p.start();
p.bump(CREATE_KW);
opt_persistence(p);
p.expect(SEQUENCE_KW);
opt_if_not_exists(p);
path_name(p);
while !p.at(EOF) {
if opt_sequence_option(p).is_none() {
break;
}
}
m.complete(p, CREATE_SEQUENCE)
}
fn create_server(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, SERVER_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(SERVER_KW);
opt_if_not_exists(p);
name(p);
if p.eat(TYPE_KW) {
string_literal(p);
}
if p.eat(VERSION_KW) {
string_literal(p);
}
p.expect(FOREIGN_KW);
p.expect(DATA_KW);
p.expect(WRAPPER_KW);
name_ref(p);
opt_alter_option_list(p);
m.complete(p, CREATE_SERVER)
}
fn create_statistics(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, STATISTICS_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(STATISTICS_KW);
opt_if_not_exists(p);
if !p.at(L_PAREN) && !p.at(ON_KW) {
path_name(p);
}
opt_paren_name_ref_list(p);
if p.eat(ON_KW) {
if !opt_expr_list(p) {
p.error("expected expression")
}
}
from_table(p);
m.complete(p, CREATE_STATISTICS)
}
fn opt_paren_name_ref_list(p: &mut Parser<'_>) -> bool {
if p.eat(L_PAREN) {
name_ref_list(p);
p.expect(R_PAREN);
true
} else {
false
}
}
fn create_subscription(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, SUBSCRIPTION_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(SUBSCRIPTION_KW);
name(p);
if p.eat(SERVER_KW) {
name_ref(p);
} else {
p.expect(CONNECTION_KW);
string_literal(p);
}
p.expect(PUBLICATION_KW);
name_ref_list(p);
opt_with_params(p);
m.complete(p, CREATE_SUBSCRIPTION)
}
fn create_tablespace(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, TABLESPACE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TABLESPACE_KW);
name(p);
if p.eat(OWNER_KW) {
role_ref(p);
}
p.expect(LOCATION_KW);
string_literal(p);
opt_with_params(p);
m.complete(p, CREATE_TABLESPACE)
}
fn create_text_search_parser(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, TEXT_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(PARSER_KW);
path_name(p);
attribute_list(p);
m.complete(p, CREATE_TEXT_SEARCH_PARSER)
}
fn create_text_search_dict(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, TEXT_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(DICTIONARY_KW);
path_name(p);
attribute_list(p);
m.complete(p, CREATE_TEXT_SEARCH_DICTIONARY)
}
fn create_text_search_config(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, TEXT_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(CONFIGURATION_KW);
path_name(p);
attribute_list(p);
m.complete(p, CREATE_TEXT_SEARCH_CONFIGURATION)
}
fn create_text_search_template(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, TEXT_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(TEMPLATE_KW);
path_name(p);
attribute_list(p);
m.complete(p, CREATE_TEXT_SEARCH_TEMPLATE)
}
fn create_transform(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.expect(TRANSFORM_KW);
p.expect(FOR_KW);
type_name(p);
p.expect(LANGUAGE_KW);
name_ref(p);
p.expect(L_PAREN);
transform_from_func(p);
p.expect(COMMA);
transform_to_func(p);
p.expect(R_PAREN);
m.complete(p, CREATE_TRANSFORM)
}
fn transform_to_func(p: &mut Parser<'_>) {
let m = p.start();
p.expect(TO_KW);
p.expect(SQL_KW);
p.expect(WITH_KW);
p.expect(FUNCTION_KW);
function_sig(p);
m.complete(p, TRANSFORM_TO_FUNC);
}
fn transform_from_func(p: &mut Parser<'_>) {
let m = p.start();
p.expect(FROM_KW);
p.expect(SQL_KW);
p.expect(WITH_KW);
p.expect(FUNCTION_KW);
function_sig(p);
m.complete(p, TRANSFORM_FROM_FUNC);
}
fn create_user_mapping(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, USER_KW) && p.nth_at(2, MAPPING_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(USER_KW);
p.bump(MAPPING_KW);
opt_if_not_exists(p);
p.expect(FOR_KW);
if !p.eat(USER_KW) {
role_ref(p);
}
server_name(p);
opt_alter_option_list(p);
m.complete(p, CREATE_USER_MAPPING)
}
const ROLE_OPTION_FIRST: TokenSet = TokenSet::new(&[
WITH_KW,
INHERIT_KW,
CONNECTION_KW,
ENCRYPTED_KW,
PASSWORD_KW,
VALID_KW,
IN_KW,
ROLE_KW,
ADMIN_KW,
USER_KW,
SYSID_KW,
IDENT,
]);
fn opt_role_option(p: &mut Parser<'_>) -> bool {
if !p.at_ts(ROLE_OPTION_FIRST) {
return false;
}
let m = p.start();
match p.current() {
INHERIT_KW | IDENT => {
p.bump_any();
}
CONNECTION_KW => {
p.bump(CONNECTION_KW);
p.expect(LIMIT_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected number literal");
}
}
ENCRYPTED_KW => {
p.bump(ENCRYPTED_KW);
p.expect(PASSWORD_KW);
string_literal(p);
}
PASSWORD_KW => {
p.bump(PASSWORD_KW);
if !p.eat(NULL_KW) {
string_literal(p);
}
}
VALID_KW => {
p.bump(VALID_KW);
p.expect(UNTIL_KW);
string_literal(p);
}
IN_KW => {
p.bump(IN_KW);
if p.at(GROUP_KW) || p.at(ROLE_KW) {
p.bump_any();
} else {
p.error("expected GROUP or ROLE");
}
role_list(p);
}
ROLE_KW | ADMIN_KW | USER_KW => {
p.bump_any();
role_list(p);
}
SYSID_KW => {
p.bump(SYSID_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected string literal");
}
}
_ => {
m.abandon(p);
p.err_and_bump("expected role option");
return false;
}
}
m.complete(p, ROLE_OPTION);
true
}
fn create_user(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, USER_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(USER_KW);
name(p);
opt_role_option_list(p);
m.complete(p, CREATE_USER)
}
fn opt_role_option_list(p: &mut Parser<'_>) {
if p.at_ts(ROLE_OPTION_FIRST) {
let m = p.start();
p.eat(WITH_KW);
opt_role_option(p);
while !p.at(EOF) && p.at_ts(ROLE_OPTION_FIRST) {
opt_role_option(p);
}
m.complete(p, ROLE_OPTION_LIST);
}
}
fn drop_language(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && matches!(p.nth(1), LANGUAGE_KW | PROCEDURAL_KW));
let m = p.start();
p.bump(DROP_KW);
p.eat(PROCEDURAL_KW);
p.expect(LANGUAGE_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_LANGUAGE)
}
fn drop_group(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, GROUP_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(GROUP_KW);
opt_if_exists(p);
name_ref_list(p);
m.complete(p, DROP_GROUP)
}
fn drop_function(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, FUNCTION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(FUNCTION_KW);
opt_if_exists(p);
function_sig_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_FUNCTION)
}
fn function_sig(p: &mut Parser<'_>) {
let m = p.start();
path_name_ref(p);
opt_param_list(p, ParamKind::All);
m.complete(p, FUNCTION_SIG);
}
fn function_sig_list(p: &mut Parser<'_>) {
let m = p.start();
function_sig(p);
while !p.at(EOF) && p.eat(COMMA) {
function_sig(p);
}
m.complete(p, FUNCTION_SIG_LIST);
}
fn drop_foreign_data(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(DROP_KW) && p.nth_at(1, FOREIGN_KW) && p.nth_at(2, DATA_KW) && p.nth_at(3, WRAPPER_KW)
);
let m = p.start();
p.bump(DROP_KW);
p.bump(FOREIGN_KW);
p.bump(DATA_KW);
p.bump(WRAPPER_KW);
opt_if_exists(p);
name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_FOREIGN_DATA_WRAPPER)
}
fn drop_foreign_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, FOREIGN_KW) && p.nth_at(2, TABLE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(FOREIGN_KW);
p.bump(TABLE_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_FOREIGN_TABLE)
}
fn drop_access_method(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, ACCESS_KW) && p.nth_at(2, METHOD_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(ACCESS_KW);
p.bump(METHOD_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_ACCESS_METHOD)
}
fn aggregate(p: &mut Parser<'_>) {
let m = p.start();
path_name_ref(p);
aggregate_arg_list(p);
m.complete(p, AGGREGATE);
}
fn drop_aggregate(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, AGGREGATE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(AGGREGATE_KW);
opt_if_exists(p);
aggregate(p);
while !p.at(EOF) && p.eat(COMMA) {
aggregate(p);
}
opt_cascade_or_restrict(p);
m.complete(p, DROP_AGGREGATE)
}
fn cast_sig(p: &mut Parser<'_>) {
let m = p.start();
p.expect(L_PAREN);
type_name(p);
p.expect(AS_KW);
type_name(p);
p.expect(R_PAREN);
m.complete(p, CAST_SIG);
}
fn drop_cast(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, CAST_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(CAST_KW);
opt_if_exists(p);
cast_sig(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_CAST)
}
fn drop_collation(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, COLLATION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(COLLATION_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_COLLATION)
}
fn drop_conversion(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, CONVERSION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(CONVERSION_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_CONVERSION)
}
fn drop_domain(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, DOMAIN_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(DOMAIN_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_DOMAIN)
}
fn drop_event_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, EVENT_KW) && p.nth_at(2, TRIGGER_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(EVENT_KW);
p.bump(TRIGGER_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_EVENT_TRIGGER)
}
fn drop_extension(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, EXTENSION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(EXTENSION_KW);
opt_if_exists(p);
name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_EXTENSION)
}
fn drop_materialized_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, MATERIALIZED_KW) && p.nth_at(2, VIEW_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(MATERIALIZED_KW);
p.bump(VIEW_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_MATERIALIZED_VIEW)
}
fn drop_operator_family(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, OPERATOR_KW) && p.nth_at(2, FAMILY_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(OPERATOR_KW);
p.bump(FAMILY_KW);
opt_if_exists(p);
path_name_ref(p);
p.expect(USING_KW);
name_ref(p); opt_cascade_or_restrict(p);
m.complete(p, DROP_OPERATOR_FAMILY)
}
fn drop_operator(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, OPERATOR_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(OPERATOR_KW);
opt_if_exists(p);
op_sig_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_OPERATOR)
}
fn op_sig_list(p: &mut Parser<'_>) {
let m = p.start();
operator_sig(p);
while !p.at(EOF) && p.eat(COMMA) {
operator_sig(p);
}
m.complete(p, OP_SIG_LIST);
}
fn operator_sig(p: &mut Parser<'_>) {
let m = p.start();
operator(p);
p.expect(L_PAREN);
if !p.eat(NONE_KW) {
type_name(p);
}
p.expect(COMMA);
type_name(p);
p.expect(R_PAREN);
m.complete(p, OP_SIG);
}
fn drop_operator_class(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, OPERATOR_KW) && p.nth_at(2, CLASS_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(OPERATOR_KW);
p.bump(CLASS_KW);
opt_if_exists(p);
path_name_ref(p);
p.expect(USING_KW);
name_ref(p); opt_cascade_or_restrict(p);
m.complete(p, DROP_OPERATOR_CLASS)
}
fn drop_owned(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, OWNED_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(OWNED_KW);
p.expect(BY_KW);
role_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_OWNED)
}
fn drop_policy(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, POLICY_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(POLICY_KW);
opt_if_exists(p);
name_ref(p);
on_table(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_POLICY)
}
fn drop_procedure(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, PROCEDURE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(PROCEDURE_KW);
opt_if_exists(p);
function_sig_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_PROCEDURE)
}
fn drop_publication(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, PUBLICATION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(PUBLICATION_KW);
opt_if_exists(p);
name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_PUBLICATION)
}
fn drop_role(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, ROLE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(ROLE_KW);
opt_if_exists(p);
name_ref_list(p);
m.complete(p, DROP_ROLE)
}
fn drop_routine(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, ROUTINE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(ROUTINE_KW);
opt_if_exists(p);
function_sig_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_ROUTINE)
}
fn drop_rule(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, RULE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(RULE_KW);
opt_if_exists(p);
name_ref(p);
on_table(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_RULE)
}
fn drop_sequence(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, SEQUENCE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(SEQUENCE_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_SEQUENCE)
}
fn drop_server(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, SERVER_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(SERVER_KW);
opt_if_exists(p);
name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_SERVER)
}
fn drop_statistics(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, STATISTICS_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(STATISTICS_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_STATISTICS)
}
fn drop_subscription(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, SUBSCRIPTION_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(SUBSCRIPTION_KW);
opt_if_exists(p);
name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_SUBSCRIPTION)
}
fn opt_cascade_or_restrict(p: &mut Parser<'_>) -> bool {
p.eat(CASCADE_KW) || p.eat(RESTRICT_KW)
}
fn drop_tablespace(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, TABLESPACE_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(TABLESPACE_KW);
opt_if_exists(p);
name_ref(p);
m.complete(p, DROP_TABLESPACE)
}
fn drop_text_search_parser(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(DROP_KW) && p.nth_at(1, TEXT_KW) && p.nth_at(2, SEARCH_KW) && p.nth_at(3, PARSER_KW)
);
let m = p.start();
p.bump(DROP_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(PARSER_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TEXT_SEARCH_PARSER)
}
fn drop_text_search_config(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(DROP_KW)
&& p.nth_at(1, TEXT_KW)
&& p.nth_at(2, SEARCH_KW)
&& p.nth_at(3, CONFIGURATION_KW)
);
let m = p.start();
p.bump(DROP_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(CONFIGURATION_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TEXT_SEARCH_CONFIG)
}
fn drop_text_search_dict(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(DROP_KW)
&& p.nth_at(1, TEXT_KW)
&& p.nth_at(2, SEARCH_KW)
&& p.nth_at(3, DICTIONARY_KW)
);
let m = p.start();
p.bump(DROP_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(DICTIONARY_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TEXT_SEARCH_DICT)
}
fn drop_text_search_template(p: &mut Parser<'_>) -> CompletedMarker {
assert!(
p.at(DROP_KW) && p.nth_at(1, TEXT_KW) && p.nth_at(2, SEARCH_KW) && p.nth_at(3, TEMPLATE_KW)
);
let m = p.start();
p.bump(DROP_KW);
p.bump(TEXT_KW);
p.bump(SEARCH_KW);
p.bump(TEMPLATE_KW);
opt_if_exists(p);
path_name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TEXT_SEARCH_TEMPLATE)
}
fn drop_transform(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, TRANSFORM_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(TRANSFORM_KW);
opt_if_exists(p);
p.expect(FOR_KW);
type_name(p);
p.expect(LANGUAGE_KW);
name_ref(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TRANSFORM)
}
fn drop_user(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, USER_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(USER_KW);
opt_if_exists(p);
name_ref_list(p);
m.complete(p, DROP_USER)
}
fn drop_user_mapping(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, USER_KW) && p.nth_at(2, MAPPING_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(USER_KW);
p.bump(MAPPING_KW);
opt_if_exists(p);
p.expect(FOR_KW);
if !p.eat(USER_KW) {
role_ref(p);
}
server_name(p);
m.complete(p, DROP_USER_MAPPING)
}
fn explain(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(EXPLAIN_KW));
let m = p.start();
p.bump(EXPLAIN_KW);
let pre_pg_9_syntax = p.eat(ANALYZE_KW) || p.eat(VERBOSE_KW);
if !pre_pg_9_syntax {
opt_explain_option_list(p);
}
let statement = stmt(p, &StmtRestrictions::default());
if let Some(statement) = statement {
match statement.kind() {
SELECT
| COMPOUND_SELECT
| SELECT_INTO
| TABLE
| VALUES
| INSERT
| UPDATE
| DELETE
| MERGE
| EXECUTE
| DECLARE
| CREATE_TABLE_AS
| CREATE_MATERIALIZED_VIEW
| PAREN_SELECT => (),
kind => {
p.error(format!(
"expected SELECT, INSERT, UPDATE, DELETE, MERGE, or VALUES statement, got {kind:?}",
));
}
}
} else {
p.error("expected SELECT, INSERT, UPDATE, DELETE, MERGE, VALUES, EXECUTE, DECLARE, CREATE TABLE AS, or CREATE MATERIALIZED VIEW AS");
}
m.complete(p, EXPLAIN)
}
fn opt_explain_option_list(p: &mut Parser<'_>) {
if !p.at(L_PAREN) || (p.at(L_PAREN) && p.nth_at_ts(1, SELECT_FIRST)) {
return;
}
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPLAIN_OPTION_FIRST,
opt_explain_option,
);
}
const EXPLAIN_OPTION_FIRST: TokenSet =
TokenSet::new(&[ANALYZE_KW, ANALYSE_KW, VERBOSE_KW, IDENT, FORMAT_KW]);
fn opt_explain_option(p: &mut Parser<'_>) -> bool {
if !p.at_ts(EXPLAIN_OPTION_FIRST) {
return false;
}
p.bump_any();
if opt_bool_literal(p) {
return true;
}
if p.eat(NONE_KW) || p.eat(TEXT_KW) || p.eat(BINARY_KW) {
return true;
}
if p.eat(TEXT_KW) || p.eat(XML_KW) || p.eat(JSON_KW) || opt_ident(p) {
return true;
}
true
}
fn opt_alter_option_list(p: &mut Parser<'_>) -> bool {
if !p.at(OPTIONS_KW) {
return false;
}
alter_option_list(p);
true
}
fn alter_option_list(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(OPTIONS_KW));
let m = p.start();
p.expect(OPTIONS_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "expected alter option".to_string(),
EXPR_FIRST,
|p| opt_alter_option(p).is_some(),
);
m.complete(p, ALTER_OPTION_LIST)
}
fn import_foreign_schema(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(IMPORT_KW) && p.nth_at(1, FOREIGN_KW));
let m = p.start();
p.bump(IMPORT_KW);
p.bump(FOREIGN_KW);
p.expect(SCHEMA_KW);
name_ref(p);
if p.at(LIMIT_KW) || p.at(EXCEPT_KW) {
let m = p.start();
let kind = if p.eat(LIMIT_KW) {
p.expect(TO_KW);
LIMIT_TO_TABLES
} else {
p.bump(EXCEPT_KW);
EXCEPT_TABLES
};
p.expect(L_PAREN);
name_ref_list(p);
p.expect(R_PAREN);
m.complete(p, kind);
}
p.expect(FROM_KW);
server_name(p);
into_schema(p);
opt_alter_option_list(p);
m.complete(p, IMPORT_FOREIGN_SCHEMA)
}
fn into_schema(p: &mut Parser<'_>) {
let m = p.start();
p.expect(INTO_KW);
name_ref(p);
m.complete(p, INTO_SCHEMA);
}
fn lock(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(LOCK_KW));
let m = p.start();
p.bump(LOCK_KW);
p.eat(TABLE_KW);
table_list(p);
if p.eat(IN_KW) {
match (p.current(), p.nth(1)) {
(ACCESS_KW | ROW_KW, SHARE_KW) => {
p.bump_any();
p.bump(SHARE_KW);
}
(ACCESS_KW | ROW_KW, EXCLUSIVE_KW) => {
p.bump_any();
p.bump(EXCLUSIVE_KW);
}
(SHARE_KW, ROW_KW) => {
p.bump(SHARE_KW);
p.bump(ROW_KW);
p.expect(EXCLUSIVE_KW);
}
(SHARE_KW, UPDATE_KW) => {
p.bump(SHARE_KW);
p.bump(UPDATE_KW);
p.expect(EXCLUSIVE_KW);
}
(SHARE_KW, _) => {
p.bump(SHARE_KW);
}
(EXCLUSIVE_KW, _) => {
p.bump(EXCLUSIVE_KW);
}
_ => p.error("expected lockmode"),
}
p.expect(MODE_KW);
}
p.eat(NOWAIT_KW);
m.complete(p, LOCK)
}
fn table_list(p: &mut Parser<'_>) {
let m = p.start();
relation_name(p);
while !p.at(EOF) && p.eat(COMMA) {
relation_name(p);
}
m.complete(p, TABLE_LIST);
}
fn merge(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(MERGE_KW));
let m = m.unwrap_or_else(|| p.start());
p.bump(MERGE_KW);
p.expect(INTO_KW);
relation_name(p);
opt_as_alias(p);
merge_using_clause(p);
merge_when_clause(p);
while !p.at(EOF) && p.at(WHEN_KW) {
merge_when_clause(p);
}
opt_returning_clause(p);
m.complete(p, MERGE)
}
fn merge_when_clause(p: &mut Parser<'_>) {
let m = p.start();
p.expect(WHEN_KW);
let kind = match p.current() {
MATCHED_KW => {
p.bump(MATCHED_KW);
MERGE_WHEN_MATCHED
}
NOT_KW => {
p.bump(NOT_KW);
p.expect(MATCHED_KW);
if p.eat(BY_KW) {
if p.eat(SOURCE_KW) {
MERGE_WHEN_NOT_MATCHED_SOURCE
} else if p.eat(TARGET_KW) {
MERGE_WHEN_NOT_MATCHED_TARGET
} else {
p.error("expected SOURCE or TARGET");
MERGE_WHEN_NOT_MATCHED_TARGET
}
} else {
MERGE_WHEN_NOT_MATCHED_TARGET
}
}
_ => {
p.error("expected MATCHED, or NOT MATCHED");
MERGE_WHEN_NOT_MATCHED_TARGET
}
};
if p.eat(AND_KW) {
if expr(p).is_none() {
p.error("expected condition");
}
}
p.expect(THEN_KW);
merge_action(p);
m.complete(p, kind);
}
fn merge_action(p: &mut Parser<'_>) {
let m = p.start();
let kind = match p.current() {
DELETE_KW => {
p.bump(DELETE_KW);
MERGE_DELETE
}
UPDATE_KW => {
p.bump(UPDATE_KW);
set_clause(p);
MERGE_UPDATE
}
INSERT_KW => {
p.bump(INSERT_KW);
opt_column_ref_list(p);
if p.eat(OVERRIDING_KW) {
if !p.eat(SYSTEM_KW) && !p.eat(USER_KW) {
p.error("expected SYSTEM or USER");
}
p.expect(VALUE_KW);
}
if p.at(VALUES_KW) {
values(p, None);
} else if p.eat(DEFAULT_KW) {
p.expect(VALUES_KW);
} else {
p.error("expected VALUES or DEFAULT VALUES");
}
MERGE_INSERT
}
DO_KW => {
p.bump(DO_KW);
p.expect(NOTHING_KW);
MERGE_DO_NOTHING
}
_ => {
p.error("expected INSERT, UPDATE, DELETE, or DO NOTHING");
MERGE_DO_NOTHING
}
};
m.complete(p, kind);
}
fn reassign(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(REASSIGN_KW));
let m = p.start();
p.bump(REASSIGN_KW);
p.expect(OWNED_KW);
p.expect(BY_KW);
role_list(p);
p.expect(TO_KW);
role_list(p);
m.complete(p, REASSIGN)
}
fn refresh(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(REFRESH_KW));
let m = p.start();
p.bump(REFRESH_KW);
p.expect(MATERIALIZED_KW);
p.expect(VIEW_KW);
p.eat(CONCURRENTLY_KW);
path_name_ref(p);
opt_with_data(p);
m.complete(p, REFRESH)
}
fn grant(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(GRANT_KW));
let m = p.start();
p.bump(GRANT_KW);
if p.eat(ALL_KW) {
p.eat(PRIVILEGES_KW);
opt_column_ref_list(p);
} else if !p.at(TO_KW) {
revoke_command_list(p);
}
if p.eat(ON_KW) {
privilege_target(p);
}
p.expect(TO_KW);
role_list(p);
if p.eat(WITH_KW) {
grant_role_option_list(p);
}
opt_granted_by(p);
m.complete(p, GRANT)
}
fn revoke_command_list(p: &mut Parser<'_>) {
let m = p.start();
revoke_command(p);
while !p.at(EOF) && p.eat(COMMA) {
revoke_command(p);
}
m.complete(p, REVOKE_COMMAND_LIST);
}
fn grant_role_option_list(p: &mut Parser<'_>) {
if p.eat(GRANT_KW) {
p.expect(OPTION_KW);
return;
}
while p.at_ts(COL_LABEL_FIRST) {
col_label(p);
if !(p.eat(OPTION_KW) || p.eat(TRUE_KW) || p.eat(FALSE_KW)) {
p.error("expected OPTION, TRUE, or FALSE")
}
if !p.eat(COMMA) {
if p.at_ts(COL_LABEL_FIRST) && !p.at(GRANTED_KW) {
p.error("missing comma");
} else {
break;
}
}
}
}
fn privilege_target(p: &mut Parser<'_>) {
if p.eat(ALL_KW) {
match p.current() {
TABLES_KW | SEQUENCES_KW | FUNCTIONS_KW | PROCEDURES_KW | ROUTINES_KW => {
p.bump_any();
p.expect(IN_KW);
p.expect(SCHEMA_KW);
name_ref_list(p);
}
_ => p.error("expected TABLE"),
}
} else {
match p.current() {
PARAMETER_KW => {
p.bump(PARAMETER_KW);
path_name_ref_list(p);
}
FUNCTION_KW | PROCEDURE_KW | ROUTINE_KW => {
p.bump_any();
function_sig_list(p);
}
TYPE_KW => {
p.bump(TYPE_KW);
type_name(p);
while !p.at(EOF) && p.eat(COMMA) {
type_name(p);
}
}
DATABASE_KW | TABLESPACE_KW | SCHEMA_KW | LANGUAGE_KW => {
p.bump_any();
name_ref_list(p);
}
TABLE_KW | SEQUENCE_KW | DOMAIN_KW => {
p.bump_any();
path_name_ref_list(p);
}
FOREIGN_KW => {
p.bump(FOREIGN_KW);
if p.eat(DATA_KW) {
p.expect(WRAPPER_KW);
} else {
p.expect(SERVER_KW);
}
name_ref_list(p);
}
LARGE_KW => {
p.bump(LARGE_KW);
p.expect(OBJECT_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected large_object_oid")
}
while !p.at(EOF) && p.eat(COMMA) {
if opt_numeric_literal(p).is_none() {
p.error("expected large_object_oid")
}
}
}
PROPERTY_KW => {
p.bump(PROPERTY_KW);
p.expect(GRAPH_KW);
path_name_ref_list(p);
}
_ if p.at_ts(COL_LABEL_FIRST) => {
path_name_ref_list(p);
}
_ => (),
}
}
}
fn opt_granted_by(p: &mut Parser<'_>) {
if p.eat(GRANTED_KW) {
p.expect(BY_KW);
role_ref(p);
}
}
fn revoke(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(REVOKE_KW));
let m = p.start();
p.bump(REVOKE_KW);
match p.current() {
ADMIN_KW | INHERIT_KW | GRANT_KW => {
p.bump_any();
p.expect(OPTION_KW);
p.expect(FOR_KW);
}
SET_KW if p.nth_at(1, OPTION_KW) => {
p.bump(SET_KW);
p.bump(OPTION_KW);
p.expect(FOR_KW);
}
_ => (),
}
privileges(p);
if p.eat(ON_KW) {
privilege_target(p);
}
p.expect(FROM_KW);
role_list(p);
opt_granted_by(p);
opt_cascade_or_restrict(p);
m.complete(p, REVOKE)
}
fn privileges(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(ALL_KW) {
p.eat(PRIVILEGES_KW);
} else if !p.at(FROM_KW) {
revoke_command_list(p);
}
opt_column_ref_list(p);
m.complete(p, PRIVILEGES);
}
const REVOKE_COMMAND_FIRST: TokenSet = TokenSet::new(&[
SELECT_KW,
INSERT_KW,
UPDATE_KW,
DELETE_KW,
TRUNCATE_KW,
REFERENCES_KW,
TRIGGER_KW,
IDENT,
ALL_KW,
ALTER_KW,
CREATE_KW,
TEMPORARY_KW,
TEMP_KW,
EXECUTE_KW,
]);
fn revoke_command(p: &mut Parser<'_>) {
let m = p.start();
if !opt_role_ref(p) {
if p.eat(ALTER_KW) {
p.expect(SYSTEM_KW);
} else if p.at_ts(REVOKE_COMMAND_FIRST) {
p.bump_any();
} else {
p.error(format!("expected command name, got {:?}", p.current()))
}
}
opt_column_ref_list(p);
m.complete(p, REVOKE_COMMAND);
}
fn role_ref(p: &mut Parser<'_>) {
if !opt_role_ref(p) {
p.error(format!("expected role, got {:?}", p.current()))
}
}
fn opt_role_ref(p: &mut Parser<'_>) -> bool {
opt_role_(p, ROLE_REF)
}
fn role(p: &mut Parser<'_>) -> bool {
opt_role_(p, ROLE)
}
fn opt_role_(p: &mut Parser<'_>, kind: SyntaxKind) -> bool {
assert!(matches!(kind, ROLE | ROLE_REF));
let func = |p: &mut Parser<'_>| {
if kind == ROLE_REF {
name_ref(p);
} else {
name(p);
}
};
let m = p.start();
match p.current() {
GROUP_KW => {
p.bump(GROUP_KW);
func(p);
}
CURRENT_ROLE_KW | CURRENT_USER_KW | SESSION_USER_KW => {
p.bump_any();
}
ALTER_KW => {
if !p.nth_at(1, SYSTEM_KW) {
p.bump_any();
} else {
m.abandon(p);
return false;
}
}
_ if p.at_ts(NON_RESERVED_WORD) => {
func(p);
}
_ => {
m.abandon(p);
return false;
}
}
m.complete(p, kind);
true
}
fn security_label(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SECURITY_KW) && p.nth_at(1, LABEL_KW));
let m = p.start();
p.bump(SECURITY_KW);
p.bump(LABEL_KW);
opt_for_provider(p);
p.expect(ON_KW);
match p.current() {
TABLE_KW | COLUMN_KW | DATABASE_KW | DOMAIN_KW | PUBLICATION_KW | ROLE_KW | SCHEMA_KW
| SEQUENCE_KW | SUBSCRIPTION_KW | TABLESPACE_KW | TYPE_KW | VIEW_KW => {
p.bump_any();
path_name_ref(p);
}
EVENT_KW => {
p.bump(EVENT_KW);
p.expect(TRIGGER_KW);
path_name_ref(p);
}
FOREIGN_KW => {
p.bump(FOREIGN_KW);
p.expect(TABLE_KW);
path_name_ref(p);
}
PROCEDURAL_KW | LANGUAGE_KW => {
p.eat(PROCEDURAL_KW);
p.expect(LANGUAGE_KW);
path_name_ref(p);
}
LARGE_KW => {
p.bump(LARGE_KW);
p.expect(OBJECT_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected large_object_oid")
}
}
MATERIALIZED_KW => {
p.bump(MATERIALIZED_KW);
p.expect(VIEW_KW);
path_name_ref(p);
}
FUNCTION_KW | PROCEDURE_KW | ROUTINE_KW => {
p.bump_any();
function_sig(p);
}
AGGREGATE_KW => {
p.bump(AGGREGATE_KW);
aggregate(p);
}
_ => p.error("expected database object name"),
}
p.expect(IS_KW);
if !p.eat(NULL_KW) {
string_literal(p);
}
m.complete(p, SECURITY_LABEL)
}
fn opt_for_provider(p: &mut Parser<'_>) {
if p.at(FOR_KW) {
let m = p.start();
p.bump(FOR_KW);
if p.at_ts(STRING_FIRST) {
string_literal(p);
} else {
name_ref(p);
}
m.complete(p, FOR_PROVIDER);
}
}
fn agg_args(p: &mut Parser<'_>) {
match p.current() {
STAR => {
p.bump(STAR);
}
ORDER_KW => {
p.bump(ORDER_KW);
p.expect(BY_KW);
param(p, ParamKind::All);
while !p.at(EOF) {
if p.eat(COMMA) {
param(p, ParamKind::All);
} else {
break;
}
}
}
_ => {
param(p, ParamKind::All);
while !p.at(EOF) {
if p.eat(COMMA) {
param(p, ParamKind::All);
} else {
break;
}
}
if p.eat(ORDER_KW) {
p.expect(BY_KW);
param(p, ParamKind::All);
while !p.at(EOF) {
if p.eat(COMMA) {
param(p, ParamKind::All);
} else {
break;
}
}
}
}
}
}
fn aggregate_arg_list(p: &mut Parser<'_>) {
let m = p.start();
p.expect(L_PAREN);
agg_args(p);
p.expect(R_PAREN);
m.complete(p, PARAM_LIST);
}
fn set_constraints(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW) && p.nth_at(1, CONSTRAINTS_KW));
let m = p.start();
p.bump(SET_KW);
p.bump(CONSTRAINTS_KW);
if !p.eat(ALL_KW) {
path_name_ref_list(p);
}
if !p.eat(DEFERRED_KW) && !p.eat(IMMEDIATE_KW) {
p.error("expected DEFERRED or IMMEDIATE");
}
m.complete(p, SET_CONSTRAINTS)
}
fn set_role(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW) || p.at(RESET_KW));
let m = p.start();
if p.eat(RESET_KW) {
p.expect(ROLE_KW);
} else {
p.bump(SET_KW);
let _ = p.eat(SESSION_KW) || p.eat(LOCAL_KW);
p.expect(ROLE_KW);
if !p.eat(NONE_KW) && opt_string_literal(p).is_none() {
role_ref(p);
}
}
m.complete(p, SET_ROLE)
}
fn set_session_auth(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
p.eat(LOCAL_KW);
p.expect(SESSION_KW);
p.eat(SESSION_KW);
p.expect(AUTHORIZATION_KW);
if !p.eat(DEFAULT_KW) && opt_string_literal(p).is_none() {
role_ref(p);
}
m.complete(p, SET_SESSION_AUTH)
}
fn reset_session_auth(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(RESET_KW));
let m = p.start();
p.bump(RESET_KW);
p.expect(SESSION_KW);
p.expect(AUTHORIZATION_KW);
m.complete(p, RESET_SESSION_AUTH)
}
fn opt_transaction_mode_list(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(TRANSACTION_MODE_FIRST) {
return None;
}
let m = p.start();
while !p.at(EOF) && p.at_ts(TRANSACTION_MODE_FIRST) {
if !opt_transaction_mode(p) {
p.error("expected transaction mode");
}
p.eat(COMMA);
}
Some(m.complete(p, TRANSACTION_MODE_LIST))
}
fn set_transaction(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
if p.eat(SESSION_KW) {
p.expect(CHARACTERISTICS_KW);
p.expect(AS_KW);
p.expect(TRANSACTION_KW);
opt_transaction_mode_list(p);
} else {
p.expect(TRANSACTION_KW);
if p.eat(SNAPSHOT_KW) {
string_literal(p);
} else {
opt_transaction_mode_list(p);
}
}
m.complete(p, SET_TRANSACTION)
}
fn values(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
let m = m.unwrap_or_else(|| p.start());
p.bump(VALUES_KW);
row_list(p);
opt_order_by_clause(p);
opt_limit_clause(p);
opt_offset_clause(p);
opt_fetch_clause(p);
m.complete(p, VALUES)
}
fn row_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
if !p.at(L_PAREN) {
p.err_and_bump("expected L_PAREN");
continue;
}
row(p);
if !p.eat(COMMA) {
if p.at(L_PAREN) {
p.error("expected COMMA");
} else {
break;
}
}
}
m.complete(p, ROW_LIST);
}
fn row(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "expected expression".to_string(),
EXPR_FIRST,
|p| expr(p).is_some(),
);
m.complete(p, ROW);
}
const REINDEX_OPTION_FIRST: TokenSet = TokenSet::new(&[CONCURRENTLY_KW, VERBOSE_KW, TABLESPACE_KW]);
fn opt_reindex_option(p: &mut Parser<'_>) -> bool {
match p.current() {
CONCURRENTLY_KW | VERBOSE_KW => {
p.bump_any();
opt_bool_literal(p);
true
}
TABLESPACE_KW => {
p.bump_any();
name(p);
true
}
_ => false,
}
}
fn reindex(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(REINDEX_KW));
let m = p.start();
p.bump(REINDEX_KW);
if p.at(L_PAREN) {
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
REINDEX_OPTION_FIRST,
opt_reindex_option,
);
}
let name_required = match p.current() {
INDEX_KW | TABLE_KW | SCHEMA_KW => {
p.bump_any();
true
}
DATABASE_KW | SYSTEM_KW => {
p.bump_any();
false
}
_ => {
p.error("expected INDEX, TABLE, SCHEMA, DATABASE, or SYSTEM");
true
}
};
p.eat(CONCURRENTLY_KW);
if opt_path_name_ref(p).is_none() && name_required {
p.error("expected name");
}
m.complete(p, REINDEX)
}
fn drop_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, VIEW_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(VIEW_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_VIEW)
}
fn create_view(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
opt_persistence(p);
p.eat(RECURSIVE_KW);
p.expect(VIEW_KW);
path_name(p);
opt_column_list_with(p, ColumnDefKind::Name);
opt_with_params(p);
p.expect(AS_KW);
match stmt(p, &StmtRestrictions::default()) {
Some(statement) => match statement.kind() {
SELECT | COMPOUND_SELECT | SELECT_INTO | VALUES | TABLE => (),
kind => p.error(format!("expected SELECT, got {kind:?}")),
},
None => p.error("expected SELECT"),
}
if p.eat(WITH_KW) {
let _ = p.eat(CASCADED_KW) | p.eat(LOCAL_KW);
p.expect(CHECK_KW);
p.expect(OPTION_KW);
}
m.complete(p, CREATE_VIEW)
}
fn execute(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(EXECUTE_KW));
let m = p.start();
p.bump(EXECUTE_KW);
name_ref(p);
if p.at(L_PAREN) {
arg_list(p);
}
m.complete(p, EXECUTE)
}
fn prepare(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(PREPARE_KW));
let m = p.start();
p.bump(PREPARE_KW);
name(p);
opt_param_list(p, ParamKind::TypeOnly);
p.expect(AS_KW);
preparable_stmt(p);
m.complete(p, PREPARE)
}
fn unlisten(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(UNLISTEN_KW));
let m = p.start();
p.bump(UNLISTEN_KW);
if !p.eat(STAR) {
name_ref(p);
}
m.complete(p, UNLISTEN)
}
fn checkpoint(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CHECKPOINT_KW));
let m = p.start();
p.bump(CHECKPOINT_KW);
m.complete(p, CHECKPOINT)
}
fn deallocate(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DEALLOCATE_KW));
let m = p.start();
p.bump(DEALLOCATE_KW);
p.eat(PREPARE_KW);
if !p.eat(ALL_KW) {
name_ref(p);
}
m.complete(p, DEALLOCATE)
}
fn load(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(LOAD_KW));
let m = p.start();
p.bump(LOAD_KW);
string_literal(p);
m.complete(p, LOAD)
}
fn listen(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(LISTEN_KW));
let m = p.start();
p.bump(LISTEN_KW);
name(p);
m.complete(p, LISTEN)
}
fn notify(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(NOTIFY_KW));
let m = p.start();
p.bump(NOTIFY_KW);
name_ref(p);
if p.eat(COMMA) {
string_literal(p);
}
m.complete(p, NOTIFY)
}
fn reset(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(RESET_KW));
let m = p.start();
p.bump(RESET_KW);
match p.current() {
ALL_KW => {
p.bump(ALL_KW);
}
SESSION_KW => {
p.bump(SESSION_KW);
p.expect(AUTHORIZATION_KW);
}
TRANSACTION_KW => {
p.bump(TRANSACTION_KW);
p.expect(ISOLATION_KW);
p.expect(LEVEL_KW);
}
TIME_KW => {
p.bump(TIME_KW);
p.expect(ZONE_KW);
}
_ => {
path_name_ref(p);
}
}
m.complete(p, RESET)
}
fn discard(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DISCARD_KW));
let m = p.start();
p.bump(DISCARD_KW);
let _ = p.eat(ALL_KW) || p.eat(PLANS_KW) || p.eat(SEQUENCES_KW) || opt_temp(p);
m.complete(p, DISCARD)
}
fn opt_temp(p: &mut Parser<'_>) -> bool {
p.eat(TEMP_KW) || p.eat(TEMPORARY_KW)
}
fn opt_language(p: &mut Parser<'_>) {
if p.eat(LANGUAGE_KW) {
if p.at_ts(NON_RESERVED_WORD) {
p.bump_any();
} else {
string_literal(p);
}
}
}
fn do_(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DO_KW));
let m = p.start();
p.bump(DO_KW);
opt_language(p);
string_literal(p);
opt_language(p);
m.complete(p, DO)
}
fn declare(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DECLARE_KW));
let m = p.start();
p.bump(DECLARE_KW);
name(p);
p.eat(BINARY_KW);
let _ = p.eat(ASENSITIVE_KW) || p.eat(INSENSITIVE_KW);
if p.eat(NO_KW) {
p.expect(SCROLL_KW);
} else {
p.eat(SCROLL_KW);
}
p.expect(CURSOR_KW);
if p.eat(WITH_KW) || p.eat(WITHOUT_KW) {
p.expect(HOLD_KW);
}
p.expect(FOR_KW);
let statement = stmt(p, &StmtRestrictions::default());
match statement.map(|x| x.kind()) {
Some(SELECT | SELECT_INTO | COMPOUND_SELECT | TABLE | VALUES) => (),
Some(kind) => {
p.error(format!(
"expected SELECT, TABLE, or VALUES statement, got {kind:?}",
));
}
None => {
p.error("expected SELECT, TABLE, or VALUES statement");
}
}
m.complete(p, DECLARE)
}
fn opt_direction(p: &mut Parser<'_>) -> bool {
match p.current() {
NEXT_KW | PRIOR_KW | FIRST_KW | LAST_KW | ALL_KW => {
p.bump_any();
}
RELATIVE_KW | ABSOLUTE_KW => {
p.bump_any();
if opt_numeric_literal(p).is_none() {
p.error("expected count")
}
}
FORWARD_KW | BACKWARD_KW => {
p.bump_any();
if !p.eat(ALL_KW) {
let _ = opt_numeric_literal(p);
}
}
_ if p.at_ts(NUMERIC_FIRST) => {
if opt_numeric_literal(p).is_none() {
p.error("expected count")
}
}
_ => return false,
}
true
}
fn move_(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(MOVE_KW));
let m = p.start();
p.bump(MOVE_KW);
opt_direction(p);
let _ = p.eat(FROM_KW) || p.eat(IN_KW);
name_ref(p);
m.complete(p, MOVE)
}
fn fetch(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(FETCH_KW));
let m = p.start();
p.bump(FETCH_KW);
opt_direction(p);
let _ = p.eat(FROM_KW) || p.eat(IN_KW);
name_ref(p);
m.complete(p, FETCH)
}
fn close(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CLOSE_KW));
let m = p.start();
p.bump(CLOSE_KW);
if !p.eat(ALL_KW) {
name_ref(p);
}
m.complete(p, CLOSE)
}
fn truncate(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(TRUNCATE_KW));
let m = p.start();
p.bump(TRUNCATE_KW);
p.eat(TABLE_KW);
table_list(p);
if p.eat(RESTART_KW) {
p.expect(IDENTITY_KW);
}
if p.eat(CONTINUE_KW) {
p.expect(IDENTITY_KW);
}
opt_cascade_or_restrict(p);
m.complete(p, TRUNCATE)
}
fn vacuum(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(VACUUM_KW));
let m = p.start();
p.bump(VACUUM_KW);
p.eat(FULL_KW);
p.eat(FREEZE_KW);
p.eat(VERBOSE_KW);
let _ = p.eat(ANALYZE_KW) || p.eat(ANALYSE_KW);
opt_vacuum_option_list(p);
opt_table_and_columns_list(p);
m.complete(p, VACUUM)
}
fn opt_vacuum_option_list(p: &mut Parser<'_>) {
if p.at(L_PAREN) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
VACUUM_OPTION_FIRST,
|p| opt_vacuum_option(p).is_some(),
);
m.complete(p, VACUUM_OPTION_LIST);
}
}
fn opt_table_and_columns_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
if !opt_table_and_columns(p) {
m.abandon(p);
return;
}
if !p.eat(COMMA) {
break;
}
}
m.complete(p, TABLE_AND_COLUMNS_LIST);
}
fn opt_table_and_columns(p: &mut Parser<'_>) -> bool {
let m = p.start();
if opt_relation_name(p).is_none() {
m.abandon(p);
return false;
}
opt_column_ref_list(p);
m.complete(p, TABLE_AND_COLUMNS);
true
}
const VACUUM_OPTION_FIRST: TokenSet = NON_RESERVED_WORD
.union(TokenSet::new(&[ANALYZE_KW, ANALYSE_KW, FORMAT_KW, ON_KW]))
.union(NUMERIC_FIRST)
.union(STRING_FIRST)
.union(BOOL_FIRST);
fn opt_vacuum_option(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(VACUUM_OPTION_FIRST) {
return None;
}
let m = p.start();
if p.at_ts(NON_RESERVED_WORD) || p.at(ANALYZE_KW) || p.at(ANALYSE_KW) || p.at(FORMAT_KW) {
p.bump_any();
}
if p.at_ts(NON_RESERVED_WORD) || p.at(ON_KW) {
p.bump_any();
return Some(m.complete(p, VACUUM_OPTION));
}
if opt_numeric_literal(p).is_some() {
return Some(m.complete(p, VACUUM_OPTION));
}
if opt_string_literal(p).is_some() {
return Some(m.complete(p, VACUUM_OPTION));
}
if opt_bool_literal(p) {
return Some(m.complete(p, VACUUM_OPTION));
}
Some(m.complete(p, VACUUM_OPTION))
}
fn opt_copy_option(p: &mut Parser) -> bool {
let m = p.start();
if !opt_col_label(p) {
m.abandon(p);
return false;
}
copy_option_arg(p);
m.complete(p, COPY_OPTION);
true
}
fn copy_option_arg(p: &mut Parser<'_>) {
match p.current() {
STAR | DEFAULT_KW | ON_KW | OFF_KW => {
p.bump_any();
}
L_PAREN => {
copy_option_list(p);
}
_ => {
if p.at_ts(NON_RESERVED_WORD) {
p.bump_any();
return;
}
if opt_numeric_literal(p).is_some() {
return;
}
if opt_string_literal(p).is_some() {
return;
}
if opt_bool_literal(p) {
return;
}
}
}
}
fn copy_option_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
COL_LABEL_FIRST,
opt_copy_option,
);
m.complete(p, COPY_OPTION_LIST);
}
fn opt_copy_option_item(p: &mut Parser<'_>) -> bool {
match p.current() {
BINARY_KW | FREEZE_KW | CSV_KW | HEADER_KW | JSON_KW => {
p.bump_any();
}
DELIMITER_KW | NULL_KW | QUOTE_KW | ESCAPE_KW => {
p.bump_any();
p.eat(AS_KW);
string_literal(p);
}
ENCODING_KW => {
p.bump_any();
string_literal(p);
}
FORCE_KW => {
p.bump_any();
match p.current() {
NOT_KW => {
p.bump_any();
p.expect(NULL_KW);
if !p.eat(STAR) {
name_ref_list(p);
}
}
QUOTE_KW | NULL_KW => {
p.bump_any();
if !p.eat(STAR) {
name_ref_list(p);
}
}
_ => return false,
}
}
_ => return false,
}
true
}
fn copy(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(COPY_KW));
let m = p.start();
p.bump(COPY_KW);
if p.eat(L_PAREN) {
preparable_stmt(p);
p.expect(R_PAREN);
} else {
p.eat(BINARY_KW);
path_name_ref(p);
opt_column_ref_list(p);
}
if p.eat(FROM_KW) {
if p.eat(STDIN_KW) || p.eat(STDOUT_KW) {
} else if p.eat(PROGRAM_KW) {
string_literal(p);
} else {
string_literal(p);
}
} else if p.eat(TO_KW) {
if !p.eat(STDOUT_KW) {
p.eat(PROGRAM_KW);
string_literal(p);
}
}
p.eat(WITH_KW);
if p.at(L_PAREN) {
copy_option_list(p);
} else {
while !p.at(EOF) && opt_copy_option_item(p) {}
}
opt_where_clause(p);
m.complete(p, COPY)
}
fn preparable_stmt(p: &mut Parser<'_>) {
let statement = stmt(p, &StmtRestrictions::default());
match statement.map(|x| x.kind()) {
Some(
SELECT | SELECT_INTO | COMPOUND_SELECT | TABLE | VALUES | INSERT | UPDATE | DELETE
| MERGE | PAREN_SELECT,
) => (),
Some(kind) => {
p.error(format!(
"expected SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE, or MERGE statement, got {kind:?}"
));
}
None => {
p.error("expected SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE, or MERGE statement");
}
}
}
fn call(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CALL_KW));
let m = p.start();
p.bump(CALL_KW);
path_name_ref(p);
if p.at(L_PAREN) {
arg_list(p);
} else {
p.error("expected L_PAREN");
}
m.complete(p, CALL)
}
fn create_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.eat(CONSTRAINT_KW);
p.expect(TRIGGER_KW);
name(p);
timing(p);
trigger_event_list(p);
on_table(p);
opt_from_table(p);
opt_constraint_option_list(p);
opt_referencing_clause(p);
if p.eat(FOR_KW) {
p.eat(EACH_KW);
if p.at(ROW_KW) || p.at(STATEMENT_KW) {
p.bump_any();
} else {
p.error("expected ROW or STATEMENT");
}
}
opt_when_condition(p);
p.expect(EXECUTE_KW);
if !p.eat(FUNCTION_KW) && !p.eat(PROCEDURE_KW) {
p.error("expected FUNCTION or PROCEDURE");
}
call_expr(p);
m.complete(p, CREATE_TRIGGER)
}
fn opt_when_condition(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(WHEN_KW) {
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expression");
}
p.expect(R_PAREN);
m.complete(p, WHEN_CONDITION);
} else {
m.abandon(p);
}
}
fn opt_referencing_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(REFERENCING_KW) {
while !p.at(EOF) {
if !opt_referencing_table(p) {
break;
}
}
m.complete(p, REFERENCING);
} else {
m.abandon(p);
}
}
fn opt_from_table(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(FROM_KW) {
let m = p.start();
p.bump(FROM_KW);
path_name_ref(p);
Some(m.complete(p, FROM_TABLE))
} else {
None
}
}
fn from_table(p: &mut Parser<'_>) {
if opt_from_table(p).is_none() {
p.error("expected from table");
}
}
fn trigger_event_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
trigger_event(p);
if !p.eat(OR_KW) {
break;
}
}
m.complete(p, TRIGGER_EVENT_LIST);
}
fn trigger_event(p: &mut Parser<'_>) {
let m = p.start();
if p.at(UPDATE_KW) {
let m = p.start();
p.bump(UPDATE_KW);
if p.eat(OF_KW) {
name_ref_list(p);
}
m.complete(p, TRIGGER_EVENT_UPDATE);
} else if !(p.eat(INSERT_KW) || p.eat(DELETE_KW) || p.eat(TRUNCATE_KW)) {
p.error("expected INSERT, UPDATE, DELETE, or TRUNCATE");
}
m.complete(p, TRIGGER_EVENT);
}
fn timing(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(INSTEAD_KW) {
p.expect(OF_KW);
} else if !p.eat(BEFORE_KW) && !p.eat(AFTER_KW) {
p.error("expected BEFORE, AFTER, or INSTEAD OF");
}
m.complete(p, TIMING);
}
fn call_expr(p: &mut Parser<'_>) {
match expr(p).map(|x| x.kind()) {
Some(CALL_EXPR) => (),
_ => p.error("expected call expression"),
}
}
fn opt_referencing_table(p: &mut Parser<'_>) -> bool {
if !(p.at(OLD_KW) || p.at(NEW_KW)) {
return false;
}
let m = p.start();
p.bump_any();
p.expect(TABLE_KW);
p.eat(AS_KW);
name_ref(p);
m.complete(p, REFERENCING_TABLE);
true
}
fn drop_schema(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW) && p.nth_at(1, SCHEMA_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(SCHEMA_KW);
opt_if_exists(p);
name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_SCHEMA)
}
fn opt_schema_elements(p: &mut Parser<'_>) {
while !p.at(EOF) {
match (p.current(), p.nth(1)) {
(CREATE_KW, TABLE_KW | GLOBAL_KW | LOCAL_KW | UNLOGGED_KW)
if !p.nth_at(2, SEQUENCE_KW) =>
{
create_table(p);
}
(CREATE_KW, TEMP_KW | TEMPORARY_KW) => {
match p.nth(2) {
RECURSIVE_KW | VIEW_KW => create_view(p),
SEQUENCE_KW => create_sequence(p),
_ => create_table(p),
};
}
(CREATE_KW, OR_KW) => {
match p.nth(3) {
AGGREGATE_KW => create_aggregate(p),
CONSTRAINT_KW | TRIGGER_KW => create_trigger(p),
PROCEDURE_KW => create_procedure(p),
RECURSIVE_KW | TEMP_KW | TEMPORARY_KW | VIEW_KW => create_view(p),
_ => create_function(p),
};
}
(CREATE_KW, RECURSIVE_KW | VIEW_KW) => {
create_view(p);
}
(CREATE_KW, UNLOGGED_KW) if p.nth_at(2, SEQUENCE_KW) => {
create_sequence(p);
}
(CREATE_KW, SEQUENCE_KW) => {
create_sequence(p);
}
(CREATE_KW, CONSTRAINT_KW | TRIGGER_KW) => {
create_trigger(p);
}
(CREATE_KW, INDEX_KW | UNIQUE_KW) => {
create_index(p);
}
(CREATE_KW, AGGREGATE_KW) => {
create_aggregate(p);
}
(CREATE_KW, COLLATION_KW) => {
create_collation(p);
}
(CREATE_KW, DOMAIN_KW) => {
create_domain(p);
}
(CREATE_KW, FUNCTION_KW) => {
create_function(p);
}
(CREATE_KW, OPERATOR_KW) => {
match p.nth(2) {
CLASS_KW => create_operator_class(p),
FAMILY_KW => create_operator_family(p),
_ => create_operator(p),
};
}
(CREATE_KW, PROCEDURE_KW) => {
create_procedure(p);
}
(CREATE_KW, TEXT_KW) if p.nth_at(2, SEARCH_KW) => {
match p.nth(3) {
CONFIGURATION_KW => create_text_search_config(p),
DICTIONARY_KW => create_text_search_dict(p),
PARSER_KW => create_text_search_parser(p),
TEMPLATE_KW => create_text_search_template(p),
_ => return,
};
}
(CREATE_KW, TYPE_KW) => {
create_type(p);
}
(GRANT_KW, _) => {
grant(p);
}
_ => return,
};
}
}
fn create_schema(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW) && p.nth_at(1, SCHEMA_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(SCHEMA_KW);
let if_not_exists = opt_if_not_exists(p).is_some();
match (if_not_exists, p.eat(AUTHORIZATION_KW)) {
(true, true) => {
role(p);
m.complete(p, CREATE_SCHEMA)
}
(true, false) => {
name(p);
if p.eat(AUTHORIZATION_KW) {
role_ref(p);
}
m.complete(p, CREATE_SCHEMA)
}
(false, true) => {
role(p);
opt_schema_elements(p);
m.complete(p, CREATE_SCHEMA)
}
(false, false) => {
name(p);
if p.eat(AUTHORIZATION_KW) {
role_ref(p);
}
opt_schema_elements(p);
m.complete(p, CREATE_SCHEMA)
}
}
}
fn query(p: &mut Parser<'_>) {
if (!p.at_ts(SELECT_FIRST) || select(p, None, &SelectRestrictions::default()).is_none())
&& opt_paren_select(p, None).is_none()
{
p.error("expected select stmt")
}
}
fn insert(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(INSERT_KW));
let m = m.unwrap_or_else(|| p.start());
p.bump(INSERT_KW);
p.expect(INTO_KW);
path_name_ref(p);
opt_as_alias_with_as(p);
opt_column_ref_list(p);
if p.eat(OVERRIDING_KW) {
let _ = p.eat(SYSTEM_KW) || p.expect(USER_KW);
p.expect(VALUE_KW);
}
if p.eat(DEFAULT_KW) {
p.expect(VALUES_KW);
} else if p.at(VALUES_KW) {
values(p, None);
} else {
query(p);
}
opt_on_conflict_clause(p);
opt_returning_clause(p);
m.complete(p, INSERT)
}
fn opt_on_conflict_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(ON_KW) {
p.expect(CONFLICT_KW);
opt_conflict_target(p);
conflict_action(p);
m.complete(p, ON_CONFLICT_CLAUSE);
} else {
m.abandon(p);
}
}
fn conflict_on_constraint(p: &mut Parser<'_>) {
assert!(p.at(ON_KW));
let m = p.start();
p.expect(ON_KW);
p.expect(CONSTRAINT_KW);
name_ref(p);
m.complete(p, CONFLICT_ON_CONSTRAINT);
}
fn opt_conflict_target(p: &mut Parser<'_>) {
if p.at(ON_KW) {
conflict_on_constraint(p);
} else if p.at(L_PAREN) {
conflict_on_index(p);
}
}
fn conflict_on_index(p: &mut Parser<'_>) {
assert!(p.at(L_PAREN));
let m = p.start();
conflict_index_item_list(p);
opt_where_clause(p);
m.complete(p, CONFLICT_ON_INDEX);
}
fn conflict_action(p: &mut Parser<'_>) {
let m = p.start();
p.expect(DO_KW);
if p.eat(NOTHING_KW) {
m.complete(p, CONFLICT_DO_NOTHING);
} else if p.eat(SELECT_KW) {
opt_locking_clause(p);
opt_where_clause(p);
m.complete(p, CONFLICT_DO_SELECT);
} else {
p.expect(UPDATE_KW);
set_clause(p);
opt_where_clause(p);
m.complete(p, CONFLICT_DO_UPDATE_SET);
}
}
fn opt_conflict_index_item(p: &mut Parser<'_>) -> bool {
if !p.at_ts(EXPR_FIRST) {
return false;
}
let m = p.start();
if expr(p).is_none() {
p.error("expected expression");
}
opt_collate(p);
opt_ident(p);
m.complete(p, CONFLICT_INDEX_ITEM);
true
}
fn conflict_index_item_list(p: &mut Parser<'_>) {
assert!(p.at(L_PAREN));
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
opt_conflict_index_item,
);
m.complete(p, CONFLICT_INDEX_ITEM_LIST);
}
fn set_clause(p: &mut Parser<'_>) {
let m = p.start();
p.expect(SET_KW);
set_column_list(p);
m.complete(p, SET_CLAUSE);
}
fn set_column_list(p: &mut Parser<'_>) {
let m = p.start();
separated(
p,
COMMA,
|| "unexpected comma".to_string(),
SET_COLUMN_FIRST,
SET_COLUMN_FOLLOW,
|p| opt_set_column(p).is_some(),
);
m.complete(p, SET_COLUMN_LIST);
}
const SET_COLUMN_FIRST: TokenSet = TokenSet::new(&[L_PAREN]).union(COLUMN_FIRST);
const SET_COLUMN_FOLLOW: TokenSet = TokenSet::new(&[FROM_KW, WHERE_KW, RETURNING_KW]);
fn opt_set_column(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(SET_COLUMN_FIRST) {
return None;
}
let m = p.start();
if p.at(L_PAREN) {
column_ref_list(p);
p.expect(EQ);
set_expr_list_or_paren_select(p);
Some(m.complete(p, SET_MULTIPLE_COLUMNS))
} else {
column(p, ColumnDefKind::NameRef);
p.expect(EQ);
set_expr(p);
Some(m.complete(p, SET_SINGLE_COLUMN))
}
}
fn set_expr_list_or_paren_select(p: &mut Parser<'_>) {
let m = p.start();
p.eat(ROW_KW);
if p.at(L_PAREN) {
if p.nth_at(1, SELECT_KW) {
if opt_paren_select(p, Some(m)).is_none() {
p.error("expected sub-SELECT");
}
} else {
set_expr_list(p, m);
}
} else {
p.error("expected row expression or sub-select");
m.abandon(p);
}
}
fn set_expr_list(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(L_PAREN));
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
SET_EXPR_FIRST,
opt_set_expr,
);
m.complete(p, SET_EXPR_LIST);
}
fn opt_set_expr(p: &mut Parser<'_>) -> bool {
if !p.at_ts(SET_EXPR_FIRST) {
return false;
}
set_expr(p);
true
}
const SET_EXPR_FIRST: TokenSet = TokenSet::new(&[DEFAULT_KW]).union(EXPR_FIRST);
fn set_expr(p: &mut Parser<'_>) {
let m = p.start();
if !p.eat(DEFAULT_KW) && expr(p).is_none() {
p.error("expected expression");
}
m.complete(p, SET_EXPR);
}
fn opt_as_alias_with_as(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(AS_KW) {
let m = p.start();
p.bump(AS_KW);
if p.at_ts(NAME_FIRST) {
name(p);
} else {
p.error("col id")
}
Some(m.complete(p, ALIAS))
} else {
None
}
}
fn opt_as_alias(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(AS_KW) {
opt_as_alias_with_as(p)
} else if p.at_ts(NAME_FIRST) {
let m = p.start();
opt_name(p);
Some(m.complete(p, ALIAS))
} else {
None
}
}
fn update(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(UPDATE_KW));
let m = m.unwrap_or_else(|| p.start());
p.bump(UPDATE_KW);
relation_name(p);
opt_for_portion_of(p);
if !p.at(SET_KW) {
opt_as_alias(p);
}
set_clause(p);
opt_from_clause(p);
opt_where_or_current_of(p);
opt_returning_clause(p);
m.complete(p, UPDATE)
}
fn opt_for_portion_of(p: &mut Parser<'_>) {
if !p.at(FOR_KW) {
return;
}
let m = p.start();
p.expect(FOR_KW);
p.expect(PORTION_KW);
p.expect(OF_KW);
name_ref(p);
for_portion_of_target(p);
m.complete(p, FOR_PORTION_OF);
}
fn for_portion_of_target(p: &mut Parser<'_>) {
if p.eat(L_PAREN) {
expr(p);
p.expect(R_PAREN);
} else {
p.expect(FROM_KW);
expr(p);
p.expect(TO_KW);
expr(p);
}
}
fn opt_where_or_current_of(p: &mut Parser<'_>) {
if p.at(WHERE_KW) {
if p.nth_at(1, CURRENT_KW) {
opt_where_current_of(p);
} else {
opt_where_clause(p);
}
}
}
fn with(p: &mut Parser<'_>, m: Option<Marker>) -> Option<CompletedMarker> {
let m = m.unwrap_or_else(|| p.start());
with_query_clause(p);
match p.current() {
DELETE_KW => Some(delete(p, Some(m))),
SELECT_KW | TABLE_KW | VALUES_KW | FROM_KW => {
select(p, Some(m), &SelectRestrictions::default())
}
INSERT_KW => Some(insert(p, Some(m))),
UPDATE_KW => Some(update(p, Some(m))),
MERGE_KW => Some(merge(p, Some(m))),
L_PAREN if p.nth_at_ts(1, PAREN_SELECT_FIRST) => {
opt_paren_select(p, Some(m))
}
_ => {
m.abandon(p);
p.error(format!(
"expected DELETE, SELECT, TABLE, UPDATE, VALUES, or MERGE, got: {:?}",
p.current()
));
None
}
}
}
fn delete(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(DELETE_KW));
let m = m.unwrap_or_else(|| p.start());
p.bump(DELETE_KW);
p.expect(FROM_KW);
relation_name(p);
opt_for_portion_of(p);
if !p.at(FOR_KW) {
opt_as_alias(p);
}
opt_using_clause(p);
opt_where_or_current_of(p);
opt_returning_clause(p);
m.complete(p, DELETE)
}
fn opt_using_clause(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(USING_KW) {
while p.at_ts(FROM_ITEM_FIRST) {
if !opt_from_item(p) || !p.eat(COMMA) {
break;
}
}
m.complete(p, USING_CLAUSE);
} else {
m.abandon(p);
}
}
fn opt_where_current_of(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(WHERE_KW) {
if p.eat(CURRENT_KW) {
p.expect(OF_KW);
name_ref(p);
}
m.complete(p, WHERE_CURRENT_OF);
} else {
m.abandon(p);
}
}
fn opt_returning_clause(p: &mut Parser<'_>) {
if p.at(RETURNING_KW) {
let m = p.start();
p.bump(RETURNING_KW);
opt_returning_option_list(p);
if opt_target_list(p).is_none() {
p.error("expected target");
}
m.complete(p, RETURNING_CLAUSE);
}
}
fn opt_returning_option_list(p: &mut Parser<'_>) {
if p.at(WITH_KW) {
let m = p.start();
p.bump(WITH_KW);
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
RETURNING_OPTION_FIRST,
opt_returning_option,
);
m.complete(p, RETURNING_OPTION_LIST);
}
}
const RETURNING_OPTION_FIRST: TokenSet = TokenSet::new(&[OLD_KW, NEW_KW]);
fn opt_returning_option(p: &mut Parser<'_>) -> bool {
if !p.at_ts(RETURNING_OPTION_FIRST) {
return false;
}
let m = p.start();
p.bump_any();
p.expect(AS_KW);
name(p);
m.complete(p, RETURNING_OPTION);
true
}
fn drop_type(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump(TYPE_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TYPE)
}
fn drop_trigger(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.expect(TRIGGER_KW);
opt_if_exists(p);
path_name_ref(p);
on_table(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_TRIGGER)
}
fn on_table(p: &mut Parser<'_>) {
let m = p.start();
p.expect(ON_KW);
path_name_ref(p);
m.complete(p, ON_TABLE);
}
fn drop_index(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.expect(INDEX_KW);
p.eat(CONCURRENTLY_KW);
opt_if_exists(p);
path_name_ref_list(p);
opt_cascade_or_restrict(p);
m.complete(p, DROP_INDEX)
}
const DROP_DATABASE_OPTION_FIRST: TokenSet = TokenSet::new(&[FORCE_KW]);
fn drop_database(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.expect(DATABASE_KW);
opt_if_exists(p);
name_ref(p);
if p.at(L_PAREN) || p.eat(WITH_KW) {
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
DROP_DATABASE_OPTION_FIRST,
|p| p.eat(FORCE_KW),
);
}
m.complete(p, DROP_DATABASE)
}
fn create_index(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.eat(UNIQUE_KW);
p.bump(INDEX_KW);
p.eat(CONCURRENTLY_KW);
if opt_if_not_exists(p).is_some() {
name(p);
} else if p.at_ts(NAME_FIRST) {
opt_name(p);
}
p.expect(ON_KW);
relation_name(p);
opt_using_method(p);
partition_items(p, true);
opt_include_columns(p);
opt_nulls_not_distinct(p);
opt_with_params(p);
opt_tablespace(p);
opt_where_clause(p);
m.complete(p, CREATE_INDEX)
}
fn partition_items(p: &mut Parser<'_>, allow_extra_params: bool) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
EXPR_FIRST,
|p| opt_partition_item(p, allow_extra_params).is_some(),
);
m.complete(p, PARTITION_ITEM_LIST);
}
const PARAM_MODE_FIRST: TokenSet = TokenSet::new(&[VARIADIC_KW, IN_KW, OUT_KW, INOUT_KW]);
fn opt_param_mode(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(PARAM_MODE_FIRST) {
return None;
}
let m = p.start();
let mode = match p.current() {
VARIADIC_KW => {
p.bump(VARIADIC_KW);
PARAM_VARIADIC
}
IN_KW => {
p.bump(IN_KW);
if p.eat(OUT_KW) {
PARAM_IN_OUT
} else {
PARAM_IN
}
}
OUT_KW => {
p.bump(OUT_KW);
PARAM_OUT
}
INOUT_KW => {
p.bump(INOUT_KW);
PARAM_IN_OUT
}
_ => {
m.abandon(p);
return None;
}
};
Some(m.complete(p, mode))
}
fn opt_param_default(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(DEFAULT_KW) || p.at(EQ) {
let m = p.start();
p.bump_any();
if expr(p).is_none() {
p.error("expected default expr for func arg");
}
Some(m.complete(p, PARAM_DEFAULT))
} else {
None
}
}
const TYPE_FUNC_NAME_KEYWORDS: TokenSet = TokenSet::new(&[
AUTHORIZATION_KW,
BINARY_KW,
COLLATION_KW,
CONCURRENTLY_KW,
CROSS_KW,
CURRENT_SCHEMA_KW,
FREEZE_KW,
FULL_KW,
ILIKE_KW,
INNER_KW,
IS_KW,
ISNULL_KW,
JOIN_KW,
LEFT_KW,
LIKE_KW,
NATURAL_KW,
NOTNULL_KW,
OUTER_KW,
OVERLAPS_KW,
RIGHT_KW,
SIMILAR_KW,
TABLESAMPLE_KW,
VERBOSE_KW,
]);
const PARAM_FIRST: TokenSet = PARAM_MODE_FIRST.union(NAME_FIRST).union(TYPE_NAME_FIRST);
fn opt_param(p: &mut Parser<'_>, kind: ParamKind) -> bool {
if !p.at_ts(PARAM_FIRST) {
return false;
}
param(p, kind);
true
}
fn param(p: &mut Parser<'_>, kind: ParamKind) {
let m = p.start();
match kind {
ParamKind::All => {
let param_mode_seen = opt_param_mode(p).is_some();
let maybe_name =
p.at(IDENT) || p.at_ts(UNRESERVED_KEYWORDS) || p.at_ts(TYPE_FUNC_NAME_KEYWORDS);
if maybe_name {
let at_type = match p.nth(1) {
DOT => true,
L_PAREN => true,
L_BRACK => true,
ORDER_KW => true,
PRECISION_KW if p.at(DOUBLE_KW) => true,
R_PAREN | EQ | DEFAULT_KW | COMMA => true,
_ => false,
};
if at_type {
type_name(p);
} else {
name(p);
if !param_mode_seen {
opt_param_mode(p);
}
type_name(p);
}
} else {
type_name(p);
}
opt_param_default(p);
}
ParamKind::TypeOnly => {
type_name(p);
}
}
m.complete(p, PARAM);
}
fn opt_function_option(p: &mut Parser<'_>) -> bool {
let m = p.start();
let kind = match p.current() {
LANGUAGE_KW => {
p.bump(LANGUAGE_KW);
if opt_string_literal(p).is_none() {
if p.at_ts(UNRESERVED_KEYWORDS) || p.at(IDENT) {
if !opt_ident(p) {
p.bump_any();
}
} else {
p.error(format!("expected a language name, got {:?}", p.current()));
}
}
LANGUAGE_FUNC_OPTION
}
TRANSFORM_KW => {
p.bump(TRANSFORM_KW);
while !p.at(EOF) {
p.expect(FOR_KW);
p.expect(TYPE_KW);
type_name(p);
if !p.eat(COMMA) {
break;
}
}
TRANSFORM_FUNC_OPTION
}
WINDOW_KW => {
p.bump(WINDOW_KW);
WINDOW_FUNC_OPTION
}
IMMUTABLE_KW | STABLE_KW | VOLATILE_KW => {
p.bump_any();
VOLATILITY_FUNC_OPTION
}
NOT_KW | LEAKPROOF_KW => {
p.eat(NOT_KW);
p.expect(LEAKPROOF_KW);
LEAKPROOF_FUNC_OPTION
}
RESET_KW => {
p.bump(RESET_KW);
if !p.eat(ALL_KW) {
path_name_ref(p);
}
RESET_FUNC_OPTION
}
CALLED_KW | RETURNS_KW | STRICT_KW => {
if p.eat(CALLED_KW) {
p.expect(ON_KW);
p.expect(NULL_KW);
p.expect(INPUT_KW);
} else if p.eat(RETURNS_KW) {
p.expect(NULL_KW);
p.expect(ON_KW);
p.expect(NULL_KW);
p.expect(INPUT_KW);
} else {
p.expect(STRICT_KW);
}
STRICT_FUNC_OPTION
}
EXTERNAL_KW | SECURITY_KW => {
p.eat(EXTERNAL_KW);
p.expect(SECURITY_KW);
let _ = p.eat(INVOKER_KW) || p.expect(DEFINER_KW);
SECURITY_FUNC_OPTION
}
PARALLEL_KW => {
p.bump(PARALLEL_KW);
ident(p);
PARALLEL_FUNC_OPTION
}
COST_KW => {
p.bump(COST_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric value for execution_cost");
}
COST_FUNC_OPTION
}
ROWS_KW => {
p.bump(ROWS_KW);
if opt_numeric_literal(p).is_none() {
p.error("expected numeric value for result_rows");
}
ROWS_FUNC_OPTION
}
SUPPORT_KW => {
p.bump(SUPPORT_KW);
path_name_ref(p);
SUPPORT_FUNC_OPTION
}
SET_KW => {
set_configuration_param(p);
SET_FUNC_OPTION
}
AS_KW => {
p.bump(AS_KW);
string_literal(p);
if p.eat(COMMA) {
string_literal(p);
}
AS_FUNC_OPTION
}
RETURN_KW => {
p.bump(RETURN_KW);
if expr(p).is_none() {
p.error("expected expression for return");
}
RETURN_FUNC_OPTION
}
BEGIN_KW => {
p.bump(BEGIN_KW);
p.expect(ATOMIC_KW);
while !p.at(EOF) && !p.at(END_KW) {
if p.eat(SEMICOLON) {
continue;
}
begin_func_option(p);
if p.at(END_KW) {
p.expect(SEMICOLON);
}
}
p.expect(END_KW);
BEGIN_FUNC_OPTION_LIST
}
_ => {
m.abandon(p);
return false;
}
};
m.complete(p, kind);
true
}
fn begin_func_option(p: &mut Parser<'_>) {
let m = p.start();
if p.at(RETURN_KW) {
let m = p.start();
p.bump(RETURN_KW);
if expr(p).is_none() {
p.error("expected expr")
}
m.complete(p, RETURN_FUNC_OPTION);
} else {
stmt(p, &StmtRestrictions::default());
}
m.complete(p, BEGIN_FUNC_OPTION);
}
fn set_configuration_param(p: &mut Parser<'_>) {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
path_name_ref(p);
if p.eat(FROM_KW) {
p.expect(CURRENT_KW);
} else if (p.eat(TO_KW) || p.expect(EQ)) && !config_value(p) {
p.error(format!("expected config value, got {:?}", p.current()));
}
m.complete(p, SET_CONFIG_PARAM);
}
fn opt_ret_type(p: &mut Parser<'_>) {
let m = p.start();
if p.eat(RETURNS_KW) {
if p.eat(TABLE_KW) {
if p.at(L_PAREN) {
table_arg_list(p);
} else {
p.error("expected table arg list");
}
} else {
type_name(p);
}
m.complete(p, RET_TYPE);
} else {
m.abandon(p);
}
}
fn func_option_list(p: &mut Parser<'_>) {
let m = p.start();
let mut seen_func_option = false;
while !p.at(EOF) {
if !opt_function_option(p) {
if !seen_func_option {
p.error("expected function option");
}
break;
} else {
seen_func_option = true
}
}
if !seen_func_option {
m.abandon(p);
return;
}
m.complete(p, FUNC_OPTION_LIST);
}
fn opt_param_list(p: &mut Parser<'_>, kind: ParamKind) -> bool {
if !p.at(L_PAREN) {
return false;
}
param_list(p, kind);
true
}
#[derive(PartialEq, Clone, Copy)]
enum ParamKind {
All,
TypeOnly,
}
fn param_list(p: &mut Parser<'_>, kind: ParamKind) {
if !p.at(L_PAREN) {
p.error("expected param list");
return;
}
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
PARAM_FIRST,
|p| opt_param(p, kind),
);
m.complete(p, PARAM_LIST);
}
fn create_function(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
opt_or_replace(p);
p.expect(FUNCTION_KW);
path_name(p);
param_list(p, ParamKind::All);
opt_ret_type(p);
func_option_list(p);
m.complete(p, CREATE_FUNCTION)
}
fn opt_or_replace(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at(OR_KW) {
let m = p.start();
p.expect(OR_KW);
p.expect(REPLACE_KW);
Some(m.complete(p, OR_REPLACE))
} else {
None
}
}
fn create_type(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(TYPE_KW);
path_name(p);
if p.eat(AS_KW) {
if p.eat(ENUM_KW) {
variant_list(p);
} else if p.eat(RANGE_KW) {
attribute_list(p);
} else {
if !opt_column_list_with(p, ColumnDefKind::WithData) {
p.error("expected column list");
}
}
} else if p.at(L_PAREN) {
attribute_list(p);
}
m.complete(p, CREATE_TYPE)
}
fn opt_variant(p: &mut Parser<'_>) -> bool {
let m = p.start();
if opt_string_literal(p).is_none() {
m.abandon(p);
return false;
}
m.complete(p, VARIANT);
true
}
fn variant_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
STRING_FIRST,
opt_variant,
);
m.complete(p, VARIANT_LIST);
}
fn create_extension(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(CREATE_KW));
let m = p.start();
p.bump(CREATE_KW);
p.bump(EXTENSION_KW);
opt_if_not_exists(p);
name(p);
p.eat(WITH_KW);
if p.eat(SCHEMA_KW) {
name_ref(p);
}
if p.eat(VERSION_KW) {
if opt_string_literal(p).is_none() && !opt_ident(p) {
p.error("expected string literal or IDENT");
}
}
p.eat(CASCADE_KW);
m.complete(p, CREATE_EXTENSION)
}
fn opt_ident(p: &mut Parser<'_>) -> bool {
if p.eat(IDENT) {
if p.eat(UESCAPE_KW) {
p.expect(STRING);
}
true
} else {
false
}
}
fn ident(p: &mut Parser<'_>) {
if !opt_ident(p) {
p.error("expected identifier");
}
}
fn config_value(p: &mut Parser<'_>) -> bool {
if p.eat(DEFAULT_KW) {
return true;
}
let mut found_value = false;
while !p.at(EOF) {
if opt_string_literal(p).is_none()
&& opt_numeric_literal(p).is_none()
&& opt_name_ref(p).is_none()
&& !opt_bool_literal(p)
&& !p.eat(NULL_KW)
{
break;
}
found_value = true;
if !p.eat(COMMA) {
break;
}
}
found_value
}
fn set(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SET_KW));
let m = p.start();
p.bump(SET_KW);
let _ = p.eat(SESSION_KW) || p.eat(LOCAL_KW);
if p.eat(XML_KW) {
p.expect(OPTION_KW);
let _ = p.eat(DOCUMENT_KW) || p.eat(CONTENT_KW);
} else
if p.eat(TIME_KW) {
p.expect(ZONE_KW);
if !p.eat(LOCAL_KW) && !config_value(p) {
p.error(format!("expected config value, got {:?}", p.current()));
}
} else if p.eat(CATALOG_KW) || p.eat(SCHEMA_KW) {
string_literal(p);
} else {
path_name_ref(p);
if p.eat(FROM_KW) {
p.expect(CURRENT_KW);
} else {
let _ = p.eat(TO_KW) || p.expect(EQ);
if !config_value(p) {
p.error(format!("expected config value, got {:?}", p.current()));
}
}
}
m.complete(p, SET)
}
fn show(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(SHOW_KW));
let m = p.start();
p.bump(SHOW_KW);
match p.current() {
ALL_KW => {
p.bump(ALL_KW);
}
SESSION_KW => {
p.bump(SESSION_KW);
p.expect(AUTHORIZATION_KW);
}
TRANSACTION_KW => {
p.bump(TRANSACTION_KW);
p.expect(ISOLATION_KW);
p.expect(LEVEL_KW);
}
TIME_KW => {
p.bump(TIME_KW);
p.expect(ZONE_KW);
}
_ => {
path_name_ref(p);
}
}
m.complete(p, SHOW)
}
const COLUMN_FIRST: TokenSet = TokenSet::new(&[IDENT])
.union(UNRESERVED_KEYWORDS)
.union(COLUMN_OR_TABLE_KEYWORDS);
const NON_RESERVED_WORD: TokenSet = TokenSet::new(&[IDENT])
.union(UNRESERVED_KEYWORDS)
.union(COLUMN_NAME_KEYWORDS)
.union(TYPE_FUNC_NAME_KEYWORDS);
const RELATION_NAME_FIRST: TokenSet = TokenSet::new(&[ONLY_KW]).union(PATH_FIRST);
fn relation_name(p: &mut Parser<'_>) {
if opt_relation_name(p).is_none() {
p.error("expected relation name");
}
}
fn opt_relation_name(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(RELATION_NAME_FIRST) {
return None;
}
let m = p.start();
if p.eat(ONLY_KW) {
let trailing_paren = p.eat(L_PAREN);
path_name_ref(p);
if trailing_paren {
p.expect(R_PAREN);
}
} else {
path_name_ref(p);
p.eat(STAR);
}
Some(m.complete(p, RELATION_NAME))
}
fn alter_table(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(ALTER_KW));
let m = p.start();
p.bump(ALTER_KW);
p.expect(TABLE_KW);
let mut all_in_tablespace = false;
if p.eat(ALL_KW) {
p.expect(IN_KW);
p.expect(TABLESPACE_KW);
all_in_tablespace = true;
} else {
opt_if_exists(p);
}
relation_name(p);
if all_in_tablespace {
opt_owned_by_roles(p);
}
opt_alter_table_action_list(p);
m.complete(p, ALTER_TABLE)
}
fn opt_owned_by_roles(p: &mut Parser<'_>) {
if !p.at(OWNED_KW) {
return;
}
let m = p.start();
p.bump(OWNED_KW);
p.expect(BY_KW);
role_list(p);
m.complete(p, OWNED_BY_ROLES);
}
const ALTER_TABLE_ACTION_FIRST: TokenSet = TokenSet::new(&[
VALIDATE_KW,
REPLICA_KW,
OF_KW,
NOT_KW,
FORCE_KW,
NO_KW,
INHERIT_KW,
ENABLE_KW,
DISABLE_KW,
CLUSTER_KW,
OWNER_KW,
DETACH_KW,
MERGE_KW,
SPLIT_KW,
DROP_KW,
ADD_KW,
ATTACH_KW,
SET_KW,
RESET_KW,
RENAME_KW,
ALTER_KW,
OPTIONS_KW,
]);
fn opt_alter_table_action(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if !p.at_ts(ALTER_TABLE_ACTION_FIRST) {
return None;
}
let cm = match p.current() {
VALIDATE_KW => {
let m = p.start();
p.bump(VALIDATE_KW);
p.expect(CONSTRAINT_KW);
name_ref(p);
m.complete(p, VALIDATE_CONSTRAINT)
}
REPLICA_KW => {
let m = p.start();
p.bump(REPLICA_KW);
p.expect(IDENTITY_KW);
if !p.eat(DEFAULT_KW) && !p.eat(FULL_KW) && !p.eat(NOTHING_KW) {
p.expect(USING_KW);
p.expect(INDEX_KW);
name_ref(p);
}
m.complete(p, REPLICA_IDENTITY)
}
OF_KW => {
let m = p.start();
p.bump(OF_KW);
simple_type_name(p);
m.complete(p, OF_TYPE)
}
NOT_KW if p.nth_at(1, OF_KW) => {
let m = p.start();
p.bump(NOT_KW);
p.bump(OF_KW);
m.complete(p, NOT_OF)
}
FORCE_KW => {
let m = p.start();
p.bump(FORCE_KW);
p.expect(ROW_KW);
p.expect(LEVEL_KW);
p.expect(SECURITY_KW);
m.complete(p, FORCE_RLS)
}
NO_KW if p.nth_at(1, FORCE_KW) => {
let m = p.start();
p.bump(NO_KW);
p.bump(FORCE_KW);
p.expect(ROW_KW);
p.expect(LEVEL_KW);
p.expect(SECURITY_KW);
m.complete(p, NO_FORCE_RLS)
}
INHERIT_KW => {
let m = p.start();
p.bump(INHERIT_KW);
path_name_ref(p);
m.complete(p, INHERIT_TABLE)
}
NO_KW if p.nth_at(1, INHERIT_KW) => {
let m = p.start();
p.bump(NO_KW);
p.bump(INHERIT_KW);
path_name_ref(p);
m.complete(p, NO_INHERIT_TABLE)
}
ENABLE_KW => {
let m = p.start();
p.bump(ENABLE_KW);
let kind = match p.current() {
TRIGGER_KW => {
p.bump(TRIGGER_KW);
if !p.eat(ALL_KW) && !p.eat(USER_KW) {
name_ref(p);
}
ENABLE_TRIGGER
}
REPLICA_KW => {
p.bump(REPLICA_KW);
if p.eat(TRIGGER_KW) {
name_ref(p);
ENABLE_REPLICA_TRIGGER
} else {
p.expect(RULE_KW);
name_ref(p);
ENABLE_REPLICA_RULE
}
}
ALWAYS_KW => {
p.bump(ALWAYS_KW);
if p.eat(TRIGGER_KW) {
name_ref(p);
ENABLE_ALWAYS_TRIGGER
} else {
p.expect(RULE_KW);
name_ref(p);
ENABLE_ALWAYS_RULE
}
}
RULE_KW => {
p.bump(RULE_KW);
name_ref(p);
ENABLE_RULE
}
ROW_KW => {
p.bump(ROW_KW);
p.expect(LEVEL_KW);
p.expect(SECURITY_KW);
ENABLE_RLS
}
_ => {
p.error("expected TRIGGER, REPLICA, ALWAYS, RULE, or ROW");
ENABLE_RLS
}
};
m.complete(p, kind)
}
DISABLE_KW => {
let m = p.start();
p.bump(DISABLE_KW);
let kind = match p.current() {
TRIGGER_KW => {
p.bump(TRIGGER_KW);
if !p.eat(ALL_KW) && !p.eat(USER_KW) {
name_ref(p);
}
DISABLE_TRIGGER
}
ROW_KW => {
p.bump(ROW_KW);
p.expect(LEVEL_KW);
p.expect(SECURITY_KW);
DISABLE_RLS
}
RULE_KW => {
p.bump(RULE_KW);
name_ref(p);
DISABLE_RULE
}
_ => {
p.error("expected TRIGGER, ROW, or RULE");
DISABLE_RULE
}
};
m.complete(p, kind)
}
CLUSTER_KW => {
let m = p.start();
p.bump(CLUSTER_KW);
p.bump(ON_KW);
name_ref(p);
m.complete(p, CLUSTER_ON)
}
OWNER_KW => owner_to(p),
DETACH_KW => {
let m = p.start();
p.bump(DETACH_KW);
p.expect(PARTITION_KW);
path_name_ref(p);
if !p.eat(CONCURRENTLY_KW) {
p.eat(FINALIZE_KW);
}
m.complete(p, DETACH_PARTITION)
}
MERGE_KW => {
let m = p.start();
p.bump(MERGE_KW);
p.expect(PARTITIONS_KW);
p.expect(L_PAREN);
path_name_ref_list(p);
p.expect(R_PAREN);
p.eat(INTO_KW);
path_name(p);
m.complete(p, MERGE_PARTITIONS)
}
SPLIT_KW => {
let m = p.start();
p.bump(SPLIT_KW);
p.expect(PARTITION_KW);
path_name_ref(p);
p.expect(INTO_KW);
partition_list(p);
m.complete(p, SPLIT_PARTITION)
}
DROP_KW => {
let m = p.start();
p.bump(DROP_KW);
let kind = if p.eat(CONSTRAINT_KW) {
opt_if_exists(p);
name_ref(p);
DROP_CONSTRAINT
} else {
p.eat(COLUMN_KW);
opt_if_exists(p);
name_ref(p);
DROP_COLUMN
};
opt_cascade_or_restrict(p);
m.complete(p, kind)
}
ADD_KW => {
let m = p.start();
p.bump(ADD_KW);
let kind = if p.at_ts(TABLE_CONSTRAINT_FIRST) {
table_constraint(p);
ADD_CONSTRAINT
} else {
p.eat(COLUMN_KW);
opt_if_not_exists(p);
name(p);
type_name(p);
opt_alter_option_list(p);
opt_collate(p);
opt_column_constraint_list(p);
ADD_COLUMN
};
m.complete(p, kind)
}
ATTACH_KW => {
let m = p.start();
p.bump(ATTACH_KW);
p.expect(PARTITION_KW);
path_name_ref(p);
partition_option(p);
m.complete(p, ATTACH_PARTITION)
}
SET_KW if p.nth_at(1, SCHEMA_KW) => set_schema(p),
SET_KW if p.nth_at(1, L_PAREN) => set_options(p),
SET_KW => {
let m = p.start();
p.expect(SET_KW);
let kind = if p.eat(TABLESPACE_KW) {
name_ref(p);
p.eat(NOWAIT_KW);
SET_TABLESPACE
} else if p.eat(WITHOUT_KW) {
if p.eat(CLUSTER_KW) {
SET_WITHOUT_CLUSTER
} else {
p.expect(OIDS_KW);
SET_WITHOUT_OIDS
}
} else if p.eat(ACCESS_KW) {
p.eat(METHOD_KW);
if !p.eat(DEFAULT_KW) {
name_ref(p);
}
SET_ACCESS_METHOD
} else if p.eat(LOGGED_KW) {
SET_LOGGED
} else {
p.expect(UNLOGGED_KW);
SET_UNLOGGED
};
m.complete(p, kind)
}
RESET_KW => reset_options(p),
RENAME_KW if p.nth_at(1, TO_KW) => rename_to(p),
RENAME_KW => {
let m = p.start();
p.expect(RENAME_KW);
let kind = if p.eat(CONSTRAINT_KW) {
name_ref(p);
p.expect(TO_KW);
name(p);
RENAME_CONSTRAINT
} else {
p.eat(COLUMN_KW);
name_ref(p);
p.expect(TO_KW);
name(p);
RENAME_COLUMN
};
m.complete(p, kind)
}
ALTER_KW => {
let m = p.start();
p.bump(ALTER_KW);
let kind = if p.eat(CONSTRAINT_KW) {
name_ref(p);
opt_constraint_option_list(p);
ALTER_CONSTRAINT
} else {
p.eat(COLUMN_KW);
if p.at_ts(COLUMN_FIRST) {
name_ref(p);
} else {
p.error("expected column_name");
}
alter_column_option(p);
ALTER_COLUMN
};
m.complete(p, kind)
}
OPTIONS_KW => alter_option_list(p),
_ => return None,
};
Some(cm)
}
fn partition_list(p: &mut Parser<'_>) {
let m = p.start();
fn opt_partition(p: &mut Parser<'_>) -> bool {
let m = p.start();
if !p.eat(PARTITION_KW) {
m.abandon(p);
return false;
}
path_name_ref(p);
partition_option(p);
m.complete(p, PARTITION);
true
}
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
TokenSet::new(&[PARTITION_KW]),
opt_partition,
);
m.complete(p, PARTITION_LIST);
}
fn opt_col_label(p: &mut Parser<'_>) -> bool {
if p.at_ts(COL_LABEL_FIRST) {
let m = p.start();
if !opt_ident(p) {
p.bump_any();
}
m.complete(p, NAME);
true
} else {
false
}
}
fn col_label(p: &mut Parser<'_>) {
if !opt_col_label(p) {
p.error("expected label");
}
}
fn opt_attribute_option(p: &mut Parser<'_>) -> bool {
let m = p.start();
if !opt_col_label(p) {
m.abandon(p);
return false;
}
if p.eat(DOT) && !opt_col_label(p) {
p.error("expected column label")
}
if p.eat(EQ) {
def_arg(p);
}
m.complete(p, ATTRIBUTE_OPTION);
true
}
fn def_arg(p: &mut Parser<'_>) {
let m = p.start();
if opt_bool_literal(p)
|| opt_string_literal(p).is_some()
|| opt_numeric_literal(p).is_some()
|| opt_operator(p)
|| p.eat(NONE_KW)
{
} else if p.at_ts(RESERVED_KEYWORDS) {
p.bump_any();
} else if p.eat(OPERATOR_KW) {
p.expect(L_PAREN);
operator(p);
p.expect(R_PAREN);
} else {
opt_type_name(p);
}
m.complete(p, ATTRIBUTE_VALUE);
}
fn generated_options(p: &mut Parser<'_>) {
while !p.at(EOF) {
let m = p.start();
if p.eat(RESTART_KW) {
if p.eat(WITH_KW) {
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
} else {
let _ = opt_numeric_literal(p);
}
m.complete(p, RESTART);
} else if p.eat(SET_KW) {
if opt_sequence_option(p).is_some() {
m.complete(p, SET_SEQUENCE_OPTION);
continue;
} else {
p.expect(GENERATED_KW);
if !p.eat(ALWAYS_KW) {
p.expect(BY_KW);
p.expect(DEFAULT_KW);
}
m.complete(p, SET_GENERATED);
}
} else {
m.abandon(p);
break;
}
}
}
fn alter_column_option(p: &mut Parser<'_>) {
let m = p.start();
let kind = match p.current() {
DROP_KW => {
p.bump(DROP_KW);
if p.eat(DEFAULT_KW) {
DROP_DEFAULT
} else if p.eat(EXPRESSION_KW) {
opt_if_exists(p);
DROP_EXPRESSION
} else if p.eat(IDENTITY_KW) {
opt_if_exists(p);
DROP_IDENTITY
} else {
p.expect(NOT_KW);
p.expect(NULL_KW);
DROP_NOT_NULL
}
}
RESTART => {
p.bump(RESTART_KW);
if p.eat(WITH_KW) {
p.expect(RESTART_KW);
} else {
p.eat(RESTART_KW);
}
RESTART
}
ADD_KW => {
p.bump(ADD_KW);
p.expect(GENERATED_KW);
if !p.eat(ALWAYS_KW) {
p.expect(BY_KW);
p.expect(DEFAULT_KW);
}
p.expect(AS_KW);
p.expect(IDENTITY_KW);
opt_sequence_options(p);
ADD_GENERATED
}
RESET_KW => {
m.abandon(p);
reset_options(p);
return;
}
TYPE_KW => {
set_data_type(p);
SET_TYPE
}
SET_KW if p.nth_at(1, DATA_KW) => {
p.bump(SET_KW);
p.bump(DATA_KW);
set_data_type(p);
SET_TYPE
}
SET_KW if p.nth_at(1, GENERATED_KW) => {
generated_options(p);
SET_GENERATED_OPTIONS
}
SET_KW if p.nth_at_ts(1, SEQUENCE_OPTION_FIRST) => {
generated_options(p);
SET_GENERATED_OPTIONS
}
RESTART_KW => {
generated_options(p);
SET_GENERATED_OPTIONS
}
OPTIONS_KW => {
if !opt_alter_option_list(p) {
p.error("expected options");
}
SET_OPTIONS_LIST
}
SET_KW if p.nth_at(1, DEFAULT_KW) => {
p.bump(SET_KW);
p.bump(DEFAULT_KW);
if expr(p).is_none() {
p.error("expected expr");
}
SET_DEFAULT
}
SET_KW if p.nth_at(1, EXPRESSION_KW) => {
p.bump(SET_KW);
p.bump(EXPRESSION_KW);
p.expect(AS_KW);
p.expect(L_PAREN);
if expr(p).is_none() {
p.error("expected expr");
}
p.expect(R_PAREN);
SET_EXPRESSION
}
SET_KW if p.nth_at(1, STATISTICS_KW) => {
p.bump(SET_KW);
p.bump(STATISTICS_KW);
if !p.eat(DEFAULT_KW) {
if opt_numeric_literal(p).is_none() {
p.error("expected numeric literal");
}
}
SET_STATISTICS
}
SET_KW if p.nth_at(1, L_PAREN) => {
p.bump(SET_KW);
attribute_list(p);
SET_OPTIONS
}
SET_KW if p.nth_at(1, STORAGE_KW) => {
p.bump(SET_KW);
p.bump(STORAGE_KW);
if !p.eat(DEFAULT_KW) {
if p.at_ts(COLUMN_FIRST) {
p.bump_any();
} else {
p.error("expected name");
}
}
SET_STORAGE
}
SET_KW if p.nth_at(1, COMPRESSION_KW) => {
p.bump(SET_KW);
p.bump(COMPRESSION_KW);
if !p.eat(DEFAULT_KW) {
if p.at_ts(COLUMN_FIRST) {
p.bump_any();
} else {
p.error("expected name");
}
}
SET_COMPRESSION
}
SET_KW if p.nth_at(1, NOT_KW) => {
p.bump(SET_KW);
p.bump(NOT_KW);
p.expect(NULL_KW);
SET_NOT_NULL
}
_ => {
p.error("expected alter column option");
m.abandon(p);
return;
}
};
m.complete(p, kind);
}
fn attribute_list(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "unexpected comma".to_string(),
COL_LABEL_FIRST,
opt_attribute_option,
);
m.complete(p, ATTRIBUTE_LIST);
}
fn opt_collate(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
if p.eat(COLLATE_KW) {
path_name_ref(p);
Some(m.complete(p, COLLATE))
} else {
m.abandon(p);
None
}
}
fn set_data_type(p: &mut Parser<'_>) {
p.expect(TYPE_KW);
type_name(p);
opt_collate(p);
if p.eat(USING_KW) && expr(p).is_none() {
p.error("expected expression");
}
}
pub(crate) fn entry_point(p: &mut Parser) {
let m = p.start();
while !p.at(EOF) {
if p.eat(SEMICOLON) {
continue;
}
let parsed_stmt = stmt(
p,
&StmtRestrictions {
begin_end_allowed: true,
},
);
if !p.at(EOF) && parsed_stmt.is_some() {
p.expect(SEMICOLON);
}
}
m.complete(p, SOURCE_FILE);
}