diff options
Diffstat (limited to 'src/clojure')
-rw-r--r-- | src/clojure/contrib/datalog/database.clj | 38 | ||||
-rw-r--r-- | src/clojure/contrib/datalog/tests/test_database.clj | 93 |
2 files changed, 123 insertions, 8 deletions
diff --git a/src/clojure/contrib/datalog/database.clj b/src/clojure/contrib/datalog/database.clj index 8fef6524..517c1b92 100644 --- a/src/clojure/contrib/datalog/database.clj +++ b/src/clojure/contrib/datalog/database.clj @@ -145,14 +145,25 @@ [db] (map-values #(-> % :data count) db)) -(defn- add-to-indexes - "Adds the tuple to the appropriate keys in the index map" - [idxs tuple] +(defn- modify-indexes + "Perform f on the indexed tuple-set. f should take a set and tuple, + and return the new set." + [idxs tuple f] (into {} (for [ik (keys idxs)] (let [im (idxs ik) iv (tuple ik) os (get im iv #{})] - [ik (assoc im iv (conj os tuple))])))) + [ik (assoc im iv (f os tuple))])))) + +(defn- add-to-indexes + "Adds the tuple to the appropriate keys in the index map" + [idxs tuple] + (modify-indexes idxs tuple conj)) + +(defn- remove-from-indexes + "Removes the tuple from the appropriate keys in the index map" + [idxs tuple] + (modify-indexes idxs tuple disj)) (defn add-tuple "Two forms: @@ -170,8 +181,25 @@ (if (identical? data new-data) ; optimization hack! rel (let [idxs (add-to-indexes (:indexes rel) tuple)] - (assoc rel :data (conj (:data rel) tuple) :indexes idxs)))))) + (assoc rel :data new-data :indexes idxs)))))) + +(defn remove-tuple + "Two forms: + + [db relation-name tuple] removes the tuple from the named relation, + returns a new database. + [rel tuple] removes the tuple from the relation. Returns the new + relation." + ([db rel-name tuple] (assoc db rel-name (remove-tuple (db rel-name) tuple))) + ([rel tuple] + (let [data (:data rel) + new-data (disj data tuple)] + (if (identical? data new-data) + rel + (let [idxs (remove-from-indexes (:indexes rel) tuple)] + (assoc rel :data new-data :indexes idxs)))))) + (defn add-tuples "Adds a collection of tuples to the db, as (add-tuples db diff --git a/src/clojure/contrib/datalog/tests/test_database.clj b/src/clojure/contrib/datalog/tests/test_database.clj index 527c8fae..b3931bb7 100644 --- a/src/clojure/contrib/datalog/tests/test_database.clj +++ b/src/clojure/contrib/datalog/tests/test_database.clj @@ -28,8 +28,18 @@ (index :sally :becky))) (deftest test-make-database - (is (= (-> test-db :fred :schema) #{:mary :sue})) - (is (= (-> test-db :sally :schema) #{:jen :becky :joan}))) + (is (= test-db + (datalog-database + {:sally (datalog-relation + #{:jen :joan :becky} + #{} + {:becky {} + :jen {}}) + :fred (datalog-relation + #{:sue :mary} + #{} + {:mary {}})})))) + (deftest test-ensure-relation (is (contains? (ensure-relation test-db :bob [:sam :george] [:sam]) :bob)) @@ -41,7 +51,6 @@ (is (= (select new-db :fred {:mary 1}) [{:mary 1 :sue 2}]))) (is (thrown? Exception (add-tuple test-db :fred {:mary 1})))) - (def test-db-1 (add-tuples test-db [:fred :mary 1 :sue 2] @@ -53,6 +62,84 @@ [:fred :mary 1 :sue 1] [:fred :mary 3 :sue 1])) +(deftest test-add-tuples + (is (= test-db-1 + (datalog-database + {:sally (datalog-relation + #{:jen :joan :becky} + #{{:jen 1, :joan 0, :becky 3} + {:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2} + {:jen 1, :joan 3, :becky 4}} + {:becky {3 + #{{:jen 1, :joan 0, :becky 3}} + 4 + #{{:jen 1, :joan 3, :becky 4}} + 2 + #{{:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2}}} + :jen {1 + #{{:jen 1, :joan 0, :becky 3} + {:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2} + {:jen 1, :joan 3, :becky 4}}}}) + :fred (datalog-relation + #{:sue :mary} + #{{:sue 2, :mary 1} + {:sue 1, :mary 1} + {:sue 3, :mary 2} + {:sue 1, :mary 3}} + {:mary {3 + #{{:sue 1, :mary 3}} + 2 + #{{:sue 3, :mary 2}} + 1 + #{{:sue 2, :mary 1} + {:sue 1, :mary 1}}}})})))) + +(deftest test-remove-tuples + (let [db (reduce #(apply remove-tuple %1 (first %2) (next %2)) + test-db-1 + [[:fred {:mary 1 :sue 1}] + [:fred {:mary 3 :sue 1}] + [:sally {:jen 1 :bekcy 2 :joan 0}] + [:sally {:jen 1 :bekcy 4 :joan 3}]])] + (assert (= db + (datalog-database + {:sally (datalog-relation + #{:jen :joan :becky} + #{{:jen 1, :joan 0, :becky 3} + {:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2} + {:jen 1, :joan 3, :becky 4}} + {:becky + {3 + #{{:jen 1, :joan 0, :becky 3}} + 4 + #{{:jen 1, :joan 3, :becky 4}} + 2 + #{{:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2}}} + :jen + {1 + #{{:jen 1, :joan 0, :becky 3} + {:jen 1, :joan 0, :becky 2} + {:jen 1, :joan 3, :becky 2} + {:jen 1, :joan 3, :becky 4}}}}) + :fred (datalog-relation + #{:sue :mary} + #{{:sue 2, :mary 1} + {:sue 3, :mary 2}} + {:mary + {3 + #{} + 2 + #{{:sue 3, :mary 2}} + 1 + #{{:sue 2, :mary 1}}}})}))))) + + + (deftest test-select (is (= (set (select test-db-1 :sally {:jen 1 :becky 2})) #{{:jen 1 :joan 0 :becky 2} {:jen 1 :joan 3 :becky 2}})) |