aboutsummaryrefslogtreecommitdiff
path: root/src/clojure
diff options
context:
space:
mode:
Diffstat (limited to 'src/clojure')
-rw-r--r--src/clojure/contrib/datalog/database.clj38
-rw-r--r--src/clojure/contrib/datalog/tests/test_database.clj93
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}}))