20
vendor/github.com/gocraft/dbr/LICENSE
generated
vendored
Normal file
20
vendor/github.com/gocraft/dbr/LICENSE
generated
vendored
Normal 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
29
vendor/github.com/gocraft/dbr/buffer.go
generated
vendored
Normal 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
13
vendor/github.com/gocraft/dbr/builder.go
generated
vendored
Normal 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
119
vendor/github.com/gocraft/dbr/condition.go
generated
vendored
Normal 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
174
vendor/github.com/gocraft/dbr/dbr.go
generated
vendored
Normal 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
61
vendor/github.com/gocraft/dbr/delete.go
generated
vendored
Normal 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
87
vendor/github.com/gocraft/dbr/delete_builder.go
generated
vendored
Normal 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
15
vendor/github.com/gocraft/dbr/dialect.go
generated
vendored
Normal 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
24
vendor/github.com/gocraft/dbr/dialect/dialect.go
generated
vendored
Normal 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
66
vendor/github.com/gocraft/dbr/dialect/mysql.go
generated
vendored
Normal 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
37
vendor/github.com/gocraft/dbr/dialect/postgresql.go
generated
vendored
Normal 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
40
vendor/github.com/gocraft/dbr/dialect/sqlite3.go
generated
vendored
Normal 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
16
vendor/github.com/gocraft/dbr/errors.go
generated
vendored
Normal 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
40
vendor/github.com/gocraft/dbr/event.go
generated
vendored
Normal 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
18
vendor/github.com/gocraft/dbr/expr.go
generated
vendored
Normal 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
24
vendor/github.com/gocraft/dbr/ident.go
generated
vendored
Normal 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
123
vendor/github.com/gocraft/dbr/insert.go
generated
vendored
Normal 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
126
vendor/github.com/gocraft/dbr/insert_builder.go
generated
vendored
Normal 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
157
vendor/github.com/gocraft/dbr/interpolate.go
generated
vendored
Normal 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
41
vendor/github.com/gocraft/dbr/join.go
generated
vendored
Normal 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
119
vendor/github.com/gocraft/dbr/load.go
generated
vendored
Normal 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
19
vendor/github.com/gocraft/dbr/now.go
generated
vendored
Normal 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
24
vendor/github.com/gocraft/dbr/order.go
generated
vendored
Normal 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
238
vendor/github.com/gocraft/dbr/select.go
generated
vendored
Normal 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
173
vendor/github.com/gocraft/dbr/select_builder.go
generated
vendored
Normal 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
66
vendor/github.com/gocraft/dbr/select_return.go
generated
vendored
Normal 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
99
vendor/github.com/gocraft/dbr/transaction.go
generated
vendored
Normal 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
242
vendor/github.com/gocraft/dbr/types.go
generated
vendored
Normal 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
43
vendor/github.com/gocraft/dbr/union.go
generated
vendored
Normal 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
96
vendor/github.com/gocraft/dbr/update.go
generated
vendored
Normal 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
97
vendor/github.com/gocraft/dbr/update_builder.go
generated
vendored
Normal 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
71
vendor/github.com/gocraft/dbr/util.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user