The Query Processor is responsible for translating the Metabase Query Language into HoneySQL SQL forms.
The Query Processor is responsible for translating the Metabase Query Language into HoneySQL SQL forms.
How many levels deep are we into nested queries? (0 = top level.) We keep track of this so we know what level to find referenced aggregations (otherwise something like [:aggregation 0] could be ambiguous in a nested query). Each nested query increments this counter by 1.
How many levels deep are we into nested queries? (0 = top level.) We keep track of this so we know what level to find referenced aggregations (otherwise something like [:aggregation 0] could be ambiguous in a nested query). Each nested query increments this counter by 1.
The outer query currently being processed.
(This is only used to power [:aggregation <index>]
and expression references, because they need to be able to find
the corresponding clauses outside of where they're being processed.)
The outer query currently being processed. (This is only used to power `[:aggregation <index>]` and expression references, because they need to be able to find the corresponding clauses outside of where they're being processed.)
The alias, if any, that should be used to qualify Fields when building the HoneySQL form, instead of defaulting to
schema + Table name. Used to implement things like :joined-field
s.
The alias, if any, that should be used to qualify Fields when building the HoneySQL form, instead of defaulting to schema + Table name. Used to implement things like `:joined-field`s.
(->honeysql driver x)
Return an appropriate HoneySQL form for an object. Dispatches off both driver and either clause name or object class making this easy to override in any places needed for a given driver.
Return an appropriate HoneySQL form for an object. Dispatches off both driver and either clause name or object class making this easy to override in any places needed for a given driver.
(apply-top-level-clause driver top-level-clause honeysql-form query)
Implementations of this methods define how the SQL Query Processor handles various top-level MBQL clauses. Each
method is called when a matching clause is present in query
, and should return an appropriately modified version
of honeysql-form
. Most drivers can use the default implementations for all of these methods, but some may need to
override one or more (e.g. SQL Server needs to override this method for the :limit
clause, since T-SQL uses TOP
instead of LIMIT
).
Implementations of this methods define how the SQL Query Processor handles various top-level MBQL clauses. Each method is called when a matching clause is present in `query`, and should return an appropriately modified version of `honeysql-form`. Most drivers can use the default implementations for all of these methods, but some may need to override one or more (e.g. SQL Server needs to override this method for the `:limit` clause, since T-SQL uses `TOP` instead of `LIMIT`).
(as driver field-clause)
(as driver field-clause unique-name-fn)
Generate HoneySQL for an AS
form (e.g. <form> AS <field>
) using the name information of a field-clause
. The
HoneySQL representation of on AS
clause is a tuple like [<form> <alias>]
.
In some cases where the alias would be redundant, such as unwrapped field literals, this returns the form as-is.
(as [:field-literal "x" :type/Text]) ;; -> <compiled-form> ;; -> SELECT "x"
(as [:datetime-field [:field-literal "x" :type/Text] :month]) ;; -> [<compiled-form> :x] ;; -> SELECT date_extract("x", 'month') AS "x"
As with field-clause->alias
, you can pass a unique-name-fn
to generate unique names for a sequence of aliases,
such as for a SELECT
clause.
Generate HoneySQL for an `AS` form (e.g. `<form> AS <field>`) using the name information of a `field-clause`. The HoneySQL representation of on `AS` clause is a tuple like `[<form> <alias>]`. In some cases where the alias would be redundant, such as unwrapped field literals, this returns the form as-is. (as [:field-literal "x" :type/Text]) ;; -> <compiled-form> ;; -> SELECT "x" (as [:datetime-field [:field-literal "x" :type/Text] :month]) ;; -> [<compiled-form> :x] ;; -> SELECT date_extract("x", 'month') AS "x" As with `field-clause->alias`, you can pass a `unique-name-fn` to generate unique names for a sequence of aliases, such as for a `SELECT` clause.
(build-honeysql-form driver {inner-query :query})
Inputs: [driver {inner-query :query} :- su/Map]
Build the HoneySQL form we will compile to SQL and execute.
Inputs: [driver {inner-query :query} :- su/Map] Build the HoneySQL form we will compile to SQL and execute.
(cast-unix-timestamp-field-if-needed driver field field-identifier)
Wrap a field-identifier
in appropriate HoneySQL expressions if it refers to a UNIX timestamp Field.
Wrap a `field-identifier` in appropriate HoneySQL expressions if it refers to a UNIX timestamp Field.
(current-datetime-fn driver)
HoneySQL form that should be used to get the current datetime
(or equivalent). Defaults to :%now
.
HoneySQL form that should be used to get the current `datetime` (or equivalent). Defaults to `:%now`.
(date driver unit field-or-value)
Return a HoneySQL form for truncating a date or timestamp field or value to a given resolution, or extracting a date component.
Return a HoneySQL form for truncating a date or timestamp field or value to a given resolution, or extracting a date component.
(field->alias driver field)
Return the string alias that should be used to for field
, an instance of the Field model, i.e. in an AS
clause.
The default implementation calls :name
, which returns the unqualified name of the Field.
Return nil
to prevent field
from being aliased.
Return the string alias that should be used to for `field`, an instance of the Field model, i.e. in an `AS` clause. The default implementation calls `:name`, which returns the *unqualified* name of the Field. Return `nil` to prevent `field` from being aliased.
(field->identifier driver field)
Return a HoneySQL form that should be used as the identifier for field
, an instance of the Field model. The default
implementation returns a keyword generated by from the components returned by field/qualified-name-components
.
Other drivers like BigQuery need to do additional qualification, e.g. the dataset name as well. (At the time of this
writing, this is only used by the SQL parameters implementation; in the future it will probably be used in more
places as well.)
Return a HoneySQL form that should be used as the identifier for `field`, an instance of the Field model. The default implementation returns a keyword generated by from the components returned by `field/qualified-name-components`. Other drivers like BigQuery need to do additional qualification, e.g. the dataset name as well. (At the time of this writing, this is only used by the SQL parameters implementation; in the future it will probably be used in more places as well.)
(field-clause->alias driver field-clause)
(field-clause->alias driver field-clause unique-name-fn)
Inputs: ([driver field-clause] [driver field-clause :- mbql.s/Field unique-name-fn :- (s/pred fn?)])
Generate HoneySQL for an approriate alias (e.g., for use with SQL AN
) for a Field clause of any type, or nil
if
the Field should not be aliased (e.g. if field->alias
returns nil
).
Optionally pass a state-maintaining unique-name-fn
, such as mbql.u/unique-name-generator
, to guarantee that each
alias generated is unique when generating a sequence of aliases, such as for a SELECT
clause.
Inputs: ([driver field-clause] [driver field-clause :- mbql.s/Field unique-name-fn :- (s/pred fn?)]) Generate HoneySQL for an approriate alias (e.g., for use with SQL `AN`) for a Field clause of any type, or `nil` if the Field should not be aliased (e.g. if `field->alias` returns `nil`). Optionally pass a state-maintaining `unique-name-fn`, such as `mbql.u/unique-name-generator`, to guarantee that each alias generated is unique when generating a sequence of aliases, such as for a `SELECT` clause.
(honeysql-form->sql+args driver honeysql-form)
Inputs: [driver honeysql-form :- su/Map]
Convert honeysql-form
to a vector of SQL string and params, like you'd pass to JDBC.
Inputs: [driver honeysql-form :- su/Map] Convert `honeysql-form` to a vector of SQL string and params, like you'd pass to JDBC.
(join->honeysql driver join)
Compile a single MBQL join
to HoneySQL.
Compile a single MBQL `join` to HoneySQL.
(join-source driver join)
Generate HoneySQL for a table or query to be joined.
Generate HoneySQL for a table or query to be joined.
(mbql->native driver {inner-query :query database :database :as outer-query})
Transpile MBQL query into a native SQL statement.
Transpile MBQL query into a native SQL statement.
(quote-style driver)
Return the quoting style that should be used by HoneySQL when building a SQL
statement. Defaults to :ansi
, but other valid options are :mysql
, :sqlserver
, :oracle
, and :h2
(added in
metabase.util.honeysql-extensions
; like :ansi
, but uppercases the result).
(hsql/format ... :quoting (quote-style driver), :allow-dashed-names? true)
Return the quoting style that should be used by [HoneySQL](https://github.com/jkk/honeysql) when building a SQL statement. Defaults to `:ansi`, but other valid options are `:mysql`, `:sqlserver`, `:oracle`, and `:h2` (added in `metabase.util.honeysql-extensions`; like `:ansi`, but uppercases the result). (hsql/format ... :quoting (quote-style driver), :allow-dashed-names? true)
Alias to use for source queries, e.g.:
SELECT source.* FROM ( SELECT * FROM some_table ) source
Alias to use for source queries, e.g.: SELECT source.* FROM ( SELECT * FROM some_table ) source
(unix-timestamp->timestamp driver seconds-or-milliseconds field-or-value)
Return a HoneySQL form appropriate for converting a Unix timestamp integer field or value to an proper SQL Timestamp.
seconds-or-milliseconds
refers to the resolution of the int in question and with be either :seconds
or
:milliseconds
.
There is a default implementation for :milliseconds
the recursively calls with :seconds
and (expr / 1000)
.
Return a HoneySQL form appropriate for converting a Unix timestamp integer field or value to an proper SQL Timestamp. `seconds-or-milliseconds` refers to the resolution of the int in question and with be either `:seconds` or `:milliseconds`. There is a default implementation for `:milliseconds` the recursively calls with `:seconds` and `(expr / 1000)`.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close