Skip to content

Commit

Permalink
Dir supports text parsing and encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
mitranim committed May 27, 2022
1 parent e5f4a72 commit 848c74e
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 37 deletions.
5 changes: 5 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ func Example_composition() {

## Changelog

### v0.6.3

* `Dir` supports text parsing and encoding.
* Minor breaking change: `Bui.Arg` now appends both an argument and a parameter.

### v0.6.2

`CommaAppender` and `ArrayAppender` are now parametrized on the element type.
Expand Down
30 changes: 21 additions & 9 deletions sqlb_bui.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,32 @@ func (self *Bui) CatchExprs(vals ...Expr) (err error) {
return
}

// Appends an ordinal parameter such as "$1", space-separated from previous text
// if necessary.
func (self *Bui) Param(val OrdinalParam) {
/*
Appends an ordinal parameter such as "$1", space-separated from previous text if
necessary. Requires caution: does not verify the existence of the corresponding
argument.
*/
func (self *Bui) OrphanParam(val OrdinalParam) {
self.Space()
self.Text = val.Append(self.Text)
}

// Appends an arg to the inner slice of args, returning the corresponding
// ordinal parameter that should be appended to the text.
func (self *Bui) Arg(val any) OrdinalParam {
/*
Appends an arg to the inner slice of args, returning the corresponding ordinal
parameter that should be appended to the text. Requires caution: does not
append the corresponding ordinal parameter.
*/
func (self *Bui) OrphanArg(val any) OrdinalParam {
self.Args = append(self.Args, val)
return OrdinalParam(len(self.Args))
}

/*
Appends an argument to `.Args` and a corresponding ordinal parameter to
`.Text`.
*/
func (self *Bui) Arg(val any) { self.OrphanParam(self.OrphanArg(val)) }

/*
Appends an arbitrary value. If the value implements `Expr`, this calls
`(*Bui).Expr`, which may append to the text and args in arbitrary ways.
Expand All @@ -151,13 +163,13 @@ func (self *Bui) Any(val any) {
if val == nil {
self.Str(`null`)
} else {
self.Param(self.Arg(val))
self.Arg(val)
}
Makes some assumptions, and might be the wrong place for such a special case.
*/

self.Param(self.Arg(val))
self.Arg(val)
}

/*
Expand All @@ -171,5 +183,5 @@ func (self *Bui) SubAny(val any) {
self.SubExpr(impl)
return
}
self.Param(self.Arg(val))
self.Arg(val)
}
12 changes: 6 additions & 6 deletions sqlb_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1501,12 +1501,12 @@ func appendOrdinal(bui *Bui, args ArgDict, tracker *argTracker, key OrdinalParam

ord, ok := tracker.GotOrdinal(key)
if ok {
bui.Param(ord)
bui.OrphanParam(ord)
return
}

ord = bui.Arg(arg)
bui.Param(ord)
ord = bui.OrphanArg(arg)
bui.OrphanParam(ord)
tracker.SetOrdinal(key, ord)
}

Expand All @@ -1526,12 +1526,12 @@ func appendNamed(bui *Bui, args ArgDict, tracker *argTracker, key NamedParam) {

ord, ok := tracker.GotNamed(key)
if ok {
bui.Param(ord)
bui.OrphanParam(ord)
return
}

ord = bui.Arg(arg)
bui.Param(ord)
ord = bui.OrphanArg(arg)
bui.OrphanParam(ord)
tracker.SetNamed(key, ord)
}

Expand Down
4 changes: 2 additions & 2 deletions sqlb_jel.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ func (self *Jel) decodeCast(bui *Bui, name string, args []json.RawMessage) {
val := r.New(field.Field.Type)
try(json.Unmarshal(args[0], val.Interface()))

bui.Param(bui.Arg(val.Elem().Interface()))
bui.Arg(val.Elem().Interface())
}

func (self *Jel) decodeString(bui *Bui, input []byte) {
Expand All @@ -405,5 +405,5 @@ func (self *Jel) decodeString(bui *Bui, input []byte) {
func (self *Jel) decodeAny(bui *Bui, input []byte) {
var val any
try(json.Unmarshal(input, &val))
bui.Param(bui.Arg(val))
bui.Arg(val)
}
53 changes: 49 additions & 4 deletions sqlb_misc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package sqlb

import r "reflect"
import (
"fmt"
r "reflect"
)

const (
TagNameDb = `db`
Expand Down Expand Up @@ -108,25 +111,67 @@ func (self Dir) Append(text []byte) []byte {
// Implement `fmt.Stringer` for debug purposes.
func (self Dir) String() string {
switch self {
default:
return ``
case DirAsc:
return `asc`
case DirDesc:
return `desc`
}
}

// Parses from a string, which must be either empty, "asc" or "desc".
func (self *Dir) Parse(src string) error {
switch src {
case ``:
*self = DirNone
return nil
case `asc`:
*self = DirAsc
return nil
case `desc`:
*self = DirDesc
return nil
default:
return ``
return ErrInvalidInput{Err{
`parsing order direction`,
fmt.Errorf(`unrecognized direction %q`, src),
}}
}
}

// Implement `encoding.TextUnmarshaler`.
func (self Dir) MarshalText() ([]byte, error) {
return stringToBytesUnsafe(self.String()), nil
}

// Implement `encoding.TextMarshaler`.
func (self *Dir) UnmarshalText(src []byte) error {
return self.Parse(bytesToMutableString(src))
}

// Implement `json.Marshaler`.
func (self Dir) MarshalJSON() ([]byte, error) {
switch self {
default:
return stringToBytesUnsafe(`null`), nil
case DirAsc:
return stringToBytesUnsafe(`"asc"`), nil
case DirDesc:
return stringToBytesUnsafe(`"desc"`), nil
}
}

// Implement `fmt.GoStringer` for debug purposes. Returns valid Go code
// representing this value.
func (self Dir) GoString() string {
switch self {
default:
return `sqlb.DirNone`
case DirAsc:
return `sqlb.DirAsc`
case DirDesc:
return `sqlb.DirDesc`
default:
return `sqlb.DirNone`
}
}

Expand Down
16 changes: 3 additions & 13 deletions sqlb_text.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ func AppenderString(val Appender) string {
}

// Variant of `String` that panics on error.
func TryString(val any) string {
out, err := String(val)
try(err)
return out
}
func TryString(val any) string { return try1(String(val)) }

/*
Missing feature of the standard library: return a string representation of an
Expand Down Expand Up @@ -120,11 +116,7 @@ func String(src any) (string, error) {
}

// Variant of `Append` that panics on error.
func TryAppend(buf []byte, src any) []byte {
out, err := Append(buf, src)
try(err)
return out
}
func TryAppend(buf []byte, src any) []byte { return try1(Append(buf, src)) }

/*
Missing feature of the standard library: append the text representation of an
Expand Down Expand Up @@ -221,9 +213,7 @@ func Append(buf []byte, src any) ([]byte, error) {

// Variant of `AppendWith` that panics on error.
func TryAppendWith(buf *[]byte, delim string, val any) bool {
out, err := AppendWith(buf, delim, val)
try(err)
return out
return try1(AppendWith(buf, delim, val))
}

/*
Expand Down
9 changes: 6 additions & 3 deletions sqlb_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ func try(err error) {
}
}

func try1[A any](val A, err error) A {
try(err)
return val
}

// Must be deferred.
func rec(ptr *error) {
val := recover()
Expand Down Expand Up @@ -218,9 +223,7 @@ func norm(val any) any {

valuer, _ := val.(driver.Valuer)
if valuer != nil {
val, err := valuer.Value()
try(err)
return val
return try1(valuer.Value())
}

return val
Expand Down
47 changes: 47 additions & 0 deletions t_ord_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sqlb

import (
"encoding/json"
r "reflect"
"testing"
)
Expand Down Expand Up @@ -335,3 +336,49 @@ func Test_ParseOpt_Filter(t *testing.T) {
)
})
}

func TestDir(t *testing.T) {
t.Run(`String`, func(t *testing.T) {
eq(t, ``, DirNone.String())
eq(t, `asc`, DirAsc.String())
eq(t, `desc`, DirDesc.String())
})

t.Run(`Parse`, func(t *testing.T) {
test := func(exp Dir, src string) {
t.Helper()
var tar Dir
try(tar.Parse(src))
eq(t, exp, tar)
}

test(DirNone, ``)
test(DirAsc, `asc`)
test(DirDesc, `desc`)
})

t.Run(`MarshalJSON`, func(t *testing.T) {
test := func(exp string, src Dir) {
t.Helper()
eq(t, exp, string(try1(json.Marshal(src))))
}

test(`null`, DirNone)
test(`"asc"`, DirAsc)
test(`"desc"`, DirDesc)
})

t.Run(`UnmarshalJSON`, func(t *testing.T) {
test := func(exp Dir, src string) {
t.Helper()
var tar Dir
try(json.Unmarshal([]byte(src), &tar))
eq(t, exp, tar)
}

test(DirNone, `null`)
test(DirNone, `""`)
test(DirAsc, `"asc"`)
test(DirDesc, `"desc"`)
})
}

0 comments on commit 848c74e

Please sign in to comment.