feat(expression): support case-when expression
This commit is contained in:
		
							parent
							
								
									deceebfab8
								
							
						
					
					
						commit
						400d51c927
					
				
							
								
								
									
										54
									
								
								clause/expr_case.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								clause/expr_case.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| package clause | ||||
| 
 | ||||
| type ExprCaseCondition struct { | ||||
| 	When string | ||||
| 	Then string | ||||
| 	Vars []any | ||||
| } | ||||
| 
 | ||||
| type ExprCaseElse struct { | ||||
| 	Then string | ||||
| 	Vars []any | ||||
| } | ||||
| 
 | ||||
| type ExprCase struct { | ||||
| 	Cases []*ExprCaseCondition | ||||
| 	Else  *ExprCaseElse | ||||
| } | ||||
| 
 | ||||
| func (expr ExprCase) Name() string { | ||||
| 	return "CASE" | ||||
| } | ||||
| 
 | ||||
| func (expr ExprCase) Build(builder Builder) { | ||||
| 	var vars []any | ||||
| 	for idx, condition := range expr.Cases { | ||||
| 		if idx > 0 { | ||||
| 			_ = builder.WriteByte(' ') | ||||
| 		} | ||||
| 		_, _ = builder.WriteString("WHEN ") | ||||
| 		_, _ = builder.WriteString(condition.When) | ||||
| 		_, _ = builder.WriteString(" THEN ") | ||||
| 		_, _ = builder.WriteString(condition.Then) | ||||
| 		if len(condition.Vars) > 0 { | ||||
| 			vars = append(vars, condition.Vars...) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if expr.Else != nil { | ||||
| 		elseExpr := expr.Else | ||||
| 		_, _ = builder.WriteString(" ELSE ") | ||||
| 		_, _ = builder.WriteString(elseExpr.Then) | ||||
| 		if len(elseExpr.Vars) > 0 { | ||||
| 			vars = append(vars, elseExpr.Vars...) | ||||
| 		} | ||||
| 	} | ||||
| 	_, _ = builder.WriteString(" END") | ||||
| 
 | ||||
| 	clauseExpr := Expr{SQL: "", Vars: vars} | ||||
| 	clauseExpr.Build(builder) | ||||
| } | ||||
| 
 | ||||
| func (expr ExprCase) MergeClause(clause *Clause) { | ||||
| 	clause.Expression = expr | ||||
| } | ||||
							
								
								
									
										60
									
								
								clause/expr_case_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								clause/expr_case_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| package clause_test | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"gorm.io/gorm" | ||||
| 	"gorm.io/gorm/clause" | ||||
| ) | ||||
| 
 | ||||
| func Test_ExprCase(t *testing.T) { | ||||
| 	type exampleUser struct { | ||||
| 		ID   string | ||||
| 		Name string | ||||
| 	} | ||||
| 
 | ||||
| 	inputUsers := []*exampleUser{ | ||||
| 		{ | ||||
| 			ID:   "user-001", | ||||
| 			Name: "user-name-001", | ||||
| 		}, | ||||
| 		{ | ||||
| 			ID:   "user-002", | ||||
| 			Name: "user-name-002", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	userIDs := make([]string, len(inputUsers)) | ||||
| 	userNameCases := make([]*clause.ExprCaseCondition, len(inputUsers)) | ||||
| 	for idx, user := range inputUsers { | ||||
| 		userIDs[idx] = user.ID | ||||
| 		userNameCases[idx] = &clause.ExprCaseCondition{ | ||||
| 			When: "user_id=?", | ||||
| 			Then: "?", | ||||
| 			Vars: []any{ | ||||
| 				user.ID, | ||||
| 				user.Name, | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	sqlQuery := db.ToSQL(func(db *gorm.DB) *gorm.DB { | ||||
| 		return db. | ||||
| 			Table("users"). | ||||
| 			Where("user_id IN (?)", userIDs). | ||||
| 			UpdateColumns(map[string]any{ | ||||
| 				"user_name": clause.ExprCase{ | ||||
| 					Cases: userNameCases, | ||||
| 					Else: &clause.ExprCaseElse{ | ||||
| 						Then: "user_name", | ||||
| 						Vars: nil, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
| 	}) | ||||
| 
 | ||||
| 	expectedSQLQuery := "UPDATE `users` SET `user_name`=CASE WHEN user_id=\"user-001\" THEN \"user-name-001\" WHEN user_id=\"user-002\" THEN \"user-name-002\" ELSE user_name END WHERE user_id IN (\"user-001\",\"user-002\")" | ||||
| 	if sqlQuery != expectedSQLQuery { | ||||
| 		t.Errorf("SQLQuery is mismatch actual: %v expected:%v\n", sqlQuery, expectedSQLQuery) | ||||
| 	} | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tri Dao
						Tri Dao