From f329f79ce51ff371ebcebd2459682a9a5aa60606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20Sch=C3=B6ll?= Date: Wed, 6 Nov 2024 14:45:42 +0100 Subject: [PATCH 1/2] fixed Clickhouse Array type --- CHANGELOG.md | 1 + db/dialect_clickhouse.go | 15 ++++++++++++++- db/dialect_clickhouse_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e6914..bbe4d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased * Added support for the Clickhouse `Date` type. +* Fixed handling of the Clickhouse `Array` type. ## v4.3.0 diff --git a/db/dialect_clickhouse.go b/db/dialect_clickhouse.go index 43b42ac..294a17f 100644 --- a/db/dialect_clickhouse.go +++ b/db/dialect_clickhouse.go @@ -2,6 +2,7 @@ package db import ( "context" + "encoding/json" "fmt" "math/big" "reflect" @@ -187,7 +188,19 @@ func convertToType(value string, valueType reflect.Type) (any, error) { case reflect.String: return value, nil case reflect.Slice: - return value, nil + if valueType.Elem().Kind() == reflect.Struct || valueType.Elem().Kind() == reflect.Ptr { + return nil, fmt.Errorf("%q is not supported as Clickhouse Array type", valueType.Elem().Name()) + } + + // in case the slice values are wrapped in single quotes, replace them to use json.Unmarshal which requires double quotes + value = strings.ReplaceAll(value, "'", "\"") + + res := reflect.New(reflect.SliceOf(valueType.Elem())) + if err := json.Unmarshal([]byte(value), res.Interface()); err != nil { + return "", fmt.Errorf("could not unmarshal slice value %q: %w", value, err) + } + + return res.Elem().Interface(), nil case reflect.Bool: return strconv.ParseBool(value) case reflect.Int: diff --git a/db/dialect_clickhouse_test.go b/db/dialect_clickhouse_test.go index 9b623e8..73638c7 100644 --- a/db/dialect_clickhouse_test.go +++ b/db/dialect_clickhouse_test.go @@ -44,6 +44,31 @@ func Test_convertToType(t *testing.T) { expectErr: nil, valueType: reflect.TypeOf(time.Time{}), }, + { + name: "String Slice Double Quoted", + value: `["field1", "field2"]`, + expect: []string{"field1", "field2"}, + expectErr: nil, + valueType: reflect.TypeOf([]string{}), + }, { + name: "Int Slice", + value: `[1, 2]`, + expect: []int{1, 2}, + expectErr: nil, + valueType: reflect.TypeOf([]int{}), + }, { + name: "Float Slice", + value: `[1.0, 2.0]`, + expect: []float64{1, 2}, + expectErr: nil, + valueType: reflect.TypeOf([]float64{}), + }, { + name: "Invalid Type Slice Struct", + value: `[""]`, + expect: nil, + expectErr: errors.New(`"Time" is not supported as Clickhouse Array type`), + valueType: reflect.TypeOf([]time.Time{}), + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From fb46820269d5879011fbf31a356190c136e45926 Mon Sep 17 00:00:00 2001 From: fschoell Date: Thu, 19 Dec 2024 12:36:59 +0100 Subject: [PATCH 2/2] remove support for single quotes, improve error message --- db/dialect_clickhouse.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/db/dialect_clickhouse.go b/db/dialect_clickhouse.go index 294a17f..6e44cf5 100644 --- a/db/dialect_clickhouse.go +++ b/db/dialect_clickhouse.go @@ -192,12 +192,9 @@ func convertToType(value string, valueType reflect.Type) (any, error) { return nil, fmt.Errorf("%q is not supported as Clickhouse Array type", valueType.Elem().Name()) } - // in case the slice values are wrapped in single quotes, replace them to use json.Unmarshal which requires double quotes - value = strings.ReplaceAll(value, "'", "\"") - res := reflect.New(reflect.SliceOf(valueType.Elem())) if err := json.Unmarshal([]byte(value), res.Interface()); err != nil { - return "", fmt.Errorf("could not unmarshal slice value %q: %w", value, err) + return "", fmt.Errorf("could not JSON unmarshal slice value %q: %w", value, err) } return res.Elem().Interface(), nil