use super::*;
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) struct SelectItem {
pub(crate) expr: ValueExpr,
pub(crate) alias: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum OrderDirection {
Asc,
Desc,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum NullsPosition {
First,
Last,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct OrderItem {
pub(crate) expr: ValueExpr,
pub(crate) direction: OrderDirection,
pub(crate) nulls: Option<NullsPosition>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum GroupByItem {
Expr(ValueExpr),
Rollup(Vec<ValueExpr>),
Cube(Vec<ValueExpr>),
GroupingSets(Vec<Vec<ValueExpr>>),
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) struct FetchClause {
pub(crate) count: ValueExpr,
pub(crate) with_ties: bool,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum RowLimit {
Limit(Param),
Fetch(FetchClause),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LockMode {
Update,
NoKeyUpdate,
Share,
KeyShare,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum LockWait {
#[default]
Wait,
NoWait,
SkipLocked,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[must_use]
#[non_exhaustive]
pub(crate) struct RowLock {
pub(crate) mode: LockMode,
pub(crate) wait: LockWait,
pub(crate) of: Vec<String>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Assignment {
pub(crate) field: Meta,
pub(crate) value: AssignmentValue,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum AssignmentValue {
Expr(ValueExpr),
Default,
}
impl From<ValueExpr> for AssignmentValue {
fn from(value: ValueExpr) -> Self {
Self::Expr(value)
}
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum InsertBody {
Values(Vec<Assignment>),
Select {
columns: Vec<Meta>,
select: Box<Select>,
},
DefaultValues,
}
#[doc(hidden)]
pub trait IntoAssignments {
fn into_assignments(self) -> Vec<Assignment>;
fn append_assignments(self, assignments: &mut Vec<Assignment>)
where
Self: Sized,
{
assignments.extend(self.into_assignments());
}
}
impl IntoAssignments for Assignment {
fn into_assignments(self) -> Vec<Assignment> {
vec![self]
}
fn append_assignments(self, assignments: &mut Vec<Assignment>) {
assignments.push(self);
}
}
impl IntoAssignments for &Assignment {
fn into_assignments(self) -> Vec<Assignment> {
vec![self.clone()]
}
fn append_assignments(self, assignments: &mut Vec<Assignment>) {
assignments.push(self.clone());
}
}
impl IntoAssignments for Vec<Assignment> {
fn into_assignments(self) -> Vec<Assignment> {
self
}
}
impl IntoAssignments for &[Assignment] {
fn into_assignments(self) -> Vec<Assignment> {
self.to_vec()
}
}
impl<const N: usize> IntoAssignments for [Assignment; N] {
fn into_assignments(self) -> Vec<Assignment> {
self.into_iter().collect()
}
}
macro_rules! impl_assignment_tuple {
($($name:ident),+ $(,)?) => {
impl<$($name),+> IntoAssignments for ($($name,)+)
where
$($name: IntoAssignments,)+
{
#[allow(non_snake_case)]
fn into_assignments(self) -> Vec<Assignment> {
let mut assignments = Vec::new();
self.append_assignments(&mut assignments);
assignments
}
#[allow(non_snake_case)]
fn append_assignments(self, assignments: &mut Vec<Assignment>) {
let ($($name,)+) = self;
$($name.append_assignments(assignments);)+
}
}
};
}
impl_assignment_tuple!(A, B);
impl_assignment_tuple!(A, B, C);
impl_assignment_tuple!(A, B, C, D);
impl_assignment_tuple!(A, B, C, D, E);
impl_assignment_tuple!(A, B, C, D, E, F);
impl_assignment_tuple!(A, B, C, D, E, F, G);
impl_assignment_tuple!(A, B, C, D, E, F, G, H);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_assignment_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum ConflictTarget {
Columns {
fields: Vec<Meta>,
predicate: Option<Box<BoolExpr>>,
},
Constraint(String),
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum ConflictAction {
DoNothing,
DoUpdate {
assignments: Vec<Assignment>,
filter: Option<Box<BoolExpr>>,
},
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) struct ConflictClause {
pub(crate) target: ConflictTarget,
pub(crate) action: ConflictAction,
}
#[derive(Clone, Debug)]
#[must_use]
pub struct MatchedMergeBuilder {
pub(super) merge: Merge,
pub(super) condition: Option<Box<BoolExpr>>,
}
#[derive(Clone, Debug)]
#[must_use]
pub struct NotMatchedMergeBuilder {
pub(super) merge: Merge,
pub(super) condition: Option<Box<BoolExpr>>,
}
#[derive(Clone, Debug)]
#[must_use]
pub struct NotMatchedBySourceMergeBuilder {
pub(super) merge: Merge,
pub(super) condition: Option<Box<BoolExpr>>,
}
#[derive(Clone, Debug)]
#[must_use]
pub struct ColumnConflictBuilder<I> {
pub(super) insert: I,
pub(super) fields: Vec<Meta>,
pub(super) predicate: Option<Box<BoolExpr>>,
}
#[derive(Clone, Debug)]
#[must_use]
pub struct ConstraintConflictBuilder<I> {
pub(super) insert: I,
pub(super) constraint: String,
}
pub trait Insertable {
fn insert_assignments(&self) -> Vec<Assignment>;
}
impl<T> Insertable for &T
where
T: Insertable + ?Sized,
{
fn insert_assignments(&self) -> Vec<Assignment> {
(**self).insert_assignments()
}
}
pub trait Changeset {
fn changeset_assignments(&self) -> Vec<Assignment>;
}
impl<T> Changeset for &T
where
T: Changeset + ?Sized,
{
fn changeset_assignments(&self) -> Vec<Assignment> {
(**self).changeset_assignments()
}
}
pub trait ConflictFields {
fn conflict_field_count(&self) -> usize;
fn push_conflict_fields(self, fields: &mut Vec<Meta>);
}
impl<T> ConflictFields for Field<T> {
fn conflict_field_count(&self) -> usize {
1
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
push_column(fields, *self.meta);
}
}
impl ConflictFields for Meta {
fn conflict_field_count(&self) -> usize {
1
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
push_column(fields, self);
}
}
impl ConflictFields for Vec<Meta> {
fn conflict_field_count(&self) -> usize {
self.len()
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
for field in self {
push_column(fields, field);
}
}
}
impl<const N: usize> ConflictFields for [Meta; N] {
fn conflict_field_count(&self) -> usize {
N
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
for field in self {
push_column(fields, field);
}
}
}
impl<A, B> ConflictFields for (A, B)
where
A: ConflictFields,
B: ConflictFields,
{
fn conflict_field_count(&self) -> usize {
self.0.conflict_field_count() + self.1.conflict_field_count()
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
let (a, b) = self;
a.push_conflict_fields(fields);
b.push_conflict_fields(fields);
}
}
impl<A, B, C> ConflictFields for (A, B, C)
where
A: ConflictFields,
B: ConflictFields,
C: ConflictFields,
{
fn conflict_field_count(&self) -> usize {
self.0.conflict_field_count()
+ self.1.conflict_field_count()
+ self.2.conflict_field_count()
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
let (a, b, c) = self;
a.push_conflict_fields(fields);
b.push_conflict_fields(fields);
c.push_conflict_fields(fields);
}
}
impl<A, B, C, D> ConflictFields for (A, B, C, D)
where
A: ConflictFields,
B: ConflictFields,
C: ConflictFields,
D: ConflictFields,
{
fn conflict_field_count(&self) -> usize {
self.0.conflict_field_count()
+ self.1.conflict_field_count()
+ self.2.conflict_field_count()
+ self.3.conflict_field_count()
}
fn push_conflict_fields(self, fields: &mut Vec<Meta>) {
let (a, b, c, d) = self;
a.push_conflict_fields(fields);
b.push_conflict_fields(fields);
c.push_conflict_fields(fields);
d.push_conflict_fields(fields);
}
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Select {
pub(crate) ctes: Vec<Cte>,
pub(crate) source: Source,
pub(crate) joins: Vec<Join>,
pub(crate) distinct: bool,
pub(crate) distinct_on: Vec<ValueExpr>,
pub(crate) projection: Vec<SelectItem>,
pub(crate) filter: Option<BoolExpr>,
pub(crate) group_by: Vec<GroupByItem>,
pub(crate) having: Option<BoolExpr>,
pub(crate) order: Vec<OrderItem>,
pub(crate) row_limit: Option<RowLimit>,
pub(crate) offset: Option<Param>,
pub(crate) lock: Option<RowLock>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Insert {
pub(crate) ctes: Vec<Cte>,
pub(crate) target: Source,
pub(crate) body: InsertBody,
pub(crate) conflict: Option<ConflictClause>,
pub(crate) returning: Vec<SelectItem>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Update {
pub(crate) ctes: Vec<Cte>,
pub(crate) target: Source,
pub(crate) assignments: Vec<Assignment>,
pub(crate) from: Vec<Source>,
pub(crate) filter: Option<BoolExpr>,
pub(crate) returning: Vec<SelectItem>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Delete {
pub(crate) ctes: Vec<Cte>,
pub(crate) target: Source,
pub(crate) using: Vec<Source>,
pub(crate) filter: Option<BoolExpr>,
pub(crate) returning: Vec<SelectItem>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub(crate) enum MergeWhen {
Matched,
NotMatched,
NotMatchedBySource,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub(crate) enum MergeAction {
DoNothing {
when: MergeWhen,
condition: Option<Box<BoolExpr>>,
},
Insert {
when: MergeWhen,
condition: Option<Box<BoolExpr>>,
assignments: Vec<Assignment>,
},
Update {
when: MergeWhen,
condition: Option<Box<BoolExpr>>,
assignments: Vec<Assignment>,
},
Delete {
when: MergeWhen,
condition: Option<Box<BoolExpr>>,
},
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct Merge {
pub(crate) ctes: Vec<Cte>,
pub(crate) target: Source,
pub(crate) using: Source,
pub(crate) on: BoolExpr,
pub(crate) actions: Vec<MergeAction>,
pub(crate) returning: Vec<SelectItem>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct RawStmt {
pub(crate) sql: String,
pub(crate) params: Vec<Param>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum SetOperator {
Union,
UnionAll,
Intersect,
IntersectAll,
Except,
ExceptAll,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub struct SetQuery {
pub(crate) left: Box<Stmt>,
pub(crate) operator: SetOperator,
pub(crate) right: Box<Stmt>,
pub(crate) order: Vec<OrderItem>,
pub(crate) row_limit: Option<RowLimit>,
pub(crate) offset: Option<Param>,
}
#[derive(Clone, Debug)]
#[must_use]
#[non_exhaustive]
pub enum Stmt {
#[non_exhaustive]
Select(Box<Select>),
#[non_exhaustive]
Set(Box<SetQuery>),
#[non_exhaustive]
Insert(Box<Insert>),
#[non_exhaustive]
Update(Box<Update>),
#[non_exhaustive]
Delete(Box<Delete>),
#[non_exhaustive]
Merge(Box<Merge>),
#[non_exhaustive]
Raw(Box<RawStmt>),
}