go-gorm / clickhouse

GORM clickhouse driver
MIT License
244 stars 72 forks source link

sql: Scan error on column index 2, name "col3": unsupported Scan, storing driver.Value type []string into type *sql.RawBytes #164

Open exfly opened 5 months ago

exfly commented 5 months ago

GORM Playground Link

https://github.com/go-gorm/playground/pull/1

package main

import (
    "fmt"

    "gorm.io/driver/clickhouse"
    "gorm.io/gorm"
)

type User struct {
    Uniqid uint8  `gorm:"column:col1"`
    Name   string `gorm:"column:col2"`
}

func (User) TableName() string {
    return "user"
}

func main() {
    dsn := "clickhouse://user:passwd@localhost:9010/test?dial_timeout=10s&read_timeout=20s"
    rawDB, err := gorm.Open(clickhouse.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    rawDB.Exec("DROP TABLE IF EXISTS user")
    err = rawDB.Exec(`
    CREATE TABLE user (
          col1 UInt8
        , col2 String
        , col3 Array(String)
    ) Engine = Memory
`).Error
    if err != nil {
        panic(err)
    }

    u := User{
        Uniqid: 1,
        Name:   "gorm",
    }

    err = rawDB.Table("user").Create(&u).Error
    if err != nil {
        panic(err)
    }

    var raw []User
    err = rawDB.Table("user").Select("col1,col2").Find(&raw).Error
    if err != nil {
        panic(err) // works !!!
    }

    err = rawDB.Table("user").Find(&raw).Error
    if err != nil {
        panic(err) // panic: sql: Scan error on column index 2, name "col3": unsupported Scan, storing driver.Value type []string into type *sql.RawBytes
    }

    fmt.Println("Ok")
}

Description

If a non-base type exists in the table, Find will ret err:

`panic: sql: Scan error on column index 2, name "col3": unsupported Scan, storing driver.Value type []string into type *sql.RawBytes`
exfly commented 5 months ago

temp workaround:

rawDB, err := gorm.Open(clickhouse.Open(dsn), &gorm.Config{
    QueryFields: true,
})

In addition, if you want to use the array, you can consider the following custom types:

type StringArray []string

func (a *StringArray) Scan(value interface{}) error {
    *a, _ = value.([]string)
    return nil
}

func (a StringArray) Value() (driver.Value, error) {
    val, err := json.Marshal([]string(a))
    if err != nil {
        return nil, err
    }
    return val, nil
}

type User struct {
    Uniqid  uint8  `gorm:"column:col1"`
    Name   string `gorm:"column:col2"`
        Tags     StringArray
}
zhaojia123 commented 4 months ago

你的可以用?dsn := "clickhouse://username:pwd#@host:9000/database?dial_timeout=10s&read_timeout=20s" rawDB, err := gorm.Open(clickhouse.Open(dsn), &gorm.Config{}) if err != nil { fmt.Print("failed to connect database") } fmt.Print(rawDB)为啥 就这两行 都链接不上啊,官方的就行 他娘嘞 处死后 都错误 failed to initialize database,