roistat / go-clickhouse

Golang ClickHouse connector
MIT License
189 stars 27 forks source link

format csv insertition #16

Open vidmed opened 7 years ago

vidmed commented 7 years ago

I want to use insert statement with format csv. For example

INSERT INTO events FORMAT CSV 8cd3e02c-83b1-41f0-8e29-c1681f03feb0,1a9cbce7-0788-430e-b3e7-15bbbea2ac27,3,0,0,0.000010,0.200000,,2017-02-27,1488203857,4,3,3,4,0,0,4,0,,,Unknown,Linux Unknown,0,0,[],,,0,0,0,,127.0.0.1,0,0,0,,0,,0,0,0,,,,,,,,,,,,,[]

For this purpose my code looks like (simplified)

...
query := clickhouse.NewQuery("INSERT INTO events FORMAT CSV https://github.com, https://vk.com")
query.Exec(c.chCluster.ActiveConn())
...

Everething works ok untill there is no "?" character in my query statement. When I`m doing something like this

query := clickhouse.NewQuery("INSERT INTO events FORMAT CSV https://github.com/roistat/go-clickhouse/issues?q=asdasda, https://vk.com/im?sel=12892913")

I have panic

panic: runtime error: index out of range

goroutine 1 [running]:
github.com/roistat/go-clickhouse.prepareHttp(0xc4570e6000, 0xd59f82b, 0x0, 0x0, 0x0, 0xc4200dc228, 0xc4212515c0)
        /home/dmitry/golang/src/github.com/roistat/go-clickhouse/transport.go:100 +0x270
github.com/roistat/go-clickhouse.HttpTransport.Exec(0xc42000c440, 0xc4570e6000, 0xd59f82b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc420000100, ...)
        /home/dmitry/golang/src/github.com/roistat/go-clickhouse/transport.go:23 +0xbf
github.com/roistat/go-clickhouse.(*HttpTransport).Exec(0x82b278, 0xc42000c440, 0xc4570e6000, 0xd59f82b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        <autogenerated>:4 +0x84
github.com/roistat/go-clickhouse.Query.Exec(0xc4570e6000, 0xd59f82b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc42000c440, 0x0, ...)
        /home/dmitry/golang/src/github.com/roistat/go-clickhouse/query.go:45 +0x7c
main.(*ClickhouseCluster).ExecQuery(0xc4200dc100, 0xc4570e6000, 0xd59f82b, 0x0, 0x0, 0x0, 0xd59f82b, 0x0)
        /home/dmitry/golang/src/main/clickhouse_cluster.go:39 +0x162
main.main()
        /home/dmitry/golang/src/main/main.go:132 +0x15b8

This panic cause your prepareHttp function in transport.go file, which tries to replace every "?" character with some arg, but args slice is empty.

func prepareHttp(stmt string, args []interface{}) string {
    var res []byte
    buf := []byte(stmt)
    res = make([]byte, 0)
    k := 0
    for _, ch := range buf {
        if ch == '?' {
            res = append(res, []byte(marshal(args[k]))...)
            k++
        } else {
            res = append(res, ch)
        }
    }

    return string(res)
}

Please, can you fix the problem or tell me how I can do such queries in another way.

m1nor commented 7 years ago

I see two ways to solve this issue:

  1. clickhouse.NewRawQuery() which will create Query that won't be prepared before running
  2. skip preparation if args slice is empty

In my opinion 1 is preferable, but it also adds entropy. Do you have any ideas?

vidmed commented 7 years ago

Я думаю, можно добавить дополнительный флаг в Query, который бы сигнализировал о том, что подготовка не нужна. Например так

type Query struct {
    Stmt      string
    args      []interface{}
    externals []External
    prepare   bool
}

И да, добавить еще один метод для получения такого запроса

func NewRawQuery(stmt string) Query {
    return Query{
        Stmt: stmt,
        prepare: false,
    }
}