diff --git a/frameworks/rust/mysql_async/Dockerfile b/frameworks/rust/mysql_async/Dockerfile index 6ffaf3b5..13dae30b 100644 --- a/frameworks/rust/mysql_async/Dockerfile +++ b/frameworks/rust/mysql_async/Dockerfile @@ -5,8 +5,7 @@ WORKDIR /src # Cache a layer with all the dependencies built RUN mkdir src && echo 'fn main() {}' > src/main.rs && cargo build && rm -Rvf src ADD src/src /src/src -RUN cargo build -ENTRYPOINT ["/src/target/debug/mysql-test"] +RUN touch src/main.rs && cargo build FROM fedora:32 COPY --from=builder /src/target/debug/mysql-test / diff --git a/frameworks/rust/mysql_async/src/Cargo.toml b/frameworks/rust/mysql_async/src/Cargo.toml index e825991e..0c949b55 100644 --- a/frameworks/rust/mysql_async/src/Cargo.toml +++ b/frameworks/rust/mysql_async/src/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Mike Cronce "] edition = "2018" [dependencies] -mysql_async = "0.24" +mysql_async = "0.27" tablefy = "0.1" tablefy_derive = "0.2" -tokio = "0.2" +tokio = {version = "1", features = ["macros", "rt-multi-thread"]} prettytable-rs = "0.8" diff --git a/frameworks/rust/mysql_async/src/src/main.rs b/frameworks/rust/mysql_async/src/src/main.rs index e6e9058f..cb556669 100644 --- a/frameworks/rust/mysql_async/src/src/main.rs +++ b/frameworks/rust/mysql_async/src/src/main.rs @@ -17,6 +17,73 @@ struct Payment { account_name: Option } +#[derive(Clone, Debug, PartialEq, Eq, Tablefy)] +struct ColumnInfo { + column_name: String, + data_type: String, + full_data_type: String, + character_maximum_length: Option, + numeric_precision: Option, + numeric_scale: Option, + datetime_precision: Option, + column_default: Option, + is_nullable: String, + extra: String, + table_name: String +} + +impl FromRow for ColumnInfo { + fn from_row_opt(row: Row) -> core::result::Result { + Ok(Self::new( + row.get(0).unwrap(), + row.get(1).unwrap(), + row.get(2).unwrap(), + row.get(3).unwrap(), + row.get(4).unwrap(), + row.get(5).unwrap(), + row.get(6).unwrap(), + row.get(7).unwrap(), + row.get(8).unwrap(), + row.get(9).unwrap(), + row.get(10).unwrap() + )) + } +} + +impl ColumnInfo { + fn new(column_name: String, data_type: String, full_data_type: String, character_maximum_length: Option, numeric_precision: Option, numeric_scale: Option, datetime_precision: Option, column_default: Option, is_nullable: String, extra: String, table_name: String) -> Self { + Self{ + column_name, + data_type, + full_data_type, + character_maximum_length, + numeric_precision, + numeric_scale, + datetime_precision, + column_default, + is_nullable, + extra, + table_name + } + } + + fn new2(column_name: &str, data_type: &str, full_data_type: &str, character_maximum_length: Option, numeric_precision: Option, numeric_scale: Option, datetime_precision: Option, column_default: Option<&str>, is_nullable: &str, extra: &str, table_name: &str) -> Self { + Self::new( + column_name.to_string(), + data_type.to_string(), + full_data_type.to_string(), + character_maximum_length, + numeric_precision, + numeric_scale, + datetime_precision, + column_default.map(|s| s.to_string()), + is_nullable.to_string(), + extra.to_string(), + table_name.to_string() + ) + } +} + #[tokio::main] async fn main() { let host = std::env::var("VT_HOST").unwrap(); @@ -153,6 +220,76 @@ async fn main() { Err(e) => println!("Error (as expected):\n\t{}\n\n", e) }; + let query = r" + CREATE TABLE `a` ( + `one` int NOT NULL, + `two` int NOT NULL, + PRIMARY KEY (`one`,`two`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 + "; + println!("--- query:{}", query); + conn.query_drop(query).await.expect("CREATE TABLE `s` failed"); + + let query = r" + SELECT + column_name column_name, + data_type data_type, + column_type full_data_type, + character_maximum_length character_maximum_length, + numeric_precision numeric_precision, + numeric_scale numeric_scale, + datetime_precision datetime_precision, + column_default column_default, + is_nullable is_nullable, + extra extra, + table_name table_name + FROM information_schema.columns + WHERE table_schema = '".to_owned() + &std::env::var("VT_DATABASE").unwrap() + r"' + ORDER BY ordinal_position + "; + println!("--- query:{}", query); + let rows: Vec = conn.query(query).await.expect("SELECT from information_schema.columns failed"); + assert_eq!(rows.len(), 2); + // MySQL 5.7 returns "int(11)" for column_type; 8.0 only returns "int" + assert!( + rows[0] == ColumnInfo::new2("one", "int", "int(11)", None, Some(10), Some(0), None, None, "NO", "", "a") || + rows[0] == ColumnInfo::new2("one", "int", "int", None, Some(10), Some(0), None, None, "NO", "", "a") + ); + assert!( + rows[1] == ColumnInfo::new2("two", "int", "int(11)", None, Some(10), Some(0), None, None, "NO", "", "a") || + rows[1] == ColumnInfo::new2("two", "int", "int", None, Some(10), Some(0), None, None, "NO", "", "a") + ); + + let query = r" + SELECT + column_name column_name, + data_type data_type, + column_type full_data_type, + character_maximum_length character_maximum_length, + numeric_precision numeric_precision, + numeric_scale numeric_scale, + datetime_precision datetime_precision, + column_default column_default, + is_nullable is_nullable, + extra extra, + table_name table_name + FROM information_schema.columns + WHERE table_schema = ? + ORDER BY ordinal_position + "; + println!("--- query:{}", query); + let stmt = conn.prep(query).await.expect("prepare SELECT from information_schema.columns failed"); + let rows: Vec = conn.exec(stmt, (std::env::var("VT_DATABASE").unwrap(),)).await.expect("exec prepared SELECT from information_schema.columns failed"); + assert_eq!(rows.len(), 2); + assert!( + rows[0] == ColumnInfo::new2("one", "int", "int(11)", None, Some(10), Some(0), None, None, "NO", "", "a") || + rows[0] == ColumnInfo::new2("one", "int", "int", None, Some(10), Some(0), None, None, "NO", "", "a") + ); + assert!( + rows[1] == ColumnInfo::new2("two", "int", "int(11)", None, Some(10), Some(0), None, None, "NO", "", "a") || + rows[1] == ColumnInfo::new2("two", "int", "int", None, Some(10), Some(0), None, None, "NO", "", "a") + ); + let query = r" CREATE TABLE `ScalarModel` ( `id` VARCHAR(191) NOT NULL,