use chrono::{TimeZone, Utc};
use futures_lite::stream::StreamExt;
use oxidized_mdf::{error::Error, MdfDatabase, Value};
use pretty_assertions::assert_eq;
use rstest::rstest;
#[rstest(
file,
db_name,
case("spg_verein_TST.mdf", "spg_verein_TST"),
case("AWLT2005.mdf", "AdventureWorksLT")
)]
#[async_std::test]
async fn database_name(file: &str, db_name: &str) -> Result<(), Error> {
let db = MdfDatabase::open(format!("data/{}", file)).await?;
assert_eq!(db.database_name(), db_name);
Ok(())
}
#[rstest(
file,
table_names,
case("spg_verein_TST.mdf", vec!["___Tool_Text", "tblDOSBAbteilungen", "tblDOSBExportBE", "tblDOSBExportJAFachverbandsweise", "tblDOSBExportJAGesamt", "tblDOSBExportJASportartenweise", "tblDOSBExportJB", "tblDOSBSportarten", "tblDOSBVerein", "tblDOSBVorstand", "tblIMPORTAbrechnung", "tblIMPORTAbrechnungArt", "tblIMPORTAbrechnungDetails", "tblIMPORTAbrechnungDetailsZeilen", "tblImportEmailParameter", "tblImportMTAbteilungBeitraege", "tblImportMTAenderungen", "tblImportMTEhrungen", "tblImportMTFunktionen", "tblImportMitglied", "tblImportSTAbteilungBeitraege", "tblImportSTAbteilungen", "tblImportSTBerufsgruppen", "tblImportSTBezirke", "tblImportSTEhrungen", "tblImportSTFunktionen", "tblImportSTVerein", "tblImportSelektionen", "tblImportUmsaetze", "tblImportZahlungseingaenge", "tblImportZahlungseingaengeFibu", "tbl_Abrechnung", "tbl_AbrechnungAbgerechnet", "tbl_AbrechnungArt", "tbl_AbrechnungDatum", "tbl_AbrechnungDetails", "tbl_AbrechnungDetailsZeilen", "tbl_AbrechnungDetailsZeilenARCHIV", "tbl_AbrechnungDetails_ARCHIV", "tbl_AbrechnungSicherung", "tbl_Abrechnung_ARCHIV", "tbl_Abrechnungen_SEPA_Dateien", "tbl_Abteilung", "tbl_Abteilung_Beitrag", "tbl_Aenderungsprotokoll", "tbl_Aenderungsprotokoll_Gruende", "tbl_Aenderungsprotokoll_MitgliedLoeschung", "tbl_Ansichten", "tbl_BE_Mitglied_AKTIV_JN", "tbl_Bankleitzahlen", "tbl_Beitragsart", "tbl_Beitragserhebung_Sortierung", "tbl_Beitragserhebungen", "tbl_Beitragserhebungen_ARCHIV", "tbl_Beitragserhebungen_Details", "tbl_Beitragserhebungen_Details_ARCHIV", "tbl_Beitragserhebungen_Nacharbeiten", "tbl_Beitragserhebungen_SEPA_Dateien", "tbl_Benutzerfelder", "tbl_Berufsgruppe", "tbl_Bezirk", "tbl_Buchungsschluessel", "tbl_DOSBCodierung", "tbl_DOSBFachverbaende", "tbl_DOSBFunktionen", "tbl_DOSBMitglied_Funktion", "tbl_DOSBSportarten", "tbl_DOSBStatistiktypen", "tbl_DOSB_VE", "tbl_DOSB_VO", "tbl_DateiImport", "tbl_DateiImportRohdaten", "tbl_Dateiimport_Fehler", "tbl_Ehrung", "tbl_EmailParameter", "tbl_Exportvorlagen", "tbl_ExportvorlagenFeldnamen", "tbl_Feldnamen", "tbl_Formulare", "tbl_Formularnamen", "tbl_Funktion", "tbl_H_Abteilung", "tbl_H_Abteilung_Beitrag", "tbl_H_Beitragsart", "tbl_H_Berufsgruppe", "tbl_H_Bezirk", "tbl_H_Ehrung", "tbl_H_Funktion", "tbl_H_Mitglied", "tbl_H_Mitglied_Abteilung_Beitrag", "tbl_H_Mitglied_Ehrung", "tbl_H_Mitglied_Funktion", "tbl_H_Umsaetze", "tbl_H_Verein", "tbl_H_Zahlungseingaenge", "tbl_ID", "tbl_ImportProtokoll", "tbl_Importzuordnungen", "tbl_Laender", "tbl_Mahnungen", "tbl_Mahnungen_ARCHIV", "tbl_Mahnungen_Details", "tbl_Mahnungen_Details_ARCHIV", "tbl_MassenaenderungFeldname", "tbl_Mitglied", "tbl_Mitglied_Abteilung_Beitrag", "tbl_Mitglied_Ehrung", "tbl_Mitglied_Funktion", "tbl_Mitglieder_GES_SEL", "tbl_PLZ", "tbl_Proxy", "tbl_SEPA_Ausfuehrungen", "tbl_Selektionen", "tbl_SelektionenDetails", "tbl_SelektionenDetailsFilterungSortierung", "tbl_Statistik_Altersgruppen", "tbl_Statistik_Mitgliedschaft", "tbl_Strassenverzeichnis", "tbl_Umsaetze", "tbl_Verein", "tbl_Voreinstellungen", "tbl_Zahlarten", "tbl_Zahlungseingaenge", "tbl_Zahlweise", "tbl__datenversion", "tbl_tempStatistikDaten", "tbl_tempStatistikDatenAusgetreten", "tbl_tempStatistikZahlungsdaten", "tbl_temp_EXPORT", "tbl_temp_LL_Daten", "tbl_temp_LL_Daten_Mitglieder", "tbl_temp_LL_Daten_Rechnung", "trace_xe_action_map", "trace_xe_event_map"]),
case("AWLT2005.mdf", vec!["Address", "BuildVersion", "Customer", "CustomerAddress", "ErrorLog", "Product", "ProductCategory", "ProductDescription", "ProductModel", "ProductModelProductDescription", "SalesOrderDetail", "SalesOrderHeader"])
)]
#[async_std::test]
async fn tables(file: &str, table_names: Vec<&str>) -> Result<(), Error> {
let db = MdfDatabase::open(format!("data/{}", file)).await?;
let mut tables = db.table_names();
tables.sort();
assert_eq!(tables, table_names);
Ok(())
}
#[rstest(
file,
table_name,
column_names,
case("AWLT2005.mdf", "Address", vec!["AddressID", "AddressLine1", "AddressLine2", "City", "CountryRegion", "ModifiedDate", "PostalCode", "StateProvince", "rowguid"]),
case("spg_verein_TST.mdf", "tbl_PLZ", vec!["Ort", "PLZ", "PLZID"]),
)]
#[async_std::test]
async fn columns(file: &str, table_name: &str, column_names: Vec<&str>) -> Result<(), Error> {
let db = MdfDatabase::open(format!("data/{}", file)).await?;
let mut columns = db.column_names(table_name).unwrap();
columns.sort();
assert_eq!(columns, column_names);
Ok(())
}
#[rstest(
file,
table_name,
column,
value,
case("AWLT2005.mdf", "Address", "AddressLine1", "8713 Yosemite Ct."),
case("spg_verein_TST.mdf", "tbl_Mitglied", "Strasse", "Rebenring 56")
)]
#[async_std::test]
async fn first_row(file: &str, table_name: &str, column: &str, value: &str) -> Result<(), Error> {
let mut db = MdfDatabase::open(format!("data/{}", file)).await?;
let mut rows = db.rows(table_name).unwrap();
let first_row = rows.next().await.unwrap();
assert_eq!(
first_row.value(column),
Some(&Value::String(value.to_string()))
);
Ok(())
}
#[rstest(
file,
table_name,
count,
case("AWLT2005.mdf", "Address", 450),
case("spg_verein_TST.mdf", "tbl_Mitglied", 13),
// TODO: 3643 should be the correct number
case("spg_verein_TST.mdf", "tbl_Bankleitzahlen", 3549)
)]
#[async_std::test]
async fn number_of_rows(file: &str, table_name: &str, count: usize) -> Result<(), Error> {
let mut db = MdfDatabase::open(format!("data/{}", file)).await?;
let rows = db.rows(table_name).unwrap();
assert_eq!(rows.count().await, count);
Ok(())
}
#[rstest(
file,
table_name,
skip,
column,
expected_value,
case(
"AWLT2005.mdf",
"ProductCategory",
0,
"ParentProductCategoryID",
Value::Null
),
case(
"AWLT2005.mdf",
"ProductCategory",
4,
"ParentProductCategoryID",
Value::Int(1)
),
case(
"spg_verein_TST.mdf",
"tbl_Mitglied",
1,
"Titel",
Value::String(String::from("Dr.Dr."))
),
case("spg_verein_TST.mdf", "tbl_Mitglied", 3, "Titel", Value::Null),
case("spg_verein_TST.mdf", "tbl_Mitglied", 0, "Kontosaldo", Value::Null),
case("AWLT2005.mdf", "SalesOrderHeader", 0, "DueDate", Value::DateTime(Utc.ymd(2004, 6, 13).and_hms(0,0,0))),
case("AWLT2005.mdf", "Product", 0, "SellEndDate", Value::Null),
case("spg_verein_TST.mdf", "tbl_Mitglied", 0, "Austritt_Datum", Value::Null),
case("spg_verein_TST.mdf", "tbl_Mitglied", 7, "Eintritt_Datum", Value::DateTime(Utc.ymd(2006, 9, 10).and_hms(0,0,0))),
)]
#[async_std::test]
async fn rows(
file: &str,
table_name: &str,
skip: usize,
column: &str,
expected_value: Value,
) -> Result<(), Error> {
let mut db = MdfDatabase::open(format!("data/{}", file)).await?;
let mut rows = db.rows(table_name).unwrap().skip(skip);
let row = rows.next().await.unwrap();
assert_eq!(row.value(column), Some(&expected_value));
Ok(())
}