-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
after.clj
107 lines (87 loc) · 3.64 KB
/
after.clj
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
(ns toucan2.tools.after
"Shared low-level implementation for doing transformations to the results of different operations defined
with [[toucan2.operation]]."
(:require
[methodical.core :as m]
[pretty.core :as pretty]
[toucan2.instance :as instance]
[toucan2.model :as model]
[toucan2.operation :as op]
[toucan2.realize :as realize]
[toucan2.util :as u]))
(set! *warn-on-reflection* true)
;;; TODO -- Consider whether the various methods here should be `:after` methods rather than `:around`
(m/defmulti after
{:arglists '([query-type model instance])}
u/dispatch-on-first-two-args)
(m/defmethod after :around :default
[query-type model instance]
(u/with-debug-result (list `after query-type model instance)
(u/try-with-error-context ["do after- transformations to result" {::query-type query-type, ::model model, ::row instance}]
(next-method query-type model instance))))
(defn has-after-method? [query-type model]
(not= (m/default-primary-method after)
(m/effective-primary-method after (m/dispatch-value after query-type model))))
;;;; reducible instances
(defn after-reducible-instances [query-type model reducible-instances]
(eduction
(map (fn [row]
(or (some-> (after query-type model row) instance/reset-original)
row)))
reducible-instances))
(m/defmethod op/reducible-returning-instances* :around [::after ::after]
[query-type model parsed-args]
(cond
(::doing-after? parsed-args)
(next-method query-type model parsed-args)
(not (has-after-method? query-type model))
(next-method query-type model parsed-args)
:else
(let [parsed-args (assoc parsed-args ::doing-after? true)]
(after-reducible-instances query-type model (next-method query-type model parsed-args)))))
;;;; reducible PKs
(deftype ^:no-doc AfterReduciblePKs [query-type model reducible-pks]
clojure.lang.IReduceInit
(reduce [_this rf init]
(u/with-debug-result ["reducing %s %s for %s" `after query-type model]
(let [affected-pks (realize/realize reducible-pks)]
(u/println-debug ["Doing %s %s for %s with PKs %s" `after query-type model affected-pks])
(reduce
rf
init
(after-reducible-instances
query-type
model
(op/select-reducible-with-pks model nil affected-pks))))))
pretty/PrettyPrintable
(pretty [_this]
(list `->AfterReduciblePKs query-type model reducible-pks)))
(m/defmethod op/reducible-update-returning-pks* :around [::after ::after]
[query-type model parsed-args]
(cond
(::doing-after? parsed-args)
(next-method query-type model parsed-args)
(not (has-after-method? query-type model))
(next-method query-type model parsed-args)
:else
(let [parsed-args (assoc parsed-args ::doing-after? true)
reducible-pks (next-method query-type model parsed-args)]
(assert (instance? clojure.lang.IReduceInit reducible-pks))
(eduction
(map (model/select-pks-fn model))
(->AfterReduciblePKs query-type model reducible-pks)))))
;;;; reducible update count
(m/defmethod op/reducible-update* :around [::after ::after]
[query-type model parsed-args]
(cond
(::doing-after? parsed-args)
(next-method query-type model parsed-args)
(not (has-after-method? query-type model))
(next-method query-type model parsed-args)
:else
(let [parsed-args (assoc parsed-args ::doing-after? true)
reducible-count (next-method query-type model parsed-args)
reducible-pks (op/return-pks-eduction model reducible-count)]
(eduction
(map (constantly 1))
(->AfterReduciblePKs query-type model reducible-pks)))))