Packages

A compile-time safe database library for Gleam - Ecto-inspired schemas, composable queries, and adapter-based persistence

Current section

Files

Jump to
cquill src cquill@error@format.erl
Raw

src/cquill@error@format.erl

-module(cquill@error@format).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/cquill/error/format.gleam").
-export([empty_context/0, with_query/2, with_params/2, with_source_location/4, with_table/2, with_operation/2, format_value/1, format_unique_violation/4, format_foreign_key_violation/5, format_decode_error/4, format_connection_failed/2, format_connection_failed_simple/1, format_connection_timeout/1, format_pool_exhausted/0, format_connection_lost/1, format_foreign_key_violation_error/3, format_check_violation/3, format_not_null_violation/2, format_not_found/1, format_too_many_rows/3, format_rich_transaction_error/2, format_rich_savepoint_error/2, format_query_failed/3, format_timeout/1, format_unique_violation_error/3, format_rich_error/2]).
-export_type([error_context/0, source_location/0, connection_config/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type error_context() :: {error_context,
gleam@option:option(binary()),
gleam@option:option(list(cquill@query@ast:value())),
gleam@option:option(source_location()),
gleam@option:option(binary()),
gleam@option:option(binary())}.
-type source_location() :: {source_location, binary(), integer(), binary()}.
-type connection_config() :: {connection_config,
binary(),
integer(),
binary(),
binary()}.
-file("src/cquill/error/format.gleam", 68).
?DOC(" Create an empty error context\n").
-spec empty_context() -> error_context().
empty_context() ->
{error_context, none, none, none, none, none}.
-file("src/cquill/error/format.gleam", 79).
?DOC(" Create a context with query information\n").
-spec with_query(error_context(), binary()) -> error_context().
with_query(Context, Query) ->
{error_context,
{some, Query},
erlang:element(3, Context),
erlang:element(4, Context),
erlang:element(5, Context),
erlang:element(6, Context)}.
-file("src/cquill/error/format.gleam", 84).
?DOC(" Create a context with query parameters\n").
-spec with_params(error_context(), list(cquill@query@ast:value())) -> error_context().
with_params(Context, Params) ->
{error_context,
erlang:element(2, Context),
{some, Params},
erlang:element(4, Context),
erlang:element(5, Context),
erlang:element(6, Context)}.
-file("src/cquill/error/format.gleam", 89).
?DOC(" Create a context with source location\n").
-spec with_source_location(error_context(), binary(), integer(), binary()) -> error_context().
with_source_location(Context, File, Line, Function) ->
{error_context,
erlang:element(2, Context),
erlang:element(3, Context),
{some, {source_location, File, Line, Function}},
erlang:element(5, Context),
erlang:element(6, Context)}.
-file("src/cquill/error/format.gleam", 102).
?DOC(" Create a context with table name\n").
-spec with_table(error_context(), binary()) -> error_context().
with_table(Context, Table) ->
{error_context,
erlang:element(2, Context),
erlang:element(3, Context),
erlang:element(4, Context),
{some, Table},
erlang:element(6, Context)}.
-file("src/cquill/error/format.gleam", 107).
?DOC(" Create a context with operation name\n").
-spec with_operation(error_context(), binary()) -> error_context().
with_operation(Context, Operation) ->
{error_context,
erlang:element(2, Context),
erlang:element(3, Context),
erlang:element(4, Context),
erlang:element(5, Context),
{some, Operation}}.
-file("src/cquill/error/format.gleam", 131).
?DOC(" Format a float value for display\n").
-spec format_float(float()) -> binary().
format_float(F) ->
gleam@string:inspect(F).
-file("src/cquill/error/format.gleam", 137).
?DOC(" Mask potentially sensitive values (emails, etc.)\n").
-spec mask_sensitive_value(binary()) -> binary().
mask_sensitive_value(Value) ->
Length = string:length(Value),
case Length of
L when L =< 3 ->
Value;
L@1 when L@1 =< 8 ->
Visible = gleam@string:slice(Value, 0, 2),
<<Visible/binary,
(gleam@string:repeat(<<"*"/utf8>>, L@1 - 2))/binary>>;
_ ->
Visible_start = gleam@string:slice(Value, 0, 3),
Visible_end = gleam@string:slice(Value, Length - 2, 2),
<<<<Visible_start/binary, "***"/utf8>>/binary, Visible_end/binary>>
end.
-file("src/cquill/error/format.gleam", 116).
?DOC(" Format a Value for display in error messages\n").
-spec format_value(cquill@query@ast:value()) -> binary().
format_value(Value) ->
case Value of
{int_value, I} ->
erlang:integer_to_binary(I);
{float_value, F} ->
format_float(F);
{string_value, S} ->
<<<<"\""/utf8, (mask_sensitive_value(S))/binary>>/binary,
"\""/utf8>>;
{bool_value, true} ->
<<"true"/utf8>>;
{bool_value, false} ->
<<"false"/utf8>>;
null_value ->
<<"NULL"/utf8>>;
{param_value, Pos} ->
<<"$"/utf8, (erlang:integer_to_binary(Pos))/binary>>;
{list_value, Values} ->
<<<<"["/utf8,
(gleam@string:join(
gleam@list:map(Values, fun format_value/1),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>
end.
-file("src/cquill/error/format.gleam", 158).
?DOC(" Format a unique constraint violation with rich context\n").
-spec format_unique_violation(
binary(),
binary(),
binary(),
cquill@query@ast:value()
) -> binary().
format_unique_violation(Constraint, Table, Column, Value) ->
Value_str = format_value(Value),
Column_underline = gleam@string:repeat(<<"^"/utf8>>, string:length(Column)),
gleam@string:join(
[<<"Error: UniqueConstraintViolation"/utf8>>,
<<""/utf8>>,
<<<<<<<<<<<<" INSERT INTO "/utf8, Table/binary>>/binary,
" ("/utf8>>/binary,
Column/binary>>/binary,
", ...) VALUES ("/utf8>>/binary,
Value_str/binary>>/binary,
", ...)"/utf8>>,
<<" "/utf8, Column_underline/binary>>,
<<""/utf8>>,
<<<<" Unique constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<<<<<<<" A record with "/utf8, Column/binary>>/binary,
" = "/utf8>>/binary,
Value_str/binary>>/binary,
" already exists."/utf8>>,
<<""/utf8>>,
<<" Hint: Use `on_conflict_do_nothing()` to ignore duplicates,"/utf8>>,
<<" or check existence first with `repo.exists(...)`."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 230).
?DOC(" Format a foreign key constraint violation with rich context\n").
-spec format_foreign_key_violation(
binary(),
binary(),
binary(),
binary(),
binary()
) -> binary().
format_foreign_key_violation(
Constraint,
Table,
Column,
References_table,
References_column
) ->
gleam@string:join(
[<<"Error: ForeignKeyViolation"/utf8>>,
<<""/utf8>>,
<<<<" Foreign key constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<<<<<<<<<<<<<<<" The value in "/utf8, Table/binary>>/binary,
"."/utf8>>/binary,
Column/binary>>/binary,
" does not exist in "/utf8>>/binary,
References_table/binary>>/binary,
"."/utf8>>/binary,
References_column/binary>>/binary,
"."/utf8>>,
<<""/utf8>>,
<<" Hint: Ensure the referenced record exists before inserting,"/utf8>>,
<<" or use ON DELETE SET NULL if the reference is optional."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 352).
?DOC(" Format a decode error with detailed context\n").
-spec format_decode_error(integer(), binary(), binary(), binary()) -> binary().
format_decode_error(Row, Column, Expected, Found) ->
gleam@string:join(
[<<"Error: DecodeError"/utf8>>,
<<""/utf8>>,
<<<<<<<<" Failed to decode row "/utf8,
(erlang:integer_to_binary(Row))/binary>>/binary,
", column \""/utf8>>/binary,
Column/binary>>/binary,
"\"."/utf8>>,
<<""/utf8>>,
<<" Expected: "/utf8, Expected/binary>>,
<<" Found: "/utf8, Found/binary>>,
<<""/utf8>>,
<<" Hint: Check that your decoder matches the database column type."/utf8>>,
<<" The schema might be out of sync — verify column types match."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 478).
?DOC(" Format a connection failed error with troubleshooting hints\n").
-spec format_connection_failed(binary(), connection_config()) -> binary().
format_connection_failed(Reason, Config) ->
Host_str = <<<<(erlang:element(2, Config))/binary, ":"/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Config)))/binary>>,
gleam@string:join(
[<<"Error: ConnectionFailed"/utf8>>,
<<""/utf8>>,
<<" Could not connect to database at "/utf8, Host_str/binary>>,
<<""/utf8>>,
<<" Reason: "/utf8, Reason/binary>>,
<<""/utf8>>,
<<" Check:"/utf8>>,
<<" - Is the database server running?"/utf8>>,
<<<<" - Is the database \""/utf8,
(erlang:element(4, Config))/binary>>/binary,
"\" created?"/utf8>>,
<<<<" - Are the credentials for user \""/utf8,
(erlang:element(5, Config))/binary>>/binary,
"\" correct?"/utf8>>,
<<<<" - Is port "/utf8,
(erlang:integer_to_binary(erlang:element(3, Config)))/binary>>/binary,
" accessible (firewall/network)?"/utf8>>,
<<" - Is the connection string/host correct?"/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 507).
?DOC(" Format a connection failed error with minimal context\n").
-spec format_connection_failed_simple(binary()) -> binary().
format_connection_failed_simple(Reason) ->
gleam@string:join(
[<<"Error: ConnectionFailed"/utf8>>,
<<""/utf8>>,
<<" Could not establish database connection."/utf8>>,
<<""/utf8>>,
<<" Reason: "/utf8, Reason/binary>>,
<<""/utf8>>,
<<" Check:"/utf8>>,
<<" - Is the database server running?"/utf8>>,
<<" - Is the database created?"/utf8>>,
<<" - Are the credentials correct?"/utf8>>,
<<" - Is the host and port accessible?"/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 528).
?DOC(" Format a connection timeout error\n").
-spec format_connection_timeout(gleam@option:option(connection_config())) -> binary().
format_connection_timeout(Config) ->
Host_info = case Config of
{some, C} ->
<<<<<<" to "/utf8, (erlang:element(2, C))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, C)))/binary>>;
none ->
<<""/utf8>>
end,
gleam@string:join(
[<<"Error: ConnectionTimeout"/utf8>>,
<<""/utf8>>,
<<<<" Connection attempt"/utf8, Host_info/binary>>/binary,
" timed out."/utf8>>,
<<""/utf8>>,
<<" Possible causes:"/utf8>>,
<<" - Database server is not responding"/utf8>>,
<<" - Network connectivity issues"/utf8>>,
<<" - Firewall blocking the connection"/utf8>>,
<<" - Server is overloaded"/utf8>>,
<<""/utf8>>,
<<" Hint: Check network connectivity and server status."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 554).
?DOC(" Format a pool exhausted error\n").
-spec format_pool_exhausted() -> binary().
format_pool_exhausted() ->
gleam@string:join(
[<<"Error: PoolExhausted"/utf8>>,
<<""/utf8>>,
<<" All database connections in the pool are in use."/utf8>>,
<<""/utf8>>,
<<" Possible causes:"/utf8>>,
<<" - Too many concurrent requests"/utf8>>,
<<" - Long-running queries holding connections"/utf8>>,
<<" - Connection leaks (connections not being returned)"/utf8>>,
<<""/utf8>>,
<<" Hint: Increase pool size, optimize slow queries,"/utf8>>,
<<" or check for connection leaks in your application."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 575).
?DOC(" Format a connection lost error\n").
-spec format_connection_lost(binary()) -> binary().
format_connection_lost(Reason) ->
gleam@string:join(
[<<"Error: ConnectionLost"/utf8>>,
<<""/utf8>>,
<<" The database connection was lost during the operation."/utf8>>,
<<""/utf8>>,
<<" Reason: "/utf8, Reason/binary>>,
<<""/utf8>>,
<<" Possible causes:"/utf8>>,
<<" - Database server was restarted"/utf8>>,
<<" - Network interruption"/utf8>>,
<<" - Server terminated the connection (idle timeout)"/utf8>>,
<<""/utf8>>,
<<" Hint: This error is often transient — retry the operation."/utf8>>,
<<" If persistent, check database server logs."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 975).
?DOC(" Format a not supported error\n").
-spec format_not_supported(binary()) -> binary().
format_not_supported(Operation) ->
gleam@string:join(
[<<"Error: NotSupported"/utf8>>,
<<""/utf8>>,
<<<<" Operation \""/utf8, Operation/binary>>/binary,
"\" is not supported by this adapter."/utf8>>,
<<""/utf8>>,
<<" Hint: Check the adapter documentation for supported operations,"/utf8>>,
<<" or use a different adapter that supports this feature."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 1015).
?DOC(" Format the operation line from context\n").
-spec format_operation_line(error_context()) -> binary().
format_operation_line(Context) ->
case {erlang:element(6, Context), erlang:element(5, Context)} of
{{some, Op}, {some, Table}} ->
<<<<<<" During: "/utf8, Op/binary>>/binary, " on "/utf8>>/binary,
Table/binary>>;
{{some, Op@1}, none} ->
<<" During: "/utf8, Op@1/binary>>;
{none, {some, Table@1}} ->
<<" Table: "/utf8, Table@1/binary>>;
{none, none} ->
<<""/utf8>>
end.
-file("src/cquill/error/format.gleam", 1042).
?DOC(" Format source location if available\n").
-spec format_source_location(gleam@option:option(source_location())) -> binary().
format_source_location(Location) ->
case Location of
{some, Loc} ->
<<<<<<<<<<<<" at "/utf8, (erlang:element(2, Loc))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Loc)))/binary>>/binary,
" in "/utf8>>/binary,
(erlang:element(4, Loc))/binary>>/binary,
"()"/utf8>>;
none ->
<<""/utf8>>
end.
-file("src/cquill/error/format.gleam", 262).
?DOC(" Format a foreign key violation from an AdapterError\n").
-spec format_foreign_key_violation_error(binary(), binary(), error_context()) -> binary().
format_foreign_key_violation_error(Constraint, Detail, Context) ->
Table = gleam@option:unwrap(erlang:element(5, Context), <<"table"/utf8>>),
gleam@string:join(
[<<"Error: ForeignKeyViolation"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<" Foreign key constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<" Detail: "/utf8, Detail/binary>>,
<<""/utf8>>,
<<" The referenced record in the parent table does not exist."/utf8>>,
<<""/utf8>>,
<<<<" Hint: Ensure the referenced record exists before inserting into "/utf8,
Table/binary>>/binary,
","/utf8>>,
<<" or verify the foreign key value is correct."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 293).
?DOC(" Format a check constraint violation\n").
-spec format_check_violation(binary(), binary(), error_context()) -> binary().
format_check_violation(Constraint, Detail, Context) ->
gleam@string:join(
[<<"Error: CheckConstraintViolation"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<" Check constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<" Detail: "/utf8, Detail/binary>>,
<<""/utf8>>,
<<" The value did not satisfy the check constraint condition."/utf8>>,
<<""/utf8>>,
<<" Hint: Review the constraint definition and ensure"/utf8>>,
<<" the data meets all validation requirements."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 320).
?DOC(" Format a NOT NULL constraint violation\n").
-spec format_not_null_violation(binary(), error_context()) -> binary().
format_not_null_violation(Column, Context) ->
Table = gleam@option:unwrap(erlang:element(5, Context), <<"table"/utf8>>),
gleam@string:join(
[<<"Error: NotNullViolation"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<<<<<" Column \""/utf8, Column/binary>>/binary,
"\" in table \""/utf8>>/binary,
Table/binary>>/binary,
"\" cannot be NULL."/utf8>>,
<<""/utf8>>,
<<<<" Hint: Provide a value for the \""/utf8, Column/binary>>/binary,
"\" column,"/utf8>>,
<<" or alter the column to allow NULL values."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 407).
?DOC(" Format a \"not found\" error\n").
-spec format_not_found(error_context()) -> binary().
format_not_found(Context) ->
Table = gleam@option:unwrap(
erlang:element(5, Context),
<<"the table"/utf8>>
),
gleam@string:join(
[<<"Error: RecordNotFound"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<" No record was found in "/utf8, Table/binary>>/binary,
" matching the query."/utf8>>,
<<""/utf8>>,
<<" Hint: Verify the query conditions are correct,"/utf8>>,
<<" or use `repo.one_or_none(...)` if the record may not exist."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 428).
?DOC(" Format a \"too many rows\" error\n").
-spec format_too_many_rows(integer(), integer(), error_context()) -> binary().
format_too_many_rows(Expected, Got, Context) ->
gleam@string:join(
[<<"Error: TooManyRows"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<<<<<" Expected "/utf8,
(erlang:integer_to_binary(Expected))/binary>>/binary,
" row(s), but found "/utf8>>/binary,
(erlang:integer_to_binary(Got))/binary>>/binary,
"."/utf8>>,
<<""/utf8>>,
<<" Hint: Add a LIMIT clause or use more specific conditions,"/utf8>>,
<<" or use `repo.all(...)` if multiple results are expected."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 602).
?DOC(" Format a transaction error with rich context\n").
-spec format_rich_transaction_error(
cquill@error:transaction_error(any()),
error_context()
) -> binary().
format_rich_transaction_error(Error, Context) ->
case Error of
{user_error, _} ->
gleam@string:join(
[<<"Error: TransactionAborted"/utf8>>,
<<""/utf8>>,
<<" Transaction was aborted due to a user error."/utf8>>,
<<""/utf8>>,
<<" The transaction function returned an error and changes"/utf8>>,
<<" were rolled back automatically."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
);
{adapter_transaction_error, Adapter_err} ->
gleam@string:join(
[<<"Error: TransactionAdapterError"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<" "/utf8,
(cquill@error:format_error(Adapter_err))/binary>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
);
{begin_failed, Reason} ->
gleam@string:join(
[<<"Error: TransactionBeginFailed"/utf8>>,
<<""/utf8>>,
<<" Failed to begin transaction: "/utf8, Reason/binary>>,
<<""/utf8>>,
<<" Hint: Check database connectivity and permissions."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
{commit_failed, Reason@1} ->
gleam@string:join(
[<<"Error: TransactionCommitFailed"/utf8>>,
<<""/utf8>>,
<<" Failed to commit transaction: "/utf8, Reason@1/binary>>,
<<""/utf8>>,
<<" Changes may have been rolled back."/utf8>>,
<<""/utf8>>,
<<" Hint: The transaction may have been invalidated by a constraint"/utf8>>,
<<" violation or other error during execution."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
rolled_back ->
gleam@string:join(
[<<"Error: TransactionRolledBack"/utf8>>,
<<""/utf8>>,
<<" Transaction was explicitly rolled back."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
{transaction_rollback, Reason@2} ->
gleam@string:join(
[<<"Error: TransactionRolledBack"/utf8>>,
<<""/utf8>>,
<<" Transaction was rolled back: "/utf8, Reason@2/binary>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
transaction_connection_lost ->
gleam@string:join(
[<<"Error: TransactionConnectionLost"/utf8>>,
<<""/utf8>>,
<<" The database connection was lost during the transaction."/utf8>>,
<<""/utf8>>,
<<" All changes in this transaction were rolled back."/utf8>>,
<<""/utf8>>,
<<" Hint: This error is often transient — retry the entire transaction."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
nested_transaction_error ->
gleam@string:join(
[<<"Error: NestedTransactionError"/utf8>>,
<<""/utf8>>,
<<" Attempted to start a nested transaction."/utf8>>,
<<""/utf8>>,
<<" Nested transactions are not supported by this adapter."/utf8>>,
<<""/utf8>>,
<<" Hint: Use savepoints instead with `repo.savepoint(...)` for"/utf8>>,
<<" partial rollback capabilities within a transaction."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
transaction_timeout ->
gleam@string:join(
[<<"Error: TransactionTimeout"/utf8>>,
<<""/utf8>>,
<<" The transaction timed out."/utf8>>,
<<""/utf8>>,
<<" Possible causes:"/utf8>>,
<<" - Long-running queries within the transaction"/utf8>>,
<<" - Deadlock with another transaction"/utf8>>,
<<" - Lock contention"/utf8>>,
<<""/utf8>>,
<<" Hint: Optimize queries, reduce transaction scope,"/utf8>>,
<<" or increase the timeout if appropriate."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
serialization_failure ->
gleam@string:join(
[<<"Error: SerializationFailure"/utf8>>,
<<""/utf8>>,
<<" Transaction could not serialize access due to concurrent updates."/utf8>>,
<<""/utf8>>,
<<" Another transaction modified data that this transaction was"/utf8>>,
<<" reading or writing."/utf8>>,
<<""/utf8>>,
<<" Hint: This error indicates a conflict — retry the transaction."/utf8>>,
<<" For frequently conflicting operations, consider using"/utf8>>,
<<" explicit locking or adjusting the isolation level."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
)
end.
-file("src/cquill/error/format.gleam", 762).
?DOC(" Format a savepoint error with rich context\n").
-spec format_rich_savepoint_error(
cquill@error:savepoint_error(any()),
error_context()
) -> binary().
format_rich_savepoint_error(Error, Context) ->
case Error of
{savepoint_not_found, Name} ->
gleam@string:join(
[<<"Error: SavepointNotFound"/utf8>>,
<<""/utf8>>,
<<<<" Savepoint \""/utf8, Name/binary>>/binary,
"\" does not exist."/utf8>>,
<<""/utf8>>,
<<" Hint: Ensure the savepoint was created with `repo.savepoint(...)`"/utf8>>,
<<" and has not been released or rolled back."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
);
{savepoint_adapter_error, Adapter_err} ->
gleam@string:join(
[<<"Error: SavepointAdapterError"/utf8>>,
<<""/utf8>>,
<<" "/utf8,
(cquill@error:format_error(Adapter_err))/binary>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
);
{savepoint_user_error, _} ->
gleam@string:join(
[<<"Error: SavepointAborted"/utf8>>,
<<""/utf8>>,
<<" Savepoint was aborted due to a user error."/utf8>>,
<<""/utf8>>,
<<" Changes since the savepoint were rolled back."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
);
{savepoint_creation_failed, Reason} ->
gleam@string:join(
[<<"Error: SavepointCreationFailed"/utf8>>,
<<""/utf8>>,
<<" Failed to create savepoint: "/utf8, Reason/binary>>,
<<""/utf8>>,
<<" Hint: Ensure you are within an active transaction."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
{savepoint_release_failed, Reason@1} ->
gleam@string:join(
[<<"Error: SavepointReleaseFailed"/utf8>>,
<<""/utf8>>,
<<" Failed to release savepoint: "/utf8, Reason@1/binary>>,
<<""/utf8>>],
<<"\n"/utf8>>
);
savepoint_no_transaction ->
gleam@string:join(
[<<"Error: SavepointNoTransaction"/utf8>>,
<<""/utf8>>,
<<" Cannot use savepoint outside of a transaction."/utf8>>,
<<""/utf8>>,
<<" Savepoints require an active transaction context."/utf8>>,
<<""/utf8>>,
<<" Hint: Wrap your code in `repo.transaction(...)` first,"/utf8>>,
<<" then use `repo.savepoint(...)` within it."/utf8>>,
<<""/utf8>>],
<<"\n"/utf8>>
)
end.
-file("src/cquill/error/format.gleam", 906).
?DOC(" Format a generic constraint violation\n").
-spec format_generic_constraint_violation(binary(), binary(), error_context()) -> binary().
format_generic_constraint_violation(Constraint, Detail, Context) ->
gleam@string:join(
[<<"Error: ConstraintViolation"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<" Constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<" Detail: "/utf8, Detail/binary>>,
<<""/utf8>>,
<<" Hint: Review the constraint definition and ensure"/utf8>>,
<<" the data meets all requirements."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 931).
?DOC(" Format a stale data error\n").
-spec format_stale_data(binary(), binary(), error_context()) -> binary().
format_stale_data(Expected, Actual, Context) ->
gleam@string:join(
[<<"Error: StaleData"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<" The record was modified by another process."/utf8>>,
<<""/utf8>>,
<<" Expected version: "/utf8, Expected/binary>>,
<<" Actual version: "/utf8, Actual/binary>>,
<<""/utf8>>,
<<" Hint: Refresh the record and retry the operation,"/utf8>>,
<<" or use optimistic locking with retry logic."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 957).
?DOC(" Format a data integrity error\n").
-spec format_data_integrity_error(binary(), error_context()) -> binary().
format_data_integrity_error(Message, Context) ->
gleam@string:join(
[<<"Error: DataIntegrityError"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<" "/utf8, Message/binary>>,
<<""/utf8>>,
<<" The database detected an integrity issue."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 991).
?DOC(" Format an adapter-specific error\n").
-spec format_adapter_specific(binary(), binary(), error_context()) -> binary().
format_adapter_specific(Code, Message, Context) ->
gleam@string:join(
[<<<<"Error: AdapterSpecific ["/utf8, Code/binary>>/binary, "]"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<" "/utf8, Message/binary>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 1082).
?DOC(" Get hint based on error message content\n").
-spec get_hint_from_message(binary()) -> binary().
get_hint_from_message(Lower_message) ->
case gleam_stdlib:contains_string(Lower_message, <<"syntax"/utf8>>) of
true ->
<<" Hint: Check the query syntax for errors."/utf8>>;
false ->
case gleam_stdlib:contains_string(
Lower_message,
<<"permission"/utf8>>
)
orelse gleam_stdlib:contains_string(
Lower_message,
<<"privilege"/utf8>>
) of
true ->
<<" Hint: Check database user permissions."/utf8>>;
false ->
case gleam_stdlib:contains_string(
Lower_message,
<<"table"/utf8>>
) of
true ->
<<" Hint: Verify the table exists and is accessible."/utf8>>;
false ->
case gleam_stdlib:contains_string(
Lower_message,
<<"column"/utf8>>
) of
true ->
<<" Hint: Verify the column name is correct."/utf8>>;
false ->
<<" Hint: Check the query and parameters for errors."/utf8>>
end
end
end
end.
-file("src/cquill/error/format.gleam", 1057).
?DOC(" Generate a hint based on the query error message and code\n").
-spec format_query_hint(binary(), gleam@option:option(binary())) -> binary().
format_query_hint(Message, Code) ->
Lower_message = string:lowercase(Message),
case Code of
{some, <<"42P01"/utf8>>} ->
<<" Hint: The table does not exist. Check the table name spelling,\n"/utf8,
" run migrations, or verify the schema."/utf8>>;
{some, <<"42703"/utf8>>} ->
<<" Hint: The column does not exist. Check the column name spelling\n"/utf8,
" or verify the schema definition."/utf8>>;
{some, <<"42601"/utf8>>} ->
<<" Hint: There is a syntax error in the query. Check for typos,\n"/utf8,
" missing commas, or incorrect SQL syntax."/utf8>>;
{some, <<"42501"/utf8>>} ->
<<" Hint: Insufficient privileges. Check that the database user\n"/utf8,
" has the required permissions for this operation."/utf8>>;
_ ->
get_hint_from_message(Lower_message)
end.
-file("src/cquill/error/format.gleam", 1105).
?DOC(" Truncate a long query for display\n").
-spec truncate_query(binary()) -> binary().
truncate_query(Query) ->
Max_length = 200,
case string:length(Query) > Max_length of
true ->
<<(gleam@string:slice(Query, 0, Max_length))/binary, "..."/utf8>>;
false ->
Query
end.
-file("src/cquill/error/format.gleam", 1025).
?DOC(" Format query context (query + params)\n").
-spec format_query_context(error_context()) -> binary().
format_query_context(Context) ->
case erlang:element(2, Context) of
{some, Query} ->
Params_str = case erlang:element(3, Context) of
{some, Params} ->
<<<<"\n Params: ["/utf8,
(gleam@string:join(
gleam@list:map(Params, fun format_value/1),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>;
none ->
<<""/utf8>>
end,
<<<<" Query: "/utf8, (truncate_query(Query))/binary>>/binary,
Params_str/binary>>;
none ->
format_operation_line(Context)
end.
-file("src/cquill/error/format.gleam", 380).
?DOC(" Format a query failed error with context\n").
-spec format_query_failed(
binary(),
gleam@option:option(binary()),
error_context()
) -> binary().
format_query_failed(Message, Code, Context) ->
Code_str = case Code of
{some, C} ->
<<<<" ["/utf8, C/binary>>/binary, "]"/utf8>>;
none ->
<<""/utf8>>
end,
gleam@string:join(
[<<"Error: QueryFailed"/utf8, Code_str/binary>>,
<<""/utf8>>,
format_query_context(Context),
<<""/utf8>>,
<<" "/utf8, Message/binary>>,
<<""/utf8>>,
format_query_hint(Message, Code),
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 455).
?DOC(" Format a timeout error\n").
-spec format_timeout(error_context()) -> binary().
format_timeout(Context) ->
gleam@string:join(
[<<"Error: Timeout"/utf8>>,
<<""/utf8>>,
format_query_context(Context),
<<""/utf8>>,
<<" The operation timed out waiting for a response."/utf8>>,
<<""/utf8>>,
<<" Hint: The query may be too slow — consider adding indexes,"/utf8>>,
<<" optimizing the query, or increasing the timeout."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 1114).
?DOC(" Extract column name from unique constraint detail\n").
-spec extract_column_from_unique_detail(binary()) -> binary().
extract_column_from_unique_detail(Detail) ->
case gleam@string:split(Detail, <<"("/utf8>>) of
[_, Rest | _] ->
case gleam@string:split(Rest, <<")"/utf8>>) of
[Column | _] ->
Column;
_ ->
<<"column"/utf8>>
end;
_ ->
<<"column"/utf8>>
end.
-file("src/cquill/error/format.gleam", 1127).
?DOC(" Extract value from unique constraint detail\n").
-spec extract_value_from_unique_detail(binary()) -> binary().
extract_value_from_unique_detail(Detail) ->
case gleam@string:split(Detail, <<"=("/utf8>>) of
[_, Rest | _] ->
case gleam@string:split(Rest, <<")"/utf8>>) of
[Value | _] ->
mask_sensitive_value(Value);
_ ->
<<"(value)"/utf8>>
end;
_ ->
<<"(value)"/utf8>>
end.
-file("src/cquill/error/format.gleam", 193).
?DOC(" Format a unique violation from an AdapterError\n").
-spec format_unique_violation_error(binary(), binary(), error_context()) -> binary().
format_unique_violation_error(Constraint, Detail, Context) ->
Table = gleam@option:unwrap(erlang:element(5, Context), <<"table"/utf8>>),
Column = extract_column_from_unique_detail(Detail),
Value_str = extract_value_from_unique_detail(Detail),
gleam@string:join(
[<<"Error: UniqueConstraintViolation"/utf8>>,
<<""/utf8>>,
format_operation_line(Context),
<<""/utf8>>,
<<<<" Unique constraint \""/utf8, Constraint/binary>>/binary,
"\" violated."/utf8>>,
<<""/utf8>>,
<<" Detail: "/utf8, Detail/binary>>,
<<""/utf8>>,
<<<<<<<<<<<<" A record with "/utf8, Column/binary>>/binary,
" = "/utf8>>/binary,
Value_str/binary>>/binary,
" already exists in "/utf8>>/binary,
Table/binary>>/binary,
"."/utf8>>,
<<""/utf8>>,
<<" Hint: Use `on_conflict_do_nothing()` to ignore duplicates,"/utf8>>,
<<" or check existence first with `repo.exists(...)`."/utf8>>,
<<""/utf8>>,
format_source_location(erlang:element(4, Context))],
<<"\n"/utf8>>
).
-file("src/cquill/error/format.gleam", 855).
?DOC(" Format any AdapterError with rich context\n").
-spec format_rich_error(cquill@error:adapter_error(), error_context()) -> binary().
format_rich_error(Error, Context) ->
case Error of
not_found ->
format_not_found(Context);
{too_many_rows, Expected, Got} ->
format_too_many_rows(Expected, Got, Context);
{connection_failed, Reason} ->
format_connection_failed_simple(Reason);
connection_timeout ->
format_connection_timeout(none);
pool_exhausted ->
format_pool_exhausted();
{connection_lost, Reason@1} ->
format_connection_lost(Reason@1);
{query_failed, Message, Code} ->
format_query_failed(Message, Code, Context);
{decode_failed, Row, Column, Expected@1, Got@1} ->
format_decode_error(Row, Column, Expected@1, Got@1);
timeout ->
format_timeout(Context);
{unique_violation, Constraint, Detail} ->
format_unique_violation_error(Constraint, Detail, Context);
{foreign_key_violation, Constraint@1, Detail@1} ->
format_foreign_key_violation_error(Constraint@1, Detail@1, Context);
{check_violation, Constraint@2, Detail@2} ->
format_check_violation(Constraint@2, Detail@2, Context);
{not_null_violation, Column@1} ->
format_not_null_violation(Column@1, Context);
{constraint_violation, Constraint@3, Detail@3} ->
format_generic_constraint_violation(Constraint@3, Detail@3, Context);
{stale_data, Expected@2, Actual} ->
format_stale_data(Expected@2, Actual, Context);
{data_integrity_error, Message@1} ->
format_data_integrity_error(Message@1, Context);
{not_supported, Operation} ->
format_not_supported(Operation);
{adapter_specific, Code@1, Message@2} ->
format_adapter_specific(Code@1, Message@2, Context)
end.