Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit a1c7836

Browse files
authored
Merge pull request ClickHouse#212 from cw9/chao-value
Add WriteArrayWithValue function to block
2 parents b7022ac + 3b27876 commit a1c7836

File tree

4 files changed

+85
-4
lines changed

4 files changed

+85
-4
lines changed

clickhouse_columnar_test.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package clickhouse_test
22

33
import (
44
"database/sql/driver"
5+
"reflect"
56
"testing"
67
"time"
78

89
"github.com/kshvakov/clickhouse"
10+
"github.com/kshvakov/clickhouse/lib/data"
911
"github.com/stretchr/testify/assert"
1012
)
1113

@@ -26,6 +28,7 @@ func Test_ColumnarInsert(t *testing.T) {
2628
enum8 Enum8 ('a' = 1, 'b' = 2),
2729
enum16 Enum16('c' = 1, 'd' = 2),
2830
array Array(String),
31+
array2 Array(UInt64),
2932
arrayArray Array(Array(String))
3033
) Engine=Memory
3134
`
@@ -44,6 +47,7 @@ func Test_ColumnarInsert(t *testing.T) {
4447
enum8,
4548
enum16,
4649
array,
50+
array2,
4751
arrayArray
4852
) VALUES (
4953
?,
@@ -104,7 +108,8 @@ func Test_ColumnarInsert(t *testing.T) {
104108
block.WriteUInt8(10, 1)
105109
block.WriteUInt16(11, 2)
106110
block.WriteArray(12, []string{"A", "B", "C"})
107-
block.WriteArray(13, [][]string{[]string{"A", "B"}, []string{"CC", "DD", "EE"}})
111+
block.WriteArrayWithValue(13, uint64SliceValue{value: []uint64{1, 2, 3}})
112+
block.WriteArray(14, [][]string{[]string{"A", "B"}, []string{"CC", "DD", "EE"}})
108113
if !assert.NoError(t, err) {
109114
return
110115
}
@@ -116,3 +121,43 @@ func Test_ColumnarInsert(t *testing.T) {
116121
}
117122
}
118123
}
124+
125+
type uint64Value struct {
126+
value uint64
127+
}
128+
129+
func (v uint64Value) Kind() reflect.Kind {
130+
return reflect.String
131+
}
132+
133+
func (v uint64Value) Len() int {
134+
panic("uint64 has no length")
135+
}
136+
137+
func (v uint64Value) Index(i int) data.Value {
138+
panic("uint64 has no index")
139+
}
140+
141+
func (v uint64Value) Interface() interface{} {
142+
return v.value
143+
}
144+
145+
type uint64SliceValue struct {
146+
value []uint64
147+
}
148+
149+
func (v uint64SliceValue) Kind() reflect.Kind {
150+
return reflect.Slice
151+
}
152+
153+
func (v uint64SliceValue) Len() int {
154+
return len(v.value)
155+
}
156+
157+
func (v uint64SliceValue) Index(i int) data.Value {
158+
return uint64Value{value: v.value[i]}
159+
}
160+
161+
func (v uint64SliceValue) Interface() interface{} {
162+
return v.value
163+
}

lib/data/block.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func (block *Block) Read(serverInfo *ServerInfo, decoder *binary.Decoder) (err e
9595
return nil
9696
}
9797

98-
func (block *Block) writeArray(column column.Column, value reflect.Value, num, level int) error {
98+
func (block *Block) writeArray(column column.Column, value Value, num, level int) error {
9999
if level > column.Depth() {
100100
return column.Write(block.buffers[num].Column, value.Interface())
101101
}
@@ -137,7 +137,7 @@ func (block *Block) AppendRow(args []driver.Value) error {
137137
if value.Kind() != reflect.Slice {
138138
return fmt.Errorf("unsupported Array(T) type [%T]", value.Interface())
139139
}
140-
if err := block.writeArray(c, value, num, 1); err != nil {
140+
if err := block.writeArray(c, newValue(value), num, 1); err != nil {
141141
return err
142142
}
143143
case *column.Nullable:

lib/data/block_write_column.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ func (block *Block) WriteFixedString(c int, v []byte) error {
9090
}
9191

9292
func (block *Block) WriteArray(c int, v interface{}) error {
93-
value := reflect.ValueOf(v)
93+
return block.WriteArrayWithValue(c, newValue(reflect.ValueOf(v)))
94+
}
95+
96+
func (block *Block) WriteArrayWithValue(c int, value Value) error {
9497
if value.Kind() != reflect.Slice {
9598
return fmt.Errorf("unsupported Array(T) type [%T]", value.Interface())
9699
}

lib/data/value.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package data
2+
3+
import "reflect"
4+
5+
// Value is a writable value.
6+
type Value interface {
7+
// Kind returns value's Kind.
8+
Kind() reflect.Kind
9+
10+
// Len returns value's length.
11+
// It panics if value's Kind is not Array, Chan, Map, Slice, or String.
12+
Len() int
13+
14+
// Index returns value's i'th element.
15+
// It panics if value's Kind is not Array, Slice, or String or i is out of range.
16+
Index(i int) Value
17+
18+
// Interface returns value's current value as an interface{}.
19+
Interface() interface{}
20+
}
21+
22+
// value is a wrapper that wraps reflect.Value to comply with Value interface.
23+
type value struct {
24+
reflect.Value
25+
}
26+
27+
func newValue(v reflect.Value) Value {
28+
return value{Value: v}
29+
}
30+
31+
func (v value) Index(i int) Value {
32+
return newValue(v.Value.Index(i))
33+
}

0 commit comments

Comments
 (0)