use std::ops::Deref;
use crate::ast::{ExprList, WindowSpec};
use super::{Condition, Duplicates, Expr, Hint, Ident, Identifier, Node, OrderBy};
#[derive(Debug)]
pub struct Select<'s, ID> {
pub query: Query<'s, ID>,
pub for_update: Option<ForUpdate<'s, ID>>,
}
#[derive(Debug)]
pub struct Query<'s, ID> {
pub with: Option<With<'s, ID>>,
pub body: QueryBody<'s, ID>,
}
#[derive(Debug)]
pub struct QueryBody<'s, ID> {
pub block: QueryBlock<'s, ID>,
pub order_by: Option<OrderBy<'s, ID>>,
pub row_limit: RowLimit<'s, ID>,
}
#[derive(Debug)]
pub enum QueryBlock<'s, ID> {
Select(QuerySelect<'s, ID>),
Composed(
Box<QueryBlock<'s, ID>>,
ComposeOperator<ID>,
Box<QueryBlock<'s, ID>>,
),
Nested(Node<Box<QueryBody<'s, ID>>, ID>),
}
#[derive(Debug)]
pub struct ComposeOperator<ID> {
pub operation: Node<ComposeOperation, ID>,
pub all_token: Option<Node<(), ID>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComposeOperation {
Union,
Intersect,
Minus,
Except,
}
#[derive(Debug)]
pub struct QuerySelect<'s, ID> {
pub select_token: Node<(), ID>,
pub hint: Option<Node<Hint<'s>, ID>>,
pub duplicates: Option<Node<Duplicates, ID>>,
pub projection: Vec<ProjectionItem<'s, ID>>,
pub from: QueryTables<'s, ID>,
pub selection: Option<WhereCondition<'s, ID>>,
pub group_by: Option<GroupBy<'s, ID>>,
pub windows: Option<QueryWindows<'s, ID>>,
}
#[derive(Debug)]
pub struct AsAlias<'s, ID> {
pub as_token: Option<Node<(), ID>>,
pub name: Option<Node<Ident<'s>, ID>>,
}
#[derive(Debug)]
pub enum ProjectionItem<'s, ID> {
Expr(Expr<'s, ID>, Option<AsAlias<'s, ID>>),
Wildcard(ProjectionWildcard<'s, ID>),
}
#[derive(Debug)]
pub enum ProjectionWildcard<'s, ID> {
Simple(Node<(), ID>),
Qualified(Identifier<'s, ID>, Node<(), ID>),
}
#[derive(Debug)]
pub struct QueryTables<'s, ID> {
pub from_token: Node<(), ID>,
pub tables: Vec<QueryTable<'s, ID>>,
}
#[derive(Debug)]
pub enum QueryTable<'s, ID> {
Table(QueryTableWithJoins<'s, ID>),
}
#[derive(Debug)]
pub struct QueryTableWithJoins<'s, ID> {
pub table: AliasedQueryTable<'s, ID>,
pub joins: Vec<TableJoin<'s, ID>>,
}
pub type QueryTableAlias<'s, ID> = Option<Node<Ident<'s>, ID>>;
#[derive(Debug)]
pub struct AliasedQueryTable<'s, ID> {
pub table: QueryTableType<'s, ID>,
pub alias: QueryTableAlias<'s, ID>,
}
#[derive(Debug)]
pub enum QueryTableType<'s, ID> {
Nested(Node<Box<QueryTable<'s, ID>>, ID>),
Expr(QueryTableExpression<'s, ID>),
Only {
only_token: Node<(), ID>,
expression: Node<QueryTableExpression<'s, ID>, ID>,
},
Containers(ContainersTable<'s, ID>),
Shards(ShardsTable<'s, ID>),
}
#[derive(Debug)]
pub struct ContainersTable<'s, ID> {
pub containers_token: Node<(), ID>,
pub table: Node<Identifier<'s, ID>, ID>,
}
#[derive(Debug)]
pub struct ShardsTable<'s, ID> {
pub shards_token: Node<(), ID>,
pub table: Node<Identifier<'s, ID>, ID>,
}
#[derive(Debug)]
pub enum QueryTableExpression<'s, ID> {
Name(Identifier<'s, ID>),
SubQuery(SubQuery<'s, ID>),
Table(TableCollection<'s, ID>),
}
#[derive(Debug)]
pub struct SubQuery<'s, ID> {
pub lateral_token: Option<Node<(), ID>>,
pub query: Node<Box<Query<'s, ID>>, ID>,
}
#[derive(Debug)]
pub struct TableCollection<'s, ID> {
pub table_token: Node<(), ID>,
pub expr: Node<Expr<'s, ID>, ID>,
pub as_outer_join: Option<Node<Node<(), ID>, ID>>,
}
#[derive(Debug)]
pub enum TableJoin<'s, ID> {
Inner(InnerTableJoin<'s, ID>),
Outer(OuterTableJoin<'s, ID>),
Apply(ApplyTableJoin<'s, ID>),
}
impl<'s, ID> From<InnerTableJoin<'s, ID>> for TableJoin<'s, ID> {
fn from(value: InnerTableJoin<'s, ID>) -> Self {
Self::Inner(value)
}
}
impl<'s, ID> From<OuterTableJoin<'s, ID>> for TableJoin<'s, ID> {
fn from(value: OuterTableJoin<'s, ID>) -> Self {
Self::Outer(value)
}
}
impl<'s, ID> From<ApplyTableJoin<'s, ID>> for TableJoin<'s, ID> {
fn from(value: ApplyTableJoin<'s, ID>) -> Self {
Self::Apply(value)
}
}
#[derive(Debug)]
pub enum InnerTableJoin<'s, ID> {
Inner(InnerJoinedTable<'s, ID>),
Cross(CrossInnerJoinedTable<'s, ID>),
Natural(NaturalInnerJoinedTable<'s, ID>),
}
impl<'s, ID> From<InnerJoinedTable<'s, ID>> for InnerTableJoin<'s, ID> {
fn from(value: InnerJoinedTable<'s, ID>) -> Self {
Self::Inner(value)
}
}
impl<'s, ID> From<InnerJoinedTable<'s, ID>> for TableJoin<'s, ID> {
fn from(value: InnerJoinedTable<'s, ID>) -> Self {
Self::Inner(value.into())
}
}
impl<'s, ID> From<CrossInnerJoinedTable<'s, ID>> for InnerTableJoin<'s, ID> {
fn from(value: CrossInnerJoinedTable<'s, ID>) -> Self {
Self::Cross(value)
}
}
impl<'s, ID> From<CrossInnerJoinedTable<'s, ID>> for TableJoin<'s, ID> {
fn from(value: CrossInnerJoinedTable<'s, ID>) -> Self {
Self::Inner(value.into())
}
}
impl<'s, ID> From<NaturalInnerJoinedTable<'s, ID>> for InnerTableJoin<'s, ID> {
fn from(value: NaturalInnerJoinedTable<'s, ID>) -> Self {
Self::Natural(value)
}
}
impl<'s, ID> From<NaturalInnerJoinedTable<'s, ID>> for TableJoin<'s, ID> {
fn from(value: NaturalInnerJoinedTable<'s, ID>) -> Self {
Self::Inner(value.into())
}
}
#[derive(Debug)]
pub struct InnerJoinedTable<'s, ID> {
pub inner_token: Option<Node<(), ID>>,
pub join_token: Node<(), ID>,
pub table: Box<AliasedQueryTable<'s, ID>>,
pub condition: JoinCondition<'s, ID>,
}
#[derive(Debug)]
pub struct CrossInnerJoinedTable<'s, ID> {
pub cross_token: Node<(), ID>,
pub join_token: Node<(), ID>,
pub table: Box<AliasedQueryTable<'s, ID>>,
}
#[derive(Debug)]
pub struct NaturalInnerJoinedTable<'s, ID> {
pub natural_token: Node<(), ID>,
pub inner_token: Option<Node<(), ID>>,
pub join_token: Node<(), ID>,
pub table: Box<AliasedQueryTable<'s, ID>>,
}
#[derive(Debug)]
pub struct OuterTableJoin<'s, ID> {
pub type_token: Node<OuterJoinType, ID>,
pub outer_token: Option<Node<(), ID>>,
pub join_token: Node<(), ID>,
pub table: Box<AliasedQueryTable<'s, ID>>,
pub partition_by: Option<OuterTableJoinParitionBy<'s, ID>>,
pub condition: OuterJoinCondition<'s, ID>,
}
#[derive(Debug)]
pub enum OuterTableJoinParitionBy<'s, ID> {
Left(PartitionBy<'s, ID>),
Right(PartitionBy<'s, ID>),
}
#[derive(Debug)]
pub struct PartitionBy<'s, ID> {
pub partition_token: Node<(), ID>,
pub by_token: Node<(), ID>,
pub expressions: PartitionByExprs<'s, ID>,
}
#[derive(Debug)]
pub enum PartitionByExprs<'s, ID> {
Exprs(Vec<Expr<'s, ID>>),
List(ExprList<'s, ID>),
}
impl<'s, ID> Deref for PartitionByExprs<'s, ID> {
type Target = [Expr<'s, ID>];
fn deref(&self) -> &Self::Target {
match self {
PartitionByExprs::Exprs(exprs) => exprs,
PartitionByExprs::List(list) => list,
}
}
}
#[derive(Debug)]
pub enum OuterJoinCondition<'s, ID> {
Natural { natural_token: Node<(), ID> },
Regular(Option<JoinCondition<'s, ID>>),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum OuterJoinType {
Full,
Left,
Right,
}
#[derive(Debug)]
pub enum JoinCondition<'s, ID> {
On(JoinConditionOn<'s, ID>),
Using(JoinConditionUsing<'s, ID>),
}
#[derive(Debug)]
pub struct JoinConditionOn<'s, ID> {
pub on_token: Node<(), ID>,
pub condition: Condition<'s, ID>,
}
#[derive(Debug)]
pub struct JoinConditionUsing<'s, ID> {
pub using_token: Node<(), ID>,
pub columns: Node<Vec<Node<Ident<'s>, ID>>, ID>,
}
#[derive(Debug)]
pub struct ApplyTableJoin<'s, ID> {
pub type_token: Node<ApplyJoinType, ID>,
pub apply_token: Node<(), ID>,
pub table: ApplyJoinTable<'s, ID>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ApplyJoinType {
Cross,
Outer,
}
#[derive(Debug)]
pub enum ApplyJoinTable<'s, ID> {
Table(Box<AliasedQueryTable<'s, ID>>),
Expr(Expr<'s, ID>),
}
#[derive(Debug)]
pub struct With<'s, ID> {
pub with_keyword: Node<(), ID>,
pub ctes: Vec<CteTable<'s, ID>>,
}
#[derive(Debug)]
pub enum CteTable<'s, ID> {
SubQuery(CteSubQuery<'s, ID>),
}
#[derive(Debug)]
pub struct CteSubQuery<'s, ID> {
pub name: Node<Ident<'s>, ID>,
pub column_aliases: Option<Node<Vec<Node<Ident<'s>, ID>>, ID>>,
pub as_token: Node<(), ID>,
pub query: Node<Box<QueryBody<'s, ID>>, ID>,
}
#[derive(Debug)]
pub struct WhereCondition<'s, ID> {
pub where_token: Node<(), ID>,
pub condition: Condition<'s, ID>,
}
#[derive(Debug)]
pub struct GroupBy<'s, ID> {
pub group_token: Node<(), ID>,
pub by_token: Node<(), ID>,
pub group_type: GroupByType<'s, ID>,
pub having: Option<HavingCondition<'s, ID>>,
}
#[derive(Debug)]
pub enum GroupByType<'s, ID> {
Exprs(GroupByExprs<'s, ID>),
}
#[derive(Debug)]
pub enum GroupByExprs<'s, ID> {
All(Node<Node<(), ID>, ID>),
Exprs(Vec<Expr<'s, ID>>),
Nested(Node<Vec<Expr<'s, ID>>, ID>),
}
#[derive(Debug)]
pub struct HavingCondition<'s, ID> {
pub having_token: Node<(), ID>,
pub condition: Condition<'s, ID>,
}
#[derive(Debug)]
pub struct ForUpdate<'s, ID> {
pub for_token: Node<(), ID>,
pub update_token: Node<(), ID>,
pub of_columns: Option<ForUpdateOfColumns<'s, ID>>,
pub lock_opts: Option<ForUpdateLockOptions<'s, ID>>,
}
#[derive(Debug)]
pub struct ForUpdateOfColumns<'s, ID> {
pub of_token: Node<(), ID>,
pub columns: Vec<Identifier<'s, ID>>,
}
#[derive(Debug)]
pub enum ForUpdateLockOptions<'s, ID> {
Skip {
skip_token: Node<(), ID>,
locked_token: Node<(), ID>,
},
NoWait {
nowait_token: Node<(), ID>,
},
Wait {
wait_token: Node<(), ID>,
duration: Node<&'s str, ID>,
},
}
#[derive(Debug)]
pub struct RowLimit<'s, ID> {
pub offset: Option<RowLimitOffset<'s, ID>>,
pub fetch: Option<RowLimitFetch<'s, ID>>,
}
#[derive(Debug)]
pub struct RowLimitOffset<'s, ID> {
pub offset_token: Node<(), ID>,
pub offset_value: Expr<'s, ID>,
pub row_token: Node<RowKeyword, ID>,
}
#[derive(Debug)]
pub struct RowLimitFetch<'s, ID> {
pub fetch_token: Node<(), ID>,
pub first_token: Node<FetchFirstKeyword, ID>,
pub row_token: Node<RowKeyword, ID>,
pub fetch_amount: FetchAmount<'s, ID>,
pub fetch_amount_spec: FetchAmountSpec<ID>,
}
#[derive(Debug, Copy, Clone)]
pub enum FetchFirstKeyword {
First,
Next,
}
#[derive(Debug)]
pub enum FetchAmount<'s, ID> {
Count(Expr<'s, ID>),
Percent {
amount: Expr<'s, ID>,
percent_token: Node<(), ID>,
},
}
#[derive(Debug)]
pub enum FetchAmountSpec<ID> {
Only {
only_token: Node<(), ID>,
},
WithTies {
with_token: Node<(), ID>,
ties_token: Node<(), ID>,
},
}
#[derive(Debug, Copy, Clone)]
pub enum RowKeyword {
Row,
Rows,
}
#[derive(Debug)]
pub struct QueryWindows<'s, ID> {
pub window_token: Node<(), ID>,
pub windows: Vec<QueryWindow<'s, ID>>,
}
#[derive(Debug)]
pub struct QueryWindow<'s, ID> {
pub name: Node<Ident<'s>, ID>,
pub as_token: Node<(), ID>,
pub window: Node<WindowSpec<'s, ID>, ID>,
}