diff --git a/src/datomish/db.cljc b/src/datomish/db.cljc index 4f39b68e..5d34de0c 100644 --- a/src/datomish/db.cljc +++ b/src/datomish/db.cljc @@ -9,7 +9,7 @@ [cljs.core.async.macros :refer [go]])) (:require [honeysql.core :as sql] - [datomish.util :as util :refer [raise]] + [datomish.util :as util #?(:cljs :refer-macros :clj :refer) [raise cond-let]] [datomish.sqlite :as s] [datomish.sqlite-schema :as sqlite-schema] #?@(:clj [[datomish.pair-chan :refer [go-pair DB {:sqlite-connection sqlite-connection :current-tx (atom (dec tx0))}))) ;; TODO: get rid of dec. -(defn- #?@(:clj [^Boolean tx-id?] - :cljs [^boolean tx-id?]) - [e] - (or (= e :db/current-tx) - (= e ":db/current-tx"))) ;; for datascript.js interop +;; TODO: consider CLJS interop. +(defn- tx-id? [e] + (= e :db/current-tx)) -(defrecord TxReport [;; db-before db-after - tx-data tempids tx-meta]) - -#?(:clj - (defmacro cond-let [& clauses] - (when-let [[test expr & rest] clauses] - `(~(if (vector? test) 'if-let 'if) ~test - ~expr - (cond-let ~@rest))))) +;; TODO: write tx-meta to transaction. +(defrecord TxReport [tx-data tempids tx-meta]) +;; TODO: persist max-tx and max-eid in SQLite. (defn , :datoms } - -;; (defn ^Datom datom-from-reader [vec] -;; (apply datom vec)) +(defn datom? [x] (instance? Datom x)) #?(:clj (defmethod print-method Datom [^Datom d, ^java.io.Writer w] @@ -84,34 +78,31 @@ (raise "Cannot store nil as a value at " at {:error :transact/syntax, :value v, :context at}))) +;; TODO: implement schemas. (defn multival? [db attr] false) +;; TODO: implement schemas. (defn ref? [db attr] false) (defn sql-clause [pattern] (merge - {:select [:e :a :v :tx] ;; TODO: generalize columns. + {:select [:*] ;; e :a :v :tx] ;; TODO: generalize columns. :from [:datoms]} (if-not (empty? pattern) {:where (cons :and (map #(vector := %1 (if (keyword? %2) (str %2) %2)) [:e :a :v :tx] pattern))} ;; TODO: use schema to intern a and v. {}))) (defn > (search->sql-clause pattern) (sql/format) (s/all-rows (:sqlite-connection db))))] - (map #(Datom. (:e %) (:a %) (:v %) (:tx %) true) rows)))) + (mapv #(Datom. (:e %) (:a %) (:v %) (:tx %) true) rows)))) (defn- report (update-in [:tx-data] conj datom))))) (defn- report (assoc-in [:tempids :db/current-tx] current-tx))) - ;; (map? entity) - ;; (let [old-eid (:db/id entity)] - ;; (cond-let - ;; ;; :db/current-tx => tx - ;; (tx-id? old-eid) - ;; (let [id (current-tx report)] - ;; (recur (allocate-eid report old-eid id) - ;; (cons (assoc entity :db/id id) entities))) - - ;; ;; lookup-ref => resolved | error - ;; (sequential? old-eid) - ;; (let [id (entid-strict db old-eid)] - ;; (recur report - ;; (cons (assoc entity :db/id id) entities))) - - ;; ;; upserted => explode | error - ;; [upserted-eid (upsert-eid db entity)] - ;; (if (and (neg-number? old-eid) - ;; (contains? (:tempids report) old-eid) - ;; (not= upserted-eid (get (:tempids report) old-eid))) - ;; (retry-with-tempid initial-report initial-es old-eid upserted-eid) - ;; (recur (allocate-eid report old-eid upserted-eid) - ;; (concat (explode db (assoc entity :db/id upserted-eid)) entities))) - - ;; ;; resolved | allocated-tempid | tempid | nil => explode - ;; (or (number? old-eid) - ;; (nil? old-eid)) - ;; (let [new-eid (cond - ;; (nil? old-eid) (next-eid db) - ;; (neg? old-eid) (or (get (:tempids report) old-eid) - ;; (next-eid db)) - ;; :else old-eid) - ;; new-entity (assoc entity :db/id new-eid)] - ;; (recur (allocate-eid report old-eid new-eid) - ;; (concat (explode db new-entity) entities))) - - ;; ;; trash => error - ;; :else - ;; (raise "Expected number or lookup ref for :db/id, got " old-eid - ;; { :error :entity-id/syntax, :entity entity }))) + (map? entity) + (raise "Map entities are not yet supported, got " entity + {:error :transact/syntax + :op entity }) (sequential? entity) (let [[op e a v] entity] (cond - ;; (= op :db.fn/call) - ;; (let [[_ f & args] entity] - ;; (recur report (concat (apply f db args) entities))) + (= op :db.fn/call) + (raise "DataScript's transactor functions are not yet supported, got " entity + {:error :transact/syntax + :op entity }) - ;; (= op :db.fn/cas) - ;; (let [[_ e a ov nv] entity - ;; e (entid-strict db e) - ;; _ (validate-attr a entity) - ;; ov (if (ref? db a) (entid-strict db ov) ov) - ;; nv (if (ref? db a) (entid-strict db nv) nv) - ;; _ (validate-val nv entity) - ;; datoms (