             (map clojure.string/lower-case))
       (eduction columns)))
 
+(defn make-row-translation-fn
+  "Takes columns, column names, and headers, and composes a function
+  that takes a chunk of rows and applies each data-spec translation
+  function for a given row as provided by `data-spec/translation-fns`."
+  [columns column-names headers]
+  (comp
+   (apply comp (data-spec/translation-fns columns))
+   #(select-keys % column-names)
+   (partial zipmap headers)))
+
 (defn do-bulk-import-and-validate-csv
-  "Prepares all the necessary formatting and transformation functions
+  "Prepares all the necessary formatting and translation functions
   along with other useful meta-data and initiates the insertion and
   preliminary validation of CSV data using the chunking mechanism in
   vip.data-processor.db.util/chunk-rows. Returns the context `ctx`

(defn process-row-chunks
  "Processes all the map rows in a chunk via `process-row` with the
  supplied format-rules (see `data-spec/create-format-rules` in
  `do-bulk-import-and-validate-csv`) and transforms (see
  `data-spec/translation-fns` in
  `do-bulk-import-and-validate-csv`). Inserts the row into the
  database, retries any UNIQUE id constraint-failing SQLExceptions

            :column-names column-names
            :required-header-names (required-header-names columns)
            :line-number (atom 1)
            :format-rules
            (data-spec/create-format-rules data-specs filename columns)
            :row-translation-fn
            (make-row-translation-fn columns column-names headers)}
            (chunk-rows-and-process ctx data-spec)))))

(defn-traced bulk-import-and-validate-csv
  "Bulk importing and CSV validation is done in one go, so that it can
