dialect/sql/sqlbuild: replace bytes.buffer with strings.builder (#1502)

benchmark                                      old ns/op     new ns/op     delta
BenchmarkInsertBuilder_Default/sqlite3-16      285           253           -11.06%
BenchmarkInsertBuilder_Default/mysql-16        283           219           -22.70%
BenchmarkInsertBuilder_Default/postgres-16     374           340           -9.17%
BenchmarkInsertBuilder_Small/sqlite3-16        1945          1734          -10.85%
BenchmarkInsertBuilder_Small/mysql-16          1957          1741          -11.04%
BenchmarkInsertBuilder_Small/postgres-16       2393          2220          -7.23%

benchmark                                      old allocs     new allocs     delta
BenchmarkInsertBuilder_Default/sqlite3-16      5              6              +20.00%
BenchmarkInsertBuilder_Default/mysql-16        5              5              +0.00%
BenchmarkInsertBuilder_Default/postgres-16     6              7              +16.67%
BenchmarkInsertBuilder_Small/sqlite3-16        22             23             +4.55%
BenchmarkInsertBuilder_Small/mysql-16          22             23             +4.55%
BenchmarkInsertBuilder_Small/postgres-16       31             32             +3.23%

benchmark                                      old bytes     new bytes     delta
BenchmarkInsertBuilder_Default/sqlite3-16      456           168           -63.16%
BenchmarkInsertBuilder_Default/mysql-16        440           104           -76.36%
BenchmarkInsertBuilder_Default/postgres-16     480           176           -63.33%
BenchmarkInsertBuilder_Small/sqlite3-16        1624          1176          -27.59%
BenchmarkInsertBuilder_Small/mysql-16          1624          1176          -27.59%
BenchmarkInsertBuilder_Small/postgres-16       1656          1192          -28.02%
This commit is contained in:
Ariel Mashraki
2021-04-23 11:10:33 +03:00
committed by GitHub
parent 63d630b7cf
commit 1908b3e35f

View File

@@ -12,7 +12,6 @@
package sql package sql
import ( import (
"bytes"
"context" "context"
"database/sql/driver" "database/sql/driver"
"fmt" "fmt"
@@ -738,11 +737,9 @@ func (i *InsertBuilder) Query() (string, []interface{}) {
i.WriteByte('(').Args(v...).WriteByte(')') i.WriteByte('(').Args(v...).WriteByte(')')
} }
} }
if len(i.conflictColumns) > 0 { if len(i.conflictColumns) > 0 {
i.buildConflictHandling() i.buildConflictHandling()
} }
if len(i.returning) > 0 && i.postgres() { if len(i.returning) > 0 && i.postgres() {
i.WriteString(" RETURNING ") i.WriteString(" RETURNING ")
i.IdentComma(i.returning...) i.IdentComma(i.returning...)
@@ -2232,11 +2229,11 @@ func (n Queries) Query() (string, []interface{}) {
// Builder is the base query builder for the sql dsl. // Builder is the base query builder for the sql dsl.
type Builder struct { type Builder struct {
bytes.Buffer // underlying buffer. sb *strings.Builder // underlying builder.
dialect string // configured dialect. dialect string // configured dialect.
args []interface{} // query parameters. args []interface{} // query parameters.
total int // total number of parameters in query tree. total int // total number of parameters in query tree.
errs []error // errors that added during the query construction. errs []error // errors that added during the query construction.
} }
// Quote quotes the given identifier with the characters based // Quote quotes the given identifier with the characters based
@@ -2285,15 +2282,45 @@ func (b *Builder) IdentComma(s ...string) *Builder {
return b return b
} }
// String returns the accumulated string.
func (b *Builder) String() string {
if b.sb == nil {
return ""
}
return b.sb.String()
}
// WriteByte wraps the Buffer.WriteByte to make it chainable with other methods. // WriteByte wraps the Buffer.WriteByte to make it chainable with other methods.
func (b *Builder) WriteByte(c byte) *Builder { func (b *Builder) WriteByte(c byte) *Builder {
b.Buffer.WriteByte(c) if b.sb == nil {
b.sb = &strings.Builder{}
}
b.sb.WriteByte(c)
return b return b
} }
// WriteString wraps the Buffer.WriteString to make it chainable with other methods. // WriteString wraps the Buffer.WriteString to make it chainable with other methods.
func (b *Builder) WriteString(s string) *Builder { func (b *Builder) WriteString(s string) *Builder {
b.Buffer.WriteString(s) if b.sb == nil {
b.sb = &strings.Builder{}
}
b.sb.WriteString(s)
return b
}
// Len returns the number of accumulated bytes.
func (b *Builder) Len() int {
if b.sb == nil {
return 0
}
return b.sb.Len()
}
// Reset resets the Builder to be empty.
func (b *Builder) Reset() *Builder {
if b.sb != nil {
b.sb.Reset()
}
return b return b
} }
@@ -2467,11 +2494,11 @@ func (b *Builder) join(qs []Querier, sep string) *Builder {
// Nested gets a callback, and wraps its result with parentheses. // Nested gets a callback, and wraps its result with parentheses.
func (b *Builder) Nested(f func(*Builder)) *Builder { func (b *Builder) Nested(f func(*Builder)) *Builder {
nb := &Builder{dialect: b.dialect, total: b.total} nb := &Builder{dialect: b.dialect, total: b.total, sb: &strings.Builder{}}
nb.WriteByte('(') nb.WriteByte('(')
f(nb) f(nb)
nb.WriteByte(')') nb.WriteByte(')')
nb.WriteTo(b) b.WriteString(nb.String())
b.args = append(b.args, nb.args...) b.args = append(b.args, nb.args...)
b.total = nb.total b.total = nb.total
return b return b
@@ -2505,11 +2532,13 @@ func (b Builder) Query() (string, []interface{}) {
// clone returns a shallow clone of a builder. // clone returns a shallow clone of a builder.
func (b Builder) clone() Builder { func (b Builder) clone() Builder {
c := Builder{dialect: b.dialect, total: b.total} c := Builder{dialect: b.dialect, total: b.total, sb: &strings.Builder{}}
if len(b.args) > 0 { if len(b.args) > 0 {
c.args = append(c.args, b.args...) c.args = append(c.args, b.args...)
} }
c.Buffer.Write(b.Bytes()) if b.sb != nil {
c.sb.WriteString(b.sb.String())
}
return c return c
} }