85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package sqlx
|
|
|
|
import (
|
|
"bytes"
|
|
"strconv"
|
|
)
|
|
|
|
// Bindvar types supported by Rebind, BindMap and BindStruct.
|
|
const (
|
|
UNKNOWN = iota
|
|
QUESTION
|
|
DOLLAR
|
|
NAMED
|
|
)
|
|
|
|
// BindType returns the bindtype for a given database given a drivername.
|
|
func BindType(driverName string) int {
|
|
switch driverName {
|
|
case "postgres", "pgx":
|
|
return DOLLAR
|
|
case "mysql":
|
|
return QUESTION
|
|
case "sqlite3":
|
|
return QUESTION
|
|
case "oci8":
|
|
return NAMED
|
|
}
|
|
return UNKNOWN
|
|
}
|
|
|
|
// FIXME: this should be able to be tolerant of escaped ?'s in queries without
|
|
// losing much speed, and should be to avoid confusion.
|
|
|
|
// FIXME: this is now produces the wrong results for oracle's NAMED bindtype
|
|
|
|
// Rebind a query from the default bindtype (QUESTION) to the target bindtype.
|
|
func Rebind(bindType int, query string) string {
|
|
if bindType != DOLLAR {
|
|
return query
|
|
}
|
|
|
|
qb := []byte(query)
|
|
// Add space enough for 10 params before we have to allocate
|
|
rqb := make([]byte, 0, len(qb)+10)
|
|
j := 1
|
|
for _, b := range qb {
|
|
if b == '?' {
|
|
rqb = append(rqb, '$')
|
|
for _, b := range strconv.Itoa(j) {
|
|
rqb = append(rqb, byte(b))
|
|
}
|
|
j++
|
|
} else {
|
|
rqb = append(rqb, b)
|
|
}
|
|
}
|
|
return string(rqb)
|
|
}
|
|
|
|
// Experimental implementation of Rebind which uses a bytes.Buffer. The code is
|
|
// much simpler and should be more resistant to odd unicode, but it is twice as
|
|
// slow. Kept here for benchmarking purposes and to possibly replace Rebind if
|
|
// problems arise with its somewhat naive handling of unicode.
|
|
|
|
func rebindBuff(bindType int, query string) string {
|
|
if bindType != DOLLAR {
|
|
return query
|
|
}
|
|
|
|
b := make([]byte, 0, len(query))
|
|
rqb := bytes.NewBuffer(b)
|
|
j := 1
|
|
for _, r := range query {
|
|
if r == '?' {
|
|
rqb.WriteRune('$')
|
|
rqb.WriteString(strconv.Itoa(j))
|
|
j++
|
|
} else {
|
|
rqb.WriteRune(r)
|
|
}
|
|
}
|
|
|
|
return rqb.String()
|
|
}
|