From d98469b30e9f7ab2c0b54e5a77c8c3b880f9e47c Mon Sep 17 00:00:00 2001 From: 4color's home Date: Fri, 5 Mar 2021 13:43:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E5=81=9Aclickhouse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dialects/clickhouse.go | 82 +++++++++++++++++++++++++++++++++++++ dialects/clickhouse_test.go | 27 ++++++++++++ dialects/dialect.go | 19 +++++---- dialects/driver.go | 9 ++++ schemas/type.go | 11 ++--- 5 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 dialects/clickhouse.go create mode 100644 dialects/clickhouse_test.go diff --git a/dialects/clickhouse.go b/dialects/clickhouse.go new file mode 100644 index 00000000..ee1c4a56 --- /dev/null +++ b/dialects/clickhouse.go @@ -0,0 +1,82 @@ +// Copyright 2020 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package dialects + +import ( + "context" + "net/url" + + "xorm.io/xorm/core" + "xorm.io/xorm/schemas" +) + +type clickhouse struct { + Base +} + +func (db *clickhouse) Init(uri *URI) error { + return db.Base.Init(db, uri) +} + +func (db *clickhouse) IsReserved(name string) bool { + return false +} + +func (db *clickhouse) SQLType(c *schemas.Column) string { + return "" +} + +func (db *clickhouse) SetQuotePolicy(quotePolicy QuotePolicy) { +} + +func (*clickhouse) AutoIncrStr() string { + return "" +} + +func (*clickhouse) CreateTableSQL(t *schemas.Table, tableName string) ([]string, bool) { + return nil, false +} + +func (*clickhouse) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { + return false, nil +} + +func (*clickhouse) Filters() []Filter { + return []Filter{} +} + +func (*clickhouse) GetColumns(core.Queryer, context.Context, string) ([]string, map[string]*schemas.Column, error) { + return nil, nil, nil +} + +func (db *clickhouse) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { + return nil, nil +} + +func (db *clickhouse) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { + return "", nil +} + +func (db *clickhouse) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { + return nil, nil +} + +// ParseClickHouse parsed clickhouse connection string +// tcp://host1:9000?username=user&password=qwerty&database=clicks&read_timeout=10&write_timeout=20&alt_hosts=host2:9000,host3:9000 +func ParseClickHouse(connStr string) (*URI, error) { + u, err := url.Parse(connStr) + if err != nil { + return nil, err + } + forms := u.Query() + return &URI{ + DBType: schemas.CLICKHOUSE, + Proto: u.Scheme, + Host: u.Hostname(), + Port: u.Port(), + DBName: forms.Get("database"), + User: forms.Get("username"), + Passwd: forms.Get("password"), + }, nil +} \ No newline at end of file diff --git a/dialects/clickhouse_test.go b/dialects/clickhouse_test.go new file mode 100644 index 00000000..97ae6998 --- /dev/null +++ b/dialects/clickhouse_test.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package dialects + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestParseClickHouse(t *testing.T) { + uri, err := ParseClickHouse("tcp://122.224.233.66:9823?username=&password=&database=clicks&read_timeout=10&write_timeout=20&alt_hosts=host2:9000,host3:9000") + assert.NoError(t, err) + + //assert.EqualValues(t, &URI{ + // DBType: schemas.CLICKHOUSE, + // Proto: "tcp", + // Host: "host1", + // Port: "9000", + // DBName: "clicks", + // User: "user", + // Passwd: "qwerty", + //}, uri) + + println(uri) + +} diff --git a/dialects/dialect.go b/dialects/dialect.go index 18b781a1..621b93a7 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -199,15 +199,16 @@ func regDrvsNDialects() bool { getDriver func() Driver getDialect func() Dialect }{ - "mssql": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, - "odbc": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access - "mysql": {"mysql", func() Driver { return &mysqlDriver{} }, func() Dialect { return &mysql{} }}, - "mymysql": {"mysql", func() Driver { return &mymysqlDriver{} }, func() Dialect { return &mysql{} }}, - "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }}, - "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }}, - "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, - "oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }}, - "goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }}, + "mssql": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, + "odbc": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access + "mysql": {"mysql", func() Driver { return &mysqlDriver{} }, func() Dialect { return &mysql{} }}, + "mymysql": {"mysql", func() Driver { return &mymysqlDriver{} }, func() Dialect { return &mysql{} }}, + "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }}, + "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }}, + "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, + "oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }}, + "goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }}, + "clickhouse": {"clickhouse", func() Driver { return &driverProxy{ParseClickHouse} }, func() Dialect { return &clickhouse{} }}, } for driverName, v := range providedDrvsNDialects { diff --git a/dialects/driver.go b/dialects/driver.go index ae3afe42..1e633d38 100644 --- a/dialects/driver.go +++ b/dialects/driver.go @@ -55,3 +55,12 @@ func OpenDialect(driverName, connstr string) (Dialect, error) { return dialect, nil } + + +type driverProxy struct { + parser func(connStr string) (*URI, error) +} + +func (p *driverProxy) Parse(driverName, dataSourceName string) (*URI, error) { + return p.parser(dataSourceName) +} \ No newline at end of file diff --git a/schemas/type.go b/schemas/type.go index f0ede296..64aeca19 100644 --- a/schemas/type.go +++ b/schemas/type.go @@ -14,11 +14,12 @@ import ( type DBType string const ( - POSTGRES DBType = "postgres" - SQLITE DBType = "sqlite3" - MYSQL DBType = "mysql" - MSSQL DBType = "mssql" - ORACLE DBType = "oracle" + POSTGRES DBType = "postgres" + SQLITE DBType = "sqlite3" + MYSQL DBType = "mysql" + MSSQL DBType = "mssql" + ORACLE DBType = "oracle" + CLICKHOUSE DBType = "clickhouse" ) // SQLType represents SQL types