From c32172b8b8bfc77f08f5bec265be5fdb1e03b7ea Mon Sep 17 00:00:00 2001 From: Aleksandr Razumov Date: Sun, 30 Jan 2022 00:10:33 +0300 Subject: [PATCH] feat(proto): add ColArr.AppendLowCardinality Fix #25 --- .../col_arr_low_cardinality_u8_str.hex | 6 ++ .../col_arr_low_cardinality_u8_str.raw | Bin 0 -> 96 bytes proto/col_low_cardinality.go | 8 ++ proto/col_low_cardinality_test.go | 69 ++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 proto/_golden/col_arr_low_cardinality_u8_str.hex create mode 100644 proto/_golden/col_arr_low_cardinality_u8_str.raw diff --git a/proto/_golden/col_arr_low_cardinality_u8_str.hex b/proto/_golden/col_arr_low_cardinality_u8_str.hex new file mode 100644 index 00000000..53e13d5c --- /dev/null +++ b/proto/_golden/col_arr_low_cardinality_u8_str.hex @@ -0,0 +1,6 @@ +00000000 03 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................| +00000010 06 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................| +00000020 0c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| +00000030 00 06 00 00 00 00 00 00 03 00 00 00 00 00 00 00 |................| +00000040 03 66 6f 6f 03 62 61 72 03 62 61 7a 0c 00 00 00 |.foo.bar.baz....| +00000050 00 00 00 00 00 01 02 00 01 01 00 00 01 01 01 01 |................| diff --git a/proto/_golden/col_arr_low_cardinality_u8_str.raw b/proto/_golden/col_arr_low_cardinality_u8_str.raw new file mode 100644 index 0000000000000000000000000000000000000000..b0a2506d83c989549cd0442b95cf8fc0e9c6e548 GIT binary patch literal 96 zcmZQ(fB+UK%?718pfnGZW`xoVPzB6TK66@rK66rH5fE3w)G{zKF)#u(FaiMpZdC*T literal 0 HcmV?d00001 diff --git a/proto/col_low_cardinality.go b/proto/col_low_cardinality.go index 0c45f002..28b28d97 100644 --- a/proto/col_low_cardinality.go +++ b/proto/col_low_cardinality.go @@ -83,6 +83,14 @@ func (c *ColLowCardinality) AppendKey(i int) { } } +func (c *ColArr) AppendLowCardinality(data []int) { + d := c.Data.(*ColLowCardinality) + for _, v := range data { + d.AppendKey(v) + } + c.Offsets = append(c.Offsets, uint64(d.Keys().Rows())) +} + func (c *ColLowCardinality) Keys() Column { switch c.Key { case KeyUInt8: diff --git a/proto/col_low_cardinality_test.go b/proto/col_low_cardinality_test.go index e9a75ed2..159f5a81 100644 --- a/proto/col_low_cardinality_test.go +++ b/proto/col_low_cardinality_test.go @@ -10,6 +10,75 @@ import ( "github.com/go-faster/ch/internal/gold" ) +func TestArrLowCardinalityStr(t *testing.T) { + // Array(LowCardinality(String)) + data := [][]string{ + {"foo", "bar", "baz"}, + {"foo"}, + {"bar", "bar"}, + {"foo", "foo"}, + {"bar", "bar", "bar", "bar"}, + } + str := &ColStr{} + idx := &ColLowCardinality{Index: str, Key: KeyUInt8} + col := &ColArr{Data: idx} + rows := len(data) + + kv := map[string]int{} // creating index + for _, v := range data { + for _, s := range v { + if _, ok := kv[s]; ok { + continue + } + kv[s] = str.Rows() + str.Append(s) + } + } + for _, v := range data { + var keys []int + for _, k := range v { + keys = append(keys, kv[k]) // mapping indexes + } + col.AppendLowCardinality(keys) // adding row + } + + var buf Buffer + col.EncodeColumn(&buf) + t.Run("Golden", func(t *testing.T) { + gold.Bytes(t, buf.Buf, "col_arr_low_cardinality_u8_str") + }) + t.Run("Ok", func(t *testing.T) { + br := bytes.NewReader(buf.Buf) + r := NewReader(br) + + strDec := &ColStr{} + idxDec := &ColLowCardinality{Index: strDec} + dec := &ColArr{Data: idxDec} + + require.NoError(t, dec.DecodeColumn(r, rows)) + require.Equal(t, col, dec) + require.Equal(t, str, strDec) + require.Equal(t, idx, idxDec) + require.Equal(t, rows, dec.Rows()) + dec.Reset() + require.Equal(t, 0, dec.Rows()) + require.Equal(t, ColumnType("Array(LowCardinality(String))"), dec.Type()) + }) + t.Run("ErrUnexpectedEOF", func(t *testing.T) { + r := NewReader(bytes.NewReader(nil)) + strDec := &ColStr{} + idxDec := &ColLowCardinality{Index: strDec} + dec := &ColArr{Data: idxDec} + require.ErrorIs(t, dec.DecodeColumn(r, rows), io.ErrUnexpectedEOF) + }) + t.Run("NoShortRead", func(t *testing.T) { + strDec := &ColStr{} + idxDec := &ColLowCardinality{Index: strDec} + dec := &ColArr{Data: idxDec} + requireNoShortRead(t, buf.Buf, colAware(dec, rows)) + }) +} + func TestColLowCardinality_DecodeColumn(t *testing.T) { t.Run("Str", func(t *testing.T) { const rows = 25