Use simple exec
This commit is contained in:
parent
fb382876ef
commit
57d2b30132
@ -12,7 +12,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -219,157 +218,6 @@ func (mc *mysqlConn) error() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (string, error) {
|
|
||||||
// Number of ? should be same to len(args)
|
|
||||||
if strings.Count(query, "?") != len(args) {
|
|
||||||
return "", driver.ErrSkip
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := mc.buf.takeCompleteBuffer()
|
|
||||||
if buf == nil {
|
|
||||||
// can not take the buffer. Something must be wrong with the connection
|
|
||||||
errLog.Print(ErrBusyBuffer)
|
|
||||||
return "", ErrInvalidConn
|
|
||||||
}
|
|
||||||
buf = buf[:0]
|
|
||||||
argPos := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(query); i++ {
|
|
||||||
q := strings.IndexByte(query[i:], '?')
|
|
||||||
if q == -1 {
|
|
||||||
buf = append(buf, query[i:]...)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf = append(buf, query[i:i+q]...)
|
|
||||||
i += q
|
|
||||||
|
|
||||||
arg := args[argPos]
|
|
||||||
argPos++
|
|
||||||
|
|
||||||
if arg == nil {
|
|
||||||
buf = append(buf, "NULL"...)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := arg.(type) {
|
|
||||||
case int64:
|
|
||||||
buf = strconv.AppendInt(buf, v, 10)
|
|
||||||
case float64:
|
|
||||||
buf = strconv.AppendFloat(buf, v, 'g', -1, 64)
|
|
||||||
case bool:
|
|
||||||
if v {
|
|
||||||
buf = append(buf, '1')
|
|
||||||
} else {
|
|
||||||
buf = append(buf, '0')
|
|
||||||
}
|
|
||||||
case time.Time:
|
|
||||||
if v.IsZero() {
|
|
||||||
buf = append(buf, "'0000-00-00'"...)
|
|
||||||
} else {
|
|
||||||
v := v.In(mc.cfg.Loc)
|
|
||||||
v = v.Add(time.Nanosecond * 500) // To round under microsecond
|
|
||||||
year := v.Year()
|
|
||||||
year100 := year / 100
|
|
||||||
year1 := year % 100
|
|
||||||
month := v.Month()
|
|
||||||
day := v.Day()
|
|
||||||
hour := v.Hour()
|
|
||||||
minute := v.Minute()
|
|
||||||
second := v.Second()
|
|
||||||
micro := v.Nanosecond() / 1000
|
|
||||||
|
|
||||||
buf = append(buf, []byte{
|
|
||||||
'\'',
|
|
||||||
digits10[year100], digits01[year100],
|
|
||||||
digits10[year1], digits01[year1],
|
|
||||||
'-',
|
|
||||||
digits10[month], digits01[month],
|
|
||||||
'-',
|
|
||||||
digits10[day], digits01[day],
|
|
||||||
' ',
|
|
||||||
digits10[hour], digits01[hour],
|
|
||||||
':',
|
|
||||||
digits10[minute], digits01[minute],
|
|
||||||
':',
|
|
||||||
digits10[second], digits01[second],
|
|
||||||
}...)
|
|
||||||
|
|
||||||
if micro != 0 {
|
|
||||||
micro10000 := micro / 10000
|
|
||||||
micro100 := micro / 100 % 100
|
|
||||||
micro1 := micro % 100
|
|
||||||
buf = append(buf, []byte{
|
|
||||||
'.',
|
|
||||||
digits10[micro10000], digits01[micro10000],
|
|
||||||
digits10[micro100], digits01[micro100],
|
|
||||||
digits10[micro1], digits01[micro1],
|
|
||||||
}...)
|
|
||||||
}
|
|
||||||
buf = append(buf, '\'')
|
|
||||||
}
|
|
||||||
case []byte:
|
|
||||||
if v == nil {
|
|
||||||
buf = append(buf, "NULL"...)
|
|
||||||
} else {
|
|
||||||
buf = append(buf, "_binary'"...)
|
|
||||||
if mc.status&statusNoBackslashEscapes == 0 {
|
|
||||||
buf = escapeBytesBackslash(buf, v)
|
|
||||||
} else {
|
|
||||||
buf = escapeBytesQuotes(buf, v)
|
|
||||||
}
|
|
||||||
buf = append(buf, '\'')
|
|
||||||
}
|
|
||||||
case string:
|
|
||||||
buf = append(buf, '\'')
|
|
||||||
if mc.status&statusNoBackslashEscapes == 0 {
|
|
||||||
buf = escapeStringBackslash(buf, v)
|
|
||||||
} else {
|
|
||||||
buf = escapeStringQuotes(buf, v)
|
|
||||||
}
|
|
||||||
buf = append(buf, '\'')
|
|
||||||
default:
|
|
||||||
return "", driver.ErrSkip
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buf)+4 > mc.maxAllowedPacket {
|
|
||||||
return "", driver.ErrSkip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if argPos != len(args) {
|
|
||||||
return "", driver.ErrSkip
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
|
|
||||||
if mc.closed.IsSet() {
|
|
||||||
errLog.Print(ErrInvalidConn)
|
|
||||||
return nil, driver.ErrBadConn
|
|
||||||
}
|
|
||||||
if len(args) != 0 {
|
|
||||||
if !mc.cfg.InterpolateParams {
|
|
||||||
return nil, driver.ErrSkip
|
|
||||||
}
|
|
||||||
// try to interpolate the parameters to save extra roundtrips for preparing and closing a statement
|
|
||||||
prepared, err := mc.interpolateParams(query, args)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
query = prepared
|
|
||||||
}
|
|
||||||
mc.affectedRows = 0
|
|
||||||
mc.insertID = 0
|
|
||||||
|
|
||||||
err := mc.exec(query)
|
|
||||||
if err == nil {
|
|
||||||
return &mysqlResult{
|
|
||||||
affectedRows: int64(mc.affectedRows),
|
|
||||||
insertID: int64(mc.insertID),
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
return nil, mc.markBadConn(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal function to execute commands
|
// Internal function to execute commands
|
||||||
func (mc *mysqlConn) exec(query string) error {
|
func (mc *mysqlConn) exec(query string) error {
|
||||||
// Send command
|
// Send command
|
||||||
|
@ -5,6 +5,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ExtendedConn provides access to internal packet functions.
|
||||||
|
type ExtendedConn struct {
|
||||||
|
*mysqlConn
|
||||||
|
}
|
||||||
|
|
||||||
// NewExtendedConnection creates a new connection extended with packet access
|
// NewExtendedConnection creates a new connection extended with packet access
|
||||||
// methods.
|
// methods.
|
||||||
func NewExtendedConnection(dsn string) (*ExtendedConn, error) {
|
func NewExtendedConnection(dsn string) (*ExtendedConn, error) {
|
||||||
@ -15,17 +20,9 @@ func NewExtendedConnection(dsn string) (*ExtendedConn, error) {
|
|||||||
return &ExtendedConn{conn}, nil
|
return &ExtendedConn{conn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtendedConn provides access to internal packet functions.
|
// Exec executes a query.
|
||||||
type ExtendedConn struct {
|
func (c *ExtendedConn) Exec(query string) error {
|
||||||
*mysqlConn
|
return c.exec(query)
|
||||||
}
|
|
||||||
|
|
||||||
// Close the connection.
|
|
||||||
func (c *ExtendedConn) Close() error {
|
|
||||||
// Reset buffer length parameter
|
|
||||||
// If it's not zero bad stuff happens
|
|
||||||
c.buf.length = 0
|
|
||||||
return c.mysqlConn.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPacket reads a packet from a given connection. If given context has a
|
// ReadPacket reads a packet from a given connection. If given context has a
|
||||||
@ -65,3 +62,11 @@ func (c *ExtendedConn) HandleErrorPacket(data []byte) error {
|
|||||||
func (c *ExtendedConn) ResetSequence() {
|
func (c *ExtendedConn) ResetSequence() {
|
||||||
c.sequence = 0
|
c.sequence = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the connection.
|
||||||
|
func (c *ExtendedConn) Close() error {
|
||||||
|
// Reset buffer length parameter
|
||||||
|
// If it's not zero bad stuff happens
|
||||||
|
c.buf.length = 0
|
||||||
|
return c.mysqlConn.Close()
|
||||||
|
}
|
||||||
|
@ -121,8 +121,7 @@ func (c *Conn) DisableChecksum() error {
|
|||||||
|
|
||||||
// SetVar assigns a new value to the given variable.
|
// SetVar assigns a new value to the given variable.
|
||||||
func (c *Conn) SetVar(name, val string) error {
|
func (c *Conn) SetVar(name, val string) error {
|
||||||
_, err := c.conn.Exec(fmt.Sprintf("SET %s=%q", name, val), nil)
|
return c.conn.Exec(fmt.Sprintf("SET %s=%q", name, val))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection.
|
// Close the connection.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user