2020-02-22 15:57:29 +03:00
|
|
|
package clause_test
|
|
|
|
|
|
|
|
import (
|
2020-07-10 07:28:24 +03:00
|
|
|
"database/sql"
|
2020-02-22 15:57:29 +03:00
|
|
|
"fmt"
|
2020-07-10 07:28:24 +03:00
|
|
|
"reflect"
|
2020-02-22 15:57:29 +03:00
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
|
2020-06-02 04:16:07 +03:00
|
|
|
"gorm.io/gorm"
|
|
|
|
"gorm.io/gorm/clause"
|
|
|
|
"gorm.io/gorm/schema"
|
2020-06-02 05:34:50 +03:00
|
|
|
"gorm.io/gorm/utils/tests"
|
2020-02-22 15:57:29 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestExpr(t *testing.T) {
|
|
|
|
results := []struct {
|
|
|
|
SQL string
|
|
|
|
Result string
|
|
|
|
Vars []interface{}
|
|
|
|
}{{
|
|
|
|
SQL: "create table ? (? ?, ? ?)",
|
|
|
|
Vars: []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}},
|
|
|
|
Result: "create table `users` (`id` int, `name` text)",
|
|
|
|
}}
|
|
|
|
|
|
|
|
for idx, result := range results {
|
|
|
|
t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
|
2020-02-26 14:06:42 +03:00
|
|
|
user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
|
2020-02-22 15:57:29 +03:00
|
|
|
stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
|
|
|
|
clause.Expr{SQL: result.SQL, Vars: result.Vars}.Build(stmt)
|
|
|
|
if stmt.SQL.String() != result.Result {
|
|
|
|
t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-07-10 07:28:24 +03:00
|
|
|
|
|
|
|
func TestNamedExpr(t *testing.T) {
|
2020-10-13 10:32:25 +03:00
|
|
|
type Base struct {
|
|
|
|
Name2 string
|
|
|
|
}
|
|
|
|
|
2020-09-17 16:52:41 +03:00
|
|
|
type NamedArgument struct {
|
|
|
|
Name1 string
|
2020-10-13 10:32:25 +03:00
|
|
|
Base
|
2020-09-17 16:52:41 +03:00
|
|
|
}
|
|
|
|
|
2020-07-10 07:28:24 +03:00
|
|
|
results := []struct {
|
|
|
|
SQL string
|
|
|
|
Result string
|
|
|
|
Vars []interface{}
|
|
|
|
ExpectedVars []interface{}
|
|
|
|
}{{
|
|
|
|
SQL: "create table ? (? ?, ? ?)",
|
|
|
|
Vars: []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}},
|
|
|
|
Result: "create table `users` (`id` int, `name` text)",
|
|
|
|
}, {
|
|
|
|
SQL: "name1 = @name AND name2 = @name",
|
|
|
|
Vars: []interface{}{sql.Named("name", "jinzhu")},
|
|
|
|
Result: "name1 = ? AND name2 = ?",
|
|
|
|
ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
|
|
|
|
}, {
|
|
|
|
SQL: "name1 = @name1 AND name2 = @name2 AND name3 = @name1",
|
|
|
|
Vars: []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")},
|
|
|
|
Result: "name1 = ? AND name2 = ? AND name3 = ?",
|
|
|
|
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
|
|
|
|
}, {
|
|
|
|
SQL: "name1 = @name1 AND name2 = @name2 AND name3 = @name1",
|
|
|
|
Vars: []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu2"}},
|
|
|
|
Result: "name1 = ? AND name2 = ? AND name3 = ?",
|
|
|
|
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
|
|
|
|
}, {
|
|
|
|
SQL: "@@test AND name1 = @name1 AND name2 = @name2 AND name3 = @name1 @notexist",
|
|
|
|
Vars: []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")},
|
|
|
|
Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? ?",
|
|
|
|
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil},
|
2020-09-17 16:52:41 +03:00
|
|
|
}, {
|
|
|
|
SQL: "@@test AND name1 = @Name1 AND name2 = @Name2 AND name3 = @Name1 @Notexist",
|
2020-10-13 10:32:25 +03:00
|
|
|
Vars: []interface{}{NamedArgument{Name1: "jinzhu", Base: Base{Name2: "jinzhu2"}}},
|
2020-09-17 16:52:41 +03:00
|
|
|
Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? ?",
|
|
|
|
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil},
|
2020-09-18 16:42:27 +03:00
|
|
|
}, {
|
|
|
|
SQL: "create table ? (? ?, ? ?)",
|
|
|
|
Vars: []interface{}{},
|
|
|
|
Result: "create table ? (? ?, ? ?)",
|
2020-07-10 07:28:24 +03:00
|
|
|
}}
|
|
|
|
|
|
|
|
for idx, result := range results {
|
|
|
|
t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
|
|
|
|
user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
|
|
|
|
stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
|
|
|
|
clause.NamedExpr{SQL: result.SQL, Vars: result.Vars}.Build(stmt)
|
|
|
|
if stmt.SQL.String() != result.Result {
|
|
|
|
t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) {
|
|
|
|
t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-12-11 09:07:23 +03:00
|
|
|
|
|
|
|
func TestExpression(t *testing.T) {
|
|
|
|
column := "column-name"
|
|
|
|
results := []struct {
|
2021-05-31 12:21:27 +03:00
|
|
|
Expressions []clause.Expression
|
|
|
|
ExpectedVars []interface{}
|
|
|
|
Result string
|
2020-12-11 09:07:23 +03:00
|
|
|
}{{
|
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Eq{Column: column, Value: "column-value"},
|
|
|
|
},
|
2021-05-31 12:21:27 +03:00
|
|
|
ExpectedVars: []interface{}{"column-value"},
|
|
|
|
Result: "`column-name` = ?",
|
2020-12-30 05:42:13 +03:00
|
|
|
}, {
|
2020-12-11 09:07:23 +03:00
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Eq{Column: column, Value: nil},
|
|
|
|
clause.Eq{Column: column, Value: (*string)(nil)},
|
|
|
|
clause.Eq{Column: column, Value: (*int)(nil)},
|
|
|
|
clause.Eq{Column: column, Value: (*bool)(nil)},
|
|
|
|
clause.Eq{Column: column, Value: (interface{})(nil)},
|
2020-12-30 05:42:13 +03:00
|
|
|
clause.Eq{Column: column, Value: sql.NullString{String: "", Valid: false}},
|
2020-12-11 09:07:23 +03:00
|
|
|
},
|
|
|
|
Result: "`column-name` IS NULL",
|
2020-12-30 05:42:13 +03:00
|
|
|
}, {
|
2020-12-11 09:07:23 +03:00
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Neq{Column: column, Value: "column-value"},
|
|
|
|
},
|
2021-05-31 12:21:27 +03:00
|
|
|
ExpectedVars: []interface{}{"column-value"},
|
|
|
|
Result: "`column-name` <> ?",
|
2020-12-30 05:42:13 +03:00
|
|
|
}, {
|
2020-12-11 09:07:23 +03:00
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Neq{Column: column, Value: nil},
|
|
|
|
clause.Neq{Column: column, Value: (*string)(nil)},
|
|
|
|
clause.Neq{Column: column, Value: (*int)(nil)},
|
|
|
|
clause.Neq{Column: column, Value: (*bool)(nil)},
|
|
|
|
clause.Neq{Column: column, Value: (interface{})(nil)},
|
|
|
|
},
|
|
|
|
Result: "`column-name` IS NOT NULL",
|
2021-05-31 10:25:38 +03:00
|
|
|
}, {
|
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Eq{Column: column, Value: []string{"a", "b"}},
|
|
|
|
},
|
2021-05-31 12:21:27 +03:00
|
|
|
ExpectedVars: []interface{}{"a", "b"},
|
|
|
|
Result: "`column-name` IN (?,?)",
|
2021-05-31 10:25:38 +03:00
|
|
|
}, {
|
|
|
|
Expressions: []clause.Expression{
|
|
|
|
clause.Neq{Column: column, Value: []string{"a", "b"}},
|
|
|
|
},
|
2021-05-31 12:21:27 +03:00
|
|
|
ExpectedVars: []interface{}{"a", "b"},
|
|
|
|
Result: "`column-name` NOT IN (?,?)",
|
2020-12-11 09:07:23 +03:00
|
|
|
}}
|
|
|
|
|
|
|
|
for idx, result := range results {
|
|
|
|
for idy, expression := range result.Expressions {
|
|
|
|
t.Run(fmt.Sprintf("case #%v.%v", idx, idy), func(t *testing.T) {
|
|
|
|
user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
|
|
|
|
stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
|
|
|
|
expression.Build(stmt)
|
|
|
|
if stmt.SQL.String() != result.Result {
|
|
|
|
t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
|
|
|
|
}
|
2021-05-31 12:21:27 +03:00
|
|
|
|
|
|
|
if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) {
|
|
|
|
t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars)
|
|
|
|
}
|
2020-12-11 09:07:23 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|