Skip to content

Commit

Permalink
Support % without verb (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristaloleg authored Mar 20, 2024
1 parent 299d3cd commit 438e2ae
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 10 deletions.
3 changes: 3 additions & 0 deletions builq.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ var (
// errUnsupportedVerb when %X is found and X isn't supported.
errUnsupportedVerb = errors.New("unsupported verb")

// errLonelyVerb when % is found without a verb.
errLonelyVerb = errors.New("lonely verb")

// errIncorrectVerb is passed like `%+`.
errIncorrectVerb = errors.New("incorrect verb")

Expand Down
11 changes: 9 additions & 2 deletions builq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ func TestBuilder(t *testing.T) {
test("bad verb", errUnsupportedVerb, "SELECT * FROM %+ slice", 1)
test("incorrect verb 1", errIncorrectVerb, "SELECT * FROM %+", 1)
test("incorrect verb 2", errIncorrectVerb, "SELECT * FROM %#", 1)
test("too few arguments", errTooFewArguments, "SELECT * FROM % super")
test("lonely verb", errLonelyVerb, "SELECT * FROM % super")
test("lonely verb", errLonelyVerb, "SELECT foo FROM bar%")
test("too few arguments", errTooFewArguments, "SELECT foo FROM bar%d")
test("too few arguments", errTooFewArguments, "SELECT * FROM %s")
test("too few arguments", errTooFewArguments, "SELECT * FROM %$")
test("too few arguments", errTooFewArguments, "SELECT * FROM %+?")
test("too many arguments", errTooManyArguments, "SELECT * FROM %s", "users", "users")
test("unsupported verb", errUnsupportedVerb, "SELECT * FROM %v", "users")
test("mixed placeholders", errMixedPlaceholders, "WHERE foo = %$ AND bar = %?", 1, 2)
Expand Down Expand Up @@ -75,8 +79,11 @@ func FuzzBuilder(f *testing.F) {
if errors.Is(err, errTooFewArguments) ||
errors.Is(err, errTooManyArguments) ||
errors.Is(err, errUnsupportedVerb) ||
errors.Is(err, errLonelyVerb) ||
errors.Is(err, errIncorrectVerb) ||
errors.Is(err, errMixedPlaceholders) ||
errors.Is(err, errNonSliceArgument) ||
errors.Is(err, errMixedPlaceholders) {
errors.Is(err, errNonNumericArg) {
return
}
t.Fatalf("unexpected error: %v", err)
Expand Down
21 changes: 21 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,27 @@ func ExampleColumns() {
// [42 right now just testing]
}

func Example_queryWithPercent() {
var q builq.OnelineBuilder
q.Addf("SELECT foo FROM bar WHERE shard = %? %% 10", 42)

query, args, err := q.Build()
if err != nil {
panic(err)
}

fmt.Println("query:")
fmt.Println(query)
fmt.Println("args:")
fmt.Println(args)

// Output:
// query:
// SELECT foo FROM bar WHERE shard = ? % 10
// args:
// [42]
}

func Example_query1() {
cols := builq.Columns{"foo, bar"}

Expand Down
33 changes: 25 additions & 8 deletions write.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

func (b *Builder) write(sb *strings.Builder, resArgs *[]any, s string, args ...any) error {
for argID := 0; ; argID++ {
n := strings.IndexByte(s, '%')
if n == -1 {
idx := strings.IndexByte(s, '%')
if idx == -1 {
if argID != len(args) {
b.setErr(errTooManyArguments)
}
Expand All @@ -21,17 +21,20 @@ func (b *Builder) write(sb *strings.Builder, resArgs *[]any, s string, args ...a
return nil
}

sb.WriteString(s[:n])
sb.WriteString(s[:idx])

if argID >= len(args) {
return errTooFewArguments
s = s[idx+1:] // skip '%'
if len(s) == 0 {
return errLonelyVerb
}

arg := args[argID]

s = s[n+1:] // skip '%'
switch verb := s[0]; verb {
case '$', '?', 's', 'd':
if argID >= len(args) {
return errTooFewArguments
}

arg := args[argID]
s = s[1:]
b.writeArg(sb, resArgs, verb, arg)

Expand All @@ -45,6 +48,11 @@ func (b *Builder) write(sb *strings.Builder, resArgs *[]any, s string, args ...a

switch verb := s[0]; verb {
case '$', '?':
if argID >= len(args) {
return errTooFewArguments
}

arg := args[argID]
s = s[1:]

if isBatch {
Expand All @@ -55,6 +63,15 @@ func (b *Builder) write(sb *strings.Builder, resArgs *[]any, s string, args ...a
default:
b.setErr(errUnsupportedVerb)
}

case '%':
argID--
s = s[1:]
sb.WriteByte('%')

case ' ':
b.setErr(errLonelyVerb)

default:
b.setErr(errUnsupportedVerb)
}
Expand Down

0 comments on commit 438e2ae

Please sign in to comment.