;; * Things like `{{x}}` (required params) get subsituted with the value of `:x`, which can be a literal used in a clause (e.g. in a clause like `value = {{x}}`) or a
;; "field filter" that handles adding the clause itself (e.g. `{{timestamp}}` might become `timestamp BETWEEN ? AND ?`).
;; * Things like `[[AND {{x}]]` are optional param. If the param (`:x`) isn't specified, the *entire* clause inside `[[...]]` is replaced with an empty string;
;; If it is specified, the value inside the curly brackets `{{x}}` is replaced as usual and the rest of the clause (`AND ...`) is included in the query as-is
;; * Things like `{{x}}` (required params) get subsituted with the value of `:x`, which can be a literal used in a
;; clause (e.g. in a clause like `value = {{x}}`) or a "field filter" that handles adding the clause itself
;; (e.g. `{{timestamp}}` might become `timestamp BETWEEN ? AND ?`).
;;
;; * Things like `[[AND {{x}]]` are optional param. If the param (`:x`) isn't specified, the *entire* clause inside
;; `[[...]]` is replaced with an empty string; If it is specified, the value inside the curly brackets `{{x}}` is
;; replaced as usual and the rest of the clause (`AND ...`) is included in the query as-is
;;
;; See the various parts of this namespace below to see how it's done.
;; Dynamic variables and record types used by the other parts of this namespace.
;; TODO - we have dynamic *driver* variables like this in several places; it probably makes more sense to see if we can share one used somewhere else instead
;; TODO - we have dynamic *driver* variables like this in several places; it probably makes more sense to see if we
;; can share one used somewhere else instead
(def^:private^:dynamic*driver*nil)
(def^:private^:dynamic*timezone*nil)
...
...
@@ -42,24 +46,27 @@
;; various record types below are used as a convenience for differentiating the different param types.
;; "Dimension" here means a "FIELD FILTER", e.g. something that expands to a clause like "some_field BETWEEN 1 AND 100"
(s/defrecord^:privateDimension[field:-FieldInstance,param]);; param is either a single param or a vector of params
;; "Dimension" here means a "FIELD FILTER", e.g. something that expands to a clause like "some_field BETWEEN 1 AND 10"
(s/defrecord^:privateDimension[field:-FieldInstance,param]); param is either single param or a vector of params
;; as in a literal date, defined by date-string S
(s/defrecord^:privateDate[s:-s/Str])
(defrecord^:privateDateRange[startend])
;; List of numbers to faciliate things like using params in a SQL `IN` clause. See the discussion in `value->number` for more details.
;; List of numbers to faciliate things like using params in a SQL `IN` clause. See the discussion in `value->number`
;; convenience for representing an *optional* parameter present in a query but whose value is unspecified in the param values.
;; convenience for representing an *optional* parameter present in a query but whose value is unspecified in the param
;; values.
(defrecord^:privateNoValue[])
;; various schemas are used to check that various functions return things in expected formats
;; TAGS in this case are simple params like {{x}} that get replaced with a single value ("ABC" or 1) as opposed to a "FieldFilter" clause like Dimensions
;; TAGS in this case are simple params like {{x}} that get replaced with a single value ("ABC" or 1) as opposed to a
;; "FieldFilter" clause like Dimensions
(def^:privateTagParam
"Schema for values passed in as part of the `:template_tags` list."
{(s/optional-key:id)su/NonBlankString; this is used internally by the frontend
...
...
@@ -97,13 +104,13 @@
(s/optional-key:replacement-snippet)s/Str; allowed to be blank if this is an optional param
;; TODO - if V is `nil` *on purpose* this still won't give us a query like `WHERE field = NULL`. That kind of query shouldn't be possible from the frontend anyway
;; TODO - if V is `nil` *on purpose* this still won't give us a query like `WHERE field = NULL`. That
;; kind of query shouldn't be possible from the frontend anyway
;; These functions combine the info from the other 3 stages (Param Info Resolution, Param->SQL Substitution, and Query Parsing) and create a sequence of maps
;; containing param details that has all the information needed to do SQL substituion. This sequence is returned in the same order as params encountered in the
;; These functions combine the info from the other 3 stages (Param Info Resolution, Param->SQL Substitution, and Query
;; Parsing) and create a sequence of maps containing param details that has all the information needed to do SQL
;; substituion. This sequence is returned in the same order as params encountered in the
;;
;; original query, making passing prepared statement args simple
;; These functions take the information about parameters from the Params Details List functions and then convert the original SQL Query into a SQL query with
;; appropriate subtitutions and a sequence of prepared statement args
;; These functions take the information about parameters from the Params Details List functions and then convert the
;; original SQL Query into a SQL query with appropriate subtitutions and a sequence of prepared statement args