use futures_util::io::{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::DateTime;
#[cfg(all(feature = "tds73", feature = "chrono"))]
use chrono::NaiveDateTime;
use runtimes_macro::test_on_runtimes;
#[allow(dead_code)]
static LOGGER_SETUP: Once = Once::new();
static CONN_STR: Lazy<String> = 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<Option<Generator<'static>>> =
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 >]<S>(mut conn: tiberius::Client<S>) -> 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 >]<S>(mut conn: tiberius::Client<S>) -> 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!(empty_varchar(
"VARCHAR(MAX)",
100,
vec![""; 100].into_iter()
));
test_bulk_type!(empty_nvarchar(
"NVARCHAR(MAX)",
100,
vec![""; 100].into_iter()
));
test_bulk_type!(empty_varbinary(
"VARBINARY(MAX)",
100,
vec![b""; 100].into_iter()
));
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![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_naive("DATETIME2", 100, {
#[allow(deprecated)]
let dt = NaiveDateTime::from_timestamp_opt(1658524194, 123456789).unwrap();
vec![dt; 100].into_iter()
}));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_0(
"DATETIME2(0)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_1(
"DATETIME2(1)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_2(
"DATETIME2(2)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_3(
"DATETIME2(3)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_4(
"DATETIME2(4)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_5(
"DATETIME2(5)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_6(
"DATETIME2(6)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));
#[cfg(all(feature = "tds73", feature = "chrono"))]
test_bulk_type!(datetime2_7(
"DATETIME2(7)",
100,
vec![DateTime::from_timestamp(1658524194, 123456789); 100].into_iter()
));