|
61 | 61 | (defn same-keys? [a b]
|
62 | 62 | (and (= (count a) (count b))
|
63 | 63 | (every? #(contains? b %) (keys a))
|
64 |
| - (every? #(contains? b %) (keys a)))) |
| 64 | + (every? #(contains? a %) (keys b)))) |
65 | 65 |
|
66 | 66 | (defn- looks-like? [pattern form]
|
67 | 67 | (cond
|
|
126 | 126 |
|
127 | 127 | #?(:clj (set! *unchecked-math* false))
|
128 | 128 |
|
| 129 | +(defn- sum-rel* [attrs-a tuples-a attrs-b tuples-b] |
| 130 | + (let [idxb->idxa (vec (for [[sym idx-b] attrs-b] |
| 131 | + [idx-b (attrs-a sym)])) |
| 132 | + tlen (->> (vals attrs-a) (reduce max) (inc)) |
| 133 | + tuples' (persistent! |
| 134 | + (reduce |
| 135 | + (fn [acc tuple-b] |
| 136 | + (let [tuple' (da/make-array tlen)] |
| 137 | + (doseq [[idx-b idx-a] idxb->idxa] |
| 138 | + (aset tuple' idx-a (#?(:cljs da/aget :clj get) tuple-b idx-b))) |
| 139 | + (conj! acc tuple'))) |
| 140 | + (transient (vec tuples-a)) |
| 141 | + tuples-b))] |
| 142 | + (Relation. attrs-a tuples'))) |
| 143 | + |
129 | 144 | (defn sum-rel [a b]
|
130 | 145 | (let [{attrs-a :attrs, tuples-a :tuples} a
|
131 | 146 | {attrs-b :attrs, tuples-b :tuples} b]
|
132 | 147 | (cond
|
133 | 148 | (= attrs-a attrs-b)
|
134 | 149 | (Relation. attrs-a (into (vec tuples-a) tuples-b))
|
135 | 150 |
|
136 |
| - (and (not (same-keys? attrs-a attrs-b)) |
137 |
| - (seq tuples-a) ; could be empty because |
138 |
| - (seq tuples-b)) ; a query short-circuited |
| 151 | + ;; BEFORE checking same-keys |
| 152 | + ;; because one rel could have had its resolution shortcircuited |
| 153 | + (empty? tuples-a) b |
| 154 | + (empty? tuples-b) a |
| 155 | + |
| 156 | + (not (same-keys? attrs-a attrs-b)) |
139 | 157 | (raise "Can’t sum relations with different attrs: " attrs-a " and " attrs-b
|
140 | 158 | {:error :query/where})
|
141 | 159 |
|
142 | 160 | (every? number? (vals attrs-a)) ;; can’t conj into BTSetIter
|
143 |
| - (let [idxb->idxa (vec (for [[sym idx-b] attrs-b] |
144 |
| - [idx-b (attrs-a sym)])) |
145 |
| - tlen (->> (vals attrs-a) (reduce max) (inc)) |
146 |
| - tuples' (persistent! |
147 |
| - (reduce |
148 |
| - (fn [acc tuple-b] |
149 |
| - (let [tuple' (da/make-array tlen)] |
150 |
| - (doseq [[idx-b idx-a] idxb->idxa] |
151 |
| - (aset tuple' idx-a (#?(:cljs da/aget :clj get) tuple-b idx-b))) |
152 |
| - (conj! acc tuple'))) |
153 |
| - (transient (vec tuples-a)) |
154 |
| - tuples-b))] |
155 |
| - (Relation. attrs-a tuples')) |
| 161 | + (sum-rel* attrs-a tuples-a attrs-b tuples-b) |
156 | 162 |
|
157 | 163 | :else
|
158 |
| - (let [all-attrs (zipmap (keys (merge attrs-a attrs-b)) (range))] |
159 |
| - (-> (Relation. all-attrs []) |
160 |
| - (sum-rel a) |
| 164 | + (let [number-attrs (zipmap (keys attrs-a) (range))] |
| 165 | + (-> (sum-rel* number-attrs [] attrs-a tuples-a) |
161 | 166 | (sum-rel b))))))
|
162 | 167 |
|
163 | 168 | (defn prod-rel
|
|
0 commit comments