Skip to content

Commit b5aff2b

Browse files
authored
Merge pull request #656 from upper/allow-select-from-db-result
allow using db.Result as subquery
2 parents bb6a386 + 9709cdd commit b5aff2b

File tree

4 files changed

+61
-10
lines changed

4 files changed

+61
-10
lines changed

internal/sqladapter/result.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func (r *Result) Select(fields ...interface{}) db.Result {
213213

214214
// String satisfies fmt.Stringer
215215
func (r *Result) String() string {
216-
query, err := r.buildPaginator()
216+
query, err := r.Paginator()
217217
if err != nil {
218218
panic(err.Error())
219219
}
@@ -222,7 +222,7 @@ func (r *Result) String() string {
222222

223223
// All dumps all Results into a pointer to an slice of structs or maps.
224224
func (r *Result) All(dst interface{}) error {
225-
query, err := r.buildPaginator()
225+
query, err := r.Paginator()
226226
if err != nil {
227227
r.setErr(err)
228228
return err
@@ -235,7 +235,7 @@ func (r *Result) All(dst interface{}) error {
235235
// One fetches only one Result from the set.
236236
func (r *Result) One(dst interface{}) error {
237237
one := r.Limit(1).(*Result)
238-
query, err := one.buildPaginator()
238+
query, err := one.Paginator()
239239
if err != nil {
240240
r.setErr(err)
241241
return err
@@ -251,7 +251,7 @@ func (r *Result) Next(dst interface{}) bool {
251251
defer r.iterMu.Unlock()
252252

253253
if r.iter == nil {
254-
query, err := r.buildPaginator()
254+
query, err := r.Paginator()
255255
if err != nil {
256256
r.setErr(err)
257257
return false
@@ -309,7 +309,7 @@ func (r *Result) Update(values interface{}) error {
309309
}
310310

311311
func (r *Result) TotalPages() (uint, error) {
312-
query, err := r.buildPaginator()
312+
query, err := r.Paginator()
313313
if err != nil {
314314
r.setErr(err)
315315
return 0, err
@@ -325,7 +325,7 @@ func (r *Result) TotalPages() (uint, error) {
325325
}
326326

327327
func (r *Result) TotalEntries() (uint64, error) {
328-
query, err := r.buildPaginator()
328+
query, err := r.Paginator()
329329
if err != nil {
330330
r.setErr(err)
331331
return 0, err
@@ -391,7 +391,7 @@ func (r *Result) Count() (uint64, error) {
391391
return counter.Count, nil
392392
}
393393

394-
func (r *Result) buildPaginator() (db.Paginator, error) {
394+
func (r *Result) Paginator() (db.Paginator, error) {
395395
if err := r.Err(); err != nil {
396396
return nil, err
397397
}

internal/sqlbuilder/builder.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ var defaultMapOptions = MapOptions{
5151
IncludeNil: false,
5252
}
5353

54-
type compilable interface {
54+
type hasPaginator interface {
55+
Paginator() (db.Paginator, error)
56+
}
57+
58+
type isCompilable interface {
5559
Compile() (string, error)
5660
Arguments() []interface{}
5761
}
@@ -347,7 +351,17 @@ func columnFragments(columns []interface{}) ([]exql.Fragment, []interface{}, err
347351

348352
for i := range columns {
349353
switch v := columns[i].(type) {
350-
case compilable:
354+
case hasPaginator:
355+
p, err := v.Paginator()
356+
if err != nil {
357+
return nil, nil, err
358+
}
359+
360+
q, a := Preprocess(p.String(), p.Arguments())
361+
362+
f[i] = exql.RawValue("(" + q + ")")
363+
args = append(args, a...)
364+
case isCompilable:
351365
c, err := v.Compile()
352366
if err != nil {
353367
return nil, nil, err

internal/sqlbuilder/convert.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,13 @@ func preprocessFn(arg interface{}) (string, []interface{}) {
122122
switch t := arg.(type) {
123123
case *adapter.RawExpr:
124124
return Preprocess(t.Raw(), t.Arguments())
125-
case compilable:
125+
case hasPaginator:
126+
p, err := t.Paginator()
127+
if err == nil {
128+
return `(` + p.String() + `)`, p.Arguments()
129+
}
130+
panic(err.Error())
131+
case isCompilable:
126132
c, err := t.Compile()
127133
if err == nil {
128134
return `(` + c + `)`, t.Arguments()

internal/testsuite/sql_suite.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,3 +1898,34 @@ func (s *SQLTestSuite) Test_Issue565() {
18981898
s.Error(err)
18991899
s.Zero(result.Name)
19001900
}
1901+
1902+
func (s *SQLTestSuite) TestSelectFromSubquery() {
1903+
sess := s.Session()
1904+
1905+
{
1906+
var artists []artistType
1907+
q := sess.SQL().SelectFrom(
1908+
sess.SQL().SelectFrom("artist").Where(db.Cond{
1909+
"name": db.IsNotNull(),
1910+
}),
1911+
).As("_q")
1912+
err := q.All(&artists)
1913+
s.NoError(err)
1914+
1915+
s.NotZero(len(artists))
1916+
}
1917+
1918+
{
1919+
var artists []artistType
1920+
q := sess.SQL().SelectFrom(
1921+
sess.Collection("artist").Find(db.Cond{
1922+
"name": db.IsNotNull(),
1923+
}),
1924+
).As("_q")
1925+
err := q.All(&artists)
1926+
s.NoError(err)
1927+
1928+
s.NotZero(len(artists))
1929+
}
1930+
1931+
}

0 commit comments

Comments
 (0)