Skip to content

Commit

Permalink
Tweak appender
Browse files Browse the repository at this point in the history
  • Loading branch information
vmihailenco committed May 15, 2021
1 parent d76c1a5 commit 6a0262a
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 95 deletions.
29 changes: 24 additions & 5 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"reflect"
"strings"
"sync/atomic"

"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
Expand All @@ -18,20 +19,27 @@ const (
discardUnknownColumns internal.Flag = 1 << iota
)

type config struct{}
type DBStats struct {
Queries uint64
Errors uint64
}

type Config struct{}

type ConfigOption func(cfg *config)
type ConfigOption func(cfg *Config)

type DB struct {
*sql.DB
dialect schema.Dialect
features feature.Feature
cfg config
cfg Config

queryHooks []QueryHook

fmter sqlfmt.Formatter
flags internal.Flag

stats DBStats
}

func Open(sqldb *sql.DB, dialect schema.Dialect, opts ...ConfigOption) *DB {
Expand All @@ -49,6 +57,13 @@ func Open(sqldb *sql.DB, dialect schema.Dialect, opts ...ConfigOption) *DB {
return db
}

func (db *DB) Stats() DBStats {
return DBStats{
Queries: atomic.LoadUint64(&db.stats.Queries),
Errors: atomic.LoadUint64(&db.stats.Errors),
}
}

func (db *DB) DiscardUnknownColumns() {
db.flags = db.flags.Set(discardUnknownColumns)
}
Expand Down Expand Up @@ -141,12 +156,16 @@ func (db *DB) RegisterModel(models ...interface{}) {
db.dialect.Tables().Register(models...)
}

func (db *DB) WithArg(name string, value interface{}) *DB {
func (db *DB) WithNamedArg(name string, value interface{}) *DB {
clone := db.clone()
clone.fmter = clone.fmter.WithArg(name, value)
return clone
}

func (db *DB) NamedArg(name string) interface{} {
return db.fmter.Arg(name)
}

func (db *DB) clone() *DB {
clone := *db

Expand Down Expand Up @@ -202,7 +221,7 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
}

func (db *DB) format(query string, args []interface{}) string {
if len(args) == 0 || strings.IndexByte(query, '?') == -1 {
if len(args) == 0 && strings.IndexByte(query, '?') == -1 {
return query
}
return internal.String(db.fmter.FormatQuery(nil, query, args...))
Expand Down
2 changes: 1 addition & 1 deletion driver/pgdriver/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func newChannel(ln *Listener, opts []ChannelOption) *Channel {
ln: ln,

size: 100,
pingTimeout: time.Second,
pingTimeout: 5 * time.Second,
chanSendTimeout: time.Minute,
}

Expand Down
2 changes: 1 addition & 1 deletion extra/bundebug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (h *QueryHook) AfterQuery(ctx context.Context, event *bun.QueryEvent) {
now.Format(" 15:04:05.000 "),
formatOperation(event),
fmt.Sprintf(" %10s ", dur.Round(time.Microsecond)),
event.Query,
string(event.Query),
}

if event.Err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/dbtest/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Bench struct {
CreatedAt time.Time
}

func BenchmarkNativeBun(b *testing.B) {
func BenchmarkSelect(b *testing.B) {
db := benchDB()

b.ResetTimer()
Expand Down
2 changes: 1 addition & 1 deletion internal/dbtest/pg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ type IngredientRecipe struct {
func TestPGMultiTenant(t *testing.T) {
db := pg()

db = db.WithArg("tenant", bun.Safe("public"))
db = db.WithNamedArg("tenant", bun.Safe("public"))
_ = db.Table(reflect.TypeOf((*IngredientRecipe)(nil)).Elem())

models := []interface{}{
Expand Down
77 changes: 32 additions & 45 deletions sqlfmt/append.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import (
"time"
"unicode/utf8"

"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
"github.com/uptrace/bun/internal/parser"
)

func Append(fmter QueryFormatter, b []byte, v interface{}) []byte {
Expand All @@ -18,12 +17,18 @@ func Append(fmter QueryFormatter, b []byte, v interface{}) []byte {
return AppendNull(b)
case bool:
return AppendBool(b, v)
case int:
return strconv.AppendInt(b, int64(v), 10)
case int32:
return strconv.AppendInt(b, int64(v), 10)
case int64:
return strconv.AppendInt(b, v, 10)
case int:
return strconv.AppendInt(b, int64(v), 10)
case uint:
return strconv.AppendUint(b, uint64(v), 10)
case uint32:
return strconv.AppendUint(b, uint64(v), 10)
case uint64:
return strconv.AppendUint(b, v, 10)
case float32:
return AppendFloat32(b, v)
case float64:
Expand Down Expand Up @@ -140,52 +145,34 @@ func AppendTime(b []byte, tm time.Time) []byte {
return b
}

//------------------------------------------------------------------------------

func AppendIdent(fmter QueryFormatter, b []byte, field string) []byte {
return appendIdent(fmter, b, internal.Bytes(field))
}

func IdentQuote(fmter QueryFormatter) byte {
if fmter.HasFeature(feature.Backticks) {
return '`'
}
return '"'
}

func appendIdent(fmter QueryFormatter, b, src []byte) []byte {
quote := IdentQuote(fmter)
func AppendJSON(b, jsonb []byte) []byte {
b = append(b, '\'')

var quoted bool
loop:
for _, c := range src {
p := parser.New(jsonb)
for p.Valid() {
c := p.Read()
switch c {
case '*':
if !quoted {
b = append(b, '*')
continue loop
}
case '.':
if quoted {
b = append(b, quote)
quoted = false
case '"':
b = append(b, '"')
case '\'':
b = append(b, "''"...)
case '\000':
continue
case '\\':
if p.SkipBytes([]byte("u0000")) {
b = append(b, "\\\\u0000"...)
} else {
b = append(b, '\\')
if p.Valid() {
b = append(b, p.Read())
}
}
b = append(b, '.')
continue loop
}

if !quoted {
b = append(b, quote)
quoted = true
}
if c == quote {
b = append(b, quote, quote)
} else {
default:
b = append(b, c)
}
}
if quoted {
b = append(b, quote)
}

b = append(b, '\'')

return b
}
35 changes: 0 additions & 35 deletions sqlfmt/append_json.go

This file was deleted.

8 changes: 2 additions & 6 deletions sqlfmt/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,15 @@ func (f Formatter) Arg(arg string) interface{} {
return f.namedArgs[arg]
}

func (f Formatter) hasArgs() bool {
return len(f.namedArgs) > 0
}

func (f Formatter) FormatQueryBytes(dst, query []byte, args ...interface{}) []byte {
if (args == nil && !f.hasArgs()) || bytes.IndexByte(query, '?') == -1 {
if (args == nil && f.namedArgs == nil) || bytes.IndexByte(query, '?') == -1 {
return append(dst, query...)
}
return f.append(dst, parser.New(query), args)
}

func (f Formatter) FormatQuery(dst []byte, query string, args ...interface{}) []byte {
if (args == nil && !f.hasArgs()) || strings.IndexByte(query, '?') == -1 {
if (args == nil && f.namedArgs == nil) || strings.IndexByte(query, '?') == -1 {
return append(dst, query...)
}
return f.append(dst, parser.NewString(query), args)
Expand Down
51 changes: 51 additions & 0 deletions sqlfmt/sqlfmt.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sqlfmt

import (
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
)

Expand Down Expand Up @@ -86,3 +87,53 @@ func SafeQueryWithSep(query string, args []interface{}, sep string) QueryWithSep
Sep: sep,
}
}

//------------------------------------------------------------------------------

func AppendIdent(fmter QueryFormatter, b []byte, field string) []byte {
return appendIdent(fmter, b, internal.Bytes(field))
}

func IdentQuote(fmter QueryFormatter) byte {
if fmter.HasFeature(feature.Backticks) {
return '`'
}
return '"'
}

func appendIdent(fmter QueryFormatter, b, src []byte) []byte {
quote := IdentQuote(fmter)

var quoted bool
loop:
for _, c := range src {
switch c {
case '*':
if !quoted {
b = append(b, '*')
continue loop
}
case '.':
if quoted {
b = append(b, quote)
quoted = false
}
b = append(b, '.')
continue loop
}

if !quoted {
b = append(b, quote)
quoted = true
}
if c == quote {
b = append(b, quote, quote)
} else {
b = append(b, c)
}
}
if quoted {
b = append(b, quote)
}
return b
}

0 comments on commit 6a0262a

Please sign in to comment.