mailru / go-clickhouse Goto Github PK
View Code? Open in Web Editor NEWGolang SQL database driver for Yandex ClickHouse
License: MIT License
Golang SQL database driver for Yandex ClickHouse
License: MIT License
If table contains column with type Nullable(DateTime), even if we fill it with data, fetching column returns nil.
Changed data type of action_time
in your example:
package main
import (
"database/sql"
"github.com/mailru/go-clickhouse"
"log"
"time"
)
func main() {
connect, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default")
if err != nil {
log.Fatal(err)
}
if err := connect.Ping(); err != nil {
log.Fatal(err)
}
_, err = connect.Exec(`
CREATE TABLE IF NOT EXISTS example (
country_code FixedString(2),
os_id UInt8,
browser_id UInt8,
categories Array(Int16),
action_day Date,
action_time Nullable(DateTime)
) engine=Memory
`)
if err != nil {
log.Fatal(err)
}
tx, err := connect.Begin()
if err != nil {
log.Fatal(err)
}
stmt, err := tx.Prepare(`
INSERT INTO example (
country_code,
os_id,
browser_id,
categories,
action_day,
action_time
) VALUES (
?, ?, ?, ?, ?, ?
)`)
if err != nil {
log.Fatal(err)
}
for i := 0; i < 100; i++ {
if _, err := stmt.Exec(
"RU",
10+i,
100+i,
clickhouse.Array([]int16{1, 2, 3}),
clickhouse.Date(time.Now()),
time.Now(),
); err != nil {
log.Fatal(err)
}
}
if err := tx.Commit(); err != nil {
log.Fatal(err)
}
rows, err := connect.Query(`
SELECT
country_code,
os_id,
browser_id,
categories,
action_day,
action_time
FROM
example`)
if err != nil {
log.Fatal(err)
}
for rows.Next() {
var (
country string
os, browser uint8
categories []int16
actionDay time.Time
actionTime *time.Time
)
if err := rows.Scan(
&country,
&os,
&browser,
&categories,
&actionDay,
&actionTime,
); err != nil {
log.Fatal(err)
}
log.Printf("country: %s, os: %d, browser: %d, categories: %v, action_day: %s, action_time: %s",
country, os, browser, categories, actionDay, actionTime,
)
log.Printf("%t", actionTime == nil)
}
}
clickhouse version: 21.4.5.46
Perhaps you can use revive insted of archived golint.
Or even better more complex solution - https://golangci-lint.run
I can't rollback the transaction after getting a statement execution error within the transaction.
When trying to rollback, an error sql: transaction has already been committed or rolled back
occurs even though commit is not reached because of panic.
package main
import (
"database/sql"
"log"
"time"
_ "github.com/mailru/go-clickhouse"
)
func failOnErr(err error, msg string) {
if err != nil {
log.Panicf("%s: %s\n\n", msg, err)
}
}
func main() {
conn, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default")
failOnErr(err, "failed to connect")
defer conn.Close()
conn.Exec(`
CREATE TABLE mytable(id UUID, ts DateTime, age Int32, CONSTRAINT check_age CHECK age > 6)
ENGINE = MergeTree() PARTITION BY toYYYYMM(ts) PRIMARY KEY ts ORDER BY ts;`)
txn, err := conn.Begin()
failOnErr(err, "failed to create txn")
defer func() {
err := txn.Rollback() // error occurs, why?
if err != nil {
log.Println("txn.Rollback: ", err)
}
}()
stmt, err := txn.Prepare("INSERT INTO mytable(id,ts,age)VALUES(?,?,?)")
failOnErr(err, "failed to prepare stmt")
defer func() {
err := stmt.Close()
if err != nil {
log.Println("stmt.Close: ", err)
}
}()
_, err = stmt.Exec("8a41192d-9f37-4bc0-9bed-bb667fb66495", time.Now(), 10)
failOnErr(err, "failed to execute stmt 1")
_, err = stmt.Exec("8a41192d-9f37-4bc0-9bed-bb667fb66495", time.Now(), 5) // knowingly incorrect query
failOnErr(err, "failed to execute stmt 2") // here get a panic because of the constraint "check_age"
err = txn.Commit()
failOnErr(err, "failed to commit txt")
}
Hi!
Having following DSN:
http://172.17.0.2:8123/default?timeout=30s&idle_timeout=30s&debug=true
and ClickHouse running inside docker I try to get keep-alive connection with no luck.
Seems like connection closed right after transaction committed (checked with lsof -p PID
).
Also tried with different idle_timeout
values (including zero, which I expect makes it keep-alive forever).
Looking to hearing from you, thanks!
when i used DateTime64 type field, i got this error:
"type DateTime64 is not supported"
connect, err := sql.Open("clickhouse", fmt.Sprintf("http://%s/%s", "127.0.0.1:8123", "default"))
if err != nil {
fmt.Println(err.Error())
return
}
err = connect.Ping()
if err != nil {
fmt.Println(err.Error())
return
}
sols := fmt.Sprintf("select id,name from %s limit 10", TableName())
rows, err := connect.Query(sols)
if err != nil {
fmt.Println(err.Error())
return
}
//If the name value is empty, the Next() method directly skips the name value and the following data, and rows.Err()
//reports error: EOF
// version v1.5.0
for rows.Next() {
var (
id uint64
name string
)
err := rows.Scan(&id, &name)
if err != nil {
continue
}
fmt.Println(id, name)
}
if rows.Err() != nil {
fmt.Println(rows.Err().Error())
}
_ = rows.Close()
Due to config.url
being passed the param dsn=false
when creating a new connection, when connecting to a service that expects the DSN to be passed in full (e.g. github.com/nikepan/clickhouse-bulk) we end up only ever being able to connect to the default
database.
The following code from config.url
shows that the database is set by a query, rather than as part of the dsn.
if len(cfg.Database) > 0 {
if dsn {
u.Path += cfg.Database
} else {
query.Set("database", cfg.Database)
}
}
Are we able to make this dsn flag a parameter of the call to Open?
Hello, thx for the library!
How to insert nested fields?
В ридми вы пишите что поддерживаете uint64 Но при записи в базу мне возвращается эта ошибка. Не подскажите пожалуйстак ак это можно решить?
Hello, I am trying to use your library but when I run go get -u github.com/mailru/go-clickhouse, I get the following error:
../../../../go/src/github.com/mailru/go-clickhouse/conn.go:316:23: multiple-value uuid.NewV4() in single-value context.
I read an other issue with the same error, but there wasn't an answer.
Thank you in advance
Go version
go version go1.14.2 linux/amd64
Module version
Code to reproduce
package main
import (
"database/sql"
"log"
_ "github.com/mailru/go-clickhouse"
)
func main() {
connect, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default")
if err != nil {
log.Fatal(err)
}
_, err = connect.Exec(`
CREATE TABLE IF NOT EXISTS test (str String) engine=Memory`)
if err != nil {
log.Fatal(err)
}
_, err = connect.Exec(`INSERT INTO test (str) VALUES ("Question?")`)
if err != nil {
log.Fatal(err)
}
}
Expected result:
Row successfully inserted
Actual result:
clickhouse: wrong placeholder count
Possible solution:
Line 289 in 433b4a0
if params != nil && len(params) > 0 {
Having this DSN
addr := fmt.Sprintf(`http://%s:8123/users?timeout=1s&debug=true`,
r.Container.NetworkSettings.IPAddress)
and CH running inside container I'm trying to connect to my database (users
in example above) with this code:
conn, err := sql.Open("clickhouse", addr)
if err != nil {
return nil, err
}
if err = conn.Ping(); err != nil {
return nil, err
}
And it always connects even database users
doesn't exists. I expect to receive error on sql.Open()
. Otherwise you receive error right after first query.
Should I manually check that database exists?
hello, I want execute some dynamic query and I can't know the result in coding. So I use ScanType() get type and use reflect.New() create value。but the type is string when filed is Nullable(String). It make error when value is Null。
create table test (
id Int64,
title String default '',
null_title Nullable(String)
) engine = MergeTree() order by id;
insert into test (id, title, null_title)
values
(0, '', NULL),
(1, 'hello', 'hello');
package main
import (
"database/sql"
"encoding/json"
"fmt"
_ "github.com/ClickHouse/clickhouse-go"
_ "github.com/go-sql-driver/mysql"
"reflect"
)
func main() {
db, err := sql.Open("clickhouse", "xxxx")
if err != nil {
panic(err)
}
rows, err := db.Query("select id, title, null_title from test ")
if err != nil {
panic(err)
}
cols, err := rows.ColumnTypes()
if err != nil {
panic(err)
}
for rows.Next() {
sl := make([]interface{}, len(cols))
for i, col := range cols {
t := col.ScanType()
col.DatabaseTypeName()
fmt.Printf("%s type is %v\n", col.Name(), t)
v := reflect.New(t)
sl[i] = v.Interface()
}
err = rows.Scan(sl...)
if err != nil {
panic(err)
}
rowMap := make(map[string]interface{})
for i, col := range cols {
rowMap[col.Name()]= sl[i]
}
fmt.Printf("print result:")
bs, err := json.Marshal(rowMap)
if err != nil {
panic(bs)
}
fmt.Printf("%s", string(bs))
fmt.Printf("\n")
}
}
when i execute it, the error :
panic: sql: Scan error on column index 2, name "null_title": converting NULL to string is unsupported
I read the code. I find Nullable's ScanType return column's ScanType which is it contain type。
func parseNullable(name, chType string, timezone *time.Location) (*Nullable, error) {
if len(chType) < 14 {
return nil, fmt.Errorf("invalid Nullable column type: %s", chType)
}
column, err := Factory(name, chType[9:][:len(chType)-10], timezone)
if err != nil {
return nil, fmt.Errorf("Nullable(T): %v", err)
}
return &Nullable{
base: base{
name: name,
chType: chType,
},
column: column,
}, nil
}
type Nullable struct {
base
column Column
}
func (null *Nullable) ScanType() reflect.Type {
return null.column.ScanType()
}
Maybe the code should be:
type Nullable struct {
base
column Column
}
func (null *Nullable) ScanType() reflect.Type {
return reflect.PtrTo(null.column.ScanType())
}
Because it is right when I use *string to scan Nullable(String).
initially, we use github.com/kshvakov/clickhouse
for a little while. but we found it write data much slower than java http client (the only one listed in ck document). (snmpdump shows 10x smaller package size compare to java http client)
so we replaced it with this driver and outcome is good (similar performance as java http client). there are only minor flaws: once we start the program ck server pop out many Code: 1000
error. which never happens before. even with github.com/kshvakov/clickhouse
or java client.
since db/sql
provider high level abstraction. so we don't touch the code to write clickhouse while replacing the driver. we only modifed some args to setup the connection.
main code looks like this
var conn *sql.DB
var bulkChan = make(bulk, 0)
func (t *ckTable) bulkWrite(conn *sql.DB, bulk *ClickhouseBulk) error {
tx, err := conn.Begin()
if err != nil {
return err
}
// odd... this has to be added while using `github.com/kshvakov/clickhouse`, otherwise OOM
// with this driver. even comment this out, `Code:1000` remains
defer tx.Rollback()
stmt1, err := tx.Prepare()
if err != nil {
return err
}
// comment this out, `Code:1000` remains
defer stmt1.Close()
for _, row := range bulk {
err = stmt1.exec(row...)
// sampled log err
}
return tx.Commit()
}
// worker goroutine
go func(){
for blk := range bulkChan {
table := tables[blk.table]
table.bulkWrite(conn, bulk)
}
}()
no where to handle connection anywhere in our code.... and the worker goroutine never exit
Hello, after the last commit I get this error:
github.com/mailru/go-clickhouse/conn.go:308:23: multiple-value uuid.NewV4() in single-value context
Hi there!
Suppose you have following table
:
id | host
----------------
1 | aaa.ru
2 | ""
Executing following query:
select host from table
returns aaa.ru
only, but we have 2 hosts in table.
The reason is csvReader
which is used to parse response body.
Actually he skips empty lines, see his source code:
func (r *Reader) readRecord(dst []string) ([]string, error) {
...
if errRead == nil && len(line) == lengthNL(line) {
line = nil
continue // Skip empty lines
}
...
Of course you want to get empty host when you extracting ALL hosts from table.
So I'm not sure that it's ok to use csvReader
there.
At the moment readonly queries are sent inside the body of the GET HTTP request. This works fine with Clickhouse, but it can make it difficult to integrate with HTTP middleware, for example, if you use caching HTTP proxy in front of the Clickhouse that uses URL as the caching key.
It seems like it would be reasonable to send query as a URL parameter in GET requests, not in the request body, or at least be able to configure this behavior.
Will there be any plans in the future to add SSL support?
If field have value "0000-00-00" (when field type is Date) or "0000-00-00 00:00;00" (for DateTime type) go-clickhouse gets error: :" month out of range"
In Clickhouse there are valid values and synonyms for "1970-01-01"/"1970-01-01 00:00:00" https://clickhouse.yandex/docs/en/single/#date
Hello,
During high intensive inserts with an arbitrary text data I noticed the error message:
clickhouse: wrong placeholder count
After digging the problem source, it seems like a bug in escaping function to me, because Exec
fails only on combination of quote and question mark values on two different fields. It may have security implications, but unfortunately I don't really have a time to prove/disprove this at the moment.
I wrote a simple snippet to play with, that pops this error:
package main
import (
"database/sql"
"log"
_ "github.com/mailru/go-clickhouse"
)
func main() {
conn, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default?debug=1")
if err != nil {
log.Fatal(err)
}
if err := conn.Ping(); err != nil {
log.Fatal(err)
}
_, err = conn.Exec(`
CREATE TABLE IF NOT EXISTS example (
field1 String,
field2 String,
field3 String,
date Date DEFAULT today()
) engine=MergeTree(date,field1,8192)
`)
if err != nil {
log.Fatal(err)
}
_, err = conn.Exec(`INSERT INTO example VALUES ('field1', "'", '?')`)
if err != nil {
log.Fatal(err)
}
}
I just copy past code: https://github.com/mailru/go-clickhouse#example
And run it in console.
2017/08/07 21:53:05 Code: 73, Message: Unknown format TSVWithNamesAndTypes
exit status 1
https://gist.github.com/romanitalian/6ad1d22ba1db816748a441bdfa133758
uname -a
2.6.32-042stab105.14 #1 SMP Fri Mar 13 20:06:37 MSK 2015 x86_64 x86_64 x86_64 GNU/Linux
I want to use something like this:
SELECT * FROM a WHERE (a,b) IN ((1,2),(2,3)
. How to do this with sql/sqlx with clickhouse driver?
ClickHouse allows for compression on the HTTP interface
https://clickhouse.yandex/docs/en/interfaces/http_interface/
It is […] possible to use the standard gzip-based HTTP compression. To send a POST request compressed using gzip, append the request header Content-Encoding: gzip. In order for ClickHouse to compress the response using gzip, you must append Accept-Encoding: gzip to the request headers[…]
The driver should support that.
hi, I found that when the var is an array, the driver will interpolate the value as a string without brackets.
example:
stmt, err := tx.Prepare("select * from persons where hasAny(array, ? )")
_, err = stmt.Exec([]string{"k1", "v1"})
The generated SQL is syntax wrong.
select * from persons where hasAny(array, 'k1', 'v1')
As a workaround, I change my SQL to this
select * from persons where hasAny(array, [?] )
and the generated SQL is accepted by the server
select * from persons where hasAny(array, ['k1', 'v1'])
However, this looks like a small bug to me. Will this behavior change in the future version?
line 111:
rows, err := connect.QueryContext(context.WithValue(ctx, clickhouse.QueryID, "dummy-query-id"),
raises
No new variables on the left side of ':='
If I insert datetime with zeroes in second, minute and hour like "2017-12-29 00:00:00" I got error
"error":"clickhouse: Code: 41, e.displayText() = DB::Exception: Cannot parse datetime 2017-12-29: (at row 1)\n, e.what() = DB::Exception\n"
formatTime() function works incorrect way
Step to reproduce:
connect, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default")
if err != nil {
log.Fatal(err)
}
if err := connect.Ping(); err != nil {
log.Fatal(err)
}
_, err = connect.Exec(`
CREATE TABLE "default"."test_driver_1"
ON CLUSTER "mycluster"
(_timestamp DateTime, wrongcolumn Lowcardinality(String))
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{shard}/default/test_driver_1', '{replica}', _timestamp)
PARTITION BY (toYYYYMM(_timestamp))
ORDER BY (_timestamp)
`)
if err != nil {
log.Fatal(err)
}
Actual behavior: no error (but the table isn't created)
Expected behavior: error Code: 50, e.displayText() = DB::Exception: There was an error on [clickhouse2:9000]: Code: 50, e.displayText() = DB::Exception: Unknown data type family: Lowcardinality. Maybe you meant: ['LowCardinality'] (version 20.9.3.45 (official build)) (version 20.9.3.45 (official build)
Still get an errors on latest master(e482166)
Code to reproduce
package main
import (
"database/sql"
"log"
_ "github.com/mailru/go-clickhouse"
)
func main() {
connect, err := sql.Open("clickhouse", "http://127.0.0.1:8123/default")
if err != nil {
log.Fatal(err)
}
defer connect.Close()
if err := connect.Ping(); err != nil {
log.Fatal(err)
}
query1 := `SELECT '"foo" foo', 'bar'`
var foo1, bar1 string
err = connect.QueryRow(query1).Scan(&foo1, &bar1)
if err != nil {
log.Print(err)
} else {
log.Printf("%s %s", foo1, bar1)
}
query2 := `SELECT 'bar', '"foo" foo'`
var foo2, bar2 string
err = connect.QueryRow(query2).Scan(&foo2, &bar2)
if err != nil {
log.Print(err)
} else {
log.Printf("%s %s", foo2, bar2)
}
}
Output:
2021/01/15 16:14:11 record on line 3: wrong number of fields
2021/01/15 16:14:11 bar foo" foo
Expected output:
2021/01/15 16:14:11 "foo" foo bar
2021/01/15 16:14:11 bar "foo" foo
When trying to select Decimal data, we've got an error: "type Decimal is not supported".
Is Decimal support in your plans and is there a workaround for that?
Currently rows.Next() breaks on the first empty line when WITH TOTALS is used in a query. The total row is separated from the main data by an empty line.
gzip works on selects only. What about Inserts?
Take a look on this part of code
func (c *conn) exec(ctx context.Context, query string, args []driver.Value) (driver.Result, error) {
// ...
_, err = c.doRequest(ctx, req)
return emptyResult, err
}
doRequest
returns response body and in this case body hasn't been closed. I guess this is possible memory leak because the connection could remain open. I've got this issue in my application.
This could be fixed:
func (c *conn) exec(ctx context.Context, query string, args []driver.Value) (driver.Result, error) {
// ...
body, err = c.doRequest(ctx, req)
if body != nil {
body.Close()
}
return emptyResult, err
}
Please tell me how to connect by tcp (native interface)?
This does not work: connect, err := sql.Open("clickhouse", "tcp://127.0.0.1:9000")
The latest Library received with the 'dep ensure -update' Command, has a Bug.
It returns Time with wrong Time Zone.
The old Version of this Library returned a correct Time Zone.
I receive Time from Database into a String.
For Example, for 'MSK' Time Zone, the old Library returned Time as '2019-09-01T00:00:00+03:00' String.
The latest Library for 'MSK' Time Zone returns Time as '2019-09-01T00:00:00Z' String.
Gopkg.toml:
[[constraint]]
name = "github.com/mailru/go-clickhouse"
version = "1.1.0"
// Begin starts and returns a new transaction.
func (c *conn) Begin() (driver.Tx, error) {
return c.beginTx(context.Background())
}
func (c *conn) beginTx(ctx context.Context) (driver.Tx, error) {
if atomic.LoadInt32(&c.closed) != 0 {
return nil, driver.ErrBadConn
}
c.txCtx = ctx
return c, nil
}
actually, the driver.Tx
returned by Being()
is conn
itself. and conn
(aka Tx) hold all prepared stmts globally
.
func (c *conn) prepare(query string) (*stmt, error) {
if atomic.LoadInt32(&c.closed) != 0 {
return nil, driver.ErrBadConn
}
c.log("new statement: ", query)
s := newStmt(query)
s.c = c
if c.txCtx == nil {
s.batchMode = false
}
if s.batchMode {
c.stmts = append(c.stmts, s)
}
return s, nil
}
consider this sitution:
thread 1: tx := Begin(), prepare(), stmt.exec(), ....... stmt.exec() ..................... tx.Commit()
thread 2: tx := Begin(), prepare(), stmt.exec(), ....... stmt.exec() tx.Commit();
thread 2
commit before thread 1
. what happened then:
since tx
is conn
, so.... all stmts will be moved out from conn
private scope to Commit()
. and then commit all stmts
subsequently, which including a stmt
prepared within thread1
. but that stmt is not ready to be committed yet.
// Commit applies prepared statement if it exists
func (c *conn) Commit() (err error) {
if atomic.LoadInt32(&c.closed) != 0 {
return driver.ErrBadConn
}
if c.txCtx == nil {
return sql.ErrTxDone
}
ctx := c.txCtx
stmts := c.stmts
c.txCtx = nil
c.stmts = stmts[:0]
if len(stmts) == 0 {
return nil
}
for _, stmt := range stmts {
c.log("commit statement: ", stmt.prefix, stmt.pattern)
if err = stmt.commit(ctx); err != nil {
break
}
}
return
}
Is it better to have an independent Tx
struct to hold states not been shared globally to avoid of this ? or I just get lost some where?
// Close closes the statement.
func (s *stmt) Close() error {
if atomic.CompareAndSwapInt32(&s.closed, 0, 1) {
s.c = nil
}
return nil
}
As you can see in this code s.c
hasn't been closed.
In my application i've got memory leak here. I've tried to use timeout and idle_timeout settings but it didn't help.
For me i've fixed this issue like this:
// Close closes the statement.
func (s *stmt) Close() error {
if atomic.CompareAndSwapInt32(&s.closed, 0, 1) {
if s.c != nil {
s.c.Close()
}
s.c = nil
}
return nil
}
Is this a bug or i'm doing something wrong?
DefaultParameterConverter.ConvertValue have known issue for high uint64 values
The ParseDSN
function extracts the tls config key from the query parameter tls_config
https://github.com/mailru/go-clickhouse/blob/master/config.go#L164
however this parameter is not set in FormatDSN()
Hi all,
My table contains FixedString(8) field and it's exactly 8 bytes length:
select fee_asset, length(fee_asset) from log limit 1
| BTC | 8 |
But receiving this field using SELECT
statement and your driver I always receive 12 bytes string:
BTC \0\0\0\0
.
To get value I'm using Scan
method for sql.Rows.
Is it expected and I'm doing something wrong?
what's the reason for doing this?
Lines 74 to 75 in 8fe4eab
We have a column diff UInt8
in a Nested
column which requires to insert field.diff as Array(UInt8)
but the driver seems to encode []uInt8
as a string which in case of an empty array gives you the empty string.
insert: Code: 62, Message: Cannot parse expression of type Array(UInt8) here: , 0)
Also this could be dangerous regarding sql injections.
Current implementation put full query result to buffer. It is very unoptimal for big results. Please add streaming mode for querys. It is implemented ok in https://github.com/kshvakov/clickhouse
I make GET-requests to clickhouse and pass authorization info in "Authorization" header and query via query string. But on a little fraction of queries clickhouse constantly returns error
Code: 195, e.displayText() = DB::Exception: User default is not allowed to connect from address ::ffff:100.116.16.11, e.what() = DB::Exception
After some research i found out that this error occurs only on requests with query-string with length equal to 4077 symbols. First line of this query looks like
GET /?<ANY_VALID_QUERY_STRING_OF_LENGTH=4077> HTTP/1.1
Example of such query:
GET /?database=target&default_format=TabSeparatedWithNamesAndTypes&query=SELECT+%60date%60+AS+%60time%60%2C+banner_id+AS+%60entity_id%60%2C+sumIf%28currency_a_amount%2Bcurrency_n_amount%2Btps_currency_a_amount%2Btps_currency_n_amount%2C+charging_status_bit%3D0%29+AS+%60amount%60%2C+sumIf%28currency_a_amount%2Btps_currency_a_amount%2C+charging_status_bit%3D0%29+AS+%60a_amount%60%2C+sumIf%28count%2C+event_type%3D10+OR+event_type%3E%3D100%29+AS+%60customs%60%2C+sumIf%28count%2C+event_type%3D0%29+AS+%60shows%60%2C+sumIf%28count%2C+event_type%3D1%29+AS+%60clicks%60%2C+sumIf%28count%2C+event_type%3D7%29+AS+%60goals%60%2C+sumIf%28count%2C+event_type%3D1090%29+AS+%60opening_post%60%2C+sumIf%28count%2C+event_type%3D1091%29+AS+%60likes%60%2C+sumIf%28count%2C+event_type%3D1092%29+AS+%60shares%60%2C+sumIf%28count%2C+event_type%3D1093%29+AS+%60comments%60%2C+sumIf%28count%2C+event_type%3D1094%29+AS+%60clicks_on_external_url%60%2C+sumIf%28count%2C+event_type%3D1095%29+AS+%60launching_video%60%2C+sumIf%28count%2C+event_type%3D1097%29+AS+%60votings%60%2C+sumIf%28count%2C+event_type%3D1099%29+AS+%60opening_app%60%2C+sumIf%28count%2C+event_type%3D1100%29+AS+%60moving_into_group%60%2C+sumIf%28count%2C+event_type%3D1105%29+AS+%60joinings%60%2C+sumIf%28count%2C+event_type%3D1202%29+AS+%60sending_form%60%2C+sumIf%28count%2C+event_type%3D1005%29+AS+%60sound_off%60%2C+sumIf%28count%2C+event_type%3D1006%29+AS+%60sound_on%60%2C+sumIf%28count%2C+event_type%3D1010%29+AS+%60fullscreen_on%60%2C+sumIf%28count%2C+event_type%3D1011%29+AS+%60fullscreen_off%60%2C+sumIf%28count%2C+event_type%3D1007%29+AS+%60paused%60%2C+sumIf%28count%2C+event_type%3D1009%29+AS+%60resumed%60%2C+sumIf%28count%2C+event_type%3D1000%29+AS+%60video_started%60%2C+sumIf%28count%2C+event_type%3D1017%29+AS+%60video_viewed_10%60%2C+sumIf%28count%2C+event_type%3D1001%29+AS+%60video_viewed_25%60%2C+sumIf%28count%2C+event_type%3D1002%29+AS+%60video_viewed_50%60%2C+sumIf%28count%2C+event_type%3D1003%29+AS+%60video_viewed_75%60%2C+sumIf%28count%2C+event_type%3D1013%29+AS+%60video_viewed_100%60%2C+sumIf%28count%2C+event_type%3D4009%29+AS+%60video_viewable_50_2_sec%60%2C+sumIf%28count%2C+event_type%3D4011%29+AS+%60video_non_viewable_50_2_sec%60%2C+sumIf%28count%2C+event_type%3D1121%29+AS+%60slide_1_clicks%60%2C+sumIf%28count%2C+event_type%3D1122%29+AS+%60slide_1_shows%60%2C+sumIf%28count%2C+event_type%3D1123%29+AS+%60slide_2_clicks%60%2C+sumIf%28count%2C+event_type%3D1124%29+AS+%60slide_2_shows%60%2C+sumIf%28count%2C+event_type%3D1125%29+AS+%60slide_3_clicks%60%2C+sumIf%28count%2C+event_type%3D1126%29+AS+%60slide_3_shows%60%2C+sumIf%28count%2C+event_type%3D1127%29+AS+%60slide_4_clicks%60%2C+sumIf%28count%2C+event_type%3D1128%29+AS+%60slide_4_shows%60%2C+sumIf%28count%2C+event_type%3D1129%29+AS+%60slide_5_clicks%60%2C+sumIf%28count%2C+event_type%3D1130%29+AS+%60slide_5_shows%60%2C+sumIf%28count%2C+event_type%3D1131%29+AS+%60slide_6_clicks%60%2C+sumIf%28count%2C+event_type%3D1132%29+AS+%60slide_6_shows%60+FROM+hour_banner_events+WHERE+%28%60date%60+BETWEEN+%272018-07-22%27+AND+%272018-07-23%27%29+AND+%28%60timestamp%60+BETWEEN+%272018-07-22+00%3A00%3A00%27+AND+%272018-07-23+23%3A59%3A59%27%29+AND+%28%60advertiser_id%60+%3D+3225395%29+AND+%28%60banner_id%60+IN+%2831521382%2C31521383%2C31521384%2C31521385%2C31521386%2C31521387%2C31708840%2C31708841%2C31708846%2C31708848%2C31708849%2C31708851%2C31708906%2C31708912%2C31708914%2C31708915%2C31708917%2C31954684%2C31954686%2C31954687%2C31954693%2C31954694%2C31954695%2C31954696%2C31954697%2C31954699%2C31954700%2C31954701%2C31954721%2C31954722%2C31954723%2C31954724%2C31954725%2C32119663%2C32119664%2C32119665%2C32119666%2C32119667%2C32119669%2C32119754%2C32119755%2C32119756%2C32119757%2C32119758%2C32119760%2C32120038%2C32120039%2C32120040%2C32120041%2C32120042%2C32120044%2C32120086%2C32120087%2C32120088%2C32120089%2C32120090%2C32120092%2C32160971%2C32160972%2C32161008%2C32161009%29%29+AND+%28charging_status_bit%3D0+OR+%28charging_status_bit%3D16+AND+currency_a_amount%3D0+AND+currency_n_amount%3D0%29%29+GROUP+BY+%60time%60%2C+%60entity_id%60 HTTP/1.1
This error is observed on clickhouse 1.1.54385
Hi,
I'm having some issues batch INSERTing rows with the columnar dialect. even in the clickhouse_columnar_test.go
unit test, there's no UUID insert as an example. Can you please provide some documentation on how this should be done.
Thanks
After executing the code
func TestMailru(t *testing.T) {
cfg := config.New("..//config.json") //config.Config{Path:"..//config_dev.json"}
err := cfg.Read()
if err != nil {
t.Fatalf("Connect >> Config >> %v", err)
}
connStr := fmt.Sprintf("https://%s:%s/?user=%s&password=%s", cfg.ClickHouse.Host, cfg.ClickHouse.Port , cfg.ClickHouse.UserName, cfg.ClickHouse.Password)
connect, err := sql.Open("clickhouse", connStr)
if err != nil {
t.Fatalf("Open >> %v", err)
}
if err := connect.Ping(); err != nil {
t.Fatalf("Ping >> %v", err)
}
}
Got error
Ping >> [hello] unexpected packet [72] from server
Подскажите пожалуйста - как можно экранировать знак '?' при вставке в таблицу, чтобы библиотека не распознавала его как placeholder ?
Вставляю так
tx.Exec(`INSERT INTO table (
field
,field1
,field2
,field3)
FORMAT JSONEachRow ` + args)
Где args это строка в виде JSON'a, среди значений параметров есть знаки ? .
При вставке получаю clickhouse: wrong placeholder count
dsn: http://default:aaaaa/bbbb/[email protected]:10001/
Connect(function): parse http://default:aaaaa/bbbb/[email protected]:10001/: invalid port ":aaaaa" after host
The following error occurs when trying to select a string field containing double quotes:
parse error on line 1, column 2: bare " in non-quoted-field
Code to reproduce:
package main
import (
"database/sql"
"log"
_ "github.com/mailru/go-clickhouse"
)
func main() {
connect, err := sql.Open("clickhouse", "http://[email protected]:8123/default")
if err != nil {
log.Fatal(err)
}
var f1, f2 string
err = connect.QueryRow(`SELECT '"foo" foo', 'bar'`).Scan(&f1, &f2)
if err != nil {
log.Fatal(err)
}
}
go-clickhouse version: f16ee58
clickhouse version: 18.10.3
Same issue mailru/dbr#16
In order not to break anything, I suggest to add the following tags:
For now, after go mod tidy
I have:
module some/project
require (
...
github.com/mailru/go-clickhouse v0.0.0-20180822112201-2af3abdc4318 // indirect
...
)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.