use crate::{
QualifiedName, Span, Spanned,
drop::{CascadeOrRestrict, parse_cascade_or_restrict},
keywords::Keyword,
lexer::Token,
parser::{ParseError, Parser},
qualified_name::parse_qualified_name_unreserved,
};
use alloc::vec::Vec;
#[derive(Debug, Clone)]
pub struct TruncateTableSpec<'a> {
pub only_span: Option<Span>,
pub table_name: QualifiedName<'a>,
pub descendants_span: Option<Span>,
}
impl<'a> Spanned for TruncateTableSpec<'a> {
fn span(&self) -> Span {
self.table_name
.span()
.join_span(&self.only_span)
.join_span(&self.descendants_span)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IdentityOption {
Restart(Span),
Continue(Span),
}
impl Spanned for IdentityOption {
fn span(&self) -> Span {
match self {
IdentityOption::Restart(span) => span.clone(),
IdentityOption::Continue(span) => span.clone(),
}
}
}
#[derive(Debug, Clone)]
pub struct TruncateTable<'a> {
pub truncate_span: Span,
pub table_span: Option<Span>,
pub tables: Vec<TruncateTableSpec<'a>>,
pub identity_option: Option<IdentityOption>,
pub cascade_or_restrict: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for TruncateTable<'a> {
fn span(&self) -> Span {
self.truncate_span
.join_span(&self.table_span)
.join_span(&self.tables)
.join_span(&self.identity_option)
.join_span(&self.cascade_or_restrict)
}
}
pub(crate) fn parse_truncate_table<'a>(
parser: &mut Parser<'a, '_>,
) -> Result<TruncateTable<'a>, ParseError> {
let truncate_span = parser.consume_keyword(Keyword::TRUNCATE)?;
let table_span = parser.skip_keyword(Keyword::TABLE);
let mut tables = Vec::new();
loop {
let only_span = parser.skip_keyword(Keyword::ONLY);
parser.postgres_only(&only_span);
let table_name = parse_qualified_name_unreserved(parser)?;
let descendants_span = parser.skip_token(Token::Mul);
parser.postgres_only(&descendants_span);
tables.push(TruncateTableSpec {
only_span,
table_name,
descendants_span,
});
let comma_span = parser.skip_token(Token::Comma);
if comma_span.is_none() {
break;
}
parser.postgres_only(&comma_span);
}
let identity_option = if let Some(restart_span) = parser.skip_keyword(Keyword::RESTART) {
let identity_span = parser.consume_keyword(Keyword::IDENTITY)?;
let full_span = restart_span.join_span(&identity_span);
parser.postgres_only(&full_span);
Some(IdentityOption::Restart(full_span))
} else if let Some(continue_span) = parser.skip_keyword(Keyword::CONTINUE) {
let identity_span = parser.consume_keyword(Keyword::IDENTITY)?;
let full_span = continue_span.join_span(&identity_span);
parser.postgres_only(&full_span);
Some(IdentityOption::Continue(full_span))
} else {
None
};
let cascade_or_restrict = parse_cascade_or_restrict(parser);
Ok(TruncateTable {
truncate_span,
table_span,
tables,
identity_option,
cascade_or_restrict,
})
}