use zero_mysql::error::Result;
use zero_mysql::protocol::BinaryRowPayload;
use zero_mysql::protocol::command::ColumnDefinition;
use zero_mysql::protocol::response::OkPayloadBytes;
use zero_mysql::protocol::r#trait::BinaryResultSetHandler;
use zero_mysql::raw::parse_value;
use zero_mysql::value::Value;
include!("common/check_eq.rs");
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DatetimeType {
Datetime0,
Datetime4,
Datetime7,
Datetime11,
Other,
}
struct DatetimeTypeCollector {
types: Vec<DatetimeType>,
}
impl DatetimeTypeCollector {
fn new() -> Self {
Self { types: Vec::new() }
}
}
impl BinaryResultSetHandler for DatetimeTypeCollector {
fn no_result_set(&mut self, _ok: OkPayloadBytes) -> Result<()> {
Ok(())
}
fn resultset_start(&mut self, _cols: &[ColumnDefinition<'_>]) -> Result<()> {
Ok(())
}
fn row(&mut self, cols: &[ColumnDefinition<'_>], row: BinaryRowPayload<'_>) -> Result<()> {
let [col0, col1, ..] = cols else {
return Err(zero_mysql::error::Error::LibraryBug(
zero_mysql::error::eyre!("expected at least 2 columns, got {}", cols.len()),
));
};
let null_bitmap = row.null_bitmap();
let data = row.values();
let (_id, rest): (i32, _) = parse_value(col0.tail, null_bitmap.is_null(0), data)?;
let (value, _): (Value<'_>, _) = parse_value(col1.tail, null_bitmap.is_null(1), rest)?;
let dt_type = match value {
Value::Datetime0 => DatetimeType::Datetime0,
Value::Datetime4(_) => DatetimeType::Datetime4,
Value::Datetime7(_) => DatetimeType::Datetime7,
Value::Datetime11(_) => DatetimeType::Datetime11,
_ => DatetimeType::Other,
};
self.types.push(dt_type);
Ok(())
}
fn resultset_end(&mut self, _eof: OkPayloadBytes) -> Result<()> {
Ok(())
}
}
#[test]
fn datetime6_with_different_inputs() -> Result<()> {
let mut conn = zero_mysql::sync::Conn::new("mysql://test:1234@localhost:3306/test")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_datetime6 (
id INT AUTO_INCREMENT PRIMARY KEY,
dt DATETIME(6)
)",
)?;
conn.query_drop("SET SESSION sql_mode = ''")?;
conn.query_drop("INSERT INTO test_datetime6 (dt) VALUES ('0000-00-00 00:00:00')")?;
conn.query_drop("INSERT INTO test_datetime6 (dt) VALUES ('2024-01-15')")?;
conn.query_drop("INSERT INTO test_datetime6 (dt) VALUES ('2024-01-15 12:30:45')")?;
conn.query_drop("INSERT INTO test_datetime6 (dt) VALUES ('2024-01-15 12:30:45.123456')")?;
let mut stmt = conn.prepare("SELECT id, dt FROM test_datetime6 ORDER BY id")?;
let mut handler = DatetimeTypeCollector::new();
conn.exec(&mut stmt, (), &mut handler)?;
check_eq!(handler.types.len(), 4);
eprintln!(
"Row 1 (zero input '0000-00-00 00:00:00'): {:?}",
handler.types[0]
);
check_eq!(
handler.types[0],
DatetimeType::Datetime0,
"zero input returns Datetime0"
);
eprintln!("Row 2 (ymd input '2024-01-15'): {:?}", handler.types[1]);
check_eq!(
handler.types[1],
DatetimeType::Datetime4,
"ymd input returns Datetime4"
);
eprintln!(
"Row 3 (ymd-hms input '2024-01-15 12:30:45'): {:?}",
handler.types[2]
);
check_eq!(
handler.types[2],
DatetimeType::Datetime7,
"ymd-hms input returns Datetime7"
);
eprintln!(
"Row 4 (ymd-hms-micro input '2024-01-15 12:30:45.123456'): {:?}",
handler.types[3]
);
check_eq!(
handler.types[3],
DatetimeType::Datetime11,
"ymd-hms-micro input returns Datetime11"
);
Ok(())
}
#[test]
fn datetime6_binary_protocol_insert() -> Result<()> {
let mut conn = zero_mysql::sync::Conn::new("mysql://test:1234@localhost:3306/test")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_datetime6_binary (
id INT AUTO_INCREMENT PRIMARY KEY,
dt DATETIME(6)
)",
)?;
conn.query_drop("SET SESSION sql_mode = ''")?;
let mut insert_stmt = conn.prepare("INSERT INTO test_datetime6_binary (dt) VALUES (?)")?;
conn.exec_drop(&mut insert_stmt, ("0000-00-00 00:00:00",))?;
conn.exec_drop(&mut insert_stmt, ("2024-01-15",))?;
conn.exec_drop(&mut insert_stmt, ("2024-01-15 12:30:45",))?;
conn.exec_drop(&mut insert_stmt, ("2024-01-15 12:30:45.123456",))?;
let mut select_stmt = conn.prepare("SELECT id, dt FROM test_datetime6_binary ORDER BY id")?;
let mut handler = DatetimeTypeCollector::new();
conn.exec(&mut select_stmt, (), &mut handler)?;
check_eq!(handler.types.len(), 4);
eprintln!(
"Binary Row 1 (zero input '0000-00-00 00:00:00'): {:?}",
handler.types[0]
);
check_eq!(
handler.types[0],
DatetimeType::Datetime0,
"zero input returns Datetime0"
);
eprintln!(
"Binary Row 2 (ymd input '2024-01-15'): {:?}",
handler.types[1]
);
check_eq!(
handler.types[1],
DatetimeType::Datetime4,
"ymd input returns Datetime4"
);
eprintln!(
"Binary Row 3 (ymd-hms input '2024-01-15 12:30:45'): {:?}",
handler.types[2]
);
check_eq!(
handler.types[2],
DatetimeType::Datetime7,
"ymd-hms input returns Datetime7"
);
eprintln!(
"Binary Row 4 (ymd-hms-micro input '2024-01-15 12:30:45.123456'): {:?}",
handler.types[3]
);
check_eq!(
handler.types[3],
DatetimeType::Datetime11,
"ymd-hms-micro input returns Datetime11"
);
Ok(())
}