(ns datascript.test.explode
(:require
#?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
:clj [clojure.test :as t :refer [is are deftest testing]])
[datascript.core :as d]
[datascript.db :as db]
[datascript.test.core :as tdc]))
#?(:cljs
(def Throwable js/Error))
(deftest test-explode
(doseq [coll [["Devil" "Tupen"]
#{"Devil" "Tupen"}
'("Devil" "Tupen")
(to-array ["Devil" "Tupen"])]]
(testing coll
(let [conn (d/create-conn {:aka {:db/cardinality :db.cardinality/many}
:also {:db/cardinality :db.cardinality/many}})]
(d/transact! conn [{:db/id -1
:name "Ivan"
:age 16
:aka coll
:also "ok"}])
(is (= (d/q '[:find ?n ?a
:where [1 :name ?n]
[1 :age ?a]] @conn)
#{["Ivan" 16]}))
(is (= (d/q '[:find ?v
:where [1 :also ?v]] @conn)
#{["ok"]}))
(is (= (d/q '[:find ?v
:where [1 :aka ?v]] @conn)
#{["Devil"] ["Tupen"]}))))))
(deftest test-explode-ref
(let [db0 (d/empty-db { :children { :db/valueType :db.type/ref
:db/cardinality :db.cardinality/many } })]
(let [db (d/db-with db0 [{:db/id -1, :name "Ivan", :children [-2 -3]}
{:db/id -2, :name "Petr"}
{:db/id -3, :name "Evgeny"}])]
(is (= (d/q '[:find ?n
:where [_ :children ?e]
[?e :name ?n]] db)
#{["Petr"] ["Evgeny"]})))
(let [db (d/db-with db0 [{:db/id -1, :name "Ivan"}
{:db/id -2, :name "Petr", :_children -1}
{:db/id -3, :name "Evgeny", :_children -1}])]
(is (= (d/q '[:find ?n
:where [_ :children ?e]
[?e :name ?n]] db)
#{["Petr"] ["Evgeny"]})))
(is (thrown-msg? "Bad attribute :_parent: reverse attribute name requires {:db/valueType :db.type/ref} in schema"
(d/db-with db0 [{:name "Sergey" :_parent 1}])))))
(deftest test-explode-nested-maps
(let [schema { :profile { :db/valueType :db.type/ref }}
db (d/empty-db schema)]
(are [tx res] (= (d/q '[:find ?e ?a ?v
:where [?e ?a ?v]]
(d/db-with db tx)) res)
[ {:db/id 5 :name "Ivan" :profile {:db/id 7 :email "@2"}} ]
#{ [5 :name "Ivan"] [5 :profile 7] [7 :email "@2"] }
[ {:name "Ivan" :profile {:email "@2"}} ]
#{ [1 :name "Ivan"] [1 :profile 2] [2 :email "@2"] }
[ {:profile {:email "@2"}} ] ;; issue #59
#{ [1 :profile 2] [2 :email "@2"] }
[ {:email "@2" :_profile {:name "Ivan"}} ]
#{ [1 :email "@2"] [2 :name "Ivan"] [2 :profile 1] }
))
(testing "multi-valued"
(let [schema { :profile { :db/valueType :db.type/ref
:db/cardinality :db.cardinality/many }}
db (d/empty-db schema)]
(are [tx res] (= (d/q '[:find ?e ?a ?v
:where [?e ?a ?v]]
(d/db-with db tx)) res)
[ {:db/id 5 :name "Ivan" :profile {:db/id 7 :email "@2"}} ]
#{ [5 :name "Ivan"] [5 :profile 7] [7 :email "@2"] }
[ {:db/id 5 :name "Ivan" :profile [{:db/id 7 :email "@2"} {:db/id 8 :email "@3"}]} ]
#{ [5 :name "Ivan"] [5 :profile 7] [7 :email "@2"] [5 :profile 8] [8 :email "@3"] }
[ {:name "Ivan" :profile {:email "@2"}} ]
#{ [1 :name "Ivan"] [1 :profile 2] [2 :email "@2"] }
[ {:name "Ivan" :profile [{:email "@2"} {:email "@3"}]} ]
#{ [1 :name "Ivan"] [1 :profile 2] [2 :email "@2"] [1 :profile 3] [3 :email "@3"] }
[ {:email "@2" :_profile {:name "Ivan"}} ]
#{ [1 :email "@2"] [2 :name "Ivan"] [2 :profile 1] }
[ {:email "@2" :_profile [{:name "Ivan"} {:name "Petr"} ]} ]
#{ [1 :email "@2"] [2 :name "Ivan"] [2 :profile 1] [3 :name "Petr"] [3 :profile 1] }
))))
(deftest test-circular-refs
(let [schema {:comp {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db/isComponent true}}
db (d/db-with (d/empty-db schema)
[{:db/id 1, :comp [{:name "C"}]}])]
(is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
[ [ 1 :comp 2 ]
[ 2 :name "C"] ])))
(let [schema {:comp {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}}
db (d/db-with (d/empty-db schema)
[{:db/id 1, :comp [{:name "C"}]}])]
(is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
[ [ 1 :comp 2 ]
[ 2 :name "C"] ])))
(let [schema {:comp {:db/valueType :db.type/ref
:db/isComponent true}}
db (d/db-with (d/empty-db schema)
[{:db/id 1, :comp {:name "C"}}])]
(is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
[ [ 1 :comp 2 ]
[ 2 :name "C"] ])))
(let [schema {:comp {:db/valueType :db.type/ref}}
db (d/db-with (d/empty-db schema)
[{:db/id 1, :comp {:name "C"}}])]
(is (= (mapv (juxt :e :a :v) (d/datoms db :eavt))
[ [ 1 :comp 2 ]
[ 2 :name "C"] ]))))