From ed88c5d9c6d4569d0e639093ed0d93e9bbe32078 Mon Sep 17 00:00:00 2001 From: Or Ben Chitrit <10655932+Orbsynated@users.noreply.github.com> Date: Wed, 19 Feb 2025 20:54:19 +0200 Subject: [PATCH] refactor: update OrderBy clause to use Exprs instead of Columns --- chainable_api.go | 11 ++++++----- clause/benchmarks_test.go | 2 +- clause/order_by.go | 41 ++++++++++++++++++--------------------- clause/order_by_test.go | 24 +++++++++++++++++------ 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/chainable_api.go b/chainable_api.go index 8953413d..512d61aa 100644 --- a/chainable_api.go +++ b/chainable_api.go @@ -318,12 +318,12 @@ func (db *DB) Order(value interface{}) (tx *DB) { tx.Statement.AddClause(v) case clause.OrderByColumn: tx.Statement.AddClause(clause.OrderBy{ - Columns: []clause.OrderByColumn{v}, + Exprs: []clause.Expression{v}, }) case string: if v != "" { tx.Statement.AddClause(clause.OrderBy{ - Columns: []clause.OrderByColumn{{ + Exprs: []clause.Expression{clause.OrderByColumn{ Column: clause.Column{Name: v, Raw: true}, }}, }) @@ -448,9 +448,10 @@ func (db *DB) Assign(attrs ...interface{}) (tx *DB) { // Unscoped allows queries to include records marked as deleted, // overriding the soft deletion behavior. // Example: -// var users []User -// db.Unscoped().Find(&users) -// // Retrieves all users, including deleted ones. +// +// var users []User +// db.Unscoped().Find(&users) +// // Retrieves all users, including deleted ones. func (db *DB) Unscoped() (tx *DB) { tx = db.getInstance() tx.Statement.Unscoped = true diff --git a/clause/benchmarks_test.go b/clause/benchmarks_test.go index 34d5df41..4f5cddee 100644 --- a/clause/benchmarks_test.go +++ b/clause/benchmarks_test.go @@ -45,7 +45,7 @@ func BenchmarkComplexSelect(b *testing.B) { }}, clause.GroupBy{Columns: []clause.Column{{Name: "role"}}, Having: []clause.Expression{clause.Eq{"role", "admin"}}}, clause.Limit{Limit: &limit10, Offset: 20}, - clause.OrderBy{Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}}, + clause.OrderBy{Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.PrimaryColumn, Desc: true}}}, } for _, clause := range clauses { diff --git a/clause/order_by.go b/clause/order_by.go index 41218025..afdf2d0c 100644 --- a/clause/order_by.go +++ b/clause/order_by.go @@ -6,48 +6,45 @@ type OrderByColumn struct { Reorder bool } -type OrderBy struct { - Columns []OrderByColumn - Expression Expression +func (column OrderByColumn) Build(builder Builder) { + builder.WriteQuoted(column.Column) + if column.Desc { + builder.WriteString(" DESC") + } +} + +type OrderBy struct { + Exprs []Expression } -// Name where clause name func (orderBy OrderBy) Name() string { return "ORDER BY" } // Build build where clause func (orderBy OrderBy) Build(builder Builder) { - if orderBy.Expression != nil { - orderBy.Expression.Build(builder) - } else { - for idx, column := range orderBy.Columns { - if idx > 0 { - builder.WriteByte(',') - } - - builder.WriteQuoted(column.Column) - if column.Desc { - builder.WriteString(" DESC") - } + for idx, expression := range orderBy.Exprs { + if idx > 0 { + builder.WriteByte(',') } + expression.Build(builder) } } // MergeClause merge order by clauses func (orderBy OrderBy) MergeClause(clause *Clause) { if v, ok := clause.Expression.(OrderBy); ok { - for i := len(orderBy.Columns) - 1; i >= 0; i-- { - if orderBy.Columns[i].Reorder { - orderBy.Columns = orderBy.Columns[i:] + for i := len(orderBy.Exprs) - 1; i >= 0; i-- { + if asColumn, ok := orderBy.Exprs[i].(OrderByColumn); ok && asColumn.Reorder { + orderBy.Exprs = orderBy.Exprs[i:] clause.Expression = orderBy return } } - copiedColumns := make([]OrderByColumn, len(v.Columns)) - copy(copiedColumns, v.Columns) - orderBy.Columns = append(copiedColumns, orderBy.Columns...) + copiedColumns := make([]Expression, len(v.Exprs)) + copy(copiedColumns, v.Exprs) + orderBy.Exprs = append(copiedColumns, orderBy.Exprs...) } clause.Expression = orderBy diff --git a/clause/order_by_test.go b/clause/order_by_test.go index d8b5dfbf..ff56455d 100644 --- a/clause/order_by_test.go +++ b/clause/order_by_test.go @@ -15,16 +15,16 @@ func TestOrderBy(t *testing.T) { }{ { []clause.Interface{clause.Select{}, clause.From{}, clause.OrderBy{ - Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}, + Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.PrimaryColumn, Desc: true}}, }}, "SELECT * FROM `users` ORDER BY `users`.`id` DESC", nil, }, { []clause.Interface{ clause.Select{}, clause.From{}, clause.OrderBy{ - Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}, + Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.PrimaryColumn, Desc: true}}, }, clause.OrderBy{ - Columns: []clause.OrderByColumn{{Column: clause.Column{Name: "name"}}}, + Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.Column{Name: "name"}}}, }, }, "SELECT * FROM `users` ORDER BY `users`.`id` DESC,`name`", nil, @@ -32,9 +32,9 @@ func TestOrderBy(t *testing.T) { { []clause.Interface{ clause.Select{}, clause.From{}, clause.OrderBy{ - Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}, + Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.PrimaryColumn, Desc: true}}, }, clause.OrderBy{ - Columns: []clause.OrderByColumn{{Column: clause.Column{Name: "name"}, Reorder: true}}, + Exprs: []clause.Expression{clause.OrderByColumn{Column: clause.Column{Name: "name"}, Reorder: true}}, }, }, "SELECT * FROM `users` ORDER BY `name`", nil, @@ -42,12 +42,24 @@ func TestOrderBy(t *testing.T) { { []clause.Interface{ clause.Select{}, clause.From{}, clause.OrderBy{ - Expression: clause.Expr{SQL: "FIELD(id, ?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true}, + Exprs: []clause.Expression{clause.Expr{SQL: "FIELD(id, ?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true}}, }, }, "SELECT * FROM `users` ORDER BY FIELD(id, ?,?,?)", []interface{}{1, 2, 3}, }, + { + []clause.Interface{ + clause.Select{}, clause.From{}, clause.OrderBy{ + Exprs: []clause.Expression{ + clause.Expr{SQL: "FIELD(id, ?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true}, + clause.OrderByColumn{Column: clause.PrimaryColumn, Desc: true}, + }, + }, + }, + "SELECT * FROM `users` ORDER BY FIELD(id, ?,?,?),`users`.`id` DESC", + []interface{}{1, 2, 3}, + }, } for idx, result := range results {