github.com/systematiccaos/gorm@v1.22.6/clause/expression_test.go (about) 1 package clause_test 2 3 import ( 4 "database/sql" 5 "fmt" 6 "reflect" 7 "sync" 8 "testing" 9 10 "github.com/systematiccaos/gorm" 11 "github.com/systematiccaos/gorm/clause" 12 "github.com/systematiccaos/gorm/schema" 13 "github.com/systematiccaos/gorm/utils/tests" 14 ) 15 16 func TestExpr(t *testing.T) { 17 results := []struct { 18 SQL string 19 Result string 20 Vars []interface{} 21 }{{ 22 SQL: "create table ? (? ?, ? ?)", 23 Vars: []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}}, 24 Result: "create table `users` (`id` int, `name` text)", 25 }} 26 27 for idx, result := range results { 28 t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) { 29 user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy) 30 stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}} 31 clause.Expr{SQL: result.SQL, Vars: result.Vars}.Build(stmt) 32 if stmt.SQL.String() != result.Result { 33 t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String()) 34 } 35 }) 36 } 37 } 38 39 func TestNamedExpr(t *testing.T) { 40 type Base struct { 41 Name2 string 42 } 43 44 type NamedArgument struct { 45 Name1 string 46 Base 47 } 48 49 results := []struct { 50 SQL string 51 Result string 52 Vars []interface{} 53 ExpectedVars []interface{} 54 }{{ 55 SQL: "create table ? (? ?, ? ?)", 56 Vars: []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}}, 57 Result: "create table `users` (`id` int, `name` text)", 58 }, { 59 SQL: "name1 = @name AND name2 = @name", 60 Vars: []interface{}{sql.Named("name", "jinzhu")}, 61 Result: "name1 = ? AND name2 = ?", 62 ExpectedVars: []interface{}{"jinzhu", "jinzhu"}, 63 }, { 64 SQL: "name1 = @name AND name2 = @@name", 65 Vars: []interface{}{map[string]interface{}{"name": "jinzhu"}}, 66 Result: "name1 = ? AND name2 = @@name", 67 ExpectedVars: []interface{}{"jinzhu"}, 68 }, { 69 SQL: "name1 = @name1 AND name2 = @name2 AND name3 = @name1", 70 Vars: []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")}, 71 Result: "name1 = ? AND name2 = ? AND name3 = ?", 72 ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"}, 73 }, { 74 SQL: "name1 = @name1 AND name2 = @name2 AND name3 = @name1", 75 Vars: []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu2"}}, 76 Result: "name1 = ? AND name2 = ? AND name3 = ?", 77 ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"}, 78 }, { 79 SQL: "@@test AND name1 = @name1 AND name2 = @name2 AND name3 = @name1 @notexist", 80 Vars: []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")}, 81 Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? @notexist", 82 ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"}, 83 }, { 84 SQL: "@@test AND name1 = @Name1 AND name2 = @Name2 AND name3 = @Name1 @notexist", 85 Vars: []interface{}{NamedArgument{Name1: "jinzhu", Base: Base{Name2: "jinzhu2"}}}, 86 Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? @notexist", 87 ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"}, 88 }, { 89 SQL: "create table ? (? ?, ? ?)", 90 Vars: []interface{}{}, 91 Result: "create table ? (? ?, ? ?)", 92 }, { 93 SQL: "name1 = @name AND name2 = @name;", 94 Vars: []interface{}{sql.Named("name", "jinzhu")}, 95 Result: "name1 = ? AND name2 = ?;", 96 ExpectedVars: []interface{}{"jinzhu", "jinzhu"}, 97 }, { 98 SQL: "?", 99 Vars: []interface{}{clause.Column{Table: "table", Name: "col"}}, 100 Result: "`table`.`col`", 101 }, { 102 SQL: "?", 103 Vars: []interface{}{clause.Column{Table: "table", Name: "col", Raw: true}}, 104 Result: "table.col", 105 }, { 106 SQL: "?", 107 Vars: []interface{}{clause.Column{Table: "table", Name: clause.PrimaryKey, Raw: true}}, 108 Result: "table.id", 109 }, { 110 SQL: "?", 111 Vars: []interface{}{clause.Column{Table: "table", Name: "col", Alias: "alias"}}, 112 Result: "`table`.`col` AS `alias`", 113 }, { 114 SQL: "?", 115 Vars: []interface{}{clause.Column{Table: "table", Name: "col", Alias: "alias", Raw: true}}, 116 Result: "table.col AS alias", 117 }, { 118 SQL: "?", 119 Vars: []interface{}{clause.Table{Name: "table", Alias: "alias"}}, 120 Result: "`table` `alias`", 121 }, { 122 SQL: "?", 123 Vars: []interface{}{clause.Table{Name: "table", Alias: "alias", Raw: true}}, 124 Result: "table alias", 125 }} 126 127 for idx, result := range results { 128 t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) { 129 user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy) 130 stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}} 131 clause.NamedExpr{SQL: result.SQL, Vars: result.Vars}.Build(stmt) 132 if stmt.SQL.String() != result.Result { 133 t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String()) 134 } 135 136 if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) { 137 t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars) 138 } 139 }) 140 } 141 } 142 143 func TestExpression(t *testing.T) { 144 column := "column-name" 145 results := []struct { 146 Expressions []clause.Expression 147 ExpectedVars []interface{} 148 Result string 149 }{{ 150 Expressions: []clause.Expression{ 151 clause.Eq{Column: column, Value: "column-value"}, 152 }, 153 ExpectedVars: []interface{}{"column-value"}, 154 Result: "`column-name` = ?", 155 }, { 156 Expressions: []clause.Expression{ 157 clause.Eq{Column: column, Value: nil}, 158 clause.Eq{Column: column, Value: (*string)(nil)}, 159 clause.Eq{Column: column, Value: (*int)(nil)}, 160 clause.Eq{Column: column, Value: (*bool)(nil)}, 161 clause.Eq{Column: column, Value: (interface{})(nil)}, 162 clause.Eq{Column: column, Value: sql.NullString{String: "", Valid: false}}, 163 }, 164 Result: "`column-name` IS NULL", 165 }, { 166 Expressions: []clause.Expression{ 167 clause.Neq{Column: column, Value: "column-value"}, 168 }, 169 ExpectedVars: []interface{}{"column-value"}, 170 Result: "`column-name` <> ?", 171 }, { 172 Expressions: []clause.Expression{ 173 clause.Neq{Column: column, Value: nil}, 174 clause.Neq{Column: column, Value: (*string)(nil)}, 175 clause.Neq{Column: column, Value: (*int)(nil)}, 176 clause.Neq{Column: column, Value: (*bool)(nil)}, 177 clause.Neq{Column: column, Value: (interface{})(nil)}, 178 }, 179 Result: "`column-name` IS NOT NULL", 180 }, { 181 Expressions: []clause.Expression{ 182 clause.Eq{Column: column, Value: []string{"a", "b"}}, 183 }, 184 ExpectedVars: []interface{}{"a", "b"}, 185 Result: "`column-name` IN (?,?)", 186 }, { 187 Expressions: []clause.Expression{ 188 clause.Neq{Column: column, Value: []string{"a", "b"}}, 189 }, 190 ExpectedVars: []interface{}{"a", "b"}, 191 Result: "`column-name` NOT IN (?,?)", 192 }, { 193 Expressions: []clause.Expression{ 194 clause.Eq{Column: clause.Expr{SQL: "SUM(?)", Vars: []interface{}{clause.Column{Name: "id"}}}, Value: 100}, 195 }, 196 ExpectedVars: []interface{}{100}, 197 Result: "SUM(`id`) = ?", 198 }, { 199 Expressions: []clause.Expression{ 200 clause.Gte{Column: clause.Expr{SQL: "SUM(?)", Vars: []interface{}{clause.Column{Table: "users", Name: "id"}}}, Value: 100}, 201 }, 202 ExpectedVars: []interface{}{100}, 203 Result: "SUM(`users`.`id`) >= ?", 204 }} 205 206 for idx, result := range results { 207 for idy, expression := range result.Expressions { 208 t.Run(fmt.Sprintf("case #%v.%v", idx, idy), func(t *testing.T) { 209 user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy) 210 stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}} 211 expression.Build(stmt) 212 if stmt.SQL.String() != result.Result { 213 t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String()) 214 } 215 216 if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) { 217 t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars) 218 } 219 }) 220 } 221 } 222 }