Current section
Files
Jump to
Current section
Files
src/galchemy@sql@compiler.erl
-module(galchemy@sql@compiler).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src\\galchemy\\sql\\compiler.gleam").
-export([default_config/0, compile_select_with/2, compile_select/1, compile_insert_with/2, compile_insert/1, compile_update_with/2, compile_update/1, compile_delete_with/2, compile_with/2, compile/1, compile_delete/1]).
-export_type([compiled_query/0, compile_error/0, compiler_config/0, compile_state/0]).
-type compiled_query() :: {compiled_query,
binary(),
list(galchemy@ast@expression:sql_value())}.
-type compile_error() :: missing_from |
empty_in_list |
empty_insert_values |
empty_update_assignments |
inconsistent_insert_row_shape |
having_without_group_by |
{invalid_function_name, binary()} |
{invalid_limit, integer()} |
{invalid_offset, integer()}.
-type compiler_config() :: {compiler_config,
fun((binary()) -> binary()),
fun((binary()) -> {ok, binary()} | {error, compile_error()})}.
-type compile_state() :: {compile_state,
integer(),
list(galchemy@ast@expression:sql_value()),
compiler_config()}.
-file("src\\galchemy\\sql\\compiler.gleam", 40).
-spec result_try(
{ok, HAO} | {error, HAP},
fun((HAO) -> {ok, HAS} | {error, HAP})
) -> {ok, HAS} | {error, HAP}.
result_try(Result, Next) ->
case Result of
{ok, Value} ->
Next(Value);
{error, Error} ->
{error, Error}
end.
-file("src\\galchemy\\sql\\compiler.gleam", 54).
-spec new_state(compiler_config()) -> compile_state().
new_state(Config) ->
{compile_state, 1, [], Config}.
-file("src\\galchemy\\sql\\compiler.gleam", 456).
-spec same_insert_shape(
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()})
) -> boolean().
same_insert_shape(One, Other) ->
case {One, Other} of
{[], []} ->
true;
{[{Left_column, _} | Left_rest], [{Right_column, _} | Right_rest]} ->
(Left_column =:= Right_column) andalso same_insert_shape(
Left_rest,
Right_rest
);
{_, _} ->
false
end.
-file("src\\galchemy\\sql\\compiler.gleam", 632).
-spec push_param(galchemy@ast@expression:sql_value(), compile_state()) -> {binary(),
compile_state()}.
push_param(Value, State) ->
Placeholder = <<"$"/utf8,
(erlang:integer_to_binary(erlang:element(2, State)))/binary>>,
Next_state = {compile_state,
erlang:element(2, State) + 1,
[Value | erlang:element(3, State)],
erlang:element(4, State)},
{Placeholder, Next_state}.
-file("src\\galchemy\\sql\\compiler.gleam", 899).
-spec compile_limit(gleam@option:option(integer())) -> {ok, binary()} |
{error, compile_error()}.
compile_limit(Limit) ->
case Limit of
none ->
{ok, <<""/utf8>>};
{some, V} ->
case V < 0 of
true ->
{error, {invalid_limit, V}};
false ->
{ok,
<<" LIMIT "/utf8, (erlang:integer_to_binary(V))/binary>>}
end
end.
-file("src\\galchemy\\sql\\compiler.gleam", 911).
-spec compile_offset(gleam@option:option(integer())) -> {ok, binary()} |
{error, compile_error()}.
compile_offset(Offset) ->
case Offset of
none ->
{ok, <<""/utf8>>};
{some, V} ->
case V < 0 of
true ->
{error, {invalid_offset, V}};
false ->
{ok,
<<" OFFSET "/utf8,
(erlang:integer_to_binary(V))/binary>>}
end
end.
-file("src\\galchemy\\sql\\compiler.gleam", 968).
-spec compile_identifier(binary(), compiler_config()) -> binary().
compile_identifier(Identifier, Config) ->
{compiler_config, Render_identifier, _} = Config,
Render_identifier(Identifier).
-file("src\\galchemy\\sql\\compiler.gleam", 923).
-spec compile_table_ref(galchemy@ast@schema:table(), compiler_config()) -> binary().
compile_table_ref(Table, Config) ->
{table, Schema_name, Name, Alias} = Table,
Qualified_name = case Schema_name of
none ->
compile_identifier(Name, Config);
{some, Schema_name@1} ->
<<<<(compile_identifier(Schema_name@1, Config))/binary, "."/utf8>>/binary,
(compile_identifier(Name, Config))/binary>>
end,
case Alias of
none ->
Qualified_name;
{some, A} ->
<<<<Qualified_name/binary, " AS "/utf8>>/binary,
(compile_identifier(A, Config))/binary>>
end.
-file("src\\galchemy\\sql\\compiler.gleam", 939).
-spec compile_column_ref(galchemy@ast@schema:column_meta(), compiler_config()) -> binary().
compile_column_ref(Column, Config) ->
{column_meta, Table, Column_name} = Column,
{table, Schema_name, Table_name, Alias} = Table,
Qualifier = case Alias of
none ->
case Schema_name of
none ->
compile_identifier(Table_name, Config);
{some, Schema_name@1} ->
<<<<(compile_identifier(Schema_name@1, Config))/binary,
"."/utf8>>/binary,
(compile_identifier(Table_name, Config))/binary>>
end;
{some, A} ->
compile_identifier(A, Config)
end,
<<<<Qualifier/binary, "."/utf8>>/binary,
(compile_identifier(Column_name, Config))/binary>>.
-file("src\\galchemy\\sql\\compiler.gleam", 960).
-spec compile_column_name(galchemy@ast@schema:column_meta(), compiler_config()) -> binary().
compile_column_name(Column, Config) ->
{column_meta, _, Name} = Column,
compile_identifier(Name, Config).
-file("src\\galchemy\\sql\\compiler.gleam", 976).
-spec compile_function_name(binary(), compiler_config()) -> {ok, binary()} |
{error, compile_error()}.
compile_function_name(Name, Config) ->
{compiler_config, _, Validate_function_name} = Config,
Validate_function_name(Name).
-file("src\\galchemy\\sql\\compiler.gleam", 987).
-spec default_render_identifier(binary()) -> binary().
default_render_identifier(Identifier) ->
<<<<"\""/utf8,
(gleam@string:replace(Identifier, <<"\""/utf8>>, <<"\"\""/utf8>>))/binary>>/binary,
"\""/utf8>>.
-file("src\\galchemy\\sql\\compiler.gleam", 991).
-spec default_validate_function_name(binary()) -> {ok, binary()} |
{error, compile_error()}.
default_validate_function_name(Name) ->
case gleam@string:is_empty(Name) of
true ->
{error, {invalid_function_name, Name}};
false ->
{ok, Name}
end.
-file("src\\galchemy\\sql\\compiler.gleam", 47).
-spec default_config() -> compiler_config().
default_config() ->
{compiler_config,
fun default_render_identifier/1,
fun default_validate_function_name/1}.
-file("src\\galchemy\\sql\\compiler.gleam", 998).
-spec op_to_sql(galchemy@ast@expression:comparison_op()) -> binary().
op_to_sql(Op) ->
case Op of
eq ->
<<"="/utf8>>;
neq ->
<<"!="/utf8>>;
gt ->
<<">"/utf8>>;
gte ->
<<">="/utf8>>;
lt ->
<<"<"/utf8>>;
lte ->
<<"<="/utf8>>
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1009).
-spec unary_operator_to_sql(galchemy@ast@expression:unary_operator()) -> binary().
unary_operator_to_sql(Operator) ->
case Operator of
negate ->
<<"-"/utf8>>
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1015).
-spec binary_operator_to_sql(galchemy@ast@expression:binary_operator()) -> binary().
binary_operator_to_sql(Operator) ->
case Operator of
add ->
<<"+"/utf8>>;
subtract ->
<<"-"/utf8>>;
multiply ->
<<"*"/utf8>>;
divide ->
<<"/"/utf8>>;
concat ->
<<"||"/utf8>>
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1032).
-spec join_strings_loop(list(binary()), binary(), binary()) -> binary().
join_strings_loop(Parts, Acc, Sep) ->
case Parts of
[] ->
Acc;
[Part | Rest] ->
join_strings_loop(
Rest,
<<<<Acc/binary, Sep/binary>>/binary, Part/binary>>,
Sep
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1025).
-spec join_strings(list(binary()), binary()) -> binary().
join_strings(Parts, Sep) ->
case Parts of
[] ->
<<""/utf8>>;
[First | Rest] ->
join_strings_loop(Rest, First, Sep)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1039).
-spec concat_strings(list(binary())) -> binary().
concat_strings(Parts) ->
case Parts of
[] ->
<<""/utf8>>;
[P | Rest] ->
<<P/binary, (concat_strings(Rest))/binary>>
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1050).
-spec reverse_loop(list(HGL), list(HGL)) -> list(HGL).
reverse_loop(Items, Acc) ->
case Items of
[] ->
Acc;
[X | Xs] ->
reverse_loop(Xs, [X | Acc])
end.
-file("src\\galchemy\\sql\\compiler.gleam", 1046).
-spec reverse(list(HGI)) -> list(HGI).
reverse(Items) ->
reverse_loop(Items, []).
-file("src\\galchemy\\sql\\compiler.gleam", 58).
-spec finalize(binary(), compile_state()) -> compiled_query().
finalize(Sql, State) ->
{compiled_query, Sql, reverse(erlang:element(3, State))}.
-file("src\\galchemy\\sql\\compiler.gleam", 276).
-spec compile_ctes_loop(
list(galchemy@ast@expression:cte()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_ctes_loop(Ctes, Acc, State) ->
case Ctes of
[] ->
{ok, {join_strings(reverse(Acc), <<", "/utf8>>), State}};
[Cte | Rest] ->
{cte, Name, Cte_query} = Cte,
result_try(
compile_select_query(Cte_query, State),
fun(_use0) ->
{Cte_sql, Next_state} = _use0,
Next_item = <<<<<<(compile_identifier(
Name,
erlang:element(4, State)
))/binary,
" AS ("/utf8>>/binary,
Cte_sql/binary>>/binary,
")"/utf8>>,
compile_ctes_loop(Rest, [Next_item | Acc], Next_state)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 93).
-spec compile_select_query(
galchemy@ast@expression:select_query(),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_select_query(Q, State) ->
{select_query,
Ctes,
Items,
From,
Joins,
Where_,
Group_by,
Having_,
Unions,
Order_by,
Limit,
Offset,
Distinct} = Q,
case From of
none ->
{error, missing_from};
{some, Source} ->
result_try(
compile_ctes(Ctes, State),
fun(_use0) ->
{Ctes_sql, State1} = _use0,
result_try(
compile_select_items(Items, State1),
fun(_use0@1) ->
{Items_sql, State2} = _use0@1,
result_try(
compile_source(Source, State2),
fun(_use0@2) ->
{From_sql, State3} = _use0@2,
result_try(
compile_joins(Joins, State3),
fun(_use0@3) ->
{Joins_sql, State4} = _use0@3,
result_try(
compile_where(Where_, State4),
fun(_use0@4) ->
{Where_sql, State5} = _use0@4,
result_try(
compile_group_by(
Group_by,
State5
),
fun(_use0@5) ->
{Group_by_sql,
State6} = _use0@5,
result_try(
compile_having(
Group_by,
Having_,
State6
),
fun(_use0@6) ->
{Having_sql,
State7} = _use0@6,
result_try(
compile_order_by(
Order_by,
State7
),
fun(
_use0@7
) ->
{Order_sql,
State8} = _use0@7,
result_try(
compile_limit(
Limit
),
fun(
Limit_sql
) ->
result_try(
compile_offset(
Offset
),
fun(
Offset_sql
) ->
result_try(
compile_set_operations(
Unions,
State8
),
fun(
_use0@8
) ->
{Unions_sql,
State9} = _use0@8,
Distinct_sql = case Distinct of
true ->
<<"DISTINCT "/utf8>>;
false ->
<<""/utf8>>
end,
Base_sql = <<<<<<<<<<<<<<<<<<<<<<"SELECT "/utf8,
Distinct_sql/binary>>/binary,
Items_sql/binary>>/binary,
" FROM "/utf8>>/binary,
From_sql/binary>>/binary,
Joins_sql/binary>>/binary,
Where_sql/binary>>/binary,
Group_by_sql/binary>>/binary,
Having_sql/binary>>/binary,
Order_sql/binary>>/binary,
Limit_sql/binary>>/binary,
Offset_sql/binary>>,
{ok,
{<<<<Ctes_sql/binary,
Base_sql/binary>>/binary,
Unions_sql/binary>>,
State9}}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 259).
-spec compile_ctes(list(galchemy@ast@expression:cte()), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_ctes(Ctes, State) ->
case Ctes of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_ctes_loop(Ctes, [], State),
fun(_use0) ->
{Ctes_sql, Next_state} = _use0,
{ok,
{<<<<"WITH "/utf8, Ctes_sql/binary>>/binary, " "/utf8>>,
Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 84).
-spec compile_select_with(
galchemy@ast@expression:select_query(),
compiler_config()
) -> {ok, compiled_query()} | {error, compile_error()}.
compile_select_with(Q, Config) ->
State0 = new_state(Config),
result_try(
compile_select_query(Q, State0),
fun(_use0) ->
{Sql, State1} = _use0,
{ok, finalize(Sql, State1)}
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 78).
-spec compile_select(galchemy@ast@expression:select_query()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_select(Q) ->
compile_select_with(Q, default_config()).
-file("src\\galchemy\\sql\\compiler.gleam", 303).
-spec compile_set_operations_loop(
list(galchemy@ast@expression:set_operation()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_set_operations_loop(Operations, Acc, State) ->
case Operations of
[] ->
{ok, {concat_strings(reverse(Acc)), State}};
[Operation | Rest] ->
{set_operation, Kind, Union_query} = Operation,
Operator_sql = case Kind of
union ->
<<" UNION "/utf8>>;
union_all ->
<<" UNION ALL "/utf8>>
end,
result_try(
compile_select_query(Union_query, State),
fun(_use0) ->
{Union_sql, Next_state} = _use0,
compile_set_operations_loop(
Rest,
[<<Operator_sql/binary, Union_sql/binary>> | Acc],
Next_state
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 296).
-spec compile_set_operations(
list(galchemy@ast@expression:set_operation()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_set_operations(Operations, State) ->
compile_set_operations_loop(Operations, [], State).
-file("src\\galchemy\\sql\\compiler.gleam", 646).
-spec compile_source(galchemy@ast@expression:source(), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_source(Source, State) ->
case Source of
{table_source, Table} ->
{ok, {compile_table_ref(Table, erlang:element(4, State)), State}};
{derived_source, Derived_query, Alias} ->
result_try(
compile_select_query(Derived_query, State),
fun(_use0) ->
{Query_sql, Next_state} = _use0,
{ok,
{<<<<<<"("/utf8, Query_sql/binary>>/binary,
") AS "/utf8>>/binary,
(compile_identifier(
Alias,
erlang:element(4, State)
))/binary>>,
Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 790).
-spec compile_order_item(galchemy@ast@expression:order(), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_order_item(Item, State) ->
{order, Expr, Direction} = Item,
result_try(
compile_expression(Expr, State),
fun(_use0) ->
{Expr_sql, State1} = _use0,
Dir_sql = case Direction of
asc ->
<<"ASC"/utf8>>;
desc ->
<<"DESC"/utf8>>
end,
{ok,
{<<<<Expr_sql/binary, " "/utf8>>/binary, Dir_sql/binary>>,
State1}}
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 511).
-spec compile_expression(galchemy@ast@expression:expression(), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_expression(Expr, State) ->
case Expr of
{column_expr, Meta} ->
{ok, {compile_column_ref(Meta, erlang:element(4, State)), State}};
{value_expr, null} ->
{ok, {<<"NULL"/utf8>>, State}};
star_expr ->
{ok, {<<"*"/utf8>>, State}};
{function_expr, Name, Arguments} ->
result_try(
compile_function_name(Name, erlang:element(4, State)),
fun(Function_name) ->
result_try(
compile_expression_list(Arguments, State),
fun(_use0) ->
{Arguments_sql, Next_state} = _use0,
{ok,
{<<<<<<Function_name/binary, "("/utf8>>/binary,
Arguments_sql/binary>>/binary,
")"/utf8>>,
Next_state}}
end
)
end
);
{unary_op_expr, Operator, Operand} ->
result_try(
compile_expression(Operand, State),
fun(_use0@1) ->
{Operand_sql, Next_state@1} = _use0@1,
{ok,
{<<<<<<"("/utf8,
(unary_operator_to_sql(Operator))/binary>>/binary,
Operand_sql/binary>>/binary,
")"/utf8>>,
Next_state@1}}
end
);
{binary_op_expr, Lhs, Operator@1, Rhs} ->
result_try(
compile_expression(Lhs, State),
fun(_use0@2) ->
{Lhs_sql, State1} = _use0@2,
result_try(
compile_expression(Rhs, State1),
fun(_use0@3) ->
{Rhs_sql, State2} = _use0@3,
{ok,
{<<<<<<<<<<<<"("/utf8, Lhs_sql/binary>>/binary,
" "/utf8>>/binary,
(binary_operator_to_sql(
Operator@1
))/binary>>/binary,
" "/utf8>>/binary,
Rhs_sql/binary>>/binary,
")"/utf8>>,
State2}}
end
)
end
);
{window_expr, Function, Window} ->
result_try(
compile_expression(Function, State),
fun(_use0@4) ->
{Function_sql, State1@1} = _use0@4,
result_try(
compile_window_definition(Window, State1@1),
fun(_use0@5) ->
{Window_sql, State2@1} = _use0@5,
{ok,
{<<<<<<Function_sql/binary, " OVER ("/utf8>>/binary,
Window_sql/binary>>/binary,
")"/utf8>>,
State2@1}}
end
)
end
);
{subquery_expr, Select_query} ->
result_try(
compile_select_query(Select_query, State),
fun(_use0@6) ->
{Subquery_sql, Next_state@2} = _use0@6,
{ok,
{<<<<"("/utf8, Subquery_sql/binary>>/binary, ")"/utf8>>,
Next_state@2}}
end
);
{value_expr, Value} ->
{Placeholder, Next_state@3} = push_param(Value, State),
{ok, {Placeholder, Next_state@3}}
end.
-file("src\\galchemy\\sql\\compiler.gleam", 577).
-spec compile_window_definition(
galchemy@ast@expression:window_definition(),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_window_definition(Window, State) ->
{window_definition, Partition_by, Order_by} = Window,
result_try(
compile_window_partition(Partition_by, State),
fun(_use0) ->
{Partition_sql, State1} = _use0,
result_try(
compile_window_order(Order_by, State1),
fun(_use0@1) ->
{Order_sql, State2} = _use0@1,
case {Partition_sql, Order_sql} of
{<<""/utf8>>, <<""/utf8>>} ->
{ok, {<<""/utf8>>, State2}};
{<<""/utf8>>, _} ->
{ok, {Order_sql, State2}};
{_, <<""/utf8>>} ->
{ok, {Partition_sql, State2}};
{_, _} ->
{ok,
{<<<<Partition_sql/binary, " "/utf8>>/binary,
Order_sql/binary>>,
State2}}
end
end
)
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 616).
-spec compile_window_order(
list(galchemy@ast@expression:order()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_window_order(Order_by, State) ->
case Order_by of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_order_items(Order_by, State),
fun(_use0) ->
{Order_sql, Next_state} = _use0,
{ok, {<<"ORDER BY "/utf8, Order_sql/binary>>, Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 769).
-spec compile_order_items(
list(galchemy@ast@expression:order()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_order_items(Items, State) ->
compile_order_items_loop(Items, [], State).
-file("src\\galchemy\\sql\\compiler.gleam", 776).
-spec compile_order_items_loop(
list(galchemy@ast@expression:order()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_order_items_loop(Items, Acc, State) ->
case Items of
[] ->
{ok, {join_strings(reverse(Acc), <<", "/utf8>>), State}};
[Item | Rest] ->
result_try(
compile_order_item(Item, State),
fun(_use0) ->
{Item_sql, Next_state} = _use0,
compile_order_items_loop(Rest, [Item_sql | Acc], Next_state)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 355).
-spec compile_select_item(
galchemy@ast@expression:select_item(),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_select_item(Item, State) ->
{select_item, Expr, Alias} = Item,
result_try(
compile_expression(Expr, State),
fun(_use0) ->
{Expr_sql, State1} = _use0,
Sql = case Alias of
none ->
Expr_sql;
{some, A} ->
<<<<Expr_sql/binary, " AS "/utf8>>/binary,
(compile_identifier(A, erlang:element(4, State)))/binary>>
end,
{ok, {Sql, State1}}
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 341).
-spec compile_select_items_loop(
list(galchemy@ast@expression:select_item()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_select_items_loop(Items, Acc, State) ->
case Items of
[] ->
{ok, {join_strings(reverse(Acc), <<", "/utf8>>), State}};
[Item | Rest] ->
result_try(
compile_select_item(Item, State),
fun(_use0) ->
{Item_sql, Next_state} = _use0,
compile_select_items_loop(
Rest,
[Item_sql | Acc],
Next_state
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 331).
-spec compile_select_items(
list(galchemy@ast@expression:select_item()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_select_items(Items, State) ->
case Items of
[] ->
{ok, {<<"*"/utf8>>, State}};
_ ->
compile_select_items_loop(Items, [], State)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 431).
-spec compile_insert_row_loop(
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
list(binary()),
list(binary()),
compile_state()
) -> {ok, {binary(), binary(), compile_state()}} | {error, compile_error()}.
compile_insert_row_loop(Row, Columns_acc, Values_acc, State) ->
case Row of
[] ->
Columns_sql = join_strings(reverse(Columns_acc), <<", "/utf8>>),
Values_sql = join_strings(reverse(Values_acc), <<", "/utf8>>),
{ok,
{Columns_sql,
<<<<"("/utf8, Values_sql/binary>>/binary, ")"/utf8>>,
State}};
[{Column, Expr} | Rest] ->
result_try(
compile_expression(Expr, State),
fun(_use0) ->
{Expr_sql, Next_state} = _use0,
Column_sql = compile_column_name(
Column,
erlang:element(4, State)
),
compile_insert_row_loop(
Rest,
[Column_sql | Columns_acc],
[Expr_sql | Values_acc],
Next_state
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 424).
-spec compile_insert_row(
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
compile_state()
) -> {ok, {binary(), binary(), compile_state()}} | {error, compile_error()}.
compile_insert_row(Row, State) ->
compile_insert_row_loop(Row, [], [], State).
-file("src\\galchemy\\sql\\compiler.gleam", 396).
-spec compile_insert_rows_loop(
list(list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()})),
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
list(binary()),
compile_state()
) -> {ok, {list(binary()), compile_state()}} | {error, compile_error()}.
compile_insert_rows_loop(Rows, First_row, Acc, State) ->
case Rows of
[] ->
{ok, {Acc, State}};
[Row | Rest] ->
case same_insert_shape(First_row, Row) of
false ->
{error, inconsistent_insert_row_shape};
true ->
result_try(
compile_insert_row(Row, State),
fun(_use0) ->
{_, Row_sql, Next_state} = _use0,
compile_insert_rows_loop(
Rest,
First_row,
lists:append(Acc, [Row_sql]),
Next_state
)
end
)
end
end.
-file("src\\galchemy\\sql\\compiler.gleam", 370).
-spec compile_insert_rows(
list(list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()})),
compile_state()
) -> {ok, {binary(), binary(), compile_state()}} | {error, compile_error()}.
compile_insert_rows(Rows, State) ->
case Rows of
[] ->
{error, empty_insert_values};
[First_row | Rest_rows] ->
case First_row of
[] ->
{error, empty_insert_values};
_ ->
result_try(
compile_insert_row(First_row, State),
fun(_use0) ->
{Columns_sql, First_row_sql, State1} = _use0,
result_try(
compile_insert_rows_loop(
Rest_rows,
First_row,
[First_row_sql],
State1
),
fun(_use0@1) ->
{Rest_rows_sql, State2} = _use0@1,
{ok,
{Columns_sql,
join_strings(
Rest_rows_sql,
<<", "/utf8>>
),
State2}}
end
)
end
)
end
end.
-file("src\\galchemy\\sql\\compiler.gleam", 478).
-spec compile_assignments_loop(
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_assignments_loop(Assignments, Acc, State) ->
case Assignments of
[] ->
{ok, {join_strings(reverse(Acc), <<", "/utf8>>), State}};
[{Column, Expr} | Rest] ->
result_try(
compile_expression(Expr, State),
fun(_use0) ->
{Expr_sql, Next_state} = _use0,
Assignment_sql = <<<<(compile_column_name(
Column,
erlang:element(4, State)
))/binary,
" = "/utf8>>/binary,
Expr_sql/binary>>,
compile_assignments_loop(
Rest,
[Assignment_sql | Acc],
Next_state
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 468).
-spec compile_assignments(
list({galchemy@ast@schema:column_meta(),
galchemy@ast@expression:expression()}),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_assignments(Assignments, State) ->
case Assignments of
[] ->
{error, empty_update_assignments};
_ ->
compile_assignments_loop(Assignments, [], State)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 494).
-spec compile_returning(
list(galchemy@ast@expression:select_item()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_returning(Returning, State) ->
case Returning of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_select_items_loop(Returning, [], State),
fun(_use0) ->
{Items_sql, Next_state} = _use0,
{ok, {<<" RETURNING "/utf8, Items_sql/binary>>, Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 167).
-spec compile_insert_with(galchemy@ast@query:insert_query(), compiler_config()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_insert_with(Q, Config) ->
{insert_query, Table, Rows, Returning} = Q,
State0 = new_state(Config),
result_try(
compile_insert_rows(Rows, State0),
fun(_use0) ->
{Columns_sql, Rows_sql, State1} = _use0,
result_try(
compile_returning(Returning, State1),
fun(_use0@1) ->
{Returning_sql, State2} = _use0@1,
Sql = <<<<<<<<<<<<"INSERT INTO "/utf8,
(compile_table_ref(
Table,
erlang:element(4, State0)
))/binary>>/binary,
" ("/utf8>>/binary,
Columns_sql/binary>>/binary,
") VALUES "/utf8>>/binary,
Rows_sql/binary>>/binary,
Returning_sql/binary>>,
{ok, finalize(Sql, State2)}
end
)
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 161).
-spec compile_insert(galchemy@ast@query:insert_query()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_insert(Q) ->
compile_insert_with(Q, default_config()).
-file("src\\galchemy\\sql\\compiler.gleam", 753).
-spec compile_order_by(list(galchemy@ast@expression:order()), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_order_by(Order_by, State) ->
case Order_by of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_order_items(Order_by, State),
fun(_use0) ->
{Items_sql, Next_state} = _use0,
{ok, {<<" ORDER BY "/utf8, Items_sql/binary>>, Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 885).
-spec compile_expression_list_loop(
list(galchemy@ast@expression:expression()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_expression_list_loop(Exprs, Acc, State) ->
case Exprs of
[] ->
{ok, {join_strings(reverse(Acc), <<", "/utf8>>), State}};
[Expr | Rest] ->
result_try(
compile_expression(Expr, State),
fun(_use0) ->
{Expr_sql, Next_state} = _use0,
compile_expression_list_loop(
Rest,
[Expr_sql | Acc],
Next_state
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 878).
-spec compile_expression_list(
list(galchemy@ast@expression:expression()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_expression_list(Exprs, State) ->
compile_expression_list_loop(Exprs, [], State).
-file("src\\galchemy\\sql\\compiler.gleam", 600).
-spec compile_window_partition(
list(galchemy@ast@expression:expression()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_window_partition(Partition_by, State) ->
case Partition_by of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_expression_list(Partition_by, State),
fun(_use0) ->
{Partition_sql, Next_state} = _use0,
{ok,
{<<"PARTITION BY "/utf8, Partition_sql/binary>>,
Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 715).
-spec compile_group_by(
list(galchemy@ast@expression:expression()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_group_by(Group_by, State) ->
case Group_by of
[] ->
{ok, {<<""/utf8>>, State}};
_ ->
result_try(
compile_expression_list(Group_by, State),
fun(_use0) ->
{Items_sql, Next_state} = _use0,
{ok, {<<" GROUP BY "/utf8, Items_sql/binary>>, Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 803).
-spec compile_predicate(galchemy@ast@expression:predicate(), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_predicate(Pred, State) ->
case Pred of
{comparison, Lhs, Op, Rhs} ->
result_try(
compile_expression(Lhs, State),
fun(_use0) ->
{Lhs_sql, State1} = _use0,
result_try(
compile_expression(Rhs, State1),
fun(_use0@1) ->
{Rhs_sql, State2} = _use0@1,
{ok,
{<<<<<<<<<<<<"("/utf8, Lhs_sql/binary>>/binary,
" "/utf8>>/binary,
(op_to_sql(Op))/binary>>/binary,
" "/utf8>>/binary,
Rhs_sql/binary>>/binary,
")"/utf8>>,
State2}}
end
)
end
);
{'and', Left, Right} ->
result_try(
compile_predicate(Left, State),
fun(_use0@2) ->
{Left_sql, State1@1} = _use0@2,
result_try(
compile_predicate(Right, State1@1),
fun(_use0@3) ->
{Right_sql, State2@1} = _use0@3,
{ok,
{<<<<<<<<"("/utf8, Left_sql/binary>>/binary,
" AND "/utf8>>/binary,
Right_sql/binary>>/binary,
")"/utf8>>,
State2@1}}
end
)
end
);
{'or', Left@1, Right@1} ->
result_try(
compile_predicate(Left@1, State),
fun(_use0@4) ->
{Left_sql@1, State1@2} = _use0@4,
result_try(
compile_predicate(Right@1, State1@2),
fun(_use0@5) ->
{Right_sql@1, State2@2} = _use0@5,
{ok,
{<<<<<<<<"("/utf8, Left_sql@1/binary>>/binary,
" OR "/utf8>>/binary,
Right_sql@1/binary>>/binary,
")"/utf8>>,
State2@2}}
end
)
end
);
{'not', Inner} ->
result_try(
compile_predicate(Inner, State),
fun(_use0@6) ->
{Inner_sql, State1@3} = _use0@6,
{ok,
{<<<<"(NOT "/utf8, Inner_sql/binary>>/binary, ")"/utf8>>,
State1@3}}
end
);
{in_list, Lhs@1, Rhs@1} ->
case Rhs@1 of
[] ->
{error, empty_in_list};
_ ->
result_try(
compile_expression(Lhs@1, State),
fun(_use0@7) ->
{Lhs_sql@1, State1@4} = _use0@7,
result_try(
compile_expression_list(Rhs@1, State1@4),
fun(_use0@8) ->
{Rhs_sql@1, State2@3} = _use0@8,
{ok,
{<<<<<<<<"("/utf8, Lhs_sql@1/binary>>/binary,
" IN ("/utf8>>/binary,
Rhs_sql@1/binary>>/binary,
"))"/utf8>>,
State2@3}}
end
)
end
)
end;
{in_subquery, Lhs@2, Rhs@2} ->
result_try(
compile_expression(Lhs@2, State),
fun(_use0@9) ->
{Lhs_sql@2, State1@5} = _use0@9,
result_try(
compile_select_query(Rhs@2, State1@5),
fun(_use0@10) ->
{Rhs_sql@2, State2@4} = _use0@10,
{ok,
{<<<<<<<<"("/utf8, Lhs_sql@2/binary>>/binary,
" IN ("/utf8>>/binary,
Rhs_sql@2/binary>>/binary,
"))"/utf8>>,
State2@4}}
end
)
end
);
{is_null, Expr} ->
result_try(
compile_expression(Expr, State),
fun(_use0@11) ->
{Expr_sql, State1@6} = _use0@11,
{ok,
{<<<<"("/utf8, Expr_sql/binary>>/binary,
" IS NULL)"/utf8>>,
State1@6}}
end
);
{is_not_null, Expr@1} ->
result_try(
compile_expression(Expr@1, State),
fun(_use0@12) ->
{Expr_sql@1, State1@7} = _use0@12,
{ok,
{<<<<"("/utf8, Expr_sql@1/binary>>/binary,
" IS NOT NULL)"/utf8>>,
State1@7}}
end
);
{like, Lhs@3, Rhs@3} ->
result_try(
compile_expression(Lhs@3, State),
fun(_use0@13) ->
{Lhs_sql@3, State1@8} = _use0@13,
result_try(
compile_expression(Rhs@3, State1@8),
fun(_use0@14) ->
{Rhs_sql@3, State2@5} = _use0@14,
{ok,
{<<<<<<<<"("/utf8, Lhs_sql@3/binary>>/binary,
" LIKE "/utf8>>/binary,
Rhs_sql@3/binary>>/binary,
")"/utf8>>,
State2@5}}
end
)
end
);
{ilike, Lhs@4, Rhs@4} ->
result_try(
compile_expression(Lhs@4, State),
fun(_use0@15) ->
{Lhs_sql@4, State1@9} = _use0@15,
result_try(
compile_expression(Rhs@4, State1@9),
fun(_use0@16) ->
{Rhs_sql@4, State2@6} = _use0@16,
{ok,
{<<<<<<<<"("/utf8, Lhs_sql@4/binary>>/binary,
" ILIKE "/utf8>>/binary,
Rhs_sql@4/binary>>/binary,
")"/utf8>>,
State2@6}}
end
)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 687).
-spec compile_join(galchemy@ast@expression:join(), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_join(J, State) ->
{join, Kind, Source, On} = J,
Kind_sql = case Kind of
inner_join ->
<<" INNER JOIN "/utf8>>;
left_join ->
<<" LEFT JOIN "/utf8>>
end,
result_try(
compile_source(Source, State),
fun(_use0) ->
{Source_sql, State1} = _use0,
result_try(
compile_predicate(On, State1),
fun(_use0@1) ->
{On_sql, State2} = _use0@1,
{ok,
{<<<<<<Kind_sql/binary, Source_sql/binary>>/binary,
" ON "/utf8>>/binary,
On_sql/binary>>,
State2}}
end
)
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 673).
-spec compile_joins_loop(
list(galchemy@ast@expression:join()),
list(binary()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_joins_loop(Joins, Acc, State) ->
case Joins of
[] ->
{ok, {concat_strings(reverse(Acc)), State}};
[J | Rest] ->
result_try(
compile_join(J, State),
fun(_use0) ->
{Join_sql, Next_state} = _use0,
compile_joins_loop(Rest, [Join_sql | Acc], Next_state)
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 666).
-spec compile_joins(list(galchemy@ast@expression:join()), compile_state()) -> {ok,
{binary(), compile_state()}} |
{error, compile_error()}.
compile_joins(Joins, State) ->
compile_joins_loop(Joins, [], State).
-file("src\\galchemy\\sql\\compiler.gleam", 702).
-spec compile_where(
gleam@option:option(galchemy@ast@expression:predicate()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_where(Where_, State) ->
case Where_ of
none ->
{ok, {<<""/utf8>>, State}};
{some, Pred} ->
result_try(
compile_predicate(Pred, State),
fun(_use0) ->
{Pred_sql, Next_state} = _use0,
{ok, {<<" WHERE "/utf8, Pred_sql/binary>>, Next_state}}
end
)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 201).
-spec compile_update_with(galchemy@ast@query:update_query(), compiler_config()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_update_with(Q, Config) ->
{update_query, Table, Assignments, Where_, Returning} = Q,
State0 = new_state(Config),
result_try(
compile_assignments(Assignments, State0),
fun(_use0) ->
{Set_sql, State1} = _use0,
result_try(
compile_where(Where_, State1),
fun(_use0@1) ->
{Where_sql, State2} = _use0@1,
result_try(
compile_returning(Returning, State2),
fun(_use0@2) ->
{Returning_sql, State3} = _use0@2,
Sql = <<<<<<<<<<"UPDATE "/utf8,
(compile_table_ref(
Table,
erlang:element(4, State0)
))/binary>>/binary,
" SET "/utf8>>/binary,
Set_sql/binary>>/binary,
Where_sql/binary>>/binary,
Returning_sql/binary>>,
{ok, finalize(Sql, State3)}
end
)
end
)
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 195).
-spec compile_update(galchemy@ast@query:update_query()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_update(Q) ->
compile_update_with(Q, default_config()).
-file("src\\galchemy\\sql\\compiler.gleam", 237).
-spec compile_delete_with(galchemy@ast@query:delete_query(), compiler_config()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_delete_with(Q, Config) ->
{delete_query, Table, Where_, Returning} = Q,
State0 = new_state(Config),
result_try(
compile_where(Where_, State0),
fun(_use0) ->
{Where_sql, State1} = _use0,
result_try(
compile_returning(Returning, State1),
fun(_use0@1) ->
{Returning_sql, State2} = _use0@1,
Sql = <<<<<<"DELETE FROM "/utf8,
(compile_table_ref(
Table,
erlang:element(4, State0)
))/binary>>/binary,
Where_sql/binary>>/binary,
Returning_sql/binary>>,
{ok, finalize(Sql, State2)}
end
)
end
).
-file("src\\galchemy\\sql\\compiler.gleam", 66).
-spec compile_with(galchemy@ast@query:'query'(), compiler_config()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_with(Q, Config) ->
case Q of
{select, S} ->
compile_select_with(S, Config);
{insert, I} ->
compile_insert_with(I, Config);
{update, U} ->
compile_update_with(U, Config);
{delete, D} ->
compile_delete_with(D, Config)
end.
-file("src\\galchemy\\sql\\compiler.gleam", 62).
-spec compile(galchemy@ast@query:'query'()) -> {ok, compiled_query()} |
{error, compile_error()}.
compile(Q) ->
compile_with(Q, default_config()).
-file("src\\galchemy\\sql\\compiler.gleam", 231).
-spec compile_delete(galchemy@ast@query:delete_query()) -> {ok,
compiled_query()} |
{error, compile_error()}.
compile_delete(Q) ->
compile_delete_with(Q, default_config()).
-file("src\\galchemy\\sql\\compiler.gleam", 731).
-spec compile_having(
list(galchemy@ast@expression:expression()),
gleam@option:option(galchemy@ast@expression:predicate()),
compile_state()
) -> {ok, {binary(), compile_state()}} | {error, compile_error()}.
compile_having(Group_by, Having_, State) ->
case Having_ of
none ->
{ok, {<<""/utf8>>, State}};
{some, Pred} ->
case gleam@list:is_empty(Group_by) of
true ->
{error, having_without_group_by};
false ->
result_try(
compile_predicate(Pred, State),
fun(_use0) ->
{Pred_sql, Next_state} = _use0,
{ok,
{<<" HAVING "/utf8, Pred_sql/binary>>,
Next_state}}
end
)
end
end.