From 900e77862e845d4cd28c5fd2a11e9635732e5aef Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Tue, 12 Jul 2016 15:37:26 -0700 Subject: [PATCH] Implement database on top of SQLite connection. r=rnewman We would prefer to talk about a knowledge base on top of a database, but all the Datomic and DataScript code (and symbols, like :db/add, etc) refer to the "database of datoms", so let's roll with that nomenclature and try to be specific that the persistent storage-layer is SQLite. This will become more clear when we actually use SQLite's unique capabilities for text indexing. --- src/datomish/db.cljc | 32 +++++++++++++++++ src/datomish/sqlite.cljc | 8 +++++ src/datomish/sqlite_schema.cljc | 61 +++++++++++++++++++++++++++++++++ test/datomish/test.cljs | 1 - 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/datomish/db.cljc create mode 100644 src/datomish/sqlite_schema.cljc diff --git a/src/datomish/db.cljc b/src/datomish/db.cljc new file mode 100644 index 00000000..cf697573 --- /dev/null +++ b/src/datomish/db.cljc @@ -0,0 +1,32 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns datomish.db + #?(:cljs + (:require-macros + [datomish.pair-chan :refer [go-pair !]]]) + #?@(:cljs [[datomish.pair-chan] + [cljs.core.async :as a :refer [!]]]))) + +(defprotocol IDB + (close + [db] + "Close this database. Returns a pair channel of [nil error].")) + +(defrecord DB [sqlite-connection] + IDB + (close [db] (close (.-sqlite-connection db)))) + +(defn DB sqlite-connection))) diff --git a/src/datomish/sqlite.cljc b/src/datomish/sqlite.cljc index fb0e866f..12ac2b46 100644 --- a/src/datomish/sqlite.cljc +++ b/src/datomish/sqlite.cljc @@ -68,3 +68,11 @@ [nil e]))) (catch #?(:clj Exception :cljs js/Error) e [nil e])))) + +(defn get-user-version [db] + (go-pair + (let [row (first (!]]]) + #?@(:cljs [[datomish.pair-chan] + [cljs.core.async :as a :refer [!]]]))) + +(def current-version 1) + +(def v1-statements + ["CREATE TABLE datoms (e INTEGER NOT NULL, a SMALLINT NOT NULL, v BLOB NOT NULL, tx INTEGER NOT NULL, index_avet TINYINT NOT NULL DEFAULT 0, index_vaet TINYINT NOT NULL DEFAULT 0)" + "CREATE INDEX eavt ON datoms (e, a)" ;; No v -- that's an opt-in index. + "CREATE INDEX aevt ON datoms (a, e)" ;; No v -- that's an opt-in index. + "CREATE INDEX avet ON datoms (a, v, e) WHERE index_avet = 1" ;; Opt-in index: only if a has :db/index true. + "CREATE INDEX vaet ON datoms (v, a, e) WHERE index_vaet = 1" ;; Opt-in index: only if a has :db/valueType :db.type/ref + "CREATE TABLE transactions (e INTEGER NOT NULL, a SMALLINT NOT NULL, v BLOB NOT NULL, tx INTEGER NOT NULL, added TINYINT NOT NULL DEFAULT 1)" + "CREATE INDEX tx ON transactions (tx)" + "CREATE TABLE attributes (name TEXT NOT NULL PRIMARY KEY, a INTEGER UNIQUE NOT NULL)"]) + +(defn > + #(go-pair + (doseq [statement v1-statements] + ( from-version 0)]} ;; Or we'd create-current-version instead. + {:pre [(< from-version current-version)]} ;; Or we wouldn't need to update-from-version. + (go-pair + (raise "No migrations yet defioned!") + (