-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(NSQ), list(NSQ)) -> list(NSQ). 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.