Skip to content

Commit

Permalink
Make Args and Exps easier to use, support In with Args or Exps
Browse files Browse the repository at this point in the history
  • Loading branch information
hlubek committed May 2, 2023
1 parent b566912 commit cb6b42e
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 12 deletions.
26 changes: 21 additions & 5 deletions builder/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,28 @@ func (a argExp) WriteSQL(sb *SQLBuilder) {
sb.WriteString(p)
}

type Expressions []Exp

func (e Expressions) IsExp() {}

func (e Expressions) WriteSQL(sb *SQLBuilder) {
sb.WriteRune('(')
for i, exp := range e {
if i > 0 {
sb.WriteRune(',')
}
exp.WriteSQL(sb)
}
sb.WriteRune(')')
}

func (e Expressions) isSelectOrExpressions() {}

// Args creates argument expressions for the given arguments.
func Args(argument any, rest ...any) []Exp {
exps := make([]Exp, 1+len(rest))
exps[0] = Arg(argument)
for i, arg := range rest {
exps[i+1] = Arg(arg)
func Args[T any](arguments ...T) Expressions {
exps := make([]Exp, len(arguments))
for i, arg := range arguments {
exps[i] = Arg(arg)
}
return exps
}
Expand Down
10 changes: 10 additions & 0 deletions builder/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ func cloneSlice[T any](dst *[]T, src []T, additionalCapacity int) {
*dst = make([]T, len(src), len(src)+additionalCapacity)
copy(*dst, src)
}

func nonNil(exps []Exp) []Exp {
result := make([]Exp, 0, len(exps))
for _, exp := range exps {
if exp != nil {
result = append(result, exp)
}
}
return result
}
6 changes: 4 additions & 2 deletions builder/op.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,18 @@ func (u unaryExp) WriteSQL(sb *SQLBuilder) {

// --- Junction expressions

// And builds an AND expression of non-nil expressions.
func And(exps ...Exp) Exp {
return junctionExp{
exps: exps,
exps: nonNil(exps),
op: "AND",
}
}

// Or builds an OR expression of non-nil expressions.
func Or(exps ...Exp) Exp {
return junctionExp{
exps: exps,
exps: nonNil(exps),
op: "OR",
}
}
Expand Down
9 changes: 8 additions & 1 deletion insert_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,14 @@ func TestInsertBuilder(t *testing.T) {
q := qrb.
InsertInto(qrb.N("films")).
ColumnNames("code", "date_prod", "did", "kind", "length", "title").
Values(qrb.Args("UA502", "1971-07-13", 105, "Comedy", "82 minutes", "Bananas")...)
Values(
qrb.Arg("UA502"),
qrb.Arg("1971-07-13"),
qrb.Arg(105),
qrb.Arg("Comedy"),
qrb.Arg("82 minutes"),
qrb.Arg("Bananas"),
)

testhelper.AssertSQLWriterEquals(
t,
Expand Down
8 changes: 4 additions & 4 deletions root.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ func Arg(argument any) builder.ExpBase {
return builder.Arg(argument)
}

// Args creates argument expressions for the given arguments.
func Args(argument any, rest ...any) []builder.Exp {
return builder.Args(argument, rest...)
// Args creates argument expressions for the given arguments (of the same type).
func Args[T any](arguments ...T) builder.Expressions {
return builder.Args(arguments...)
}

// Bind creates an expression that represents an argument that will be bound to a placeholder with the given value.
Expand Down Expand Up @@ -144,7 +144,7 @@ func Interval(s string) builder.Exp {

// Exps returns a slice of expressions, just for syntactic sugar.
// TODO We could use this as a way to express a scalar list of expressions e.g. for IN by using a custom slice type
func Exps(exps ...builder.Exp) []builder.Exp {
func Exps(exps ...builder.Exp) builder.Expressions {
return exps
}

Expand Down
36 changes: 36 additions & 0 deletions select_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,42 @@ func TestSelectBuilder_Where(t *testing.T) {
q,
)
})

t.Run("where in args", func(t *testing.T) {
ids := []int{1, 2, 3}

q := qrb.Select(qrb.N("username")).
From(qrb.N("accounts")).
Where(qrb.N("id").In(qrb.Args(ids...)))

testhelper.AssertSQLWriterEquals(
t,
`
SELECT username
FROM accounts
WHERE id IN ($1, $2, $3)
`,
[]any{1, 2, 3},
q,
)
})

t.Run("where in exps", func(t *testing.T) {
q := qrb.Select(qrb.N("username")).
From(qrb.N("accounts")).
Where(qrb.N("id").In(qrb.Exps(qrb.Int(42), qrb.String("abc"))))

testhelper.AssertSQLWriterEquals(
t,
`
SELECT username
FROM accounts
WHERE id IN (42, 'abc')
`,
nil,
q,
)
})
}

func TestSelectBuilder_GroupBy(t *testing.T) {
Expand Down

0 comments on commit cb6b42e

Please sign in to comment.