Merge 57c10046c0f5b4966db36a699d7283a12d0e00d1 into 8d457146283e0a4197c26a559bedb1938767b78e
This commit is contained in:
commit
2c1a3c9078
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tmFmtWithMS = "2006-01-02 15:04:05.999"
|
tmFmtWithMS = "2006-01-02 15:04:05.999 Z0700"
|
||||||
tmFmtZero = "0000-00-00 00:00:00"
|
tmFmtZero = "0000-00-00 00:00:00"
|
||||||
nullStr = "NULL"
|
nullStr = "NULL"
|
||||||
)
|
)
|
||||||
@ -30,7 +30,7 @@ func isPrintable(s string) bool {
|
|||||||
|
|
||||||
var convertibleTypes = []reflect.Type{reflect.TypeOf(time.Time{}), reflect.TypeOf(false), reflect.TypeOf([]byte{})}
|
var convertibleTypes = []reflect.Type{reflect.TypeOf(time.Time{}), reflect.TypeOf(false), reflect.TypeOf([]byte{})}
|
||||||
|
|
||||||
// ExplainSQL generate SQL string with given parameters, the generated SQL is expected to be used in logger, execute it might introduce a SQL injection vulnerability
|
// ExplainSQL generate SQL strings with given parameters, the generated SQL is expected to be used in logger, execute it might introduce a SQL injection vulnerability
|
||||||
func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, avars ...interface{}) string {
|
func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, avars ...interface{}) string {
|
||||||
var (
|
var (
|
||||||
convertParams func(interface{}, int)
|
convertParams func(interface{}, int)
|
||||||
@ -42,21 +42,9 @@ func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, a
|
|||||||
case bool:
|
case bool:
|
||||||
vars[idx] = strconv.FormatBool(v)
|
vars[idx] = strconv.FormatBool(v)
|
||||||
case time.Time:
|
case time.Time:
|
||||||
if v.IsZero() {
|
vars[idx] = formatTime(&v, escaper)
|
||||||
vars[idx] = escaper + tmFmtZero + escaper
|
|
||||||
} else {
|
|
||||||
vars[idx] = escaper + v.Format(tmFmtWithMS) + escaper
|
|
||||||
}
|
|
||||||
case *time.Time:
|
case *time.Time:
|
||||||
if v != nil {
|
vars[idx] = formatTime(v, escaper)
|
||||||
if v.IsZero() {
|
|
||||||
vars[idx] = escaper + tmFmtZero + escaper
|
|
||||||
} else {
|
|
||||||
vars[idx] = escaper + v.Format(tmFmtWithMS) + escaper
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vars[idx] = nullStr
|
|
||||||
}
|
|
||||||
case driver.Valuer:
|
case driver.Valuer:
|
||||||
reflectValue := reflect.ValueOf(v)
|
reflectValue := reflect.ValueOf(v)
|
||||||
if v != nil && reflectValue.IsValid() && ((reflectValue.Kind() == reflect.Ptr && !reflectValue.IsNil()) || reflectValue.Kind() != reflect.Ptr) {
|
if v != nil && reflectValue.IsValid() && ((reflectValue.Kind() == reflect.Ptr && !reflectValue.IsNil()) || reflectValue.Kind() != reflect.Ptr) {
|
||||||
@ -145,3 +133,14 @@ func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, a
|
|||||||
|
|
||||||
return sql
|
return sql
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatTime(v *time.Time, escaper string) string {
|
||||||
|
if v == nil {
|
||||||
|
return nullStr
|
||||||
|
}
|
||||||
|
if v.IsZero() {
|
||||||
|
return escaper + tmFmtZero + escaper
|
||||||
|
} else {
|
||||||
|
return escaper + v.Format(tmFmtWithMS) + escaper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/jinzhu/now"
|
"github.com/jinzhu/now"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
@ -38,7 +39,9 @@ func TestExplainSQL(t *testing.T) {
|
|||||||
type role string
|
type role string
|
||||||
type password []byte
|
type password []byte
|
||||||
var (
|
var (
|
||||||
tt = now.MustParse("2020-02-23 11:10:10")
|
tt = now.MustParseInLocation(time.UTC, "2020-02-23 11:10:10")
|
||||||
|
pst, _ = time.LoadLocation("America/Los_Angeles")
|
||||||
|
est, _ = time.LoadLocation("America/New_York")
|
||||||
myrole = role("admin")
|
myrole = role("admin")
|
||||||
pwd = password([]byte("pass"))
|
pwd = password([]byte("pass"))
|
||||||
jsVal = []byte(`{"Name":"test","Val":"test"}`)
|
jsVal = []byte(`{"Name":"test","Val":"test"}`)
|
||||||
@ -57,43 +60,55 @@ func TestExplainSQL(t *testing.T) {
|
|||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
NumericRegexp: nil,
|
NumericRegexp: nil,
|
||||||
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd},
|
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd},
|
||||||
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.\"com", "admin", "pass")`,
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
NumericRegexp: nil,
|
NumericRegexp: nil,
|
||||||
Vars: []interface{}{"jinzhu?", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd},
|
Vars: []interface{}{"jinzhu?", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd},
|
||||||
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu?", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.\"com", "admin", "pass")`,
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu?", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)",
|
||||||
NumericRegexp: regexp.MustCompile(`@p(\d+)`),
|
NumericRegexp: regexp.MustCompile(`@p(\d+)`),
|
||||||
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.com", myrole, pwd},
|
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.com", myrole, pwd},
|
||||||
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.com", "admin", "pass")`,
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ($3, $4, $1, $2, $7, $8, $5, $6, $9, $10, $11)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ($3, $4, $1, $2, $7, $8, $5, $6, $9, $10, $11)",
|
||||||
NumericRegexp: regexp.MustCompile(`\$(\d+)`),
|
NumericRegexp: regexp.MustCompile(`\$(\d+)`),
|
||||||
Vars: []interface{}{999.99, true, "jinzhu", 1, &tt, nil, []byte("12345"), tt, "w@g.com", myrole, pwd},
|
Vars: []interface{}{999.99, true, "jinzhu", 1, &tt, nil, []byte("12345"), tt, "w@g.com", myrole, pwd},
|
||||||
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.com", "admin", "pass")`,
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (@p1, @p11, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (@p1, @p11, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10)",
|
||||||
NumericRegexp: regexp.MustCompile(`@p(\d+)`),
|
NumericRegexp: regexp.MustCompile(`@p(\d+)`),
|
||||||
Vars: []interface{}{"jinzhu", 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.com", myrole, pwd, 1},
|
Vars: []interface{}{"jinzhu", 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.com", myrole, pwd, 1},
|
||||||
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.com", "admin", "pass")`,
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
NumericRegexp: nil,
|
NumericRegexp: nil,
|
||||||
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd, js, es},
|
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd, js, es},
|
||||||
Result: fmt.Sprintf(`create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.\"com", "admin", "pass", %v, %v)`, format(jsVal, `"`), format(esVal, `"`)),
|
Result: fmt.Sprintf(`create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass", %v, %v)`, format(jsVal, `"`), format(esVal, `"`)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
NumericRegexp: nil,
|
NumericRegexp: nil,
|
||||||
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd, &js, &es},
|
Vars: []interface{}{"jinzhu", 1, 999.99, true, []byte("12345"), tt, &tt, nil, "w@g.\"com", myrole, pwd, &js, &es},
|
||||||
Result: fmt.Sprintf(`create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10", "2020-02-23 11:10:10", NULL, "w@g.\"com", "admin", "pass", %v, %v)`, format(jsVal, `"`), format(esVal, `"`)),
|
Result: fmt.Sprintf(`create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass, json_struct, example_struct) values ("jinzhu", 1, 999.990000, true, "12345", "2020-02-23 11:10:10 Z", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass", %v, %v)`, format(jsVal, `"`), format(esVal, `"`)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
NumericRegexp: nil,
|
||||||
|
Vars: []interface{}{"jinzhu?", 1, 999.99, true, []byte("12345"), tt.In(pst), &tt, nil, "w@g.\"com", myrole, pwd},
|
||||||
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu?", 1, 999.990000, true, "12345", "2020-02-23 03:10:10 -0800", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass")`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQL: "create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
NumericRegexp: nil,
|
||||||
|
Vars: []interface{}{"jinzhu?", 1, 999.99, true, []byte("12345"), tt.In(est), &tt, nil, "w@g.\"com", myrole, pwd},
|
||||||
|
Result: `create table users (name, age, height, actived, bytes, create_at, update_at, deleted_at, email, role, pass) values ("jinzhu?", 1, 999.990000, true, "12345", "2020-02-23 06:10:10 -0500", "2020-02-23 11:10:10 Z", NULL, "w@g.\"com", "admin", "pass")`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ func TestToSQL(t *testing.T) {
|
|||||||
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
||||||
return tx.Model(&User{}).Create(user)
|
return tx.Model(&User{}).Create(user)
|
||||||
})
|
})
|
||||||
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
|
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00 Z','2021-10-18 00:00:00 Z',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
|
||||||
|
|
||||||
// save
|
// save
|
||||||
user = &User{Name: "foo", Age: 20}
|
user = &User{Name: "foo", Age: 20}
|
||||||
@ -412,7 +412,7 @@ func TestToSQL(t *testing.T) {
|
|||||||
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
||||||
return tx.Model(&User{}).Save(user)
|
return tx.Model(&User{}).Save(user)
|
||||||
})
|
})
|
||||||
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
|
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00 Z','2021-10-18 00:00:00 Z',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
|
||||||
|
|
||||||
// updates
|
// updates
|
||||||
user = &User{Name: "bar", Age: 22}
|
user = &User{Name: "bar", Age: 22}
|
||||||
@ -421,13 +421,13 @@ func TestToSQL(t *testing.T) {
|
|||||||
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
||||||
return tx.Model(&User{}).Where("id = ?", 100).Updates(user)
|
return tx.Model(&User{}).Where("id = ?", 100).Updates(user)
|
||||||
})
|
})
|
||||||
assertEqualSQL(t, `UPDATE "users" SET "created_at"='2021-10-18 00:00:00',"updated_at"='2021-10-18 19:50:09.438',"name"='bar',"age"=22 WHERE id = 100 AND "users"."deleted_at" IS NULL`, sql)
|
assertEqualSQL(t, `UPDATE "users" SET "created_at"='2021-10-18 00:00:00 Z',"updated_at"='2021-10-18 19:50:09.438 Z',"name"='bar',"age"=22 WHERE id = 100 AND "users"."deleted_at" IS NULL`, sql)
|
||||||
|
|
||||||
// update
|
// update
|
||||||
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
||||||
return tx.Model(&User{}).Where("id = ?", 100).Update("name", "Foo bar")
|
return tx.Model(&User{}).Where("id = ?", 100).Update("name", "Foo bar")
|
||||||
})
|
})
|
||||||
assertEqualSQL(t, `UPDATE "users" SET "name"='Foo bar',"updated_at"='2021-10-18 19:50:09.438' WHERE id = 100 AND "users"."deleted_at" IS NULL`, sql)
|
assertEqualSQL(t, `UPDATE "users" SET "name"='Foo bar',"updated_at"='2021-10-18 19:50:09.438 Z' WHERE id = 100 AND "users"."deleted_at" IS NULL`, sql)
|
||||||
|
|
||||||
// UpdateColumn
|
// UpdateColumn
|
||||||
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user