Giter VIP home page Giter VIP logo

go-clickhouse's People

Contributors

al-tush avatar arkie avatar bgaifullin avatar cemezgin avatar doubledi avatar elbroom avatar elrondfromrussia avatar errx avatar evilaffliction avatar evrentan avatar fiery-fenix avatar glebvk85 avatar im-kulikov avatar jtroy avatar kimbeejay avatar kirilldanshin avatar maciej avatar maxprihodko avatar mishfish avatar mtojek avatar phil-schreiber avatar sl4mmer avatar slach avatar twowind avatar ukurysheva avatar vano144 avatar victor-perov avatar vladlutkov avatar yakud avatar zhenghaoz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-clickhouse's Issues

querying Nullable(DateTime) returns nil

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

Cannot rollback after getting an error when executing statement

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")
}

keep-alive connection to docker clickhouse

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!

Cannot get data and report an error:EOF v1.5.0

    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()

Unable to connect to intermediate services expecting DSN

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?

uint64 values with high bit set are not supported

В ридми вы пишите что поддерживаете uint64 Но при записи в базу мне возвращается эта ошибка. Не подскажите пожалуйстак ак это можно решить?

Cannot import go-clickhouse

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

Wrong placeholder interpolation

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:

if params != nil {

replace with

if params != nil && len(params) > 0 {

wrong dsn behavior

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?

Nullable(String) database field ScanType() return type is string

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).

CK server `Code:1000` error

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)

image

image

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

image

Don't ignore empty string when selecting single string field

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.

Sending query as a URL parameter in GET requests

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.

Wrong placeholder error on valid query

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)
	}
}

The behavior of binding an array var

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?

Example in Readme.md raises error

line 111:
rows, err := connect.QueryContext(context.WithValue(ctx, clickhouse.QueryID, "dummy-query-id"),
raises
No new variables on the left side of ':='

Invalid datetime encoding

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

Driver doesn't return an error on creating table on cluster with wrong data type

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)

Bugs on parse strings with double quotes

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

Decimal type support

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?

WITH TOTALS support

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.

Potential memory leak on conn exec

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
}

tcp connection

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")

Time is returned with wrong Time Zone.

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"

tx.Commit() is not thread safe

// 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?

Closing conn on stmt close

// 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?

wrong length of string selected from FixedString field

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?

[]uint8{} encoded as empty string

what's the reason for doing this?

go-clickhouse/encoder.go

Lines 74 to 75 in 8fe4eab

case []byte:
return string(v)

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.

error: Authorization via "Authorization" header fails when passing query via query-string

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

How to INSERT UUID field in columnar mode

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

Ping unexpected packet

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

Вопросы в JSON

Подскажите пожалуйста - как можно экранировать знак '?' при вставке в таблицу, чтобы библиотека не распознавала его как placeholder ?
Вставляю так

tx.Exec(`INSERT INTO table (
                        field
                       ,field1
                       ,field2
                       ,field3)
                      FORMAT JSONEachRow ` + args)

Где args это строка в виде JSON'a, среди значений параметров есть знаки ? .
При вставке получаю clickhouse: wrong placeholder count

Parse error on strings with double quotes

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

Go modules support

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
	...
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.