Skip to content
This repository was archived by the owner on Jun 14, 2019. It is now read-only.

Commit 88fb632

Browse files
committed
update From(take out NestedFlag) & optimize Limit(use ROW_NUMBER() supported by mssql 2005 or later) & update test cases
1 parent 8ed5202 commit 88fb632

File tree

6 files changed

+48
-84
lines changed

6 files changed

+48
-84
lines changed

builder.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ type Builder struct {
4444
optype
4545
dialect string
4646
tableName string
47-
pk []string
4847
subQuery *Builder
4948
cond Cond
5049
selects []string
@@ -56,7 +55,6 @@ type Builder struct {
5655
orderBy string
5756
groupBy string
5857
having string
59-
isNested bool
6058
}
6159

6260
// Dialect sets the db dialect of Builder.
@@ -82,23 +80,6 @@ func (b *Builder) From(tableName string, subQuery ...*Builder) *Builder {
8280
return b
8381
}
8482

85-
// PK sets the pk(s) of table
86-
// Usually this indicates PK(s) when performing a LIMIT operation in mssql(especially in LIMIT n,m).
87-
// Use full name to avoid ambiguity
88-
func (b *Builder) PK(pk ...string) *Builder {
89-
b.pk = pk
90-
91-
return b
92-
}
93-
94-
// NestedFlag set the nested flag. If turn this on, current builder would accept empty table name when building SQL
95-
// and this builder would also be treated as a nested query at the same time.
96-
func (b *Builder) NestedFlag(isNested bool) *Builder {
97-
b.isNested = isNested
98-
99-
return b
100-
}
101-
10283
// TableName returns the table name
10384
func (b *Builder) TableName() string {
10485
return b.tableName

builder_b_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ func randSelectByCondition(dialect string, rgc *randGenConf) *Builder {
193193
if rgc.allowSubQuery {
194194
cpRgc := *rgc
195195
cpRgc.allowSubQuery = false
196-
b = Dialect(dialect).Select(randSelects()...).From(randTableName(0), randQuery(dialect, &cpRgc)).PK("id")
196+
b = Dialect(dialect).Select(randSelects()...).From(randTableName(0), randQuery(dialect, &cpRgc))
197197
} else {
198-
b = Dialect(dialect).Select(randSelects()...).From(randTableName(0)).PK("id")
198+
b = Dialect(dialect).Select(randSelects()...).From(randTableName(0))
199199
}
200200
if rgc.allowJoin {
201201
b = randJoin(b, 3)

builder_limit.go

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,19 @@ func (b *Builder) limitWriteTo(w Writer) error {
3737
selects := b.selects
3838
b.selects = append(selects, "ROWNUM RN")
3939
if limit.offset == 0 {
40-
final = Dialect(b.dialect).Select(selects...).From("at", b).PK(b.pk...).
41-
Where(Lte{"at.ROWNUM": limit.limitN})
42-
} else {
43-
sub := Dialect(b.dialect).Select(append(selects, "RN")...).
44-
From("at", b).PK(b.pk...).Where(Lte{"at.ROWNUM": limit.offset + limit.limitN})
45-
4640
if len(selects) == 0 {
47-
return ErrNotSupportType
41+
selects = append(selects, "*")
42+
} else {
43+
selects = append(selects)
4844
}
4945

50-
final = Dialect(b.dialect).Select(selects...).From("att", sub).PK(b.pk...).
46+
final = Dialect(b.dialect).Select(selects...).From("at", b).
47+
Where(Lte{"at.ROWNUM": limit.limitN})
48+
} else {
49+
sub := Dialect(b.dialect).Select("*").
50+
From("at", b).Where(Lte{"at.ROWNUM": limit.offset + limit.limitN})
51+
52+
final = Dialect(b.dialect).Select("*").From("att", sub).
5153
Where(Gt{"att.RN": limit.offset})
5254
}
5355

@@ -78,33 +80,20 @@ func (b *Builder) limitWriteTo(w Writer) error {
7880

7981
final = Dialect(b.dialect).
8082
Select(fmt.Sprintf("TOP %d %v", limit.limitN, strings.Join(selects, ","))).
81-
From("", b).PK(b.pk...).NestedFlag(true)
83+
From("at", b)
8284
} else {
83-
var column string
84-
if len(b.pk) != 0 {
85-
column = strings.TrimSpace(b.pk[0])
86-
if column == "" {
87-
return errors.New("please assign a PK for MsSQL LIMIT operation")
88-
}
89-
}
85+
sub := Dialect(b.dialect).Select(
86+
fmt.Sprintf("TOP %d %v,%v", limit.limitN+limit.offset,
87+
strings.Join(selects, ","), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN")).
88+
From(b.tableName).Where(b.cond)
9089

91-
if column == "" {
92-
return errors.New("please assign a PK for MsSQL LIMIT operation")
93-
} else {
94-
b.selects = append(b.selects, column)
95-
sub := Dialect(b.dialect).Select(fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset,
96-
strings.Join(append(selects, column), ","))).From("", b).
97-
PK(b.pk...).NestedFlag(true)
98-
99-
if len(selects) == 0 {
100-
return ErrNotSupportType
101-
}
102-
103-
final = Dialect(b.dialect).
104-
Select(fmt.Sprintf("TOP %d %v", limit.limitN, strings.Join(selects, ","))).
105-
From("", sub).PK(b.pk...).NestedFlag(true).
106-
Where(NotIn(column, sub))
90+
if len(selects) == 0 {
91+
return ErrNotSupportType
10792
}
93+
94+
final = Dialect(b.dialect).Select(
95+
fmt.Sprintf("TOP %d %v", limit.limitN, strings.Join(append(selects, "RN"), ","))).
96+
From("at", sub).Where(Gt{"at.RN": limit.limitN})
10897
}
10998

11099
return final.WriteTo(ow)

builder_select.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func Select(cols ...string) *Builder {
1616
}
1717

1818
func (b *Builder) selectWriteTo(w Writer) error {
19-
if !b.isNested && len(b.tableName) <= 0 {
19+
if len(b.tableName) <= 0 {
2020
return errors.New("no table indicated")
2121
}
2222

builder_select_test.go

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,15 @@ func TestBuilder_From(t *testing.T) {
7777
Select("id").From("table1").Where(Eq{"a": 1})).Where(Eq{"b": 1}).ToSQL()
7878
assert.NoError(t, err)
7979
assert.EqualValues(t, "SELECT sub.id FROM (SELECT id FROM table1 WHERE a=?) sub WHERE b=?", sql)
80-
assert.EqualValues(t, 2, len(args))
80+
assert.EqualValues(t, []interface{}{1, 1}, args)
8181

8282
// from union
8383
sql, args, err = Select("sub.id").From("sub",
8484
Select("id").From("table1").Where(Eq{"a": 1}).
8585
Union("all", Select("id").From("table1").Where(Eq{"a": 2}))).Where(Eq{"b": 1}).ToSQL()
8686
assert.NoError(t, err)
8787
assert.EqualValues(t, "SELECT sub.id FROM ((SELECT id FROM table1 WHERE a=?) UNION ALL (SELECT id FROM table1 WHERE a=?)) sub WHERE b=?", sql)
88-
assert.EqualValues(t, 3, len(args))
88+
assert.EqualValues(t, []interface{}{1, 2, 1}, args)
8989

9090
// will raise error
9191
sql, args, err = Select("c").From("table1", Insert(Eq{"a": 1}).From("table1")).ToSQL()
@@ -98,29 +98,29 @@ func TestBuilder_Limit(t *testing.T) {
9898
sql, args, err := Dialect(ORACLE).Select("a", "b", "c").From("table1").OrderBy("a ASC").
9999
Limit(5, 10).ToSQL()
100100
assert.NoError(t, err)
101-
assert.EqualValues(t, "SELECT a,b,c FROM (SELECT a,b,c,RN FROM (SELECT a,b,c,ROWNUM RN FROM table1 ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
102-
assert.EqualValues(t, 2, len(args))
101+
assert.EqualValues(t, "SELECT * FROM (SELECT * FROM (SELECT a,b,c,ROWNUM RN FROM table1 ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
102+
assert.EqualValues(t, []interface{}{15, 10}, args)
103103

104104
// simple with join -- OracleSQL style
105105
sql, args, err = Dialect(ORACLE).Select("a", "b", "c").From("table1 t1").
106106
InnerJoin("table2 t2", "t1.id = t2.ref_id").OrderBy("a ASC").Limit(5, 10).ToSQL()
107107
assert.NoError(t, err)
108-
assert.EqualValues(t, "SELECT a,b,c FROM (SELECT a,b,c,RN FROM (SELECT a,b,c,ROWNUM RN FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.ref_id ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
109-
assert.EqualValues(t, 2, len(args))
108+
assert.EqualValues(t, "SELECT * FROM (SELECT * FROM (SELECT a,b,c,ROWNUM RN FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.ref_id ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
109+
assert.EqualValues(t, []interface{}{15, 10}, args)
110110

111111
// simple -- OracleSQL style
112112
sql, args, err = Dialect(ORACLE).Select("a", "b", "c").From("table1").
113113
OrderBy("a ASC").Limit(5).ToSQL()
114114
assert.NoError(t, err)
115115
assert.EqualValues(t, "SELECT a,b,c FROM (SELECT a,b,c,ROWNUM RN FROM table1 ORDER BY a ASC) at WHERE at.ROWNUM<=?", sql)
116-
assert.EqualValues(t, 1, len(args))
116+
assert.EqualValues(t, []interface{}{5}, args)
117117

118118
// simple with where -- OracleSQL style
119119
sql, args, err = Dialect(ORACLE).Select("a", "b", "c").From("table1").Where(Eq{"f1": "v1", "f2": "v2"}).
120120
OrderBy("a ASC").Limit(5, 10).ToSQL()
121121
assert.NoError(t, err)
122-
assert.EqualValues(t, "SELECT a,b,c FROM (SELECT a,b,c,RN FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE f1=? AND f2=? ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
123-
assert.EqualValues(t, 4, len(args))
122+
assert.EqualValues(t, "SELECT * FROM (SELECT * FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE f1=? AND f2=? ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?", sql)
123+
assert.EqualValues(t, []interface{}{"v1", "v2", 15, 10}, args)
124124

125125
// simple -- MySQL/SQLite/PostgreSQL style
126126
sql, args, err = Dialect(MYSQL).Select("a", "b", "c").From("table1").OrderBy("a ASC").
@@ -141,36 +141,30 @@ func TestBuilder_Limit(t *testing.T) {
141141
Where(Eq{"f1": "v1", "f2": "v2"}).OrderBy("a ASC").Limit(5, 10).ToSQL()
142142
assert.NoError(t, err)
143143
assert.EqualValues(t, "SELECT a,b,c FROM table1 WHERE f1=? AND f2=? ORDER BY a ASC LIMIT 5 OFFSET 10", sql)
144-
assert.EqualValues(t, 2, len(args))
144+
assert.EqualValues(t, []interface{}{"v1", "v2"}, args)
145145

146146
// simple -- MsSQL style
147-
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").PK("id").From("table1").
148-
OrderBy("a ASC").Limit(5, 10).ToSQL()
147+
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").From("table1").
148+
OrderBy("a ASC").Limit(5).ToSQL()
149149
assert.NoError(t, err)
150-
assert.EqualValues(t, "SELECT TOP 5 a,b,c FROM (SELECT TOP 15 a,b,c,id FROM (SELECT a,b,c,id FROM table1 ORDER BY a ASC)) WHERE id NOT IN (SELECT TOP 15 a,b,c,id FROM (SELECT a,b,c,id FROM table1 ORDER BY a ASC))", sql)
150+
assert.EqualValues(t, "SELECT TOP 5 a,b,c FROM (SELECT a,b,c FROM table1 ORDER BY a ASC) at", sql)
151151
assert.EqualValues(t, 0, len(args))
152152

153153
// simple with where -- MsSQL style
154-
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").PK("id").From("table1").
154+
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").From("table1").
155155
Where(Eq{"a": "3"}).OrderBy("a ASC").Limit(5, 10).ToSQL()
156156
assert.NoError(t, err)
157-
assert.EqualValues(t, "SELECT TOP 5 a,b,c FROM (SELECT TOP 15 a,b,c,id FROM (SELECT a,b,c,id FROM table1 WHERE a=? ORDER BY a ASC)) WHERE id NOT IN (SELECT TOP 15 a,b,c,id FROM (SELECT a,b,c,id FROM table1 WHERE a=? ORDER BY a ASC))", sql)
158-
assert.EqualValues(t, 2, len(args))
159-
160-
// raise error
161-
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").From("table1").
162-
OrderBy("a ASC").Limit(5, 10).ToSQL()
163-
assert.Error(t, err)
157+
assert.EqualValues(t, "SELECT TOP 5 a,b,c,RN FROM (SELECT TOP 15 a,b,c,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN FROM table1 WHERE a=?) at WHERE at.RN>?", sql)
158+
assert.EqualValues(t, []interface{}{"3", 5}, args)
164159

165160
// union with limit -- OracleSQL style
166161
sql, args, err = Dialect(ORACLE).Select("a", "b", "c").From("table1").
167162
Where(Eq{"a": 1}).OrderBy("a ASC").Limit(5, 10).Union("ALL",
168163
Select("a", "b", "c").From("table1").Where(Eq{"a": 2}).OrderBy("a DESC").Limit(10)).
169164
Limit(3).ToSQL()
170165
assert.NoError(t, err)
171-
assert.EqualValues(t, "SELECT * FROM ((SELECT a,b,c FROM (SELECT a,b,c,RN FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE a=? ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?) UNION ALL (SELECT a,b,c FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE a=? ORDER BY a DESC) at WHERE at.ROWNUM<=?)) at WHERE at.ROWNUM<=?", sql)
172-
assert.EqualValues(t, 6, len(args))
173-
assert.EqualValues(t, "[1 15 10 2 10 3]", fmt.Sprintf("%v", args))
166+
assert.EqualValues(t, "SELECT * FROM ((SELECT * FROM (SELECT * FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE a=? ORDER BY a ASC) at WHERE at.ROWNUM<=?) att WHERE att.RN>?) UNION ALL (SELECT a,b,c FROM (SELECT a,b,c,ROWNUM RN FROM table1 WHERE a=? ORDER BY a DESC) at WHERE at.ROWNUM<=?)) at WHERE at.ROWNUM<=?", sql)
167+
assert.EqualValues(t, []interface{}{1, 15, 10, 2, 10, 3}, args)
174168

175169
// union -- MySQL/SQLite/PostgreSQL style
176170
sql, args, err = Dialect(MYSQL).Select("a", "b", "c").From("table1").Where(Eq{"a": 1}).
@@ -179,14 +173,14 @@ func TestBuilder_Limit(t *testing.T) {
179173
Limit(5, 10).ToSQL()
180174
assert.NoError(t, err)
181175
assert.EqualValues(t, "(SELECT a,b,c FROM table1 WHERE a=? ORDER BY a ASC LIMIT 5 OFFSET 9) UNION ALL (SELECT a,b,c FROM table1 WHERE a=? ORDER BY a DESC LIMIT 10) LIMIT 5 OFFSET 10", sql)
182-
assert.EqualValues(t, 2, len(args))
176+
assert.EqualValues(t, []interface{}{1, 2}, args)
183177

184178
// union with limit -- MsSQL style
185179
sql, args, err = Dialect(MSSQL).Select("a", "b", "c").From("table1").
186-
PK("id1").Where(Eq{"a": 1}).OrderBy("a ASC").Limit(5, 6).Union("ALL",
187-
Select("a", "b").From("table1").Where(Eq{"b": 2}).OrderBy("a DESC").Limit(10)).
180+
Where(Eq{"a": 1}).OrderBy("a ASC").Limit(5, 6).Union("ALL",
181+
Select("a", "b", "c").From("table1").Where(Eq{"b": 2}).OrderBy("a DESC").Limit(10)).
188182
OrderBy("b DESC").Limit(7).ToSQL()
189183
assert.NoError(t, err)
190-
assert.EqualValues(t, "SELECT TOP 7 * FROM ((SELECT TOP 5 a,b,c FROM (SELECT TOP 11 a,b,c,id1 FROM (SELECT a,b,c,id1 FROM table1 WHERE a=? ORDER BY a ASC)) WHERE id1 NOT IN (SELECT TOP 11 a,b,c,id1 FROM (SELECT a,b,c,id1 FROM table1 WHERE a=? ORDER BY a ASC))) UNION ALL (SELECT TOP 10 a,b FROM (SELECT a,b FROM table1 WHERE b=? ORDER BY a DESC)))", sql)
191-
assert.EqualValues(t, 3, len(args))
184+
assert.EqualValues(t, "SELECT TOP 7 * FROM ((SELECT TOP 5 a,b,c,RN FROM (SELECT TOP 11 a,b,c,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN FROM table1 WHERE a=?) at WHERE at.RN>?) UNION ALL (SELECT TOP 10 a,b,c FROM (SELECT a,b,c FROM table1 WHERE b=? ORDER BY a DESC) at)) at", sql)
185+
assert.EqualValues(t, []interface{}{1, 5, 2}, args)
192186
}

builder_union_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func TestBuilder_Union(t *testing.T) {
1818
Union("", Select("*").From("t2").Where(Eq{"status": "3"})).
1919
ToSQL()
2020
assert.NoError(t, err)
21-
assert.EqualValues(t, 4, len(args))
21+
assert.EqualValues(t, []interface{}{"1", "2", "3", "3"}, args)
2222
fmt.Println(sql, args)
2323

2424
// will raise error

0 commit comments

Comments
 (0)