From 615dbdc340ff6948b0fbd5eb4d2ce71f1c80d2fd Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Sat, 18 Jul 2026 09:20:07 -0700 Subject: [PATCH] Fix RowBinary tuple encoding re-normalizing nested types Signed-off-by: Sai Asish Y --- lib/ch/row_binary.ex | 4 +++- test/ch/row_binary_test.exs | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/ch/row_binary.ex b/lib/ch/row_binary.ex index f207a720..6bd466f2 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 ad0bb119..789c45c7 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