From 3e97249097ceae29b7c5dd44100480ee58b4e4f3 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 30 Jan 2024 12:48:24 +0800 Subject: [PATCH] mysql: sized blob data type moved to `MySqlType` & upstream `StringLen` --- src/backend/mysql/table.rs | 21 +++++------- src/backend/postgres/table.rs | 9 +++-- src/backend/sqlite/table.rs | 15 ++++----- src/extension/mysql/column.rs | 21 ++++++++++++ src/extension/mysql/mod.rs | 2 ++ src/table/column.rs | 62 +++++++++++++++++++---------------- src/value.rs | 8 ++--- tests/common.rs | 1 + tests/mysql/mod.rs | 2 +- tests/mysql/table.rs | 19 +++++------ tests/postgres/table.rs | 20 ++--------- tests/sqlite/table.rs | 20 ++--------- 12 files changed, 97 insertions(+), 103 deletions(-) create mode 100644 src/extension/mysql/column.rs diff --git a/src/backend/mysql/table.rs b/src/backend/mysql/table.rs index 881922f4c..42f0d0646 100644 --- a/src/backend/mysql/table.rs +++ b/src/backend/mysql/table.rs @@ -34,8 +34,9 @@ impl TableBuilder for MysqlQueryBuilder { None => "char".into(), }, ColumnType::String(length) => match length { - Some(length) => format!("varchar({length})"), - None => "varchar(255)".into(), + StringLen::N(length) => format!("varchar({length})"), + StringLen::None => format!("varchar(255)"), + StringLen::Max => "varchar(65535)".into(), }, ColumnType::Text => "text".into(), ColumnType::TinyInteger | ColumnType::TinyUnsigned => "tinyint".into(), @@ -63,18 +64,12 @@ impl TableBuilder for MysqlQueryBuilder { } } ColumnType::Interval(_, _) => "unsupported".into(), - ColumnType::Binary(blob_size) => match blob_size { - BlobSize::Tiny => "tinyblob".into(), - BlobSize::Blob(length) => { - match length { - Some(length) => format!("binary({length})"), - None => "blob".into(), - } - } - BlobSize::Medium => "mediumblob".into(), - BlobSize::Long => "longblob".into(), + ColumnType::Binary(length) => format!("binary({length})"), + ColumnType::VarBinary(length) => match length { + StringLen::N(length) => format!("varbinary({length})"), + StringLen::None => format!("varbinary(255)"), + StringLen::Max => "varbinary(65535)".into(), }, - ColumnType::VarBinary(length) => format!("varbinary({length})"), ColumnType::Bit(length) => { match length { Some(length) => format!("bit({length})"), diff --git a/src/backend/postgres/table.rs b/src/backend/postgres/table.rs index 11fc6a4f3..bc13b1558 100644 --- a/src/backend/postgres/table.rs +++ b/src/backend/postgres/table.rs @@ -18,8 +18,8 @@ impl TableBuilder for PostgresQueryBuilder { None => "char".into(), }, ColumnType::String(length) => match length { - Some(length) => format!("varchar({length})"), - None => "varchar".into(), + StringLen::N(length) => format!("varchar({length})"), + _ => "varchar".into(), }, ColumnType::Text => "text".into(), ColumnType::TinyInteger | ColumnType::TinyUnsigned => "smallint".into(), @@ -48,7 +48,10 @@ impl TableBuilder for PostgresQueryBuilder { typ } ColumnType::Binary(_) => "bytea".into(), - ColumnType::VarBinary(length) => format!("bit varying({length})"), + ColumnType::VarBinary(length) => match length { + StringLen::N(length) => format!("bit varying({length})"), + _ => "bit varying".into(), + }, ColumnType::Bit(length) => { match length { Some(length) => format!("varbit({length})"), diff --git a/src/backend/sqlite/table.rs b/src/backend/sqlite/table.rs index e32741bea..b87698ba1 100644 --- a/src/backend/sqlite/table.rs +++ b/src/backend/sqlite/table.rs @@ -135,8 +135,8 @@ impl SqliteQueryBuilder { None => "char".into(), }, ColumnType::String(length) => match length { - Some(length) => format!("varchar({length})"), - None => "varchar".into(), + StringLen::N(length) => format!("varchar({length})"), + _ => "varchar".into(), }, ColumnType::Text => "text".into(), ColumnType::TinyInteger | ColumnType::TinyUnsigned => integer("tinyint").into(), @@ -167,14 +167,11 @@ impl SqliteQueryBuilder { ColumnType::Date => "date_text".into(), ColumnType::Interval(_, _) => unimplemented!("Interval is not available in Sqlite."), - ColumnType::Binary(blob_size) => match blob_size { - BlobSize::Tiny => "tinyblob".into(), - BlobSize::Blob(Some(length)) => format!("blob({length})"), - BlobSize::Blob(None) => "blob".into(), - BlobSize::Medium => "mediumblob".into(), - BlobSize::Long => "longblob".into(), + ColumnType::Binary(length) => format!("blob({length})"), + ColumnType::VarBinary(length) => match length { + StringLen::N(length) => format!("varbinary_blob({length})"), + _ => "varbinary_blob".into(), }, - ColumnType::VarBinary(length) => format!("varbinary_blob({length})"), ColumnType::Boolean => "boolean".into(), ColumnType::Money(precision) => match precision { Some((precision, scale)) => format!("money({precision}, {scale})"), diff --git a/src/extension/mysql/column.rs b/src/extension/mysql/column.rs new file mode 100644 index 000000000..2782208a6 --- /dev/null +++ b/src/extension/mysql/column.rs @@ -0,0 +1,21 @@ +use crate::Iden; + +#[derive(Debug, Copy, Clone)] +pub enum MySqlType { + Blob, + TinyBlob, + MediumBlob, + LongBlob, +} + +impl Iden for MySqlType { + fn unquoted(&self, s: &mut dyn std::fmt::Write) { + let ty = match self { + Self::Blob => "blob", + Self::TinyBlob => "tinyblob", + Self::MediumBlob => "mediumblob", + Self::LongBlob => "longblob", + }; + write!(s, "{ty}").unwrap(); + } +} diff --git a/src/extension/mysql/mod.rs b/src/extension/mysql/mod.rs index dd8cc4f86..9841ca6eb 100644 --- a/src/extension/mysql/mod.rs +++ b/src/extension/mysql/mod.rs @@ -1,5 +1,7 @@ +mod column; mod index; mod select; +pub use column::*; pub use index::*; pub use select::*; diff --git a/src/table/column.rs b/src/table/column.rs index 7ed0f7165..fc145e8ba 100644 --- a/src/table/column.rs +++ b/src/table/column.rs @@ -14,7 +14,7 @@ pub struct ColumnDef { #[derive(Debug, Clone)] pub enum ColumnType { Char(Option), - String(Option), + String(StringLen), Text, TinyInteger, SmallInteger, @@ -34,8 +34,8 @@ pub enum ColumnType { Date, Year(Option), Interval(Option, Option), - Binary(BlobSize), - VarBinary(u32), + Binary(u32), + VarBinary(StringLen), Bit(Option), VarBit(u32), Boolean, @@ -55,6 +55,21 @@ pub enum ColumnType { LTree, } +/// Length for var-char/binary; default to 255 +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum StringLen { + /// String size + N(u32), + Max, + None, +} + +impl Default for StringLen { + fn default() -> Self { + Self::None + } +} + impl PartialEq for ColumnType { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -140,15 +155,6 @@ pub enum MySqlYear { Four, } -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum BlobSize { - Tiny, - /// MySQL & SQLite support `binary(length)` column type - Blob(Option), - Medium, - Long, -} - impl ColumnDef { /// Construct a table column pub fn new(name: T) -> Self @@ -266,13 +272,19 @@ impl ColumnDef { /// Set column type as string with custom length pub fn string_len(&mut self, length: u32) -> &mut Self { - self.types = Some(ColumnType::String(Some(length))); + self.types = Some(ColumnType::String(StringLen::N(length))); + self + } + + /// Set column type as string with maximum length + pub fn string_max(&mut self) -> &mut Self { + self.types = Some(ColumnType::String(StringLen::Max)); self } /// Set column type as string pub fn string(&mut self) -> &mut Self { - self.types = Some(ColumnType::String(None)); + self.types = Some(ColumnType::String(Default::default())); self } @@ -437,26 +449,20 @@ impl ColumnDef { } /// Set column type as binary with custom length - pub fn binary_len(&mut self, length: u32) -> &mut Self { - self.types = Some(ColumnType::Binary(BlobSize::Blob(Some(length)))); - self - } - - /// Set column type as binary - pub fn binary(&mut self) -> &mut Self { - self.types = Some(ColumnType::Binary(BlobSize::Blob(None))); + pub fn binary(&mut self, length: u32) -> &mut Self { + self.types = Some(ColumnType::Binary(length)); self } - /// Set column type as blob, but when given BlobSize::Blob(size) argument, this column map to binary(size) type instead. - pub fn blob(&mut self, size: BlobSize) -> &mut Self { - self.types = Some(ColumnType::Binary(size)); + /// Set column type as binary with variable length + pub fn var_binary(&mut self, length: u32) -> &mut Self { + self.types = Some(ColumnType::VarBinary(StringLen::N(length))); self } - /// Set column type as binary with variable length - pub fn var_binary(&mut self, length: u32) -> &mut Self { - self.types = Some(ColumnType::VarBinary(length)); + /// Set column type as binary with maximum length + pub fn var_binary_max(&mut self) -> &mut Self { + self.types = Some(ColumnType::VarBinary(StringLen::Max)); self } diff --git a/src/value.rs b/src/value.rs index 7049d744a..37cd4d2f6 100644 --- a/src/value.rs +++ b/src/value.rs @@ -31,7 +31,7 @@ use std::net::IpAddr; #[cfg(feature = "with-mac_address")] use mac_address::MacAddress; -use crate::{BlobSize, ColumnType, CommonSqlQueryBuilder, QueryBuilder}; +use crate::{ColumnType, CommonSqlQueryBuilder, QueryBuilder, StringLen}; /// [`Value`] types variant for Postgres array #[derive(Clone, Debug, Eq, PartialEq, Hash)] @@ -495,12 +495,12 @@ impl ValueType for Cow<'_, str> { } fn column_type() -> ColumnType { - ColumnType::String(None) + ColumnType::String(StringLen::Max) } } -type_to_box_value!(Vec, Bytes, Binary(BlobSize::Blob(None))); -type_to_box_value!(String, String, String(None)); +type_to_box_value!(Vec, Bytes, VarBinary(StringLen::Max)); +type_to_box_value!(String, String, String(StringLen::Max)); #[cfg(feature = "with-json")] #[cfg_attr(docsrs, doc(cfg(feature = "with-json")))] diff --git a/tests/common.rs b/tests/common.rs index 65a24ebfa..a3f90863c 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -11,6 +11,7 @@ use sea_query::Iden; /// /// [`Iden`]: crate::types::Iden #[derive(Debug)] +#[allow(dead_code)] pub enum BinaryType { Table, BinaryLen, diff --git a/tests/mysql/mod.rs b/tests/mysql/mod.rs index fc7388cd0..d717774f1 100644 --- a/tests/mysql/mod.rs +++ b/tests/mysql/mod.rs @@ -1,4 +1,4 @@ -use sea_query::{tests_cfg::*, *}; +use sea_query::{extension::mysql::*, tests_cfg::*, *}; mod foreign_key; mod index; diff --git a/tests/mysql/table.rs b/tests/mysql/table.rs index d07df98dd..e49ad4a7a 100644 --- a/tests/mysql/table.rs +++ b/tests/mysql/table.rs @@ -163,20 +163,17 @@ fn create_6() { assert_eq!( Table::create() .table(BinaryType::Table) - .col(ColumnDef::new(BinaryType::BinaryLen).binary_len(32)) - .col(ColumnDef::new(BinaryType::Binary).binary()) - .col(ColumnDef::new(BinaryType::BlobSize).blob(BlobSize::Blob(Some(32)))) - .col(ColumnDef::new(BinaryType::TinyBlob).blob(BlobSize::Tiny)) - .col(ColumnDef::new(BinaryType::Blob).blob(BlobSize::Blob(None))) - .col(ColumnDef::new(BinaryType::MediumBlob).blob(BlobSize::Medium)) - .col(ColumnDef::new(BinaryType::LongBlob).blob(BlobSize::Long)) + .col(ColumnDef::new(BinaryType::BinaryLen).binary(32)) + .col(ColumnDef::new(BinaryType::Binary).custom(MySqlType::Blob)) + .col(ColumnDef::new(BinaryType::TinyBlob).custom(MySqlType::TinyBlob)) + .col(ColumnDef::new(BinaryType::MediumBlob).custom(MySqlType::MediumBlob)) + .col(ColumnDef::new(BinaryType::LongBlob).custom(MySqlType::LongBlob)) .to_string(MysqlQueryBuilder), [ "CREATE TABLE `binary_type` (", "`binlen` binary(32),", - "`bin` blob, `defb` binary(32),", + "`bin` blob,", "`tb` tinyblob,", - "`b` blob,", "`mb` mediumblob,", "`lb` longblob", ")", @@ -190,8 +187,8 @@ fn create_7() { assert_eq!( Table::create() .table(Char::Table) - .col(ColumnDef::new(Char::Character).binary()) - .col(ColumnDef::new(Char::FontSize).binary_len(10)) + .col(ColumnDef::new(Char::Character).custom(MySqlType::Blob)) + .col(ColumnDef::new(Char::FontSize).binary(10)) .col(ColumnDef::new(Char::SizeW).var_binary(10)) .to_string(MysqlQueryBuilder), [ diff --git a/tests/postgres/table.rs b/tests/postgres/table.rs index c63e9e54b..a56b538a2 100644 --- a/tests/postgres/table.rs +++ b/tests/postgres/table.rs @@ -258,23 +258,11 @@ fn create_12() { assert_eq!( Table::create() .table(BinaryType::Table) - .col(ColumnDef::new(BinaryType::BinaryLen).binary_len(32)) - .col(ColumnDef::new(BinaryType::Binary).binary()) - .col(ColumnDef::new(BinaryType::BlobSize).blob(BlobSize::Blob(Some(32)))) - .col(ColumnDef::new(BinaryType::TinyBlob).blob(BlobSize::Tiny)) - .col(ColumnDef::new(BinaryType::Blob).blob(BlobSize::Blob(None))) - .col(ColumnDef::new(BinaryType::MediumBlob).blob(BlobSize::Medium)) - .col(ColumnDef::new(BinaryType::LongBlob).blob(BlobSize::Long)) + .col(ColumnDef::new(BinaryType::BinaryLen).binary(32)) .to_string(PostgresQueryBuilder), [ r#"CREATE TABLE "binary_type" ("#, - r#""binlen" bytea,"#, - r#""bin" bytea,"#, - r#""defb" bytea,"#, - r#""tb" bytea,"#, - r#""b" bytea,"#, - r#""mb" bytea,"#, - r#""lb" bytea"#, + r#""binlen" bytea"#, r#")"#, ] .join(" ") @@ -286,13 +274,11 @@ fn create_13() { assert_eq!( Table::create() .table(Char::Table) - .col(ColumnDef::new(Char::Character).binary()) - .col(ColumnDef::new(Char::FontSize).binary_len(10)) + .col(ColumnDef::new(Char::FontSize).binary(10)) .col(ColumnDef::new(Char::SizeW).var_binary(10)) .to_string(PostgresQueryBuilder), [ r#"CREATE TABLE "character" ("#, - r#""character" bytea,"#, r#""font_size" bytea,"#, r#""size_w" bit varying(10)"#, r#")"#, diff --git a/tests/sqlite/table.rs b/tests/sqlite/table.rs index aa377359d..5b4a36561 100644 --- a/tests/sqlite/table.rs +++ b/tests/sqlite/table.rs @@ -105,23 +105,11 @@ fn create_4() { assert_eq!( Table::create() .table(BinaryType::Table) - .col(ColumnDef::new(BinaryType::BinaryLen).binary_len(32)) - .col(ColumnDef::new(BinaryType::Binary).binary()) - .col(ColumnDef::new(BinaryType::BlobSize).blob(BlobSize::Blob(Some(32)))) - .col(ColumnDef::new(BinaryType::TinyBlob).blob(BlobSize::Tiny)) - .col(ColumnDef::new(BinaryType::Blob).blob(BlobSize::Blob(None))) - .col(ColumnDef::new(BinaryType::MediumBlob).blob(BlobSize::Medium)) - .col(ColumnDef::new(BinaryType::LongBlob).blob(BlobSize::Long)) + .col(ColumnDef::new(BinaryType::BinaryLen).binary(32)) .to_string(SqliteQueryBuilder), [ r#"CREATE TABLE "binary_type" ("#, - r#""binlen" blob(32),"#, - r#""bin" blob,"#, - r#""defb" blob(32),"#, - r#""tb" tinyblob,"#, - r#""b" blob,"#, - r#""mb" mediumblob,"#, - r#""lb" longblob"#, + r#""binlen" blob(32)"#, r#")"#, ] .join(" ") @@ -133,13 +121,11 @@ fn create_5() { assert_eq!( Table::create() .table(Char::Table) - .col(ColumnDef::new(Char::Character).binary()) - .col(ColumnDef::new(Char::FontSize).binary_len(10)) + .col(ColumnDef::new(Char::FontSize).binary(10)) .col(ColumnDef::new(Char::SizeW).var_binary(10)) .to_string(SqliteQueryBuilder), [ r#"CREATE TABLE "character" ("#, - r#""character" blob,"#, r#""font_size" blob(10),"#, r#""size_w" varbinary_blob(10)"#, r#")"#,