use sql_dialect_fmt_syntax::SyntaxKind::*;
use crate::parser::{ContextualKeyword, Parser};
const DELTA_COMMAND_WORDS: &[ContextualKeyword] = &[
ContextualKeyword::Vacuum,
ContextualKeyword::Optimize,
ContextualKeyword::Cache,
ContextualKeyword::Uncache,
ContextualKeyword::Refresh,
ContextualKeyword::Restore,
ContextualKeyword::Analyze,
];
pub(in crate::grammar) fn at_delta_stmt_start(p: &Parser) -> bool {
at_command_word(p) || at_describe_history(p) || at_msck_repair(p)
}
fn at_command_word(p: &Parser) -> bool {
p.nth_any_contextual(0, DELTA_COMMAND_WORDS) && at_command_operand(p, 1)
}
fn at_command_operand(p: &Parser, n: usize) -> bool {
p.nth_at(n, IDENT)
|| p.nth_at(n, QUOTED_IDENT)
|| p.nth_at(n, STRING)
|| p.nth_at(n, TABLE_KW)
|| p.nth_at(n, IF_KW)
|| p.nth_contextual(n, ContextualKeyword::Lazy)
}
pub(in crate::grammar) fn at_describe_history(p: &Parser) -> bool {
(p.at(DESCRIBE_KW) || p.at(DESC_KW)) && p.nth_contextual(1, ContextualKeyword::History)
}
fn at_msck_repair(p: &Parser) -> bool {
p.nth_contextual(0, ContextualKeyword::Msck)
&& p.nth_contextual(1, ContextualKeyword::Repair)
&& p.nth_at(2, TABLE_KW)
}
pub(in crate::grammar) fn delta_stmt(p: &mut Parser) {
if at_describe_history(p) {
describe_history_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Vacuum) {
vacuum_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Optimize) {
optimize_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Uncache) {
uncache_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Cache) {
cache_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Refresh) {
refresh_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Restore) {
restore_stmt(p);
} else if p.nth_contextual(0, ContextualKeyword::Analyze) {
analyze_stmt(p);
} else if at_msck_repair(p) {
msck_repair_stmt(p);
} else {
super::expr(p);
}
}
fn table_or_path(p: &mut Parser) {
if p.at(STRING) {
let m = p.start();
p.bump(STRING);
m.complete(p, NAME_REF);
} else if p.at_name() {
super::name_ref(p);
} else {
p.error("expected a table name or path");
}
}
fn vacuum_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); table_or_path(p);
if p.nth_contextual(0, ContextualKeyword::Retain) {
p.bump_as(CONTEXTUAL_KEYWORD); if super::at_expr_start(p) {
super::expr(p); } else {
p.error("expected a retention duration after RETAIN");
}
if p.nth_contextual(0, ContextualKeyword::Hours) {
p.bump_as(CONTEXTUAL_KEYWORD); } else {
p.error("expected HOURS after the retention duration");
}
}
if p.nth_contextual(0, ContextualKeyword::Dry) {
p.bump_as(CONTEXTUAL_KEYWORD); if p.nth_contextual(0, ContextualKeyword::Run) {
p.bump_as(CONTEXTUAL_KEYWORD); } else {
p.error("expected RUN after DRY");
}
}
m.complete(p, VACUUM_STMT);
}
fn optimize_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); table_or_path(p);
if p.at(WHERE_KW) {
super::where_clause(p);
}
if p.nth_contextual(0, ContextualKeyword::Zorder) {
zorder_clause(p);
}
m.complete(p, OPTIMIZE_STMT);
}
fn zorder_clause(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.expect(BY_KW);
if p.at(L_PAREN) {
super::column_list(p);
} else {
p.error("expected '(' after ZORDER BY");
}
m.complete(p, ZORDER_CLAUSE);
}
fn cache_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); if p.nth_contextual(0, ContextualKeyword::Lazy) {
p.bump_as(CONTEXTUAL_KEYWORD); }
p.expect(TABLE_KW);
table_or_path(p);
if p.nth_contextual(0, ContextualKeyword::Options) {
p.bump_as(CONTEXTUAL_KEYWORD); if p.at(L_PAREN) {
super::balanced_parens(p);
} else {
p.error("expected '(' after OPTIONS");
}
}
p.eat(AS_KW);
if at_cache_query(p) {
super::query_expr(p);
}
m.complete(p, CACHE_STMT);
}
fn at_cache_query(p: &Parser) -> bool {
p.at(SELECT_KW)
|| p.at(WITH_KW)
|| p.at(VALUES_KW)
|| p.at(TABLE_KW)
|| p.at(FROM_KW)
|| (p.at(L_PAREN) && (p.nth_at(1, SELECT_KW) || p.nth_at(1, WITH_KW)))
}
fn uncache_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.expect(TABLE_KW);
if p.at(IF_KW) {
p.bump(IF_KW);
p.expect(EXISTS_KW);
}
table_or_path(p);
m.complete(p, UNCACHE_STMT);
}
fn refresh_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.eat(TABLE_KW);
table_or_path(p);
m.complete(p, REFRESH_STMT);
}
fn describe_history_stmt(p: &mut Parser) {
let m = p.start();
p.bump_any(); p.bump_as(CONTEXTUAL_KEYWORD); if p.at_name() || p.at(STRING) {
table_or_path(p);
}
while !super::at_stmt_terminator(p) {
p.bump_any();
}
m.complete(p, DESCRIBE_HISTORY_STMT);
}
fn restore_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.eat(TABLE_KW);
table_or_path(p);
if p.nth_contextual(0, ContextualKeyword::To) {
p.bump_as(CONTEXTUAL_KEYWORD);
} else {
p.error("expected TO in RESTORE statement");
}
if p.nth_contextual(0, ContextualKeyword::Version)
|| p.nth_contextual(0, ContextualKeyword::Timestamp)
{
p.bump_as(CONTEXTUAL_KEYWORD);
}
p.expect(AS_KW);
if p.nth_contextual(0, ContextualKeyword::Of) {
p.bump_as(CONTEXTUAL_KEYWORD);
} else {
p.error("expected OF in RESTORE statement");
}
if super::at_expr_start(p) {
super::expr(p);
} else {
p.error("expected a RESTORE version or timestamp value");
}
while !super::at_stmt_terminator(p) {
p.bump_any();
}
m.complete(p, RESTORE_STMT);
}
fn analyze_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.expect(TABLE_KW);
table_or_path(p);
while !super::at_stmt_terminator(p) {
if p.nth_contextual(0, ContextualKeyword::Compute)
|| p.nth_contextual(0, ContextualKeyword::Statistics)
|| p.nth_contextual(0, ContextualKeyword::Columns)
{
p.bump_as(CONTEXTUAL_KEYWORD);
} else if p.at(L_PAREN) {
super::balanced_parens(p);
} else {
p.bump_any();
}
}
m.complete(p, ANALYZE_STMT);
}
fn msck_repair_stmt(p: &mut Parser) {
let m = p.start();
p.bump_as(CONTEXTUAL_KEYWORD); p.bump_as(CONTEXTUAL_KEYWORD); p.expect(TABLE_KW);
table_or_path(p);
while !super::at_stmt_terminator(p) {
if p.nth_contextual(0, ContextualKeyword::Sync)
|| p.nth_contextual(0, ContextualKeyword::Partitions)
{
p.bump_as(CONTEXTUAL_KEYWORD);
} else {
p.bump_any();
}
}
m.complete(p, MSCK_REPAIR_STMT);
}