diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f35dc56..07ffd1b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.35.2 + version: latest test: runs-on: ubuntu-latest @@ -43,6 +43,6 @@ jobs: services: clickhouse: - image: yandex/clickhouse-server:latest + image: clickhouse/clickhouse-server:latest ports: - 8123:8123 diff --git a/clickhouse_test.go b/clickhouse_test.go index 81f0eea..7e5b3a6 100644 --- a/clickhouse_test.go +++ b/clickhouse_test.go @@ -21,6 +21,7 @@ var ddls = []string{ i64 Int64, u64 UInt64, f64 Float64, + b Boolean, s String, s2 String, a16 Array(Int16), @@ -39,9 +40,9 @@ var ddls = []string{ m Map(String, Array(Int64)) ) ENGINE = Memory`, `INSERT INTO data VALUES - (-1, 1, 1.0, '1', '1', [1], [10], '2011-03-06', '2011-03-06 06:20:00', 'one', '10.1111', '100.1111', '1000.1111', '1.1111', '127.0.0.1', '2001:db8:3333:4444:5555:6666:7777:8888', '12345678', 'one', {'key1':[1]}), - (-2, 2, 2.0, '2', '2', [2], [20], '2012-05-31', '2012-05-31 11:20:00', 'two', '30.1111', '300.1111', '2000.1111', '2.1111', '8.8.8.8', '2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF', '88888888', 'two', {'key2':[2]}), - (-3, 3, 3.0, '3', '2', [3], [30], '2016-04-04', '2016-04-04 11:30:00', 'three', '40.1111', '400.1111', '3000.1111', '3.1111', '255.255.255.255', '::1234:5678', '87654321', 'three', {'key3':[3]}) + (-1, 1, 1.0, true, '1', '1', [1], [10], '2011-03-06', '2011-03-06 06:20:00', 'one', '10.1111', '100.1111', '1000.1111', '1.1111', '127.0.0.1', '2001:db8:3333:4444:5555:6666:7777:8888', '12345678', 'one', {'key1':[1]}), + (-2, 2, 2.0, false, '2', '2', [2], [20], '2012-05-31', '2012-05-31 11:20:00', 'two', '30.1111', '300.1111', '2000.1111', '2.1111', '8.8.8.8', '2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF', '88888888', 'two', {'key2':[2]}), + (-3, 3, 3.0, true, '3', '2', [3], [30], '2016-04-04', '2016-04-04 11:30:00', 'three', '40.1111', '400.1111', '3000.1111', '3.1111', '255.255.255.255', '::1234:5678', '87654321', 'three', {'key3':[3]}) `, } diff --git a/conn_go18_test.go b/conn_go18_test.go index 488ca98..0abbe10 100644 --- a/conn_go18_test.go +++ b/conn_go18_test.go @@ -45,7 +45,7 @@ func (s *connSuite) TestColumnTypes() { types, err := rows.ColumnTypes() s.Require().NoError(err) expected := []string{ - "Int64", "UInt64", "Float64", "String", "String", "Array(Int16)", "Array(UInt8)", "Date", "DateTime", + "Int64", "UInt64", "Float64", "Bool", "String", "String", "Array(Int16)", "Array(UInt8)", "Date", "DateTime", "Enum8('one' = 1, 'two' = 2, 'three' = 3)", "Decimal(9, 4)", "Decimal(18, 4)", "Decimal(38, 4)", "Decimal(10, 4)", "IPv4", "IPv6", "FixedString(8)", "LowCardinality(String)", "Map(String, Array(Int64))", diff --git a/conn_test.go b/conn_test.go index caf0f6f..7021b90 100644 --- a/conn_test.go +++ b/conn_test.go @@ -44,7 +44,7 @@ func (s *connSuite) TestQuery() { []interface{}{1}, [][]interface{}{ { - int64(-1), uint64(1), float64(1), "1", "1", []int16{1}, []uint8{10}, + int64(-1), uint64(1), float64(1), true, "1", "1", []int16{1}, []uint8{10}, parseDate("2011-03-06"), parseDateTime("2011-03-06 06:20:00"), "one", "10.1111", "100.1111", "1000.1111", "1.1111", "127.0.0.1", "2001:db8:3333:4444:5555:6666:7777:8888", "12345678", "one", diff --git a/dataparser.go b/dataparser.go index c172201..49e4439 100644 --- a/dataparser.go +++ b/dataparser.go @@ -15,6 +15,7 @@ var ( reflectTypeString = reflect.TypeOf("") reflectTypeTime = reflect.TypeOf(time.Time{}) reflectTypeEmptyStruct = reflect.TypeOf(struct{}{}) + reflectTypeBool = reflect.TypeOf(bool(false)) reflectTypeInt8 = reflect.TypeOf(int8(0)) reflectTypeInt16 = reflect.TypeOf(int16(0)) reflectTypeInt32 = reflect.TypeOf(int32(0)) @@ -460,6 +461,24 @@ func newDateTimeParser(format string, loc *time.Location, precision int, unquote }, nil } +type boolParser struct{} + +func (p *boolParser) Parse(s io.RuneScanner) (driver.Value, error) { + repr := readRaw(s).String() + switch repr { + case "true": + return true, nil + case "false": + return false, nil + default: + return nil, fmt.Errorf("incorrect bool value: %v", repr) + } +} + +func (p *boolParser) Type() reflect.Type { + return reflectTypeBool +} + type intParser struct { signed bool bitSize int @@ -646,6 +665,8 @@ func newDataParser(t *TypeDesc, unquote bool, opt *DataParserOptions) (DataParse } return newDateTimeParser(dateTime64Format, loc, precision, unquote) + case "Bool": + return &boolParser{}, nil case "UInt8": return &intParser{false, 8}, nil case "UInt16":