devops tenant api

Signed-off-by: runzexia <runzexia@yunify.com>
This commit is contained in:
runzexia
2019-04-23 20:47:47 +08:00
committed by zryfish
parent 78f2dab18c
commit 5a6f51d775
143 changed files with 19533 additions and 341 deletions

20
vendor/github.com/gocraft/dbr/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014-2017 Jonathan Novak, Tai-Lin Chu
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

29
vendor/github.com/gocraft/dbr/buffer.go generated vendored Normal file
View File

@@ -0,0 +1,29 @@
package dbr
import "bytes"
type Buffer interface {
WriteString(s string) (n int, err error)
String() string
WriteValue(v ...interface{}) (err error)
Value() []interface{}
}
type buffer struct {
bytes.Buffer
v []interface{}
}
func NewBuffer() Buffer {
return &buffer{}
}
func (b *buffer) WriteValue(v ...interface{}) error {
b.v = append(b.v, v...)
return nil
}
func (b *buffer) Value() []interface{} {
return b.v
}

13
vendor/github.com/gocraft/dbr/builder.go generated vendored Normal file
View File

@@ -0,0 +1,13 @@
package dbr
// Builder builds sql in one dialect like MySQL/PostgreSQL
// e.g. XxxBuilder
type Builder interface {
Build(Dialect, Buffer) error
}
type BuildFunc func(Dialect, Buffer) error
func (b BuildFunc) Build(d Dialect, buf Buffer) error {
return b(d, buf)
}

119
vendor/github.com/gocraft/dbr/condition.go generated vendored Normal file
View File

@@ -0,0 +1,119 @@
package dbr
import "reflect"
func buildCond(d Dialect, buf Buffer, pred string, cond ...Builder) error {
for i, c := range cond {
if i > 0 {
buf.WriteString(" ")
buf.WriteString(pred)
buf.WriteString(" ")
}
buf.WriteString("(")
err := c.Build(d, buf)
if err != nil {
return err
}
buf.WriteString(")")
}
return nil
}
// And creates AND from a list of conditions
func And(cond ...Builder) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCond(d, buf, "AND", cond...)
})
}
// Or creates OR from a list of conditions
func Or(cond ...Builder) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCond(d, buf, "OR", cond...)
})
}
func buildCmp(d Dialect, buf Buffer, pred string, column string, value interface{}) error {
buf.WriteString(d.QuoteIdent(column))
buf.WriteString(" ")
buf.WriteString(pred)
buf.WriteString(" ")
buf.WriteString(placeholder)
buf.WriteValue(value)
return nil
}
// Eq is `=`.
// When value is nil, it will be translated to `IS NULL`.
// When value is a slice, it will be translated to `IN`.
// Otherwise it will be translated to `=`.
func Eq(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
if value == nil {
buf.WriteString(d.QuoteIdent(column))
buf.WriteString(" IS NULL")
return nil
}
v := reflect.ValueOf(value)
if v.Kind() == reflect.Slice {
if v.Len() == 0 {
buf.WriteString(d.EncodeBool(false))
return nil
}
return buildCmp(d, buf, "IN", column, value)
}
return buildCmp(d, buf, "=", column, value)
})
}
// Neq is `!=`.
// When value is nil, it will be translated to `IS NOT NULL`.
// When value is a slice, it will be translated to `NOT IN`.
// Otherwise it will be translated to `!=`.
func Neq(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
if value == nil {
buf.WriteString(d.QuoteIdent(column))
buf.WriteString(" IS NOT NULL")
return nil
}
v := reflect.ValueOf(value)
if v.Kind() == reflect.Slice {
if v.Len() == 0 {
buf.WriteString(d.EncodeBool(true))
return nil
}
return buildCmp(d, buf, "NOT IN", column, value)
}
return buildCmp(d, buf, "!=", column, value)
})
}
// Gt is `>`.
func Gt(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCmp(d, buf, ">", column, value)
})
}
// Gte is '>='.
func Gte(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCmp(d, buf, ">=", column, value)
})
}
// Lt is '<'.
func Lt(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCmp(d, buf, "<", column, value)
})
}
// Lte is `<=`.
func Lte(column string, value interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
return buildCmp(d, buf, "<=", column, value)
})
}

174
vendor/github.com/gocraft/dbr/dbr.go generated vendored Normal file
View File

