diff --git a/strmangle/strmangle.go b/strmangle/strmangle.go index 28e7672..c9d3e56 100644 --- a/strmangle/strmangle.go +++ b/strmangle/strmangle.go @@ -258,6 +258,24 @@ func WhereClause(cols []string, start int) string { return strings.Join(ret, " AND ") } +// InClause generates SQL that could go inside an "IN ()" statement +// $1, $2, $3 +func InClause(start, count int) string { + if start == 0 { + panic("0 is not a valid start number for inClause") + } + + buf := &bytes.Buffer{} + for i := 0; i < count; i++ { + if i > 0 { + buf.WriteByte(',') + } + fmt.Fprintf(buf, "$%d", i+start) + } + + return buf.String() +} + // DriverUsesLastInsertID returns whether the database driver supports the // sql.Result interface. func DriverUsesLastInsertID(driverName string) bool { diff --git a/strmangle/strmangle_test.go b/strmangle/strmangle_test.go index 67655e1..39165fa 100644 --- a/strmangle/strmangle_test.go +++ b/strmangle/strmangle_test.go @@ -334,6 +334,29 @@ func TestWherePrimaryKeyPanic(t *testing.T) { WhereClause(nil, 0) } +func TestInClause(t *testing.T) { + t.Parallel() + + if str := InClause(1, 2); str != `$1,$2` { + t.Error("wrong output:", str) + } + if str := InClause(2, 2); str != `$2,$3` { + t.Error("wrong output:", str) + } +} + +func TestInClausePanic(t *testing.T) { + t.Parallel() + + defer func() { + if recover() == nil { + t.Error("did not panic") + } + }() + + InClause(0, 0) +} + func TestSubstring(t *testing.T) { t.Parallel()