diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d20ab0d..e2446b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# WIP + +- Regression: transacting many ref value as a set of inline maps #476 + # 1.7.1 - Jun 20, 2024 - Regression: :db.fn/call returning entity without :db/id #474 #475 via @DerGuteMoritz diff --git a/script/release.clj b/script/release.clj index 0d3871c8..d35f0a7a 100755 --- a/script/release.clj +++ b/script/release.clj @@ -37,8 +37,11 @@ (defn update-version [] (println "\n\n[ Updating version number ]\n") - (let [old-v (current-version)] - (update-file "CHANGELOG.md" #(str/replace % "# WIP" (str "# " new-v))) + (let [old-v (current-version) + today (.format + (java.time.format.DateTimeFormatter. "MMM d, yyyy") + (java.time.LocalDate/now))] + (update-file "CHANGELOG.md" #(str/replace % "# WIP" (str "# " new-v " - " today))) (update-file "project.clj" #(str/replace % old-v new-v)) (update-file "README.md" #(str/replace % old-v new-v)) (update-file "release-js/package.json" #(str/replace % @@ -55,11 +58,11 @@ (defn make-commit [] (println "\n\n[ Making a commit ]\n") (sh "git" "add" - "CHANGELOG.md" - "project.clj" - "README.md" - "release-js/package.json" - "release-js/wrapper.prefix") + "CHANGELOG.md" + "project.clj" + "README.md" + "release-js/package.json" + "release-js/wrapper.prefix") (sh "git" "commit" "-m" commit-message) (sh "git" "tag" new-v) @@ -71,9 +74,9 @@ (defn- str->json [s] (-> s - (str/replace "\\" "\\\\") - (str/replace "\"" "\\\"") - (str/replace "\n" "\\n"))) + (str/replace "\\" "\\\\") + (str/replace "\"" "\\\"") + (str/replace "\n" "\\n"))) (defn- map->json [m] (str "{ " @@ -86,36 +89,41 @@ (defn github-release [] (sh "cp" "release-js/datascript.js" (str "release-js/datascript-" new-v ".min.js")) - (let [changelog (->> (slurp "CHANGELOG.md") - str/split-lines - (drop-while #(not= (str "# " new-v) %)) - next - (take-while #(not (re-matches #"# .+" %))) - (remove str/blank?) - (str/join "\n")) - request { "tag_name" new-v - "name" new-v + (let [re (as-> new-v % + (str/replace % "." "\\.") + (str "# " % " .*") + (re-pattern %)) + changelog (->> (slurp "CHANGELOG.md") + str/split-lines + (drop-while #(not (re-matches re %))) + next + (take-while #(not (re-matches #"# .+" %))) + (remove str/blank?) + (str/join "\n")) + request {"tag_name" new-v + "name" new-v "target_commitish" "master" - "body" changelog} - response (sh "curl" "-u" GITHUB_BASIC - "-X" "POST" - "--data" (map->json request) - "https://api.github.com/repos/tonsky/datascript/releases") - [_ id] (re-find #"\"id\": (\d+)" response)] + "body" changelog} + response (sh "curl" "-u" GITHUB_BASIC + "-X" "POST" + "--data" (map->json request) + "https://api.github.com/repos/tonsky/datascript/releases") + [_ id] (re-find #"\"id\": (\d+)" response)] (sh "curl" "-u" GITHUB_BASIC - "-X" "POST" - "-H" "Content-Type: application/javascript" - "--data-binary" (str "@release-js/datascript-" new-v ".min.js") - (str "https://uploads.github.com/repos/tonsky/datascript/releases/" id "/assets?name=datascript-" new-v ".min.js")))) + "-X" "POST" + "-H" "Content-Type: application/javascript" + "--data-binary" (str "@release-js/datascript-" new-v ".min.js") + (str "https://uploads.github.com/repos/tonsky/datascript/releases/" id "/assets?name=datascript-" new-v ".min.js")))) (defn -main [] (sh "lein" "clean") (update-version) - (run-tests) - (make-commit) - (publish-npm) - (github-release) - (sh "lein" "deploy" "clojars") - (System/exit 0)) + ; (run-tests) + ; (make-commit) + ; (publish-npm) + ; (github-release) + ; (sh "lein" "deploy" "clojars") + ; (System/exit 0) + ) (-main) diff --git a/src/datascript/db.cljc b/src/datascript/db.cljc index 5a86aad2..5b93a98f 100644 --- a/src/datascript/db.cljc +++ b/src/datascript/db.cljc @@ -1163,6 +1163,13 @@ (defn+ ^boolean multival? [db attr] (is-attr? db attr :db.cardinality/many)) +(defn+ ^boolean multi-value? [db attr value] + (and + (is-attr? db attr :db.cardinality/many) + (or + (arrays/array? value) + (and (coll? value) (not (map? value)))))) + (defn+ ^boolean ref? [db attr] (is-attr? db attr :db.type/ref)) @@ -1304,7 +1311,7 @@ (not (or (keyword? a) (string? a))) (assoc entity a v) - (and (ref? db a) (multival? db a) (sequential? v)) + (and (ref? db a) (multi-value? db a v)) (assoc entity a (assoc-auto-tempids db v)) (ref? db a) @@ -1328,7 +1335,7 @@ :let [[op e a v] entity] (= :db/add op) (ref? db a)) - (if (and (multival? db a) (sequential? v)) + (if (multi-value? db a v) [op e a (assoc-auto-tempids db v)] [op e a (first (assoc-auto-tempids db [v]))]) @@ -1490,11 +1497,7 @@ (not (contains? idents a)) [(assoc entity' a v) upserts] - (and - (multival? db a) - (or - (arrays/array? v) - (and (coll? v) (not (map? v))))) + (multi-value? db a v) (let [[insert upsert] (split a v)] [(cond-> entity' (not (empty? insert)) (assoc a insert)) diff --git a/test/datascript/test/explode.cljc b/test/datascript/test/explode.cljc index ddcdd83a..028ba962 100644 --- a/test/datascript/test/explode.cljc +++ b/test/datascript/test/explode.cljc @@ -36,21 +36,27 @@ (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"]}))) + (doseq [children [[-2 -3] + #{-2 -3} + (list -2 -3)]] + (testing (str "ref + many + " children) + (let [db (d/db-with db0 [{:db/id -1, :name "Ivan", :children children} + {:db/id -2, :name "Petr"} + {:db/id -3, :name "Evgeny"}])] + (is (= #{["Petr"] ["Evgeny"]} + (d/q '[:find ?n + :where + [_ :children ?e] + [?e :name ?n]] db)))))) (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 (= #{["Petr"] ["Evgeny"]} + (d/q '[:find ?n + :where + [_ :children ?e] + [?e :name ?n]] db)))) (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}]))))) @@ -78,9 +84,9 @@ (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) + (are [tx res] (= res (d/q '[:find ?e ?a ?v + :where [?e ?a ?v]] + (d/db-with db tx))) [{:db/id 5 :name "Ivan" :profile {:db/id 7 :email "@2"}}] #{[5 :name "Ivan"] [5 :profile 7] [7 :email "@2"]} @@ -92,6 +98,13 @@ [{:name "Ivan" :profile [{:email "@2"} {:email "@3"}]}] #{[1 :name "Ivan"] [1 :profile 2] [2 :email "@2"] [1 :profile 3] [3 :email "@3"]} + + ;; issue-467 + [{:name "Ivan" :profile #{{:email "@2"} {:email "@3"}}}] + #{[1 :name "Ivan"] [1 :profile 2] [2 :email "@3"] [1 :profile 3] [3 :email "@2"]} + + [{:name "Ivan" :profile (list {: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]} diff --git a/test/datascript/test/transact.cljc b/test/datascript/test/transact.cljc index 347e2ad2..9d115f4d 100644 --- a/test/datascript/test/transact.cljc +++ b/test/datascript/test/transact.cljc @@ -18,7 +18,7 @@ (is (= (d/q '[:find ?v :where [1 :aka ?v]] db) #{["Devil"] ["Tupen"]})) - + (testing "Retract" (let [db (-> db (d/db-with [[:db/retract 1 :name "Petr"]]) @@ -219,7 +219,21 @@ (let [{:keys [db-after]} (d/transact! conn [[:db.fn/call inc-age "Petr"]]) e (d/entity db-after 1)] (is (= (:age e) 32)) - (is (:had-birthday e))))) + (is (:had-birthday e))) + + (let [{:keys [db-after]} (d/transact! conn + [[:db.fn/call (fn [db] + [{:name "Oleg"}])]]) + e (d/entity db-after 2)] + (is (= "Oleg" (:name e)))) + + (let [{:keys [db-after + tempids]} (d/transact! conn + [[:db.fn/call (fn [db] + [{:db/id -1 + :name "Vera"}])]]) + e (d/entity db-after (tempids -1))] + (is (= "Vera" (:name e)))))) (deftest test-db-ident-fn (let [conn (d/create-conn {:name {:db/unique :db.unique/identity}})