formular lesen (binär) und openspec für codex
This commit is contained in:
@@ -38,8 +38,11 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
let a = r.next() as i16;
|
||||
let b = r.next() as i16;
|
||||
assert_eq!(
|
||||
kodiere(&Value::Int(a), &TypeInit::Int, false)
|
||||
.cmp(&kodiere(&Value::Int(b), &TypeInit::Int, false)),
|
||||
kodiere(&Value::Int(a), &TypeInit::Int, false).cmp(&kodiere(
|
||||
&Value::Int(b),
|
||||
&TypeInit::Int,
|
||||
false
|
||||
)),
|
||||
a.cmp(&b),
|
||||
"INTEGER {a} vs {b}"
|
||||
);
|
||||
@@ -48,8 +51,11 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
let a = r.next() as i32;
|
||||
let b = r.next() as i32;
|
||||
assert_eq!(
|
||||
kodiere(&Value::Lng(a), &TypeInit::Lng, false)
|
||||
.cmp(&kodiere(&Value::Lng(b), &TypeInit::Lng, false)),
|
||||
kodiere(&Value::Lng(a), &TypeInit::Lng, false).cmp(&kodiere(
|
||||
&Value::Lng(b),
|
||||
&TypeInit::Lng,
|
||||
false
|
||||
)),
|
||||
a.cmp(&b),
|
||||
"LONG {a} vs {b}"
|
||||
);
|
||||
@@ -58,8 +64,11 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
let a = r.next() as i32 as i64;
|
||||
let b = r.next() as i32 as i64;
|
||||
assert_eq!(
|
||||
kodiere(&Value::Cur(a), &TypeInit::Cur, false)
|
||||
.cmp(&kodiere(&Value::Cur(b), &TypeInit::Cur, false)),
|
||||
kodiere(&Value::Cur(a), &TypeInit::Cur, false).cmp(&kodiere(
|
||||
&Value::Cur(b),
|
||||
&TypeInit::Cur,
|
||||
false
|
||||
)),
|
||||
a.cmp(&b),
|
||||
"CURRENCY {a} vs {b}"
|
||||
);
|
||||
@@ -68,8 +77,11 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
let a = (r.next() as i32 as f64) / 1024.0;
|
||||
let b = (r.next() as i32 as f64) / 1024.0;
|
||||
assert_eq!(
|
||||
kodiere(&Value::Dbl(a), &TypeInit::Dbl, false)
|
||||
.cmp(&kodiere(&Value::Dbl(b), &TypeInit::Dbl, false)),
|
||||
kodiere(&Value::Dbl(a), &TypeInit::Dbl, false).cmp(&kodiere(
|
||||
&Value::Dbl(b),
|
||||
&TypeInit::Dbl,
|
||||
false
|
||||
)),
|
||||
a.partial_cmp(&b).unwrap(),
|
||||
"DOUBLE {a} vs {b}"
|
||||
);
|
||||
@@ -78,8 +90,11 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
let a = (r.next() as i32 as f32) / 64.0;
|
||||
let b = (r.next() as i32 as f32) / 64.0;
|
||||
assert_eq!(
|
||||
kodiere(&Value::Sng(a), &TypeInit::Sng, false)
|
||||
.cmp(&kodiere(&Value::Sng(b), &TypeInit::Sng, false)),
|
||||
kodiere(&Value::Sng(a), &TypeInit::Sng, false).cmp(&kodiere(
|
||||
&Value::Sng(b),
|
||||
&TypeInit::Sng,
|
||||
false
|
||||
)),
|
||||
a.partial_cmp(&b).unwrap(),
|
||||
"SINGLE {a} vs {b}"
|
||||
);
|
||||
@@ -88,14 +103,19 @@ fn kodierung_erhaelt_die_ordnung_bei_zufallspaaren() {
|
||||
// Dialekts, der auf UTF-8-Bytes vergleicht (interp::CmpStr).
|
||||
let mach = |x: u32| -> String {
|
||||
let zeichen = ['a', 'b', 'z', 'A', 'Z', 'ä', 'ß', '€'];
|
||||
(0..4).map(|i| zeichen[((x >> (i * 3)) & 7) as usize]).collect()
|
||||
(0..4)
|
||||
.map(|i| zeichen[((x >> (i * 3)) & 7) as usize])
|
||||
.collect()
|
||||
};
|
||||
let sa = mach(r.next());
|
||||
let sb = mach(r.next());
|
||||
let t = TypeInit::FixedStr(4);
|
||||
assert_eq!(
|
||||
kodiere(&Value::Str(Rc::from(sa.as_str())), &t, false)
|
||||
.cmp(&kodiere(&Value::Str(Rc::from(sb.as_str())), &t, false)),
|
||||
kodiere(&Value::Str(Rc::from(sa.as_str())), &t, false).cmp(&kodiere(
|
||||
&Value::Str(Rc::from(sb.as_str())),
|
||||
&t,
|
||||
false
|
||||
)),
|
||||
sa.as_bytes().cmp(sb.as_bytes()),
|
||||
"TEXT {sa:?} vs {sb:?}"
|
||||
);
|
||||
@@ -181,7 +201,10 @@ impl Drop for TempDb {
|
||||
}
|
||||
|
||||
fn isam_mit_tabelle(db: &str) -> Isam {
|
||||
let mut i = Isam { udts: test_udts(), ..Default::default() };
|
||||
let mut i = Isam {
|
||||
udts: test_udts(),
|
||||
..Default::default()
|
||||
};
|
||||
i.oeffnen(1, db, "Kunden", "Nummer,Name", 0).unwrap();
|
||||
i
|
||||
}
|
||||
@@ -203,9 +226,15 @@ fn hoehere_formatversion_wird_abgewiesen() {
|
||||
meta_schreiben(&txn, "version", &(FORMATVERSION + 1).to_le_bytes()).unwrap();
|
||||
txn.commit().unwrap();
|
||||
}
|
||||
let mut i = Isam { udts: test_udts(), ..Default::default() };
|
||||
let mut i = Isam {
|
||||
udts: test_udts(),
|
||||
..Default::default()
|
||||
};
|
||||
let e = i.oeffnen(1, &pfad, "Kunden", "Nummer,Name", 0).unwrap_err();
|
||||
assert_eq!(e, INKONSISTENT, "höhere Formatversion muss benannt scheitern");
|
||||
assert_eq!(
|
||||
e, INKONSISTENT,
|
||||
"höhere Formatversion muss benannt scheitern"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -213,7 +242,10 @@ fn beschaedigte_datei_meldet_fehler_88() {
|
||||
let t = TempDb::neu("kaputt");
|
||||
let pfad = t.pfad("kaputt.isam");
|
||||
std::fs::write(&pfad, b"das ist keine Datenbankdatei").unwrap();
|
||||
let mut i = Isam { udts: test_udts(), ..Default::default() };
|
||||
let mut i = Isam {
|
||||
udts: test_udts(),
|
||||
..Default::default()
|
||||
};
|
||||
let e = i.oeffnen(1, &pfad, "Kunden", "Nummer,Name", 0).unwrap_err();
|
||||
assert_eq!(e, RuntimeError(88));
|
||||
}
|
||||
@@ -229,7 +261,10 @@ fn geloeschte_satz_id_wird_nicht_neu_vergeben() {
|
||||
i.satz_loeschen(1).unwrap();
|
||||
i.einfuegen(1, &satz(2, "zwei")).unwrap();
|
||||
let zweite = i.satznummer(1).unwrap();
|
||||
assert_ne!(erste, zweite, "eine gelöschte ID darf nicht neu vergeben werden");
|
||||
assert_ne!(
|
||||
erste, zweite,
|
||||
"eine gelöschte ID darf nicht neu vergeben werden"
|
||||
);
|
||||
assert!(zweite > erste);
|
||||
}
|
||||
|
||||
@@ -249,8 +284,12 @@ fn satz_roundtrip_ueber_alle_feldtypen() {
|
||||
TypeInit::FixedStr(5),
|
||||
],
|
||||
}];
|
||||
let mut i = Isam { udts, ..Default::default() };
|
||||
i.oeffnen(1, &t.pfad("db.isam"), "Alles", "A,B,C,D,E,F", 0).unwrap();
|
||||
let mut i = Isam {
|
||||
udts,
|
||||
..Default::default()
|
||||
};
|
||||
i.oeffnen(1, &t.pfad("db.isam"), "Alles", "A,B,C,D,E,F", 0)
|
||||
.unwrap();
|
||||
let original = Value::Rec(Rc::new(RefCell::new(RecordObj {
|
||||
fields: vec![
|
||||
Value::Int(-7),
|
||||
@@ -262,7 +301,9 @@ fn satz_roundtrip_ueber_alle_feldtypen() {
|
||||
],
|
||||
})));
|
||||
i.einfuegen(1, &original).unwrap();
|
||||
let Value::Rec(gelesen) = i.satz_lesen(1).unwrap() else { panic!("kein Record") };
|
||||
let Value::Rec(gelesen) = i.satz_lesen(1).unwrap() else {
|
||||
panic!("kein Record")
|
||||
};
|
||||
let f = &gelesen.borrow().fields;
|
||||
assert!(matches!(f[0], Value::Int(-7)));
|
||||
assert!(matches!(f[1], Value::Lng(123456)));
|
||||
@@ -279,7 +320,8 @@ fn satz_roundtrip_ueber_alle_feldtypen() {
|
||||
fn indexeintraege_stehen_in_schluesselreihenfolge() {
|
||||
let t = TempDb::neu("indexordnung");
|
||||
let mut i = isam_mit_tabelle(&t.pfad("db.isam"));
|
||||
i.index_anlegen(1, "NachName", false, &["Name".into()]).unwrap();
|
||||
i.index_anlegen(1, "NachName", false, &["Name".into()])
|
||||
.unwrap();
|
||||
for (n, name) in [(3, "Cäsar"), (1, "Anton"), (2, "Berta")] {
|
||||
i.einfuegen(1, &satz(n, name)).unwrap();
|
||||
}
|
||||
@@ -287,8 +329,12 @@ fn indexeintraege_stehen_in_schluesselreihenfolge() {
|
||||
let mut namen = Vec::new();
|
||||
i.bewegen(1, Richtung::Erster).unwrap();
|
||||
while !i.eof(1) {
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else { panic!() };
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else { panic!() };
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else {
|
||||
panic!()
|
||||
};
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else {
|
||||
panic!()
|
||||
};
|
||||
namen.push(s.trim_end().to_string());
|
||||
i.bewegen(1, Richtung::Naechster).unwrap();
|
||||
}
|
||||
@@ -303,7 +349,8 @@ fn indexeintraege_stehen_in_schluesselreihenfolge() {
|
||||
fn cursor_ueberlebt_eine_satzaenderung() {
|
||||
let t = TempDb::neu("cursor");
|
||||
let mut i = isam_mit_tabelle(&t.pfad("db.isam"));
|
||||
i.index_anlegen(1, "NachName", false, &["Name".into()]).unwrap();
|
||||
i.index_anlegen(1, "NachName", false, &["Name".into()])
|
||||
.unwrap();
|
||||
for (n, name) in [(1, "Anton"), (2, "Berta"), (3, "Cäsar")] {
|
||||
i.einfuegen(1, &satz(n, name)).unwrap();
|
||||
}
|
||||
@@ -313,18 +360,31 @@ fn cursor_ueberlebt_eine_satzaenderung() {
|
||||
let vorher = i.satznummer(1).unwrap();
|
||||
|
||||
// Über eine zweite Bindung einen anderen Satz einfügen.
|
||||
i.oeffnen(2, &t.pfad("db.isam"), "Kunden", "Nummer,Name", 0).unwrap();
|
||||
i.oeffnen(2, &t.pfad("db.isam"), "Kunden", "Nummer,Name", 0)
|
||||
.unwrap();
|
||||
i.einfuegen(2, &satz(4, "Anna")).unwrap();
|
||||
|
||||
assert_eq!(i.satznummer(1).unwrap(), vorher, "Cursor darf nicht wandern");
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else { panic!() };
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else { panic!() };
|
||||
assert_eq!(
|
||||
i.satznummer(1).unwrap(),
|
||||
vorher,
|
||||
"Cursor darf nicht wandern"
|
||||
);
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else {
|
||||
panic!()
|
||||
};
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else {
|
||||
panic!()
|
||||
};
|
||||
assert_eq!(s.trim_end(), "Berta");
|
||||
|
||||
// Und er bewegt sich weiter in der neuen Ordnung.
|
||||
i.bewegen(1, Richtung::Naechster).unwrap();
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else { panic!() };
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else { panic!() };
|
||||
let Value::Rec(r) = i.satz_lesen(1).unwrap() else {
|
||||
panic!()
|
||||
};
|
||||
let Value::Str(s) = r.borrow().fields[1].clone() else {
|
||||
panic!()
|
||||
};
|
||||
assert_eq!(s.trim_end(), "Cäsar");
|
||||
}
|
||||
|
||||
@@ -383,12 +443,16 @@ fn ungueltige_namen_werden_abgewiesen() {
|
||||
fn close_beendet_keine_transaktion() {
|
||||
let t = TempDb::neu("close_trans");
|
||||
let mut i = isam_mit_tabelle(&t.pfad("db.isam"));
|
||||
i.oeffnen(2, &t.pfad("db.isam"), "Kunden", "Nummer,Name", 0).unwrap();
|
||||
i.oeffnen(2, &t.pfad("db.isam"), "Kunden", "Nummer,Name", 0)
|
||||
.unwrap();
|
||||
i.trans_beginn().unwrap();
|
||||
i.einfuegen(1, &satz(1, "eins")).unwrap();
|
||||
|
||||
i.schliessen(2).unwrap();
|
||||
assert!(i.trans.is_some(), "CLOSE darf die Transaktion nicht beenden");
|
||||
assert!(
|
||||
i.trans.is_some(),
|
||||
"CLOSE darf die Transaktion nicht beenden"
|
||||
);
|
||||
|
||||
// Die Rücknahme wirkt danach noch auf die Änderung an #1.
|
||||
i.ruecknahme(ROLLBACK_ALL).unwrap();
|
||||
@@ -407,7 +471,10 @@ fn nicht_festgeschriebene_transaktion_verfaellt() {
|
||||
i.einfuegen(1, &satz(1, "eins")).unwrap();
|
||||
i.alles_schliessen();
|
||||
}
|
||||
let mut i = Isam { udts: test_udts(), ..Default::default() };
|
||||
let mut i = Isam {
|
||||
udts: test_udts(),
|
||||
..Default::default()
|
||||
};
|
||||
i.oeffnen(1, &pfad, "Kunden", "Nummer,Name", 0).unwrap();
|
||||
assert_eq!(
|
||||
i.satzzahl(1).unwrap(),
|
||||
@@ -427,7 +494,9 @@ fn gescheitertes_createindex_hinterlaesst_keinen_index() {
|
||||
i.einfuegen(1, &satz(2, "gleich")).unwrap();
|
||||
|
||||
i.trans_beginn().unwrap();
|
||||
let e = i.index_anlegen(1, "Eindeutig", true, &["Name".into()]).unwrap_err();
|
||||
let e = i
|
||||
.index_anlegen(1, "Eindeutig", true, &["Name".into()])
|
||||
.unwrap_err();
|
||||
assert_eq!(e, DOPPELTER_SCHLUESSEL);
|
||||
i.trans_festschreiben().unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user