(configuration)
Get global logging configuration
(context)
Get global logging context.
(effective-ns-logger a-namespace)
Get the logger that will be used for the namespace named by a-namespace
.
(for-ns ns out & [{:keys [additive level], :or {additive true, level Level/INFO}}])
Create separate logger for a given namespace to fork out some logs.
(logger-name a-namespace)
Get string name from symbol or ns
(messages)
Get the list of currently buffered log entries, from most-recent to oldest.
(->NumericWrapper num-str num-value)
Positional factory function for class metabase.formatter.NumericWrapper.
Schema used for functions that operate on pulse card contents and their attachments
(coerce-bignum-to-int row)
Graal polyglot system (not the JS machine itself, the polyglot system) is not happy with BigInts or BigDecimals. For more information, this is the GraalVM issue, open a while oracle/graal#2737 Because of this unfortunately they all have to get smushed into normal ints and decimals in JS land.
(create-formatter timezone-id col visualization-settings)
Inputs: [timezone-id :- [:maybe :string] col visualization-settings] Return: :any
Create a formatter for a column based on its timezone, column metadata, and visualization-settings
(format-geographic-coordinates lon-or-lat v)
Format longitude/latitude values as 0.00000000° N|S|E|W
(format-number n)
(format-number value column viz-settings)
Inputs: ([n :- number?] [value column viz-settings]) Return: (ms/InstanceOfClass NumericWrapper)
Format a number n
and return it as a NumericWrapper; this type is used to do special formatting in other
pulse.render
namespaces.
(format-temporal-str timezone-id temporal-str col)
(format-temporal-str timezone-id temporal-str col viz-settings)
Reformat a temporal literal string by combining time zone, column, and viz setting information to create a final desired output format.
(graphing-column-row-fns card data)
Return a pair of [get-x-axis get-y-axis]
functions that can be used to get the x-axis and y-axis values in a row,
or columns, respectively.
(map->NumericWrapper m__7972__auto__)
Factory function for class metabase.formatter.NumericWrapper, taking a map of keywords to field values.
(number-formatter {:keys [semantic_type effective_type base_type], col-id :id, field-ref :field_ref, col-name :name, :as _column} viz-settings)
Return a function that will take a number and format it according to its column viz settings. Useful to compute the format string once and then apply it over many values.
(row-preprocess x-axis-fn y-axis-fn rows)
Preprocess rows.
- Removes any rows that have a nil value for the
x-axis-fn
ORy-axis-fn
- Normalizes bigints and bigdecs to ordinary sizes
(temporal-string? s)
Returns true
if the string s
is parseable as a datetime.
(temporal-string? "asdf")
-> false
(temporal-string? "2020-02-02")
-> true
(->v2-path path)
Inputs: [path :- [:or [:re path-regex-v1] [:re path-regex-v2]]] Return: [:vector [:re path-regex-v2]]
Takes either a v1 or v2 path, and translates it into one or more v2 paths.
A permissions path that's guaranteed to be a v1 data-permissions path
A permission path.
Schema for a permissions path with a valid format.
(classify-data-path data-path)
Inputs: [data-path :- DataPath] Return: DataKind
Classifies data path permissions [[metabase.models.permissions/DataPath]] into a [[metabase.models.permissions/DataKind]]
(classify-path path)
Inputs: [path :- Path] Return: Kind
Classifies a permission [[metabase.models.permissions/Path]] into a [[metabase.models.permissions/Kind]], or throws.
(escape-path-component s)
Escape slashes in something that might be passed as a string part of a permissions path (e.g. DB schema name or Collection name).
(escape-path-component "a/b") ;-> "a\/b"
Regex for a valid character for a name that appears in a permissions path (e.g. a schema name or a Collection name).
Character is valid if it is either:
1. Any character other than a slash
2. A forward slash, escaped by a backslash: \/
3. A backslash escaped by a backslash: \\
Regex for a valid permissions path. The [[metabase.util.regex/rx]] macro is used to make the big-and-hairy regex somewhat readable.
Regex for a valid permissions path. built with [[metabase.util.regex/rx]] to make the big-and-hairy regex somewhat readable. Will not match:
- a v1 data path like "/db/1" or "/db/1/"
- a block path like "block/db/2/"
Paths starting with /db/ is a DATA ACCESS permissions path
Paths that do not start with /db/ (e.g. /download/db/...) do not involve granting data access, and are not data-permissions. They are other kinds of paths, for example: see [[download-permissions-rx]].
(valid-path-format? path)
Is path
a string with a valid permissions path format? This is a less strict version of [[valid-path?]] which
just checks that the path components contain alphanumeric characters or dashes, separated by slashes
This should be used for schema validation in most places, to preserve downgradability when new permissions paths are
added.
(valid-path? path)
Is path
a valid, known permissions path?
Schema for searchable models
Set of all valid models to search for.
(query-model-set search-ctx)
Inputs: [search-ctx :- SearchContext] Return: [:set SearchableModel]
Queries all models with respect to query for one result to see if we get a result or not
(search search-ctx)
Inputs: [search-ctx :- SearchContext] Return: :any
Builds a search query that includes all the searchable entities and runs it.
(search-context {:keys [archived created-at created-by current-user-id current-user-perms last-edited-at last-edited-by limit models filter-items-in-personal-collection offset search-string model-ancestors? table-db-id search-native-query verified]})
Inputs: [{:keys [archived created-at created-by current-user-id current-user-perms last-edited-at last-edited-by limit models filter-items-in-personal-collection offset search-string model-ancestors? table-db-id search-native-query verified]} :- :metabase.search.impl/search-context.input] Return: :any
Create a new search context that you can pass to other functions like [[search]].
(infer-model {{database-id :id, :keys [models]} :database, :keys [user_prompt], :as context})
Find the model in the db that best matches the prompt. Return nil if no good model found.
(infer-native-sql-query {{database-id :id} :database, :keys [user_prompt prompt_template_versions], :as context})
Given a database and user prompt, determine a sql query to answer my question.
(infer-sql {:keys [model user_prompt], :as context})
Given a model and prompt, attempt to generate a native dataset.
(infer-viz {sql :sql, :as context})
Determine an 'interesting' visualization for this data.
(match-best-model {{database-id :id, :keys [models]} :database, :keys [user_prompt]})
Find the model in the db that best matches the prompt using embedding matching.
(extract-and-sync-sample-database!)
Adds the sample database as a Metabase DB if it doesn't already exist. If it does exist in the app DB, we update its details.
(update-sample-database-if-needed!)
(update-sample-database-if-needed! sample-db)
Update the path to the sample database DB if it exists in case the JAR has moved.
(apply-json-query object jq-query)
Executes a jq query on [[object]].
(cached-value unique-key value-thunk)
Get a cached value from the [[misc-value-cache]] using a unique-key
if it already exists. If it does not exist,
calculate the value using value-thunk
, cache it, then return it.
unique-key
must be unique app-wide. Something like
[::cast-values table-id]
is a good key.
(check-actions-enabled! action-or-id)
Throws an appropriate error if actions are unsupported or disabled for the database of the action's model, otherwise returns nil.
(check-actions-enabled-for-database! {db-settings :settings, db-id :id, driver :engine, db-name :name, :as db})
Throws an appropriate error if actions are unsupported or disabled for a database, otherwise returns nil.
(execute-action! action request-parameters)
Inputs: [action request-parameters] Return: :any
Execute the given action with the given parameters of shape `{ }.
(execute-dashcard! dashboard-id dashcard-id request-parameters)
Inputs: [dashboard-id :- :metabase.lib.schema.id/dashboard dashcard-id :- :metabase.lib.schema.id/dashcard request-parameters :- [:maybe [:map-of :string :any]]] Return: :any
Execute the given action in the dashboard/dashcard context with the given parameters of shape `{ }.
(fetch-values action request-parameters)
Fetch values to pre-fill implicit action execution - custom actions will return no values.
Must pass in parameters of shape {<parameter-id> <value>}
for primary keys.
Error type for SQL incorrect value type.
(perform-action!* driver action database arg-map)
Multimethod for doing an Action. The specific action
is a keyword like :row/create
or :bulk/create
; the shape
of arg-map
depends on the action being performed. [[action-arg-map-spec]] returns the appropriate spec to use to
validate the args for a given action. When implementing a new action type, be sure to implement both this method
and [[action-arg-map-spec]].
At the time of this writing Actions are performed with either POST /api/action/:action-namespace/:action-name
,
which passes in the request body as args-map
directly, or POST /api/action/:action-namespace/:action-name/:table-id
, which passes in an args-map
like
{:table-id <table-id>, :arg <request-body>}
The former endpoint is currently used for the various :row/*
Actions while the version with :table-id
as part of
the route is currently used for :bulk/*
Actions.
DON'T CALL THIS METHOD DIRECTLY TO PERFORM ACTIONS -- use [[perform-action!]] instead which does normalization, validation, and binds Database-local values.
Error type for SQL foreign key constraint violation.
Error type for SQL not null constraint violation.
Error type for SQL unique constraint violation.
(metabase-info)
Make it easy for the user to tell us what they're using
(system-info)
System info we ask for for bug reports
Maps DB name of the moderated item type to the model symbol (used for t2/select and such)
Schema enum of the acceptable values for the moderated_item_type
column
(moderation-reviews-for-items items)
Hydrate moderation reviews onto a seq of items. All are cards or the nils that end up here on text dashboard cards. In the future could have dashboards here as well.
(moderation-user-details moderation-reviews)
User details on moderation reviews
For testing purposes, we'd like to control whether the analyze and field values steps of sync are run synchronously, or not at all. In production this should always be asynchronous, so users can use the table earlier.
The keyword of the auto-incrementing PK column.
The lower-case name of the auto-incrementing PK column. The actual name in the database could be in upper-case.
(based-on-upload cards)
Add based_on_upload= to a card if: - the card is a model - the query is a GUI query, and does not have any joins - the base table of the card is based on an upload - the user has permissions to upload to the table - uploads are enabled Otherwise based_on_upload is nil.
(can-create-upload? db schema-name)
Returns true if the user can upload to the given database and schema, and false otherwise.
(create-csv-upload! {:keys [collection-id filename file db-id schema-name table-prefix]})
Inputs: [{:keys [collection-id filename file db-id schema-name table-prefix]} :- [:map [:collection-id [:maybe ms/PositiveInt]] [:filename :string] [:file (ms/InstanceOfClass File)] [:db-id ms/PositiveInt] [:schema-name {:optional true} [:maybe :string]] [:table-prefix {:optional true} [:maybe :string]]]] Return: :any
Main entry point for CSV uploading.
What it does:
- throws an error if the user cannot upload to the given database and schema (see [[can-create-upload-error]] for reasons)
- throws an error if the user has write permissions to the given collection
- detects the schema of the CSV file
- inserts the data into a new table with a unique name, along with an extra auto-generated primary key column
- syncs and scans the table
- creates a model which wraps the table
Requires that current-user dynamic vars in [[metabase.api.common]] are bound as if by API middleware (this is needed for QP permissions checks). Returns the newly created model. May throw validation, permimissions, or DB errors.
Args:
collection-id
: the ID of the collection to create the model in.nil
means the root collection.filename
: the name of the file being uploaded.file
: the file being uploaded.db-id
: the ID of the database to upload to.schema-name
: the name of the schema to create the table in (optional).table-prefix
: the prefix to use for the table name (optional).
(current-database)
The database being used for uploads (as per the uploads-database-id
setting).
(delete-upload! table & {:keys [archive-cards?]})
Delete the given table from both the app-db and the customer database.
(model-hydrate-based-on-upload models)
Inputs: [models :- [:sequential [:map [:dataset_query [:maybe ms/Map]] [:query_type [:maybe [:or :string :keyword]]] [:table_id [:maybe ms/PositiveInt]] [:is_upload {:optional true} [:maybe :any]]]]] Return: :any
Batch hydrates :based_on_upload
for each item of models
. Assumes each item of model
represents a model.
(table-identifier {:keys [schema name], :as _table})
Inputs: [{:keys [schema name], :as _table} :- [:map [:schema {:optional true} [:maybe :string]] [:name :string]]] Return: :any
Returns a string that can be used as a table identifier in SQL, including a schema if provided.
The :action values supported by [[update-csv!]]
(update-csv! {:keys [file table-id action]})
Inputs: [{:keys [file table-id action]} :- [:map [:table-id ms/PositiveInt] [:file (ms/InstanceOfClass File)] [:action update-action-schema]]] Return: :any
Main entry point for updating an uploaded table with a CSV file. This will create an auto-incrementing primary key (auto-pk) column in the table for drivers that supported uploads before auto-pk columns were introduced by metabase#36249, if it does not already exist.
(definition instance)
Return the relevant parts of a given entity's definition. Relevant parts are those that carry semantic meaning, and especially context-bearing forms.
(related entity)
Return related entities.
(automagic-analysis entity opts)
Create a transient dashboard analyzing given entity.
This function eventually calls out to automagic-dashboard
with two primary arguments:
- The item to be analyzed. This entity is a 'decorated' version of the raw input that has been
passed through the
->root
function, which is an aggregate including the original entity, its source, what dashboard template categories to apply, etc. - Additional options such as how many cards to show, a cell query (a drill through), etc.
(candidate-tables database)
(candidate-tables database schema)
Return a list of tables in database with ID database-id
for which it makes sense
to generate an automagic dashboard. Results are grouped by schema and ranked
acording to interestingness (both schemas and tables within each schema). Each
schema contains up to max-candidate-tables
tables.
Tables are ranked based on how specific dashboard template has been used, and the number of fields. Schemes are ranked based on the number of distinct entity types and the interestingness of tables they contain (see above).
(comparison-dashboard dashboard left right opts)
Create a comparison dashboard based on dashboard dashboard
comparing subsets of
the dataset defined by segments left
and right
.
(create-collection! title description parent-collection-id)
Create and return a new collection.
(dashboard transform-name)
Create a (transient) dashboard for transform named transform-name
.
(get-collection collection-name)
(get-collection collection-name location)
Get collection named collection-name
. If no location is given root collection for automatically
generated transforms is assumed (see get-or-create-root-container-collection!
).
(get-dashboard-template path)
Get dashboard template at path path
.
(get-dashboard-templates prefix)
Get all dashboard templates with prefix prefix
.
prefix is greedy, so ["table"] will match table/TransactionTable.yaml, but not
table/TransactionTable/ByCountry.yaml
(get-or-create-root-container-collection)
Get or create container collection for automagic dashboards in the root collection.
(create-token!)
Create and set a new setup token, if one has not already been created. Returns the newly created token.
(has-user-setup)
A value that is true iff the metabase instance has one or more users registered.
has-user-setup
is a :boolean
Setting. You can get its value by calling:
(has-user-setup)
and set its value by calling:
(has-user-setup! <new-value>)
You can also set its value with the env var MB_HAS_USER_SETUP
.
Clear its value by calling:
(has-user-setup! nil)
Its default value is nil
.
(has-user-setup! new-value)
A value that is true iff the metabase instance has one or more users registered.
has-user-setup
is a :boolean
Setting. You can get its value by calling:
(has-user-setup)
and set its value by calling:
(has-user-setup! <new-value>)
You can also set its value with the env var MB_HAS_USER_SETUP
.
Clear its value by calling:
(has-user-setup! nil)
Its default value is nil
.
(setup-token)
A token used to signify that an instance has permissions to create the initial User. This is created upon the first launch of Metabase, by the first instance; once used, it is cleared out, never to be used again.
setup-token
is a :string
Setting. You can get its value by calling:
(setup-token)
and set its value by calling:
(setup-token! <new-value>)
You can also set its value with the env var MB_SETUP_TOKEN
.
Clear its value by calling:
(setup-token! nil)
Its default value is nil
.
(token-match? token)
Function for checking if the supplied string matches our setup token.
Returns boolean true
if supplied token matches the setup token, false
otherwise.
Malli schema for an event topic keyword.
(object->metadata object)
Determine metadata, if there is any, for given object
.
Expand the object when we need more metadata.
(publish-event! topic event)
'Publish' an event by calling [[publish-event!]] with a [[Topic]] and an event
map, whose contents vary
based on their topic
. These calls return the original event
object passed in, to support chaining.
(events/publish-event! :event/database-create {:object database :user-id api/*current-user-id*})
'Subscribe' to an event by add a Methodical method implementation. Since this uses the [[methodical/do-method-combination]], all multiple method implementations can be called for a single invocation. The order is indeterminate, but return value is ignored.
Don't write method implementations for the event names themselves, e.g. :event/database-create
, because these will
stomp on other methods with the same key:
;; bad! If someone else writes a method for `:event/database-create`, it will stomp on this
(methodical/defmethod events/publish-event! :event/database-create
[topic event]
...)
Instead, derive the event from another key, and write a method for that
;; Good
(derive :event/database-create ::events)
(methodical/defmethod events/publish-event! ::events
[topic event]
...)
The schema for each event topic are defined in metabase.events.schema
, makes sure to keep it up-to-date
if you're working on a new event topic or updating an existing one.
publish-event! is defined in [[metabase.events]] (metabase/events.clj:60).
#object[metabase.util.methodical.null_cache.NullCache 0xef85757 "metabase.util.methodical.null_cache.NullCache@ef85757"]
It uses the method combination methodical.impl.combo.operator.OperatorMethodCombination
with the operator :do
.
#object[metabase.util.methodical.unsorted_dispatcher.UnsortedDispatcher 0x1db90b5c "metabase.util.methodical.unsorted_dispatcher.UnsortedDispatcher@1db90b5c"]
It uses the method table methodical.impl.method_table.standard.StandardMethodTable
.
These primary methods are known:
-
:metabase.events.audit-log/install-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:164) -
:metabase.events.last-login/event
, defined in [[metabase.events.last-login]] (metabase/events/last_login.clj:12) -
:metabase.events.audit-log/user-update-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:147) -
:metabase.events.sync-database/event
, defined in [[metabase.events.sync-database]] (metabase/events/sync_database.clj:13) -
:metabase.events.audit-log/metric-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:65) -
:metabase.events.audit-log/upload-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:217) -
:metabase.events.audit-log/cache-config-changed-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:224) -
:metabase.events.revision/metric-event
, defined in [[metabase.events.revision]] (metabase/events/revision.clj:53) -
:metabase.events.audit-log/settings-changed-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:199) -
:default
, defined in [[metabase.events]] (metabase/events.clj:105) -
:metabase.events.audit-log/dashboard-card-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:33) -
:metabase.events.persisted-info/event
, defined in [[metabase.events.persisted-info]] (metabase/events/persisted_info.clj:15) -
:metabase.events.view-log/dashboard-read
, defined in [[metabase.events.view-log]] (metabase/events/view_log.clj:99)It has the following documentation:
Handle processing for the dashboard read event. Logs the dashboard view as well as card views for each card on the dashboard.
-
:metabase.events.audit-log/permission-failure-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:192) -
:metabase.events.audit-log/database-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:176) -
:metabase.events.audit-log/api-key-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:209) -
:metabase.events.driver-notifications/event
, defined in [[metabase.events.driver-notifications]] (metabase/events/driver_notifications.clj:18) -
:metabase.events.audit-log/table-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:56) -
:metabase.events.audit-log/dashboard-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:25) -
:metabase.events.view-log/read-permission-failure
, defined in [[metabase.events.view-log]] (metabase/events/view_log.clj:76)It has the following documentation:
Handle processing for a generic read event notification
-
:metabase.events.audit-log/user-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:140) -
:metabase.events.audit-log/user-joined-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:154) -
:metabase.events.revision/segment-event
, defined in [[metabase.events.revision]] (metabase/events/revision.clj:62) -
:metabase.events.view-log/table-read
, defined in [[metabase.events.view-log]] (metabase/events/view_log.clj:127)It has the following documentation:
Handle processing for the table read event. Does a basic permissions check to see if the the user has data perms for the table.
-
:metabase.events.view-log/card-read-event
, defined in [[metabase.events.view-log]] (metabase/events/view_log.clj:44)It has the following documentation:
Handle processing for a generic read event notification
-
:metabase.events.recent-views/card-query-event
, defined in [[metabase.events.recent-views]] (metabase/events/recent_views.clj:37)It has the following documentation:
Handle processing for a single card query event.
-
:metabase.events.audit-log/pulse-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:93) -
:metabase.events.audit-log/segment-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:127) -
:metabase.events.revision/card-event
, defined in [[metabase.events.revision]] (metabase/events/revision.clj:36) -
:metabase.events.revision/dashboard-event
, defined in [[metabase.events.revision]] (metabase/events/revision.clj:44) -
:metabase.events.audit-log/database-update-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:183) -
:metabase.events.view-log/collection-read-event
, defined in [[metabase.events.view-log]] (metabase/events/view_log.clj:63)It has the following documentation:
Handle processing for a generic read event notification
-
:metabase.events.audit-log/card-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:17) -
:metabase.events.audit-log/alert-event
, defined in [[metabase.events.audit-log]] (metabase/events/audit_log.clj:111) -
:metabase.events.recent-views/event
, defined in [[metabase.events.recent-views]] (metabase/events/recent_views.clj:18)It has the following documentation:
Handle processing for a single event notification which should update the recent views for a user.
These aux methods are known:
:around
methods:
:default
, defined in [[metabase.events]] (metabase/events.clj:109)
Is a value of type x
assignable to a variable of type y
?
When deciding assignability, We also consider the type hierarchy. If x is assignable to z and z is a y, then x is also assignable to y. Also, if z is assignable to y and x is an z, then x is assignable to y.
(coercion-possibilities base-type)
Possible coercions for a base type, returned as a map of effective-type -> #{coercion-strategy}
(coercions_for_type base-type)
Coercions available for a type. In cljs will return a js array of strings like ["Coercion/ISO8601->Time" ...]. In clojure will return a sequence of keywords.
(declare-assignable x y)
Declare that a value of type x
assignable to a variable of type y
.
(effective-type-for-coercion coercion)
The effective type resulting from a coercion.
(field-is-type? tyype {base-type :base_type, effective-type :effective_type})
Inputs: [tyype :- :keyword {base-type :base_type, effective-type :effective_type} :- SnakeCasedField] Return: :any
True if a Metabase Field
instance has a temporal base or semantic type, i.e. if this Field represents a value
relating to a moment in time.
(is-coercible-from? coercion-strategy base-type)
Whether coercion-strategy
is allowed for base-type
.
(is-coercible-to? coercion-strategy effective-type)
Whether coercion-strategy
coerces to effective-type
or some subtype thereof.
(is-coercible? coercion-strategy base-type effective-type)
Whether coercion-strategy
is allowed for base-type
and coerces to effective-type
or some subtype thereof.
(is_coerceable base-type)
Returns a boolean of whether a field base-type has any coercion strategies available.
(most-specific-common-ancestor x y)
Return the most-specific type that is an ancestor of both x
and y
.
(most-specific-common-ancestor :type/BigInteger :type/Decimal) => :type/Number
(temporal-field? field)
Inputs: [field :- SnakeCasedField] Return: :any
True if a Metabase Field
instance has a temporal base or semantic type, i.e. if this Field represents a value
relating to a moment in time.
Normally, a native card's query is parsed on every create/update. For most tests, this is an unnecessary expense. Therefore, we skip parsing while testing unless this variable is turned on.
c.f. [[active?]]
(field-ids-for-sql query)
Returns a {:direct #{...} :indirect #{...}}
map with field IDs that (may) be referenced in the given cards's
query. Errs on the side of optimism: i.e., it may return fields that are not in the query, and is unlikely to fail
to return fields that are in the query.
Direct references are columns that are named in the query; indirect ones are from wildcards. If a field could be
both direct and indirect, it will only show up in the :direct
set.
(replace-names sql-query renames)
Returns a modified query with the given table and column renames applied. renames
is expected to be a map with
:tables
and :columns
keys, and values of the shape old-name -> new-name
:
(replace-names "SELECT o.id, o.total FROM orders o" {:columns {"id" "pk" "total" "amount"} :tables {"orders" "purchases"}}) ;; => "SELECT o.pk, o.amount FROM purchases o"