diff --git a/lib/ch/row_binary.ex b/lib/ch/row_binary.ex index f207a72..6bd466f 100644 --- a/lib/ch/row_binary.ex +++ b/lib/ch/row_binary.ex @@ -321,7 +321,9 @@ defmodule Ch.RowBinary do end def encode({:tuple, types}, values) when is_list(types) and is_list(values) do - encode_row(values, types) + # types were already normalized by encoding_type({:tuple, ts}); use the + # private encoder so we don't re-run encoding_types/1 on normalized types + _encode_row(values, types) end def encode({:tuple, types}, nil) when is_list(types) do diff --git a/test/ch/row_binary_test.exs b/test/ch/row_binary_test.exs index ad0bb11..789c45c 100644 --- a/test/ch/row_binary_test.exs +++ b/test/ch/row_binary_test.exs @@ -173,6 +173,16 @@ defmodule Ch.RowBinaryTest do encode({:map, :string, :string}, [{"hello", "world"}]) end + test "tuple with normalized nested types round-trips" do + dt = ~U[2026-01-02 03:04:05.123Z] + encoded = IO.iodata_to_binary(encode_rows([[{dt}]], ["Tuple(DateTime64(3, 'UTC'))"])) + assert decode_rows(encoded, ["Tuple(DateTime64(3, 'UTC'))"]) == [[{dt}]] + + time = ~T[03:04:05.123456] + encoded = IO.iodata_to_binary(encode_rows([[{time}]], ["Tuple(Time64(6))"])) + assert decode_rows(encoded, ["Tuple(Time64(6))"]) == [[{time}]] + end + test "nil" do assert encode({:nullable, :string}, nil) == 1 assert encode(:string, nil) == 0