@@ -0,0 +1,174 @@
package dbr
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/gocraft/dbr/dialect"
)
// Open instantiates a Connection for a given database/sql connection
// and event receiver
func Open(driver, dsn string, log EventReceiver) (*Connection, error) {
if log == nil {
log = nullReceiver
}
conn, err := sql.Open(driver, dsn)
if err != nil {
return nil, err
}
var d Dialect
switch driver {
case "mysql":
d = dialect.MySQL
case "postgres":
d = dialect.PostgreSQL
case "sqlite3":
d = dialect.SQLite3
default:
return nil, ErrNotSupported
}
return &Connection{DB: conn, EventReceiver: log, Dialect: d}, nil
}
const (
placeholder = "?"
)
// Connection is a connection to the database with an EventReceiver
// to send events, errors, and timings to
type Connection struct {
*sql.DB
Dialect Dialect
EventReceiver
}
// Session represents a business unit of execution for some connection
type Session struct {
*Connection
EventReceiver
Timeout time.Duration
}
func (s *Session) GetTimeout() time.Duration {
return s.Timeout
}
// NewSession instantiates a Session for the Connection
func (conn *Connection) NewSession(log EventReceiver) *Session {
if log == nil {
log = conn.EventReceiver // Use parent instrumentation
}
return &Session{Connection: conn, EventReceiver: log}
}
// Ensure that tx and session are session runner
var (
_ SessionRunner = (*Tx)(nil)
_ SessionRunner = (*Session)(nil)
)
// SessionRunner can do anything that a Session can except start a transaction.
type SessionRunner interface {
Select(column ...string) *SelectBuilder
SelectBySql(query string, value ...interface{}) *SelectBuilder
InsertInto(table string) *InsertBuilder
InsertBySql(query string, value ...interface{}) *InsertBuilder
Update(table string) *UpdateBuilder
UpdateBySql(query string, value ...interface{}) *UpdateBuilder
DeleteFrom(table string) *DeleteBuilder
DeleteBySql(query string, value ...interface{}) *DeleteBuilder
}
type runner interface {
GetTimeout() time.Duration
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
}
func exec(ctx context.Context, runner runner, log EventReceiver, builder Builder, d Dialect) (sql.Result, error) {
timeout := runner.GetTimeout()
if timeout > 0 {
var cancel func()
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
i := interpolator{
Buffer: NewBuffer(),
Dialect: d,
IgnoreBinary: true,
}
err := i.interpolate(placeholder, []interface{}{builder})
query, value := i.String(), i.Value()
if err != nil {
return nil, log.EventErrKv("dbr.exec.interpolate", err, kvs{
"sql": query,
"args": fmt.Sprint(value),
})
}
startTime := time.Now()
defer func() {
log.TimingKv("dbr.exec", time.Since(startTime).Nanoseconds(), kvs{
"sql": query,
})
}()
result, err := runner.ExecContext(ctx, query, value...)
if err != nil {
return result, log.EventErrKv("dbr.exec.exec", err, kvs{
"sql": query,
})
}
return result, nil
}
func query(ctx context.Context, runner runner, log EventReceiver, builder Builder, d Dialect, dest interface{}) (int, error) {
timeout := runner.GetTimeout()
if timeout > 0 {
var cancel func()
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
i := interpolator{
Buffer: NewBuffer(),
Dialect: d,
IgnoreBinary: true,
}
err := i.interpolate(placeholder, []interface{}{builder})
query, value := i.String(), i.Value()
if err != nil {
return 0, log.EventErrKv("dbr.select.interpolate", err, kvs{
"sql": query,
"args": fmt.Sprint(value),
})
}
startTime := time.Now()
defer func() {
log.TimingKv("dbr.select", time.Since(startTime).Nanoseconds(), kvs{
"sql": query,
})
}()
rows, err := runner.QueryContext(ctx, query, value...)
if err != nil {
return 0, log.EventErrKv("dbr.select.load.query", err, kvs{
"sql": query,
})
}
count, err := Load(rows, dest)
if err != nil {
return 0, log.EventErrKv("dbr.select.load.scan", err, kvs{
"sql": query,
})
}
return count, nil
}

61
vendor/github.com/gocraft/dbr/delete.go generated vendored Normal file
View File

@@ -0,0 +1,61 @@
package dbr
// DeleteStmt builds `DELETE ...`
type DeleteStmt struct {
raw
Table string
WhereCond []Builder
}
// Build builds `DELETE ...` in dialect
func (b *DeleteStmt) Build(d Dialect, buf Buffer) error {
if b.raw.Query != "" {
return b.raw.Build(d, buf)
}
if b.Table == "" {
return ErrTableNotSpecified
}
buf.WriteString("DELETE FROM ")
buf.WriteString(d.QuoteIdent(b.Table))
if len(b.WhereCond) > 0 {
buf.WriteString(" WHERE ")
err := And(b.WhereCond...).Build(d, buf)
if err != nil {
return err
}
}
return nil
}
// DeleteFrom creates a DeleteStmt
func DeleteFrom(table string) *DeleteStmt {
return &DeleteStmt{
Table: table,
}
}
// DeleteBySql creates a DeleteStmt from raw query
func DeleteBySql(query string, value ...interface{}) *DeleteStmt {
return &DeleteStmt{
raw: raw{
Query: query,
Value: value,
},
}
}
// Where adds a where condition
func (b *DeleteStmt) Where(query interface{}, value ...interface{}) *DeleteStmt {
switch query := query.(type) {
case string:
b.WhereCond = append(b.WhereCond, Expr(query, value...))
case Builder:
b.WhereCond = append(b.WhereCond, query)
}
return b
}

87
vendor/github.com/gocraft/dbr/delete_builder.go generated vendored Normal file
View File

@@ -0,0 +1,87 @@
package dbr
import (
"context"
"database/sql"
"fmt"
)
type DeleteBuilder struct {
runner
EventReceiver
Dialect Dialect
*DeleteStmt
LimitCount int64
}
func (sess *Session) DeleteFrom(table string) *DeleteBuilder {
return &DeleteBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
DeleteStmt: DeleteFrom(table),
LimitCount: -1,
}
}
func (tx *Tx) DeleteFrom(table string) *DeleteBuilder {
return &DeleteBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
DeleteStmt: DeleteFrom(table),
LimitCount: -1,
}
}
func (sess *Session) DeleteBySql(query string, value ...interface{}) *DeleteBuilder {
return &DeleteBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
DeleteStmt: DeleteBySql(query, value...),
LimitCount: -1,
}
}
func (tx *Tx) DeleteBySql(query string, value ...interface{}) *DeleteBuilder {
return &DeleteBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
DeleteStmt: DeleteBySql(query, value...),
LimitCount: -1,
}
}
func (b *DeleteBuilder) Exec() (sql.Result, error) {
return b.ExecContext(context.Background())
}
func (b *DeleteBuilder) ExecContext(ctx context.Context) (sql.Result, error) {
return exec(ctx, b.runner, b.EventReceiver, b, b.Dialect)
}
func (b *DeleteBuilder) Where(query interface{}, value ...interface{}) *DeleteBuilder {
b.DeleteStmt.Where(query, value...)
return b
}
func (b *DeleteBuilder) Limit(n uint64) *DeleteBuilder {
b.LimitCount = int64(n)
return b
}
func (b *DeleteBuilder) Build(d Dialect, buf Buffer) error {
err := b.DeleteStmt.Build(b.Dialect, buf)
if err != nil {
return err
}
if b.LimitCount >= 0 {
buf.WriteString(" LIMIT ")
buf.WriteString(fmt.Sprint(b.LimitCount))
}
return nil
}

15
vendor/github.com/gocraft/dbr/dialect.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
package dbr
import "time"
// Dialect abstracts database differences
type Dialect interface {
QuoteIdent(id string) string
EncodeString(s string) string
EncodeBool(b bool) string
EncodeTime(t time.Time) string
EncodeBytes(b []byte) string
Placeholder(n int) string
}

24
vendor/github.com/gocraft/dbr/dialect/dialect.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package dialect
import "strings"
var (
// MySQL dialect
MySQL = mysql{}
// PostgreSQL dialect
PostgreSQL = postgreSQL{}
// SQLite3 dialect
SQLite3 = sqlite3{}
)
const (
timeFormat = "2006-01-02 15:04:05.000000"
)
func quoteIdent(s, quote string) string {
part := strings.SplitN(s, ".", 2)
if len(part) == 2 {
return quoteIdent(part[0], quote) + "." + quoteIdent(part[1], quote)
}
return quote + s + quote
}

66
vendor/github.com/gocraft/dbr/dialect/mysql.go generated vendored Normal file
View File

@@ -0,0 +1,66 @@
package dialect
import (
"bytes"
"fmt"
"time"
)
type mysql struct{}
func (d mysql) QuoteIdent(s string) string {
return quoteIdent(s, "`")
}
func (d mysql) EncodeString(s string) string {
buf := new(bytes.Buffer)
buf.WriteRune('\'')
// https://dev.mysql.com/doc/refman/5.7/en/string-literals.html
for i := 0; i < len(s); i++ {
switch s[i] {
case 0:
buf.WriteString(`\0`)
case '\'':
buf.WriteString(`\'`)
case '"':
buf.WriteString(`\"`)
case '\b':
buf.WriteString(`\b`)
case '\n':
buf.WriteString(`\n`)
case '\r':
buf.WriteString(`\r`)
case '\t':
buf.WriteString(`\t`)
case 26:
buf.WriteString(`\Z`)
case '\\':
buf.WriteString(`\\`)
default:
buf.WriteByte(s[i])
}
}
buf.WriteRune('\'')
return buf.String()
}
func (d mysql) EncodeBool(b bool) string {
if b {
return "1"
}
return "0"
}
func (d mysql) EncodeTime(t time.Time) string {
return `'` + t.UTC().Format(timeFormat) + `'`
}
func (d mysql) EncodeBytes(b []byte) string {
return fmt.Sprintf(`0x%x`, b)
}
func (d mysql) Placeholder(_ int) string {
return "?"
}

37
vendor/github.com/gocraft/dbr/dialect/postgresql.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package dialect
import (
"fmt"
"strings"
"time"
)
type postgreSQL struct{}
func (d postgreSQL) QuoteIdent(s string) string {
return quoteIdent(s, `"`)
}
func (d postgreSQL) EncodeString(s string) string {
// http://www.postgresql.org/docs/9.2/static/sql-syntax-lexical.html
return `'` + strings.Replace(s, `'`, `''`, -1) + `'`
}
func (d postgreSQL) EncodeBool(b bool) string {
if b {
return "TRUE"
}
return "FALSE"
}
func (d postgreSQL) EncodeTime(t time.Time) string {
return MySQL.EncodeTime(t)
}
func (d postgreSQL) EncodeBytes(b []byte) string {
return fmt.Sprintf(`E'\\x%x'`, b)
}
func (d postgreSQL) Placeholder(n int) string {
return fmt.Sprintf("$%d", n+1)
}

