Skip to content

Commit

Permalink
fix handling Clickhouse Array type (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
fschoell authored Nov 6, 2024
1 parent 8ebe195 commit 3d753a0
Showing 1 changed file with 29 additions and 53 deletions.
82 changes: 29 additions & 53 deletions db/dialect_clickhouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package db

import (
"context"
"encoding/json"
"fmt"
"math/big"
"reflect"
Expand Down Expand Up @@ -189,7 +190,22 @@ func convertToType(value string, valueType reflect.Type) (any, error) {
case reflect.String:
return value, nil
case reflect.Slice:
return value, nil
// in case the slice values are wrapped in single quotes replace them to use json.Unmarshal which requires double quotes
value = strings.ReplaceAll(value, "'", "\"")
var anySlice []any
if err := json.Unmarshal([]byte(value), &anySlice); err != nil {
return "", fmt.Errorf("could not unmarshal slice value %q: %w", value, err)
}

for i, v := range anySlice {
convertedType, err := convertToType(fmt.Sprintf("%v", v), valueType.Elem())
if err != nil {
return "", fmt.Errorf("converting value %q to type %q in column %q: %w", v, valueType.Elem(), i, err)
}
anySlice[i] = convertedType
}

return anySlice, nil
case reflect.Bool:
return strconv.ParseBool(value)
case reflect.Int:
Expand Down Expand Up @@ -262,59 +278,19 @@ func convertToType(value string, valueType reflect.Type) (any, error) {
return newInt, nil
}

switch valueType.Elem().Kind() {
case reflect.String:
return &value, nil
case reflect.Bool:
res, err := strconv.ParseBool(value)
if err != nil {
return nil, err
}
return &res, err
case reflect.Int:
v, err := strconv.ParseInt(value, 10, 0)
res := int(v)
return &res, err
case reflect.Int8:
v, err := strconv.ParseInt(value, 10, 8)
res := int8(v)
return &res, err
case reflect.Int16:
v, err := strconv.ParseInt(value, 10, 16)
res := int16(v)
return &res, err
case reflect.Int32:
v, err := strconv.ParseInt(value, 10, 32)
res := int32(v)
return &res, err
case reflect.Int64:
v, err := strconv.ParseInt(value, 10, 64)
return &v, err
case reflect.Uint:
v, err := strconv.ParseUint(value, 10, 0)
res := uint(v)
return &res, err
case reflect.Uint8:
v, err := strconv.ParseUint(value, 10, 8)
res := uint8(v)
return &res, err
case reflect.Uint16:
v, err := strconv.ParseUint(value, 10, 16)
res := uint16(v)
return &res, err
case reflect.Uint32:
v, err := strconv.ParseUint(value, 10, 32)
res := uint32(v)
return &res, err
case reflect.Uint64:
v, err := strconv.ParseUint(value, 10, 0)
return &v, err
case reflect.Float32, reflect.Float64:
v, err := strconv.ParseFloat(value, 10)
return &v, err
default:
return "", fmt.Errorf("unsupported pointer type %s", valueType)
elemType := valueType.Elem()
val, err := convertToType(value, elemType)
if err != nil {
return nil, fmt.Errorf("invalid pointer type: %w", err)
}

// We cannot just return &val here as this will return an *interface{} that the Clickhouse Go client won't be
// able to convert on inserting. Instead, we create a new variable using the type that valueType has been
// pointing to, assign the converted value from convertToType to that and then return a pointer to the new variable.
result := reflect.New(elemType).Elem()
result.Set(reflect.ValueOf(val))
return result.Addr().Interface(), nil

default:
return value, nil
}
Expand Down

0 comments on commit 3d753a0

Please sign in to comment.