diff --git a/CHANGELOG.md b/CHANGELOG.md index 28fcbf7..78530ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- raise on invalid UInt8 and Int8 when encoding RowBinary https://github.com/plausible/ch/pull/180 + ## 0.2.6 (2024-05-30) - fix query encoding for datetimes where the microseconds value starts with zeroes `~U[****-**-** **:**:**.0*****]` https://github.com/plausible/ch/pull/175 diff --git a/lib/ch/row_binary.ex b/lib/ch/row_binary.ex index 22d477b..d2081b7 100644 --- a/lib/ch/row_binary.ex +++ b/lib/ch/row_binary.ex @@ -195,13 +195,23 @@ defmodule Ch.RowBinary do def encode({:fixed_string, size}, nil), do: <<0::size(size * 8)>> - def encode(:u8, u) when is_integer(u), do: u + # UInt8 — [0 : 255] + def encode(:u8, u) when is_integer(u) and u >= 0 and u <= 255, do: u def encode(:u8, nil), do: 0 - def encode(:i8, i) when is_integer(i) and i >= 0, do: i - def encode(:i8, i) when is_integer(i), do: <> + def encode(:u8, term) do + raise ArgumentError, "invalid UInt8: #{inspect(term)}" + end + + # Int8 — [-128 : 127] + def encode(:i8, i) when is_integer(i) and i >= 0 and i <= 127, do: i + def encode(:i8, i) when is_integer(i) and i < 0 and i >= -128, do: <> def encode(:i8, nil), do: 0 + def encode(:i8, term) do + raise ArgumentError, "invalid Int8: #{inspect(term)}" + end + for size <- [16, 32, 64, 128, 256] do def encode(unquote(:"u#{size}"), u) when is_integer(u) do <> diff --git a/test/ch/row_binary_test.exs b/test/ch/row_binary_test.exs index 497a61d..908a182 100644 --- a/test/ch/row_binary_test.exs +++ b/test/ch/row_binary_test.exs @@ -305,4 +305,20 @@ defmodule Ch.RowBinaryTest do assert decode_rows(<<1, 2>>, [:u8, :u8]) == [[1, 2]] end end + + # TODO maybe use stream_data? + describe "invalid arguments" do + # https://github.com/plausible/ch/issues/166 + test "for UInt8" do + assert_raise ArgumentError, "invalid UInt8: 256", fn -> encode(:u8, 256) end + assert_raise ArgumentError, "invalid UInt8: -1", fn -> encode(:u8, -1) end + assert_raise ArgumentError, "invalid UInt8: \"a\"", fn -> encode(:u8, "a") end + end + + test "for Int8" do + assert_raise ArgumentError, "invalid Int8: 128", fn -> encode(:i8, 128) end + assert_raise ArgumentError, "invalid Int8: -129", fn -> encode(:i8, -129) end + assert_raise ArgumentError, "invalid Int8: \"a\"", fn -> encode(:i8, "a") end + end + end end