diff --git a/package.json b/package.json index b8d506f8..cdf135a0 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": "6.x.x" }, - "version": "0.3.5", + "version": "0.3.7", "description": "A persistent, embedded knowledge base inspired by Datomic and DataScript.", "dependencies": { "promise-sqlite": "1.5.0", diff --git a/project.clj b/project.clj index d3655644..83b55285 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject mozilla/datomish "0.3.5" +(defproject mozilla/datomish "0.3.7" :description "A persistent, embedded knowledge base inspired by Datomic and DataScript." :url "https://github.com/mozilla/datomish" :license {:name "Apache License, Version 2.0" diff --git a/src/common/datomish/db.cljc b/src/common/datomish/db.cljc index 49592648..b9ec6ea3 100644 --- a/src/common/datomish/db.cljc +++ b/src/common/datomish/db.cljc @@ -124,9 +124,6 @@ Returns a pair-chan resolving to the same pair as the pair-chan returned by `chan-fn`.") - ( - (:sqlite-connection db) - (s/all-rows ["SELECT EXISTS(SELECT 1 FROM transactions LIMIT 1) AS bootstrapped"]) - (vector (fn [[part {:keys [start idx]}]] + [(sqlite-schema/->SQLite part) start idx]) + fail-alter-attr + (fn [old new] + (if-not (= old new) + (raise "Altering schema attributes is not yet supported, got " new " altering existing schema attribute " old + {:error :schema/alter-schema :old old :new new}) + new))] + (case from-version + 0 + (go-pair + ;; TODO: think more carefully about allocating new parts and bitmasking part ranges. + ;; TODO: install these using bootstrap assertions. It's tricky because the part ranges are implicit. + ;; TODO: chunk into 999/3 sections, for safety. + (vector bootstrap/parts)))) + + ;; We use (map (keyword attribute -> keyword value)), like @@ -81,63 +132,53 @@ (vector (fn [[part {:keys [start idx]}]] - [(sqlite-schema/->SQLite part) start idx])] - ;; TODO: allow inserting new parts. - ;; TODO: think more carefully about allocating new parts and bitmasking part ranges. - ;; TODO: install these using bootstrap assertions. It's tricky because the part ranges are implicit. - ;; TODO: chunk into 999/3 sections, for safety. - (vector bootstrap/parts))))) - - (-> db - ;; We use !]]]))) -(def current-version 1) +;; Version history: +;; 1: initial schema. +;; 2: added :db.schema/version and /attribute in bootstrap; assigned +;; idents 36 and 37, so we bump the part range here; tie bootstrapping +;; to the SQLite user_version. + +(def current-version 2) (def v1-statements ["CREATE TABLE datoms (e INTEGER NOT NULL, a SMALLINT NOT NULL, v BLOB NOT NULL, tx INTEGER NOT NULL, @@ -103,6 +109,8 @@ "CREATE TABLE parts (part TEXT NOT NULL PRIMARY KEY, start INTEGER NOT NULL, idx INTEGER NOT NULL)" ]) +(def v2-statements v1-statements) + (defn create-temp-tx-lookup-statement [table-name] ;; n.b., v0/value_type_tag0 can be NULL, in which case we look up v from datoms; ;; and the datom columns are NULL into the LEFT JOIN fills them in. @@ -133,40 +141,54 @@ " (e0, a0, v0, added0, value_type_tag0) WHERE sv IS NOT NULL")]) (defn > + [db bootstrapper] + (println "Creating database at" current-version) + (s/in-transaction! + db #(go-pair - (doseq [statement v1-statements] + (doseq [statement v2-statements] (try ( 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-str "No migrations yet defined!") - ( version. + :db/doc 35}) + +(def v2-idents + {:db.schema/version 36 ; Fragment -> version. :db.schema/attribute 37 ; Fragment -> attribute. }) +(def idents (merge v1-idents v2-idents)) + (def parts {:db.part/db {:start 0 :idx (inc (apply max (vals idents)))} :db.part/user {:start 0x10000 :idx 0x10000} :db.part/tx {:start 0x10000000 :idx 0x10000000} }) -(defn tx-data [] +(defn tx-data [new-idents new-symbolic-schema] (concat - (map (fn [[ident entid]] [:db/add entid :db/ident ident]) idents) + (map (fn [[ident entid]] [:db/add entid :db/ident ident]) new-idents) ;; TODO: install partitions as well, like (map (fn [[ident entid]] [:db/add :db.part/db :db.install/partition ident])). - (map (fn [[ident attrs]] (assoc attrs :db/id ident)) symbolic-schema) - (map (fn [[ident attrs]] [:db/add :db.part/db :db.install/attribute (get idents ident)]) symbolic-schema) ;; TODO: fail if nil. + (map (fn [[ident attrs]] (assoc attrs :db/id ident)) new-symbolic-schema) + (map (fn [[ident attrs]] [:db/add :db.part/db :db.install/attribute (get idents ident)]) new-symbolic-schema) ;; TODO: fail if nil. )) diff --git a/test/datomish/upgrade_test.clj b/test/datomish/upgrade_test.clj new file mode 100644 index 00000000..8848118e --- /dev/null +++ b/test/datomish/upgrade_test.clj @@ -0,0 +1,60 @@ +;; Copyright 2016 Mozilla +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); you may not use +;; this file except in compliance with the License. You may obtain a copy of the +;; License at http://www.apache.org/licenses/LICENSE-2.0 +;; Unless required by applicable law or agreed to in writing, software distributed +;; under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +;; CONDITIONS OF ANY KIND, either express or implied. See the License for the +;; specific language governing permissions and limitations under the License. + +(ns datomish.upgrade-test + (:require + [clojure.java.io :refer [copy]] + [datomish.jdbc-sqlite :as jdbc] + [datomish.sqlite :as s] + [datomish.api :as d] + [datomish.test-macros :refer [deftest-async]] + [datomish.pair-chan :refer [go-pair