use std::fmt;
use crate::{expr::*, types::*};
#[derive(Debug, Clone)]
pub struct ColumnDef {
pub(crate) table: Option<TableRef>,
pub(crate) name: DynIden,
pub(crate) types: Option<ColumnType>,
pub(crate) spec: Vec<ColumnSpec>,
}
pub trait IntoColumnDef {
fn into_column_def(self) -> ColumnDef;
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum ColumnType {
Char(Option<u32>),
String(StringLen),
Text,
Blob,
TinyInteger,
SmallInteger,
Integer,
BigInteger,
TinyUnsigned,
SmallUnsigned,
Unsigned,
BigUnsigned,
Float,
Double,
Decimal(Option<(u32, u32)>),
DateTime,
Timestamp,
TimestampWithTimeZone,
Time,
Date,
Year,
Interval(Option<PgInterval>, Option<u32>),
Binary(u32),
VarBinary(StringLen),
Bit(Option<u32>),
VarBit(u32),
Boolean,
Money(Option<(u32, u32)>),
Json,
JsonBinary,
Uuid,
Custom(DynIden),
Enum {
name: DynIden,
variants: Vec<DynIden>,
},
Array(RcOrArc<ColumnType>),
Vector(Option<u32>),
Cidr,
Inet,
MacAddr,
LTree,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum StringLen {
N(u32),
Max,
#[default]
None,
}
impl PartialEq for ColumnType {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Char(l0), Self::Char(r0)) => l0 == r0,
(Self::String(l0), Self::String(r0)) => l0 == r0,
(Self::Decimal(l0), Self::Decimal(r0)) => l0 == r0,
(Self::Interval(l0, l1), Self::Interval(r0, r1)) => l0 == r0 && l1 == r1,
(Self::Binary(l0), Self::Binary(r0)) => l0 == r0,
(Self::VarBinary(l0), Self::VarBinary(r0)) => l0 == r0,
(Self::Bit(l0), Self::Bit(r0)) => l0 == r0,
(Self::VarBit(l0), Self::VarBit(r0)) => l0 == r0,
(Self::Money(l0), Self::Money(r0)) => l0 == r0,
(Self::Custom(l0), Self::Custom(r0)) => l0.to_string() == r0.to_string(),
(
Self::Enum {
name: l_name,
variants: l_variants,
},
Self::Enum {
name: r_name,
variants: r_variants,
},
) => {
l_name.to_string() == r_name.to_string()
&& l_variants
.iter()
.map(|v| v.to_string())
.eq(r_variants.iter().map(|v| v.to_string()))
}
(Self::Array(l0), Self::Array(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
impl ColumnType {
pub fn custom<T>(ty: T) -> ColumnType
where
T: Into<String>,
{
ColumnType::Custom(Alias::new(ty).into_iden())
}
pub fn string(length: Option<u32>) -> ColumnType {
match length {
Some(s) => ColumnType::String(StringLen::N(s)),
None => ColumnType::String(StringLen::None),
}
}
pub fn var_binary(length: u32) -> ColumnType {
ColumnType::VarBinary(StringLen::N(length))
}
}
#[derive(Debug, Clone)]
pub enum ColumnSpec {
Null,
NotNull,
Default(SimpleExpr),
AutoIncrement,
UniqueKey,
PrimaryKey,
Check(SimpleExpr),
Generated { expr: SimpleExpr, stored: bool },
Extra(String),
Comment(String),
Using(SimpleExpr),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PgInterval {
Year,
Month,
Day,
Hour,
Minute,
Second,
YearToMonth,
DayToHour,
DayToMinute,
DayToSecond,
HourToMinute,
HourToSecond,
MinuteToSecond,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PgDateTruncUnit {
Microseconds,
Milliseconds,
Second,
Minute,
Hour,
Day,
Week,
Month,
Quarter,
Year,
Decade,
Century,
Millennium,
}
impl fmt::Display for PgDateTruncUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let text = match self {
PgDateTruncUnit::Microseconds => "microseconds",
PgDateTruncUnit::Milliseconds => "milliseconds",
PgDateTruncUnit::Second => "second",
PgDateTruncUnit::Minute => "minute",
PgDateTruncUnit::Hour => "hour",
PgDateTruncUnit::Day => "day",
PgDateTruncUnit::Week => "week",
PgDateTruncUnit::Month => "month",
PgDateTruncUnit::Quarter => "quarter",
PgDateTruncUnit::Year => "year",
PgDateTruncUnit::Decade => "decade",
PgDateTruncUnit::Century => "century",
PgDateTruncUnit::Millennium => "millennium",
};
write!(f, "{}", text)
}
}
impl ColumnDef {
pub fn new<T>(name: T) -> Self
where
T: IntoIden,
{
Self {
table: None,
name: name.into_iden(),
types: None,
spec: Vec::new(),
}
}
pub fn new_with_type<T>(name: T, types: ColumnType) -> Self
where
T: IntoIden,
{
Self {
table: None,
name: name.into_iden(),
types: Some(types),
spec: Vec::new(),
}
}
pub fn not_null(&mut self) -> &mut Self {
self.spec.push(ColumnSpec::NotNull);
self
}
pub fn null(&mut self) -> &mut Self {
self.spec.push(ColumnSpec::Null);
self
}
pub fn default<T>(&mut self, value: T) -> &mut Self
where
T: Into<SimpleExpr>,
{
self.spec.push(ColumnSpec::Default(value.into()));
self
}
pub fn auto_increment(&mut self) -> &mut Self {
self.spec.push(ColumnSpec::AutoIncrement);
self
}
pub fn unique_key(&mut self) -> &mut Self {
self.spec.push(ColumnSpec::UniqueKey);
self
}
pub fn primary_key(&mut self) -> &mut Self {
self.spec.push(ColumnSpec::PrimaryKey);
self
}
pub fn char_len(&mut self, length: u32) -> &mut Self {
self.types = Some(ColumnType::Char(Some(length)));
self
}
pub fn char(&mut self) -> &mut Self {
self.types = Some(ColumnType::Char(None));
self
}
pub fn string_len(&mut self, length: u32) -> &mut Self {
self.types = Some(ColumnType::String(StringLen::N(length)));
self
}
pub fn string(&mut self) -> &mut Self {
self.types = Some(ColumnType::String(Default::default()));
self
}
pub fn text(&mut self) -> &mut Self {
self.types = Some(ColumnType::Text);
self
}
pub fn tiny_integer(&mut self) -> &mut Self {
self.types = Some(ColumnType::TinyInteger);
self
}
pub fn small_integer(&mut self) -> &mut Self {
self.types = Some(ColumnType::SmallInteger);
self
}
pub fn integer(&mut self) -> &mut Self {
self.types = Some(ColumnType::Integer);
self
}
pub fn big_integer(&mut self) -> &mut Self {
self.types = Some(ColumnType::BigInteger);
self
}
pub fn tiny_unsigned(&mut self) -> &mut Self {
self.types = Some(ColumnType::TinyUnsigned);
self
}
pub fn small_unsigned(&mut self) -> &mut Self {
self.types = Some(ColumnType::SmallUnsigned);
self
}
pub fn unsigned(&mut self) -> &mut Self {
self.types = Some(ColumnType::Unsigned);
self
}
pub fn big_unsigned(&mut self) -> &mut Self {
self.types = Some(ColumnType::BigUnsigned);
self
}
pub fn float(&mut self) -> &mut Self {
self.types = Some(ColumnType::Float);
self
}
pub fn double(&mut self) -> &mut Self {
self.types = Some(ColumnType::Double);
self
}
pub fn decimal_len(&mut self, precision: u32, scale: u32) -> &mut Self {
self.types = Some(ColumnType::Decimal(Some((precision, scale))));
self
}
pub fn decimal(&mut self) -> &mut Self {
self.types = Some(ColumnType::Decimal(None));
self
}
pub fn date_time(&mut self) -> &mut Self {
self.types = Some(ColumnType::DateTime);
self
}
#[cfg(feature = "backend-postgres")]
pub fn interval(&mut self, fields: Option<PgInterval>, precision: Option<u32>) -> &mut Self {
self.types = Some(ColumnType::Interval(fields, precision));
self
}
#[cfg(feature = "postgres-vector")]
pub fn vector(&mut self, size: Option<u32>) -> &mut Self {
self.types = Some(ColumnType::Vector(size));
self
}
pub fn timestamp(&mut self) -> &mut Self {
self.types = Some(ColumnType::Timestamp);
self
}
pub fn timestamp_with_time_zone(&mut self) -> &mut Self {
self.types = Some(ColumnType::TimestampWithTimeZone);
self
}
pub fn time(&mut self) -> &mut Self {
self.types = Some(ColumnType::Time);
self
}
pub fn date(&mut self) -> &mut Self {
self.types = Some(ColumnType::Date);
self
}
pub fn year(&mut self) -> &mut Self {
self.types = Some(ColumnType::Year);
self
}
pub fn binary_len(&mut self, length: u32) -> &mut Self {
self.types = Some(ColumnType::Binary(length));
self
}
pub fn binary(&mut self) -> &mut Self {
self.binary_len(1)
}
pub fn var_binary(&mut self, length: u32) -> &mut Self {
self.types = Some(ColumnType::VarBinary(StringLen::N(length)));
self
}
pub fn bit(&mut self, length: Option<u32>) -> &mut Self {
self.types = Some(ColumnType::Bit(length));
self
}
pub fn varbit(&mut self, length: u32) -> &mut Self {
self.types = Some(ColumnType::VarBit(length));
self
}
pub fn blob(&mut self) -> &mut Self {
self.types = Some(ColumnType::Blob);
self
}
pub fn boolean(&mut self) -> &mut Self {
self.types = Some(ColumnType::Boolean);
self
}
pub fn money_len(&mut self, precision: u32, scale: u32) -> &mut Self {
self.types = Some(ColumnType::Money(Some((precision, scale))));
self
}
pub fn money(&mut self) -> &mut Self {
self.types = Some(ColumnType::Money(None));
self
}
pub fn json(&mut self) -> &mut Self {
self.types = Some(ColumnType::Json);
self
}
pub fn json_binary(&mut self) -> &mut Self {
self.types = Some(ColumnType::JsonBinary);
self
}
pub fn uuid(&mut self) -> &mut Self {
self.types = Some(ColumnType::Uuid);
self
}
pub fn custom<T>(&mut self, name: T) -> &mut Self
where
T: IntoIden,
{
self.types = Some(ColumnType::Custom(name.into_iden()));
self
}
pub fn enumeration<N, S, V>(&mut self, name: N, variants: V) -> &mut Self
where
N: IntoIden,
S: IntoIden,
V: IntoIterator<Item = S>,
{
self.types = Some(ColumnType::Enum {
name: name.into_iden(),
variants: variants.into_iter().map(IntoIden::into_iden).collect(),
});
self
}
pub fn array(&mut self, elem_type: ColumnType) -> &mut Self {
self.types = Some(ColumnType::Array(RcOrArc::new(elem_type)));
self
}
pub fn cidr(&mut self) -> &mut Self {
self.types = Some(ColumnType::Cidr);
self
}
pub fn inet(&mut self) -> &mut Self {
self.types = Some(ColumnType::Inet);
self
}
pub fn mac_address(&mut self) -> &mut Self {
self.types = Some(ColumnType::MacAddr);
self
}
pub fn ltree(&mut self) -> &mut Self {
self.types = Some(ColumnType::LTree);
self
}
pub fn check<T>(&mut self, value: T) -> &mut Self
where
T: Into<SimpleExpr>,
{
self.spec.push(ColumnSpec::Check(value.into()));
self
}
pub fn generated<T>(&mut self, expr: T, stored: bool) -> &mut Self
where
T: Into<SimpleExpr>,
{
self.spec.push(ColumnSpec::Generated {
expr: expr.into(),
stored,
});
self
}
pub fn extra<T>(&mut self, string: T) -> &mut Self
where
T: Into<String>,
{
self.spec.push(ColumnSpec::Extra(string.into()));
self
}
pub fn using<T>(&mut self, value: T) -> &mut Self
where
T: Into<SimpleExpr>,
{
self.spec.push(ColumnSpec::Using(value.into()));
self
}
pub fn comment<T>(&mut self, string: T) -> &mut Self
where
T: Into<String>,
{
self.spec.push(ColumnSpec::Comment(string.into()));
self
}
pub fn get_column_name(&self) -> String {
self.name.to_string()
}
pub fn get_column_type(&self) -> Option<&ColumnType> {
self.types.as_ref()
}
pub fn get_column_spec(&self) -> &Vec<ColumnSpec> {
self.spec.as_ref()
}
pub fn take(&mut self) -> Self {
Self {
table: self.table.take(),
name: std::mem::replace(&mut self.name, SeaRc::new(NullAlias::new())),
types: self.types.take(),
spec: std::mem::take(&mut self.spec),
}
}
}
impl IntoColumnDef for &mut ColumnDef {
fn into_column_def(self) -> ColumnDef {
self.take()
}
}
impl IntoColumnDef for ColumnDef {
fn into_column_def(self) -> ColumnDef {
self
}
}