40
vendor/github.com/gocraft/dbr/dialect/sqlite3.go generated vendored Normal file
View File

@@ -0,0 +1,40 @@
package dialect
import (
"fmt"
"strings"
"time"
)
type sqlite3 struct{}
func (d sqlite3) QuoteIdent(s string) string {
return quoteIdent(s, `"`)
}
func (d sqlite3) EncodeString(s string) string {
// https://www.sqlite.org/faq.html
return `'` + strings.Replace(s, `'`, `''`, -1) + `'`
}
func (d sqlite3) EncodeBool(b bool) string {
// https://www.sqlite.org/lang_expr.html
if b {
return "1"
}
return "0"
}
func (d sqlite3) EncodeTime(t time.Time) string {
// https://www.sqlite.org/lang_datefunc.html
return MySQL.EncodeTime(t)
}
func (d sqlite3) EncodeBytes(b []byte) string {
// https://www.sqlite.org/lang_expr.html
return fmt.Sprintf(`X'%x'`, b)
}
func (d sqlite3) Placeholder(_ int) string {
return "?"
}

16
vendor/github.com/gocraft/dbr/errors.go generated vendored Normal file
View File

@@ -0,0 +1,16 @@
package dbr
import "errors"
// package errors
var (
ErrNotFound = errors.New("dbr: not found")
ErrNotSupported = errors.New("dbr: not supported")
ErrTableNotSpecified = errors.New("dbr: table not specified")
ErrColumnNotSpecified = errors.New("dbr: column not specified")
ErrInvalidPointer = errors.New("dbr: attempt to load into an invalid pointer")
ErrPlaceholderCount = errors.New("dbr: wrong placeholder count")
ErrInvalidSliceLength = errors.New("dbr: length of slice is 0. length must be >= 1")
ErrCantConvertToTime = errors.New("dbr: can't convert to time.Time")
ErrInvalidTimestring = errors.New("dbr: invalid time string")
)

40
vendor/github.com/gocraft/dbr/event.go generated vendored Normal file
View File

@@ -0,0 +1,40 @@
package dbr
// EventReceiver gets events from dbr methods for logging purposes
type EventReceiver interface {
Event(eventName string)
EventKv(eventName string, kvs map[string]string)
EventErr(eventName string, err error) error
EventErrKv(eventName string, err error, kvs map[string]string) error
Timing(eventName string, nanoseconds int64)
TimingKv(eventName string, nanoseconds int64, kvs map[string]string)
}
type kvs map[string]string
var nullReceiver = &NullEventReceiver{}
// NullEventReceiver is a sentinel EventReceiver; use it if the caller doesn't supply one
type NullEventReceiver struct{}
// Event receives a simple notification when various events occur
func (n *NullEventReceiver) Event(eventName string) {}
// EventKv receives a notification when various events occur along with
// optional key/value data
func (n *NullEventReceiver) EventKv(eventName string, kvs map[string]string) {}
// EventErr receives a notification of an error if one occurs
func (n *NullEventReceiver) EventErr(eventName string, err error) error { return err }
// EventErrKv receives a notification of an error if one occurs along with
// optional key/value data
func (n *NullEventReceiver) EventErrKv(eventName string, err error, kvs map[string]string) error {
return err
}
// Timing receives the time an event took to happen
func (n *NullEventReceiver) Timing(eventName string, nanoseconds int64) {}
// TimingKv receives the time an event took to happen along with optional key/value data
func (n *NullEventReceiver) TimingKv(eventName string, nanoseconds int64, kvs map[string]string) {}

18
vendor/github.com/gocraft/dbr/expr.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
package dbr
// XxxBuilders all support raw query
type raw struct {
Query string
Value []interface{}
}
// Expr should be used when sql syntax is not supported
func Expr(query string, value ...interface{}) Builder {
return &raw{Query: query, Value: value}
}
func (raw *raw) Build(_ Dialect, buf Buffer) error {
buf.WriteString(raw.Query)
buf.WriteValue(raw.Value...)
return nil
}

24
vendor/github.com/gocraft/dbr/ident.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package dbr
// identifier is a type of string
type I string
func (i I) Build(d Dialect, buf Buffer) error {
buf.WriteString(d.QuoteIdent(string(i)))
return nil
}
// As creates an alias for expr. e.g. SELECT `a1` AS `a2`
func (i I) As(alias string) Builder {
return as(i, alias)
}
func as(expr interface{}, alias string) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
buf.WriteString(placeholder)
buf.WriteValue(expr)
buf.WriteString(" AS ")
buf.WriteString(d.QuoteIdent(alias))
return nil
})
}

123
vendor/github.com/gocraft/dbr/insert.go generated vendored Normal file
View File

@@ -0,0 +1,123 @@
package dbr
import (
"bytes"
"reflect"
)
// InsertStmt builds `INSERT INTO ...`
type InsertStmt struct {
raw
Table string
Column []string
Value [][]interface{}
ReturnColumn []string
}
// Build builds `INSERT INTO ...` in dialect
func (b *InsertStmt) Build(d Dialect, buf Buffer) error {
if b.raw.Query != "" {
return b.raw.Build(d, buf)
}
if b.Table == "" {
return ErrTableNotSpecified
}
if len(b.Column) == 0 {
return ErrColumnNotSpecified
}
buf.WriteString("INSERT INTO ")
buf.WriteString(d.QuoteIdent(b.Table))
placeholderBuf := new(bytes.Buffer)
placeholderBuf.WriteString("(")
buf.WriteString(" (")
for i, col := range b.Column {
if i > 0 {
buf.WriteString(",")
placeholderBuf.WriteString(",")
}
buf.WriteString(d.QuoteIdent(col))
placeholderBuf.WriteString(placeholder)
}
buf.WriteString(") VALUES ")
placeholderBuf.WriteString(")")
placeholderStr := placeholderBuf.String()
for i, tuple := range b.Value {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(placeholderStr)
buf.WriteValue(tuple...)
}
if len(b.ReturnColumn) > 0 {
buf.WriteString(" RETURNING ")
for i, col := range b.ReturnColumn {
if i > 0 {
buf.WriteString(",")
}
buf.WriteString(d.QuoteIdent(col))
}
}
return nil
}
// InsertInto creates an InsertStmt
func InsertInto(table string) *InsertStmt {
return &InsertStmt{
Table: table,
}
}
// InsertBySql creates an InsertStmt from raw query
func InsertBySql(query string, value ...interface{}) *InsertStmt {
return &InsertStmt{
raw: raw{
Query: query,
Value: value,
},
}
}
// Columns adds columns
func (b *InsertStmt) Columns(column ...string) *InsertStmt {
b.Column = column
return b
}
// Values adds a tuple for columns
func (b *InsertStmt) Values(value ...interface{}) *InsertStmt {
b.Value = append(b.Value, value)
return b
}
// Record adds a tuple for columns from a struct
func (b *InsertStmt) Record(structValue interface{}) *InsertStmt {
v := reflect.Indirect(reflect.ValueOf(structValue))
if v.Kind() == reflect.Struct {
var value []interface{}
m := structMap(v)
for _, key := range b.Column {
if val, ok := m[key]; ok {
value = append(value, val.Interface())
} else {
value = append(value, nil)
}
}
b.Values(value...)
}
return b
}
func (b *InsertStmt) Returning(column ...string) *InsertStmt {
b.ReturnColumn = column
return b
}

126
vendor/github.com/gocraft/dbr/insert_builder.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package dbr
import (
"context"
"database/sql"
"reflect"
)
type InsertBuilder struct {
runner
EventReceiver
Dialect Dialect
RecordID reflect.Value
*InsertStmt
}
func (sess *Session) InsertInto(table string) *InsertBuilder {
return &InsertBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
InsertStmt: InsertInto(table),
}
}
func (tx *Tx) InsertInto(table string) *InsertBuilder {
return &InsertBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
InsertStmt: InsertInto(table),
}
}
func (sess *Session) InsertBySql(query string, value ...interface{}) *InsertBuilder {
return &InsertBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
InsertStmt: InsertBySql(query, value...),
}
}
func (tx *Tx) InsertBySql(query string, value ...interface{}) *InsertBuilder {
return &InsertBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
InsertStmt: InsertBySql(query, value...),
}
}
func (b *InsertBuilder) Pair(column string, value interface{}) *InsertBuilder {
b.Column = append(b.Column, column)
switch len(b.Value) {
case 0:
b.InsertStmt.Values(value)
case 1:
b.Value[0] = append(b.Value[0], value)
default:
panic("pair only allows one record to insert")
}
return b
}
func (b *InsertBuilder) Exec() (sql.Result, error) {
return b.ExecContext(context.Background())
}
func (b *InsertBuilder) ExecContext(ctx context.Context) (sql.Result, error) {
result, err := exec(ctx, b.runner, b.EventReceiver, b, b.Dialect)
if err != nil {
return nil, err
}
if b.RecordID.IsValid() {
if id, err := result.LastInsertId(); err == nil {
b.RecordID.SetInt(id)
}
}
return result, nil
}
func (b *InsertBuilder) LoadContext(ctx context.Context, value interface{}) error {
_, err := query(ctx, b.runner, b.EventReceiver, b, b.Dialect, value)
return err
}
func (b *InsertBuilder) Load(value interface{}) error {
return b.LoadContext(context.Background(), value)
}
func (b *InsertBuilder) Columns(column ...string) *InsertBuilder {
b.InsertStmt.Columns(column...)
return b
}
func (b *InsertBuilder) Returning(column ...string) *InsertBuilder {
b.InsertStmt.Returning(column...)
return b
}
func (b *InsertBuilder) Record(structValue interface{}) *InsertBuilder {
v := reflect.Indirect(reflect.ValueOf(structValue))
if v.Kind() == reflect.Struct && v.CanSet() {
// ID is recommended by golint here
for _, name := range []string{"Id", "ID"} {
field := v.FieldByName(name)
if field.IsValid() && field.Kind() == reflect.Int64 {
b.RecordID = field
break
}
}
}
b.InsertStmt.Record(structValue)
return b
}
func (b *InsertBuilder) Values(value ...interface{}) *InsertBuilder {
b.InsertStmt.Values(value...)
return b
}

157
vendor/github.com/gocraft/dbr/interpolate.go generated vendored Normal file
View File

@@ -0,0 +1,157 @@
package dbr
import (
"database/sql/driver"
"reflect"
"strconv"
"strings"
"time"
)
type interpolator struct {
Buffer
Dialect
IgnoreBinary bool
N int
}
// InterpolateForDialect replaces placeholder in query with corresponding value in dialect
func InterpolateForDialect(query string, value []interface{}, d Dialect) (string, error) {
i := interpolator{
Buffer: NewBuffer(),
Dialect: d,
}
err := i.interpolate(query, value)
if err != nil {
return "", err
}
return i.String(), nil
}
func (i *interpolator) interpolate(query string, value []interface{}) error {
if strings.Count(query, placeholder) != len(value) {
return ErrPlaceholderCount
}
valueIndex := 0
for {
index := strings.Index(query, placeholder)
if index == -1 {
break
}
i.WriteString(query[:index])
if _, ok := value[valueIndex].([]byte); ok && i.IgnoreBinary {
i.WriteString(i.Placeholder(i.N))
i.N++
i.WriteValue(value[valueIndex])
} else {
err := i.encodePlaceholder(value[valueIndex])
if err != nil {
return err
}
}
query = query[index+len(placeholder):]
valueIndex++
}
// placeholder not found; write remaining query
i.WriteString(query)
return nil
}
func (i *interpolator) encodePlaceholder(value interface{}) error {
if builder, ok := value.(Builder); ok {
pbuf := NewBuffer()
err := builder.Build(i.Dialect, pbuf)
if err != nil {
return err
}
paren := true
switch value.(type) {
case *SelectStmt:
case *union:
default:
paren = false
}
if paren {
i.WriteString("(")
}
err = i.interpolate(pbuf.String(), pbuf.Value())
if err != nil {
return err
}
if paren {
i.WriteString(")")
}
return nil
}
if valuer, ok := value.(driver.Valuer); ok {
// get driver.Valuer's data
var err error
value, err = valuer.Value()
if err != nil {
return err
}
}
if value == nil {
i.WriteString("NULL")
return nil
}
v := reflect.ValueOf(value)
switch v.Kind() {
case reflect.String:
i.WriteString(i.EncodeString(v.String()))
return nil
case reflect.Bool:
i.WriteString(i.EncodeBool(v.Bool()))
return nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i.WriteString(strconv.FormatInt(v.Int(), 10))
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
i.WriteString(strconv.FormatUint(v.Uint(), 10))
return nil
case reflect.Float32, reflect.Float64:
i.WriteString(strconv.FormatFloat(v.Float(), 'f', -1, 64))
return nil
case reflect.Struct:
if v.Type() == reflect.TypeOf(time.Time{}) {
i.WriteString(i.EncodeTime(v.Interface().(time.Time)))
return nil
}
case reflect.Slice:
if v.Type().Elem().Kind() == reflect.Uint8 {
// []byte
i.WriteString(i.EncodeBytes(v.Bytes()))
return nil
}
if v.Len() == 0 {
// FIXME: support zero-length slice
return ErrInvalidSliceLength
}
i.WriteString("(")
for n := 0; n < v.Len(); n++ {
if n > 0 {
i.WriteString(",")
}
err := i.encodePlaceholder(v.Index(n).Interface())
if err != nil {
return err
}
}
i.WriteString(")")
return nil
case reflect.Ptr:
if v.IsNil() {
i.WriteString("NULL")
return nil
}
return i.encodePlaceholder(v.Elem().Interface())
}
return ErrNotSupported
}

41
vendor/github.com/gocraft/dbr/join.go generated vendored Normal file
View File

@@ -0,0 +1,41 @@
package dbr
type joinType uint8
const (
inner joinType = iota
left
right
full
)
func join(t joinType, table interface{}, on interface{}) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
buf.WriteString(" ")
switch t {
case left:
buf.WriteString("LEFT ")
case right:
buf.WriteString("RIGHT ")
case full:
buf.WriteString("FULL ")
}
buf.WriteString("JOIN ")
switch table := table.(type) {
case string:
buf.WriteString(d.QuoteIdent(table))
default:
buf.WriteString(placeholder)
buf.WriteValue(table)
}
buf.WriteString(" ON ")
switch on := on.(type) {
case string:
buf.WriteString(on)
case Builder:
buf.WriteString(placeholder)
buf.WriteValue(on)
}
return nil
})
}

119
vendor/github.com/gocraft/dbr/load.go generated vendored Normal file
View File

@@ -0,0 +1,119 @@
package dbr
import (
"database/sql"
"reflect"
)
// Load loads any value from sql.Rows
func Load(rows *sql.Rows, value interface{}) (int, error) {
defer rows.Close()
column, err := rows.Columns()
if err != nil {
return 0, err
}
v := reflect.ValueOf(value)
if v.Kind() != reflect.Ptr || v.IsNil() {
return 0, ErrInvalidPointer
}
v = v.Elem()
isScanner := v.Addr().Type().Implements(typeScanner)
isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 && !isScanner
isMap := v.Kind() == reflect.Map && !isScanner
isMapOfSlices := isMap && v.Type().Elem().Kind() == reflect.Slice && v.Type().Elem().Elem().Kind() != reflect.Uint8
if isMap {
v.Set(reflect.MakeMap(v.Type()))
}
count := 0
for rows.Next() {
var elem, keyElem reflect.Value
var ptr []interface{}
var err error
if isMapOfSlices {
elem = reflect.New(v.Type().Elem().Elem()).Elem()
} else if isSlice || isMap {
elem = reflect.New(v.Type().Elem()).Elem()
} else {
elem = v
}
if isMap {
ptr, err = findPtr(column[1:], elem)
if err != nil {
return 0, err
}
keyElem = reflect.New(v.Type().Key()).Elem()
keyPtr, err := findPtr(column[0:1], keyElem)
if err != nil {
return 0, err
}
ptr = append(keyPtr, ptr...)
} else {
ptr, err = findPtr(column, elem)
if err != nil {
return 0, err
}
}
err = rows.Scan(ptr...)
if err != nil {
return 0, err
}
count++
if isSlice {
v.Set(reflect.Append(v, elem))
} else if isMapOfSlices {
s := v.MapIndex(keyElem)
if !s.IsValid() {
s = reflect.Zero(v.Type().Elem())
}
v.SetMapIndex(keyElem, reflect.Append(s, elem))
} else if isMap {
v.SetMapIndex(keyElem, elem)
} else {
break
}
}
return count, nil
}
type dummyScanner struct{}
func (dummyScanner) Scan(interface{}) error {
return nil
}
var (
dummyDest sql.Scanner = dummyScanner{}
typeScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
)
func findPtr(column []string, value reflect.Value) ([]interface{}, error) {
if value.Addr().Type().Implements(typeScanner) {
return []interface{}{value.Addr().Interface()}, nil
}
switch value.Kind() {
case reflect.Struct:
var ptr []interface{}
m := structMap(value)
for _, key := range column {
if val, ok := m[key]; ok {
ptr = append(ptr, val.Addr().Interface())
} else {
ptr = append(ptr, dummyDest)
}
}
return ptr, nil
case reflect.Ptr:
if value.IsNil() {
value.Set(reflect.New(value.Type().Elem()))
}
return findPtr(column, value.Elem())
}
return []interface{}{value.Addr().Interface()}, nil
}

19
vendor/github.com/gocraft/dbr/now.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package dbr
import (
"database/sql/driver"
"time"
)
// Now is a value that serializes to the current time
var Now = nowSentinel{}
const timeFormat = "2006-01-02 15:04:05.000000"
type nowSentinel struct{}
// Value implements a valuer for compatibility
func (n nowSentinel) Value() (driver.Value, error) {
now := time.Now().UTC().Format(timeFormat)
return now, nil
}

24
vendor/github.com/gocraft/dbr/order.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package dbr
type direction bool
// orderby directions
// most databases by default use asc
const (
asc direction = false
desc = true
)
func order(column string, dir direction) Builder {
return BuildFunc(func(d Dialect, buf Buffer) error {
// FIXME: no quote ident
buf.WriteString(column)
switch dir {
case asc:
buf.WriteString(" ASC")
case desc:
buf.WriteString(" DESC")
}
return nil
})
}

238
vendor/github.com/gocraft/dbr/select.go generated vendored Normal file
View File

@@ -0,0 +1,238 @@
package dbr
import "fmt"
// SelectStmt builds `SELECT ...`
type SelectStmt struct {
raw
IsDistinct bool
Column []interface{}
Table interface{}
JoinTable []Builder
WhereCond []Builder
Group []Builder
HavingCond []Builder
Order []Builder
LimitCount int64
OffsetCount int64
}
// Build builds `SELECT ...` in dialect
func (b *SelectStmt) Build(d Dialect, buf Buffer) error {
if b.raw.Query != "" {
return b.raw.Build(d, buf)
}
if len(b.Column) == 0 {
return ErrColumnNotSpecified
}
buf.WriteString("SELECT ")
if b.IsDistinct {
buf.WriteString("DISTINCT ")
}
for i, col := range b.Column {
if i > 0 {
buf.WriteString(", ")
}
switch col := col.(type) {
case string:
// FIXME: no quote ident
buf.WriteString(col)
default:
buf.WriteString(placeholder)
buf.WriteValue(col)
}
}
if b.Table != nil {
buf.WriteString(" FROM ")
switch table := b.Table.(type) {
case string:
// FIXME: no quote ident
buf.WriteString(table)
default:
buf.WriteString(placeholder)
buf.WriteValue(table)
}
if len(b.JoinTable) > 0 {
for _, join := range b.JoinTable {
err := join.Build(d, buf)
if err != nil {
return err
}
}
}
}
if len(b.WhereCond) > 0 {
buf.WriteString(" WHERE ")
err := And(b.WhereCond...).Build(d, buf)
if err != nil {
return err
}
}
if len(b.Group) > 0 {
buf.WriteString(" GROUP BY ")
for i, group := range b.Group {
if i > 0 {
buf.WriteString(", ")
}
err := group.Build(d, buf)
if err != nil {
return err
}
}
}
if len(b.HavingCond) > 0 {
buf.WriteString(" HAVING ")
err := And(b.HavingCond...).Build(d, buf)
if err != nil {
return err
}
}
if len(b.Order) > 0 {
buf.WriteString(" ORDER BY ")
for i, order := range b.Order {
if i > 0 {
buf.WriteString(", ")
}
err := order.Build(d, buf)
if err != nil {
return err
}
}
}
if b.LimitCount >= 0 {
buf.WriteString(" LIMIT ")
buf.WriteString(fmt.Sprint(b.LimitCount))
}
if b.OffsetCount >= 0 {
buf.WriteString(" OFFSET ")
buf.WriteString(fmt.Sprint(b.OffsetCount))
}
return nil
}
// Select creates a SelectStmt
func Select(column ...interface{}) *SelectStmt {
return &SelectStmt{
Column: column,
LimitCount: -1,
OffsetCount: -1,
}
}
// From specifies table
func (b *SelectStmt) From(table interface{}) *SelectStmt {
b.Table = table
return b
}
// SelectBySql creates a SelectStmt from raw query
func SelectBySql(query string, value ...interface{}) *SelectStmt {
return &SelectStmt{
raw: raw{
Query: query,
Value: value,
},
LimitCount: -1,
OffsetCount: -1,
}
}
// Distinct adds `DISTINCT`
func (b *SelectStmt) Distinct() *SelectStmt {
b.IsDistinct = true
return b
}
// Where adds a where condition
func (b *SelectStmt) Where(query interface{}, value ...interface{}) *SelectStmt {
switch query := query.(type) {
case string:
b.WhereCond = append(b.WhereCond, Expr(query, value...))
case Builder:
b.WhereCond = append(b.WhereCond, query)
}
return b
}
// Having adds a having condition
func (b *SelectStmt) Having(query interface{}, value ...interface{}) *SelectStmt {
switch query := query.(type) {
case string:
b.HavingCond = append(b.HavingCond, Expr(query, value...))
case Builder:
b.HavingCond = append(b.HavingCond, query)
}
return b
}
// GroupBy specifies columns for grouping
func (b *SelectStmt) GroupBy(col ...string) *SelectStmt {
for _, group := range col {
b.Group = append(b.Group, Expr(group))
}
return b
}
// OrderBy specifies columns for ordering
func (b *SelectStmt) OrderAsc(col string) *SelectStmt {
b.Order = append(b.Order, order(col, asc))
return b
}
func (b *SelectStmt) OrderDesc(col string) *SelectStmt {
b.Order = append(b.Order, order(col, desc))
return b
}
// Limit adds limit
func (b *SelectStmt) Limit(n uint64) *SelectStmt {
b.LimitCount = int64(n)
return b
}
// Offset adds offset
func (b *SelectStmt) Offset(n uint64) *SelectStmt {
b.OffsetCount = int64(n)
return b
}
// Join joins table on condition
func (b *SelectStmt) Join(table, on interface{}) *SelectStmt {
b.JoinTable = append(b.JoinTable, join(inner, table, on))
return b
}
func (b *SelectStmt) LeftJoin(table, on interface{}) *SelectStmt {
b.JoinTable = append(b.JoinTable, join(left, table, on))
return b
}
func (b *SelectStmt) RightJoin(table, on interface{}) *SelectStmt {
b.JoinTable = append(b.JoinTable, join(right, table, on))
return b
}
func (b *SelectStmt) FullJoin(table, on interface{}) *SelectStmt {
b.JoinTable = append(b.JoinTable, join(full, table, on))
return b
}
// As creates alias for select statement
func (b *SelectStmt) As(alias string) Builder {
return as(b, alias)
}

