kura_query_compiler (kura v2.20.7)
View SourcePublic entry point for compiling kura_query ASTs into SQL.
Resolves the dialect per repo: the configured dialect module lives in
the repo's config map (set automatically when the repo declares a
{backend, ...}). Different repos in the same app may use different
dialects.
This module is internal. Use kura_repo_worker for executing queries.
Summary
Functions
-spec delete_all(module(), #kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {iodata(), [term()]}.
Return the dialect module configured for RepoMod.
Resolution order:
dialectkey in the repo's config map (multi-repo or v2.4 flat env).- Global
application:get_env(kura, dialect)for legacy single-dialect setups.
-spec to_sql(module(), #kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {iodata(), [term()]}.
Compile a query record into {SQL, Params} for RepoMod's dialect.
-spec to_sql_cached(module(), #kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {iodata(), [term()]}.
Cached to_sql/2. The cache key includes RepoMod so two repos with
different dialects don't share an entry.
The key holds the whole query term, never a hash of it. erlang:phash2/1
returns only 27 bits, so a long-lived cache accumulates collisions, and a
collision here does not degrade a lookup - it returns another query's SQL
and its bound parameters, so the caller silently reads rows from a
different table.
The key also carries the ambient tenant. kura_repo_worker normalises the
tenant into the top-level query record before compiling, but a nested CTE
or combination query keeps prefix = undefined and resolves it from
kura_tenant at emit time, so the compiled SQL is a function of ambient
state the query term does not describe. Without the tenant in the key, one
tenant's cached entry is served to the next - a cross-tenant read.
The dialect is deliberately not in the key: it is resolved from boot-time
repo config. Swapping a repo's dialect at runtime requires an explicit
kura_query_cache:flush/0.
-spec to_sql_from(module(), #kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}, pos_integer()) -> {iodata(), [term()], pos_integer()}.
-spec update_all(module(), #kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}, map()) -> {iodata(), [term()]}.