Skip to content

Commit

Permalink
Support subquery in FROM operator
Browse files Browse the repository at this point in the history
  • Loading branch information
umisama committed Sep 19, 2014
1 parent 8d49cce commit fffd5d6
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 6 deletions.
26 changes: 26 additions & 0 deletions from.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package squirrel

import (
"fmt"
"github.com/lann/builder"
)

type fromPart part

func newFromPart(pred interface{}) Sqlizer {
return &fromPart{pred: pred, args: []interface{}{}}
}

func (p fromPart) ToSql() (sql string, args []interface{}, err error) {
switch pred := p.pred.(type) {
case SelectBuilder:
entity := builder.GetStruct(pred).(selectData)
sql, args, err = entity.toSql(true)
case string:
sql = pred
args = []interface{}{}
default:
err = fmt.Errorf("expected string or SelectBuilder, not %T", pred)
}
return
}
43 changes: 43 additions & 0 deletions from_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package squirrel

import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
)

func TestFromPartsAppendToSqlWithString(t *testing.T) {
parts := []Sqlizer{
newFromPart("TABLE_NAME"),
}

sql := &bytes.Buffer{}
args, _ := appendToSql(parts, sql, "", []interface{}{})
assert.Equal(t, "TABLE_NAME", sql.String())
assert.Equal(t, []interface{}{}, args)
}

func TestFromPartAppendToSqlWithSelect(t *testing.T) {
parts := []Sqlizer{
newFromPart(Select("*").Where(Eq{"col":"value"})),
}

sql := &bytes.Buffer{}
args, _ := appendToSql(parts, sql, "", []interface{}{})
assert.Equal(t, "( SELECT * WHERE col = ? )", sql.String())
assert.Equal(t, []interface{}{"value"}, args)
}

func TestFromPartAppendToSqlErr(t *testing.T) {
parts := []Sqlizer{
newFromPart(1),
}

_, err := appendToSql(parts, &bytes.Buffer{}, "", []interface{}{})
assert.Error(t, err)
}

func TestFromPartToSqlErr(t *testing.T) {
_, _, err := newFromPart(1).ToSql()
assert.Error(t, err)
}
32 changes: 26 additions & 6 deletions select.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type selectData struct {
Prefixes exprs
Distinct bool
Columns []Sqlizer
From string
FromPart Sqlizer
Joins []string
WhereParts []Sqlizer
GroupBys []string
Expand Down Expand Up @@ -51,13 +51,21 @@ func (d *selectData) QueryRow() RowScanner {
}

func (d *selectData) ToSql() (sqlStr string, args []interface{}, err error) {
return d.toSql(false)
}

func (d *selectData) toSql(subquery bool) (sqlStr string, args []interface{}, err error) {
if len(d.Columns) == 0 {
err = fmt.Errorf("select statements must have at least one result column")
return
}

sql := &bytes.Buffer{}

if subquery {
sql.WriteString("( ")
}

if len(d.Prefixes) > 0 {
args, _ = d.Prefixes.AppendToSql(sql, " ", args)
sql.WriteString(" ")
Expand All @@ -76,9 +84,12 @@ func (d *selectData) ToSql() (sqlStr string, args []interface{}, err error) {
}
}

if len(d.From) > 0 {
if d.FromPart != nil {
sql.WriteString(" FROM ")
sql.WriteString(d.From)
args, err = appendToSql([]Sqlizer{d.FromPart}, sql, ", ", args)
if err != nil {
return
}
}

if len(d.Joins) > 0 {
Expand Down Expand Up @@ -127,7 +138,16 @@ func (d *selectData) ToSql() (sqlStr string, args []interface{}, err error) {
args, _ = d.Suffixes.AppendToSql(sql, " ", args)
}

sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String())
if subquery {
sql.WriteString(" )")
}

if subquery {
sqlStr = sql.String()
} else {
sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String())
}

return
}

Expand Down Expand Up @@ -214,8 +234,8 @@ func (b SelectBuilder) Column(column interface{}, args ...interface{}) SelectBui
}

// From sets the FROM clause of the query.
func (b SelectBuilder) From(from string) SelectBuilder {
return builder.Set(b, "From", from).(SelectBuilder)
func (b SelectBuilder) From(from interface{}) SelectBuilder {
return builder.Set(b, "FromPart", newFromPart(from)).(SelectBuilder)
}

// JoinClause adds a join clause to the query.
Expand Down

0 comments on commit fffd5d6

Please sign in to comment.