dcd9bcb1ce
* Pre: Drop unneeded tx0 from search results. * Pre: Don't require a schema in some of the DB code. The idea is to separate the transaction applying code, which is schema-aware, from the concrete storage code, which is just concerned with getting bits onto disk. * Pre: Only reference Schema, not DB, in debug module. This is part of a larger separation of the volatile PartitionMap, which is modified every transaction, from the stable Schema, which is infrequently modified. * Pre: Fix indentation. * Extract part of DB to new SchemaTypeChecking trait. * Extract part of DB to new PartitionMapping trait. * Pre: Don't expect :db.part/tx partition to advance when tx fails. This fails right now, because we allocate tx IDs even when we shouldn't. * Sketch a db interface without DB. * Add ValueParseError; use error-chain in tx-parser. This can be simplified when https://github.com/Marwes/combine/issues/86 makes it to a published release, but this unblocks us for now. This converts the `combine` error type `ParseError<&'a [edn::Value]>` to a type with owned `Vec<edn::Value>` collections, re-using `edn::Value::Vector` for making them `Display`. * Pre: Accept Borrow<Schema> instead of just &Schema in debug module. This makes it easy to use Rc<Schema> or Arc<Schema> without inserting &* sigils throughout the code. * Use error-chain in query-parser. There are a few things to point out here: - the fine grained error types have been flattened into one crate-wide error type; it's pretty easy to regain the granularity as needed. - edn::ParseError is automatically lifted to mentat_query_parser::errors::Error; - we use mentat_parser_utils::ValueParser to maintain parsing error information from `combine`. * Patch up top-level. * Review comment: Only `borrow()` once.
121 lines
3.7 KiB
Clojure
121 lines
3.7 KiB
Clojure
[{:test/label ":db.cardinality/one, insert"
|
|
:test/assertions
|
|
[[:db/add 100 :db/ident :name/Ivan]
|
|
[:db/add 101 :db/ident :name/Petr]]
|
|
:test/expected-transaction
|
|
#{[100 :db/ident :name/Ivan ?tx1 true]
|
|
[101 :db/ident :name/Petr ?tx1 true]
|
|
[?tx1 :db/txInstant ?ms1 ?tx1 true]}
|
|
:test/expected-datoms
|
|
#{[100 :db/ident :name/Ivan]
|
|
[101 :db/ident :name/Petr]}}
|
|
|
|
{:test/label "upsert two tempids to same entid"
|
|
:test/assertions
|
|
[[:db/add "t1" :db/ident :name/Ivan]
|
|
[:db/add "t1" :db.schema/attribute 100]
|
|
[:db/add "t2" :db/ident :name/Petr]
|
|
[:db/add "t2" :db.schema/attribute 101]]
|
|
:test/expected-transaction
|
|
#{[100 :db.schema/attribute 100 ?tx2 true]
|
|
[101 :db.schema/attribute 101 ?tx2 true]
|
|
[?tx2 :db/txInstant ?ms2 ?tx2 true]}
|
|
:test/expected-datoms
|
|
#{[100 :db/ident :name/Ivan]
|
|
[101 :db/ident :name/Petr]
|
|
[100 :db.schema/attribute 100]
|
|
[101 :db.schema/attribute 101]}
|
|
:test/expected-tempids
|
|
{"t1" 100
|
|
"t2" 101}}
|
|
|
|
{:test/label "upsert with tempid"
|
|
:test/assertions
|
|
[[:db/add "t1" :db/ident :name/Ivan]
|
|
;; Ref doesn't have to exist (at this time). Can't reuse due to :db/unique :db.unique/value.
|
|
[:db/add "t1" :db.schema/attribute 102]]
|
|
:test/expected-transaction
|
|
#{[100 :db.schema/attribute 102 ?tx3 true]
|
|
[?tx3 :db/txInstant ?ms3 ?tx3 true]}
|
|
:test/expected-datoms
|
|
#{[100 :db/ident :name/Ivan]
|
|
[101 :db/ident :name/Petr]
|
|
[100 :db.schema/attribute 100]
|
|
[100 :db.schema/attribute 102]
|
|
[101 :db.schema/attribute 101]}
|
|
:test/expected-tempids
|
|
{"t1" 100}}
|
|
|
|
;; TODO: don't hard-code allocated entids.
|
|
{:test/label "single complex upsert allocates new entid"
|
|
:test/assertions
|
|
[[:db/add "t1" :db.schema/attribute "t2"]]
|
|
:test/expected-transaction
|
|
#{[65536 :db.schema/attribute 65537 ?tx4 true]
|
|
[?tx4 :db/txInstant ?ms4 ?tx4 true]}
|
|
:test/expected-tempids
|
|
{"t1" 65536
|
|
"t2" 65537}}
|
|
|
|
{:test/label "conflicting upserts fail"
|
|
:test/assertions
|
|
[[:db/add "t1" :db/ident :name/Ivan]
|
|
[:db/add "t1" :db/ident :name/Petr]]
|
|
:test/expected-transaction
|
|
nil
|
|
:test/expected-error-message
|
|
"Conflicting upsert"
|
|
;; nil
|
|
}
|
|
|
|
{:test/label "tempids in :db/retract that do upsert are fine"
|
|
:test/assertions
|
|
[[:db/add "t1" :db/ident :name/Ivan]
|
|
;; This ref doesn't exist, so the assertion will be ignored.
|
|
[:db/retract "t1" :db.schema/attribute 103]]
|
|
:test/expected-transaction
|
|
#{[?tx5 :db/txInstant ?ms5 ?tx5 true]}
|
|
:test/expected-error-message
|
|
""
|
|
:test/expected-tempids
|
|
{}}
|
|
|
|
{:test/label "tempids in :db/retract that don't upsert fail"
|
|
:test/assertions
|
|
[[:db/retract "t1" :db/ident :name/Anonymous]]
|
|
:test/expected-transaction
|
|
nil
|
|
:test/expected-error-message
|
|
""}
|
|
|
|
;; The upsert algorithm will first try to resolve "t1", fail, and then allocate both "t1" and "t2".
|
|
{:test/label "multistep, both allocated"
|
|
:test/assertions
|
|
[[:db/add "t1" :db/ident :name/Josef]
|
|
[:db/add "t2" :db.schema/attribute "t1"]]
|
|
:test/expected-transaction
|
|
#{[65538 :db/ident :name/Josef ?tx6 true]
|
|
[65539 :db.schema/attribute 65538 ?tx6 true]
|
|
[?tx6 :db/txInstant ?ms6 ?tx6 true]}
|
|
:test/expected-error-message
|
|
""
|
|
:test/expected-tempids
|
|
{"t1" 65538
|
|
"t2" 65539}}
|
|
|
|
;; Can't quite test this without more schema elements.
|
|
;; ;; This time, we can resolve both, but we have to try "t1", succeed, and then resolve "t2".
|
|
;; {:test/label "multistep, upserted allocated"
|
|
;; :test/assertions
|
|
;; [[:db/add "t1" :db/ident :name/Josef]
|
|
;; [:db/add "t2" :db/ident "t1"]]
|
|
;; :test/expected-transaction
|
|
;; #{[65538 :db/ident :name/Josef]
|
|
;; [65538 :db/ident :name/Karl]
|
|
;; [?tx8 :db/txInstant ?ms8 ?tx8 true]}
|
|
;; :test/expected-error-message
|
|
;; ""
|
|
;; :test/expected-tempids
|
|
;; {"t1" 65538
|
|
;; "t2" 65539}}
|
|
]
|