1511 lines
38 KiB
Go
1511 lines
38 KiB
Go
|
package sqlbuilder
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"git.hexq.cn/tiglog/mydb"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`)
|
||
|
)
|
||
|
|
||
|
func TestSelect(t *testing.T) {
|
||
|
|
||
|
b := &sqlBuilder{t: newTemplateWithUtils(&testTemplate)}
|
||
|
assert := assert.New(t)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DATE()`,
|
||
|
b.Select(mydb.Func("DATE")).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DATE() FOR UPDATE`,
|
||
|
b.Select(mydb.Func("DATE")).Amend(func(query string) string {
|
||
|
return query + " FOR UPDATE"
|
||
|
}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist"`,
|
||
|
b.SelectFrom("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT "bcolor" FROM "artist"`,
|
||
|
b.Select().Distinct("bcolor").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT * FROM "artist"`,
|
||
|
b.Select().Distinct().From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON("col1"), "col2" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON("col1")`), "col2").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON("col1") AS col1, "col2" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON("col1") AS col1`)).Distinct("col2").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON("col1") AS col1, "col2", "col3", "col4", "col5" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON("col1") AS col1`)).Columns("col2", "col3").Distinct("col4", "col5").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON(SELECT foo FROM bar) col1, "col2", "col3", "col4", "col5" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON(?) col1`, mydb.Raw(`SELECT foo FROM bar`))).Columns("col2", "col3").Distinct("col4", "col5").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q0 := b.Select("foo").From("bar")
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON (SELECT "foo" FROM "bar") col1, "col2", "col3", "col4", "col5" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON ? col1`, q0)).Columns("col2", "col3").Distinct("col4", "col5").From("artist").String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON (SELECT foo FROM bar, SELECT baz from qux) col1, "col2", "col3", "col4", "col5" FROM "artist"`,
|
||
|
b.Select().Distinct(mydb.Raw(`ON ? col1`, []interface{}{mydb.Raw(`SELECT foo FROM bar`), mydb.Raw(`SELECT baz from qux`)})).Columns("col2", "col3").Distinct("col4", "col5").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Select().
|
||
|
Distinct(mydb.Raw(`ON ? col1`, []*mydb.RawExpr{mydb.Raw(`SELECT foo FROM bar WHERE id = ?`, 1), mydb.Raw(`SELECT baz from qux WHERE id = 2`)})).
|
||
|
Columns("col2", "col3").
|
||
|
Distinct("col4", "col5").From("artist").
|
||
|
Where("id", 3)
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON (SELECT foo FROM bar WHERE id = $1, SELECT baz from qux WHERE id = 2) col1, "col2", "col3", "col4", "col5" FROM "artist" WHERE ("id" = $2)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 3},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
rawCase := mydb.Raw("CASE WHEN id IN ? THEN 0 ELSE 1 END", []int{1000, 2000})
|
||
|
sel := b.SelectFrom("artist").OrderBy(rawCase)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY CASE WHEN id IN ($1, $2) THEN 0 ELSE 1 END`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1000, 2000},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
rawCase := mydb.Raw("CASE WHEN id IN ? THEN 0 ELSE 1 END", []int{1000})
|
||
|
sel := b.SelectFrom("artist").OrderBy(rawCase)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY CASE WHEN id IN ($1) THEN 0 ELSE 1 END`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1000},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
rawCase := mydb.Raw("CASE WHEN id IN ? THEN 0 ELSE 1 END", []int{})
|
||
|
sel := b.SelectFrom("artist").OrderBy(rawCase)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY CASE WHEN id IN (NULL) THEN 0 ELSE 1 END`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
rawCase := mydb.Raw("CASE WHEN id IN (NULL) THEN 0 ELSE 1 END")
|
||
|
sel := b.SelectFrom("artist").OrderBy(rawCase)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY CASE WHEN id IN (NULL) THEN 0 ELSE 1 END`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
rawCase.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
rawCase := mydb.Raw("CASE WHEN id IN (?, ?) THEN 0 ELSE 1 END", 1000, 2000)
|
||
|
sel := b.SelectFrom("artist").OrderBy(rawCase)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY CASE WHEN id IN ($1, $2) THEN 0 ELSE 1 END`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1000, 2000},
|
||
|
rawCase.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.Select(mydb.Func("DISTINCT", "name")).From("artist")
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT($1) FROM "artist"`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"name"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (1 = $1)`,
|
||
|
b.Select().From("artist").Where(mydb.Cond{1: 1}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (1 = ANY($1))`,
|
||
|
b.Select().From("artist").Where(mydb.Cond{1: mydb.Func("ANY", "name")}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (1 = ANY(column))`,
|
||
|
b.Select().From("artist").Where(mydb.Cond{1: mydb.Func("ANY", mydb.Raw("column"))}).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Where(mydb.Cond{"id NOT IN": []int{0, -1}})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" NOT IN ($1, $2))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{0, -1},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Where(mydb.Cond{"id NOT IN": []int{-1}})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" NOT IN ($1))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{-1},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" IN ($1, $2))`,
|
||
|
b.Select().From("artist").Where(mydb.Cond{"id IN": []int{0, -1}}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (("id" = $1 OR "id" = $2 OR "id" = $3))`,
|
||
|
b.Select().From("artist").Where(
|
||
|
mydb.Or(
|
||
|
mydb.Cond{"id": 1},
|
||
|
mydb.Cond{"id": 2},
|
||
|
mydb.Cond{"id": 3},
|
||
|
),
|
||
|
).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Where(
|
||
|
mydb.Or(
|
||
|
mydb.And(mydb.Cond{"a": 1}, mydb.Cond{"b": 2}, mydb.Cond{"c": 3}),
|
||
|
mydb.And(mydb.Cond{"d": 1}, mydb.Cond{"e": 2}, mydb.Cond{"f": 3}),
|
||
|
),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ((("a" = $1 AND "b" = $2 AND "c" = $3) OR ("d" = $4 AND "e" = $5 AND "f" = $6)))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2, 3, 1, 2, 3},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Where(
|
||
|
mydb.Or(
|
||
|
mydb.And(mydb.Cond{"a": 1, "b": 2, "c": 3}),
|
||
|
mydb.And(mydb.Cond{"f": 6, "e": 5, "d": 4}),
|
||
|
),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ((("a" = $1 AND "b" = $2 AND "c" = $3) OR ("d" = $4 AND "e" = $5 AND "f" = $6)))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2, 3, 4, 5, 6},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ((("id" = $1 OR "id" = $2 OR "id" IS NULL) OR ("name" = $3 OR "name" = $4)))`,
|
||
|
b.Select().From("artist").Where(
|
||
|
mydb.Or(
|
||
|
mydb.Or(
|
||
|
mydb.Cond{"id": 1},
|
||
|
mydb.Cond{"id": 2},
|
||
|
mydb.Cond{"id IS": nil},
|
||
|
),
|
||
|
mydb.Or(
|
||
|
mydb.Cond{"name": "John"},
|
||
|
mydb.Cond{"name": "Peter"},
|
||
|
),
|
||
|
),
|
||
|
).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ((("id" = $1 OR "id" = $2 OR "id" = $3 OR "id" = $4) AND ("name" = $5 AND "last_name" = $6) AND "age" > $7))`,
|
||
|
b.Select().From("artist").Where(
|
||
|
mydb.And(
|
||
|
mydb.Or(
|
||
|
mydb.Cond{"id": 1},
|
||
|
mydb.Cond{"id": 2},
|
||
|
mydb.Cond{"id": 3},
|
||
|
).Or(
|
||
|
mydb.Cond{"id": 4},
|
||
|
),
|
||
|
mydb.Or(),
|
||
|
mydb.And(
|
||
|
mydb.Cond{"name": "John"},
|
||
|
mydb.Cond{"last_name": "Smith"},
|
||
|
),
|
||
|
mydb.And(),
|
||
|
).And(
|
||
|
mydb.Cond{"age >": "20"},
|
||
|
),
|
||
|
).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist"`,
|
||
|
b.Select().From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "name" DESC`,
|
||
|
b.Select().From("artist").OrderBy("name DESC").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
sel := b.Select().From("artist").OrderBy(mydb.Raw("id = ?", 1), "name DESC")
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY id = $1 , "name" DESC`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.Select().From("artist").OrderBy(mydb.Func("RAND"))
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY RAND()`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY RAND()`,
|
||
|
b.Select().From("artist").OrderBy(mydb.Raw("RAND()")).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "name" DESC`,
|
||
|
b.Select().From("artist").OrderBy("-name").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "name" ASC`,
|
||
|
b.Select().From("artist").OrderBy("name").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "name" ASC`,
|
||
|
b.Select().From("artist").OrderBy("name ASC").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" OFFSET 5`,
|
||
|
b.Select().From("artist").Limit(-1).Offset(5).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" LIMIT 1 OFFSET 5`,
|
||
|
b.Select().From("artist").Limit(1).Offset(5).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "id" FROM "artist"`,
|
||
|
b.Select("id").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "id", "name" FROM "artist"`,
|
||
|
b.Select("id", "name").From("artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("name" = $1)`,
|
||
|
b.SelectFrom("artist").Where("name", "Haruki").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (name LIKE $1)`,
|
||
|
b.SelectFrom("artist").Where("name LIKE ?", `%F%`).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "id" FROM "artist" WHERE (name LIKE $1 OR name LIKE $2)`,
|
||
|
b.Select("id").From("artist").Where(`name LIKE ? OR name LIKE ?`, `%Miya%`, `F%`).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" > $1)`,
|
||
|
b.SelectFrom("artist").Where("id >", 2).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (id <= 2 AND name != $1)`,
|
||
|
b.SelectFrom("artist").Where("id <= 2 AND name != ?", "A").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" IN ($1, $2, $3, $4))`,
|
||
|
b.SelectFrom("artist").Where("id IN", []int{1, 9, 8, 7}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (id IN ($1, $2, $3, $4) AND foo = $5 AND bar IN ($6, $7, $8))`,
|
||
|
b.SelectFrom("artist").Where("id IN ? AND foo = ? AND bar IN ?", []int{1, 9, 8, 7}, 28, []int{1, 2, 3}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE (name IS NOT NULL)`,
|
||
|
b.SelectFrom("artist").Where("name IS NOT NULL").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a", "publication" AS "p" WHERE (p.author_id = a.id) LIMIT 1`,
|
||
|
b.Select().From("artist a", "publication as p").Where("p.author_id = a.id").Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "id" FROM "artist" NATURAL JOIN "publication"`,
|
||
|
b.Select("id").From("artist").Join("publication").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.author_id = a.id) LIMIT 1`,
|
||
|
b.SelectFrom("artist a").Join("publication p").On("p.author_id = a.id").Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.author_id = a.id) WHERE ("a"."id" = $1) LIMIT 1`,
|
||
|
b.SelectFrom("artist a").Join("publication p").On("p.author_id = a.id").Where("a.id", 2).Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" JOIN "publication" AS "p" ON (p.author_id = a.id) WHERE (a.id = 2) LIMIT 1`,
|
||
|
b.SelectFrom("artist").Join("publication p").On("p.author_id = a.id").Where("a.id = 2").Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.title LIKE $1 OR p.title LIKE $2) WHERE (a.id = $3) LIMIT 1`,
|
||
|
b.SelectFrom("artist a").Join("publication p").On("p.title LIKE ? OR p.title LIKE ?", "%Totoro%", "%Robot%").Where("a.id = ?", 2).Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.title LIKE $1 OR p.title LIKE $2) WHERE (a.id = $3 AND a.sub_id = $4) LIMIT 1`,
|
||
|
b.SelectFrom("artist a").Join("publication p").On("p.title LIKE ? OR p.title LIKE ?", "%Totoro%", "%Robot%").Where("a.id = ?", 2).Where("a.sub_id = ?", 3).Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.title LIKE $1 OR p.title LIKE $2) WHERE (a.id = $3 AND a.id = $4) LIMIT 1`,
|
||
|
b.SelectFrom("artist a").Join("publication p").On("p.title LIKE ? OR p.title LIKE ?", "%Totoro%", "%Robot%").Where("a.id = ?", 2).And("a.id = ?", 3).Limit(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" AS "a" LEFT JOIN "publication" AS "p1" ON (p1.id = a.id) RIGHT JOIN "publication" AS "p2" ON (p2.id = a.id)`,
|
||
|
b.SelectFrom("artist a").
|
||
|
LeftJoin("publication p1").On("p1.id = a.id").
|
||
|
RightJoin("publication p2").On("p2.id = a.id").
|
||
|
String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" CROSS JOIN "publication"`,
|
||
|
b.SelectFrom("artist").CrossJoin("publication").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" JOIN "publication" USING ("id")`,
|
||
|
b.SelectFrom("artist").Join("publication").Using("id").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" IS NULL)`,
|
||
|
b.SelectFrom("artist").Where(mydb.Cond{"id": nil}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" IN (NULL))`,
|
||
|
b.SelectFrom("artist").Where(mydb.Cond{"id": []int64{}}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" IN ($1))`,
|
||
|
b.SelectFrom("artist").Where(mydb.Cond{"id": []int64{0}}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT COUNT(*) AS total FROM "user" AS "u" JOIN (SELECT DISTINCT user_id FROM user_profile) AS up ON (u.id = up.user_id)`,
|
||
|
b.Select(mydb.Raw(`COUNT(*) AS total`)).From("user u").Join(mydb.Raw("(SELECT DISTINCT user_id FROM user_profile) AS up")).On("u.id = up.user_id").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q0 := b.Select("user_id").Distinct().From("user_profile")
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT COUNT(*) AS total FROM "user" AS "u" JOIN (SELECT DISTINCT "user_id" FROM "user_profile") AS up ON (u.id = up.user_id)`,
|
||
|
b.Select(mydb.Raw(`COUNT(*) AS total`)).From("user u").Join(mydb.Raw("? AS up", q0)).On("u.id = up.user_id").String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q0 := b.Select("user_id").Distinct().From("user_profile").Where("t", []int{1, 2, 4, 5})
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2, 4, 5},
|
||
|
q0.Arguments(),
|
||
|
)
|
||
|
|
||
|
q1 := b.Select(mydb.Raw(`COUNT(*) AS total`)).From("user u").Join(mydb.Raw("? AS up", q0)).On("u.id = up.user_id AND foo = ?", 8)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT COUNT(*) AS total FROM "user" AS "u" JOIN (SELECT DISTINCT "user_id" FROM "user_profile" WHERE ("t" IN ($1, $2, $3, $4))) AS up ON (u.id = up.user_id AND foo = $5)`,
|
||
|
q1.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2, 4, 5, 8},
|
||
|
q1.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DATE()`,
|
||
|
b.Select(mydb.Raw("DATE()")).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
sel := b.Select(mydb.Raw("CONCAT(?, ?)", "foo", "bar"))
|
||
|
assert.Equal(
|
||
|
`SELECT CONCAT($1, $2)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"foo", "bar"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{"bar": mydb.Raw("1")})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = 1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{mydb.Raw("1"): 1})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE (1 = $1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{mydb.Raw("1"): mydb.Raw("1")})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE (1 = 1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Raw("1 = 1"))
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE (1 = 1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{"bar": 1}, mydb.Cond{"baz": mydb.Raw("CONCAT(?, ?)", "foo", "bar")})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND "baz" = CONCAT($2, $3))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, "foo", "bar"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{"bar": 1}, mydb.Raw("? = ANY(col)", "name"))
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND $2 = ANY(col))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, "name"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{"bar": 1}, mydb.Cond{"name": mydb.Raw("ANY(col)")})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND "name" = ANY(col))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{"bar": 1}, mydb.Cond{mydb.Raw("CONCAT(?, ?)", "a", "b"): mydb.Raw("ANY(col)")})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND CONCAT($2, $3) = ANY(col))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, "a", "b"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where("bar", 2).And(mydb.Cond{"baz": 1})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND "baz" = $2)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{2, 1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").And(mydb.Cond{"bar": 1})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where("bar", 2).And(mydb.Cond{"baz": 1})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND "baz" = $2)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{2, 1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where("bar", 2).Where(mydb.Cond{"baz": 1})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("bar" = $1 AND "baz" = $2)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{2, 1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Raw("bar->'baz' = ?", true))
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE (bar->'baz' = $1)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{true},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where(mydb.Cond{}).And(mydb.Cond{})
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo"`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where("bar = 1").And(mydb.Or(
|
||
|
mydb.Raw("fieldA ILIKE ?", `%a%`),
|
||
|
mydb.Raw("fieldB ILIKE ?", `%b%`),
|
||
|
))
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE (bar = 1 AND (fieldA ILIKE $1 OR fieldB ILIKE $2))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{`%a%`, `%b%`},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sel := b.SelectFrom("foo").Where("group_id", 1).And("user_id", 2)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "foo" WHERE ("group_id" = $1 AND "user_id" = $2)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
s := `SUM(CASE WHEN foo in ? THEN 1 ELSE 0 END) AS _sum`
|
||
|
sel := b.Select("c1").Columns(mydb.Raw(s, []int{5, 4, 3, 2})).From("foo").Where("bar = ?", 1)
|
||
|
assert.Equal(
|
||
|
`SELECT "c1", SUM(CASE WHEN foo in ($1, $2, $3, $4) THEN 1 ELSE 0 END) AS _sum FROM "foo" WHERE (bar = $5)`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{5, 4, 3, 2, 1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
s := `SUM(CASE WHEN foo in ? THEN 1 ELSE 0 END) AS _sum`
|
||
|
sel := b.Select("c1").Columns(mydb.Raw(s, []int{5, 4, 3, 2})).From("foo").Where("bar = ?", 1)
|
||
|
sel2 := b.SelectFrom(sel).As("subquery").Where(mydb.Cond{"foo": "bar"}).OrderBy("subquery.seq")
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM (SELECT "c1", SUM(CASE WHEN foo in ($1, $2, $3, $4) THEN 1 ELSE 0 END) AS _sum FROM "foo" WHERE (bar = $5)) AS "subquery" WHERE ("foo" = $6) ORDER BY "subquery"."seq" ASC`,
|
||
|
sel2.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{5, 4, 3, 2, 1, "bar"},
|
||
|
sel2.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
series := b.Select(
|
||
|
mydb.Raw("start + interval ? - interval '1s' AS end", "1 day"),
|
||
|
).From(
|
||
|
b.Select(
|
||
|
mydb.Raw("generate_series(?::timestamp, ?::timestamp, ?::interval) AS start", 1, 2, 3),
|
||
|
),
|
||
|
).As("series")
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{"1 day", 1, 2, 3},
|
||
|
series.Arguments(),
|
||
|
)
|
||
|
|
||
|
distinct := b.Select().Distinct(
|
||
|
mydb.Raw(`ON(dt.email) SUBSTRING(email,(POSITION('@' in email) + 1),252) AS email_domain`),
|
||
|
"dt.event_type AS event_type",
|
||
|
mydb.Raw("count(dt.*) AS count"),
|
||
|
"intervals.start AS start",
|
||
|
"intervals.end AS start",
|
||
|
).From("email_events AS dt").
|
||
|
RightJoin("intervals").On("dt.ts BETWEEN intervals.stast AND intervals.END AND dt.hub_id = ? AND dt.object_id = ?", 67, 68).
|
||
|
GroupBy("email_domain", "event_type", "start").
|
||
|
OrderBy("email", "start", "event_type")
|
||
|
|
||
|
sq, args := Preprocess(
|
||
|
`WITH intervals AS ? ?`,
|
||
|
[]interface{}{
|
||
|
series,
|
||
|
distinct,
|
||
|
},
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
stripWhitespace(`
|
||
|
WITH intervals AS (SELECT start + interval ? - interval '1s' AS end FROM (SELECT generate_series(?::timestamp, ?::timestamp, ?::interval) AS start) AS "series")
|
||
|
(SELECT DISTINCT ON(dt.email) SUBSTRING(email,(POSITION('@' in email) + 1),252) AS email_domain, "dt"."event_type" AS "event_type", count(dt.*) AS count, "intervals"."start" AS "start", "intervals"."end" AS "start"
|
||
|
FROM "email_events" AS "dt"
|
||
|
RIGHT JOIN "intervals" ON (dt.ts BETWEEN intervals.stast AND intervals.END AND dt.hub_id = ? AND dt.object_id = ?)
|
||
|
GROUP BY "email_domain", "event_type", "start"
|
||
|
ORDER BY "email" ASC, "start" ASC, "event_type" ASC)`),
|
||
|
stripWhitespace(sq),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{"1 day", 1, 2, 3, 67, 68},
|
||
|
args,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sq := b.
|
||
|
Select("user_id").
|
||
|
From("user_access").
|
||
|
Where(mydb.Cond{"hub_id": 3})
|
||
|
|
||
|
// Don't reassign
|
||
|
_ = sq.And(mydb.Cond{"role": []int{1, 2}})
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "user_id" FROM "user_access" WHERE ("hub_id" = $1)`,
|
||
|
sq.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{3},
|
||
|
sq.Arguments(),
|
||
|
)
|
||
|
|
||
|
// Reassign
|
||
|
sq = sq.And(mydb.Cond{"role": []int{1, 2}})
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT "user_id" FROM "user_access" WHERE ("hub_id" = $1 AND "role" IN ($2, $3))`,
|
||
|
sq.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{3, 1, 2},
|
||
|
sq.Arguments(),
|
||
|
)
|
||
|
|
||
|
cond := mydb.Or(
|
||
|
mydb.Raw("a.id IN ?", sq),
|
||
|
)
|
||
|
|
||
|
cond = cond.Or(mydb.Cond{"ml.mailing_list_id": []int{4, 5, 6}})
|
||
|
|
||
|
sel := b.
|
||
|
Select(mydb.Raw("DISTINCT ON(a.id) a.id"), mydb.Raw("COALESCE(NULLIF(ml.name,''), a.name) as name"), "a.email").
|
||
|
From("mailing_list_recipients ml").
|
||
|
FullJoin("accounts a").On("a.id = ml.user_id").
|
||
|
Where(cond)
|
||
|
|
||
|
search := "word"
|
||
|
sel = sel.And(mydb.Or(
|
||
|
mydb.Raw("COALESCE(NULLIF(ml.name,''), a.name) ILIKE ?", fmt.Sprintf("%%%s%%", search)),
|
||
|
mydb.Cond{"a.email ILIKE": fmt.Sprintf("%%%s%%", search)},
|
||
|
))
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT DISTINCT ON(a.id) a.id, COALESCE(NULLIF(ml.name,''), a.name) as name, "a"."email" FROM "mailing_list_recipients" AS "ml" FULL JOIN "accounts" AS "a" ON (a.id = ml.user_id) WHERE ((a.id IN (SELECT "user_id" FROM "user_access" WHERE ("hub_id" = $1 AND "role" IN ($2, $3))) OR "ml"."mailing_list_id" IN ($4, $5, $6)) AND (COALESCE(NULLIF(ml.name,''), a.name) ILIKE $7 OR "a"."email" ILIKE $8))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{3, 1, 2, 4, 5, 6, `%word%`, `%word%`},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
sel := b.Select(mydb.Func("FOO", "A", "B", 1)).From("accounts").Where(mydb.Cond{"time": mydb.Func("FUNCTION", "20170103", "YYYYMMDD", 1, "E")})
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT FOO($1, $2, $3) FROM "accounts" WHERE ("time" = FUNCTION($4, $5, $6, $7))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"A", "B", 1, "20170103", "YYYYMMDD", 1, "E"},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
|
||
|
sel := b.Select(mydb.Func("FOO", "A", "B", 1)).From("accounts").Where(mydb.Cond{mydb.Func("FUNCTION", "20170103", "YYYYMMDD", 1, "E"): mydb.Func("FOO", 1)})
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT FOO($1, $2, $3) FROM "accounts" WHERE (FUNCTION($4, $5, $6, $7) = FOO($8))`,
|
||
|
sel.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"A", "B", 1, "20170103", "YYYYMMDD", 1, "E", 1},
|
||
|
sel.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert(t *testing.T) {
|
||
|
b := &sqlBuilder{t: newTemplateWithUtils(&testTemplate)}
|
||
|
assert := assert.New(t)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" VALUES ($1, $2), ($3, $4), ($5, $6)`,
|
||
|
b.InsertInto("artist").
|
||
|
Values(10, "Ryuichi Sakamoto").
|
||
|
Values(11, "Alondra de la Parra").
|
||
|
Values(12, "Haruki Murakami").
|
||
|
String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2)`,
|
||
|
b.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2) RETURNING "id"`,
|
||
|
b.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).Returning("id").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2) RETURNING "id"`,
|
||
|
b.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).Amend(func(query string) string {
|
||
|
return query + ` RETURNING "id"`
|
||
|
}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2)`,
|
||
|
b.InsertInto("artist").Values(map[string]interface{}{"name": "Chavela Vargas", "id": 12}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2)`,
|
||
|
b.InsertInto("artist").Values(struct {
|
||
|
ID int `db:"id"`
|
||
|
Name string `db:"name"`
|
||
|
}{12, "Chavela Vargas"}).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
type artistStruct struct {
|
||
|
ID int `db:"id,omitempty"`
|
||
|
Name string `db:"name,omitempty"`
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, $2), ($3, $4), ($5, $6)`,
|
||
|
b.InsertInto("artist").
|
||
|
Values(artistStruct{12, "Chavela Vargas"}).
|
||
|
Values(artistStruct{13, "Alondra de la Parra"}).
|
||
|
Values(artistStruct{14, "Haruki Murakami"}).
|
||
|
String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
type artistStruct struct {
|
||
|
ID int `db:"id,omitempty"`
|
||
|
Name string `db:"name,omitempty"`
|
||
|
}
|
||
|
|
||
|
q := b.InsertInto("artist").
|
||
|
Values(artistStruct{0, ""}).
|
||
|
Values(artistStruct{12, "Chavela Vargas"}).
|
||
|
Values(artistStruct{0, "Alondra de la Parra"}).
|
||
|
Values(artistStruct{14, ""}).
|
||
|
Values(artistStruct{0, ""})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES (DEFAULT, DEFAULT), ($1, $2), (DEFAULT, $3), ($4, DEFAULT), (DEFAULT, DEFAULT)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{12, "Chavela Vargas", "Alondra de la Parra", 14},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
type artistStruct struct {
|
||
|
ID int `db:"id,omitempty"`
|
||
|
Name string `db:"name,omitempty"`
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("name") VALUES ($1)`,
|
||
|
b.InsertInto("artist").
|
||
|
Values(artistStruct{Name: "Chavela Vargas"}).
|
||
|
String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id") VALUES ($1)`,
|
||
|
b.InsertInto("artist").
|
||
|
Values(artistStruct{ID: 1}).
|
||
|
String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
type artistStruct struct {
|
||
|
ID int `db:"id,omitempty"`
|
||
|
Name string `db:"name,omitempty"`
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.InsertInto("artist").Values(artistStruct{Name: "Chavela Vargas"})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("name") VALUES ($1)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"Chavela Vargas"},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.InsertInto("artist").Values(artistStruct{Name: "Chavela Vargas"}).Values(artistStruct{Name: "Alondra de la Parra"})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES (DEFAULT, $1), (DEFAULT, $2)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{"Chavela Vargas", "Alondra de la Parra"},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.InsertInto("artist").Values(artistStruct{ID: 1})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id") VALUES ($1)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{1},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.InsertInto("artist").Values(artistStruct{ID: 1}).Values(artistStruct{ID: 2})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES ($1, DEFAULT), ($2, DEFAULT)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{1, 2},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
{
|
||
|
intRef := func(i int) *int {
|
||
|
if i == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return &i
|
||
|
}
|
||
|
|
||
|
strRef := func(s string) *string {
|
||
|
if s == "" {
|
||
|
return nil
|
||
|
}
|
||
|
return &s
|
||
|
}
|
||
|
|
||
|
type artistStruct struct {
|
||
|
ID *int `db:"id,omitempty"`
|
||
|
Name *string `db:"name,omitempty"`
|
||
|
}
|
||
|
|
||
|
q := b.InsertInto("artist").
|
||
|
Values(artistStruct{intRef(0), strRef("")}).
|
||
|
Values(artistStruct{intRef(12), strRef("Chavela Vargas")}).
|
||
|
Values(artistStruct{intRef(0), strRef("Alondra de la Parra")}).
|
||
|
Values(artistStruct{intRef(14), strRef("")}).
|
||
|
Values(artistStruct{intRef(0), strRef("")})
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("id", "name") VALUES (DEFAULT, DEFAULT), ($1, $2), (DEFAULT, $3), ($4, DEFAULT), (DEFAULT, DEFAULT)`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{intRef(12), strRef("Chavela Vargas"), strRef("Alondra de la Parra"), intRef(14)},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" ("name", "id") VALUES ($1, $2)`,
|
||
|
b.InsertInto("artist").Columns("name", "id").Values("Chavela Vargas", 12).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`INSERT INTO "artist" VALUES (default)`,
|
||
|
b.InsertInto("artist").String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func TestUpdate(t *testing.T) {
|
||
|
b := &sqlBuilder{t: newTemplateWithUtils(&testTemplate)}
|
||
|
assert := assert.New(t)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1`,
|
||
|
b.Update("artist").Set("name", "Artist").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 RETURNING "name"`,
|
||
|
b.Update("artist").Set("name", "Artist").Amend(func(query string) string {
|
||
|
return query + ` RETURNING "name"`
|
||
|
}).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
idSlice := []int64{8, 7, 6}
|
||
|
q := b.Update("artist").Set(mydb.Cond{"some_column": 10}).Where(mydb.Cond{"id": 1}, mydb.Cond{"another_val": idSlice})
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IN ($3, $4, $5))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{10, 1, int64(8), int64(7), int64(6)},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
idSlice := []int64{}
|
||
|
q := b.Update("artist").Set(mydb.Cond{"some_column": 10}).Where(mydb.Cond{"id": 1}, mydb.Cond{"another_val": idSlice})
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IN (NULL))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{10, 1},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
idSlice := []int64{}
|
||
|
q := b.Update("artist").Where(mydb.Cond{"id": 1}, mydb.Cond{"another_val": idSlice}).Set(mydb.Cond{"some_column": 10})
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IN (NULL))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{10, 1},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
|
||
|
b.Update("artist").Set("name = ?", "Artist").Where("id <", 5).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
|
||
|
b.Update("artist").Set(map[string]string{"name": "Artist"}).Where(mydb.Cond{"id <": 5}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
|
||
|
b.Update("artist").Set(struct {
|
||
|
Nombre string `db:"name"`
|
||
|
}{"Artist"}).Where(mydb.Cond{"id <": 5}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
|
||
|
b.Update("artist").Where(mydb.Cond{"id <": 5}).Set(struct {
|
||
|
Nombre string `db:"name"`
|
||
|
}{"Artist"}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1, "last_name" = $2 WHERE ("id" < $3)`,
|
||
|
b.Update("artist").Set(struct {
|
||
|
Nombre string `db:"name"`
|
||
|
}{"Artist"}).Set(map[string]string{"last_name": "Foo"}).Where(mydb.Cond{"id <": 5}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "artist" SET "name" = $1 || ' ' || $2 || id, "id" = id + $3 WHERE (id > $4)`,
|
||
|
b.Update("artist").Set(
|
||
|
"name = ? || ' ' || ? || id", "Artist", "#",
|
||
|
"id = id + ?", 10,
|
||
|
).Where("id > ?", 0).String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Update("posts").Set("column = ?", "foo")
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "posts" SET "column" = $1`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{"foo"},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Update("posts").Set(mydb.Raw("column = ?", "foo"))
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "posts" SET column = $1`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{"foo"},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Update("posts").Set("foo = bar")
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}(nil),
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "posts" SET "foo" = bar`,
|
||
|
q.String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Update("posts").Set(
|
||
|
mydb.Cond{"tags": mydb.Raw("array_remove(tags, ?)", "foo")},
|
||
|
).Where(mydb.Raw("hub_id = ? AND ? = ANY(tags) AND ? = ANY(tags)", 1, "bar", "baz"))
|
||
|
|
||
|
assert.Equal(
|
||
|
`UPDATE "posts" SET "tags" = array_remove(tags, $1) WHERE (hub_id = $2 AND $3 = ANY(tags) AND $4 = ANY(tags))`,
|
||
|
q.String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
[]interface{}{"foo", 1, "bar", "baz"},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDelete(t *testing.T) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
assert := assert.New(t)
|
||
|
|
||
|
assert.Equal(
|
||
|
`DELETE FROM "artist" WHERE (name = $1)`,
|
||
|
bt.DeleteFrom("artist").Where("name = ?", "Chavela Vargas").String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`DELETE FROM "artist" WHERE (name = $1) RETURNING 1`,
|
||
|
bt.DeleteFrom("artist").Where("name = ?", "Chavela Vargas").Amend(func(query string) string {
|
||
|
return fmt.Sprintf("%s RETURNING 1", query)
|
||
|
}).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`DELETE FROM "artist" WHERE (id > 5)`,
|
||
|
bt.DeleteFrom("artist").Where("id > 5").String(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func TestPaginate(t *testing.T) {
|
||
|
b := &sqlBuilder{t: newTemplateWithUtils(&testTemplate)}
|
||
|
assert := assert.New(t)
|
||
|
|
||
|
// Limit, offset
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" LIMIT 10`,
|
||
|
b.Select().From("artist").Paginate(10).Page(1).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" LIMIT 10 OFFSET 10`,
|
||
|
b.Select().From("artist").Paginate(10).Page(2).String(),
|
||
|
)
|
||
|
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" LIMIT 5 OFFSET 110`,
|
||
|
b.Select().From("artist").Paginate(5).Page(23).String(),
|
||
|
)
|
||
|
|
||
|
// Cursor
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "id" ASC LIMIT 10`,
|
||
|
b.Select().From("artist").Paginate(10).Cursor("id").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Paginate(10).Cursor("id").NextPage(3)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" > $1) ORDER BY "id" ASC LIMIT 10`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{3},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Paginate(10).Cursor("id").PrevPage(30)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM (SELECT * FROM "artist" WHERE ("id" < $1) ORDER BY "id" DESC LIMIT 10) AS p0 ORDER BY "id" ASC`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{30},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// Cursor reversed
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" ORDER BY "id" DESC LIMIT 10`,
|
||
|
b.Select().From("artist").Paginate(10).Cursor("-id").String(),
|
||
|
)
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Paginate(10).Cursor("-id").NextPage(3)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM "artist" WHERE ("id" < $1) ORDER BY "id" DESC LIMIT 10`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{3},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
q := b.Select().From("artist").Paginate(10).Cursor("-id").PrevPage(30)
|
||
|
assert.Equal(
|
||
|
`SELECT * FROM (SELECT * FROM "artist" WHERE ("id" > $1) ORDER BY "id" ASC LIMIT 10) AS p0 ORDER BY "id" DESC`,
|
||
|
q.String(),
|
||
|
)
|
||
|
assert.Equal(
|
||
|
[]interface{}{30},
|
||
|
q.Arguments(),
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkDelete1(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.DeleteFrom("artist").Where("name = ?", "Chavela Vargas").Limit(1).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkDelete2(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.DeleteFrom("artist").Where("id > 5").String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkInsert1(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.InsertInto("artist").Values(10, "Ryuichi Sakamoto").Values(11, "Alondra de la Parra").Values(12, "Haruki Murakami").String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkInsert2(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkInsert3(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).Returning("id").String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkInsert4(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.InsertInto("artist").Values(map[string]interface{}{"name": "Chavela Vargas", "id": 12}).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkInsert5(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.InsertInto("artist").Values(struct {
|
||
|
ID int `db:"id"`
|
||
|
Name string `db:"name"`
|
||
|
}{12, "Chavela Vargas"}).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkSelect1(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Select().From("artist").OrderBy("name DESC").String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkSelect2(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Select("id").From("artist").Where(`name LIKE ? OR name LIKE ?`, `%Miya%`, `F%`).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkSelect3(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Select().From("artist a", "publication as p").Where("p.author_id = a.id").Limit(1).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkSelect4(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.SelectFrom("artist").Join("publication p").On("p.author_id = a.id").Where("a.id = 2").Limit(1).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkSelect5(b *testing.B) {
|
||
|
t := WithTemplate(&testTemplate)
|
||
|
b.ResetTimer()
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = t.SelectFrom("artist a").
|
||
|
LeftJoin("publication p1").On("p1.id = a.id").
|
||
|
RightJoin("publication p2").On("p2.id = a.id").
|
||
|
String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUpdate1(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Update("artist").Set("name", "Artist").String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUpdate2(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Update("artist").Set("name = ?", "Artist").Where("id <", 5).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUpdate3(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Update("artist").Set(struct {
|
||
|
Nombre string `db:"name"`
|
||
|
}{"Artist"}).Set(map[string]string{"last_name": "Foo"}).Where(mydb.Cond{"id <": 5}).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUpdate4(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Update("artist").Set(map[string]string{"name": "Artist"}).Where(mydb.Cond{"id <": 5}).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUpdate5(b *testing.B) {
|
||
|
bt := WithTemplate(&testTemplate)
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
_ = bt.Update("artist").Set(
|
||
|
"name = ? || ' ' || ? || id", "Artist", "#",
|
||
|
"id = id + ?", 10,
|
||
|
).Where("id > ?", 0).String()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func stripWhitespace(in string) string {
|
||
|
q := reInvisibleChars.ReplaceAllString(in, ` `)
|
||
|
return strings.TrimSpace(q)
|
||
|
}
|