HoneySQL query data checked against a registry, without a database: the tables must exist, the columns a query selects, returns, inserts, sets or compares must exist, an INSERT must carry the required columns, an enum literal must be one of the enum's values; and from the same data, the types of the query's parameters and of the rows it returns, as malli schemas.
Scope: tables come from :from, :using, :cross-join, the joins (:join-by is not read), :insert-into, :update, :delete-from and :truncate, under their aliases. CTEs (:with), subqueries, table functions, a symbol where a table goes and a pg_catalog or information_schema table the registry lacks are opaque tables: their columns exist but have no type. Every table has the system columns (ctid, xmin, ...). A column is :col (unique in the scope), :alias/col or :alias.col; a column a subquery cannot resolve is looked for in the enclosing statements, as PostgreSQL does. An unqualified table is in :schema (default "public"). What code in the query builds (a list) is not in the data and is not judged.
Types are what next.jdbc and PostgreSQL's JDBC driver return and take. The functions take the options of docs/queries.md#options; a key or value not among them is an error.
HoneySQL query data checked against a registry, without a database: the tables must exist, the columns a query selects, returns, inserts, sets or compares must exist, an INSERT must carry the required columns, an enum literal must be one of the enum's values; and from the same data, the types of the query's parameters and of the rows it returns, as malli schemas. Scope: tables come from :from, :using, :cross-join, the joins (:join-by is not read), :insert-into, :update, :delete-from and :truncate, under their aliases. CTEs (:with), subqueries, table functions, a symbol where a table goes and a pg_catalog or information_schema table the registry lacks are opaque tables: their columns exist but have no type. Every table has the system columns (ctid, xmin, ...). A column is :col (unique in the scope), :alias/col or :alias.col; a column a subquery cannot resolve is looked for in the enclosing statements, as PostgreSQL does. An unqualified table is in :schema (default "public"). What code in the query builds (a list) is not in the data and is not judged. Types are what next.jdbc and PostgreSQL's JDBC driver return and take. The functions take the options of docs/queries.md#options; a key or value not among them is an error.
(arg-types registry body)(arg-types registry body {:keys [schema] :or {schema default-schema} :as opts}){arg schema} for the named parameters of a query (:?id, [:param :id]), keyed as sql/format's :params takes them (:id).
(arg-types registry {:select [:id] :from [:users] :where [:= :email :?email]}) ;; => {:email [:string {:pg/type "character varying"}]}
An argument compared with a column has the column's kind without NULL; one in :in a non-empty collection of it; one assigned to a column the column's type; one in :limit or :offset an :int of at least 0; any other :any. The first typed use wins. Options: docs/queries.md#options.
{arg schema} for the named parameters of a query (:?id, [:param :id]), keyed as sql/format's
:params takes them (:id).
(arg-types registry {:select [:id] :from [:users] :where [:= :email :?email]})
;; => {:email [:string {:pg/type "character varying"}]}
An argument compared with a column has the column's kind without NULL; one in :in a
non-empty collection of it; one assigned to a column the column's type; one in :limit or
:offset an :int of at least 0; any other :any. The first typed use wins. Options:
docs/queries.md#options.(check registry body)(check registry body opts)[problem ...] of a HoneySQL query against the registry; [] when there are none.
(check registry {:select [:id :mail] :from [:users]}) ;; => [{:kind :unknown-column, :column :mail, :did-you-mean [:email]}]
A problem in a nested statement (a subquery, a CTE) carries :in, where the statement sits: (get-in q (:in p)) for data, the position in the form for code. explain says each problem as a sentence. Names resolve as PostgreSQL resolves them. A clause pgmalli does not read is an :unread-clause problem. Code in the query (a list) is not read. Options: docs/queries.md#options. Throws when body is no HoneySQL data.
[problem ...] of a HoneySQL query against the registry; [] when there are none.
(check registry {:select [:id :mail] :from [:users]})
;; => [{:kind :unknown-column, :column :mail, :did-you-mean [:email]}]
A problem in a nested statement (a subquery, a CTE) carries :in, where the statement sits:
(get-in q (:in p)) for data, the position in the form for code. explain says each problem
as a sentence. Names resolve as PostgreSQL resolves them. A clause pgmalli does not read is an
:unread-clause problem. Code in the query (a list) is not read. Options: docs/queries.md#options.
Throws when body is no HoneySQL data.(explain problems)A sentence for each problem of check (or of query-schema's :pgmalli/problems): what is wrong and what to do.
(is (= [] (check registry q)) (explain (check registry q)))
A sentence for each problem of check (or of query-schema's :pgmalli/problems): what is wrong and what to do. (is (= [] (check registry q)) (explain (check registry q)))
(params-schema registry body)(params-schema registry body opts)The [:map ...] of sql/format's :params for a query: every named argument, typed as arg-types types it, is required, as sql/format refuses a missing one; one that takes nil is [:maybe ...]. Options: docs/queries.md#options.
(params-schema registry {:select [:id] :from [:users] :where [:= :email :?email]}) ;; => [:map [:email [:string {:pg/type "character varying"}]]]
The [:map ...] of sql/format's :params for a query: every named argument, typed as arg-types
types it, is required, as sql/format refuses a missing one; one that takes nil is
[:maybe ...]. Options: docs/queries.md#options.
(params-schema registry {:select [:id] :from [:users] :where [:= :email :?email]})
;; => [:map [:email [:string {:pg/type "character varying"}]]](query-schema registry args body)(query-schema registry args body {:keys [result] :as opts})[:=> [:cat arg ...] [:sequential row]], the malli function schema of a function taking args and running body: the args' types from arg-types (:any for a key the query lacks), the row from row-schema (:any when it cannot be resolved).
(query-schema registry [:db :id] {:select [:email] :from [:users] :where [:= :id :?id]})
The problems of check, and a query argument args lack (:missing-arg), are the schema's :pgmalli/problems property, not an error: the vector is then one longer, so read its parts with m/children. {:result :one} makes the return [:maybe row]. Options: docs/queries.md#options. Throws when args are not keywords or symbols.
[:=> [:cat arg ...] [:sequential row]], the malli function schema of a function taking args
and running body: the args' types from arg-types (:any for a key the query lacks), the
row from row-schema (:any when it cannot be resolved).
(query-schema registry [:db :id] {:select [:email] :from [:users] :where [:= :id :?id]})
The problems of check, and a query argument args lack (:missing-arg), are the schema's
:pgmalli/problems property, not an error: the vector is then one longer, so read its parts
with m/children. {:result :one} makes the return [:maybe row]. Options:
docs/queries.md#options. Throws when args are not keywords or symbols.(row-schema registry body)(row-schema registry body opts)The [:map ...] of one row a query returns, as next.jdbc builds it; nil when a selected column cannot be resolved (check says which), or a whole row is selected ({:select [:t]}), which next.jdbc reads as one PGobject.
Columns an outer join may leave NULL are nullable; an expression is nullable :any; a set operation's row is its first member's names. Under qualified keys, a column next.jdbc keys by a table the data does not show (one through a subquery or a CTE, a cast column) is left out of the map, which is open, and named under the :pgmalli/untold property. Options: docs/queries.md#options.
The [:map ...] of one row a query returns, as next.jdbc builds it; nil when a selected
column cannot be resolved (check says which), or a whole row is selected ({:select [:t]}),
which next.jdbc reads as one PGobject.
Columns an outer join may leave NULL are nullable; an expression is nullable :any; a set
operation's row is its first member's names. Under qualified keys, a column next.jdbc keys
by a table the data does not show (one through a subquery or a CTE, a cast column) is left
out of the map, which is open, and named under the :pgmalli/untold property. Options:
docs/queries.md#options.(schema-problems)(schema-problems {:keys [ns] :or {ns (all-ns)}})[problem ...] of the :malli/schema of every var in the namespaces (all loaded ones by default), each with its :var: query-schema's :pgmalli/problems, which a schema carries rather than throws, so a namespace still loads. One test asserts there are none:
(is (= [] (schema-problems)))
[problem ...] of the :malli/schema of every var in the namespaces (all loaded ones by default), each with its :var: query-schema's :pgmalli/problems, which a schema carries rather than throws, so a namespace still loads. One test asserts there are none: (is (= [] (schema-problems)))
(tables registry body)(tables registry body {:keys [schema] :or {schema default-schema} :as opts}){:reads #{"schema.table" ...} :writes #{...}}: the tables and views a query reads (FROM, joins, USING, in every subquery and CTE) and writes (INSERT INTO, UPDATE, DELETE FROM, TRUNCATE), aliases and CTE names resolved as PostgreSQL resolves them. A table code in the query brings in is not seen. Options: docs/queries.md#options.
(tables registry {:update :users :set {:nick "a"} :from [[:groups :g]] :where [:= :g.id :users.group_id]}) ;; => {:reads #{"public.groups"}, :writes #{"public.users"}}
{:reads #{"schema.table" ...} :writes #{...}}: the tables and views a query reads (FROM,
joins, USING, in every subquery and CTE) and writes (INSERT INTO, UPDATE, DELETE FROM,
TRUNCATE),
aliases and CTE names resolved as PostgreSQL resolves them. A table code in the query
brings in is not seen. Options: docs/queries.md#options.
(tables registry {:update :users :set {:nick "a"} :from [[:groups :g]] :where [:= :g.id :users.group_id]})
;; => {:reads #{"public.groups"}, :writes #{"public.users"}}cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |