use crate::{FunctionCall, SelectStatement, ValueTuple};
use std::{fmt::Debug, iter::Flatten};
use super::*;
pub trait IdenList {
type IntoIter: Iterator<Item = DynIden>;
fn into_iter(self) -> Self::IntoIter;
}
impl<I> IdenList for I
where
I: IntoIden,
{
type IntoIter = std::iter::Once<DynIden>;
fn into_iter(self) -> Self::IntoIter {
std::iter::once(self.into_iden())
}
}
impl<A, B> IdenList for (A, B)
where
A: IntoIden,
B: IntoIden,
{
type IntoIter = std::array::IntoIter<DynIden, 2>;
fn into_iter(self) -> Self::IntoIter {
[self.0.into_iden(), self.1.into_iden()].into_iter()
}
}
impl<A, B, C> IdenList for (A, B, C)
where
A: IntoIden,
B: IntoIden,
C: IntoIden,
{
type IntoIter = std::array::IntoIter<DynIden, 3>;
fn into_iter(self) -> Self::IntoIter {
[self.0.into_iden(), self.1.into_iden(), self.2.into_iden()].into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DatabaseName(pub DynIden);
impl<T> From<T> for DatabaseName
where
T: IntoIden,
{
fn from(iden: T) -> Self {
DatabaseName(iden.into_iden())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SchemaName(pub Option<DatabaseName>, pub DynIden);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeRef(pub Option<SchemaName>, pub DynIden);
pub trait IntoTypeRef: Into<TypeRef> {
fn into_type_ref(self) -> TypeRef;
}
impl<T> IntoTypeRef for T
where
T: Into<TypeRef>,
{
fn into_type_ref(self) -> TypeRef {
self.into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TableName(pub Option<SchemaName>, pub DynIden);
impl TableName {
pub(crate) fn as_iden_tuple(&self) -> (Option<&DynIden>, Option<&DynIden>, &DynIden) {
let TableName(schema_name, table) = self;
match schema_name {
None => (None, None, table),
Some(SchemaName(db_name, schema)) => match db_name {
None => (None, Some(schema), table),
Some(DatabaseName(db)) => (Some(db), Some(schema), table),
},
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ColumnName(pub Option<TableName>, pub DynIden);
impl IdenList for ColumnName {
type IntoIter = Flatten<std::array::IntoIter<Option<DynIden>, 4>>;
fn into_iter(self) -> Self::IntoIter {
let ColumnName(table_name, column) = self;
let arr = match table_name {
None => [None, None, None, Some(column)],
Some(TableName(schema_name, table)) => match schema_name {
None => [None, None, Some(table), Some(column)],
Some(SchemaName(db_name, schema)) => {
let db = db_name.map(|db| db.0);
[db, Some(schema), Some(table), Some(column)]
}
},
};
arr.into_iter().flatten()
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ColumnRef {
Column(ColumnName),
Asterisk(Option<TableName>),
}
impl ColumnRef {
#[doc(hidden)]
pub fn column(&self) -> Option<&DynIden> {
match self {
ColumnRef::Column(ColumnName(_table_ref, column_itself)) => Some(column_itself),
ColumnRef::Asterisk(..) => None,
}
}
}
impl From<Asterisk> for ColumnRef {
fn from(_: Asterisk) -> Self {
ColumnRef::Asterisk(None)
}
}
impl<T> From<T> for ColumnRef
where
T: Into<ColumnName>,
{
fn from(value: T) -> Self {
ColumnRef::Column(value.into())
}
}
impl<T> From<(T, Asterisk)> for ColumnRef
where
T: IntoIden,
{
fn from(value: (T, Asterisk)) -> Self {
ColumnRef::Asterisk(Some(value.0.into_iden().into()))
}
}
pub trait IntoColumnRef: Into<ColumnRef> {
fn into_column_ref(self) -> ColumnRef;
}
impl<T> IntoColumnRef for T
where
T: Into<ColumnRef>,
{
fn into_column_ref(self) -> ColumnRef {
self.into()
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum TableRef {
Table(TableName, Option<DynIden>),
SubQuery(Box<SelectStatement>, DynIden),
ValuesList(Vec<ValueTuple>, DynIden),
FunctionCall(FunctionCall, DynIden),
}
impl TableRef {
pub fn alias<A>(self, alias: A) -> Self
where
A: IntoIden,
{
match self {
Self::Table(table, _) => Self::Table(table, Some(alias.into_iden())),
Self::SubQuery(statement, _) => Self::SubQuery(statement, alias.into_iden()),
Self::ValuesList(values, _) => Self::ValuesList(values, alias.into_iden()),
Self::FunctionCall(func, _) => Self::FunctionCall(func, alias.into_iden()),
}
}
#[doc(hidden)]
pub fn sea_orm_table(&self) -> &DynIden {
match self {
TableRef::Table(TableName(_, tbl), _)
| TableRef::SubQuery(_, tbl)
| TableRef::ValuesList(_, tbl)
| TableRef::FunctionCall(_, tbl) => tbl,
}
}
#[doc(hidden)]
pub fn sea_orm_table_alias(&self) -> Option<&DynIden> {
match self {
TableRef::Table(_, None) | TableRef::SubQuery(_, _) | TableRef::ValuesList(_, _) => {
None
}
TableRef::Table(_, Some(alias)) | TableRef::FunctionCall(_, alias) => Some(alias),
}
}
}
impl<T> From<T> for TableRef
where
T: Into<TableName>,
{
fn from(value: T) -> Self {
TableRef::Table(value.into(), None)
}
}
pub trait IntoTableRef: Into<TableRef> {
fn into_table_ref(self) -> TableRef {
self.into()
}
}
impl<T> IntoTableRef for T where T: Into<TableRef> {}