173
vendor/github.com/gocraft/dbr/select_builder.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package dbr
import "context"
type SelectBuilder struct {
runner
EventReceiver
Dialect Dialect
*SelectStmt
}
func prepareSelect(a []string) []interface{} {
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
return b
}
func (sess *Session) Select(column ...string) *SelectBuilder {
return &SelectBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
SelectStmt: Select(prepareSelect(column)...),
}
}
func (tx *Tx) Select(column ...string) *SelectBuilder {
return &SelectBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
SelectStmt: Select(prepareSelect(column)...),
}
}
func (sess *Session) SelectBySql(query string, value ...interface{}) *SelectBuilder {
return &SelectBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
SelectStmt: SelectBySql(query, value...),
}
}
func (tx *Tx) SelectBySql(query string, value ...interface{}) *SelectBuilder {
return &SelectBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
SelectStmt: SelectBySql(query, value...),
}
}
// DEPRECATED: use LoadOne instead
func (b *SelectBuilder) LoadStruct(value interface{}) error {
return b.LoadOne(value)
}
// DEPRECATED: use Load instead
func (b *SelectBuilder) LoadStructs(value interface{}) (int, error) {
return b.Load(value)
}
// DEPRECATED: use LoadOne instead
func (b *SelectBuilder) LoadValue(value interface{}) error {
return b.LoadOne(value)
}
// DEPRECATED: use Load instead
func (b *SelectBuilder) LoadValues(value interface{}) (int, error) {
return b.Load(value)
}
func (b *SelectBuilder) LoadOneContext(ctx context.Context, value interface{}) error {
count, err := query(ctx, b.runner, b.EventReceiver, b, b.Dialect, value)
if err != nil {
return err
}
if count == 0 {
return ErrNotFound
}
return nil
}
func (b *SelectBuilder) LoadOne(value interface{}) error {
return b.LoadOneContext(context.Background(), value)
}
func (b *SelectBuilder) LoadContext(ctx context.Context, value interface{}) (int, error) {
return query(ctx, b.runner, b.EventReceiver, b, b.Dialect, value)
}
func (b *SelectBuilder) Load(value interface{}) (int, error) {
return b.LoadContext(context.Background(), value)
}
func (b *SelectBuilder) Join(table, on interface{}) *SelectBuilder {
b.SelectStmt.Join(table, on)
return b
}
func (b *SelectBuilder) LeftJoin(table, on interface{}) *SelectBuilder {
b.SelectStmt.LeftJoin(table, on)
return b
}
func (b *SelectBuilder) RightJoin(table, on interface{}) *SelectBuilder {
b.SelectStmt.RightJoin(table, on)
return b
}
func (b *SelectBuilder) FullJoin(table, on interface{}) *SelectBuilder {
b.SelectStmt.FullJoin(table, on)
return b
}
func (b *SelectBuilder) Distinct() *SelectBuilder {
b.SelectStmt.Distinct()
return b
}
func (b *SelectBuilder) From(table interface{}) *SelectBuilder {
b.SelectStmt.From(table)
return b
}
func (b *SelectBuilder) GroupBy(col ...string) *SelectBuilder {
b.SelectStmt.GroupBy(col...)
return b
}
func (b *SelectBuilder) Having(query interface{}, value ...interface{}) *SelectBuilder {
b.SelectStmt.Having(query, value...)
return b
}
func (b *SelectBuilder) Limit(n uint64) *SelectBuilder {
b.SelectStmt.Limit(n)
return b
}
func (b *SelectBuilder) Offset(n uint64) *SelectBuilder {
b.SelectStmt.Offset(n)
return b
}
func (b *SelectBuilder) OrderDir(col string, isAsc bool) *SelectBuilder {
if isAsc {
b.SelectStmt.OrderAsc(col)
} else {
b.SelectStmt.OrderDesc(col)
}
return b
}
func (b *SelectBuilder) Paginate(page, perPage uint64) *SelectBuilder {
b.Limit(perPage)
b.Offset((page - 1) * perPage)
return b
}
func (b *SelectBuilder) OrderBy(col string) *SelectBuilder {
b.SelectStmt.Order = append(b.SelectStmt.Order, Expr(col))
return b
}
func (b *SelectBuilder) Where(query interface{}, value ...interface{}) *SelectBuilder {
b.SelectStmt.Where(query, value...)
return b
}

66
vendor/github.com/gocraft/dbr/select_return.go generated vendored Normal file
View File

@@ -0,0 +1,66 @@
package dbr
//
// These are a set of helpers that just call LoadValue and return the value.
// They return (_, ErrNotFound) if nothing was found.
//
// The inclusion of these helpers in the package is not an obvious choice:
// Benefits:
// - slight increase in code clarity/conciseness b/c you can use ":=" to define the variable
//
// count, err := d.Select("COUNT(*)").From("users").Where("x = ?", x).ReturnInt64()
//
// vs
//
// var count int64
// err := d.Select("COUNT(*)").From("users").Where("x = ?", x).LoadValue(&count)
//
// Downsides:
// - very small increase in code cost, although it's not complex code
// - increase in conceptual model / API footprint when presenting the package to new users
// - no functionality that you can't achieve calling .LoadValue directly.
// - There's a lot of possible types. Do we want to include ALL of them? u?int{8,16,32,64}?, strings, null varieties, etc.
// - Let's just do the common, non-null varieties.
// ReturnInt64 executes the SelectStmt and returns the value as an int64
func (b *SelectBuilder) ReturnInt64() (int64, error) {
var v int64
err := b.LoadValue(&v)
return v, err
}
// ReturnInt64s executes the SelectStmt and returns the value as a slice of int64s
func (b *SelectBuilder) ReturnInt64s() ([]int64, error) {
var v []int64
_, err := b.LoadValues(&v)
return v, err
}
// ReturnUint64 executes the SelectStmt and returns the value as an uint64
func (b *SelectBuilder) ReturnUint64() (uint64, error) {
var v uint64
err := b.LoadValue(&v)
return v, err
}
// ReturnUint64s executes the SelectStmt and returns the value as a slice of uint64s
func (b *SelectBuilder) ReturnUint64s() ([]uint64, error) {
var v []uint64
_, err := b.LoadValues(&v)
return v, err
}
// ReturnString executes the SelectStmt and returns the value as a string
func (b *SelectBuilder) ReturnString() (string, error) {
var v string
err := b.LoadValue(&v)
return v, err
}
// ReturnStrings executes the SelectStmt and returns the value as a slice of strings
func (b *SelectBuilder) ReturnStrings() ([]string, error) {
var v []string
_, err := b.LoadValues(&v)
return v, err
}

