 	rhs-indeces (rest new-indeces)
 	joins (mapcat (fn [lhs] (derive-joins lhs rhs-indeces rhs-ks join-fn)) lhses)
 	]
-    (println "RHS JOINS: " joins)
-    new-indeces
+    [new-indeces (fn [_] (on-upserts joined-model joins))]
     ))
 
 ;;; TODO

	c1 (->C :c1 0 :c "c1-data")
	c2 (->C :c2 0 :c "c2-data")]
    (is (= [[{}{}]{}{}] (data join)))

    (attach join view)
    (is (= nil (data view)))

   (fn [args] (apply join-fn v args))
   (permute [[]] (map (fn [index key] (index (key v))) rhs-indeces ks))))

(defn- lhs-upsert [[old-index & rhs-indeces] ks v join-fn joined-model]
  (let [new-index (mapv (fn [index key] (group index (key v) v)) old-index ks)
	new-indeces (apply vector new-index rhs-indeces)
	joins (derive-joins v rhs-indeces ks join-fn)]
    [new-indeces (fn [_] (on-upserts joined-model joins))]))

;;; TODO
(defn- lhs-delete [old-indeces i ks v join-fn])
(defn- lhs-upserts [old-indeces i ks vs join-fn])
(defn- lhs-deletes [old-indeces i ks vs join-fn])

(defn- lhs-view [indeces i keys join-fn joined-model]
  (reify
   View
   ;; singleton changes
   (on-upsert [_ upsertion] ((swap*! indeces lhs-upsert keys upsertion join-fn joined-model) []) nil) ;TODO - pass in views to notifier
   (on-delete [_ deletion]  (swap! indeces lhs-delete keys deletion join-fn) nil)
   ;; batch changes
   (on-upserts [_ upsertions] (swap! indeces lhs-upserts keys upsertions join-fn) nil)
