 (defn add-resources!
   "Persist the given resource and associate it with the given catalog."
   [catalog-hash refs-to-resources refs-to-hashes]
-  (let [resource-values   (for [[ref resource] refs-to-resources]
-                            (resource->values catalog-hash resource (refs-to-hashes ref)))
+  (let [hashes-to-refs    (into {} (for [[ref hash] refs-to-hashes] [hash ref]))
+        resource-hashes   (set (keys hashes-to-refs))
+        persisted?        (resources-exist? resource-hashes)
+        resource-values   (for [[ref resource] refs-to-resources
+                                :let [hash (refs-to-hashes ref)]]
+                            (resource->values catalog-hash resource hash (persisted? hash)))
         lookup-table      [[:resource "INSERT INTO catalog_resources (catalog,resource,type,title,tags,exported,sourcefile,sourceline) VALUES (?,?,?,?,?,?,?,?)"]
                            [:parameters "INSERT INTO resource_params (resource,name,value) VALUES (?,?,?)"]]]
     (sql/transaction

  1. Each key corresponds to a table, and each value is a list of rows
  2. The mapping of keys and values to table names and columns is done
     by `add-resources!`"
  [catalog-hash {:keys [type title exported parameters tags file line] :as resource} resource-hash]
  {:pre  [(every? string? #{catalog-hash type title})]
   :post [(= (set (keys %)) #{:resource :parameters})]}
  (let [persisted?    (resource-exists? resource-hash)
        values        {:resource [[catalog-hash resource-hash type title (to-jdbc-varchar-array tags) exported file line]]
                       :parameters []}]

    (if persisted?
      values

  (pr-str [type title (sort tags) exported file line (sort parameters)]))

(defn- resource->values
  "Given a catalog-hash, a resource, and a truthy value indicating
  whether or not the indicated resource already exists somewhere in
  the database, return a map representing the set of database rows
  pending insertion.

  The result map has the following format:

