Skip to content

Commit 7fed3ae

Browse files
committed
OrderByCond options
1 parent f0e8aca commit 7fed3ae

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

select.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,36 @@ func (b SelectBuilder) OrderBy(orderBys ...string) SelectBuilder {
426426
return b
427427
}
428428

429+
// OrderNullsType is used to specify the order of NULLs in ORDER BY clause.
430+
type OrderNullsType int
431+
432+
const (
433+
OrderNullsUndefined OrderNullsType = iota
434+
OrderNullsFirst // ORDER BY ... NULLS FIRST
435+
OrderNullsLast // ORDER BY ... NULLS LAST
436+
)
437+
438+
// String returns the string representation of the order of NULLs.
439+
func (o OrderNullsType) String() string {
440+
if o == OrderNullsFirst {
441+
return "FIRST"
442+
}
443+
if o == OrderNullsLast {
444+
return "LAST"
445+
}
446+
return ""
447+
}
448+
449+
// OrderByCondOption is used to specify additional options for OrderByCond.
450+
type OrderByCondOption struct {
451+
ColumnID int
452+
NullsType OrderNullsType
453+
}
454+
429455
// OrderByCond adds ORDER BY expressions with direction to the query.
430456
// The columns map is used to map OrderCond.ColumnID to the column name.
431457
// Can be used to avoid hardcoding column names in the code.
432-
func (b SelectBuilder) OrderByCond(columns map[int]string, conds []OrderCond) SelectBuilder {
458+
func (b SelectBuilder) OrderByCond(columns map[int]string, conds []OrderCond, opts ...OrderByCondOption) SelectBuilder {
433459
for i, cond := range conds {
434460
if pos := slices.IndexFunc(conds[:i], func(c OrderCond) bool {
435461
return c.ColumnID == cond.ColumnID
@@ -442,7 +468,19 @@ func (b SelectBuilder) OrderByCond(columns map[int]string, conds []OrderCond) Se
442468
panic(fmt.Sprintf("column id %d not found in columns map %v", cond.ColumnID, columns))
443469
}
444470

445-
b = b.OrderByClause(fmt.Sprintf("%s %s", column, cond.Direction.String()))
471+
nullsType := OrderNullsUndefined
472+
for _, opt := range opts {
473+
if opt.ColumnID == cond.ColumnID {
474+
nullsType = opt.NullsType
475+
break
476+
}
477+
}
478+
479+
if nullsType == OrderNullsUndefined {
480+
b = b.OrderByClause(fmt.Sprintf("%s %s", column, cond.Direction.String()))
481+
} else {
482+
b = b.OrderByClause(fmt.Sprintf("%s %s NULLS %s", column, cond.Direction.String(), nullsType.String()))
483+
}
446484
}
447485

448486
return b

select_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,16 @@ func TestOrderByCond(t *testing.T) {
412412
assert.Panics(t, func() {
413413
_ = Select("id").From("users").OrderByCond(columns, []OrderCond{{3, Asc}})
414414
})
415+
416+
// test with options
417+
sql, args, err = Select("id").From("users").OrderByCond(columns, orderConds,
418+
OrderByCondOption{
419+
ColumnID: 2,
420+
NullsType: OrderNullsLast,
421+
}).ToSql()
422+
assert.NoError(t, err)
423+
assert.Equal(t, "SELECT id FROM users ORDER BY id ASC, created DESC NULLS LAST", sql)
424+
assert.Empty(t, args)
415425
}
416426

417427
func TestSearch(t *testing.T) {

0 commit comments

Comments
 (0)