From 5202b147eed350e7cdbf76341c14f44199907f98 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Thu, 14 Jul 2016 11:09:17 -0700 Subject: [PATCH] Part 1: Hacking up DB sqlite-connection))) + (map->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 + +(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))))) + +(defn , :datoms } + +;; (defn ^Datom datom-from-reader [vec] +;; (apply datom vec)) + +#?(: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)])))) + +(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 (or (keyword? attr) (string? attr)) + (raise "Bad entity attribute " attr " at " at ", expected keyword or string" + {: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}))) + +(defn multival? [db attr] false) + +(defn ref? [db attr] false) + +(defn sql-clause [pattern] + (merge + {: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)))) + +(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 }))) + + (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/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 (TxReport + {:current-tx current-tx + :tx-data [] + :tempids {} + :tx-meta tx-meta}) tx-data)))))) + +#_ (a/! !!]])) + +(defn !]]]) + #?@(: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 > + (> + (