-
Notifications
You must be signed in to change notification settings - Fork 29
/
core.cljc
135 lines (109 loc) · 4.19 KB
/
core.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
(ns ^{:doc "A storage implementation over in-memory indexing. Includes full query engine."
:author "Paula Gearon"}
asami.core
(:require [clojure.string :as str]
[asami.graph :as gr]
[asami.index :as mem]
[asami.multi-graph :as multi]
[asami.query :as query]
[naga.storage.store-util :as store-util]
[naga.store :as store :refer [Storage StorageType]]
[naga.store-registry :as registry]
#?(:clj [schema.core :as s]
:cljs [schema.core :as s :include-macros true])
#?(:clj [clojure.core.cache :as c])))
#?(:clj
;; Using a cache of 1 is currently redundant to an atom
(let [m (atom (c/lru-cache-factory {} :threshold 1))]
(defn get-count-fn
"Returns a memoized counting function for the current graph.
These functions only last as long as the current graph."
[graph]
(if-let [f (c/lookup @m graph)]
(do
(swap! m c/hit graph)
f)
(let [f (memoize #(gr/count-pattern graph %))]
(swap! m c/miss graph f)
f))))
:cljs
(let [m (atom {})]
(defn get-count-fn
"Returns a memoized counting function for the current graph.
These functions only last as long as the current graph."
[graph]
(if-let [f (get @m graph)]
f
(let [f (memoize #(gr/count-pattern graph %))]
(reset! m {graph f})
f)))))
(declare ->MemoryStore)
(defrecord MemoryStore [before-graph graph]
Storage
(start-tx [this] (->MemoryStore graph graph))
(commit-tx [this] this)
(deltas [this]
;; sort responses by the number in the node ID, since these are known to be ordered
(when-let [previous-graph (or (:data (meta this)) before-graph)]
(->> (gr/graph-diff graph previous-graph)
(filter (fn [s] (seq (gr/resolve-pattern graph [s :naga/entity '?]))))
(sort-by #(subs (name %) 5)))))
(new-node [this]
(->> "node-"
gensym
name
(keyword "mem")))
(node-id [this n]
(subs (name n) 5))
(node-type? [this prop value]
(and (keyword? value)
(= "mem" (namespace value))
(str/starts-with? (name value) "node-")))
(data-property [_ data]
:naga/first)
(container-property [_ data]
:naga/contains)
(resolve-pattern [_ pattern]
(gr/resolve-pattern graph pattern))
(count-pattern [_ pattern]
(if-let [count-fn (get-count-fn graph)]
(count-fn pattern)
(gr/count-pattern graph pattern)))
(query [this output-pattern patterns]
(store-util/project this output-pattern (query/join-patterns graph patterns nil)))
(assert-data [_ data]
(->MemoryStore before-graph (query/add-to-graph graph data)))
(retract-data [_ data]
(->MemoryStore before-graph (query/delete-from-graph graph data)))
(assert-schema-opts [this _ _] this)
(query-insert [this assertion-patterns patterns]
(letfn [(ins-project [data]
(let [cols (:cols (meta data))]
(store-util/insert-project this assertion-patterns cols data)))]
(->> (query/join-patterns graph patterns nil)
ins-project
(query/add-to-graph graph)
(->MemoryStore before-graph)))))
(def empty-store (->MemoryStore nil mem/empty-graph))
(def empty-multi-store (->MemoryStore nil multi/empty-multi-graph))
(defn update-store
[{:keys [before-graph graph]} f & args]
(->MemoryStore before-graph (apply f graph args)))
(s/defn create-store :- StorageType
"Factory function to create a store"
[config]
empty-store)
(s/defn create-multi-store :- StorageType
"Factory function to create a multi-graph-store"
[config]
empty-multi-store)
(registry/register-storage! :memory create-store)
(registry/register-storage! :memory-multi create-multi-store)
(s/defn q
[query & inputs]
(let [{:keys [find in with where]} (-> (query/query-map query)
query/query-validator)
[bindings default-store] (query/create-bindings in inputs)
store (or default-store empty-store)
graph (or (:graph store) mem/empty-graph)]
(store-util/project store find (query/join-patterns graph where bindings))))