99
vendor/github.com/gocraft/dbr/transaction.go generated vendored Normal file
View File

@@ -0,0 +1,99 @@
package dbr
import (
"context"
"database/sql"
"time"
)
// Tx is a transaction for the given Session
type Tx struct {
EventReceiver
Dialect Dialect
*sql.Tx
Timeout time.Duration
// normally we don't call the context cancelFunc.
// however, if we start a tx without explictly tx,
// we will need to call this after the transaction.
Cancel func()
}
func (tx *Tx) GetTimeout() time.Duration {
return tx.Timeout
}
func (sess *Session) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
tx, err := sess.Connection.BeginTx(ctx, opts)
if err != nil {
return nil, sess.EventErr("dbr.begin.error", err)
}
sess.Event("dbr.begin")
stx := &Tx{
EventReceiver: sess,
Dialect: sess.Dialect,
Tx: tx,
Cancel: func() {},
}
deadline, ok := ctx.Deadline()
if ok {
stx.Timeout = deadline.Sub(time.Now())
}
return stx, nil
}
// Begin creates a transaction for the given session
func (sess *Session) Begin() (*Tx, error) {
ctx := context.Background()
var cancel func()
timeout := sess.GetTimeout()
if timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, timeout)
}
stx, err := sess.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
if cancel != nil {
stx.Cancel = cancel
}
return stx, nil
}
// Commit finishes the transaction
func (tx *Tx) Commit() error {
defer tx.Cancel()
err := tx.Tx.Commit()
if err != nil {
return tx.EventErr("dbr.commit.error", err)
}
tx.Event("dbr.commit")
return nil
}
// Rollback cancels the transaction
func (tx *Tx) Rollback() error {
defer tx.Cancel()
err := tx.Tx.Rollback()
if err != nil {
return tx.EventErr("dbr.rollback", err)
}
tx.Event("dbr.rollback")
return nil
}
// RollbackUnlessCommitted rollsback the transaction unless it has already been committed or rolled back.
// Useful to defer tx.RollbackUnlessCommitted() -- so you don't have to handle N failure cases
// Keep in mind the only way to detect an error on the rollback is via the event log.
func (tx *Tx) RollbackUnlessCommitted() {
defer tx.Cancel()
err := tx.Tx.Rollback()
if err == sql.ErrTxDone {
// ok
} else if err != nil {
tx.EventErr("dbr.rollback_unless_committed", err)
} else {
tx.Event("dbr.rollback")
}
}

242
vendor/github.com/gocraft/dbr/types.go generated vendored Normal file
View File

@@ -0,0 +1,242 @@
package dbr
import (
"bytes"
"database/sql"
"database/sql/driver"
"encoding/json"
"time"
)
//
// Your app can use these Null types instead of the defaults. The sole benefit you get is a MarshalJSON method that is not retarded.
//
// NullString is a type that can be null or a string
type NullString struct {
sql.NullString
}
// NullFloat64 is a type that can be null or a float64
type NullFloat64 struct {
sql.NullFloat64
}
// NullInt64 is a type that can be null or an int
type NullInt64 struct {
sql.NullInt64
}
// NullTime is a type that can be null or a time
type NullTime struct {
Time time.Time
Valid bool // Valid is true if Time is not NULL
}
// Value implements the driver Valuer interface.
func (n NullTime) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.Time, nil
}
// NullBool is a type that can be null or a bool
type NullBool struct {
sql.NullBool
}
var nullString = []byte("null")
// MarshalJSON correctly serializes a NullString to JSON
func (n NullString) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.String)
}
return nullString, nil
}
// MarshalJSON correctly serializes a NullInt64 to JSON
func (n NullInt64) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.Int64)
}
return nullString, nil
}
// MarshalJSON correctly serializes a NullFloat64 to JSON
func (n NullFloat64) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.Float64)
}
return nullString, nil
}
// MarshalJSON correctly serializes a NullTime to JSON
func (n NullTime) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.Time)
}
return nullString, nil
}
// MarshalJSON correctly serializes a NullBool to JSON
func (n NullBool) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.Bool)
}
return nullString, nil
}
// UnmarshalJSON correctly deserializes a NullString from JSON
func (n *NullString) UnmarshalJSON(b []byte) error {
var s interface{}
if err := json.Unmarshal(b, &s); err != nil {
return err
}
return n.Scan(s)
}
// UnmarshalJSON correctly deserializes a NullInt64 from JSON
func (n *NullInt64) UnmarshalJSON(b []byte) error {
var s json.Number
if err := json.Unmarshal(b, &s); err != nil {
return err
}
if s == "" {
return n.Scan(nil)
}
return n.Scan(s)
}
// UnmarshalJSON correctly deserializes a NullFloat64 from JSON
func (n *NullFloat64) UnmarshalJSON(b []byte) error {
var s interface{}
if err := json.Unmarshal(b, &s); err != nil {
return err
}
return n.Scan(s)
}
// UnmarshalJSON correctly deserializes a NullTime from JSON
func (n *NullTime) UnmarshalJSON(b []byte) error {
// scan for null
if bytes.Equal(b, nullString) {
return n.Scan(nil)
}
// scan for JSON timestamp
var t time.Time
if err := json.Unmarshal(b, &t); err != nil {
return err
}
return n.Scan(t)
}
// UnmarshalJSON correctly deserializes a NullBool from JSON
func (n *NullBool) UnmarshalJSON(b []byte) error {
var s interface{}
if err := json.Unmarshal(b, &s); err != nil {
return err
}
return n.Scan(s)
}
func NewNullInt64(v interface{}) (n NullInt64) {
n.Scan(v)
return
}
func NewNullFloat64(v interface{}) (n NullFloat64) {
n.Scan(v)
return
}
func NewNullString(v interface{}) (n NullString) {
n.Scan(v)
return
}
func NewNullTime(v interface{}) (n NullTime) {
n.Scan(v)
return
}
func NewNullBool(v interface{}) (n NullBool) {
n.Scan(v)
return
}
// The `(*NullTime) Scan(interface{})` and `parseDateTime(string, *time.Location)`
// functions are slightly modified versions of code from the github.com/go-sql-driver/mysql
// package. They work with Postgres and MySQL databases. Potential future
// drivers should ensure these will work for them, or come up with an alternative.
//
// Conforming with its licensing terms the copyright notice and link to the licence
// are available below.
//
// Source: https://github.com/go-sql-driver/mysql/blob/527bcd55aab2e53314f1a150922560174b493034/utils.go#L452-L508
// Copyright notice from original developers:
//
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/
// Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails.
func (n *NullTime) Scan(value interface{}) error {
var err error
if value == nil {
n.Time, n.Valid = time.Time{}, false
return nil
}
switch v := value.(type) {
case time.Time:
n.Time, n.Valid = v, true
return nil
case []byte:
n.Time, err = parseDateTime(string(v), time.UTC)
n.Valid = (err == nil)
return err
case string:
n.Time, err = parseDateTime(v, time.UTC)
n.Valid = (err == nil)
return err
}
n.Valid = false
return nil
}
func parseDateTime(str string, loc *time.Location) (time.Time, error) {
var t time.Time
var err error
base := "0000-00-00 00:00:00.0000000"
switch len(str) {
case 10, 19, 21, 22, 23, 24, 25, 26:
if str == base[:len(str)] {
return t, err
}
t, err = time.Parse(timeFormat[:len(str)], str)
default:
err = ErrInvalidTimestring
return t, err
}
// Adjust location
if err == nil && loc != time.UTC {
y, mo, d := t.Date()
h, mi, s := t.Clock()
t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
}
return t, err
}

