From 513f23c45ca91c9ec24b67901462412cdba06446 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Mon, 25 Jul 2016 08:07:53 -0700 Subject: [PATCH] Process !]]]) #?@(:cljs [[datomish.pair-chan] [cljs.core.async :as a :refer [chan !]]]))) (defprotocol IDB + (idents + [db] + "Return map {ident -> entid} if known idents. See http://docs.datomic.com/identity.html#idents.") + (query-context [db]) + (close [db] "Close this database. Returns a pair channel of [nil error].")) -(defrecord DB [sqlite-connection] +(defn db? [x] + (and (satisfies? IDB x))) + +;; TODO: implement support for DB parts? +(def tx0 0x2000000) + +;; TODO: write tx-meta to transaction. +(defrecord TxReport [tx-data tempids tx-meta]) + +;; TODO: persist max-tx and max-eid in SQLite. +(defn Context (source/datoms-source db) nil nil)) (close [db] (s/close (.-sqlite-connection db)))) @@ -36,7 +62,58 @@ (go-pair (when-not (= sqlite-schema/current-version (DB sqlite-connection))) + (map->DB {:sqlite-connection sqlite-connection + :idents (atom {:db/txInstant 100 :x 101 :y 102}) ;; TODO: pre-populate idents and SQLite tables? + :current-tx (atom (dec tx0))}))) ;; TODO: get rid of dec. + + + +#?(:clj + (defmethod print-method Datom [^Datom d, ^java.io.Writer w] + (.write w (str "#datomish/Datom ")) + (binding [*out* w] + (pr [(.-e d) (.-a d) (.-v d) (.-tx d) (.-added d)])))) + +;; TODO: implement schemas. +(defn multival? [db attr] false) + +;; TODO: implement schemas. +(defn ref? [db attr] false) + +(defn db query-context - (query/expand-find-into-context parsed)) + (query/find-into-context parsed)) row-pair-transducer (projection/row-pair-transducer context) sql (query/context->sql-string context args) chan (chan 50 row-pair-transducer)] @@ -67,4 +144,3 @@ [db find args] (a/reduce (partial reduce-error-pair conj) [[] nil] (!]]]) + #?@(:cljs [[datomish.pair-chan] + [cljs.core.async :as a :refer [chan !]]]))) + +(defn- tx-id? [e] + (= e :db/current-tx)) + +(defn- validate-eid [eid at] + (when-not (number? eid) + (raise "Bad entity id " eid " at " at ", expected number" + {:error :transact/syntax, :entity-id eid, :context at}))) + +(defn- validate-attr [attr at] + (when-not (number? attr) + (raise "Bad entity attribute " attr " at " at ", expected number" + {:error :transact/syntax, :attribute attr, :context at}))) + +(defn- validate-val [v at] + (when (nil? v) + (raise "Cannot store nil as a value at " at + {:error :transact/syntax, :value v, :context at}))) + +;; TODO: handle _? +(defn search->sql-clause [pattern] + (merge + {:select [:*] ;; e :a :v :tx] ;; TODO: generalize columns. + :from [:datoms]} + (if-not (empty? pattern) + {:where (cons :and (map #(vector := %1 %2) [:e :a :v :tx] pattern))} ;; TODO: use schema to v. + {}))) + +(defn > + (search->sql-clause pattern) + (sql/format) + (s/all-rows (:sqlite-connection db))))] + (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) + (raise "Map entities are not yet supported, got " entity + {:error :transact/syntax + :op entity }) + + (sequential? entity) + (let [[op e a v] entity] + (cond + (keyword? a) + (if-let [entid (get (db/idents db) a)] + (recur report (cons [op e entid v] entities)) + (raise "No entid found for ident " a + {:error :transact/syntax + :op entity})) + + (= op :db.fn/call) + (raise "DataScript's transactor functions are not yet supported, got " entity + {:error :transact/syntax + :op entity }) + + (= op :db.fn/cas) + (raise "Datomic's compare-and-swap is not yet supported, got " entity + {:error :transact/syntax + :op entity }) + + (tx-id? e) + (recur report (cons [op current-tx a v] entities)) + + (and (db/ref? db a) (tx-id? v)) + (recur report (cons [op e a current-tx] entities)) + + (neg-number? e) + (if (not= op :db/add) + (raise "Negative entity ids are resolved for :db/add only" + {:error :transact/syntax + :op entity }) + (raise "Negative entity ids are not yet supported, got " entity + {:error :transact/syntax + :op entity })) + + (and (db/ref? db a) (neg-number? v)) + (raise "Negative entity ids are not yet supported, got " entity + {:error :transact/syntax + :op entity }) + + (= op :db/add) + (recur (TxReport + {:current-tx current-tx + :tx-data [] + :tempids {} + :tx-meta tx-meta}) tx-data))] + (!]]]) + #?@(:cljs [[datomish.pair-chan] + [datomish.test-macros :refer-macros [deftest-async]] + [datomish.node-tempfile :refer [tempfile]] + [cljs.test :as t :refer-macros [is are deftest testing async]] + [cljs.core.async :as a :refer [!]]]))) + +(defn > + (> + (