Repository: go-gorm/gorm
Pull request #7339 (2025-01-07 18:55:44)

Fixed Empty Returning Clause Merge Edge Case
- [x] Do only one thing
- [x] Non breaking API changes
- [x] Tested

### What does this pull request do?

This pull request fixes the merging behavior of two `clause.Returning` clauses. Specifically, it ensures that if a `clause.Returning` contains expressions without `Columns`, it won't be overridden by specific columns during the merge. This addresses an issue caused by the implicit behavior of empty `clause.Returning` clauses.

### Use Case Description

I work with queries involving multiple embedded models, where each model requires different columns to be returned. Some operations need all columns to be returned, while others need a subset.

Currently, the merging strategy overrides an implicit empty `clause.Returning` clause with specific columns, making it impossible to implement this mechanism. This fix resolves that limitation, enabling better control over the returned columns in complex query scenarios.



Patch:
diff --git a/clause/returning.go b/clause/returning.go
index d94b7a4..76064c4 100644
--- a/clause/returning.go
+++ b/clause/returning.go
@@ -26,9 +26,12 @@ func (returning Returning) Build(builder Builder) {
 
 // MergeClause merge order by clauses
 func (returning Returning) MergeClause(clause *Clause) {
-	if v, ok := clause.Expression.(Returning); ok {
-		returning.Columns = append(v.Columns, returning.Columns...)
+	if v, ok := clause.Expression.(Returning); ok && len(returning.Columns) > 0 {
+		if v.Columns != nil {
+			returning.Columns = append(v.Columns, returning.Columns...)
+		} else {
+			returning.Columns = nil
+		}
 	}
-
 	clause.Expression = returning
 }
diff --git a/schema/index.go b/schema/index.go
index 786e210..72fc6ca 100644
--- a/schema/index.go
+++ b/schema/index.go
@@ -23,7 +23,7 @@ type IndexOption struct {
 	Sort       string // DESC, ASC
 	Collate    string
 	Length     int
-	priority   int
+	Priority   int
 }
 
 // ParseIndexes parse schema indexes
@@ -64,7 +64,7 @@ func (schema *Schema) ParseIndexes() []*Index {
 
 				idx.Fields = append(idx.Fields, index.Fields...)
 				sort.Slice(idx.Fields, func(i, j int) bool {
-					return idx.Fields[i].priority < idx.Fields[j].priority
+					return idx.Fields[i].Priority < idx.Fields[j].Priority
 				})
 			}
 		}
@@ -155,7 +155,7 @@ func parseFieldIndexes(field *Field) (indexes []Index, err error) {
 						Sort:       settings["SORT"],
 						Collate:    settings["COLLATE"],
 						Length:     length,
-						priority:   priority,
+						Priority:   priority,
 					}},
 				})
 			}


Test patch:
diff --git a/clause/returning_test.go b/clause/returning_test.go
index bd0ecce..b7a408b 100644
--- a/clause/returning_test.go
+++ b/clause/returning_test.go
@@ -26,6 +26,22 @@ func TestReturning(t *testing.T) {
 			}},
 			"SELECT * FROM `users` RETURNING `users`.`id`,`name`,`age`", nil,
 		},
+		{
+			[]clause.Interface{clause.Select{}, clause.From{}, clause.Returning{
+				[]clause.Column{clause.PrimaryColumn},
+			}, clause.Returning{}, clause.Returning{
+				[]clause.Column{{Name: "name"}, {Name: "age"}},
+			}},
+			"SELECT * FROM `users` RETURNING *", nil,
+		},
+		{
+			[]clause.Interface{clause.Select{}, clause.From{}, clause.Returning{
+				[]clause.Column{clause.PrimaryColumn},
+			}, clause.Returning{
+				[]clause.Column{{Name: "name"}, {Name: "age"}},
+			}, clause.Returning{}},
+			"SELECT * FROM `users` RETURNING *", nil,
+		},
 	}
 
 	for idx, result := range results {