Files
kubesphere/vendor/github.com/Masterminds/squirrel/squirrel.go
Roland.Ma 7bb8124a61 pin dependencies
Signed-off-by: Roland.Ma <rolandma@yunify.com>
2021-08-27 06:37:31 +00:00

167 lines
4.3 KiB
Go

// Package squirrel provides a fluent SQL generator.
//
// See https://github.com/lann/squirrel for examples.
package squirrel
import (
"bytes"
"database/sql"
"fmt"
"strings"
"github.com/lann/builder"
)
// Sqlizer is the interface that wraps the ToSql method.
//
// ToSql returns a SQL representation of the Sqlizer, along with a slice of args
// as passed to e.g. database/sql.Exec. It can also return an error.
type Sqlizer interface {
ToSql() (string, []interface{}, error)
}
// Execer is the interface that wraps the Exec method.
//
// Exec executes the given query as implemented by database/sql.Exec.
type Execer interface {
Exec(query string, args ...interface{}) (sql.Result, error)
}
// Queryer is the interface that wraps the Query method.
//
// Query executes the given query as implemented by database/sql.Query.
type Queryer interface {
Query(query string, args ...interface{}) (*sql.Rows, error)
}
// QueryRower is the interface that wraps the QueryRow method.
//
// QueryRow executes the given query as implemented by database/sql.QueryRow.
type QueryRower interface {
QueryRow(query string, args ...interface{}) RowScanner
}
// BaseRunner groups the Execer and Queryer interfaces.
type BaseRunner interface {
Execer
Queryer
}
// Runner groups the Execer, Queryer, and QueryRower interfaces.
type Runner interface {
Execer
Queryer
QueryRower
}
// DBRunner wraps sql.DB to implement Runner.
type dbRunner struct {
*sql.DB
}
func (r *dbRunner) QueryRow(query string, args ...interface{}) RowScanner {
return r.DB.QueryRow(query, args...)
}
type txRunner struct {
*sql.Tx
}
func (r *txRunner) QueryRow(query string, args ...interface{}) RowScanner {
return r.Tx.QueryRow(query, args...)
}
func setRunWith(b interface{}, baseRunner BaseRunner) interface{} {
var runner Runner
switch r := baseRunner.(type) {
case Runner:
runner = r
case *sql.DB:
runner = &dbRunner{r}
case *sql.Tx:
runner = &txRunner{r}
}
return builder.Set(b, "RunWith", runner)
}
// RunnerNotSet is returned by methods that need a Runner if it isn't set.
var RunnerNotSet = fmt.Errorf("cannot run; no Runner set (RunWith)")
// RunnerNotQueryRunner is returned by QueryRow if the RunWith value doesn't implement QueryRower.
var RunnerNotQueryRunner = fmt.Errorf("cannot QueryRow; Runner is not a QueryRower")
// ExecWith Execs the SQL returned by s with db.
func ExecWith(db Execer, s Sqlizer) (res sql.Result, err error) {
query, args, err := s.ToSql()
if err != nil {
return
}
return db.Exec(query, args...)
}
// QueryWith Querys the SQL returned by s with db.
func QueryWith(db Queryer, s Sqlizer) (rows *sql.Rows, err error) {
query, args, err := s.ToSql()
if err != nil {
return
}
return db.Query(query, args...)
}
// QueryRowWith QueryRows the SQL returned by s with db.
func QueryRowWith(db QueryRower, s Sqlizer) RowScanner {
query, args, err := s.ToSql()
return &Row{RowScanner: db.QueryRow(query, args...), err: err}
}
// DebugSqlizer calls ToSql on s and shows the approximate SQL to be executed
//
// If ToSql returns an error, the result of this method will look like:
// "[ToSql error: %s]" or "[DebugSqlizer error: %s]"
//
// IMPORTANT: As its name suggests, this function should only be used for
// debugging. While the string result *might* be valid SQL, this function does
// not try very hard to ensure it. Additionally, executing the output of this
// function with any untrusted user input is certainly insecure.
func DebugSqlizer(s Sqlizer) string {
sql, args, err := s.ToSql()
if err != nil {
return fmt.Sprintf("[ToSql error: %s]", err)
}
// TODO: dedupe this with placeholder.go
buf := &bytes.Buffer{}
i := 0
for {
p := strings.Index(sql, "?")
if p == -1 {
break
}
if len(sql[p:]) > 1 && sql[p:p+2] == "??" { // escape ?? => ?
buf.WriteString(sql[:p])
buf.WriteString("?")
if len(sql[p:]) == 1 {
break
}
sql = sql[p+2:]
} else {
if i+1 > len(args) {
return fmt.Sprintf(
"[DebugSqlizer error: too many placeholders in %#v for %d args]",
sql, len(args))
}
buf.WriteString(sql[:p])
fmt.Fprintf(buf, "'%v'", args[i])
sql = sql[p+1:]
i++
}
}
if i < len(args) {
return fmt.Sprintf(
"[DebugSqlizer error: not enough placeholders in %#v for %d args]",
sql, len(args))
}
buf.WriteString(sql)
return buf.String()
}