-
Notifications
You must be signed in to change notification settings - Fork 0
/
integrity_constraints.clj
74 lines (65 loc) · 3.91 KB
/
integrity_constraints.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
(ns lambdaconnect-sync.integrity-constraints
(:require [clojure.set :as s]))
(defn- set-last [coll x]
; Replace last element of coll by x
(conj (pop coll) x))
(defn get-uuids-from-db [config uuids entity-name snapshot]
(when (seq uuids)
(let [entity-keyword (keyword entity-name "ident__")]
(->> ((:q config)
'[:find ?uuid
:in $ [?uuid ...] ?attr
:where
[?e :app/uuid ?uuid]
[?e ?attr]]
snapshot uuids entity-keyword)
(mapv first)
set))))
(defn get-uuids-from-json [entity-name push-input]
(into #{} (map :app/uuid (get push-input entity-name))))
(defn check-many [config push-input snapshot entity-name relation-name destination-entity-name]
(let [uuids (->> entity-name
(get push-input)
(map (fn [object] ((keyword entity-name relation-name) object)))
(apply concat)
(map :app/uuid)
(into #{}))
uuids-from-json (get-uuids-from-db config uuids destination-entity-name snapshot)
uuids-from-db (get-uuids-from-json destination-entity-name push-input)
all-uuids (s/union uuids-from-json uuids-from-db #{nil})]
[entity-name relation-name (s/subset? uuids all-uuids) (s/difference uuids all-uuids)]))
(defn check-one [config push-input snapshot entity-name relation-name destination-entity-name]
(let [uuids (->> entity-name
(get push-input)
(map (fn [object] ((keyword entity-name relation-name) object)))
(map :app/uuid)
(into #{}))
uuids-from-json (get-uuids-from-json destination-entity-name push-input)
uuids-from-db (get-uuids-from-db config uuids destination-entity-name snapshot)
all-uuids (s/union uuids-from-json uuids-from-db #{nil})]
[entity-name relation-name (s/subset? uuids all-uuids) (s/difference uuids all-uuids)]))
(defn check [config push-input snapshot [relation-name destination-entity-name to-many entity-name]]
(if to-many
(check-many config push-input snapshot entity-name relation-name destination-entity-name)
(check-one config push-input snapshot entity-name relation-name destination-entity-name)))
(defn check-foreign-key [config push-input snapshot relations]
(let [check-all-entity-relations (fn [x] (filter (fn [rel] (let [[_ _ valid-uuids? _difference] (check config push-input snapshot rel)] (not valid-uuids?))) x))
get-all-invalid-uuids (fn [x] (map (fn [rel] (let [[entity relation _valid-uuids? difference] (check config push-input snapshot rel)] (when-not (empty? difference) [entity relation difference]))) x))
invalid-relations-by-entities (filter seq (map check-all-entity-relations relations))
invalid-uuids (filter (fn [res] (and res (not= #{nil} (last res)))) (apply concat (map get-all-invalid-uuids relations)))
filtered-invalid-uuids (map (fn [l] (set-last l (keep identity (last l)))) invalid-uuids)
invalid-entities (map (fn [entity-rels] (last (first entity-rels))) invalid-relations-by-entities)
invalid-relations (map (fn [entity-rels] (map #(first %) entity-rels)) invalid-relations-by-entities)
response (into {} (map vector invalid-entities invalid-relations))
result (empty? response)]
[result response filtered-invalid-uuids]))
(defn entity-names [entities-by-name]
(filter #(not= % "NOSynchData") (keys entities-by-name)))
(defn relations [entities-by-name]
(let [names (entity-names entities-by-name)
relation-maps-with-names (map #(list (:relationships (get entities-by-name %)) %) names)
relation-maps-values-with-names (map (fn [[map name]] (list (vals map) name)) relation-maps-with-names)]
(map
(fn [[list-rels name]]
(map #(flatten (list (vals (select-keys % [:name :destination-entity :to-many])) name)) list-rels))
relation-maps-values-with-names)))