Current section
Files
Jump to
Current section
Files
src/sqlode@query_analyzer@embed_rewriter.erl
-module(sqlode@query_analyzer@embed_rewriter).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/sqlode/query_analyzer/embed_rewriter.gleam").
-export([rewrite/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Expand `sqlode.embed(TABLE)` macro calls into concrete qualified column\n"
" lists inside an already-tokenized query. The rewriter is meant to run\n"
" after `column_inferencer.infer_result_columns` so that the\n"
" `EmbeddedResult` entries it receives already have the table's column\n"
" list resolved against the catalog.\n"
).
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 30).
-spec collect_embeds(list(sqlode@model:result_item())) -> list(sqlode@model:embedded_column()).
collect_embeds(Result_columns) ->
gleam@list:filter_map(Result_columns, fun(Item) -> case Item of
{embedded_result, Embed} ->
{ok, Embed};
{scalar_result, _} ->
{error, nil}
end end).
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 70).
-spec try_match_embed(list(sqlode@lexer:token())) -> {ok,
{binary(), list(sqlode@lexer:token())}} |
{error, nil}.
try_match_embed(Tokens) ->
case Tokens of
[{ident, Sqlode_tok},
dot,
{ident, Embed_tok},
l_paren,
{ident, Table_tok},
r_paren |
Rest] ->
case (string:lowercase(Sqlode_tok) =:= <<"sqlode"/utf8>>) andalso (string:lowercase(
Embed_tok
)
=:= <<"embed"/utf8>>) of
true ->
{ok, {Table_tok, Rest}};
false ->
{error, nil}
end;
_ ->
{error, nil}
end.
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 94).
-spec find_embed(list(sqlode@model:embedded_column()), binary()) -> {ok,
sqlode@model:embedded_column()} |
{error, nil}.
find_embed(Embeds, Table_token) ->
Key = string:lowercase(Table_token),
gleam@list:find(Embeds, fun(E) -> erlang:element(3, E) =:= Key end).
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 102).
-spec build_column_tokens(sqlode@model:embedded_column()) -> list(sqlode@lexer:token()).
build_column_tokens(Embed) ->
_pipe = erlang:element(4, Embed),
_pipe@1 = gleam@list:index_map(
_pipe,
fun(Col, Idx) ->
Prefix = case Idx of
0 ->
[];
_ ->
[comma]
end,
lists:append(
Prefix,
[{ident, erlang:element(3, Embed)},
dot,
{ident, erlang:element(2, Col)}]
)
end
),
lists:append(_pipe@1).
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 118).
-spec prepend_reversed(list(NJI), list(NJI)) -> list(NJI).
prepend_reversed(Items, Acc) ->
case Items of
[] ->
Acc;
[X | Rest] ->
prepend_reversed(Rest, [X | Acc])
end.
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 59).
-spec advance_one(
list(sqlode@lexer:token()),
list(sqlode@model:embedded_column()),
list(sqlode@lexer:token())
) -> list(sqlode@lexer:token()).
advance_one(Tokens, Embeds, Acc) ->
case Tokens of
[] ->
lists:reverse(Acc);
[T | Rest] ->
do_rewrite(Rest, Embeds, [T | Acc])
end.
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 41).
-spec do_rewrite(
list(sqlode@lexer:token()),
list(sqlode@model:embedded_column()),
list(sqlode@lexer:token())
) -> list(sqlode@lexer:token()).
do_rewrite(Tokens, Embeds, Acc) ->
case try_match_embed(Tokens) of
{ok, {Table_token, Rest}} ->
case find_embed(Embeds, Table_token) of
{ok, Embed} ->
Replacement = build_column_tokens(Embed),
do_rewrite(Rest, Embeds, prepend_reversed(Replacement, Acc));
{error, nil} ->
advance_one(Tokens, Embeds, Acc)
end;
{error, nil} ->
advance_one(Tokens, Embeds, Acc)
end.
-file("src/sqlode/query_analyzer/embed_rewriter.gleam", 19).
?DOC(
" Rewrite token list, replacing every `sqlode.embed(TABLE)` occurrence with\n"
" a comma-separated list of qualified columns derived from the matching\n"
" `EmbeddedResult` in `result_columns`.\n"
"\n"
" If `result_columns` contains no `EmbeddedResult`, tokens are returned\n"
" unchanged — callers can use this to short-circuit re-rendering when\n"
" there is nothing to do.\n"
).
-spec rewrite(list(sqlode@lexer:token()), list(sqlode@model:result_item())) -> list(sqlode@lexer:token()).
rewrite(Tokens, Result_columns) ->
Embeds = collect_embeds(Result_columns),
case Embeds of
[] ->
Tokens;
_ ->
do_rewrite(Tokens, Embeds, [])
end.