Variables is where part of an sql string can be compiled in advance with placeholders in it, only the missing pieces are produced at run time and filled into placeholders.

Variables is also the way to allow dynamic queries because the values of such variables are evaluated at run time.

Variable getters

To use variables, place a Clojure symbol inside any Walkable S-expression, which means in a pseudo column or an aggregator’s :formula or in a root or join’s filter.

  • Registry

[{:key :person/age
  :type :pseudo-column
  :formula [:- 'current-year :person/yob]} (1)
 ;; Of course, you must provide how that variable is computed:
 {:key 'current-year
  :type :variable
  :compute  (fn [env] (2)
1 a variable use inside a formula
2 Do you remember the weird env hash-map we talked about in Overview? All getter functions will have that env as the argument. The function in this example just returns a hard-coded value (2019) - that’s boring, I know - but you can be more creative than I am.

with the above definition, the pseudo column :person/age will be the value of the variable current-year minus the true column :person/yob.

You can have as many variables in your expresions as you like, as long as you have written down how to compute all of them in the registry:

  • Registry

[{:key 'foo
  :type :variable
  :compute  (fn [env] ...)}
 {:key 'bar
  :type :variable
  :cached? true (1)
  :compute  (fn [env] ...)}
 {:key 'braca/buzz (2)
  :type :variable
  :compute  (fn [env] ...)}]
1 A variable’s value can be cached throughout the request by the keyword :cached?
2 It’s totally fine to use namespaced symbols for your variables.