use crate::custom_err;
use crate::dialect::{from_token, Token};
use crate::parser::{parse::YYCODETYPE, ParserError};
use indexmap::IndexSet;
use strum_macros::{EnumIter, EnumString};
use super::types_10::{
DeferSubclause, ForeignKeyClause, Id, Indexed, JoinConstraint, JoinOperator, Over,
QuotedIterator, RefAct, ResolveType, Select, Set, SortOrder, Window,
};
use super::types_11::{ColumnDefinition, CommonTableExpr, QualifiedName, SortedColumn};
use super::types_9::{Expr, JoinedSelectTable};
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DistinctNames(pub(super) IndexSet<Name>);
impl DistinctNames {
pub fn new(name: Name) -> Self {
let mut dn = Self(IndexSet::new());
dn.0.insert(name);
dn
}
pub fn single(name: Name) -> Self {
let mut dn = Self(IndexSet::with_capacity(1));
dn.0.insert(name);
dn
}
pub fn insert(&mut self, name: Name) -> Result<(), ParserError> {
if self.0.contains(&name) {
return Err(custom_err!("column \"{}\" specified more than once", name));
}
self.0.insert(name);
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FromClause {
pub select: Option<Box<SelectTable>>, pub joins: Option<Vec<JoinedSelectTable>>,
pub(super) op: Option<JoinOperator>, }
impl FromClause {
pub(crate) fn empty() -> Self {
Self {
select: None,
joins: None,
op: None,
}
}
pub(crate) fn push(
&mut self,
table: SelectTable,
jc: Option<JoinConstraint>,
) -> Result<(), ParserError> {
let op = self.op.take();
if let Some(op) = op {
let jst = JoinedSelectTable {
operator: op,
table,
constraint: jc,
};
if jst.operator.is_natural() && jst.constraint.is_some() {
return Err(custom_err!(
"a NATURAL join may not have an ON or USING clause"
));
}
if let Some(ref mut joins) = self.joins {
joins.push(jst);
} else {
self.joins = Some(vec![jst]);
}
} else {
if jc.is_some() {
return Err(custom_err!("a JOIN clause is required before ON"));
}
debug_assert!(self.select.is_none());
debug_assert!(self.joins.is_none());
self.select = Some(Box::new(table));
}
Ok(())
}
pub(crate) fn push_op(&mut self, op: JoinOperator) {
self.op = Some(op);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AlterTableBody {
RenameTo(Name),
AddColumn(ColumnDefinition), RenameColumn {
old: Name,
new: Name,
},
DropColumn(Name), }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum As {
As(Name),
Elided(Name), }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GroupBy {
pub exprs: Vec<Expr>,
pub having: Option<Box<Expr>>, }
#[derive(Clone, Debug, PartialEq, Eq, EnumIter, EnumString, strum::Display)]
#[strum(serialize_all = "snake_case")]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum PragmaName {
ApplicationId,
AutoVacuum,
CacheSize,
ForeignKeyList,
IndexInfo,
IndexList,
IntegrityCheck,
JournalMode,
LegacyFileFormat,
PageCount,
PageSize,
SchemaVersion,
Synchronous,
TableInfo,
UserVersion,
WalCheckpoint,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct With {
pub recursive: bool,
pub ctes: Vec<CommonTableExpr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ResultColumn {
Expr(Expr, Option<As>),
Star,
TableStar(Name),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RefArg {
OnDelete(RefAct),
OnInsert(RefAct),
OnUpdate(RefAct),
Match(Name),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TriggerCmdDelete {
pub tbl_name: Name,
pub where_clause: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FunctionTail {
pub filter_clause: Option<Box<Expr>>,
pub over_clause: Option<Box<Over>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct WindowDef {
pub name: Name,
pub window: Window,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TransactionType {
Deferred, Immediate,
Exclusive,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FrameBound {
CurrentRow,
Following(Box<Expr>),
Preceding(Box<Expr>),
UnboundedFollowing,
UnboundedPreceding,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UpsertDo {
Set {
sets: Vec<Set>,
where_clause: Option<Expr>,
},
Nothing,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Distinctness {
Distinct,
All,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TriggerCmdInsert {
pub or_conflict: Option<ResolveType>,
pub tbl_name: Name,
pub col_names: Option<DistinctNames>,
pub select: Box<Select>,
pub upsert: Option<Upsert>,
pub returning: Option<Vec<ResultColumn>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Operator {
Add,
And,
ArrowRight,
ArrowRightShift,
BitwiseAnd,
BitwiseOr,
BitwiseNot,
Concat,
Equals,
Divide,
Greater,
GreaterEquals,
Is,
IsNot,
LeftShift,
Less,
LessEquals,
Modulus,
Multiply,
NotEquals,
Or,
RightShift,
Subtract,
}
impl Operator {
pub fn is_commutative(&self) -> bool {
matches!(
self,
Operator::Add
| Operator::Multiply
| Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::Equals
| Operator::NotEquals
)
}
pub fn is_comparison(&self) -> bool {
matches!(
self,
Self::Equals
| Self::NotEquals
| Self::Less
| Self::LessEquals
| Self::Greater
| Self::GreaterEquals
| Self::Is
| Self::IsNot
)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ColumnConstraint {
PrimaryKey {
order: Option<SortOrder>,
conflict_clause: Option<ResolveType>,
auto_increment: bool,
},
NotNull {
nullable: bool,
conflict_clause: Option<ResolveType>,
},
Unique(Option<ResolveType>),
Check(Expr),
Default(Expr),
Defer(DeferSubclause), Collate {
collation_name: Name, },
ForeignKey {
clause: ForeignKeyClause,
deref_clause: Option<DeferSubclause>,
},
Generated {
expr: Expr,
typ: Option<Id>,
},
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Limit {
pub expr: Expr,
pub offset: Option<Expr>, }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SelectTable {
Table(QualifiedName, Option<As>, Option<Indexed>),
TableCall(QualifiedName, Option<Vec<Expr>>, Option<As>),
Select(Box<Select>, Option<As>),
Sub(FromClause, Option<As>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UpsertIndex {
pub targets: Vec<SortedColumn>,
pub where_clause: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Upsert {
pub index: Option<Box<UpsertIndex>>,
pub do_clause: Box<UpsertDo>,
pub next: Option<Box<Upsert>>,
}
#[derive(Clone, Debug, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Name(pub String); impl Name {
pub fn from_token(ty: YYCODETYPE, token: Token) -> Self {
Self(from_token(ty, token))
}
pub(super) fn as_bytes(&self) -> QuotedIterator<'_> {
if self.0.is_empty() {
return QuotedIterator(self.0.bytes(), 0);
}
let bytes = self.0.as_bytes();
let mut quote = bytes[0];
if quote != b'"' && quote != b'`' && quote != b'\'' && quote != b'[' {
return QuotedIterator(self.0.bytes(), 0);
} else if quote == b'[' {
quote = b']';
}
debug_assert!(bytes.len() > 1);
debug_assert_eq!(quote, bytes[bytes.len() - 1]);
let sub = &self.0.as_str()[1..bytes.len() - 1];
if quote == b']' {
return QuotedIterator(sub.bytes(), 0); }
QuotedIterator(sub.bytes(), quote)
}
pub(crate) fn unquoted(&self) -> String {
String::from_utf8(self.as_bytes().collect()).unwrap_or_else(|_| self.0.clone())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TriggerTime {
Before, After,
InsteadOf,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NamedColumnConstraint {
pub name: Option<Name>,
pub constraint: ColumnConstraint,
}