       (map :row)))
 
 (defn fetch-genes [field-id values]
-  (into #{} (field-genes field-id values)))
+  (into (sorted-set) (field-genes field-id values)))
+
+; fetch-indexed doesn't cache, and it's unclear
+; if we should cache the indexed fields during 'restrict'.
+; h2 also has caches, so it might be better to rely on them,
+; simply doing the query again if we need it. 
+
+; Otherwise, we might want to inform the cache of what columns are
+; required later during 'restrict', or in 'project', so
+; we know if they should be cached.
 
 (defn fetch-indexed [fields field values]
   (let [field-id (fields field)]
     (cond
-      (has-position? field-id) #{})
+      (has-position? field-id) #{}) ; XXX fix this!
       (has-genes? field-id) (fetch-genes field-id values)))
 
+; XXX Look at memory use of pulling :gene field. If it's not
+; interned, it could be expensive.
+
+; XXX Add some param guards, esp. unknown field.
 (defn eval-sql [{[from] :from where :where select :select :as exp}]
   (let [{dataset-id :id N :rows} (dataset-by-name from :id :rows)
         fields (into {} (fetch-field-ids dataset-id
                                          (into (collect-fields where) select)))
-        fetch (partial fetch-rows fields (atom {}))]
+        cache (atom {})
+        fetch (fn [rows field] (fetch-rows cache rows (fields field)))]
     ; XXX project, perhaps in sqleval
-  (evaluate (range N) {:fetch fetch
+  (evaluate (apply sorted-set (range N)) {:fetch fetch
                        :fetch-indexed (partial fetch-indexed fields)
                        :indexed? (partial has-index? fields)} exp)))
 
+
+;
+;
+;
+;
+;
+;
 
 ; Each req is a map of
 ;  :table "tablename"


;
;
;

(def ^:private field-ids-query
  (cached-statement

        (update-in new-cache [:codes] update-codes-cache field-id missing new-cache))
       cache)))

(defmulti fetch-rows
  (fn [cache rows field-id]
    (cond
      (has-genes? field-id) :gene
      (has-position? field-id) :position
      :else :binned)))

; return fn of rows->vals
(defmethod fetch-rows :binned [cache rows field-id]
  (swap! cache update-in [field-id] update-cache field-id rows)
  (let [f (@cache field-id)
        getter (match [(:codes f)]
                      ; XXX cast to int here is pretty horrible.
                      ; Really calls for an int array bin in h2.
