use serde::Serialize;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
pub enum InnoDbVendor {
MySQL,
Percona,
MariaDB,
}
impl fmt::Display for InnoDbVendor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InnoDbVendor::MySQL => write!(f, "MySQL"),
InnoDbVendor::Percona => write!(f, "Percona XtraDB"),
InnoDbVendor::MariaDB => write!(f, "MariaDB"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
pub enum MariaDbFormat {
Original,
FullCrc32,
}
impl fmt::Display for MariaDbFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MariaDbFormat::Original => write!(f, "original"),
MariaDbFormat::FullCrc32 => write!(f, "full_crc32"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct VendorInfo {
pub vendor: InnoDbVendor,
#[serde(skip_serializing_if = "Option::is_none")]
pub mariadb_format: Option<MariaDbFormat>,
}
impl VendorInfo {
pub fn mysql() -> Self {
VendorInfo {
vendor: InnoDbVendor::MySQL,
mariadb_format: None,
}
}
pub fn percona() -> Self {
VendorInfo {
vendor: InnoDbVendor::Percona,
mariadb_format: None,
}
}
pub fn mariadb(format: MariaDbFormat) -> Self {
VendorInfo {
vendor: InnoDbVendor::MariaDB,
mariadb_format: Some(format),
}
}
pub fn is_full_crc32(&self) -> bool {
self.mariadb_format == Some(MariaDbFormat::FullCrc32)
}
}
impl fmt::Display for VendorInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.mariadb_format {
Some(format) => write!(f, "{} ({})", self.vendor, format),
None => write!(f, "{}", self.vendor),
}
}
}
pub fn detect_vendor_from_flags(fsp_flags: u32) -> VendorInfo {
use crate::innodb::constants::*;
if fsp_flags & MARIADB_FSP_FLAGS_FCRC32_MARKER_MASK != 0 {
return VendorInfo::mariadb(MariaDbFormat::FullCrc32);
}
if fsp_flags & MARIADB_FSP_FLAGS_PAGE_COMPRESSION != 0 {
let mysql_comp_bits = (fsp_flags >> 11) & 0x03;
if mysql_comp_bits == 0 {
return VendorInfo::mariadb(MariaDbFormat::Original);
}
}
VendorInfo::mysql()
}
pub fn detect_vendor_from_created_by(created_by: &str) -> InnoDbVendor {
let lower = created_by.to_lowercase();
if lower.contains("mariadb") {
InnoDbVendor::MariaDB
} else if lower.contains("percona") {
InnoDbVendor::Percona
} else {
InnoDbVendor::MySQL
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_flags_are_mysql() {
let info = detect_vendor_from_flags(0);
assert_eq!(info.vendor, InnoDbVendor::MySQL);
assert_eq!(info.mariadb_format, None);
}
#[test]
fn test_mysql_flags_with_page_size() {
let flags = 5 << 6;
let info = detect_vendor_from_flags(flags);
assert_eq!(info.vendor, InnoDbVendor::MySQL);
}
#[test]
fn test_mysql_flags_with_compression() {
let flags = 1 << 11;
let info = detect_vendor_from_flags(flags);
assert_eq!(info.vendor, InnoDbVendor::MySQL);
}
#[test]
fn test_mariadb_full_crc32_detected() {
let flags = 0x10;
let info = detect_vendor_from_flags(flags);
assert_eq!(info.vendor, InnoDbVendor::MariaDB);
assert_eq!(info.mariadb_format, Some(MariaDbFormat::FullCrc32));
assert!(info.is_full_crc32());
}
#[test]
fn test_mariadb_full_crc32_with_page_size() {
let flags = 0x10 | 5;
let info = detect_vendor_from_flags(flags);
assert_eq!(info.vendor, InnoDbVendor::MariaDB);
assert_eq!(info.mariadb_format, Some(MariaDbFormat::FullCrc32));
}
#[test]
fn test_mariadb_original_page_compression() {
let flags = 1 << 16;
let info = detect_vendor_from_flags(flags);
assert_eq!(info.vendor, InnoDbVendor::MariaDB);
assert_eq!(info.mariadb_format, Some(MariaDbFormat::Original));
}
#[test]
fn test_vendor_from_created_by_mysql() {
assert_eq!(
detect_vendor_from_created_by("MySQL 8.0.32"),
InnoDbVendor::MySQL
);
}
#[test]
fn test_vendor_from_created_by_mariadb() {
assert_eq!(
detect_vendor_from_created_by("MariaDB 10.11.4"),
InnoDbVendor::MariaDB
);
}
#[test]
fn test_vendor_from_created_by_percona() {
assert_eq!(
detect_vendor_from_created_by("Percona Server 8.0.32-24"),
InnoDbVendor::Percona
);
}
#[test]
fn test_vendor_from_empty_string() {
assert_eq!(detect_vendor_from_created_by(""), InnoDbVendor::MySQL);
}
#[test]
fn test_vendor_info_display() {
assert_eq!(format!("{}", VendorInfo::mysql()), "MySQL");
assert_eq!(format!("{}", VendorInfo::percona()), "Percona XtraDB");
assert_eq!(
format!("{}", VendorInfo::mariadb(MariaDbFormat::FullCrc32)),
"MariaDB (full_crc32)"
);
assert_eq!(
format!("{}", VendorInfo::mariadb(MariaDbFormat::Original)),
"MariaDB (original)"
);
}
}