Compare commits

...

5 Commits

Author SHA1 Message Date
f34304433e improve clickhouse driver 2022-04-25 13:17:48 +08:00
bb3ca6d414 improve clickhouse driver 2022-04-19 14:21:03 +08:00
674eada9ed improve clickhouse driver 2022-04-19 14:20:00 +08:00
310baaf67d improve clickhouse driver 2022-04-19 14:18:25 +08:00
c9971b21ec improve clickhouse driver 2022-04-19 14:15:53 +08:00
7 changed files with 489 additions and 184 deletions

View File

@ -87,7 +87,7 @@ jobs:
# strategy set
strategy:
matrix:
go: ["1.15", "1.16", "1.17"]
go: ["1.16", "1.17"]
steps:

View File

@ -58,10 +58,8 @@ import _ "github.com/gogf/gf/contrib/drivers/clickhouse/v2"
```
Note:
- It does not support `InsertIgnore/InsertGetId` features.
- It does not support `Save/Replace` features.
- It does not support `Transaction` feature.
- It does not support `Transaction` feature.
- It does not support `RowsAffected` feature.
# Custom Drivers

View File

@ -12,10 +12,11 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/longbridgeapp/sqlparser"
"net/url"
"strings"
"github.com/ClickHouse/clickhouse-go"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
@ -33,12 +34,13 @@ type Driver struct {
var (
// tableFieldsMap caches the table information retrieved from database.
tableFieldsMap = gmap.New(true)
errUnsupportedInsertIgnore = errors.New("unsupported method: InsertIgnore")
errUnsupportedInsertGetId = errors.New("unsupported method: InsertGetId")
errUnsupportedReplace = errors.New("unsupported method: Replace")
errUnsupportedBegin = errors.New("unsupported method: Begin")
errUnsupportedTransaction = errors.New("unsupported method: Transaction")
errSQLNull = errors.New("SQL cannot be null")
errUnsupportedInsertIgnore = errors.New("unsupported method:InsertIgnore")
errUnsupportedInsertGetId = errors.New("unsupported method:InsertGetId")
errUnsupportedReplace = errors.New("unsupported method:Replace")
errUnsupportedBegin = errors.New("unsupported method:Begin")
errUnsupportedTransaction = errors.New("unsupported method:Transaction")
errNotCondition = errors.New("there should be WHERE condition statement for UPDATE/DELETE operation")
errNotAssignment = errors.New("there should be WHERE condition statement for Assignment operation")
)
func init() {
@ -70,12 +72,12 @@ func (d *Driver) Open(config *gdb.ConfigNode) (*sql.DB, error) {
source = config.Link
} else if config.Pass != "" {
source = fmt.Sprintf(
"clickhouse://%s:%s@%s:%s/%s?charset=%s&debug=%s",
config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset, gconv.String(config.Debug))
"clickhouse://%s:%s@%s:%s/%s?charset=%s&debug=%t",
config.User, url.PathEscape(config.Pass), config.Host, config.Port, config.Name, config.Charset, config.Debug)
} else {
source = fmt.Sprintf(
"clickhouse://%s@%s:%s/%s?charset=%s&debug=%s",
config.User, config.Host, config.Port, config.Name, config.Charset, gconv.String(config.Debug))
"clickhouse://%s@%s:%s/%s?charset=%s&debug=%t",
config.User, config.Host, config.Port, config.Name, config.Charset, config.Debug)
}
db, err := sql.Open(driver, source)
if err != nil {
@ -128,7 +130,7 @@ func (d *Driver) TableFields(
if link, err = d.SlaveLink(useSchema); err != nil {
return nil
}
getColumnsSql := fmt.Sprintf("select name,position,default_expression,comment from `system`.columns c where database = '%s' and `table` = '%s'", d.GetConfig().Name, table)
getColumnsSql := fmt.Sprintf("select name,position,default_expression,comment,type from `system`.columns c where database = '%s' and `table` = '%s'", d.GetConfig().Name, table)
result, err = d.DoSelect(ctx, link, getColumnsSql)
if err != nil {
return nil
@ -210,33 +212,78 @@ func (d *Driver) ping(conn *sql.DB) error {
func (d *Driver) DoFilter(
ctx context.Context, link gdb.Link, originSql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
// It replaces STD SQL to Clickhouse SQL grammar.
// MySQL eg: UPDATE visits SET xxx
// Clickhouse eg: ALTER TABLE visits UPDATE xxx
// MySQL eg: DELETE FROM VISIT
// Clickhouse eg: ALTER TABLE VISIT DELETE WHERE filter_expr
result, err := gregex.MatchString("(?i)^UPDATE|DELETE", originSql)
if len(args) == 0 {
return originSql, args, nil
}
var index int
// Convert placeholder char '?' to string "$x".
originSql, _ = gregex.ReplaceStringFunc(`\?`, originSql, func(s string) string {
index++
return fmt.Sprintf(`$%d`, index)
})
// Only SQL generated through the framework is processed.
if !d.GetNeedParsedSqlFromCtx(ctx) {
return originSql, args, nil
}
// replace STD SQL to Clickhouse SQL grammar
parsedStmt, err := sqlparser.NewParser(strings.NewReader(originSql)).ParseStatement()
if err != nil {
return "", nil, err
}
if len(result) != 0 {
sqlSlice := strings.Split(originSql, " ")
if len(sqlSlice) < 3 {
return "", nil, errSQLNull
switch stmt := parsedStmt.(type) {
case *sqlparser.UpdateStatement:
// MySQL eg: UPDATE visits SET xxx
// Clickhouse eg: ALTER TABLE visits UPDATE xxx
newSql, err = d.doFilterUpdate(stmt)
if err != nil {
return originSql, args, err
}
ck := []string{"ALTER", "TABLE"}
switch strings.ToUpper(result[0]) {
case "UPDATE":
sqlSlice = append(append(append(ck, sqlSlice[1]), result[0]), sqlSlice[3:]...)
return strings.Join(sqlSlice, " "), args, nil
case "DELETE":
sqlSlice = append(append(append(ck, sqlSlice[2]), result[0]), sqlSlice[3:]...)
return strings.Join(sqlSlice, " "), args, nil
return newSql, args, nil
case *sqlparser.DeleteStatement:
// MySQL eg: DELETE FROM VISIT
// Clickhouse eg: ALTER TABLE VISIT DELETE WHERE filter_expr
newSql, err = d.doFilterDelete(stmt)
if err != nil {
return originSql, args, err
}
return newSql, args, nil
}
return originSql, args, nil
}
func (d *Driver) doFilterDelete(stmt *sqlparser.DeleteStatement) (string, error) {
if stmt.Condition == nil {
return "", errNotCondition
}
var (
condition = stmt.Condition.String()
tableName = stmt.TableName
)
newSql := fmt.Sprintf("ALTER TABLE %s DELETE WHERE %s", tableName, condition)
return newSql, nil
}
func (d *Driver) doFilterUpdate(stmt *sqlparser.UpdateStatement) (string, error) {
if stmt.Condition == nil {
return "", errNotCondition
}
if len(stmt.Assignments) == 0 {
return "", errNotAssignment
}
var (
condition = stmt.Condition.String()
assignment string
tableName = stmt.TableName
assignments = []string{}
)
for _, item := range stmt.Assignments {
assignments = append(assignments, item.String())
}
assignment = strings.Join(assignments, ",")
newSql := fmt.Sprintf("ALTER TABLE %s UPDATE %s WHERE %s", tableName, assignment, condition)
return newSql, nil
}
// DoCommit commits current sql and arguments to underlying sql driver.
func (d *Driver) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) {
ctx = d.InjectIgnoreResult(ctx)
@ -290,6 +337,29 @@ func (d *Driver) DoInsert(
return stdSqlResult, tx.Commit()
}
// ConvertDataForRecord converting for any data that will be inserted into table/collection as a record.
func (d *Driver) ConvertDataForRecord(ctx context.Context, value interface{}) map[string]interface{} {
// Clickhouse does not need to preprocess the value and can be inserted directly
// So it is not processed here
return gconv.Map(value, gdb.OrmTagForStruct)
}
func (d *Driver) ConvertDataForRecordValue(ctx context.Context, value interface{}) interface{} {
// Clickhouse does not need to preprocess the value and can be inserted directly
// So it is not processed here
return value
}
func (d *Driver) DoDelete(ctx context.Context, link gdb.Link, table string, condition string, args ...interface{}) (result sql.Result, err error) {
ctx = d.InjectNeedParsedSql(ctx)
return d.Core.DoDelete(ctx, link, table, condition, args...)
}
func (d *Driver) DoUpdate(ctx context.Context, link gdb.Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) {
ctx = d.InjectNeedParsedSql(ctx)
return d.Core.DoUpdate(ctx, link, table, data, condition, args...)
}
// InsertIgnore Other queries for modifying data parts are not supported: REPLACE, MERGE, UPSERT, INSERT UPDATE.
func (d *Driver) InsertIgnore(ctx context.Context, table string, data interface{}, batch ...int) (sql.Result, error) {
return nil, errUnsupportedInsertIgnore

View File

@ -3,6 +3,7 @@ package clickhouse
import (
"context"
"fmt"
"github.com/google/uuid"
"testing"
"time"
@ -13,160 +14,257 @@ import (
"github.com/gogf/gf/v2/util/grand"
)
// table DDL
// CREATE TABLE visits
// (
// id UInt64,
// duration Float64,
// url String,
// created DateTime
//)
// ENGINE = MergeTree()
// PRIMARY KEY id
// ORDER BY id
func InitClickhouse() gdb.DB {
const (
sqlVisitsDDL = `
CREATE TABLE IF NOT EXISTS visits (
id UInt64,
duration Float64,
url String,
created DateTime
) ENGINE = MergeTree()
PRIMARY KEY id
ORDER BY id
`
dimSqlDDL = `
CREATE TABLE IF NOT EXISTS dim (
"code" String COMMENT '编码',
"translation" String COMMENT '译文',
"superior" UInt64 COMMENT '上级ID',
"row_number" UInt16 COMMENT '行号',
"is_active" UInt8 COMMENT '是否激活',
"is_preset" UInt8 COMMENT '是否预置',
"category" String COMMENT '类别',
"tree_path" Array(String) COMMENT '树路径',
"id" UInt64 COMMENT '代理主键ID',
"scd" UInt64 COMMENT '缓慢变化维ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位',
"created_by" UInt64 COMMENT '创建者ID',
"created_at" DateTime64(3,'Asia/Shanghai') COMMENT '创建时间',
"updated_by" UInt64 COMMENT '最后修改者ID',
"updated_at" DateTime64(3,'Asia/Shanghai') COMMENT '最后修改时间',
"updated_tick" UInt16 COMMENT '累计修改次数'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("id","scd")
COMMENT '会计准则';
`
dimSqlDML = `
insert into dim (code, translation, superior, row_number, is_active, is_preset, category, tree_path, id, scd, version, sign, created_by, created_at, updated_by, updated_at, updated_tick)
values ('CN', '{"zh_CN":"中国大陆会计准则","en_US":"Chinese mainland accounting legislation"}', 0, 1, 1, 1, 1, '[''CN'']', 607972403489804288, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0),
('HK', '{"zh_CN":"中国香港会计准则","en_US":"Chinese Hong Kong accounting legislation"}', 0, 2, 1, 1, 1, '[''HK'']', 607972558544834566, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0);
`
factSqlDDL = `
CREATE TABLE IF NOT EXISTS fact (
"adjustment_level" UInt64 COMMENT '调整层ID',
"data_version" UInt64 COMMENT '数据版本ID',
"accounting_legislation" UInt64 COMMENT '会计准则ID',
"fiscal_year" UInt16 COMMENT '会计年度',
"fiscal_period" UInt8 COMMENT '会计期间',
"fiscal_year_period" UInt32 COMMENT '会计年度期间',
"legal_entity" UInt64 COMMENT '法人主体ID',
"cost_center" UInt64 COMMENT '成本中心ID',
"legal_entity_partner" UInt64 COMMENT '内部关联方ID',
"financial_posting" UInt64 COMMENT '凭证头ID',
"line" UInt16 COMMENT '行号',
"general_ledger_account" UInt64 COMMENT '总账科目ID',
"debit" Decimal64(9) COMMENT '借方金额',
"credit" Decimal64(9) COMMENT '贷方金额',
"transaction_currency" UInt64 COMMENT '交易币种ID',
"debit_tc" Decimal64(9) COMMENT '借方金额(交易币种)',
"credit_tc" Decimal64(9) COMMENT '贷方金额(交易币种)',
"posting_date" Date32 COMMENT '过账日期',
"gc_year" UInt16 COMMENT '公历年',
"gc_quarter" UInt8 COMMENT '公历季',
"gc_month" UInt8 COMMENT '公历月',
"gc_week" UInt8 COMMENT '公历周',
"raw_info" String COMMENT '源信息',
"summary" String COMMENT '摘要',
"id" UInt64 COMMENT '代理主键ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period","financial_posting","line")
PARTITION BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period")
COMMENT '数据主表';
`
factSqlDML = `
insert into fact (adjustment_level, data_version, accounting_legislation, fiscal_year, fiscal_period, fiscal_year_period, legal_entity, cost_center, legal_entity_partner, financial_posting, line, general_ledger_account, debit, credit, transaction_currency, debit_tc, credit_tc, posting_date, gc_year, gc_quarter, gc_month, gc_week, raw_info, summary, id, version, sign)
values (607970943242866688, 607973669943119880, 607972403489804288, 2022, 3, 202203, 607974511316307985, 0, 607976190010986520, 607996702456025136, 1, 607985607569838111, 8674.39, 0, 607974898261823505, 8674.39, 0, '2022-03-05', 2022, 1, 3, 11, '{}', '摘要', 607992882741121073, 0, 0),
(607970943242866688, 607973669943119880, 607972403489804288, 2022, 4, 202204, 607974511316307985, 0, 607976190010986520, 607993586419503145, 1, 607985607569838111, 9999.88, 0, 607974898261823505, 9999.88, 0, '2022-04-10', 2022, 2, 4, 18, '{}', '摘要', 607996939140599857, 0, 0);
`
expmSqlDDL = `
CREATE TABLE IF NOT EXISTS data_type (
Col1 UInt8
, Col2 String
, Col3 FixedString(3)
, Col4 UUID
, Col5 Map(String, UInt8)
, Col6 Array(String)
, Col7 Tuple(String, UInt8, Array(Map(String, String)))
, Col8 DateTime
) ENGINE = MergeTree()
PRIMARY KEY Col4
ORDER BY Col4
`
)
func clickhouseConfigDB() gdb.DB {
connect, err := gdb.New(gdb.ConfigNode{
Host: "127.0.0.1",
Port: "9000",
User: "default",
Name: "default",
Type: "clickhouse",
Debug: true,
Host: "127.0.0.1",
Port: "9000",
User: "default",
Name: "default",
Type: "clickhouse",
})
gtest.AssertNil(err)
gtest.AssertNE(connect, nil)
return connect
}
func TestDriverClickhouse_Create(t *testing.T) {
gtest.AssertNil(createClickhouseTable(InitClickhouse()))
}
func createClickhouseTable(connect gdb.DB) error {
sqlStr := "CREATE TABLE IF NOT EXISTS visits (id UInt64,duration Float64,url String,created DateTime) ENGINE = MergeTree() PRIMARY KEY id ORDER BY id"
_, err := connect.Exec(context.Background(), sqlStr)
func createClickhouseTableVisits(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), sqlVisitsDDL)
return err
}
func dropClickhouseTable(conn gdb.DB) {
func createClickhouseTableDim(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), dimSqlDDL)
return err
}
func createClickhouseTableFact(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), factSqlDDL)
return err
}
func createClickhouseExampleTable(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), expmSqlDDL)
return err
}
func dropClickhouseTableVisits(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `visits`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseTableDim(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `dim`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseTableFact(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `fact`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseExampleTable(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `data_type`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func TestDriverClickhouse_Create(t *testing.T) {
gtest.AssertNil(createClickhouseTableVisits(clickhouseConfigDB()))
}
func TestDriverClickhouse_New(t *testing.T) {
connect := InitClickhouse()
connect := clickhouseConfigDB()
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
gtest.AssertNil(connect.PingSlave())
}
func TestDriverClickhouse_OpenLink_Ping(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
}
func TestDriverClickhouse_Tables(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
tables, err := connect.Tables(context.Background())
gtest.AssertNil(err)
gtest.AssertNE(len(tables), 0)
}
func TestDriverClickhouse_TableFields_Use_Config(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
field, err := connect.TableFields(context.Background(), "visits")
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
}
func TestDriverClickhouse_TableFields_Use_Link(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
field, err := connect.TableFields(context.Background(), "visits")
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
}
func TestDriverClickhouse_Transaction(t *testing.T) {
connect := InitClickhouse()
defer dropClickhouseTable(connect)
connect := clickhouseConfigDB()
defer dropClickhouseTableVisits(connect)
gtest.AssertNE(connect.Transaction(context.Background(), func(ctx context.Context, tx *gdb.TX) error {
return nil
}), nil)
}
func TestDriverClickhouse_DoDelete(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
_, err := connect.Model("visits").Where("created >", "2021-01-01 00:00:00").Delete()
gtest.AssertNil(err)
}
func TestDriverClickhouse_DoUpdate(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
_, err := connect.Model("visits").Where("created > ", "2021-01-01 15:15:15").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNil(err)
_, err = connect.Model("visits").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNE(err, nil)
_, err = connect.Model("visits").Update()
gtest.AssertNE(err, nil)
}
func TestDriverClickhouse_Select(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
data, err := connect.Model("visits").All()
gtest.AssertNil(err)
gtest.AssertEQ(len(data), 0)
}
func TestDriver_InsertIgnore(t *testing.T) {
connect := InitClickhouse()
func TestDriverClickhouse_InsertIgnore(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.InsertIgnore(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedInsertIgnore)
}
func TestDriver_InsertAndGetId(t *testing.T) {
connect := InitClickhouse()
func TestDriverClickhouse_InsertAndGetId(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.InsertAndGetId(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedInsertGetId)
}
func TestDriver_Replace(t *testing.T) {
connect := InitClickhouse()
_, err := connect.Replace(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedReplace)
}
func TestDriverClickhouse_DoInsertOne(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
func TestDriverClickhouse_InsertOne(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Data(g.Map{
"id": grand.Intn(999),
"duration": float64(grand.Intn(999)),
"url": gconv.String(grand.Intn(999)),
"created": time.Now().Format("2006-01-02 15:04:05"),
"created": time.Now(),
}).Insert()
gtest.AssertNil(err)
}
func TestDriver_DoInsertMany(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
func TestDriverClickhouse_InsertMany(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
tx, err := connect.Begin(context.Background())
gtest.AssertEQ(err, errUnsupportedBegin)
gtest.AssertNil(tx)
}
func TestDriverClickhouse_DoInsert(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
func TestDriverClickhouse_Insert(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
type insertItem struct {
Id int `orm:"id"`
Duration float64 `orm:"duration"`
Url string `orm:"url"`
Created string `orm:"created"`
Id uint64 `orm:"id"`
Duration float64 `orm:"duration"`
Url string `orm:"url"`
Created time.Time `orm:"created"`
}
var (
insertUrl = "https://goframe.org"
total = 0
item = insertItem{
Id: 0,
Duration: 1,
Url: insertUrl,
Created: time.Now().Format("2006-01-02 15:04:05"),
Created: time.Now(),
}
)
_, err := connect.Model("visits").Data(item).Insert()
@ -176,13 +274,12 @@ func TestDriverClickhouse_DoInsert(t *testing.T) {
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 2)
list := []*insertItem{}
var list []*insertItem
for i := 0; i < 50; i++ {
list = append(list, &insertItem{
Id: grand.Intn(999),
Duration: float64(grand.Intn(999)),
Url: insertUrl,
Created: time.Now().Format("2006-01-02 15:04:05"),
Created: time.Now(),
})
}
_, err = connect.Model("visits").Data(list).Insert()
@ -192,63 +289,150 @@ func TestDriverClickhouse_DoInsert(t *testing.T) {
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 102)
dropClickhouseTable(connect)
}
func TestDriverClickhouse_DoExec(t *testing.T) {
connect := InitClickhouse()
gtest.AssertNil(createClickhouseTable(connect))
defer dropClickhouseTable(connect)
func TestDriverClickhouse_Insert_Use_Exec(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableFact(connect), nil)
defer dropClickhouseTableFact(connect)
_, err := connect.Exec(context.Background(), factSqlDML)
gtest.AssertNil(err)
}
func TestDriverClickhouse_Delete(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Where("created >", "2021-01-01 00:00:00").Delete()
gtest.AssertNil(err)
}
func TestDriverClickhouse_Update(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Where("created > ", "2021-01-01 15:15:15").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNil(err)
}
func TestDriverClickhouse_Replace(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.Replace(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedReplace)
}
func TestDriverClickhouse_DoFilter(t *testing.T) {
rawSQL := "select * from visits where 1 = 1"
this := Driver{}
replaceSQL, _, err := this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(rawSQL, replaceSQL)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
rawSQL = "update visit set url = '1'"
replaceSQL, _, err = this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
rawSQL = "delete from visit"
replaceSQL, _, err = this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
core := gdb.Core{}
ctx := core.InjectNeedParsedSql(context.Background())
rawSQL = "update visit set url = '1' where url = '0'"
replaceSQL, _, err = this.DoFilter(ctx, nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit UPDATE url = '1' WHERE url = '0'")
rawSQL = "delete from visit where url='0'"
replaceSQL, _, err = this.DoFilter(ctx, nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit DELETE WHERE url = '0'")
}
func TestDriverClickhouse_Select(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Data(g.Map{
"url": "goframe.org",
"duration": float64(1),
}).Insert()
gtest.AssertNil(err)
temp, err := connect.Model("visits").Where("url", "goframe.org").Where("duration >= ", 1).One()
gtest.AssertNil(err)
gtest.AssertEQ(temp.IsEmpty(), false)
_, err = connect.Model("visits").Data(g.Map{
"url": "goframe.org",
"duration": float64(2),
}).Insert()
gtest.AssertNil(err)
data, err := connect.Model("visits").Where("url", "goframe.org").Where("duration >= ", 1).All()
gtest.AssertNil(err)
gtest.AssertEQ(len(data), 2)
}
func TestDriverClickhouse_Exec_OPTIMIZE(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
sqlStr := "OPTIMIZE table visits"
_, err := connect.Exec(context.Background(), sqlStr)
gtest.AssertNil(err)
}
func TestDriver_DoFilter(t *testing.T) {
rawSQL := "select * from visits where 1 = 1"
this := Driver{}
replaceSQL, _, err := this.DoFilter(nil, nil, rawSQL, nil)
func TestDriverClickhouse_ExecInsert(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableDim(connect), nil)
defer dropClickhouseTableDim(connect)
_, err := connect.Exec(context.Background(), dimSqlDML)
gtest.AssertNil(err)
gtest.AssertEQ(rawSQL, replaceSQL)
rawSQL = "update visit set url = '1'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit update url = '1'")
rawSQL = "delete from visit"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit delete")
rawSQL = "update visit set url = '1' where url = '0'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit update url = '1' where url = '0'")
rawSQL = "delete from visit where url='0'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit delete where url='0'")
}
func TestDriver_TableFields(t *testing.T) {
connect := InitClickhouse()
gtest.AssertNil(createClickhouseTable(connect))
defer dropClickhouseTable(connect)
field, err := connect.TableFields(context.Background(), "visits")
func TestDriverClickhouse_BatchInsert(t *testing.T) {
// example from
// https://github.com/ClickHouse/clickhouse-go/blob/v2/examples/std/batch/main.go
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseExampleTable(connect))
defer dropClickhouseExampleTable(connect)
insertData := []g.Map{}
for i := 0; i < 10000; i++ {
insertData = append(insertData, g.Map{
"Col1": uint8(42),
"Col2": "ClickHouse",
"Col3": "Inc",
"Col4": uuid.New(),
"Col5": map[string]uint8{"key": 1}, // Map(String, UInt8)
"Col6": []string{"Q", "W", "E", "R", "T", "Y"}, // Array(String)
"Col7": []interface{}{ // Tuple(String, UInt8, Array(Map(String, String)))
"String Value", uint8(5), []map[string]string{
map[string]string{"key": "value"},
map[string]string{"key": "value"},
map[string]string{"key": "value"},
},
},
"Col8": time.Now(),
})
}
_, err := connect.Model("data_type").Data(insertData).Insert()
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
count, err := connect.Model("data_type").Where("Col2", "ClickHouse").Where("Col3", "Inc").Count()
gtest.AssertNil(err)
gtest.AssertEQ(count, 10000)
}
func TestDriver_OpenLink(t *testing.T) {
connect, err := gdb.New(gdb.ConfigNode{
Link: "clickhouse://default@127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60&skip_verify=true&secure=false&compress=true",
func TestDriverClickhouse_Open(t *testing.T) {
// link
// DSM
// clickhouse://username:password@host1:9000,host2:9000/database?dial_timeout=200ms&max_execution_time=60
link := "clickhouse://default@127.0.0.1:9000,127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60"
db, err := gdb.New(gdb.ConfigNode{
Link: link,
Type: "clickhouse",
})
gtest.AssertNil(err)
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
gtest.AssertNil(db.PingMaster())
}

View File

@ -3,8 +3,10 @@ module github.com/gogf/gf/contrib/drivers/clickhouse/v2
go 1.15
require (
github.com/ClickHouse/clickhouse-go v1.5.2
github.com/ClickHouse/clickhouse-go/v2 v2.0.12
github.com/gogf/gf/v2 v2.0.0
github.com/google/uuid v1.3.0
github.com/longbridgeapp/sqlparser v0.3.1
)
replace github.com/gogf/gf/v2 => ../../../

View File

@ -1,14 +1,15 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/ClickHouse/clickhouse-go v1.5.2 h1:yXgaOZ8WEHrd+okvZXjzulSt1zS33nM4ujfx9lVncl8=
github.com/ClickHouse/clickhouse-go v1.5.2/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
github.com/ClickHouse/clickhouse-go v1.5.3 h1:Vok8zUb/wlqc9u8oEqQzBMBRDoFd8NxPRqgYEqMnV88=
github.com/ClickHouse/clickhouse-go v1.5.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/ClickHouse/clickhouse-go/v2 v2.0.12 h1:Nbl/NZwoM6LGJm7smNBgvtdr/rxjlIssSW3eG/Nmb9E=
github.com/ClickHouse/clickhouse-go/v2 v2.0.12/go.mod h1:u4RoNQLLM2W6hNSPYrIESLJqaWSInZVmfM+MlaAhXcg=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -21,6 +22,11 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@ -29,6 +35,7 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -43,14 +50,21 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/longbridgeapp/sqlparser v0.3.1 h1:iWOZWGIFgQrJRgobLXUNJdvqGRpbVXkyKUKUA5CNJBE=
github.com/longbridgeapp/sqlparser v0.3.1/go.mod h1:GIHaUq8zvYyHLCLMJJykx1CdM6LHtkUih/QaJXySSx4=
@ -62,6 +76,7 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -75,31 +90,46 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/paulmach/orb v0.4.0 h1:ilp1MQjRapLJ1+qcays1nZpe0mvkCY+b8JU/qBKRZ1A=
github.com/paulmach/orb v0.4.0/go.mod h1:FkcWtplUAIVqAuhAOV2d3rpbnQyliDOjOcLW9dUrfdU=
github.com/paulmach/protoscan v0.2.1-0.20210522164731-4e53c6875432/go.mod h1:2sV+uZ/oQh66m4XJVZm5iqUZ62BN88Ex1E+TTS0nLzI=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
go.opentelemetry.io/otel v1.4.1 h1:QbINgGDDcoQUoMJa2mMaWno49lja9sHwp6aoa2n3a4g=
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
go.opentelemetry.io/otel/sdk v1.0.0 h1:BNPMYUONPNbLneMttKSjQhOTlFLOD9U22HNG1KrIN2Y=
go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
go.opentelemetry.io/otel/trace v1.4.1 h1:O+16qcdTrT7zxv2J6GejTPFinSwA++cYerC5iSiF8EQ=
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
@ -108,6 +138,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -116,6 +147,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -125,8 +157,9 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 h1:WecRHqgE09JBkh/584XIE6PMz5KKE/vER4izNUi30AQ=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -135,7 +168,9 @@ golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObF
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -32,6 +32,8 @@ const (
// but returns errors when execute `RowsAffected`. It here ignores the calling of `RowsAffected`
// to avoid triggering errors, rather than ignoring errors after they are triggered.
ignoreResultKeyInCtx gctx.StrKey = "IgnoreResult"
needParsedSqlInCtx gctx.StrKey = "NeedParsedSql"
)
func (c *Core) InjectInternalCtxData(ctx context.Context) context.Context {
@ -64,3 +66,17 @@ func (c *Core) GetIgnoreResultFromCtx(ctx context.Context) bool {
}
return false
}
func (c *Core) InjectNeedParsedSql(ctx context.Context) context.Context {
if ctx.Value(needParsedSqlInCtx) != nil {
return ctx
}
return context.WithValue(ctx, needParsedSqlInCtx, true)
}
func (c *Core) GetNeedParsedSqlFromCtx(ctx context.Context) bool {
if ctx.Value(needParsedSqlInCtx) != nil {
return true
}
return false
}