forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/go-sql-driver/mysql/utils.go

1510 lines
21 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// This Source Code Form is subject to the terms of the Mozilla Public
2024-02-18 10:42:21 +00:00
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
2024-02-18 10:42:21 +00:00
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"crypto/tls"
"database/sql"
"database/sql/driver"
"encoding/binary"
"errors"
"fmt"
"io"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
// Registry for custom tls.Configs
2024-02-18 10:42:21 +00:00
var (
tlsConfigLock sync.RWMutex
2024-02-18 10:42:21 +00:00
tlsConfigRegistry map[string]*tls.Config
)
// RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.
2024-02-18 10:42:21 +00:00
// Use the key as a value in the DSN where tls=value.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Note: The provided tls.Config is exclusively owned by the driver after
2024-02-18 10:42:21 +00:00
// registering it.
2024-02-18 10:42:21 +00:00
//
2024-06-14 08:41:36 +00:00
// rootCertPool := x509.NewCertPool()
2024-06-14 08:41:36 +00:00
// pem, err := ioutil.ReadFile("/path/ca-cert.pem")
2024-06-14 08:41:36 +00:00
// if err != nil {
2024-06-14 08:41:36 +00:00
// log.Fatal(err)
2024-06-14 08:41:36 +00:00
// }
2024-06-14 08:41:36 +00:00
// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
2024-06-14 08:41:36 +00:00
// log.Fatal("Failed to append PEM.")
2024-06-14 08:41:36 +00:00
// }
2024-06-14 08:41:36 +00:00
// clientCert := make([]tls.Certificate, 0, 1)
2024-06-14 08:41:36 +00:00
// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
2024-06-14 08:41:36 +00:00
// if err != nil {
2024-06-14 08:41:36 +00:00
// log.Fatal(err)
2024-06-14 08:41:36 +00:00
// }
2024-06-14 08:41:36 +00:00
// clientCert = append(clientCert, certs)
2024-06-14 08:41:36 +00:00
// mysql.RegisterTLSConfig("custom", &tls.Config{
2024-06-14 08:41:36 +00:00
// RootCAs: rootCertPool,
2024-06-14 08:41:36 +00:00
// Certificates: clientCert,
2024-06-14 08:41:36 +00:00
// })
2024-06-14 08:41:36 +00:00
// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom")
2024-02-18 10:42:21 +00:00
func RegisterTLSConfig(key string, config *tls.Config) error {
2024-02-18 10:42:21 +00:00
if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" || strings.ToLower(key) == "preferred" {
2024-02-18 10:42:21 +00:00
return fmt.Errorf("key '%s' is reserved", key)
2024-02-18 10:42:21 +00:00
}
tlsConfigLock.Lock()
2024-02-18 10:42:21 +00:00
if tlsConfigRegistry == nil {
2024-02-18 10:42:21 +00:00
tlsConfigRegistry = make(map[string]*tls.Config)
2024-02-18 10:42:21 +00:00
}
tlsConfigRegistry[key] = config
2024-02-18 10:42:21 +00:00
tlsConfigLock.Unlock()
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
// DeregisterTLSConfig removes the tls.Config associated with key.
2024-02-18 10:42:21 +00:00
func DeregisterTLSConfig(key string) {
2024-02-18 10:42:21 +00:00
tlsConfigLock.Lock()
2024-02-18 10:42:21 +00:00
if tlsConfigRegistry != nil {
2024-02-18 10:42:21 +00:00
delete(tlsConfigRegistry, key)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
tlsConfigLock.Unlock()
2024-02-18 10:42:21 +00:00
}
func getTLSConfigClone(key string) (config *tls.Config) {
2024-02-18 10:42:21 +00:00
tlsConfigLock.RLock()
2024-02-18 10:42:21 +00:00
if v, ok := tlsConfigRegistry[key]; ok {
2024-02-18 10:42:21 +00:00
config = v.Clone()
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
tlsConfigLock.RUnlock()
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
// Returns the bool value of the input.
2024-02-18 10:42:21 +00:00
// The 2nd return value indicates if the input was a valid bool value
2024-02-18 10:42:21 +00:00
func readBool(input string) (value bool, valid bool) {
2024-02-18 10:42:21 +00:00
switch input {
2024-02-18 10:42:21 +00:00
case "1", "true", "TRUE", "True":
2024-02-18 10:42:21 +00:00
return true, true
2024-02-18 10:42:21 +00:00
case "0", "false", "FALSE", "False":
2024-02-18 10:42:21 +00:00
return false, true
2024-02-18 10:42:21 +00:00
}
// Not a valid bool value
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
/******************************************************************************
2024-02-18 10:42:21 +00:00
* Time related utils *
2024-02-18 10:42:21 +00:00
******************************************************************************/
func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
2024-02-18 10:42:21 +00:00
const base = "0000-00-00 00:00:00.000000"
2024-02-18 10:42:21 +00:00
switch len(b) {
2024-02-18 10:42:21 +00:00
case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
2024-02-18 10:42:21 +00:00
if string(b) == base[:len(b)] {
2024-02-18 10:42:21 +00:00
return time.Time{}, nil
2024-02-18 10:42:21 +00:00
}
year, err := parseByteYear(b)
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if year <= 0 {
2024-02-18 10:42:21 +00:00
year = 1
2024-02-18 10:42:21 +00:00
}
if b[4] != '-' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[4])
2024-02-18 10:42:21 +00:00
}
m, err := parseByte2Digits(b[5], b[6])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if m <= 0 {
2024-02-18 10:42:21 +00:00
m = 1
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
month := time.Month(m)
if b[7] != '-' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[7])
2024-02-18 10:42:21 +00:00
}
day, err := parseByte2Digits(b[8], b[9])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if day <= 0 {
2024-02-18 10:42:21 +00:00
day = 1
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if len(b) == 10 {
2024-02-18 10:42:21 +00:00
return time.Date(year, month, day, 0, 0, 0, 0, loc), nil
2024-02-18 10:42:21 +00:00
}
if b[10] != ' ' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[10])
2024-02-18 10:42:21 +00:00
}
hour, err := parseByte2Digits(b[11], b[12])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if b[13] != ':' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[13])
2024-02-18 10:42:21 +00:00
}
min, err := parseByte2Digits(b[14], b[15])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if b[16] != ':' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[16])
2024-02-18 10:42:21 +00:00
}
sec, err := parseByte2Digits(b[17], b[18])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if len(b) == 19 {
2024-02-18 10:42:21 +00:00
return time.Date(year, month, day, hour, min, sec, 0, loc), nil
2024-02-18 10:42:21 +00:00
}
if b[19] != '.' {
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[19])
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
nsec, err := parseByteNanoSec(b[20:])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return time.Time{}, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return time.Date(year, month, day, hour, min, sec, nsec, loc), nil
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
return time.Time{}, fmt.Errorf("invalid time bytes: %s", b)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
func parseByteYear(b []byte) (int, error) {
2024-02-18 10:42:21 +00:00
year, n := 0, 1000
2024-02-18 10:42:21 +00:00
for i := 0; i < 4; i++ {
2024-02-18 10:42:21 +00:00
v, err := bToi(b[i])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return 0, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
year += v * n
2024-02-18 10:42:21 +00:00
n = n / 10
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return year, nil
2024-02-18 10:42:21 +00:00
}
func parseByte2Digits(b1, b2 byte) (int, error) {
2024-02-18 10:42:21 +00:00
d1, err := bToi(b1)
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return 0, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
d2, err := bToi(b2)
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return 0, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return d1*10 + d2, nil
2024-02-18 10:42:21 +00:00
}
func parseByteNanoSec(b []byte) (int, error) {
2024-02-18 10:42:21 +00:00
ns, digit := 0, 100000 // max is 6-digits
2024-02-18 10:42:21 +00:00
for i := 0; i < len(b); i++ {
2024-02-18 10:42:21 +00:00
v, err := bToi(b[i])
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return 0, err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
ns += v * digit
2024-02-18 10:42:21 +00:00
digit /= 10
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
// nanoseconds has 10-digits. (needs to scale digits)
2024-02-18 10:42:21 +00:00
// 10 - 6 = 4, so we have to multiple 1000.
2024-02-18 10:42:21 +00:00
return ns * 1000, nil
2024-02-18 10:42:21 +00:00
}
func bToi(b byte) (int, error) {
2024-02-18 10:42:21 +00:00
if b < '0' || b > '9' {
2024-02-18 10:42:21 +00:00
return 0, errors.New("not [0-9]")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return int(b - '0'), nil
2024-02-18 10:42:21 +00:00
}
func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {
2024-02-18 10:42:21 +00:00
switch num {
2024-02-18 10:42:21 +00:00
case 0:
2024-02-18 10:42:21 +00:00
return time.Time{}, nil
2024-02-18 10:42:21 +00:00
case 4:
2024-02-18 10:42:21 +00:00
return time.Date(
2024-02-18 10:42:21 +00:00
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
2024-02-18 10:42:21 +00:00
0, 0, 0, 0,
2024-02-18 10:42:21 +00:00
loc,
), nil
2024-02-18 10:42:21 +00:00
case 7:
2024-02-18 10:42:21 +00:00
return time.Date(
2024-02-18 10:42:21 +00:00
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
2024-02-18 10:42:21 +00:00
0,
2024-02-18 10:42:21 +00:00
loc,
), nil
2024-02-18 10:42:21 +00:00
case 11:
2024-02-18 10:42:21 +00:00
return time.Date(
2024-02-18 10:42:21 +00:00
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
2024-02-18 10:42:21 +00:00
int(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds
2024-02-18 10:42:21 +00:00
loc,
), nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil, fmt.Errorf("invalid DATETIME packet length %d", num)
2024-02-18 10:42:21 +00:00
}
func appendDateTime(buf []byte, t time.Time) ([]byte, error) {
2024-02-18 10:42:21 +00:00
year, month, day := t.Date()
2024-02-18 10:42:21 +00:00
hour, min, sec := t.Clock()
2024-02-18 10:42:21 +00:00
nsec := t.Nanosecond()
if year < 1 || year > 9999 {
2024-02-18 10:42:21 +00:00
return buf, errors.New("year is not in the range [1, 9999]: " + strconv.Itoa(year)) // use errors.New instead of fmt.Errorf to avoid year escape to heap
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
year100 := year / 100
2024-02-18 10:42:21 +00:00
year1 := year % 100
var localBuf [len("2006-01-02T15:04:05.999999999")]byte // does not escape
2024-02-18 10:42:21 +00:00
localBuf[0], localBuf[1], localBuf[2], localBuf[3] = digits10[year100], digits01[year100], digits10[year1], digits01[year1]
2024-02-18 10:42:21 +00:00
localBuf[4] = '-'
2024-02-18 10:42:21 +00:00
localBuf[5], localBuf[6] = digits10[month], digits01[month]
2024-02-18 10:42:21 +00:00
localBuf[7] = '-'
2024-02-18 10:42:21 +00:00
localBuf[8], localBuf[9] = digits10[day], digits01[day]
if hour == 0 && min == 0 && sec == 0 && nsec == 0 {
2024-02-18 10:42:21 +00:00
return append(buf, localBuf[:10]...), nil
2024-02-18 10:42:21 +00:00
}
localBuf[10] = ' '
2024-02-18 10:42:21 +00:00
localBuf[11], localBuf[12] = digits10[hour], digits01[hour]
2024-02-18 10:42:21 +00:00
localBuf[13] = ':'
2024-02-18 10:42:21 +00:00
localBuf[14], localBuf[15] = digits10[min], digits01[min]
2024-02-18 10:42:21 +00:00
localBuf[16] = ':'
2024-02-18 10:42:21 +00:00
localBuf[17], localBuf[18] = digits10[sec], digits01[sec]
if nsec == 0 {
2024-02-18 10:42:21 +00:00
return append(buf, localBuf[:19]...), nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
nsec100000000 := nsec / 100000000
2024-02-18 10:42:21 +00:00
nsec1000000 := (nsec / 1000000) % 100
2024-02-18 10:42:21 +00:00
nsec10000 := (nsec / 10000) % 100
2024-02-18 10:42:21 +00:00
nsec100 := (nsec / 100) % 100
2024-02-18 10:42:21 +00:00
nsec1 := nsec % 100
2024-02-18 10:42:21 +00:00
localBuf[19] = '.'
// milli second
2024-02-18 10:42:21 +00:00
localBuf[20], localBuf[21], localBuf[22] =
2024-02-18 10:42:21 +00:00
digits01[nsec100000000], digits10[nsec1000000], digits01[nsec1000000]
2024-02-18 10:42:21 +00:00
// micro second
2024-02-18 10:42:21 +00:00
localBuf[23], localBuf[24], localBuf[25] =
2024-02-18 10:42:21 +00:00
digits10[nsec10000], digits01[nsec10000], digits10[nsec100]
2024-02-18 10:42:21 +00:00
// nano second
2024-02-18 10:42:21 +00:00
localBuf[26], localBuf[27], localBuf[28] =
2024-02-18 10:42:21 +00:00
digits01[nsec100], digits10[nsec1], digits01[nsec1]
// trim trailing zeros
2024-02-18 10:42:21 +00:00
n := len(localBuf)
2024-02-18 10:42:21 +00:00
for n > 0 && localBuf[n-1] == '0' {
2024-02-18 10:42:21 +00:00
n--
2024-02-18 10:42:21 +00:00
}
return append(buf, localBuf[:n]...), nil
2024-02-18 10:42:21 +00:00
}
// zeroDateTime is used in formatBinaryDateTime to avoid an allocation
2024-02-18 10:42:21 +00:00
// if the DATE or DATETIME has the zero value.
2024-02-18 10:42:21 +00:00
// It must never be changed.
2024-02-18 10:42:21 +00:00
// The current behavior depends on database/sql copying the result.
2024-02-18 10:42:21 +00:00
var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
2024-02-18 10:42:21 +00:00
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
func appendMicrosecs(dst, src []byte, decimals int) []byte {
2024-02-18 10:42:21 +00:00
if decimals <= 0 {
2024-02-18 10:42:21 +00:00
return dst
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if len(src) == 0 {
2024-02-18 10:42:21 +00:00
return append(dst, ".000000"[:decimals+1]...)
2024-02-18 10:42:21 +00:00
}
microsecs := binary.LittleEndian.Uint32(src[:4])
2024-02-18 10:42:21 +00:00
p1 := byte(microsecs / 10000)
2024-02-18 10:42:21 +00:00
microsecs -= 10000 * uint32(p1)
2024-02-18 10:42:21 +00:00
p2 := byte(microsecs / 100)
2024-02-18 10:42:21 +00:00
microsecs -= 100 * uint32(p2)
2024-02-18 10:42:21 +00:00
p3 := byte(microsecs)
switch decimals {
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1],
2024-02-18 10:42:21 +00:00
digits10[p2], digits01[p2],
2024-02-18 10:42:21 +00:00
digits10[p3], digits01[p3],
)
2024-02-18 10:42:21 +00:00
case 1:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1],
)
2024-02-18 10:42:21 +00:00
case 2:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1],
)
2024-02-18 10:42:21 +00:00
case 3:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1],
2024-02-18 10:42:21 +00:00
digits10[p2],
)
2024-02-18 10:42:21 +00:00
case 4:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1],
2024-02-18 10:42:21 +00:00
digits10[p2], digits01[p2],
)
2024-02-18 10:42:21 +00:00
case 5:
2024-02-18 10:42:21 +00:00
return append(dst, '.',
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1],
2024-02-18 10:42:21 +00:00
digits10[p2], digits01[p2],
2024-02-18 10:42:21 +00:00
digits10[p3],
)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
func formatBinaryDateTime(src []byte, length uint8) (driver.Value, error) {
2024-02-18 10:42:21 +00:00
// length expects the deterministic length of the zero value,
2024-02-18 10:42:21 +00:00
// negative time and 100+ hours are automatically added if needed
2024-02-18 10:42:21 +00:00
if len(src) == 0 {
2024-02-18 10:42:21 +00:00
return zeroDateTime[:length], nil
2024-02-18 10:42:21 +00:00
}
var dst []byte // return value
2024-02-18 10:42:21 +00:00
var p1, p2, p3 byte // current digit pair
switch length {
2024-02-18 10:42:21 +00:00
case 10, 19, 21, 22, 23, 24, 25, 26:
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
t := "DATE"
2024-02-18 10:42:21 +00:00
if length > 10 {
2024-02-18 10:42:21 +00:00
t += "TIME"
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil, fmt.Errorf("illegal %s length %d", t, length)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
switch len(src) {
2024-02-18 10:42:21 +00:00
case 4, 7, 11:
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
t := "DATE"
2024-02-18 10:42:21 +00:00
if length > 10 {
2024-02-18 10:42:21 +00:00
t += "TIME"
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
dst = make([]byte, 0, length)
2024-02-18 10:42:21 +00:00
// start with the date
2024-02-18 10:42:21 +00:00
year := binary.LittleEndian.Uint16(src[:2])
2024-02-18 10:42:21 +00:00
pt := year / 100
2024-02-18 10:42:21 +00:00
p1 = byte(year - 100*uint16(pt))
2024-02-18 10:42:21 +00:00
p2, p3 = src[2], src[3]
2024-02-18 10:42:21 +00:00
dst = append(dst,
2024-02-18 10:42:21 +00:00
digits10[pt], digits01[pt],
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1], '-',
2024-02-18 10:42:21 +00:00
digits10[p2], digits01[p2], '-',
2024-02-18 10:42:21 +00:00
digits10[p3], digits01[p3],
)
2024-02-18 10:42:21 +00:00
if length == 10 {
2024-02-18 10:42:21 +00:00
return dst, nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if len(src) == 4 {
2024-02-18 10:42:21 +00:00
return append(dst, zeroDateTime[10:length]...), nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
dst = append(dst, ' ')
2024-02-18 10:42:21 +00:00
p1 = src[4] // hour
2024-02-18 10:42:21 +00:00
src = src[5:]
// p1 is 2-digit hour, src is after hour
2024-02-18 10:42:21 +00:00
p2, p3 = src[0], src[1]
2024-02-18 10:42:21 +00:00
dst = append(dst,
2024-02-18 10:42:21 +00:00
digits10[p1], digits01[p1], ':',
2024-02-18 10:42:21 +00:00
digits10[p2], digits01[p2], ':',
2024-02-18 10:42:21 +00:00
digits10[p3], digits01[p3],
)
2024-02-18 10:42:21 +00:00
return appendMicrosecs(dst, src[2:], int(length)-20), nil
2024-02-18 10:42:21 +00:00
}
func formatBinaryTime(src []byte, length uint8) (driver.Value, error) {
2024-02-18 10:42:21 +00:00
// length expects the deterministic length of the zero value,
2024-02-18 10:42:21 +00:00
// negative time and 100+ hours are automatically added if needed
2024-02-18 10:42:21 +00:00
if len(src) == 0 {
2024-02-18 10:42:21 +00:00
return zeroDateTime[11 : 11+length], nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
var dst []byte // return value
switch length {
2024-02-18 10:42:21 +00:00
case
8, // time (can be up to 10 when negative and 100+ hours)
2024-02-18 10:42:21 +00:00
10, 11, 12, 13, 14, 15: // time with fractional seconds
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
return nil, fmt.Errorf("illegal TIME length %d", length)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
switch len(src) {
2024-02-18 10:42:21 +00:00
case 8, 12:
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
// +2 to enable negative time and 100+ hours
2024-02-18 10:42:21 +00:00
dst = make([]byte, 0, length+2)
2024-02-18 10:42:21 +00:00
if src[0] == 1 {
2024-02-18 10:42:21 +00:00
dst = append(dst, '-')
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
days := binary.LittleEndian.Uint32(src[1:5])
2024-02-18 10:42:21 +00:00
hours := int64(days)*24 + int64(src[5])
if hours >= 100 {
2024-02-18 10:42:21 +00:00
dst = strconv.AppendInt(dst, hours, 10)
2024-02-18 10:42:21 +00:00
} else {
2024-02-18 10:42:21 +00:00
dst = append(dst, digits10[hours], digits01[hours])
2024-02-18 10:42:21 +00:00
}
min, sec := src[6], src[7]
2024-02-18 10:42:21 +00:00
dst = append(dst, ':',
2024-02-18 10:42:21 +00:00
digits10[min], digits01[min], ':',
2024-02-18 10:42:21 +00:00
digits10[sec], digits01[sec],
)
2024-02-18 10:42:21 +00:00
return appendMicrosecs(dst, src[8:], int(length)-9), nil
2024-02-18 10:42:21 +00:00
}
/******************************************************************************
2024-02-18 10:42:21 +00:00
* Convert from and to bytes *
2024-02-18 10:42:21 +00:00
******************************************************************************/
func uint64ToBytes(n uint64) []byte {
2024-02-18 10:42:21 +00:00
return []byte{
2024-02-18 10:42:21 +00:00
byte(n),
2024-02-18 10:42:21 +00:00
byte(n >> 8),
2024-02-18 10:42:21 +00:00
byte(n >> 16),
2024-02-18 10:42:21 +00:00
byte(n >> 24),
2024-02-18 10:42:21 +00:00
byte(n >> 32),
2024-02-18 10:42:21 +00:00
byte(n >> 40),
2024-02-18 10:42:21 +00:00
byte(n >> 48),
2024-02-18 10:42:21 +00:00
byte(n >> 56),
}
2024-02-18 10:42:21 +00:00
}
func uint64ToString(n uint64) []byte {
2024-02-18 10:42:21 +00:00
var a [20]byte
2024-02-18 10:42:21 +00:00
i := 20
// U+0030 = 0
2024-02-18 10:42:21 +00:00
// ...
2024-02-18 10:42:21 +00:00
// U+0039 = 9
var q uint64
2024-02-18 10:42:21 +00:00
for n >= 10 {
2024-02-18 10:42:21 +00:00
i--
2024-02-18 10:42:21 +00:00
q = n / 10
2024-02-18 10:42:21 +00:00
a[i] = uint8(n-q*10) + 0x30
2024-02-18 10:42:21 +00:00
n = q
2024-02-18 10:42:21 +00:00
}
i--
2024-02-18 10:42:21 +00:00
a[i] = uint8(n) + 0x30
return a[i:]
2024-02-18 10:42:21 +00:00
}
// treats string value as unsigned integer representation
2024-02-18 10:42:21 +00:00
func stringToInt(b []byte) int {
2024-02-18 10:42:21 +00:00
val := 0
2024-02-18 10:42:21 +00:00
for i := range b {
2024-02-18 10:42:21 +00:00
val *= 10
2024-02-18 10:42:21 +00:00
val += int(b[i] - 0x30)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return val
2024-02-18 10:42:21 +00:00
}
// returns the string read as a bytes slice, wheter the value is NULL,
2024-02-18 10:42:21 +00:00
// the number of bytes read and an error, in case the string is longer than
2024-02-18 10:42:21 +00:00
// the input slice
2024-02-18 10:42:21 +00:00
func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
2024-02-18 10:42:21 +00:00
// Get length
2024-02-18 10:42:21 +00:00
num, isNull, n := readLengthEncodedInteger(b)
2024-02-18 10:42:21 +00:00
if num < 1 {
2024-02-18 10:42:21 +00:00
return b[n:n], isNull, n, nil
2024-02-18 10:42:21 +00:00
}
n += int(num)
// Check data length
2024-02-18 10:42:21 +00:00
if len(b) >= n {
2024-02-18 10:42:21 +00:00
return b[n-int(num) : n : n], false, n, nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil, false, n, io.EOF
2024-02-18 10:42:21 +00:00
}
// returns the number of bytes skipped and an error, in case the string is
2024-02-18 10:42:21 +00:00
// longer than the input slice
2024-02-18 10:42:21 +00:00
func skipLengthEncodedString(b []byte) (int, error) {
2024-02-18 10:42:21 +00:00
// Get length
2024-02-18 10:42:21 +00:00
num, _, n := readLengthEncodedInteger(b)
2024-02-18 10:42:21 +00:00
if num < 1 {
2024-02-18 10:42:21 +00:00
return n, nil
2024-02-18 10:42:21 +00:00
}
n += int(num)
// Check data length
2024-02-18 10:42:21 +00:00
if len(b) >= n {
2024-02-18 10:42:21 +00:00
return n, nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return n, io.EOF
2024-02-18 10:42:21 +00:00
}
// returns the number read, whether the value is NULL and the number of bytes read
2024-02-18 10:42:21 +00:00
func readLengthEncodedInteger(b []byte) (uint64, bool, int) {
2024-02-18 10:42:21 +00:00
// See issue #349
2024-02-18 10:42:21 +00:00
if len(b) == 0 {
2024-02-18 10:42:21 +00:00
return 0, true, 1
2024-02-18 10:42:21 +00:00
}
switch b[0] {
2024-02-18 10:42:21 +00:00
// 251: NULL
2024-02-18 10:42:21 +00:00
case 0xfb:
2024-02-18 10:42:21 +00:00
return 0, true, 1
// 252: value of following 2
2024-02-18 10:42:21 +00:00
case 0xfc:
2024-02-18 10:42:21 +00:00
return uint64(b[1]) | uint64(b[2])<<8, false, 3
// 253: value of following 3
2024-02-18 10:42:21 +00:00
case 0xfd:
2024-02-18 10:42:21 +00:00
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16, false, 4
// 254: value of following 8
2024-02-18 10:42:21 +00:00
case 0xfe:
2024-02-18 10:42:21 +00:00
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16 |
2024-02-18 10:42:21 +00:00
uint64(b[4])<<24 | uint64(b[5])<<32 | uint64(b[6])<<40 |
2024-02-18 10:42:21 +00:00
uint64(b[7])<<48 | uint64(b[8])<<56,
2024-02-18 10:42:21 +00:00
false, 9
2024-02-18 10:42:21 +00:00
}
// 0-250: value of first byte
2024-02-18 10:42:21 +00:00
return uint64(b[0]), false, 1
2024-02-18 10:42:21 +00:00
}
// encodes a uint64 value and appends it to the given bytes slice
2024-02-18 10:42:21 +00:00
func appendLengthEncodedInteger(b []byte, n uint64) []byte {
2024-02-18 10:42:21 +00:00
switch {
2024-02-18 10:42:21 +00:00
case n <= 250:
2024-02-18 10:42:21 +00:00
return append(b, byte(n))
case n <= 0xffff:
2024-02-18 10:42:21 +00:00
return append(b, 0xfc, byte(n), byte(n>>8))
case n <= 0xffffff:
2024-02-18 10:42:21 +00:00
return append(b, 0xfd, byte(n), byte(n>>8), byte(n>>16))
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return append(b, 0xfe, byte(n), byte(n>>8), byte(n>>16), byte(n>>24),
2024-02-18 10:42:21 +00:00
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
2024-02-18 10:42:21 +00:00
}
// reserveBuffer checks cap(buf) and expand buffer to len(buf) + appendSize.
2024-02-18 10:42:21 +00:00
// If cap(buf) is not enough, reallocate new buffer.
2024-02-18 10:42:21 +00:00
func reserveBuffer(buf []byte, appendSize int) []byte {
2024-02-18 10:42:21 +00:00
newSize := len(buf) + appendSize
2024-02-18 10:42:21 +00:00
if cap(buf) < newSize {
2024-02-18 10:42:21 +00:00
// Grow buffer exponentially
2024-02-18 10:42:21 +00:00
newBuf := make([]byte, len(buf)*2+appendSize)
2024-02-18 10:42:21 +00:00
copy(newBuf, buf)
2024-02-18 10:42:21 +00:00
buf = newBuf
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return buf[:newSize]
2024-02-18 10:42:21 +00:00
}
// escapeBytesBackslash escapes []byte with backslashes (\)
2024-02-18 10:42:21 +00:00
// This escapes the contents of a string (provided as []byte) by adding backslashes before special
2024-02-18 10:42:21 +00:00
// characters, and turning others into specific escape sequences, such as
2024-02-18 10:42:21 +00:00
// turning newlines into \n and null bytes into \0.
2024-02-18 10:42:21 +00:00
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
2024-02-18 10:42:21 +00:00
func escapeBytesBackslash(buf, v []byte) []byte {
2024-02-18 10:42:21 +00:00
pos := len(buf)
2024-02-18 10:42:21 +00:00
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
2024-02-18 10:42:21 +00:00
switch c {
2024-02-18 10:42:21 +00:00
case '\x00':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '0'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\n':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'n'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\r':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'r'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\x1a':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'Z'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\'':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\''
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '"':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '"'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\\':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\\'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
buf[pos] = c
2024-02-18 10:42:21 +00:00
pos++
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
return buf[:pos]
2024-02-18 10:42:21 +00:00
}
// escapeStringBackslash is similar to escapeBytesBackslash but for string.
2024-02-18 10:42:21 +00:00
func escapeStringBackslash(buf []byte, v string) []byte {
2024-02-18 10:42:21 +00:00
pos := len(buf)
2024-02-18 10:42:21 +00:00
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
2024-02-18 10:42:21 +00:00
c := v[i]
2024-02-18 10:42:21 +00:00
switch c {
2024-02-18 10:42:21 +00:00
case '\x00':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '0'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\n':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'n'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\r':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'r'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\x1a':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = 'Z'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\'':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\''
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '"':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '"'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
case '\\':
2024-02-18 10:42:21 +00:00
buf[pos] = '\\'
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\\'
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
buf[pos] = c
2024-02-18 10:42:21 +00:00
pos++
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
return buf[:pos]
2024-02-18 10:42:21 +00:00
}
// escapeBytesQuotes escapes apostrophes in []byte by doubling them up.
2024-02-18 10:42:21 +00:00
// This escapes the contents of a string by doubling up any apostrophes that
2024-02-18 10:42:21 +00:00
// it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
2024-02-18 10:42:21 +00:00
// effect on the server.
2024-02-18 10:42:21 +00:00
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
2024-02-18 10:42:21 +00:00
func escapeBytesQuotes(buf, v []byte) []byte {
2024-02-18 10:42:21 +00:00
pos := len(buf)
2024-02-18 10:42:21 +00:00
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
2024-02-18 10:42:21 +00:00
if c == '\'' {
2024-02-18 10:42:21 +00:00
buf[pos] = '\''
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\''
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
} else {
2024-02-18 10:42:21 +00:00
buf[pos] = c
2024-02-18 10:42:21 +00:00
pos++
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
return buf[:pos]
2024-02-18 10:42:21 +00:00
}
// escapeStringQuotes is similar to escapeBytesQuotes but for string.
2024-02-18 10:42:21 +00:00
func escapeStringQuotes(buf []byte, v string) []byte {
2024-02-18 10:42:21 +00:00
pos := len(buf)
2024-02-18 10:42:21 +00:00
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
2024-02-18 10:42:21 +00:00
c := v[i]
2024-02-18 10:42:21 +00:00
if c == '\'' {
2024-02-18 10:42:21 +00:00
buf[pos] = '\''
2024-02-18 10:42:21 +00:00
buf[pos+1] = '\''
2024-02-18 10:42:21 +00:00
pos += 2
2024-02-18 10:42:21 +00:00
} else {
2024-02-18 10:42:21 +00:00
buf[pos] = c
2024-02-18 10:42:21 +00:00
pos++
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
return buf[:pos]
2024-02-18 10:42:21 +00:00
}
/******************************************************************************
2024-02-18 10:42:21 +00:00
* Sync utils *
2024-02-18 10:42:21 +00:00
******************************************************************************/
// noCopy may be embedded into structs which must not be copied
2024-02-18 10:42:21 +00:00
// after the first use.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// See https://github.com/golang/go/issues/8005#issuecomment-190753527
2024-02-18 10:42:21 +00:00
// for details.
2024-02-18 10:42:21 +00:00
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
2024-02-18 10:42:21 +00:00
func (*noCopy) Lock() {}
// atomicBool is a wrapper around uint32 for usage as a boolean value with
2024-02-18 10:42:21 +00:00
// atomic access.
2024-02-18 10:42:21 +00:00
type atomicBool struct {
_noCopy noCopy
value uint32
2024-02-18 10:42:21 +00:00
}
// IsSet returns whether the current boolean value is true
2024-02-18 10:42:21 +00:00
func (ab *atomicBool) IsSet() bool {
2024-02-18 10:42:21 +00:00
return atomic.LoadUint32(&ab.value) > 0
2024-02-18 10:42:21 +00:00
}
// Set sets the value of the bool regardless of the previous value
2024-02-18 10:42:21 +00:00
func (ab *atomicBool) Set(value bool) {
2024-02-18 10:42:21 +00:00
if value {
2024-02-18 10:42:21 +00:00
atomic.StoreUint32(&ab.value, 1)
2024-02-18 10:42:21 +00:00
} else {
2024-02-18 10:42:21 +00:00
atomic.StoreUint32(&ab.value, 0)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
// TrySet sets the value of the bool and returns whether the value changed
2024-02-18 10:42:21 +00:00
func (ab *atomicBool) TrySet(value bool) bool {
2024-02-18 10:42:21 +00:00
if value {
2024-02-18 10:42:21 +00:00
return atomic.SwapUint32(&ab.value, 1) == 0
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return atomic.SwapUint32(&ab.value, 0) > 0
2024-02-18 10:42:21 +00:00
}
// atomicError is a wrapper for atomically accessed error values
2024-02-18 10:42:21 +00:00
type atomicError struct {
_noCopy noCopy
value atomic.Value
2024-02-18 10:42:21 +00:00
}
// Set sets the error value regardless of the previous value.
2024-02-18 10:42:21 +00:00
// The value must not be nil
2024-02-18 10:42:21 +00:00
func (ae *atomicError) Set(value error) {
2024-02-18 10:42:21 +00:00
ae.value.Store(value)
2024-02-18 10:42:21 +00:00
}
// Value returns the current error value
2024-02-18 10:42:21 +00:00
func (ae *atomicError) Value() error {
2024-02-18 10:42:21 +00:00
if v := ae.value.Load(); v != nil {
2024-02-18 10:42:21 +00:00
// this will panic if the value doesn't implement the error interface
2024-02-18 10:42:21 +00:00
return v.(error)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
2024-02-18 10:42:21 +00:00
dargs := make([]driver.Value, len(named))
2024-02-18 10:42:21 +00:00
for n, param := range named {
2024-02-18 10:42:21 +00:00
if len(param.Name) > 0 {
2024-02-18 10:42:21 +00:00
// TODO: support the use of Named Parameters #561
2024-02-18 10:42:21 +00:00
return nil, errors.New("mysql: driver does not support the use of Named Parameters")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
dargs[n] = param.Value
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return dargs, nil
2024-02-18 10:42:21 +00:00
}
func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
2024-02-18 10:42:21 +00:00
switch sql.IsolationLevel(level) {
2024-02-18 10:42:21 +00:00
case sql.LevelRepeatableRead:
2024-02-18 10:42:21 +00:00
return "REPEATABLE READ", nil
2024-02-18 10:42:21 +00:00
case sql.LevelReadCommitted:
2024-02-18 10:42:21 +00:00
return "READ COMMITTED", nil
2024-02-18 10:42:21 +00:00
case sql.LevelReadUncommitted:
2024-02-18 10:42:21 +00:00
return "READ UNCOMMITTED", nil
2024-02-18 10:42:21 +00:00
case sql.LevelSerializable:
2024-02-18 10:42:21 +00:00
return "SERIALIZABLE", nil
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}