Add constraint

This commit is contained in:
eraden 2023-06-10 22:48:33 +02:00
parent 1ac4327a0a
commit 894e8b40a4
3 changed files with 231 additions and 5 deletions

View File

@ -502,7 +502,8 @@ impl Migration {
PaymentCollectionSession::PaymentSessionId, PaymentCollectionSession::PaymentSessionId,
)) ))
.to_owned(), .to_owned(),
); )
.await?;
Ok(()) Ok(())
} }
/// ```sql /// ```sql

View File

@ -1,9 +1,10 @@
use sea_orm_migration::prelude::*; use sea_orm_migration::prelude::*;
use crate::constraint::Check;
use crate::sea_orm::Iterable; use crate::sea_orm::Iterable;
use crate::{ use crate::{
auto_uuid_not_null, create_type, drop_type, to_fk_name, to_pk2_name, ts_def_now_not_null, auto_uuid_not_null, create_constraint, create_type, drop_type, to_fk_name, to_pk2_name,
DropTable, IntoColumnDef, ts_def_now_not_null, AsIden, DropTable, IntoColumnDef,
}; };
#[derive(DeriveMigrationName)] #[derive(DeriveMigrationName)]
@ -21,6 +22,7 @@ impl MigrationTrait for Migration {
} }
impl Migration { impl Migration {
/// ```sql
/// CREATE TABLE line_items /// CREATE TABLE line_items
/// ( /// (
/// id uuid NOT NULL, /// id uuid NOT NULL,
@ -52,7 +54,26 @@ impl Migration {
/// CONSTRAINT "CHK_91f40396d847f6ecfd9f752bf8" CHECK ((returned_quantity <= quantity)), /// CONSTRAINT "CHK_91f40396d847f6ecfd9f752bf8" CHECK ((returned_quantity <= quantity)),
/// CONSTRAINT "CHK_c61716c68f5ad5de2834c827d3" CHECK ((fulfilled_quantity <= quantity)) /// CONSTRAINT "CHK_c61716c68f5ad5de2834c827d3" CHECK ((fulfilled_quantity <= quantity))
/// ); /// );
/// /// ```
async fn create_line_items(&self, m: &SchemaManager<'_>) -> Result<(), DbErr> {
create_constraint(
m,
LineItem::LineItems,
Check::lower_eq(LineItem::ShippedQuantity, LineItem::FulfilledQuantity),
)
.await?;
create_constraint(
m,
LineItem::LineItems,
Check::greater(LineItem::Quantity, 0.iden()),
)
.await?;
Ok(())
}
/// ```sql
/// CREATE TABLE line_item_adjustments /// CREATE TABLE line_item_adjustments
/// ( /// (
/// id uuid NOT NULL, /// id uuid NOT NULL,
@ -62,7 +83,12 @@ impl Migration {
/// amount numeric NOT NULL, /// amount numeric NOT NULL,
/// metadata jsonb /// metadata jsonb
/// ); /// );
/// /// ```
async fn create_line_item_adjustments(&self, m: &SchemaManager<'_>) -> Result<(), DbErr> {
Ok(())
}
/// ```sql
/// CREATE TABLE line_item_tax_lines /// CREATE TABLE line_item_tax_lines
/// ( /// (
/// id uuid NOT NULL, /// id uuid NOT NULL,
@ -74,4 +100,61 @@ impl Migration {
/// metadata jsonb, /// metadata jsonb,
/// item_id uuid NOT NULL /// item_id uuid NOT NULL
/// ); /// );
/// ```
async fn create_line_item_tax_lines(&self, m: &SchemaManager<'_>) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(Iden)]
pub enum LineItem {
LineItems,
Id,
CartId,
OrderId,
SwapId,
Title,
Description,
Thumbnail,
IsGiftcard,
ShouldMerge,
AllowDiscounts,
HasShipping,
UnitPrice,
VariantId,
Quantity,
FulfilledQuantity,
ReturnedQuantity,
ShippedQuantity,
CreatedAt,
UpdatedAt,
Metadata,
ClaimOrderId,
IsReturn,
OriginalItemId,
OrderEditId,
}
#[derive(Iden)]
pub enum LineItemAdjustment {
LineItemAdjustments,
Id,
ItemId,
Description,
DiscountId,
Amount,
Metadata,
}
#[derive(Iden)]
pub enum LineItemTaxLine {
LineItemTaxLines,
Id,
Rate,
Name,
Code,
CreatedAt,
UpdatedAt,
Metadata,
ItemId,
} }

View File

@ -1,3 +1,5 @@
use std::fmt::{Display, Formatter, Pointer};
pub use sea_orm_migration::prelude::*; pub use sea_orm_migration::prelude::*;
pub mod carts; pub mod carts;
@ -18,6 +20,8 @@ pub mod types;
pub use types::*; pub use types::*;
use crate::constraint::Check;
#[macro_export] #[macro_export]
macro_rules! ts_def_now_not_null { macro_rules! ts_def_now_not_null {
($identifier: expr) => { ($identifier: expr) => {
@ -109,3 +113,141 @@ fn to_snake(s: String) -> String {
m m
}) })
} }
pub mod constraint {
use std::fmt::{Display, Formatter, Write};
use crate::{Constraint, Iden};
pub enum Check {
Lower(Box<dyn Iden>, Box<dyn Iden>),
LowerEq(Box<dyn Iden>, Box<dyn Iden>),
Eq(Box<dyn Iden>, Box<dyn Iden>),
GreaterEq(Box<dyn Iden>, Box<dyn Iden>),
Greater(Box<dyn Iden>, Box<dyn Iden>),
Or(Box<Check>, Box<Check>),
}
impl Check {
pub fn or(self, r: Check) -> Check {
Check::Or(Box::new(self), Box::new(r))
}
pub fn constraint(self) -> Constraint {
Constraint::Check(self)
}
pub fn to_name(&self) -> String {
match self {
Check::Lower(l, r) => format!("{}_lw_{}", l.to_string(), r.to_string()),
Check::LowerEq(l, r) => format!("{}_le_{}", l.to_string(), r.to_string()),
Check::Eq(l, r) => format!("{}_eq_{}", l.to_string(), r.to_string()),
Check::GreaterEq(l, r) => format!("{}_ge_{}", l.to_string(), r.to_string()),
Check::Greater(l, r) => format!("{}_g_{}", l.to_string(), r.to_string()),
Check::Or(l, r) => format!("{}_or_{}", l.to_name(), r.to_name()),
}
}
}
impl Display for Check {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Check::Lower(l, r) => {
f.write_fmt(format_args!("{} < {}", l.to_string(), r.to_string()))
}
Check::LowerEq(l, r) => {
f.write_fmt(format_args!("{} <= {}", l.to_string(), r.to_string()))
}
Check::Eq(l, r) => {
f.write_fmt(format_args!("{} = {}", l.to_string(), r.to_string()))
}
Check::GreaterEq(l, r) => {
f.write_fmt(format_args!("{} >= {}", l.to_string(), r.to_string()))
}
Check::Greater(l, r) => {
f.write_fmt(format_args!("{} > {}", l.to_string(), r.to_string()))
}
Check::Or(l, r) => f.write_fmt(format_args!("({l}) OR ({r})")),
}
}
}
impl Check {
pub fn lower<L: Iden + 'static, R: Iden + 'static>(l: L, r: R) -> Check {
Check::Lower(Box::new(l), Box::new(r))
}
pub fn lower_eq<L: Iden + 'static, R: Iden + 'static>(l: L, r: R) -> Check {
Check::LowerEq(Box::new(l), Box::new(r))
}
pub fn eq<L: Iden + 'static, R: Iden + 'static>(l: L, r: R) -> Check {
Check::Eq(Box::new(l), Box::new(r))
}
pub fn greater_eq<L: Iden + 'static, R: Iden + 'static>(l: L, r: R) -> Check {
Check::GreaterEq(Box::new(l), Box::new(r))
}
pub fn greater<L: Iden + 'static, R: Iden + 'static>(l: L, r: R) -> Check {
Check::Greater(Box::new(l), Box::new(r))
}
}
}
pub struct CheckUSize(usize);
impl Iden for CheckUSize {
fn unquoted(&self, s: &mut dyn Write) {
s.write_str(&format!("{}", self.0));
}
}
pub trait AsIden<I: Iden> {
fn iden(self) -> I;
}
impl AsIden<CheckUSize> for usize {
fn iden(self) -> CheckUSize {
CheckUSize(self)
}
}
pub enum Constraint {
Check(Check),
}
impl Constraint {
fn to_name(&self) -> String {
match self {
Constraint::Check(check) => format!("ck_{}", check.to_name()),
}
}
}
impl From<Check> for Constraint {
fn from(value: Check) -> Self {
Self::Check(value)
}
}
impl Display for Constraint {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Constraint::Check(check) => f.write_fmt(format_args!("CHECK {check}")),
}
}
}
async fn create_constraint<T: Iden, C: Into<Constraint>>(
m: &SchemaManager<'_>,
table: T,
c: C,
) -> Result<(), DbErr> {
let c = c.into();
m.get_connection()
.execute_unprepared(&format!(
"ALTER TABLE {} ADD CONSTRAINT {} {}",
table.to_string(),
c.to_name(),
c
))
.await;
Ok(())
}