            (.setComparisonOperator (enum-op operator))
            (.setAttributeValueList (mapv clj-val->db-val vals)))))
      conditions)))
+
+(defn query-request
+  "Implementation detail"
+  [table prim-key-conds
+   & [{:keys [last-prim-kvs query-filter span-reqs return index order limit consistent?
+              return-cc?] :as opts
+       :or {order :asc}}]]
+  (doto-cond [g (QueryRequest.)]
+    :always (.setTableName        (name table))
+    :always (.setKeyConditions    (query|scan-conditions prim-key-conds))
+    :always (.setScanIndexForward (case order :asc true :desc false))
+    last-prim-kvs   (.setExclusiveStartKey
+                     (clj-item->db-item last-prim-kvs))
+    query-filter    (.setQueryFilter (query|scan-conditions query-filter))
+    limit           (.setLimit     (int g))
+    index           (.setIndexName      g)
+    consistent?     (.setConsistentRead g)
+    (coll?* return) (.setAttributesToGet (mapv name return))
+    return-cc? (.setReturnConsumedCapacity (utils/enum :total))
+    (and return (not (coll?* return)))
+    (.setSelect (utils/enum return))))
 
 (defn query
   "Retrieves items from a table (indexed) with options:

  (letfn [(run1 [last-prim-kvs]
            (as-map
             (.scan (db-client client-opts)
               (doto-cond [g (ScanRequest.)]
                 :always (.setTableName (name table))
                 attr-conds      (.setScanFilter        (query|scan-conditions g))
                 last-prim-kvs   (.setExclusiveStartKey
                                  (clj-item->db-item last-prim-kvs))
                 limit           (.setLimit             (int g))
                 total-segments  (.setTotalSegments     (int g))
                 segment         (.setSegment           (int g))
                 (coll?* return) (.setAttributesToGet (mapv name return))
                 return-cc? (.setReturnConsumedCapacity (utils/enum :total))
                 (and return (not (coll?* return)))
                 (.setSelect (utils/enum return))))))]
    (merge-more run1 span-reqs (run1 last-prim-kvs))))

(defn scan-parallel

                  {<attr> <expected-value> ...}
                  {<attr> false ...} ; Attribute must not exist"
  [client-opts table item & [{:keys [return expected return-cc?]
                              :as   opts}]]
  (as-map
   (.putItem (db-client client-opts)
     (put-item-request table item opts))))

(defn- attribute-updates
  "{<attr> [<action> <value>] ...} -> {<attr> AttributeValueUpdate ...}"
