diff --git a/clause/expression.go b/clause/expression.go index 3140846e..fc1da2b0 100644 --- a/clause/expression.go +++ b/clause/expression.go @@ -88,6 +88,7 @@ func (expr NamedExpr) Build(builder Builder) { inName bool afterParenthesis bool namedMap = make(map[string]interface{}, len(expr.Vars)) + quotationMarks byte ) for _, v := range expr.Vars { @@ -124,6 +125,14 @@ func (expr NamedExpr) Build(builder Builder) { name := make([]byte, 0, 10) for _, v := range []byte(expr.SQL) { + if quotationMarks == v && (v == '"' || v == '\'') { + quotationMarks = 0 + } else if quotationMarks == 0 && (v == '"' || v == '\'') { + quotationMarks = v + } else if quotationMarks == '"' || quotationMarks == '\'' { + builder.WriteByte(v) + continue + } if v == '@' && !inName { inName = true name = name[:0] diff --git a/tests/raw_test.go b/tests/raw_test.go new file mode 100644 index 00000000..abc9b7ef --- /dev/null +++ b/tests/raw_test.go @@ -0,0 +1,103 @@ +package tests_test + +import ( + . "gorm.io/gorm/utils/tests" + "testing" +) + +func TestRawSelect(t *testing.T) { + users := []User{ + *GetUser("raw1", Config{}), + *GetUser("raw2", Config{}), + *GetUser("raw3", Config{}), + *GetUser("@name", Config{}), + *GetUser("@age", Config{}), + } + + if err := DB.Create(&users).Error; err != nil { + t.Fatalf("errors happened when create users: %v", err) + } + tests := []struct { + TestName string + Sql string + args map[string]interface{} + Expect []User + }{ + { + "raw_test1", + `select * from users where name like @name and age = 18`, + map[string]interface{}{ + "name": "raw1", + }, + []User{ + users[0], + }, + }, + { + "raw_test2", + `select * from users where name like @name and age = 18`, + map[string]interface{}{ + "name": "@name", + }, + []User{ + users[3], + }, + }, + { + "raw_test3", + `select * from users where name like @name and age = 18`, + map[string]interface{}{ + "name": "@age", + }, + []User{ + users[4], + }, + }, + { + "raw_test4", + `select * from users where name like 'raw3' and age = @age`, + map[string]interface{}{ + "age": 18, + }, + []User{ + users[2], + }, + }, + { + "raw_test5", + `select * from users where name like '@name' and age = @age`, + map[string]interface{}{ + "age": 18, + }, + []User{ + users[3], + }, + }, + { + "raw_test6", + `select * from users where name like '@age' and age = @age`, + map[string]interface{}{ + "age": 18, + }, + []User{ + users[4], + }, + }, + } + for _, test := range tests { + t.Run(test.TestName, func(t *testing.T) { + var results []User + if err := DB.Raw(test.Sql, test.args).Scan(&results).Error; err != nil { + t.Errorf("errors %s: %v", test.TestName, err) + } else { + if len(results) != len(test.Expect) { + t.Errorf("errors %s: %v", test.TestName, err) + } else { + for i := 0; i < len(results); i++ { + CheckUser(t, results[i], test.Expect[i]) + } + } + } + }) + } +}