diff --git a/Cargo.toml b/Cargo.toml index 6bec7da4..1003f9e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,8 @@ path = "src/lib.rs" [dependencies] futures = { version = "0.3", default-features = false, optional = true, features = ["alloc"] } sea-schema-derive = { version = "0.2.0", path = "sea-schema-derive", default-features = false } -sea-query = { version = "0.30.0", default-features = false, features = ["derive"] } -sea-query-binder = { version = "0.5.0", default-features = false, optional = true } +sea-query = { version = "0.31.0-rc.1", default-features = false, features = ["derive"] } +sea-query-binder = { version = "0.6.0-rc.1", default-features = false, optional = true } serde = { version = "1", default-features = false, optional = true, features = ["derive"] } sqlx = { version = "0.7", default-features = false, optional = true } log = { version = "0.4", default-features = false, optional = true } diff --git a/src/mysql/writer/column.rs b/src/mysql/writer/column.rs index 7991922e..6588cbe1 100644 --- a/src/mysql/writer/column.rs +++ b/src/mysql/writer/column.rs @@ -1,7 +1,7 @@ use crate::mysql::def::{CharSet, ColumnDefault, ColumnInfo, NumericAttr, StringAttr, Type}; use sea_query::{ - Alias, BlobSize, ColumnDef, DynIden, EscapeBuilder, Expr, Iden, IntoIden, Keyword, - MysqlQueryBuilder, SimpleExpr, + extension::mysql::MySqlType, Alias, ColumnDef, DynIden, EscapeBuilder, Expr, Iden, IntoIden, + Keyword, MysqlQueryBuilder, SimpleExpr, }; use std::fmt::Write; @@ -55,9 +55,8 @@ impl ColumnInfo { .auto_increment() .unique_key(); } - Type::Bit(_) => { - // FIXME: Unresolved type mapping - col_def.custom(self.col_type.clone()); + Type::Bit(num_attr) => { + col_def.bit(num_attr.maximum); } Type::TinyInt(num_attr) => { match num_attr.unsigned { @@ -122,8 +121,7 @@ impl ColumnInfo { col_def.timestamp(); } Type::Year => { - // FIXME: Unresolved type mapping - col_def.custom(self.col_type.clone()); + col_def.year(None); } Type::Char(str_attr) => { match str_attr.length { @@ -156,14 +154,14 @@ impl ColumnInfo { Type::Binary(str_attr) => { match str_attr.length { Some(length) => col_def.binary_len(length), - _ => col_def.binary(), + None => col_def.custom(MySqlType::Blob), }; col_def = self.write_str_attr(col_def, str_attr); } Type::Varbinary(str_attr) => { match str_attr.length { Some(length) => col_def.var_binary(length), - None => col_def.binary(), + None => col_def.custom(MySqlType::Blob), }; } Type::Text(str_attr) => { @@ -185,17 +183,17 @@ impl ColumnInfo { Type::Blob(blob_attr) => { match blob_attr.length { Some(length) => col_def.binary_len(length), - None => col_def.binary(), + None => col_def.custom(MySqlType::Blob), }; } Type::TinyBlob => { - col_def.blob(BlobSize::Tiny); + col_def.custom(MySqlType::TinyBlob); } Type::MediumBlob => { - col_def.blob(BlobSize::Medium); + col_def.custom(MySqlType::MediumBlob); } Type::LongBlob => { - col_def.blob(BlobSize::Long); + col_def.custom(MySqlType::LongBlob); } Type::Enum(enum_attr) => { let name = Alias::new(&self.name); diff --git a/src/postgres/def/types.rs b/src/postgres/def/types.rs index 4d6f3791..df7d0fe3 100644 --- a/src/postgres/def/types.rs +++ b/src/postgres/def/types.rs @@ -91,6 +91,9 @@ pub enum Type { /// Fixed length bit string Bit(BitAttr), + /// Variable length bit string + VarBit(BitAttr), + // Text search types /// A sorted list of distinct lexemes which are words that have been normalized to merge different /// variants of the same word @@ -171,7 +174,7 @@ impl Type { "time" | "time without time zone" => Type::Time(TimeAttr::default()), "time with time zone" => Type::TimeWithTimeZone(TimeAttr::default()), "interval" => Type::Interval(IntervalAttr::default()), - "boolean" => Type::Boolean, + "boolean" | "bool" => Type::Boolean, "point" => Type::Point, "line" => Type::Line, "lseg" => Type::Lseg, @@ -184,6 +187,7 @@ impl Type { "macaddr" => Type::MacAddr, "macaddr8" => Type::MacAddr8, "bit" => Type::Bit(BitAttr::default()), + "bit varying" | "varbit" => Type::VarBit(BitAttr::default()), "tsvector" => Type::TsVector, "tsquery" => Type::TsQuery, "uuid" => Type::Uuid, @@ -288,7 +292,7 @@ impl Type { } pub fn has_bit_attr(&self) -> bool { - matches!(self, Type::Bit(_)) + matches!(self, Type::Bit(_) | Type::VarBit(_)) } pub fn has_enum_attr(&self) -> bool { diff --git a/src/postgres/parser/column.rs b/src/postgres/parser/column.rs index 046cf814..3358d6ef 100644 --- a/src/postgres/parser/column.rs +++ b/src/postgres/parser/column.rs @@ -176,6 +176,15 @@ pub fn parse_bit_attributes( }, }; } + Type::VarBit(ref mut attr) => { + attr.length = match character_maximum_length { + None => None, + Some(num) => match u16::try_from(num) { + Ok(num) => Some(num), + Err(_) => None, + }, + }; + } _ => panic!("parse_bit_attributes(_) received a type that does not have BitAttr"), }; diff --git a/src/postgres/writer/column.rs b/src/postgres/writer/column.rs index ee1b6d91..43072fe4 100644 --- a/src/postgres/writer/column.rs +++ b/src/postgres/writer/column.rs @@ -1,5 +1,5 @@ use crate::postgres::def::{ColumnInfo, Type}; -use sea_query::{Alias, BlobSize, ColumnDef, ColumnType, DynIden, IntoIden, PgInterval, RcOrArc}; +use sea_query::{Alias, ColumnDef, ColumnType, DynIden, IntoIden, PgInterval, RcOrArc, StringLen}; use std::{convert::TryFrom, fmt::Write}; impl ColumnInfo { @@ -72,12 +72,13 @@ impl ColumnInfo { Type::Serial => ColumnType::Integer, Type::BigSerial => ColumnType::BigInteger, Type::Money => ColumnType::Money(None), - Type::Varchar(string_attr) => { - ColumnType::String(string_attr.length.map(Into::into)) - } + Type::Varchar(string_attr) => match string_attr.length { + Some(length) => ColumnType::String(StringLen::N(length.into())), + None => ColumnType::String(StringLen::None), + }, Type::Char(string_attr) => ColumnType::Char(string_attr.length.map(Into::into)), Type::Text => ColumnType::Text, - Type::Bytea => ColumnType::Binary(BlobSize::Blob(None)), + Type::Bytea => ColumnType::VarBinary(StringLen::None), // The SQL standard requires that writing just timestamp be equivalent to timestamp without time zone, // and PostgreSQL honors that behavior. (https://www.postgresql.org/docs/current/datatype-datetime.html) Type::Timestamp(_) => ColumnType::DateTime, @@ -105,18 +106,8 @@ impl ColumnInfo { Type::Inet => ColumnType::Custom(Alias::new("inet").into_iden()), Type::MacAddr => ColumnType::Custom(Alias::new("macaddr").into_iden()), Type::MacAddr8 => ColumnType::Custom(Alias::new("macaddr8").into_iden()), - Type::Bit(bit_attr) => { - let mut str = String::new(); - write!(str, "bit").unwrap(); - if bit_attr.length.is_some() { - write!(str, "(").unwrap(); - if let Some(length) = bit_attr.length { - write!(str, "{}", length).unwrap(); - } - write!(str, ")").unwrap(); - } - ColumnType::Custom(Alias::new(&str).into_iden()) - } + Type::Bit(bit_attr) => ColumnType::Bit(bit_attr.length.map(Into::into)), + Type::VarBit(bit_attr) => ColumnType::VarBit(bit_attr.length.unwrap_or(1).into()), Type::TsVector => ColumnType::Custom(Alias::new("tsvector").into_iden()), Type::TsQuery => ColumnType::Custom(Alias::new("tsquery").into_iden()), Type::Uuid => ColumnType::Uuid, diff --git a/src/sqlite/def/column.rs b/src/sqlite/def/column.rs index da6ae80c..7b42ed47 100644 --- a/src/sqlite/def/column.rs +++ b/src/sqlite/def/column.rs @@ -1,6 +1,7 @@ -use super::{DefaultType, Type}; +use super::{parse_type, DefaultType}; use sea_query::{ - foreign_key::ForeignKeyAction as SeaQueryForeignKeyAction, Alias, Index, IndexCreateStatement, + foreign_key::ForeignKeyAction as SeaQueryForeignKeyAction, Alias, ColumnType, Index, + IndexCreateStatement, }; use std::num::ParseIntError; @@ -12,7 +13,7 @@ use crate::sqlx_types::{sqlite::SqliteRow, Row}; pub struct ColumnInfo { pub cid: i32, pub name: String, - pub r#type: Type, + pub r#type: ColumnType, pub not_null: bool, pub default_value: DefaultType, pub primary_key: bool, @@ -28,7 +29,7 @@ impl ColumnInfo { Ok(ColumnInfo { cid: row.get(0), name: row.get(1), - r#type: Type::to_type(row.get(2))?, + r#type: parse_type(row.get(2))?, not_null: col_not_null != 0, default_value: if default_value == "NULL" { DefaultType::Null diff --git a/src/sqlite/def/table.rs b/src/sqlite/def/table.rs index 1837f7a9..9ebdeacb 100644 --- a/src/sqlite/def/table.rs +++ b/src/sqlite/def/table.rs @@ -224,7 +224,8 @@ impl TableDef { new_table.table(Alias::new(&self.name)); self.columns.iter().for_each(|column_info| { - let mut new_column = ColumnDef::new(Alias::new(&column_info.name)); + let mut new_column = + ColumnDef::new_with_type(Alias::new(&column_info.name), column_info.r#type.clone()); if column_info.not_null { new_column.not_null(); } @@ -235,8 +236,6 @@ impl TableDef { primary_keys.push(column_info.name.clone()); } - column_info.r#type.write_type(&mut new_column); - match &column_info.default_value { DefaultType::Integer(integer_value) => { new_column.default(Value::Int(Some(*integer_value))); diff --git a/src/sqlite/def/types.rs b/src/sqlite/def/types.rs index 67f2e7ef..a88724c6 100644 --- a/src/sqlite/def/types.rs +++ b/src/sqlite/def/types.rs @@ -1,166 +1,62 @@ -use sea_query::ColumnDef; +use sea_query::{ColumnType, StringLen}; use std::num::ParseIntError; -/// A list of the offical SQLite types as outline at the official [SQLite Docs](https://www.sqlite.org/datatype3.html) -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum Type { - Int, - Integer, - TinyInt, - SmallInt, - MediumInt, - BigInt, - UnsignedBigInt, - Int2, - Int8, - Character { length: u8 }, - VarChar { length: u8 }, - VaryingCharacter { length: u8 }, - Nchar { length: u8 }, - NativeCharacter { length: u8 }, - NvarChar { length: u8 }, - Text, - Clob, - Blob, //No datatype specified - Real, - Double, - DoublePrecision, - Float, - Numeric, - Decimal { integral: u8, fractional: u8 }, - Boolean, - Date, - DateTime, - Timestamp, -} - -impl Type { - /// Maps a string type from an `SqliteRow` into a [Type] - pub fn to_type(data_type: &str) -> Result { - let data_type = data_type.to_uppercase(); - - let split_type: Vec<&str> = data_type.split('(').collect(); - let type_result = match split_type[0] { - "INT" => Type::Int, - "INTEGER" => Type::Integer, - "TINY INT" | "TINYINT" => Type::TinyInt, - "SMALL INT" | "SMALLINT" => Type::SmallInt, - "MEDIUM INT" | "MEDIUMINT" => Type::MediumInt, - "BIG INT" | "BIGINT" => Type::BigInt, - "UNSIGNED INT" | "UNSIGNEDBIGINT" => Type::UnsignedBigInt, - "INT2" => Type::Int2, - "INT8" => Type::Int8, - "TEXT" => Type::Text, - "CLOB" => Type::Clob, - "BLOB" => Type::Blob, - "REAL" => Type::Real, - "DOUBLE" => Type::Double, - "DOUBLE PRECISION" => Type::DoublePrecision, - "FLOAT" => Type::Float, - "NUMERIC" => Type::Numeric, - "DECIMAL" => { - let decimals = split_type[1].chars().collect::>(); - - let integral = decimals[0].to_string().parse::()?; - let fractional = decimals[2].to_string().parse::()?; - - Type::Decimal { - integral, - fractional, +pub fn parse_type(data_type: &str) -> Result { + let mut type_name = data_type; + let mut parts: Vec = Vec::new(); + if let Some((prefix, suffix)) = data_type.split_once('(') { + if let Some(suffix) = suffix.strip_suffix(')') { + type_name = prefix; + for part in suffix.split(',') { + if let Ok(part) = part.trim().parse() { + parts.push(part); + } else { + break; } } - "BOOLEAN" => Type::Boolean, - "DATE" => Type::Date, - "DATETIME" => Type::DateTime, - "TIMESTAMP" => Type::Timestamp, - _ => Type::variable_types(&split_type)?, - }; - - Ok(type_result) - } - - /// Write a [Type] to a [ColumnDef] - pub fn write_type(&self, column_def: &mut ColumnDef) { - match self { - Self::Int | Self::Integer | Self::MediumInt | Self::Int2 | Self::Int8 => { - column_def.integer(); - } - Self::TinyInt => { - column_def.tiny_integer(); - } - Self::SmallInt => { - column_def.small_integer(); - } - Self::BigInt | Self::UnsignedBigInt => { - column_def.big_integer(); - } - Self::Character { .. } - | Self::VarChar { .. } - | Self::VaryingCharacter { .. } - | Self::Nchar { .. } - | Self::NativeCharacter { .. } - | Self::NvarChar { .. } - | Self::Text - | Self::Clob => { - column_def.string(); - } - Self::Blob => { - column_def.binary(); - } - Self::Real | Self::Double | Self::DoublePrecision | Self::Float | Self::Numeric => { - column_def.double(); - } - Self::Decimal { - integral, - fractional, - } => { - column_def.decimal_len((*integral) as u32, (*fractional) as u32); - } - Self::Boolean => { - column_def.boolean(); - } - Self::Date => { - column_def.date(); - } - Self::DateTime => { - column_def.date_time(); - } - Self::Timestamp => { - column_def.timestamp(); - } } } - - #[allow(dead_code)] - fn concat_type(&self, type_name: &str, length: &u8) -> String { - let mut value = String::default(); - value.push_str(type_name); - value.push('('); - value.push_str(&length.to_string()); - value.push(')'); - - value - } - - fn variable_types(split_type: &[&str]) -> Result { - let length = if !split_type.len() == 1 { - let maybe_size = split_type[1].replace(')', ""); - maybe_size.parse::()? + Ok(match type_name.to_lowercase().as_str() { + "char" => ColumnType::Char(parts.into_iter().next()), + "varchar" => ColumnType::String(match parts.into_iter().next() { + Some(length) => StringLen::N(length), + None => StringLen::None, + }), + "text" => ColumnType::Text, + "tinyint" => ColumnType::TinyInteger, + "smallint" => ColumnType::SmallInteger, + "integer" => ColumnType::Integer, + "bigint" => ColumnType::BigInteger, + "float" => ColumnType::Float, + "double" => ColumnType::Double, + "real" => ColumnType::Decimal(if parts.len() == 2 { + Some((parts[0], parts[1])) } else { - 255_u8 - }; - - let type_result = match split_type[0] { - "VARCHAR" => Type::VarChar { length }, - "CHARACTER" => Type::Character { length }, - "VARYING CHARACTER" => Type::VaryingCharacter { length }, - "NCHAR" => Type::Nchar { length }, - "NATIVE CHARACTER" => Type::NativeCharacter { length }, - "NVARCHAR" => Type::NvarChar { length }, - _ => Type::Blob, - }; - Ok(type_result) - } + None + }), + "datetime_text" => ColumnType::DateTime, + "timestamp_text" => ColumnType::Timestamp, + "timestamp_with_timezone_text" => ColumnType::TimestampWithTimeZone, + "time_text" => ColumnType::Time, + "date_text" => ColumnType::Date, + "blob" if parts.len() == 1 => ColumnType::Binary(parts[0]), + "varbinary_blob" if parts.len() == 1 => { + ColumnType::VarBinary(match parts.into_iter().next() { + Some(length) => StringLen::N(length), + None => StringLen::None, + }) + } + "boolean" => ColumnType::Boolean, + "real_money" => ColumnType::Money(if parts.len() == 2 { + Some((parts[0], parts[1])) + } else { + None + }), + "json_text" => ColumnType::Json, + "jsonb_text" => ColumnType::JsonBinary, + "uuid_text" => ColumnType::Uuid, + _ => ColumnType::custom(data_type), + }) } /// The default types for an SQLite `dflt_value` @@ -170,6 +66,6 @@ pub enum DefaultType { Float(f32), String(String), Null, - Unspecified, //FIXME For other types + Unspecified, CurrentTimestamp, } diff --git a/tests/live/mysql/src/main.rs b/tests/live/mysql/src/main.rs index ef6beabe..86c56f95 100644 --- a/tests/live/mysql/src/main.rs +++ b/tests/live/mysql/src/main.rs @@ -32,6 +32,7 @@ async fn main() { create_lineitem_table(), create_parent_table(), create_child_table(), + create_db_types_table(), ]; for tbl_create_stmt in tbl_create_stmts.iter() { @@ -421,3 +422,23 @@ fn create_child_table() -> TableCreateStatement { .collate("utf8mb4_general_ci") .to_owned() } + +fn create_db_types_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("db_types")) + .col( + ColumnDef::new(Alias::new("id")) + .integer() + .not_null() + .auto_increment(), + ) + .col(ColumnDef::new(Alias::new("bit_1")).bit(Some(1))) + .col(ColumnDef::new(Alias::new("bit_2")).bit(Some(16))) + .col(ColumnDef::new(Alias::new("bit_3")).bit(Some(32))) + .col(ColumnDef::new(Alias::new("year")).year(None)) + .primary_key(Index::create().col(Alias::new("id"))) + .engine("InnoDB") + .character_set("utf8mb4") + .collate("utf8mb4_general_ci") + .to_owned() +} diff --git a/tests/live/postgres/src/main.rs b/tests/live/postgres/src/main.rs index 90c89ed0..60889c6e 100644 --- a/tests/live/postgres/src/main.rs +++ b/tests/live/postgres/src/main.rs @@ -54,6 +54,7 @@ async fn main() { create_collection_table(), create_parent_table(), create_child_table(), + create_db_types_table(), ]; for tbl_create_stmt in tbl_create_stmts.iter() { @@ -424,3 +425,34 @@ fn create_child_table() -> TableCreateStatement { ) .to_owned() } + +fn create_db_types_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("db_types")) + .col( + ColumnDef::new(Alias::new("id")) + .integer() + .not_null() + .auto_increment(), + ) + .col(ColumnDef::new(Alias::new("binary_1")).binary()) + .col(ColumnDef::new(Alias::new("binary_2")).binary_len(1)) + .col(ColumnDef::new(Alias::new("binary_3")).binary_len(16)) + .col(ColumnDef::new(Alias::new("var_binary_1")).var_binary(1)) + .col(ColumnDef::new(Alias::new("var_binary_2")).var_binary(16)) + .col(ColumnDef::new(Alias::new("var_binary_3")).var_binary(32)) + .col(ColumnDef::new(Alias::new("bit_1")).bit(Some(1))) + .col(ColumnDef::new(Alias::new("bit_2")).bit(Some(16))) + .col(ColumnDef::new(Alias::new("bit_3")).bit(Some(32))) + .col(ColumnDef::new(Alias::new("var_bit_1")).varbit(1)) + .col(ColumnDef::new(Alias::new("var_bit_2")).varbit(16)) + .col(ColumnDef::new(Alias::new("var_bit_3")).varbit(32)) + .col(ColumnDef::new(Alias::new("bool")).boolean()) + .primary_key( + Index::create() + .primary() + .name("db_types_pkey") + .col(Alias::new("id")), + ) + .to_owned() +} diff --git a/tests/live/sqlite/src/main.rs b/tests/live/sqlite/src/main.rs index 1743b731..70f5526a 100644 --- a/tests/live/sqlite/src/main.rs +++ b/tests/live/sqlite/src/main.rs @@ -52,7 +52,7 @@ async fn test_001() -> DiscoveryResult<()> { .table(Alias::new("Programming_Langs")) .col( ColumnDef::new(Alias::new("Name")) - .custom(Alias::new("INTEGER")) + .integer() .not_null() .auto_increment() .primary_key(), @@ -65,7 +65,7 @@ async fn test_001() -> DiscoveryResult<()> { ) .col( ColumnDef::new(Alias::new("SemVer")) - .custom(Alias::new("VARCHAR(255)")) + .string_len(255) .not_null(), ) .col( @@ -126,17 +126,13 @@ async fn test_001() -> DiscoveryResult<()> { // Tests foreign key discovery let table_create_suppliers = Table::create() .table(Alias::new("suppliers")) - .col(ColumnDef::new(Alias::new("supplier_id")).custom(Alias::new("INTEGER"))) + .col(ColumnDef::new(Alias::new("supplier_id")).integer()) .col( ColumnDef::new(Alias::new("supplier_name")) - .custom(Alias::new("TEXT")) - .not_null(), - ) - .col( - ColumnDef::new(Alias::new("group_id")) - .custom(Alias::new("INTEGER")) + .text() .not_null(), ) + .col(ColumnDef::new(Alias::new("group_id")).integer().not_null()) .primary_key(Index::create().col(Alias::new("supplier_id"))) .foreign_key( ForeignKeyCreateStatement::new() @@ -150,12 +146,8 @@ async fn test_001() -> DiscoveryResult<()> { let table_create_supplier_groups = Table::create() .table(Alias::new("supplier_groups")) - .col(ColumnDef::new(Alias::new("group_id")).custom(Alias::new("INTEGER"))) - .col( - ColumnDef::new(Alias::new("group_name")) - .custom(Alias::new("TEXT")) - .not_null(), - ) + .col(ColumnDef::new(Alias::new("group_id")).integer()) + .col(ColumnDef::new(Alias::new("group_name")).text().not_null()) .primary_key(Index::create().col(Alias::new("group_id"))) .to_owned(); @@ -215,13 +207,6 @@ async fn test_001() -> DiscoveryResult<()> { let schema = SchemaDiscovery::new(sqlite_pool.clone()).discover().await?; - let convert_column_types = |str: String| { - str.replace("INTEGER", "integer") - .replace("INT8", "integer") - .replace("TEXT", "text") - .replace("VARCHAR(255)", "text") - .replace("DATETIME", "text") - }; let expected_sql = [ create_table.to_string(SqliteQueryBuilder), create_table_inventors.to_string(SqliteQueryBuilder), @@ -229,12 +214,11 @@ async fn test_001() -> DiscoveryResult<()> { table_create_suppliers.to_string(SqliteQueryBuilder), ] .into_iter() - .map(convert_column_types) .collect::>(); assert_eq!(schema.tables.len(), expected_sql.len()); for (i, table) in schema.tables.into_iter().enumerate() { - let sql = convert_column_types(table.write().to_string(SqliteQueryBuilder)); + let sql = table.write().to_string(SqliteQueryBuilder); if sql == expected_sql[i] { println!("[OK] {sql}"); } @@ -273,6 +257,7 @@ async fn test_002() -> DiscoveryResult<()> { create_lineitem_table(), create_parent_table(), create_child_table(), + create_strange_table(), ]; for tbl_create_stmt in tbl_create_stmts.iter() { @@ -304,9 +289,9 @@ async fn test_002() -> DiscoveryResult<()> { r#""total" real,"#, r#""bakery_id" integer NOT NULL,"#, r#""customer_id" integer NOT NULL,"#, - r#""placed_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP,"#, - r#""updated" text NOT NULL DEFAULT '2023-06-07 16:24:00',"#, - r#""net_weight" real NOT NULL DEFAULT 10.05,"#, + r#""placed_at" datetime_text NOT NULL DEFAULT CURRENT_TIMESTAMP,"#, + r#""updated" datetime_text NOT NULL DEFAULT '2023-06-07 16:24:00',"#, + r#""net_weight" double NOT NULL DEFAULT 10.05,"#, r#""priority" integer NOT NULL DEFAULT 5,"#, r#"FOREIGN KEY ("customer_id") REFERENCES "customer" ("id") ON DELETE CASCADE ON UPDATE CASCADE,"#, r#"FOREIGN KEY ("bakery_id") REFERENCES "bakery" ("id") ON DELETE CASCADE ON UPDATE CASCADE"#, @@ -566,3 +551,39 @@ fn create_child_table() -> TableCreateStatement { ) .to_owned() } + +fn create_strange_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("strange")) + .col( + ColumnDef::new(Alias::new("id")) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("int1")).integer()) + .col(ColumnDef::new(Alias::new("int2")).tiny_integer()) + .col(ColumnDef::new(Alias::new("int3")).small_integer()) + .col(ColumnDef::new(Alias::new("int4")).big_integer()) + .col(ColumnDef::new(Alias::new("string1")).string()) + .col(ColumnDef::new(Alias::new("string2")).string_len(24)) + .col(ColumnDef::new(Alias::new("char1")).char()) + .col(ColumnDef::new(Alias::new("char2")).char_len(24)) + .col(ColumnDef::new(Alias::new("text_col")).text()) + .col(ColumnDef::new(Alias::new("json_col")).json()) + .col(ColumnDef::new(Alias::new("uuid_col")).uuid()) + .col(ColumnDef::new(Alias::new("decimal1")).decimal()) + .col(ColumnDef::new(Alias::new("decimal2")).decimal_len(12, 4)) + .col(ColumnDef::new(Alias::new("money1")).money()) + .col(ColumnDef::new(Alias::new("money2")).money_len(12, 4)) + .col(ColumnDef::new(Alias::new("float_col")).float()) + .col(ColumnDef::new(Alias::new("double_col")).double()) + .col(ColumnDef::new(Alias::new("date_col")).date()) + .col(ColumnDef::new(Alias::new("time_col")).time()) + .col(ColumnDef::new(Alias::new("datetime_col")).date_time()) + .col(ColumnDef::new(Alias::new("boolean_col")).boolean()) + .col(ColumnDef::new(Alias::new("binary2")).binary_len(1024)) + .col(ColumnDef::new(Alias::new("binary3")).var_binary(1024)) + .to_owned() +}