use futures::{AsyncRead, AsyncWrite}; use names::{Generator, Name}; use once_cell::sync::Lazy; use std::cell::RefCell; use std::env; use std::sync::Once; use tiberius::{IntoSql, Result, TokenRow}; #[cfg(all(feature = "tds73", feature = "chrono"))] use chrono::NaiveDateTime; use runtimes_macro::test_on_runtimes; // This is used in the testing macro :) #[allow(dead_code)] static LOGGER_SETUP: Once = Once::new(); static CONN_STR: Lazy = Lazy::new(|| { env::var("TIBERIUS_TEST_CONNECTION_STRING").unwrap_or_else(|_| { "server=tcp:localhost,1433;IntegratedSecurity=true;TrustServerCertificate=true".to_owned() }) }); thread_local! { static NAMES: RefCell>> = RefCell::new(None); } async fn random_table() -> String { NAMES.with(|maybe_generator| { maybe_generator .borrow_mut() .get_or_insert_with(|| Generator::with_naming(Name::Plain)) .next() .unwrap() .replace('-', "") }) } macro_rules! test_bulk_type { ($name:ident($sql_type:literal, $total_generated:expr, $generator:expr)) => { paste::item! { #[test_on_runtimes] async fn [< bulk_load_optional_ $name >](mut conn: tiberius::Client) -> Result<()> where S: AsyncRead + AsyncWrite + Unpin + Send, { let table = format!("##{}", random_table().await); conn.execute( &format!( "CREATE TABLE {} (id INT IDENTITY PRIMARY KEY, content {} NULL)", table, $sql_type, ), &[], ) .await?; let mut req = conn.bulk_insert(&table).await?; for i in $generator { let mut row = TokenRow::new(); row.push(i.into_sql()); req.send(row).await?; } let res = req.finalize().await?; assert_eq!($total_generated, res.total()); Ok(()) } #[test_on_runtimes] async fn [< bulk_load_required_ $name >](mut conn: tiberius::Client) -> Result<()> where S: AsyncRead + AsyncWrite + Unpin + Send, { let table = format!("##{}", random_table().await); conn.execute( &format!( "CREATE TABLE {} (id INT IDENTITY PRIMARY KEY, content {} NOT NULL)", table, $sql_type ), &[], ) .await?; let mut req = conn.bulk_insert(&table).await?; for i in $generator { let mut row = TokenRow::new(); row.push(i.into_sql()); req.send(row).await?; } let res = req.finalize().await?; assert_eq!($total_generated, res.total()); Ok(()) } } }; } test_bulk_type!(tinyint("TINYINT", 256, 0..=255u8)); test_bulk_type!(smallint("SMALLINT", 2000, 0..2000i16)); test_bulk_type!(int("INT", 2000, 0..2000i32)); test_bulk_type!(bigint("BIGINT", 2000, 0..2000i64)); test_bulk_type!(real( "REAL", 1000, vec![std::f32::consts::PI; 1000].into_iter() )); test_bulk_type!(float( "FLOAT", 1000, vec![std::f64::consts::PI; 1000].into_iter() )); test_bulk_type!(varchar_limited( "VARCHAR(255)", 1000, vec!["aaaaaaaaaaaaaaaaaaaaaaa"; 1000].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2( "DATETIME2", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_0( "DATETIME2(0)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_1( "DATETIME2(1)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_2( "DATETIME2(2)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_3( "DATETIME2(3)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_4( "DATETIME2(4)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_5( "DATETIME2(5)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_6( "DATETIME2(6)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() )); #[cfg(all(feature = "tds73", feature = "chrono"))] test_bulk_type!(datetime2_7( "DATETIME2(7)", 100, vec![NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap(); 100].into_iter() ));