       (reset! called? true)
       (qp query))))
 
-(defn- process-structured [{:keys [driver], :as query}]
+
+;; +------------------------------------------------------------------------------------------------------------------------+
+;; |                                                     QUERY PROCESSOR                                                    |
+;; +------------------------------------------------------------------------------------------------------------------------+
+
+
+;; The way these functions are applied is actually straight-forward; it matches the middleware pattern used by Compojure.
+;;
+;; (defn- qp-middleware-fn [qp]
+;;   (fn [query]
+;;     (do-some-postprocessing (qp (do-some-preprocessing query)))))
+;;
+;; Each query processor function is passed a single arg, QP, and returns a function that accepts a single arg, QUERY.
+;;
+;; This returned function *pre-processes* QUERY as needed, and then passes it to QP.
+;; The function may then *post-process* the results of (QP QUERY) as neeeded, and returns the results.
+;;
+;; Many functions do both pre and post-processing; this middleware pattern allows them to return closures that maintain some sort of
+;; internal state. For example, cumulative-sum can determine if it needs to perform cumulative summing, and, if so, modify the query
+;; before passing it to QP, and modify the results of that call.
+;;
+;; For the sake of clarity, functions are named with the following convention:
+;; *  Ones that only do pre-processing are prefixed with pre-
+;; *  Ones that only do post-processing are prefixed with post-
+;; *  Ones that do both aren't prefixed
+;;
+;; The <<- (reverse-threading macro) is used below for clarity.
+;; Pre-processing happens from top-to-bottom, i.e. the QUERY passed to the function returned by POST-ADD-ROW-COUNT-AND-STATUS is the
+;; query as modified by PRE-EXPAND.
+;;
+;; Pre-processing then happens in order from bottom-to-top; i.e. POST-ANNOTATE gets to modify the results, then LIMIT, then CUMULATIVE-SUM, etc.
+
+
+(defn process
+  "Process a QUERY and return the results."
+  [driver query]
+  (when-not *disable-qp-logging*
+    (log/debug (u/format-color 'blue "\nQUERY: 😎\n%s" (u/pprint-to-str query))))
   (let [driver-process-query      (:process-query driver)
         driver-wrap-process-query (or (:process-query-in-context driver)
                                       (fn [qp] qp))]

    (qp query)))


;; +------------------------------------------------------------------------------------------------------------------------+
;; |                                                     QUERY PROCESSOR                                                    |
;; +------------------------------------------------------------------------------------------------------------------------+


;; The way these functions are applied is actually straight-forward; it matches the middleware pattern used by Compojure.
;;
;; (defn- qp-middleware-fn [qp]
;;   (fn [query]
;;     (do-some-postprocessing (qp (do-some-preprocessing query)))))
;;
;; Each query processor function is passed a single arg, QP, and returns a function that accepts a single arg, QUERY.
;;
;; This returned function *pre-processes* QUERY as needed, and then passes it to QP.
;; The function may then *post-process* the results of (QP QUERY) as neeeded, and returns the results.
;;
;; Many functions do both pre and post-processing; this middleware pattern allows them to return closures that maintain some sort of
;; internal state. For example, cumulative-sum can determine if it needs to perform cumulative summing, and, if so, modify the query
;; before passing it to QP, and modify the results of that call.
;;
;; For the sake of clarity, functions are named with the following convention:
;; *  Ones that only do pre-processing are prefixed with pre-
;; *  Ones that only do post-processing are prefixed with post-
;; *  Ones that do both aren't prefixed
;;
;; The <<- (reverse-threading macro) is used below for clarity.
;; Pre-processing happens from top-to-bottom, i.e. the QUERY passed to the function returned by POST-ADD-ROW-COUNT-AND-STATUS is the
;; query as modified by PRE-EXPAND.
;;
;; Pre-processing then happens in order from bottom-to-top; i.e. POST-ANNOTATE gets to modify the results, then LIMIT, then CUMULATIVE-SUM, etc.

(defn- wrap-guard-multiple-calls
  "Throw an exception if a QP function accidentally calls (QP QUERY) more than once."
  [qp]

          annotate/post-annotate
          pre-log-query
          wrap-guard-multiple-calls
          driver-process-query) (assoc query
                                       :driver driver))))
