ClickHouse/ch-go

ColTuple issue when using proto.Named() helper

nikita-vanyasin opened this issue · 1 comments

Describe the bug

Steps to reproduce

(code taken from slightly adjusted tuple_test.go):

	require.NoError(t, conn.Do(ctx, Query{
		Body: "CREATE TABLE named_tuples (`1` Tuple(`s` String, `i` Int64, `m` Map(String, Float32))) ENGINE = Memory",
	}))
	
	// ...

        var (
                // ...
		mapData = proto.Named[map[string]float32](
			proto.NewMap[string, float32](new(proto.ColStr), new(proto.ColFloat32)),
			"m",
		)
	)
	results := proto.Results{
		{Name: "1", Data: proto.ColTuple{strData, intData, mapData}},
	}
	require.NoError(t, conn.Do(ctx, Query{
		Body:   "SELECT * FROM named_tuples",
		Result: results,
	}))

Error log

                Error:          Received unexpected error:
                                decode block:
                                    github.com/ClickHouse/ch-go.(*Client).Do.func5
                                        /home/nikita/work/ch-go/query.go:729
                                  - decode block:
                                    github.com/ClickHouse/ch-go.(*Client).decodeBlock
                                        /home/nikita/work/ch-go/query.go:245
                                  - raw block:
                                    github.com/ClickHouse/ch-go/proto.(*Block).DecodeBlock
                                        /home/nikita/work/ch-go/proto/block.go:282
                                  - target:
                                    github.com/ClickHouse/ch-go/proto.(*Block).DecodeRawBlock
                                        /home/nikita/work/ch-go/proto/block.go:269
                                  - infer:
                                    github.com/ClickHouse/ch-go/proto.Results.DecodeResult
                                        /home/nikita/work/ch-go/proto/results.go:129
                                  - infer:
                                    github.com/ClickHouse/ch-go/proto.ColTuple.Infer
                                        /home/nikita/work/ch-go/proto/col_tuple.go:121
                                  - named:
                                    github.com/ClickHouse/ch-go/proto.(*ColNamed[...]).Infer
                                        /home/nikita/work/ch-go/proto/col_tuple.go:44
                                  - invalid map type:
                                    github.com/ClickHouse/ch-go/proto.(*ColMap[...]).Infer
                                        /home/nikita/work/ch-go/proto/col_map.go:186

The issue happens only when using proto.Named helper because it returns reference to new ColName obj instead of obj itself. This causes Infer function does not work properly for this case:
it passes (Tuple(String, Int64, Map(String, Float32))) into each of column.Infer call instead of parsing each column separately.

To fix the issue I had to replace

                mapData = proto.ColNamed[map[string]float32]{
			ColumnOf: proto.NewMap[string, float32](new(proto.ColStr), new(proto.ColFloat32)),
			Name:     "m",
		}

with

		mapData = proto.Named[map[string]float32](
			proto.NewMap[string, float32](new(proto.ColStr), new(proto.ColFloat32)),
			"m",
		)

In general, this is just usability issue: I've spent a few hours trying to debug why my code don't work - only because I've used (seemingly harmless) helper function proto.Named. I think interfaces should be adjusted to ensure the result of proto.Named() can't be used as element of ColTuple list. At least some clarification needed about what elements should be passed to ColTuple.