Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,20 +199,26 @@ func ToTables(values []interface{}) []stmt.Table {
}

// ToFrom takes an empty interfaces and returns a From instance.
func ToFrom(arg interface{}) stmt.From {
func ToFrom(args ...interface{}) stmt.From {
from := stmt.From{}

switch value := arg.(type) {
case string:
from = stmt.NewFrom(stmt.NewTable(value), false)
case stmt.From:
from = value
case stmt.Table:
from = stmt.NewFrom(value, false)
default:
panic(fmt.Sprintf("loukoum: cannot use %T as from clause", arg))
tables := make([]stmt.Statement, len(args))
for i := range args {
switch value := args[i].(type) {
case string:
tables[i] = stmt.NewTable(value)
case stmt.From:
from = value
case stmt.Table:
tables[i] = value
case stmt.Raw:
tables[i] = value
default:
panic(fmt.Sprintf("loukoum: cannot use %T as from clause", args[i]))
}
}

from = stmt.NewFrom(tables)
if from.IsEmpty() {
panic("loukoum: given from clause is undefined")
}
Expand Down
14 changes: 2 additions & 12 deletions builder/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,13 @@ func NewDelete() Delete {
}

// From sets the FROM clause of the query.
func (b Delete) From(arg interface{}) Delete {
func (b Delete) From(arg ...interface{}) Delete {
if !b.query.From.IsEmpty() {
panic("loukoum: delete builder has from clause already defined")
}

only := b.query.From.Only
b.query.From = ToFrom(arg)
if only {
b.query.From.Only = only
}

return b
}
b.query.From = ToFrom(arg...)

// Only adds a ONLY clause to the query.
func (b Delete) Only() Delete {
b.query.From.Only = true
return b
}

Expand Down
5 changes: 2 additions & 3 deletions builder/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ func TestDelete(t *testing.T) {
{
Name: "Only",
Builders: []builder.Builder{
loukoum.Delete("table").Only(),
loukoum.Delete(loukoum.Table("table")).Only(),
loukoum.Delete(loukoum.Table("table").Only()),
},
SameQuery: "DELETE FROM ONLY \"table\"",
},
Expand All @@ -33,7 +32,7 @@ func TestDelete(t *testing.T) {
},
{
Name: "As only",
Builder: loukoum.Delete(loukoum.Table("table").As("foobar")).Only(),
Builder: loukoum.Delete(loukoum.Table("table").As("foobar").Only()),
SameQuery: "DELETE FROM ONLY \"table\" AS \"foobar\"",
},
})
Expand Down
4 changes: 2 additions & 2 deletions builder/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ func (b Select) Columns(args ...interface{}) Select {
}

// From sets the FROM clause of the query.
func (b Select) From(arg interface{}) Select {
func (b Select) From(arg ...interface{}) Select {
if !b.query.From.IsEmpty() {
panic("loukoum: select builder has from clause already defined")
}

b.query.From = ToFrom(arg)
b.query.From = ToFrom(arg...)

return b
}
Expand Down
20 changes: 20 additions & 0 deletions builder/select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,26 @@ func TestSelect_From(t *testing.T) {
Builder: loukoum.Select("a").From(loukoum.Table("foobar").As("example")),
SameQuery: "SELECT \"a\" FROM \"foobar\" AS \"example\"",
},
{
Name: "Multiple",
Builder: loukoum.Select("a").From(loukoum.Table("foobar").As("example"), loukoum.Table("foobar").As("example2")),
SameQuery: "SELECT \"a\" FROM \"foobar\" AS \"example\", \"foobar\" AS \"example2\"",
},
{
Name: "Multiple strings",
Builder: loukoum.Select("a").From("example", "example2"),
SameQuery: "SELECT \"a\" FROM \"example\", \"example2\"",
},
{
Name: "Multiple raws",
Builder: loukoum.Select("a").From(loukoum.Raw("example1 ex1"), loukoum.Raw("example2 ex2")),
SameQuery: "SELECT \"a\" FROM example1 ex1, example2 ex2",
},
{
Name: "Multiple raw",
Builder: loukoum.Select("a").From(loukoum.Raw("example1 ex1, example2 ex2")),
SameQuery: "SELECT \"a\" FROM example1 ex1, example2 ex2",
},
})
}

Expand Down
23 changes: 12 additions & 11 deletions stmt/from.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,33 @@ import (

// From is a FROM clause.
type From struct {
Only bool
Table Table
Tables []Statement
}

// NewFrom returns a new From instance.
func NewFrom(table Table, only bool) From {
func NewFrom(tables []Statement) From {
return From{
Only: only,
Table: table,
Tables: tables,
}
}

// Write exposes statement as a SQL query.
func (from From) Write(ctx types.Context) {
ctx.Write(token.From.String())
if from.Only {
ctx.Write(" ")
ctx.Write(token.Only.String())
}
ctx.Write(" ")
from.Table.Write(ctx)

for i := range from.Tables {
from.Tables[i].Write(ctx)

if i != len(from.Tables)-1 {
ctx.Write(", ")
}
}
}

// IsEmpty returns true if statement is undefined.
func (from From) IsEmpty() bool {
return from.Table.IsEmpty()
return len(from.Tables) == 0
}

// Ensure that From is a Statement
Expand Down
13 changes: 12 additions & 1 deletion stmt/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ import (

// Table is a table identifier.
type Table struct {
Name string
Alias string
Name string
only bool
}

// NewTable returns a new Table instance.
func NewTable(name string) Table {
return NewTableAlias(name, "")
}

// Only sets ONLY clause to the table.
func (table Table) Only() Table {
table.only = true
return table
}

// NewTableAlias returns a new Table instance with an alias.
func NewTableAlias(name, alias string) Table {
return Table{
Expand All @@ -32,6 +39,10 @@ func (table Table) As(alias string) Table {

// Write exposes statement as a SQL query.
func (table Table) Write(ctx types.Context) {
if table.only {
ctx.Write(token.Only.String())
ctx.Write(" ")
}
ctx.Write(quote(table.Name))
if table.Alias != "" {
ctx.Write(" ")
Expand Down