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

Commit 9850ae9

Browse files
committed
support Array(IPv4) && Array(IPv6) type
fix ClickHouse#220 ClickHouse#196
1 parent a1ffb9f commit 9850ae9

File tree

11 files changed

+113
-41
lines changed

11 files changed

+113
-41
lines changed

clickhouse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func (ch *clickhouse) CheckNamedValue(nv *driver.NamedValue) error {
185185
[]float32, []float64,
186186
[]string:
187187
return nil
188-
case net.IP:
188+
case net.IP, *net.IP:
189189
return nil
190190
case driver.Valuer:
191191
value, err := v.Value()

lib/column/array.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package column
22

33
import (
44
"fmt"
5+
"net"
56
"reflect"
67
"strings"
78
"time"
@@ -88,31 +89,33 @@ loop:
8889
}
8990

9091
var scanType interface{}
91-
switch t := column.ScanType().Kind(); t {
92-
case reflect.Int8:
92+
switch t := column.ScanType(); t {
93+
case arrayBaseTypes[int8(0)]:
9394
scanType = []int8{}
94-
case reflect.Int16:
95+
case arrayBaseTypes[int16(0)]:
9596
scanType = []int16{}
96-
case reflect.Int32:
97+
case arrayBaseTypes[int32(0)]:
9798
scanType = []int32{}
98-
case reflect.Int64:
99+
case arrayBaseTypes[int64(0)]:
99100
scanType = []int64{}
100-
case reflect.Uint8:
101+
case arrayBaseTypes[uint8(0)]:
101102
scanType = []uint8{}
102-
case reflect.Uint16:
103+
case arrayBaseTypes[uint16(0)]:
103104
scanType = []uint16{}
104-
case reflect.Uint32:
105+
case arrayBaseTypes[uint32(0)]:
105106
scanType = []uint32{}
106-
case reflect.Uint64:
107+
case arrayBaseTypes[uint64(0)]:
107108
scanType = []uint64{}
108-
case reflect.Float32:
109+
case arrayBaseTypes[float32(0)]:
109110
scanType = []float32{}
110-
case reflect.Float64:
111+
case arrayBaseTypes[float64(0)]:
111112
scanType = []float64{}
112-
case reflect.String:
113+
case arrayBaseTypes[string("")]:
113114
scanType = []string{}
114-
case baseTypes[time.Time{}].Kind():
115+
case arrayBaseTypes[time.Time{}]:
115116
scanType = []time.Time{}
117+
case arrayBaseTypes[IPv4{}], arrayBaseTypes[IPv6{}]:
118+
scanType = []net.IP{}
116119
default:
117120
return nil, fmt.Errorf("unsupported Array type '%s'", column.ScanType().Name())
118121
}

lib/column/column.go

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,95 +26,95 @@ func Factory(name, chType string, timezone *time.Location) (Column, error) {
2626
base: base{
2727
name: name,
2828
chType: chType,
29-
valueOf: baseTypes[int8(0)],
29+
valueOf: columnBaseTypes[int8(0)],
3030
},
3131
}, nil
3232
case "Int16":
3333
return &Int16{
3434
base: base{
3535
name: name,
3636
chType: chType,
37-
valueOf: baseTypes[int16(0)],
37+
valueOf: columnBaseTypes[int16(0)],
3838
},
3939
}, nil
4040
case "Int32":
4141
return &Int32{
4242
base: base{
4343
name: name,
4444
chType: chType,
45-
valueOf: baseTypes[int32(0)],
45+
valueOf: columnBaseTypes[int32(0)],
4646
},
4747
}, nil
4848
case "Int64":
4949
return &Int64{
5050
base: base{
5151
name: name,
5252
chType: chType,
53-
valueOf: baseTypes[int64(0)],
53+
valueOf: columnBaseTypes[int64(0)],
5454
},
5555
}, nil
5656
case "UInt8":
5757
return &UInt8{
5858
base: base{
5959
name: name,
6060
chType: chType,
61-
valueOf: baseTypes[uint8(0)],
61+
valueOf: columnBaseTypes[uint8(0)],
6262
},
6363
}, nil
6464
case "UInt16":
6565
return &UInt16{
6666
base: base{
6767
name: name,
6868
chType: chType,
69-
valueOf: baseTypes[uint16(0)],
69+
valueOf: columnBaseTypes[uint16(0)],
7070
},
7171
}, nil
7272
case "UInt32":
7373
return &UInt32{
7474
base: base{
7575
name: name,
7676
chType: chType,
77-
valueOf: baseTypes[uint32(0)],
77+
valueOf: columnBaseTypes[uint32(0)],
7878
},
7979
}, nil
8080
case "UInt64":
8181
return &UInt64{
8282
base: base{
8383
name: name,
8484
chType: chType,
85-
valueOf: baseTypes[uint64(0)],
85+
valueOf: columnBaseTypes[uint64(0)],
8686
},
8787
}, nil
8888
case "Float32":
8989
return &Float32{
9090
base: base{
9191
name: name,
9292
chType: chType,
93-
valueOf: baseTypes[float32(0)],
93+
valueOf: columnBaseTypes[float32(0)],
9494
},
9595
}, nil
9696
case "Float64":
9797
return &Float64{
9898
base: base{
9999
name: name,
100100
chType: chType,
101-
valueOf: baseTypes[float64(0)],
101+
valueOf: columnBaseTypes[float64(0)],
102102
},
103103
}, nil
104104
case "String":
105105
return &String{
106106
base: base{
107107
name: name,
108108
chType: chType,
109-
valueOf: baseTypes[string("")],
109+
valueOf: columnBaseTypes[string("")],
110110
},
111111
}, nil
112112
case "UUID":
113113
return &UUID{
114114
base: base{
115115
name: name,
116116
chType: chType,
117-
valueOf: baseTypes[string("")],
117+
valueOf: columnBaseTypes[string("")],
118118
},
119119
}, nil
120120
case "Date":
@@ -123,7 +123,7 @@ func Factory(name, chType string, timezone *time.Location) (Column, error) {
123123
base: base{
124124
name: name,
125125
chType: chType,
126-
valueOf: baseTypes[time.Time{}],
126+
valueOf: columnBaseTypes[time.Time{}],
127127
},
128128
Timezone: timezone,
129129
offset: int64(offset),
@@ -133,22 +133,24 @@ func Factory(name, chType string, timezone *time.Location) (Column, error) {
133133
base: base{
134134
name: name,
135135
chType: chType,
136-
valueOf: baseTypes[time.Time{}],
136+
valueOf: columnBaseTypes[time.Time{}],
137137
},
138138
Timezone: timezone,
139139
}, nil
140140
case "IPv4":
141141
return &IPv4{
142142
base: base{
143-
name: name,
144-
chType: chType,
143+
name: name,
144+
chType: chType,
145+
valueOf: columnBaseTypes[IPv4{}],
145146
},
146147
}, nil
147148
case "IPv6":
148149
return &IPv6{
149150
base: base{
150-
name: name,
151-
chType: chType,
151+
name: name,
152+
chType: chType,
153+
valueOf: columnBaseTypes[IPv6{}],
152154
},
153155
}, nil
154156
}

lib/column/column_benchmark_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io/ioutil"
66
"math"
7+
"net"
78
"testing"
89
"time"
910

@@ -251,3 +252,31 @@ func Benchmark_Column_UUID(b *testing.B) {
251252
}
252253
}
253254
}
255+
256+
func Benchmark_Column_IP(b *testing.B) {
257+
var (
258+
encoder = binary.NewEncoder(ioutil.Discard)
259+
column, _ = Factory("", "IPv4", time.Local)
260+
)
261+
b.ResetTimer()
262+
b.ReportAllocs()
263+
for i := 0; i < b.N; i++ {
264+
if err := column.Write(encoder, net.ParseIP("1.2.3.4")); err != nil {
265+
b.Fatal(err)
266+
}
267+
}
268+
}
269+
270+
func Benchmark_Column_IP_STRING(b *testing.B) {
271+
var (
272+
encoder = binary.NewEncoder(ioutil.Discard)
273+
column, _ = Factory("", "IPv4", time.Local)
274+
)
275+
b.ResetTimer()
276+
b.ReportAllocs()
277+
for i := 0; i < b.N; i++ {
278+
if err := column.Write(encoder, "1.2.3.4"); err != nil {
279+
b.Fatal(err)
280+
}
281+
}
282+
}

