Skip to content

Commit e19815a

Browse files
authored
Optimize variant decoding (#402)
1 parent c6bb5b2 commit e19815a

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

lib/ch/row_binary.ex

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ defmodule Ch.RowBinary do
754754
end
755755

756756
defp decoding_type({:variant = v, ts}) do
757-
{v, Enum.map(ts, &decoding_type/1)}
757+
{v, ts |> Enum.map(&decoding_type/1) |> List.to_tuple()}
758758
end
759759

760760
defp decoding_type({:map = m, kt, vt}) do
@@ -1397,10 +1397,14 @@ defmodule Ch.RowBinary do
13971397
decode_rows(types_rest, bin, [nil | row], rows, types)
13981398

13991399
# TODO varint?
1400-
<<variant_type_index::8, bin::bytes>> ->
1401-
variant_type = Enum.at(variant_types, variant_type_index)
1400+
<<variant_type_index::8, bin::bytes>>
1401+
when variant_type_index < tuple_size(variant_types) ->
1402+
variant_type = elem(variant_types, variant_type_index)
14021403
decode_rows([variant_type | types_rest], bin, row, rows, types)
14031404

1405+
<<variant_type_index::8, _bin::bytes>> ->
1406+
raise ArgumentError, "invalid Variant type index: #{variant_type_index}"
1407+
14041408
_ ->
14051409
to_be_continued(rows, bin, [type | types_rest], row)
14061410
end

test/ch/row_binary_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ defmodule Ch.RowBinaryTest do
300300
{"Array(LowCardinality(String))", {:array, :string}},
301301
{"Array(Enum8('hello' = 2, 'world' = 3))",
302302
{:array, {:enum8, %{2 => "hello", 3 => "world"}}}},
303+
{"Variant(String, UInt32)", {:variant, {:string, :u32}}},
303304
{"Array(Nothing)", {:array, :nothing}},
304305
{"Nullable(String)", {:nullable, :string}},
305306
{"Nullable(Float64)", {:nullable, :f64}},
@@ -410,6 +411,12 @@ defmodule Ch.RowBinaryTest do
410411
decode_rows(<<0>>, [:unsupported])
411412
end
412413
end
414+
415+
test "rejects invalid Variant type indexes" do
416+
assert_raise ArgumentError, "invalid Variant type index: 2", fn ->
417+
decode_rows(<<2>>, ["Variant(String, UInt32)"])
418+
end
419+
end
413420
end
414421

415422
# TODO maybe use stream_data?

0 commit comments

Comments
 (0)