From 50b04c658ce8f7bb29a11987baaa873b3c11cf74 Mon Sep 17 00:00:00 2001 From: zhonghuaxunGM <50815786+zhonghuaxunGM@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:52:36 +0800 Subject: [PATCH] improve implements and fix issues for package `contrib/drivers/dm` (#3128) --- contrib/drivers/dm/dm.go | 81 ++++++++++++++++++++++++++++++--------- contrib/drivers/dm/go.mod | 2 +- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/contrib/drivers/dm/dm.go b/contrib/drivers/dm/dm.go index a30b2087b2b..076c70d77b5 100644 --- a/contrib/drivers/dm/dm.go +++ b/contrib/drivers/dm/dm.go @@ -12,8 +12,6 @@ import ( "database/sql" "fmt" "net/url" - "reflect" - "strconv" "strings" "time" @@ -77,8 +75,8 @@ func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) { // Data Source Name of DM8: // dm://userName:password@ip:port/dbname source = fmt.Sprintf( - "dm://%s:%s@%s:%s/%s?charset=%s", - config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset, + "dm://%s:%s@%s:%s/%s?charset=%s&schema=%s", + config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset, config.Name, ) // Demo of timezone setting: // &loc=Asia/Shanghai @@ -147,8 +145,9 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string result, err = d.DoSelect( ctx, link, fmt.Sprintf( - `SELECT * FROM ALL_TAB_COLUMNS WHERE Table_Name= '%s'`, + `SELECT * FROM ALL_TAB_COLUMNS WHERE Table_Name= '%s' AND OWNER = '%s'`, strings.ToUpper(table), + strings.ToUpper(d.GetSchema()), ), ) if err != nil { @@ -206,14 +205,53 @@ func (d *Driver) ConvertValueForField(ctx context.Context, fieldType string, fie func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { // There should be no need to capitalize, because it has been done from field processing before newSql, _ = gregex.ReplaceString(`["\n\t]`, "", sql) + newSql = gstr.ReplaceI(gstr.ReplaceI(newSql, "GROUP_CONCAT", "LISTAGG"), "SEPARATOR", ",") + + // TODO The current approach is too rough. We should deal with the GROUP_CONCAT function and the parsing of the index field from within the select from match. + // (GROUP_CONCAT DM does not approve; index cannot be used as a query column name, and security characters need to be added, such as "index") + l, r := d.GetChars() + newSql = gstr.ReplaceI(newSql, "INDEX", l+"INDEX"+r) + + // TODO i tried to do but it never work: + // array, err := gregex.MatchAllString(`SELECT (.*INDEX.*) FROM .*`, newSql) + // g.Dump("err:", err) + // g.Dump("array:", array) + // g.Dump("array:", array[0][1]) + + // newSql, err = gregex.ReplaceString(`SELECT (.*INDEX.*) FROM .*`, l+"INDEX"+r, newSql) + // g.Dump("err:", err) + // g.Dump("newSql:", newSql) + + // re, err := regexp.Compile(`.*SELECT (.*INDEX.*) FROM .*`) + // newSql = re.ReplaceAllStringFunc(newSql, func(data string) string { + // fmt.Println("data:", data) + // return data + // }) + return d.Core.DoFilter( ctx, link, - gstr.ReplaceI(newSql, "GROUP_CONCAT", "WM_CONCAT"), + newSql, args, ) } +// TODO I originally wanted to only convert keywords in select +// 但是我发现 DoQuery 中会对 sql 会对 " " 达梦的安全字符 进行 / 转义,最后还是导致达梦无法正常解析 +// However, I found that DoQuery() will perform / escape on sql with " " Dameng's safe characters, which ultimately caused Dameng to be unable to parse normally. +// But processing in DoFilter() is OK +// func (d *Driver) DoQuery(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (gdb.Result, error) { +// l, r := d.GetChars() +// new := gstr.ReplaceI(sql, "INDEX", l+"INDEX"+r) +// g.Dump("new:", new) +// return d.Core.DoQuery( +// ctx, +// link, +// new, +// args, +// ) +// } + // DoInsert inserts or updates data forF given table. func (d *Driver) DoInsert( ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, @@ -342,22 +380,27 @@ func parseUnion(list gdb.List, char struct { if mapper[column] == nil { continue } - va := reflect.ValueOf(mapper[column]) - ty := reflect.TypeOf(mapper[column]) - switch ty.Kind() { - case reflect.String: - saveValue = append(saveValue, char.valueCharL+va.String()+char.valueCharR) + // va := reflect.ValueOf(mapper[column]) + // ty := reflect.TypeOf(mapper[column]) + // switch ty.Kind() { + // case reflect.String: + // saveValue = append(saveValue, char.valueCharL+va.String()+char.valueCharR) - case reflect.Int: - saveValue = append(saveValue, strconv.FormatInt(va.Int(), 10)) + // case reflect.Int: + // saveValue = append(saveValue, strconv.FormatInt(va.Int(), 10)) - case reflect.Int64: - saveValue = append(saveValue, strconv.FormatInt(va.Int(), 10)) + // case reflect.Int64: + // saveValue = append(saveValue, strconv.FormatInt(va.Int(), 10)) - default: - // The fish has no chance getting here. - // Nothing to do. - } + // default: + // // The fish has no chance getting here. + // // Nothing to do. + // } + saveValue = append(saveValue, + fmt.Sprintf( + char.valueCharL+"%s"+char.valueCharR, + gconv.String(mapper[column]), + )) } unionValues = append( unionValues, diff --git a/contrib/drivers/dm/go.mod b/contrib/drivers/dm/go.mod index aaee57d4842..510e0c6bdef 100644 --- a/contrib/drivers/dm/go.mod +++ b/contrib/drivers/dm/go.mod @@ -5,7 +5,7 @@ go 1.18 replace github.com/gogf/gf/v2 => ../../../ require ( - gitee.com/chunanyong/dm v1.8.10 + gitee.com/chunanyong/dm v1.8.12 github.com/gogf/gf/v2 v2.5.6 )