lib/column/common.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package column
22

33
import (
44
"fmt"
5+
"net"
56
"reflect"
67
"time"
78
)
@@ -15,7 +16,7 @@ func (err *ErrUnexpectedType) Error() string {
1516
return fmt.Sprintf("%s: unexpected type %T", err.Column, err.T)
1617
}
1718

18-
var baseTypes = map[interface{}]reflect.Value{
19+
var columnBaseTypes = map[interface{}]reflect.Value{
1920
int8(0): reflect.ValueOf(int8(0)),
2021
int16(0): reflect.ValueOf(int16(0)),
2122
int32(0): reflect.ValueOf(int32(0)),
@@ -28,6 +29,25 @@ var baseTypes = map[interface{}]reflect.Value{
2829
float64(0): reflect.ValueOf(float64(0)),
2930
string(""): reflect.ValueOf(string("")),
3031
time.Time{}: reflect.ValueOf(time.Time{}),
32+
IPv4{}: reflect.ValueOf(net.IP{}),
33+
IPv6{}: reflect.ValueOf(net.IP{}),
34+
}
35+
36+
var arrayBaseTypes = map[interface{}]reflect.Type{
37+
int8(0): reflect.ValueOf(int8(0)).Type(),
38+
int16(0): reflect.ValueOf(int16(0)).Type(),
39+
int32(0): reflect.ValueOf(int32(0)).Type(),
40+
int64(0): reflect.ValueOf(int64(0)).Type(),
41+
uint8(0): reflect.ValueOf(uint8(0)).Type(),
42+
uint16(0): reflect.ValueOf(uint16(0)).Type(),
43+
uint32(0): reflect.ValueOf(uint32(0)).Type(),
44+
uint64(0): reflect.ValueOf(uint64(0)).Type(),
45+
float32(0): reflect.ValueOf(float32(0)).Type(),
46+
float64(0): reflect.ValueOf(float64(0)).Type(),
47+
string(""): reflect.ValueOf(string("")).Type(),
48+
time.Time{}: reflect.ValueOf(time.Time{}).Type(),
49+
IPv4{}: reflect.ValueOf(net.IP{}).Type(),
50+
IPv6{}: reflect.ValueOf(net.IP{}).Type(),
3151
}
3252

3353
type base struct {

lib/column/decimal.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,10 @@ func parseDecimal(name, chType string) (Column, error) {
227227
switch {
228228
case decimal.precision <= 9:
229229
decimal.nobits = 32
230-
decimal.valueOf = baseTypes[int32(0)]
230+
decimal.valueOf = columnBaseTypes[int32(0)]
231231
case decimal.precision <= 18:
232232
decimal.nobits = 64
233-
decimal.valueOf = baseTypes[int64(0)]
233+
decimal.valueOf = columnBaseTypes[int64(0)]
234234
case decimal.precision <= 38:
235235
return nil, errors.New("Decimal128 is not supported")
236236
default:

lib/column/enum.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func parseEnum(name, chType string) (*Enum, error) {
104104
base: base{
105105
name: name,
106106
chType: chType,
107-
valueOf: baseTypes[string("")],
107+
valueOf: columnBaseTypes[string("")],
108108
},
109109
iv: make(map[string]interface{}),
110110
vi: make(map[interface{}]string),

lib/column/fixed_string.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func parseFixedString(name, chType string) (*FixedString, error) {
6464
base: base{
6565
name: name,
6666
chType: chType,
67-
valueOf: baseTypes[string("")],
67+
valueOf: columnBaseTypes[string("")],
6868
},
6969
len: strLen,
7070
}, nil

lib/column/ip.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ func (ip *IP) Scan(value interface{}) (err error) {
6161
} else {
6262
err = errInvalidScanValue
6363
}
64+
case net.IP:
65+
*ip = IP(v)
6466
default:
6567
err = errInvalidScanType
6668
}

lib/column/ipv4.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,21 @@ func (*IPv4) Read(decoder *binary.Decoder) (interface{}, error) {
1919
}
2020

2121
func (ip *IPv4) Write(encoder *binary.Encoder, v interface{}) error {
22-
netIP, ok := v.(net.IP)
23-
if !ok {
22+
var netIP net.IP
23+
switch v.(type) {
24+
case string:
25+
netIP = net.ParseIP(v.(string))
26+
case net.IP:
27+
netIP = v.(net.IP)
28+
case *net.IP:
29+
netIP = *(v.(*net.IP))
30+
default:
2431
return &ErrUnexpectedType{
2532
T: v,
2633
Column: ip,
2734
}
2835
}
36+
2937
ip4 := netIP.To4()
3038
if _, err := encoder.Write([]byte{ip4[3], ip4[2], ip4[1], ip4[0]}); err != nil {
3139
return err

0 commit comments

Comments
 (0)