From cbcd48e2b5abf895fb47d508f70da51b5da904b6 Mon Sep 17 00:00:00 2001 From: Aleksandr Razumov Date: Wed, 25 May 2022 23:38:07 +0300 Subject: [PATCH] feat(proto): support Point --- README.md | 1 + proto/_golden/col_point.hex | 50 ++++++++++++++++++++++++++++ proto/_golden/col_point.raw | Bin 0 -> 800 bytes proto/col_point.go | 63 +++++++++++++++++++++++++++++++++++ proto/col_point_test.go | 64 ++++++++++++++++++++++++++++++++++++ proto/column.go | 1 + query_test.go | 40 ++++++++++++++++++++++ 7 files changed, 219 insertions(+) create mode 100644 proto/_golden/col_point.hex create mode 100644 proto/_golden/col_point.raw create mode 100644 proto/col_point.go create mode 100644 proto/col_point_test.go diff --git a/README.md b/README.md index 9a0c435c..ecb4a240 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ q := ch.Query{ * Bool * Tuple(T1, T2, ..., Tn) * Nullable(T) +* Point ## Generics diff --git a/proto/_golden/col_point.hex b/proto/_golden/col_point.hex new file mode 100644 index 00000000..be6ec48e --- /dev/null +++ b/proto/_golden/col_point.hex @@ -0,0 +1,50 @@ +00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f0 3f |...............?| +00000010 00 00 00 00 00 00 00 40 00 00 00 00 00 00 08 40 |.......@.......@| +00000020 00 00 00 00 00 00 10 40 00 00 00 00 00 00 14 40 |.......@.......@| +00000030 00 00 00 00 00 00 18 40 00 00 00 00 00 00 1c 40 |.......@.......@| +00000040 00 00 00 00 00 00 20 40 00 00 00 00 00 00 22 40 |...... @......"@| +00000050 00 00 00 00 00 00 24 40 00 00 00 00 00 00 26 40 |......$@......&@| +00000060 00 00 00 00 00 00 28 40 00 00 00 00 00 00 2a 40 |......(@......*@| +00000070 00 00 00 00 00 00 2c 40 00 00 00 00 00 00 2e 40 |......,@.......@| +00000080 00 00 00 00 00 00 30 40 00 00 00 00 00 00 31 40 |......0@......1@| +00000090 00 00 00 00 00 00 32 40 00 00 00 00 00 00 33 40 |......2@......3@| +000000a0 00 00 00 00 00 00 34 40 00 00 00 00 00 00 35 40 |......4@......5@| +000000b0 00 00 00 00 00 00 36 40 00 00 00 00 00 00 37 40 |......6@......7@| +000000c0 00 00 00 00 00 00 38 40 00 00 00 00 00 00 39 40 |......8@......9@| +000000d0 00 00 00 00 00 00 3a 40 00 00 00 00 00 00 3b 40 |......:@......;@| +000000e0 00 00 00 00 00 00 3c 40 00 00 00 00 00 00 3d 40 |......<@......=@| +000000f0 00 00 00 00 00 00 3e 40 00 00 00 00 00 00 3f 40 |......>@......?@| +00000100 00 00 00 00 00 00 40 40 00 00 00 00 00 80 40 40 |......@@......@@| +00000110 00 00 00 00 00 00 41 40 00 00 00 00 00 80 41 40 |......A@......A@| +00000120 00 00 00 00 00 00 42 40 00 00 00 00 00 80 42 40 |......B@......B@| +00000130 00 00 00 00 00 00 43 40 00 00 00 00 00 80 43 40 |......C@......C@| +00000140 00 00 00 00 00 00 44 40 00 00 00 00 00 80 44 40 |......D@......D@| +00000150 00 00 00 00 00 00 45 40 00 00 00 00 00 80 45 40 |......E@......E@| +00000160 00 00 00 00 00 00 46 40 00 00 00 00 00 80 46 40 |......F@......F@| +00000170 00 00 00 00 00 00 47 40 00 00 00 00 00 80 47 40 |......G@......G@| +00000180 00 00 00 00 00 00 48 40 00 00 00 00 00 80 48 40 |......H@......H@| +00000190 00 00 00 00 00 00 00 80 00 00 00 00 00 00 f0 bf |................| +000001a0 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 08 c0 |................| +000001b0 00 00 00 00 00 00 10 c0 00 00 00 00 00 00 14 c0 |................| +000001c0 00 00 00 00 00 00 18 c0 00 00 00 00 00 00 1c c0 |................| +000001d0 00 00 00 00 00 00 20 c0 00 00 00 00 00 00 22 c0 |...... .......".| +000001e0 00 00 00 00 00 00 24 c0 00 00 00 00 00 00 26 c0 |......$.......&.| +000001f0 00 00 00 00 00 00 28 c0 00 00 00 00 00 00 2a c0 |......(.......*.| +00000200 00 00 00 00 00 00 2c c0 00 00 00 00 00 00 2e c0 |......,.........| +00000210 00 00 00 00 00 00 30 c0 00 00 00 00 00 00 31 c0 |......0.......1.| +00000220 00 00 00 00 00 00 32 c0 00 00 00 00 00 00 33 c0 |......2.......3.| +00000230 00 00 00 00 00 00 34 c0 00 00 00 00 00 00 35 c0 |......4.......5.| +00000240 00 00 00 00 00 00 36 c0 00 00 00 00 00 00 37 c0 |......6.......7.| +00000250 00 00 00 00 00 00 38 c0 00 00 00 00 00 00 39 c0 |......8.......9.| +00000260 00 00 00 00 00 00 3a c0 00 00 00 00 00 00 3b c0 |......:.......;.| +00000270 00 00 00 00 00 00 3c c0 00 00 00 00 00 00 3d c0 |......<.......=.| +00000280 00 00 00 00 00 00 3e c0 00 00 00 00 00 00 3f c0 |......>.......?.| +00000290 00 00 00 00 00 00 40 c0 00 00 00 00 00 80 40 c0 |......@.......@.| +000002a0 00 00 00 00 00 00 41 c0 00 00 00 00 00 80 41 c0 |......A.......A.| +000002b0 00 00 00 00 00 00 42 c0 00 00 00 00 00 80 42 c0 |......B.......B.| +000002c0 00 00 00 00 00 00 43 c0 00 00 00 00 00 80 43 c0 |......C.......C.| +000002d0 00 00 00 00 00 00 44 c0 00 00 00 00 00 80 44 c0 |......D.......D.| +000002e0 00 00 00 00 00 00 45 c0 00 00 00 00 00 80 45 c0 |......E.......E.| +000002f0 00 00 00 00 00 00 46 c0 00 00 00 00 00 80 46 c0 |......F.......F.| +00000300 00 00 00 00 00 00 47 c0 00 00 00 00 00 80 47 c0 |......G.......G.| +00000310 00 00 00 00 00 00 48 c0 00 00 00 00 00 80 48 c0 |......H.......H.| diff --git a/proto/_golden/col_point.raw b/proto/_golden/col_point.raw new file mode 100644 index 0000000000000000000000000000000000000000..a28fd35ae7fe428ad283beec7189bc02bdc1f797 GIT binary patch literal 800 zcmYkvIf?=S07bzc8X6cF7>J07h`8_C?e4MqX5*1O!oYL|^OE8v|N9oMtZlH#7TfHw z%O3k2aL5tIoN&q+=Ui~f71!Kw%N_ST@W>O-ELhf7%*8WT&)ht7_sqjHPtUwO^Y%=t z{Pq2*&8N1(CR=Q?!!CR5bHE`-9CN}cXPk4vC0AT?!!38*^S~odJhNa~TQL{UTs?F1 R%-u5&&pbWz^32=6Kfm0aP!9kA literal 0 HcmV?d00001 diff --git a/proto/col_point.go b/proto/col_point.go new file mode 100644 index 00000000..0e1549ff --- /dev/null +++ b/proto/col_point.go @@ -0,0 +1,63 @@ +package proto + +import "github.com/go-faster/errors" + +type Point struct { + X, Y float64 +} + +// Compile-time assertions for ColPoint. +var ( + _ ColInput = ColPoint{} + _ ColResult = (*ColPoint)(nil) + _ Column = (*ColPoint)(nil) + _ ColumnOf[Point] = (*ColPoint)(nil) +) + +type ColPoint struct { + X, Y ColFloat64 +} + +func (c *ColPoint) Append(v Point) { + c.X.Append(v.X) + c.Y.Append(v.Y) +} + +func (c *ColPoint) AppendArr(v []Point) { + for _, vv := range v { + c.Append(vv) + } +} + +func (c ColPoint) Row(i int) Point { + return Point{ + X: c.X.Row(i), + Y: c.Y.Row(i), + } +} + +func (c ColPoint) Type() ColumnType { return ColumnTypePoint } +func (c ColPoint) Rows() int { return c.X.Rows() } + +func (c *ColPoint) DecodeColumn(r *Reader, rows int) error { + if err := c.X.DecodeColumn(r, rows); err != nil { + return errors.Wrap(err, "x") + } + if err := c.Y.DecodeColumn(r, rows); err != nil { + return errors.Wrap(err, "y") + } + return nil +} + +func (c *ColPoint) Reset() { + c.X.Reset() + c.Y.Reset() +} + +func (c ColPoint) EncodeColumn(b *Buffer) { + if b == nil { + return + } + c.X.EncodeColumn(b) + c.Y.EncodeColumn(b) +} diff --git a/proto/col_point_test.go b/proto/col_point_test.go new file mode 100644 index 00000000..282604d9 --- /dev/null +++ b/proto/col_point_test.go @@ -0,0 +1,64 @@ +package proto + +import ( + "bytes" + "io" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/go-faster/ch/internal/gold" +) + +func TestColPoint(t *testing.T) { + t.Parallel() + const rows = 50 + var data ColPoint + for i := 0; i < rows; i++ { + v := Point{ + X: float64(i), + Y: -float64(i), + } + data.Append(v) + require.Equal(t, v, data.Row(i)) + } + + var buf Buffer + data.EncodeColumn(&buf) + t.Run("Golden", func(t *testing.T) { + t.Parallel() + gold.Bytes(t, buf.Buf, "col_point") + }) + t.Run("Ok", func(t *testing.T) { + br := bytes.NewReader(buf.Buf) + r := NewReader(br) + + var dec ColPoint + require.NoError(t, dec.DecodeColumn(r, rows)) + require.Equal(t, data, dec) + require.Equal(t, rows, dec.Rows()) + dec.Reset() + require.Equal(t, 0, dec.Rows()) + require.Equal(t, ColumnTypePoint, dec.Type()) + }) + t.Run("ZeroRows", func(t *testing.T) { + r := NewReader(bytes.NewReader(nil)) + + var dec ColPoint + require.NoError(t, dec.DecodeColumn(r, 0)) + }) + t.Run("ErrUnexpectedEOF", func(t *testing.T) { + r := NewReader(bytes.NewReader(nil)) + + var dec ColPoint + require.ErrorIs(t, dec.DecodeColumn(r, rows), io.ErrUnexpectedEOF) + }) + t.Run("NoShortRead", func(t *testing.T) { + var dec ColPoint + requireNoShortRead(t, buf.Buf, colAware(&dec, rows)) + }) + t.Run("ZeroRowsEncode", func(t *testing.T) { + var v ColPoint + v.EncodeColumn(nil) // should be no-op + }) +} diff --git a/proto/column.go b/proto/column.go index 689e91b2..74f8e8a3 100644 --- a/proto/column.go +++ b/proto/column.go @@ -193,6 +193,7 @@ const ( ColumnTypeDecimal64 ColumnType = "Decimal64" ColumnTypeDecimal128 ColumnType = "Decimal128" ColumnTypeDecimal256 ColumnType = "Decimal256" + ColumnTypePoint ColumnType = "Point" ) // colWrap wraps Column with type t. diff --git a/query_test.go b/query_test.go index cc33651f..f1f4961f 100644 --- a/query_test.go +++ b/query_test.go @@ -804,6 +804,46 @@ func TestClient_Query(t *testing.T) { require.Equal(t, data.Row(i), gotData.Row(i)) } }) + t.Run("InsertGeoPoint", func(t *testing.T) { + t.Parallel() + conn := ConnOpt(t, Options{ + Settings: []Setting{ + // https://clickhouse.com/docs/en/sql-reference/data-types/geo/ + SettingInt("allow_experimental_geo_types", 1), + }, + }) + require.NoError(t, conn.Do(ctx, Query{ + Body: "CREATE TABLE test_table (v Point) ENGINE = Memory", + }), "create table") + + data := new(proto.ColPoint) + data.AppendArr([]proto.Point{ + {X: 1, Y: 0}, + {X: 0, Y: 1}, + {X: 1, Y: 1}, + {X: 0, Y: 0}, + {X: 0, Y: -1}, + }) + require.NoError(t, conn.Do(ctx, Query{ + Body: "INSERT INTO test_table VALUES", + Input: []proto.InputColumn{ + {Name: "v", Data: data}, + }, + }), "insert") + + gotData := new(proto.ColPoint) + require.NoError(t, conn.Do(ctx, Query{ + Body: "SELECT * FROM test_table", + Result: proto.Results{ + {Name: "v", Data: gotData}, + }, + }), "select") + + require.Equal(t, data.Rows(), gotData.Rows()) + for i := 0; i < data.Rows(); i++ { + require.Equal(t, data.Row(i), gotData.Row(i)) + } + }) } func TestClientCompression(t *testing.T) {