diff --git a/contrib/drivers/dm/dm_do_insert.go b/contrib/drivers/dm/dm_do_insert.go index 003a9923c..de2b216a4 100644 --- a/contrib/drivers/dm/dm_do_insert.go +++ b/contrib/drivers/dm/dm_do_insert.go @@ -17,7 +17,6 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gconv" ) // DoInsert inserts or updates data for given table. @@ -25,15 +24,16 @@ func (d *Driver) DoInsert( ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ) (result sql.Result, err error) { switch option.InsertOption { + case gdb.InsertOptionSave: + return d.doSave(ctx, link, table, list, option) + case gdb.InsertOptionReplace: // TODO:: Should be Supported return nil, gerror.NewCode( gcode.CodeNotSupported, `Replace operation is not supported by dm driver`, ) - - case gdb.InsertOptionSave: - return d.doSave(ctx, link, table, list, option) } + return d.Core.DoInsert(ctx, link, table, list, option) } @@ -54,18 +54,23 @@ func (d *Driver) doSave(ctx context.Context, } var ( - one = list[0] - charL, charR = d.GetChars() - valueCharL, valueCharR = "'", "'" + one = list[0] + oneLen = len(one) + charL, charR = d.GetChars() conflictKeys = option.OnConflict conflictKeySet = gset.New(false) - // insertKeys: Handle valid keys that need to be inserted - // insertValues: Handle values that need to be inserted - // updateValues: Handle values that need to be updated - // queryValues: Handle data that need to be upsert - queryValues, insertKeys, insertValues, updateValues []string + // queryHolders: Handle data with Holder that need to be upsert + // queryValues: Handle data that need to be upsert + // insertKeys: Handle valid keys that need to be inserted + // insertValues: Handle values that need to be inserted + // updateValues: Handle values that need to be updated + queryHolders = make([]string, oneLen) + queryValues = make([]interface{}, oneLen) + insertKeys = make([]string, oneLen) + insertValues = make([]string, oneLen) + updateValues []string ) // conflictKeys slice type conv to set type @@ -73,31 +78,28 @@ func (d *Driver) doSave(ctx context.Context, conflictKeySet.Add(gstr.ToUpper(conflictKey)) } + index := 0 for key, value := range one { - saveValue := gconv.String(value) - queryValues = append( - queryValues, - fmt.Sprintf( - valueCharL+"%s"+valueCharR+" AS "+charL+"%s"+charR, - saveValue, key, - ), - ) + keyWithChar := charL + key + charR + queryHolders[index] = fmt.Sprintf("? AS %s", keyWithChar) + queryValues[index] = value + insertKeys[index] = keyWithChar + insertValues[index] = fmt.Sprintf("T2.%s", keyWithChar) - insertKeys = append(insertKeys, charL+key+charR) - insertValues = append(insertValues, "T2."+charL+key+charR) - - // filter conflict keys in updateValues - if !conflictKeySet.Contains(key) { + // filter conflict keys in updateValues. + // And the key is not a soft created field. + if !(conflictKeySet.Contains(key) || d.Core.IsSoftCreatedFieldName(key)) { updateValues = append( updateValues, - fmt.Sprintf(`T1.%s = T2.%s`, charL+key+charR, charL+key+charR), + fmt.Sprintf(`T1.%s = T2.%s`, keyWithChar, keyWithChar), ) } + index++ } batchResult := new(gdb.SqlResult) - sqlStr := parseSqlForUpsert(table, queryValues, insertKeys, insertValues, updateValues, conflictKeys) - r, err := d.DoExec(ctx, link, sqlStr) + sqlStr := parseSqlForUpsert(table, queryHolders, insertKeys, insertValues, updateValues, conflictKeys) + r, err := d.DoExec(ctx, link, sqlStr, queryValues...) if err != nil { return r, err } @@ -112,17 +114,17 @@ func (d *Driver) doSave(ctx context.Context, // parseSqlForUpsert // MERGE INTO {{table}} T1 -// USING ( SELECT {{queryValues}} FROM DUAL T2 +// USING ( SELECT {{queryHolders}} FROM DUAL T2 // ON (T1.{{duplicateKey}} = T2.{{duplicateKey}} AND ...) // WHEN NOT MATCHED THEN // INSERT {{insertKeys}} VALUES {{insertValues}} // WHEN MATCHED THEN // UPDATE SET {{updateValues}} func parseSqlForUpsert(table string, - queryValues, insertKeys, insertValues, updateValues, duplicateKey []string, + queryHolders, insertKeys, insertValues, updateValues, duplicateKey []string, ) (sqlStr string) { var ( - queryValueStr = strings.Join(queryValues, ",") + queryHolderStr = strings.Join(queryHolders, ",") insertKeyStr = strings.Join(insertKeys, ",") insertValueStr = strings.Join(insertValues, ",") updateValueStr = strings.Join(updateValues, ",") @@ -140,7 +142,7 @@ func parseSqlForUpsert(table string, return fmt.Sprintf(pattern, table, - queryValueStr, + queryHolderStr, duplicateKeyStr, insertKeyStr, insertValueStr, diff --git a/contrib/drivers/oracle/oracle_do_insert.go b/contrib/drivers/oracle/oracle_do_insert.go index 2dd36408f..381597d35 100644 --- a/contrib/drivers/oracle/oracle_do_insert.go +++ b/contrib/drivers/oracle/oracle_do_insert.go @@ -10,9 +10,10 @@ import ( "context" "database/sql" "fmt" + "strings" + "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/text/gstr" - "strings" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" @@ -110,18 +111,23 @@ func (d *Driver) doSave(ctx context.Context, } var ( - one = list[0] - charL, charR = d.GetChars() - valueCharL, valueCharR = "'", "'" + one = list[0] + oneLen = len(one) + charL, charR = d.GetChars() conflictKeys = option.OnConflict conflictKeySet = gset.New(false) - // insertKeys: Handle valid keys that need to be inserted - // insertValues: Handle values that need to be inserted - // updateValues: Handle values that need to be updated - // queryValues: Handle data that need to be upsert - queryValues, insertKeys, insertValues, updateValues []string + // queryHolders: Handle data with Holder that need to be upsert + // queryValues: Handle data that need to be upsert + // insertKeys: Handle valid keys that need to be inserted + // insertValues: Handle values that need to be inserted + // updateValues: Handle values that need to be updated + queryHolders = make([]string, oneLen) + queryValues = make([]interface{}, oneLen) + insertKeys = make([]string, oneLen) + insertValues = make([]string, oneLen) + updateValues []string ) // conflictKeys slice type conv to set type @@ -129,31 +135,28 @@ func (d *Driver) doSave(ctx context.Context, conflictKeySet.Add(gstr.ToUpper(conflictKey)) } + index := 0 for key, value := range one { - saveValue := gconv.String(value) - queryValues = append( - queryValues, - fmt.Sprintf( - valueCharL+"%s"+valueCharR+" AS "+charL+"%s"+charR, - saveValue, key, - ), - ) + keyWithChar := charL + key + charR + queryHolders[index] = fmt.Sprintf("? AS %s", keyWithChar) + queryValues[index] = value + insertKeys[index] = keyWithChar + insertValues[index] = fmt.Sprintf("T2.%s", keyWithChar) - insertKeys = append(insertKeys, charL+key+charR) - insertValues = append(insertValues, "T2."+charL+key+charR) - - // filter conflict keys in updateValues - if !conflictKeySet.Contains(key) { + // filter conflict keys in updateValues. + // And the key is not a soft created field. + if !(conflictKeySet.Contains(key) || d.Core.IsSoftCreatedFieldName(key)) { updateValues = append( updateValues, - fmt.Sprintf(`T1.%s = T2.%s`, charL+key+charR, charL+key+charR), + fmt.Sprintf(`T1.%s = T2.%s`, keyWithChar, keyWithChar), ) } + index++ } batchResult := new(gdb.SqlResult) - sqlStr := parseSqlForUpsert(table, queryValues, insertKeys, insertValues, updateValues, conflictKeys) - r, err := d.DoExec(ctx, link, sqlStr) + sqlStr := parseSqlForUpsert(table, queryHolders, insertKeys, insertValues, updateValues, conflictKeys) + r, err := d.DoExec(ctx, link, sqlStr, queryValues...) if err != nil { return r, err } @@ -168,17 +171,17 @@ func (d *Driver) doSave(ctx context.Context, // parseSqlForUpsert // MERGE INTO {{table}} T1 -// USING ( SELECT {{queryValues}} FROM DUAL T2 +// USING ( SELECT {{queryHolders}} FROM DUAL T2 // ON (T1.{{duplicateKey}} = T2.{{duplicateKey}} AND ...) // WHEN NOT MATCHED THEN // INSERT {{insertKeys}} VALUES {{insertValues}} // WHEN MATCHED THEN // UPDATE SET {{updateValues}} func parseSqlForUpsert(table string, - queryValues, insertKeys, insertValues, updateValues, duplicateKey []string, + queryHolders, insertKeys, insertValues, updateValues, duplicateKey []string, ) (sqlStr string) { var ( - queryValueStr = strings.Join(queryValues, ",") + queryHolderStr = strings.Join(queryHolders, ",") insertKeyStr = strings.Join(insertKeys, ",") insertValueStr = strings.Join(insertValues, ",") updateValueStr = strings.Join(updateValues, ",") @@ -196,7 +199,7 @@ func parseSqlForUpsert(table string, return fmt.Sprintf(pattern, table, - queryValueStr, + queryHolderStr, duplicateKeyStr, insertKeyStr, insertValueStr, diff --git a/contrib/drivers/oracle/oracle_z_unit_init_test.go b/contrib/drivers/oracle/oracle_z_unit_init_test.go index d58b44eb0..f7e041c6a 100644 --- a/contrib/drivers/oracle/oracle_z_unit_init_test.go +++ b/contrib/drivers/oracle/oracle_z_unit_init_test.go @@ -126,7 +126,7 @@ func createTable(table ...string) (name string) { gtest.Fatal(err) } - //db.Schema("test") + // db.Schema("test") return }