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  }