diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c8a2d..d66368d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +- Fixed a bug where an authentication error would result in a failure with a + confusing error message. + ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) + - Added support for the `timestamp` type, represented as tuples `#(#(Int, Int, Int), #(Int Int Int))` with `#(#(year, month, day), #(hour, minute, second))`. diff --git a/src/squirrel/internal/database/postgres_protocol.gleam b/src/squirrel/internal/database/postgres_protocol.gleam index 20fbe46..922c35b 100644 --- a/src/squirrel/internal/database/postgres_protocol.gleam +++ b/src/squirrel/internal/database/postgres_protocol.gleam @@ -1370,7 +1370,16 @@ fn decode_fields_rec(binary, result) { case bit_array.to_string(head) { Ok(value) -> decode_fields_rec(tail, [#(field_type, value), ..result]) - Error(Nil) -> dec_err("invalid field encoding", binary) + Error(Nil) -> + // Sometimes Postgres can reply with a string that is not utf8 + // encoded, in that case we try our best to still get something + // out of it. + // If all fails, we still return an error. + case recover_string(head) { + Ok(value) -> + decode_fields_rec(tail, [#(field_type, value), ..result]) + Error(Nil) -> dec_err("invalid field encoding", binary) + } } } _ -> dec_err("invalid field separator", binary) @@ -1380,6 +1389,9 @@ fn decode_fields_rec(binary, result) { } } +@external(erlang, "squirrel_ffi", "recover_string") +fn recover_string(value: a) -> Result(String, Nil) + type BinarySplitOption { Global } diff --git a/src/squirrel_ffi.erl b/src/squirrel_ffi.erl index 5fdf79f..5fd25f0 100644 --- a/src/squirrel_ffi.erl +++ b/src/squirrel_ffi.erl @@ -1,5 +1,13 @@ -module(squirrel_ffi). --export([unique/0, exit/1]). +-export([unique/0, exit/1, recover_string/1]). + +recover_string(Binary) -> + try + Chars = lists:flatten(io_lib:format("~ts", [Binary])), + {ok, unicode:characters_to_binary(Chars)} + catch + _ -> {error, nil} + end. unique() -> erlang:unique_integer([positive]).