use alloc::{boxed::Box, vec::Vec};
use crate::{
Identifier, QualifiedName, Span, Spanned, Statement,
data_type::{DataType, DataTypeContext},
keywords::Keyword,
lexer::Token,
operator::parse_operator_name,
parser::{ParseError, Parser},
qualified_name::parse_qualified_name_unreserved,
};
#[derive(Debug, Clone)]
pub enum CascadeOrRestrict {
Cascade(Span),
Restrict(Span),
}
impl Spanned for CascadeOrRestrict {
fn span(&self) -> Span {
match self {
CascadeOrRestrict::Cascade(s) => s.clone(),
CascadeOrRestrict::Restrict(s) => s.clone(),
}
}
}
pub(crate) fn parse_cascade_or_restrict<'a>(
parser: &mut Parser<'a, '_>,
) -> Option<CascadeOrRestrict> {
let cascade_span = parser.skip_keyword(Keyword::CASCADE);
parser.postgres_only(&cascade_span);
let restrict_span = parser.skip_keyword(Keyword::RESTRICT);
parser.postgres_only(&restrict_span);
match (cascade_span, restrict_span) {
(Some(cascade), None) => Some(CascadeOrRestrict::Cascade(cascade)),
(None, Some(restrict)) => Some(CascadeOrRestrict::Restrict(restrict)),
(Some(cascade), Some(restrict)) => {
parser
.err("Cannot specify both CASCADE and RESTRICT", &cascade)
.frag("RESTRICT specified here", &restrict);
None
}
(None, None) => None,
}
}
#[derive(Debug, Clone)]
pub struct DropTable<'a> {
pub drop_span: Span,
pub temporary: Option<Span>,
pub table_span: Span,
pub if_exists: Option<Span>,
pub tables: Vec<QualifiedName<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropTable<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.temporary)
.join_span(&self.table_span)
.join_span(&self.if_exists)
.join_span(&self.tables)
}
}
fn parse_drop_table<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
temporary: Option<Span>,
) -> Result<DropTable<'a>, ParseError> {
let table_span = parser.consume_keyword(Keyword::TABLE)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut tables = Vec::new();
loop {
tables.push(parse_qualified_name_unreserved(parser)?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropTable {
drop_span,
temporary,
table_span,
if_exists,
tables,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropView<'a> {
pub drop_span: Span,
pub temporary: Option<Span>,
pub view_span: Span,
pub if_exists: Option<Span>,
pub views: Vec<QualifiedName<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropView<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.temporary)
.join_span(&self.view_span)
.join_span(&self.if_exists)
.join_span(&self.views)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_view<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
temporary: Option<Span>,
) -> Result<DropView<'a>, ParseError> {
let view_span = parser.consume_keyword(Keyword::VIEW)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut views = Vec::new();
loop {
views.push(parse_qualified_name_unreserved(parser)?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropView {
drop_span,
temporary,
view_span,
if_exists,
views,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropDatabase<'a> {
pub drop_span: Span,
pub database_span: Span,
pub if_exists: Option<Span>,
pub database: Identifier<'a>,
}
impl<'a> Spanned for DropDatabase<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.database_span)
.join_span(&self.if_exists)
.join_span(&self.database)
}
}
fn parse_drop_database<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
kw: Keyword,
) -> Result<DropDatabase<'a>, ParseError> {
let database_span = parser.consume_keyword(kw)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let database = parser.consume_plain_identifier_unreserved()?;
Ok(DropDatabase {
drop_span,
database_span,
if_exists,
database,
})
}
#[derive(Debug, Clone)]
pub struct DropEvent<'a> {
pub drop_span: Span,
pub event_span: Span,
pub if_exists: Option<Span>,
pub event: QualifiedName<'a>,
}
impl<'a> Spanned for DropEvent<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.event_span)
.join_span(&self.if_exists)
.join_span(&self.event)
}
}
fn parse_drop_event<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropEvent<'a>, ParseError> {
let event_span = parser.consume_keyword(Keyword::EVENT)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let event = parse_qualified_name_unreserved(parser)?;
Ok(DropEvent {
drop_span,
event_span,
if_exists,
event,
})
}
#[derive(Debug, Clone)]
pub enum DropFunctionArgMode {
In(Span),
Out(Span),
InOut(Span),
}
impl Spanned for DropFunctionArgMode {
fn span(&self) -> Span {
match self {
DropFunctionArgMode::In(s) => s.clone(),
DropFunctionArgMode::Out(s) => s.clone(),
DropFunctionArgMode::InOut(s) => s.clone(),
}
}
}
#[derive(Debug, Clone)]
pub struct DropFunctionArg<'a> {
pub mode: Option<DropFunctionArgMode>,
pub name: Option<Identifier<'a>>,
pub data_type: DataType<'a>,
pub default: Option<Span>, }
impl<'a> Spanned for DropFunctionArg<'a> {
fn span(&self) -> Span {
self.data_type
.span()
.join_span(&self.mode)
.join_span(&self.name)
.join_span(&self.default)
}
}
#[derive(Debug, Clone)]
pub struct DropFunction<'a> {
pub drop_span: Span,
pub function_span: Span,
pub if_exists: Option<Span>,
pub functions: Vec<(QualifiedName<'a>, Option<Vec<DropFunctionArg<'a>>>)>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropFunction<'a> {
fn span(&self) -> Span {
let mut span = self
.drop_span
.join_span(&self.function_span)
.join_span(&self.if_exists)
.join_span(&self.restrict_or_cascade);
for (name, args) in &self.functions {
span = span.join_span(name);
if let Some(args) = args {
for arg in args {
span = span.join_span(arg);
}
}
}
span
}
}
fn parse_drop_function<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropFunction<'a>, ParseError> {
let function_span = parser.consume_keyword(Keyword::FUNCTION)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut functions = Vec::new();
loop {
let name = parse_qualified_name_unreserved(parser)?;
let args = if parser.token == Token::LParen {
let lparen = parser.consume_token(Token::LParen)?;
let mut arg_list = Vec::new();
parser.recovered(")", &|t| t == &Token::RParen, |parser| {
loop {
let mode = match &parser.token {
Token::Ident(_, Keyword::IN) => Some(DropFunctionArgMode::In(
parser.consume_keyword(Keyword::IN)?,
)),
Token::Ident(_, Keyword::OUT) => Some(DropFunctionArgMode::Out(
parser.consume_keyword(Keyword::OUT)?,
)),
Token::Ident(_, Keyword::INOUT) => Some(DropFunctionArgMode::InOut(
parser.consume_keyword(Keyword::INOUT)?,
)),
_ => None,
};
let name = match &parser.token {
Token::Ident(_, kw) if !kw.restricted(parser.reserved()) => {
Some(parser.consume_plain_identifier_unreserved()?)
}
_ => None,
};
let data_type =
crate::data_type::parse_data_type(parser, DataTypeContext::FunctionParam)?;
let default = if parser.skip_token(Token::Eq).is_some() {
Some(parser.consume().clone())
} else {
None
};
arg_list.push(DropFunctionArg {
mode,
name,
data_type,
default,
});
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
Ok(())
})?;
parser.consume_token(Token::RParen)?;
parser.postgres_only(&lparen.join_span(&arg_list));
Some(arg_list)
} else {
None
};
functions.push((name, args));
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
if let [(first, _), (second, _), ..] = functions.as_slice()
&& !parser.options.dialect.is_postgresql()
{
parser
.err("Multiple function only supported by ", second)
.frag("First function supplied here", first);
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropFunction {
drop_span,
function_span,
if_exists,
functions,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropProcedure<'a> {
pub drop_span: Span,
pub procedure_span: Span,
pub if_exists: Option<Span>,
pub procedure: QualifiedName<'a>,
}
impl<'a> Spanned for DropProcedure<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.procedure_span)
.join_span(&self.if_exists)
.join_span(&self.procedure)
}
}
fn parse_drop_procedure<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropProcedure<'a>, ParseError> {
let procedure_span = parser.consume_keyword(Keyword::PROCEDURE)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let procedure = parse_qualified_name_unreserved(parser)?;
Ok(DropProcedure {
drop_span,
procedure_span,
if_exists,
procedure,
})
}
#[derive(Debug, Clone)]
pub struct DropSequence<'a> {
pub drop_span: Span,
pub sequence_span: Span,
pub if_exists: Option<Span>,
pub sequences: Vec<QualifiedName<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropSequence<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.sequence_span)
.join_span(&self.if_exists)
.join_span(&self.sequences)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_sequence<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropSequence<'a>, ParseError> {
let sequence_span = parser.consume_keyword(Keyword::SEQUENCE)?;
parser.postgres_only(&sequence_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut sequences = Vec::new();
loop {
sequences.push(parse_qualified_name_unreserved(parser)?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropSequence {
drop_span,
sequence_span,
if_exists,
sequences,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropServer<'a> {
pub drop_span: Span,
pub server_span: Span,
pub if_exists: Option<Span>,
pub server: Identifier<'a>,
}
impl<'a> Spanned for DropServer<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.server_span)
.join_span(&self.if_exists)
.join_span(&self.server)
}
}
fn parse_drop_server<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropServer<'a>, ParseError> {
let server_span = parser.consume_keyword(Keyword::SERVER)?;
parser.postgres_only(&server_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let server = parser.consume_plain_identifier_unreserved()?;
Ok(DropServer {
drop_span,
server_span,
if_exists,
server,
})
}
#[derive(Debug, Clone)]
pub struct DropTrigger<'a> {
pub drop_span: Span,
pub trigger_span: Span,
pub if_exists: Option<Span>,
pub identifier: QualifiedName<'a>,
pub on: Option<(Span, QualifiedName<'a>)>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropTrigger<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.trigger_span)
.join_span(&self.if_exists)
.join_span(&self.identifier)
.join_span(&self.on)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_trigger<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropTrigger<'a>, ParseError> {
let trigger_span = parser.consume_keyword(Keyword::TRIGGER)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let identifier = parse_qualified_name_unreserved(parser)?;
let on = if let Some(span) = parser.skip_keyword(Keyword::ON) {
let table_name = parse_qualified_name_unreserved(parser)?;
parser.postgres_only(&span);
Some((span, table_name))
} else {
if parser.options.dialect.is_postgresql() {
parser.err("ON required for trigger drops in PostgreSQL", &trigger_span);
}
None
};
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropTrigger {
drop_span,
trigger_span,
if_exists,
identifier,
on,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropIndex<'a> {
pub drop_span: Span,
pub index_span: Span,
pub if_exists: Option<Span>,
pub index_name: Identifier<'a>,
pub on: Option<(Span, QualifiedName<'a>)>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropIndex<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.index_span)
.join_span(&self.if_exists)
.join_span(&self.index_name)
.join_span(&self.on)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_index<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropIndex<'a>, ParseError> {
let index_span = parser.consume_keyword(Keyword::INDEX)?;
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let index_name = parser.consume_plain_identifier_unreserved()?;
let on = if let Some(span) = parser.skip_keyword(Keyword::ON) {
let table_name = parse_qualified_name_unreserved(parser)?;
Some((span, table_name))
} else {
None
};
if on.is_none() && parser.options.dialect.is_maria() {
parser.err("On required for index drops in MariaDb", &drop_span);
}
parser.maria_only(&on);
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropIndex {
drop_span,
index_span,
if_exists,
index_name,
on,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropDomain<'a> {
pub drop_span: Span,
pub domain_span: Span,
pub if_exists: Option<Span>,
pub domains: Vec<QualifiedName<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropDomain<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.domain_span)
.join_span(&self.if_exists)
.join_span(&self.domains)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_domain<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropDomain<'a>, ParseError> {
let domain_span = parser.consume_keyword(Keyword::DOMAIN)?;
parser.postgres_only(&domain_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut domains = Vec::new();
loop {
domains.push(parse_qualified_name_unreserved(parser)?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropDomain {
drop_span,
domain_span,
if_exists,
domains,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropExtension<'a> {
pub drop_span: Span,
pub extension_span: Span,
pub if_exists: Option<Span>,
pub extensions: Vec<Identifier<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropExtension<'a> {
fn span(&self) -> Span {
self.drop_span
.join_span(&self.extension_span)
.join_span(&self.if_exists)
.join_span(&self.extensions)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_extension<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropExtension<'a>, ParseError> {
let extension_span = parser.consume_keyword(Keyword::EXTENSION)?;
parser.postgres_only(&extension_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut extensions = Vec::new();
loop {
extensions.push(parser.consume_plain_identifier_unreserved()?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropExtension {
drop_span,
extension_span,
if_exists,
extensions,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropOperatorItem<'a> {
pub name: QualifiedName<'a>,
pub left_type: Option<DataType<'a>>,
pub right_type: Option<DataType<'a>>,
}
impl<'a> Spanned for DropOperatorItem<'a> {
fn span(&self) -> Span {
self.name
.span()
.join_span(&self.left_type)
.join_span(&self.right_type)
}
}
#[derive(Debug, Clone)]
pub struct DropOperator<'a> {
pub drop_operator_span: Span,
pub if_exists: Option<Span>,
pub operators: Vec<DropOperatorItem<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropOperator<'a> {
fn span(&self) -> Span {
self.drop_operator_span
.join_span(&self.if_exists)
.join_span(&self.restrict_or_cascade)
.join_span(&self.operators)
}
}
fn parse_drop_operator<'a>(
parser: &mut Parser<'a, '_>,
drop_operator_span: Span,
) -> Result<DropOperator<'a>, ParseError> {
parser.postgres_only(&drop_operator_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut operators = Vec::new();
loop {
if parser.token == Token::LParen {
return Err(parser.expected_failure("operator name")?);
}
let name = parse_operator_name(parser)?;
let (left_type, right_type) = if parser.token == Token::LParen {
parser.consume_token(Token::LParen)?;
let mut left = None;
let mut right = None;
parser.recovered(")", &|t| t == &Token::RParen, |parser| {
if parser.token != Token::Comma && parser.token != Token::RParen {
left = Some(crate::data_type::parse_data_type(
parser,
DataTypeContext::TypeRef,
)?);
}
if parser.skip_token(Token::Comma).is_some() && parser.token != Token::RParen {
right = Some(crate::data_type::parse_data_type(
parser,
DataTypeContext::TypeRef,
)?);
}
Ok(())
})?;
parser.consume_token(Token::RParen)?;
(left, right)
} else {
(None, None)
};
operators.push(DropOperatorItem {
name,
left_type,
right_type,
});
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropOperator {
drop_operator_span,
if_exists,
operators,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropOperatorFamily<'a> {
pub drop_operator_family_span: Span,
pub if_exists: Option<Span>,
pub family: QualifiedName<'a>,
pub using: Option<(Span, Identifier<'a>)>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropOperatorFamily<'a> {
fn span(&self) -> Span {
self.drop_operator_family_span
.join_span(&self.if_exists)
.join_span(&self.family)
.join_span(&self.using)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_operator_family<'a>(
parser: &mut Parser<'a, '_>,
drop_operator_family_span: Span,
) -> Result<DropOperatorFamily<'a>, ParseError> {
parser.postgres_only(&drop_operator_family_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let family = parse_qualified_name_unreserved(parser)?;
let using = if let Some(span) = parser.skip_keyword(Keyword::USING) {
let method = parser.consume_plain_identifier_unreserved()?;
Some((span, method))
} else {
None
};
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropOperatorFamily {
drop_operator_family_span,
if_exists,
family,
using,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropOperatorClass<'a> {
pub drop_operator_class_span: Span,
pub if_exists: Option<Span>,
pub class: QualifiedName<'a>,
pub using: Option<(Span, Identifier<'a>)>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropOperatorClass<'a> {
fn span(&self) -> Span {
self.drop_operator_class_span
.join_span(&self.if_exists)
.join_span(&self.class)
.join_span(&self.using)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_operator_class<'a>(
parser: &mut Parser<'a, '_>,
drop_operator_class_span: Span,
) -> Result<DropOperatorClass<'a>, ParseError> {
parser.postgres_only(&drop_operator_class_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let class = parse_qualified_name_unreserved(parser)?;
let using = if let Some(span) = parser.skip_keyword(Keyword::USING) {
let method = parser.consume_plain_identifier_unreserved()?;
Some((span, method))
} else {
None
};
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropOperatorClass {
drop_operator_class_span,
if_exists,
class,
using,
restrict_or_cascade,
})
}
#[derive(Debug, Clone)]
pub struct DropType<'a> {
pub drop_type_span: Span,
pub if_exists: Option<Span>,
pub names: Vec<QualifiedName<'a>>,
pub restrict_or_cascade: Option<CascadeOrRestrict>,
}
impl<'a> Spanned for DropType<'a> {
fn span(&self) -> Span {
self.drop_type_span
.join_span(&self.if_exists)
.join_span(&self.names)
.join_span(&self.restrict_or_cascade)
}
}
fn parse_drop_type<'a>(
parser: &mut Parser<'a, '_>,
drop_span: Span,
) -> Result<DropType<'a>, ParseError> {
let type_span = parser.consume_keyword(Keyword::TYPE)?;
parser.postgres_only(&type_span);
let drop_type_span = drop_span.join_span(&type_span);
let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
} else {
None
};
let mut names = Vec::new();
loop {
names.push(parse_qualified_name_unreserved(parser)?);
if parser.skip_token(Token::Comma).is_none() {
break;
}
}
let restrict_or_cascade = parse_cascade_or_restrict(parser);
Ok(DropType {
drop_type_span,
if_exists,
names,
restrict_or_cascade,
})
}
pub(crate) fn parse_drop<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
let drop_span = parser.consume_keyword(Keyword::DROP)?;
let temporary = parser.skip_keyword(Keyword::TEMPORARY);
match &parser.token {
Token::Ident(_, Keyword::TABLE) => Ok(Statement::DropTable(Box::new(parse_drop_table(
parser, drop_span, temporary,
)?))),
Token::Ident(_, Keyword::VIEW) => Ok(Statement::DropView(Box::new(parse_drop_view(
parser, drop_span, temporary,
)?))),
Token::Ident(_, kw @ Keyword::DATABASE | kw @ Keyword::SCHEMA) => Ok(
Statement::DropDatabase(Box::new(parse_drop_database(parser, drop_span, *kw)?)),
),
Token::Ident(_, Keyword::DOMAIN) => Ok(Statement::DropDomain(Box::new(parse_drop_domain(
parser, drop_span,
)?))),
Token::Ident(_, Keyword::EXTENSION) => Ok(Statement::DropExtension(Box::new(
parse_drop_extension(parser, drop_span)?,
))),
Token::Ident(_, Keyword::EVENT) => Ok(Statement::DropEvent(Box::new(parse_drop_event(
parser, drop_span,
)?))),
Token::Ident(_, Keyword::FUNCTION) => Ok(Statement::DropFunction(Box::new(
parse_drop_function(parser, drop_span)?,
))),
Token::Ident(_, Keyword::OPERATOR) => {
let operator_span = parser.consume_keyword(Keyword::OPERATOR)?;
match &parser.token {
Token::Ident(_, Keyword::FAMILY) => {
let family_span = parser.consume_keyword(Keyword::FAMILY)?;
Ok(Statement::DropOperatorFamily(Box::new(
parse_drop_operator_family(
parser,
drop_span.join_span(&operator_span).join_span(&family_span),
)?,
)))
}
Token::Ident(_, Keyword::CLASS) => {
let class_span = parser.consume_keyword(Keyword::CLASS)?;
Ok(Statement::DropOperatorClass(Box::new(
parse_drop_operator_class(
parser,
drop_span.join_span(&operator_span).join_span(&class_span),
)?,
)))
}
_ => Ok(Statement::DropOperator(Box::new(parse_drop_operator(
parser,
drop_span.join_span(&operator_span),
)?))),
}
}
Token::Ident(_, Keyword::INDEX) => Ok(Statement::DropIndex(Box::new(parse_drop_index(
parser, drop_span,
)?))),
Token::Ident(_, Keyword::PROCEDURE) => Ok(Statement::DropProcedure(Box::new(
parse_drop_procedure(parser, drop_span)?,
))),
Token::Ident(_, Keyword::SEQUENCE) => Ok(Statement::DropSequence(Box::new(
parse_drop_sequence(parser, drop_span)?,
))),
Token::Ident(_, Keyword::SERVER) => Ok(Statement::DropServer(Box::new(parse_drop_server(
parser, drop_span,
)?))),
Token::Ident(_, Keyword::TRIGGER) => Ok(Statement::DropTrigger(Box::new(
parse_drop_trigger(parser, drop_span)?,
))),
Token::Ident(_, Keyword::TYPE) => Ok(Statement::DropType(Box::new(parse_drop_type(
parser, drop_span,
)?))),
Token::Ident(_, Keyword::USER) => {
parser.todo(file!(), line!())
}
_ => parser.expected_failure("droppable"),
}
}