Skip to content

Commit c2510fe

Browse files
authored
fix(orderby): improved OrderByBuilder for api input (#34)
1 parent 4a878bb commit c2510fe

File tree

3 files changed

+58
-15
lines changed

3 files changed

+58
-15
lines changed

CHANGELOG.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.3] - 2014-04-12
9+
### Fixes
10+
- fixed close issue when it fails to build prepareStmt (#33)
11+
- improved `OrderByBuilder` for api input (#34)
12+
813
## [1.4.2] - 2014-04-10
914
### Added
10-
- added `OrderByBuilder` to prevent sql injection (#32)
15+
- added `OrderByBuilder` to prevent sql injection (#32, #33)
1116

1217
## [1.4.1] - 2014-04-09
1318
### Added

sqlbuilder_orderby.go

+33-6
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ type OrderByBuilder struct {
1111
allowedColumns []string
1212
}
1313

14-
// OrderBy create an OrderByBuilder with allowed columns to prevent sql injection. NB: any input is allowed if it is not provided
15-
func (b *Builder) OrderBy(allowedColumns ...string) *OrderByBuilder {
14+
// Order create an OrderByBuilder with allowed columns to prevent sql injection. NB: any input is allowed if it is not provided
15+
func (b *Builder) Order(allowedColumns ...string) *OrderByBuilder {
1616
ob := &OrderByBuilder{
1717
Builder: b,
1818
allowedColumns: allowedColumns,
@@ -34,8 +34,35 @@ func (ob *OrderByBuilder) isAllowed(col string) bool {
3434
})
3535
}
3636

37-
// Asc order by ASC with columns
38-
func (ob *OrderByBuilder) Asc(columns ...string) *OrderByBuilder {
37+
// By order by raw sql. eg By("a asc, b desc")
38+
func (ob *OrderByBuilder) By(raw string) *OrderByBuilder {
39+
cols := strings.Split(raw, ",")
40+
41+
var n int
42+
var items []string
43+
var by string
44+
for _, col := range cols {
45+
items = strings.Split(strings.TrimSpace(col), " ")
46+
n = len(items)
47+
switch n {
48+
case 1:
49+
ob.ByAsc(strings.TrimSpace(col))
50+
case 2:
51+
by = strings.TrimSpace(items[1])
52+
if strings.EqualFold(by, "ASC") {
53+
ob.ByAsc(strings.TrimSpace(items[0]))
54+
} else if strings.EqualFold(by, "DESC") {
55+
ob.ByDesc(strings.TrimSpace(items[0]))
56+
}
57+
}
58+
}
59+
60+
return ob
61+
62+
}
63+
64+
// ByAsc order by ascending with columns
65+
func (ob *OrderByBuilder) ByAsc(columns ...string) *OrderByBuilder {
3966
for _, c := range columns {
4067
if ob.isAllowed(c) {
4168
if ob.isWritten {
@@ -49,8 +76,8 @@ func (ob *OrderByBuilder) Asc(columns ...string) *OrderByBuilder {
4976
return ob
5077
}
5178

52-
// Desc order by desc with columns
53-
func (ob *OrderByBuilder) Desc(columns ...string) *OrderByBuilder {
79+
// ByDesc order by descending with columns
80+
func (ob *OrderByBuilder) ByDesc(columns ...string) *OrderByBuilder {
5481
for _, c := range columns {
5582
if ob.isAllowed(c) {
5683
if ob.isWritten {

sqlbuilder_orderby_test.go

+19-8
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ func TestOrderByBuilder(t *testing.T) {
1616
name: "no_safe_columns_should_work",
1717
build: func() *Builder {
1818
b := New("SELECT * FROM users")
19-
b.OrderBy().
20-
Desc("created_at").
21-
Asc("id", "name").
22-
Asc("updated_at")
19+
b.Order().
20+
ByDesc("created_at").
21+
ByAsc("id", "name").
22+
ByAsc("updated_at")
2323

2424
return b
2525
},
@@ -29,15 +29,26 @@ func TestOrderByBuilder(t *testing.T) {
2929
name: "safe_columns_should_work",
3030
build: func() *Builder {
3131
b := New("SELECT * FROM users")
32-
b.OrderBy("id", "created_at", "updated_at").
33-
Asc("id", "name").
34-
Desc("created_at", "unsafe_input").
35-
Asc("updated_at")
32+
b.Order("id", "created_at", "updated_at").
33+
ByAsc("id", "name").
34+
ByDesc("created_at", "unsafe_input").
35+
ByAsc("updated_at")
3636

3737
return b
3838
},
3939
wanted: "SELECT * FROM users ORDER BY id ASC, created_at DESC, updated_at ASC",
4040
},
41+
{
42+
name: "order_by_raw_sql_should_work",
43+
build: func() *Builder {
44+
b := New("SELECT * FROM users")
45+
b.Order("id", "created_at", "updated_at", "age").
46+
By("created_at desc, id, name asc, updated_at asc, age invalid_by, unsafe_asc, unsafe_desc desc")
47+
48+
return b
49+
},
50+
wanted: "SELECT * FROM users ORDER BY created_at DESC, id ASC, updated_at ASC",
51+
},
4152
}
4253

4354
for _, test := range tests {

0 commit comments

Comments
 (0)