43
vendor/github.com/gocraft/dbr/union.go generated vendored Normal file
View File

@@ -0,0 +1,43 @@
package dbr
type union struct {
builder []Builder
all bool
}
func Union(builder ...Builder) interface {
Builder
As(string) Builder
} {
return &union{
builder: builder,
}
}
func UnionAll(builder ...Builder) interface {
Builder
As(string) Builder
} {
return &union{
builder: builder,
all: true,
}
}
func (u *union) Build(d Dialect, buf Buffer) error {
for i, b := range u.builder {
if i > 0 {
buf.WriteString(" UNION ")
if u.all {
buf.WriteString("ALL ")
}
}
buf.WriteString(placeholder)
buf.WriteValue(b)
}
return nil
}
func (u *union) As(alias string) Builder {
return as(u, alias)
}

96
vendor/github.com/gocraft/dbr/update.go generated vendored Normal file
View File

@@ -0,0 +1,96 @@
package dbr
// UpdateStmt builds `UPDATE ...`
type UpdateStmt struct {
raw
Table string
Value map[string]interface{}
WhereCond []Builder
}
// Build builds `UPDATE ...` in dialect
func (b *UpdateStmt) Build(d Dialect, buf Buffer) error {
if b.raw.Query != "" {
return b.raw.Build(d, buf)
}
if b.Table == "" {
return ErrTableNotSpecified
}
if len(b.Value) == 0 {
return ErrColumnNotSpecified
}
buf.WriteString("UPDATE ")
buf.WriteString(d.QuoteIdent(b.Table))
buf.WriteString(" SET ")
i := 0
for col, v := range b.Value {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(d.QuoteIdent(col))
buf.WriteString(" = ")
buf.WriteString(placeholder)
buf.WriteValue(v)
i++
}
if len(b.WhereCond) > 0 {
buf.WriteString(" WHERE ")
err := And(b.WhereCond...).Build(d, buf)
if err != nil {
return err
}
}
return nil
}
// Update creates an UpdateStmt
func Update(table string) *UpdateStmt {
return &UpdateStmt{
Table: table,
Value: make(map[string]interface{}),
}
}
// UpdateBySql creates an UpdateStmt with raw query
func UpdateBySql(query string, value ...interface{}) *UpdateStmt {
return &UpdateStmt{
raw: raw{
Query: query,
Value: value,
},
Value: make(map[string]interface{}),
}
}
// Where adds a where condition
func (b *UpdateStmt) Where(query interface{}, value ...interface{}) *UpdateStmt {
switch query := query.(type) {
case string:
b.WhereCond = append(b.WhereCond, Expr(query, value...))
case Builder:
b.WhereCond = append(b.WhereCond, query)
}
return b
}
// Set specifies a key-value pair
func (b *UpdateStmt) Set(column string, value interface{}) *UpdateStmt {
b.Value[column] = value
return b
}
// SetMap specifies a list of key-value pair
func (b *UpdateStmt) SetMap(m map[string]interface{}) *UpdateStmt {
for col, val := range m {
b.Set(col, val)
}
return b
}

97
vendor/github.com/gocraft/dbr/update_builder.go generated vendored Normal file
View File

@@ -0,0 +1,97 @@
package dbr
import (
"context"
"database/sql"
"fmt"
)
type UpdateBuilder struct {
runner
EventReceiver
Dialect Dialect
*UpdateStmt
LimitCount int64
}
func (sess *Session) Update(table string) *UpdateBuilder {
return &UpdateBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
UpdateStmt: Update(table),
LimitCount: -1,
}
}
func (tx *Tx) Update(table string) *UpdateBuilder {
return &UpdateBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
UpdateStmt: Update(table),
LimitCount: -1,
}
}
func (sess *Session) UpdateBySql(query string, value ...interface{}) *UpdateBuilder {
return &UpdateBuilder{
runner: sess,
EventReceiver: sess,
Dialect: sess.Dialect,
UpdateStmt: UpdateBySql(query, value...),
LimitCount: -1,
}
}
func (tx *Tx) UpdateBySql(query string, value ...interface{}) *UpdateBuilder {
return &UpdateBuilder{
runner: tx,
EventReceiver: tx,
Dialect: tx.Dialect,
UpdateStmt: UpdateBySql(query, value...),
LimitCount: -1,
}
}
func (b *UpdateBuilder) Exec() (sql.Result, error) {
return b.ExecContext(context.Background())
}
func (b *UpdateBuilder) ExecContext(ctx context.Context) (sql.Result, error) {
return exec(ctx, b.runner, b.EventReceiver, b, b.Dialect)
}
func (b *UpdateBuilder) Set(column string, value interface{}) *UpdateBuilder {
b.UpdateStmt.Set(column, value)
return b
}
func (b *UpdateBuilder) SetMap(m map[string]interface{}) *UpdateBuilder {
b.UpdateStmt.SetMap(m)
return b
}
func (b *UpdateBuilder) Where(query interface{}, value ...interface{}) *UpdateBuilder {
b.UpdateStmt.Where(query, value...)
return b
}
func (b *UpdateBuilder) Limit(n uint64) *UpdateBuilder {
b.LimitCount = int64(n)
return b
}
func (b *UpdateBuilder) Build(d Dialect, buf Buffer) error {
err := b.UpdateStmt.Build(b.Dialect, buf)
if err != nil {
return err
}
if b.LimitCount >= 0 {
buf.WriteString(" LIMIT ")
buf.WriteString(fmt.Sprint(b.LimitCount))
}
return nil
}

71
vendor/github.com/gocraft/dbr/util.go generated vendored Normal file
View File

@@ -0,0 +1,71 @@
package dbr
import (
"bytes"
"database/sql/driver"
"reflect"
"unicode"
)
func camelCaseToSnakeCase(name string) string {
buf := new(bytes.Buffer)
runes := []rune(name)
for i := 0; i < len(runes); i++ {
buf.WriteRune(unicode.ToLower(runes[i]))
if i != len(runes)-1 && unicode.IsUpper(runes[i+1]) &&
(unicode.IsLower(runes[i]) || unicode.IsDigit(runes[i]) ||
(i != len(runes)-2 && unicode.IsLower(runes[i+2]))) {
buf.WriteRune('_')
}
}
return buf.String()
}
func structMap(value reflect.Value) map[string]reflect.Value {
m := make(map[string]reflect.Value)
structValue(m, value)
return m
}
var (
typeValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
)
func structValue(m map[string]reflect.Value, value reflect.Value) {
if value.Type().Implements(typeValuer) {
return
}
switch value.Kind() {
case reflect.Ptr:
if value.IsNil() {
return
}
structValue(m, value.Elem())
case reflect.Struct:
t := value.Type()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.PkgPath != "" && !field.Anonymous {
// unexported
continue
}
tag := field.Tag.Get("db")
if tag == "-" {
// ignore
continue
}
if tag == "" {
// no tag, but we can record the field name
tag = camelCaseToSnakeCase(field.Name)
}
fieldValue := value.Field(i)
if _, ok := m[tag]; !ok {
m[tag] = fieldValue
}
structValue(m, fieldValue)
}
}
}