mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-07 17:29:33 -06:00
Grand test fixup (#138)
* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
This commit is contained in:
parent
329a5e8144
commit
98263a7de6
2677 changed files with 1090869 additions and 219 deletions
100
vendor/github.com/go-pg/pg/v10/orm/composite.go
generated
vendored
Normal file
100
vendor/github.com/go-pg/pg/v10/orm/composite.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal/pool"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
func compositeScanner(typ reflect.Type) types.ScannerFunc {
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
var table *Table
|
||||
return func(v reflect.Value, rd types.Reader, n int) error {
|
||||
if n == -1 {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
if table == nil {
|
||||
table = GetTable(typ)
|
||||
}
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
p := newCompositeParser(rd)
|
||||
var elemReader *pool.BytesReader
|
||||
|
||||
var firstErr error
|
||||
for i := 0; ; i++ {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == errEndOfComposite {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if i >= len(table.Fields) {
|
||||
if firstErr == nil {
|
||||
firstErr = fmt.Errorf(
|
||||
"pg: %s has %d fields, but composite requires at least %d values",
|
||||
table, len(table.Fields), i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if elemReader == nil {
|
||||
elemReader = pool.NewBytesReader(elem)
|
||||
} else {
|
||||
elemReader.Reset(elem)
|
||||
}
|
||||
|
||||
field := table.Fields[i]
|
||||
if elem == nil {
|
||||
err = field.ScanValue(v, elemReader, -1)
|
||||
} else {
|
||||
err = field.ScanValue(v, elemReader, len(elem))
|
||||
}
|
||||
if err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
|
||||
return firstErr
|
||||
}
|
||||
}
|
||||
|
||||
func compositeAppender(typ reflect.Type) types.AppenderFunc {
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
var table *Table
|
||||
return func(b []byte, v reflect.Value, quote int) []byte {
|
||||
if table == nil {
|
||||
table = GetTable(typ)
|
||||
}
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
b = append(b, "ROW("...)
|
||||
for i, f := range table.Fields {
|
||||
if i > 0 {
|
||||
b = append(b, ',')
|
||||
}
|
||||
b = f.AppendValue(b, v, quote)
|
||||
}
|
||||
b = append(b, ')')
|
||||
return b
|
||||
}
|
||||
}
|
||||
89
vendor/github.com/go-pg/pg/v10/orm/composite_create.go
generated
vendored
Normal file
89
vendor/github.com/go-pg/pg/v10/orm/composite_create.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type CreateCompositeOptions struct {
|
||||
Varchar int // replaces PostgreSQL data type `text` with `varchar(n)`
|
||||
}
|
||||
|
||||
type CreateCompositeQuery struct {
|
||||
q *Query
|
||||
opt *CreateCompositeOptions
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*CreateCompositeQuery)(nil)
|
||||
_ QueryCommand = (*CreateCompositeQuery)(nil)
|
||||
)
|
||||
|
||||
func NewCreateCompositeQuery(q *Query, opt *CreateCompositeOptions) *CreateCompositeQuery {
|
||||
return &CreateCompositeQuery{
|
||||
q: q,
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) Operation() QueryOp {
|
||||
return CreateCompositeOp
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) Clone() QueryCommand {
|
||||
return &CreateCompositeQuery{
|
||||
q: q.q.Clone(),
|
||||
opt: q.opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
return q.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *CreateCompositeQuery) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
if q.q.tableModel == nil {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
table := q.q.tableModel.Table()
|
||||
|
||||
b = append(b, "CREATE TYPE "...)
|
||||
b = append(b, table.Alias...)
|
||||
b = append(b, " AS ("...)
|
||||
|
||||
for i, field := range table.Fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b = append(b, field.Column...)
|
||||
b = append(b, " "...)
|
||||
if field.UserSQLType == "" && q.opt != nil && q.opt.Varchar > 0 &&
|
||||
field.SQLType == "text" {
|
||||
b = append(b, "varchar("...)
|
||||
b = strconv.AppendInt(b, int64(q.opt.Varchar), 10)
|
||||
b = append(b, ")"...)
|
||||
} else {
|
||||
b = append(b, field.SQLType...)
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, ")"...)
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
70
vendor/github.com/go-pg/pg/v10/orm/composite_drop.go
generated
vendored
Normal file
70
vendor/github.com/go-pg/pg/v10/orm/composite_drop.go
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package orm
|
||||
|
||||
type DropCompositeOptions struct {
|
||||
IfExists bool
|
||||
Cascade bool
|
||||
}
|
||||
|
||||
type DropCompositeQuery struct {
|
||||
q *Query
|
||||
opt *DropCompositeOptions
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*DropCompositeQuery)(nil)
|
||||
_ QueryCommand = (*DropCompositeQuery)(nil)
|
||||
)
|
||||
|
||||
func NewDropCompositeQuery(q *Query, opt *DropCompositeOptions) *DropCompositeQuery {
|
||||
return &DropCompositeQuery{
|
||||
q: q,
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) Operation() QueryOp {
|
||||
return DropCompositeOp
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) Clone() QueryCommand {
|
||||
return &DropCompositeQuery{
|
||||
q: q.q.Clone(),
|
||||
opt: q.opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
return q.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *DropCompositeQuery) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
if q.q.tableModel == nil {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
b = append(b, "DROP TYPE "...)
|
||||
if q.opt != nil && q.opt.IfExists {
|
||||
b = append(b, "IF EXISTS "...)
|
||||
}
|
||||
b = append(b, q.q.tableModel.Table().Alias...)
|
||||
if q.opt != nil && q.opt.Cascade {
|
||||
b = append(b, " CASCADE"...)
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
140
vendor/github.com/go-pg/pg/v10/orm/composite_parser.go
generated
vendored
Normal file
140
vendor/github.com/go-pg/pg/v10/orm/composite_parser.go
generated
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal/parser"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
var errEndOfComposite = errors.New("pg: end of composite")
|
||||
|
||||
type compositeParser struct {
|
||||
p parser.StreamingParser
|
||||
|
||||
stickyErr error
|
||||
}
|
||||
|
||||
func newCompositeParserErr(err error) *compositeParser {
|
||||
return &compositeParser{
|
||||
stickyErr: err,
|
||||
}
|
||||
}
|
||||
|
||||
func newCompositeParser(rd types.Reader) *compositeParser {
|
||||
p := parser.NewStreamingParser(rd)
|
||||
err := p.SkipByte('(')
|
||||
if err != nil {
|
||||
return newCompositeParserErr(err)
|
||||
}
|
||||
return &compositeParser{
|
||||
p: p,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *compositeParser) NextElem() ([]byte, error) {
|
||||
if p.stickyErr != nil {
|
||||
return nil, p.stickyErr
|
||||
}
|
||||
|
||||
c, err := p.p.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil, errEndOfComposite
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch c {
|
||||
case '"':
|
||||
return p.readQuoted()
|
||||
case ',':
|
||||
return nil, nil
|
||||
case ')':
|
||||
return nil, errEndOfComposite
|
||||
default:
|
||||
_ = p.p.UnreadByte()
|
||||
}
|
||||
|
||||
var b []byte
|
||||
for {
|
||||
tmp, err := p.p.ReadSlice(',')
|
||||
if err == nil {
|
||||
if b == nil {
|
||||
b = tmp
|
||||
} else {
|
||||
b = append(b, tmp...)
|
||||
}
|
||||
b = b[:len(b)-1]
|
||||
break
|
||||
}
|
||||
b = append(b, tmp...)
|
||||
if err == bufio.ErrBufferFull {
|
||||
continue
|
||||
}
|
||||
if err == io.EOF {
|
||||
if b[len(b)-1] == ')' {
|
||||
b = b[:len(b)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b) == 0 { // NULL
|
||||
return nil, nil
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (p *compositeParser) readQuoted() ([]byte, error) {
|
||||
var b []byte
|
||||
|
||||
c, err := p.p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
next, err := p.p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c == '\\' || c == '\'' {
|
||||
if next == c {
|
||||
b = append(b, c)
|
||||
c, err = p.p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
b = append(b, c)
|
||||
c = next
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if c == '"' {
|
||||
switch next {
|
||||
case '"':
|
||||
b = append(b, '"')
|
||||
c, err = p.p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ',', ')':
|
||||
return b, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("pg: got %q, wanted ',' or ')'", c)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
b = append(b, c)
|
||||
c = next
|
||||
}
|
||||
}
|
||||
90
vendor/github.com/go-pg/pg/v10/orm/count_estimate.go
generated
vendored
Normal file
90
vendor/github.com/go-pg/pg/v10/orm/count_estimate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
)
|
||||
|
||||
// Placeholder that is replaced with count(*).
|
||||
const placeholder = `'_go_pg_placeholder'`
|
||||
|
||||
// https://wiki.postgresql.org/wiki/Count_estimate
|
||||
//nolint
|
||||
var pgCountEstimateFunc = fmt.Sprintf(`
|
||||
CREATE OR REPLACE FUNCTION _go_pg_count_estimate_v2(query text, threshold int)
|
||||
RETURNS int AS $$
|
||||
DECLARE
|
||||
rec record;
|
||||
nrows int;
|
||||
BEGIN
|
||||
FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP
|
||||
nrows := substring(rec."QUERY PLAN" FROM ' rows=(\d+)');
|
||||
EXIT WHEN nrows IS NOT NULL;
|
||||
END LOOP;
|
||||
|
||||
-- Return the estimation if there are too many rows.
|
||||
IF nrows > threshold THEN
|
||||
RETURN nrows;
|
||||
END IF;
|
||||
|
||||
-- Otherwise execute real count query.
|
||||
query := replace(query, 'SELECT '%s'', 'SELECT count(*)');
|
||||
EXECUTE query INTO nrows;
|
||||
|
||||
IF nrows IS NULL THEN
|
||||
nrows := 0;
|
||||
END IF;
|
||||
|
||||
RETURN nrows;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`, placeholder)
|
||||
|
||||
// CountEstimate uses EXPLAIN to get estimated number of rows returned the query.
|
||||
// If that number is bigger than the threshold it returns the estimation.
|
||||
// Otherwise it executes another query using count aggregate function and
|
||||
// returns the result.
|
||||
//
|
||||
// Based on https://wiki.postgresql.org/wiki/Count_estimate
|
||||
func (q *Query) CountEstimate(threshold int) (int, error) {
|
||||
if q.stickyErr != nil {
|
||||
return 0, q.stickyErr
|
||||
}
|
||||
|
||||
query, err := q.countSelectQuery(placeholder).AppendQuery(q.db.Formatter(), nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var count int
|
||||
_, err = q.db.QueryOneContext(
|
||||
q.ctx,
|
||||
Scan(&count),
|
||||
"SELECT _go_pg_count_estimate_v2(?, ?)",
|
||||
string(query), threshold,
|
||||
)
|
||||
if err != nil {
|
||||
if pgerr, ok := err.(internal.PGError); ok && pgerr.Field('C') == "42883" {
|
||||
// undefined_function
|
||||
err = q.createCountEstimateFunc()
|
||||
if err != nil {
|
||||
pgerr, ok := err.(internal.PGError)
|
||||
if !ok || !pgerr.IntegrityViolation() {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
return count, err
|
||||
}
|
||||
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (q *Query) createCountEstimateFunc() error {
|
||||
_, err := q.db.ExecContext(q.ctx, pgCountEstimateFunc)
|
||||
return err
|
||||
}
|
||||
158
vendor/github.com/go-pg/pg/v10/orm/delete.go
generated
vendored
Normal file
158
vendor/github.com/go-pg/pg/v10/orm/delete.go
generated
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type DeleteQuery struct {
|
||||
q *Query
|
||||
placeholder bool
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*DeleteQuery)(nil)
|
||||
_ QueryCommand = (*DeleteQuery)(nil)
|
||||
)
|
||||
|
||||
func NewDeleteQuery(q *Query) *DeleteQuery {
|
||||
return &DeleteQuery{
|
||||
q: q,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) Operation() QueryOp {
|
||||
return DeleteOp
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) Clone() QueryCommand {
|
||||
return &DeleteQuery{
|
||||
q: q.q.Clone(),
|
||||
placeholder: q.placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
cp := q.Clone().(*DeleteQuery)
|
||||
cp.placeholder = true
|
||||
return cp.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *DeleteQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
|
||||
if len(q.q.with) > 0 {
|
||||
b, err = q.q.appendWith(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, "DELETE FROM "...)
|
||||
b, err = q.q.appendFirstTableWithAlias(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if q.q.hasMultiTables() {
|
||||
b = append(b, " USING "...)
|
||||
b, err = q.q.appendOtherTables(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, " WHERE "...)
|
||||
value := q.q.tableModel.Value()
|
||||
|
||||
if q.q.isSliceModelWithData() {
|
||||
if len(q.q.where) > 0 {
|
||||
b, err = q.q.appendWhere(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
table := q.q.tableModel.Table()
|
||||
err = table.checkPKs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b = appendColumnAndSliceValue(fmter, b, value, table.Alias, table.PKs)
|
||||
}
|
||||
} else {
|
||||
b, err = q.q.mustAppendWhere(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.returning) > 0 {
|
||||
b, err = q.q.appendReturning(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
|
||||
func appendColumnAndSliceValue(
|
||||
fmter QueryFormatter, b []byte, slice reflect.Value, alias types.Safe, fields []*Field,
|
||||
) []byte {
|
||||
if len(fields) > 1 {
|
||||
b = append(b, '(')
|
||||
}
|
||||
b = appendColumns(b, alias, fields)
|
||||
if len(fields) > 1 {
|
||||
b = append(b, ')')
|
||||
}
|
||||
|
||||
b = append(b, " IN ("...)
|
||||
|
||||
isPlaceholder := isTemplateFormatter(fmter)
|
||||
sliceLen := slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
el := indirect(slice.Index(i))
|
||||
|
||||
if len(fields) > 1 {
|
||||
b = append(b, '(')
|
||||
}
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
if isPlaceholder {
|
||||
b = append(b, '?')
|
||||
} else {
|
||||
b = f.AppendValue(b, el, 1)
|
||||
}
|
||||
}
|
||||
if len(fields) > 1 {
|
||||
b = append(b, ')')
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, ')')
|
||||
|
||||
return b
|
||||
}
|
||||
146
vendor/github.com/go-pg/pg/v10/orm/field.go
generated
vendored
Normal file
146
vendor/github.com/go-pg/pg/v10/orm/field.go
generated
vendored
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
"github.com/go-pg/zerochecker"
|
||||
)
|
||||
|
||||
const (
|
||||
PrimaryKeyFlag = uint8(1) << iota
|
||||
ForeignKeyFlag
|
||||
NotNullFlag
|
||||
UseZeroFlag
|
||||
UniqueFlag
|
||||
ArrayFlag
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
Field reflect.StructField
|
||||
Type reflect.Type
|
||||
Index []int
|
||||
|
||||
GoName string // struct field name, e.g. Id
|
||||
SQLName string // SQL name, .e.g. id
|
||||
Column types.Safe // escaped SQL name, e.g. "id"
|
||||
SQLType string
|
||||
UserSQLType string
|
||||
Default types.Safe
|
||||
OnDelete string
|
||||
OnUpdate string
|
||||
|
||||
flags uint8
|
||||
|
||||
append types.AppenderFunc
|
||||
scan types.ScannerFunc
|
||||
|
||||
isZero zerochecker.Func
|
||||
}
|
||||
|
||||
func indexEqual(ind1, ind2 []int) bool {
|
||||
if len(ind1) != len(ind2) {
|
||||
return false
|
||||
}
|
||||
for i, ind := range ind1 {
|
||||
if ind != ind2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *Field) Clone() *Field {
|
||||
cp := *f
|
||||
cp.Index = cp.Index[:len(f.Index):len(f.Index)]
|
||||
return &cp
|
||||
}
|
||||
|
||||
func (f *Field) setFlag(flag uint8) {
|
||||
f.flags |= flag
|
||||
}
|
||||
|
||||
func (f *Field) hasFlag(flag uint8) bool {
|
||||
return f.flags&flag != 0
|
||||
}
|
||||
|
||||
func (f *Field) Value(strct reflect.Value) reflect.Value {
|
||||
return fieldByIndexAlloc(strct, f.Index)
|
||||
}
|
||||
|
||||
func (f *Field) HasZeroValue(strct reflect.Value) bool {
|
||||
return f.hasZeroValue(strct, f.Index)
|
||||
}
|
||||
|
||||
func (f *Field) hasZeroValue(v reflect.Value, index []int) bool {
|
||||
for _, idx := range index {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return true
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
v = v.Field(idx)
|
||||
}
|
||||
return f.isZero(v)
|
||||
}
|
||||
|
||||
func (f *Field) NullZero() bool {
|
||||
return !f.hasFlag(UseZeroFlag)
|
||||
}
|
||||
|
||||
func (f *Field) AppendValue(b []byte, strct reflect.Value, quote int) []byte {
|
||||
fv, ok := fieldByIndex(strct, f.Index)
|
||||
if !ok {
|
||||
return types.AppendNull(b, quote)
|
||||
}
|
||||
|
||||
if f.NullZero() && f.isZero(fv) {
|
||||
return types.AppendNull(b, quote)
|
||||
}
|
||||
if f.append == nil {
|
||||
panic(fmt.Errorf("pg: AppendValue(unsupported %s)", fv.Type()))
|
||||
}
|
||||
return f.append(b, fv, quote)
|
||||
}
|
||||
|
||||
func (f *Field) ScanValue(strct reflect.Value, rd types.Reader, n int) error {
|
||||
if f.scan == nil {
|
||||
return fmt.Errorf("pg: ScanValue(unsupported %s)", f.Type)
|
||||
}
|
||||
|
||||
var fv reflect.Value
|
||||
if n == -1 {
|
||||
var ok bool
|
||||
fv, ok = fieldByIndex(strct, f.Index)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
fv = fieldByIndexAlloc(strct, f.Index)
|
||||
}
|
||||
|
||||
return f.scan(fv, rd, n)
|
||||
}
|
||||
|
||||
type Method struct {
|
||||
Index int
|
||||
|
||||
flags int8
|
||||
|
||||
appender func([]byte, reflect.Value, int) []byte
|
||||
}
|
||||
|
||||
func (m *Method) Has(flag int8) bool {
|
||||
return m.flags&flag != 0
|
||||
}
|
||||
|
||||
func (m *Method) Value(strct reflect.Value) reflect.Value {
|
||||
return strct.Method(m.Index).Call(nil)[0]
|
||||
}
|
||||
|
||||
func (m *Method) AppendValue(dst []byte, strct reflect.Value, quote int) []byte {
|
||||
mv := m.Value(strct)
|
||||
return m.appender(dst, mv, quote)
|
||||
}
|
||||
333
vendor/github.com/go-pg/pg/v10/orm/format.go
generated
vendored
Normal file
333
vendor/github.com/go-pg/pg/v10/orm/format.go
generated
vendored
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
"github.com/go-pg/pg/v10/internal/parser"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
var defaultFmter = NewFormatter()
|
||||
|
||||
type queryWithSepAppender interface {
|
||||
QueryAppender
|
||||
AppendSep([]byte) []byte
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type SafeQueryAppender struct {
|
||||
query string
|
||||
params []interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*SafeQueryAppender)(nil)
|
||||
_ types.ValueAppender = (*SafeQueryAppender)(nil)
|
||||
)
|
||||
|
||||
//nolint
|
||||
func SafeQuery(query string, params ...interface{}) *SafeQueryAppender {
|
||||
return &SafeQueryAppender{query, params}
|
||||
}
|
||||
|
||||
func (q *SafeQueryAppender) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
return fmter.FormatQuery(b, q.query, q.params...), nil
|
||||
}
|
||||
|
||||
func (q *SafeQueryAppender) AppendValue(b []byte, quote int) ([]byte, error) {
|
||||
return q.AppendQuery(defaultFmter, b)
|
||||
}
|
||||
|
||||
func (q *SafeQueryAppender) Value() types.Safe {
|
||||
b, err := q.AppendValue(nil, 1)
|
||||
if err != nil {
|
||||
return types.Safe(err.Error())
|
||||
}
|
||||
return types.Safe(internal.BytesToString(b))
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type condGroupAppender struct {
|
||||
sep string
|
||||
cond []queryWithSepAppender
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*condAppender)(nil)
|
||||
_ queryWithSepAppender = (*condAppender)(nil)
|
||||
)
|
||||
|
||||
func (q *condGroupAppender) AppendSep(b []byte) []byte {
|
||||
return append(b, q.sep...)
|
||||
}
|
||||
|
||||
func (q *condGroupAppender) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
b = append(b, '(')
|
||||
for i, app := range q.cond {
|
||||
if i > 0 {
|
||||
b = app.AppendSep(b)
|
||||
}
|
||||
b, err = app.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
b = append(b, ')')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type condAppender struct {
|
||||
sep string
|
||||
cond string
|
||||
params []interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*condAppender)(nil)
|
||||
_ queryWithSepAppender = (*condAppender)(nil)
|
||||
)
|
||||
|
||||
func (q *condAppender) AppendSep(b []byte) []byte {
|
||||
return append(b, q.sep...)
|
||||
}
|
||||
|
||||
func (q *condAppender) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
b = append(b, '(')
|
||||
b = fmter.FormatQuery(b, q.cond, q.params...)
|
||||
b = append(b, ')')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type fieldAppender struct {
|
||||
field string
|
||||
}
|
||||
|
||||
var _ QueryAppender = (*fieldAppender)(nil)
|
||||
|
||||
func (a fieldAppender) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
return types.AppendIdent(b, a.field, 1), nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type dummyFormatter struct{}
|
||||
|
||||
func (f dummyFormatter) FormatQuery(b []byte, query string, params ...interface{}) []byte {
|
||||
return append(b, query...)
|
||||
}
|
||||
|
||||
func isTemplateFormatter(fmter QueryFormatter) bool {
|
||||
_, ok := fmter.(dummyFormatter)
|
||||
return ok
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type QueryFormatter interface {
|
||||
FormatQuery(b []byte, query string, params ...interface{}) []byte
|
||||
}
|
||||
|
||||
type Formatter struct {
|
||||
namedParams map[string]interface{}
|
||||
model TableModel
|
||||
}
|
||||
|
||||
var _ QueryFormatter = (*Formatter)(nil)
|
||||
|
||||
func NewFormatter() *Formatter {
|
||||
return new(Formatter)
|
||||
}
|
||||
|
||||
func (f *Formatter) String() string {
|
||||
if len(f.namedParams) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
keys := make([]string, len(f.namedParams))
|
||||
index := 0
|
||||
for k := range f.namedParams {
|
||||
keys[index] = k
|
||||
index++
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
ss := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
ss[i] = fmt.Sprintf("%s=%v", k, f.namedParams[k])
|
||||
}
|
||||
return " " + strings.Join(ss, " ")
|
||||
}
|
||||
|
||||
func (f *Formatter) clone() *Formatter {
|
||||
cp := NewFormatter()
|
||||
|
||||
cp.model = f.model
|
||||
if len(f.namedParams) > 0 {
|
||||
cp.namedParams = make(map[string]interface{}, len(f.namedParams))
|
||||
}
|
||||
for param, value := range f.namedParams {
|
||||
cp.setParam(param, value)
|
||||
}
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
func (f *Formatter) WithTableModel(model TableModel) *Formatter {
|
||||
cp := f.clone()
|
||||
cp.model = model
|
||||
return cp
|
||||
}
|
||||
|
||||
func (f *Formatter) WithModel(model interface{}) *Formatter {
|
||||
switch model := model.(type) {
|
||||
case TableModel:
|
||||
return f.WithTableModel(model)
|
||||
case *Query:
|
||||
return f.WithTableModel(model.tableModel)
|
||||
case QueryCommand:
|
||||
return f.WithTableModel(model.Query().tableModel)
|
||||
default:
|
||||
panic(fmt.Errorf("pg: unsupported model %T", model))
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Formatter) setParam(param string, value interface{}) {
|
||||
if f.namedParams == nil {
|
||||
f.namedParams = make(map[string]interface{})
|
||||
}
|
||||
f.namedParams[param] = value
|
||||
}
|
||||
|
||||
func (f *Formatter) WithParam(param string, value interface{}) *Formatter {
|
||||
cp := f.clone()
|
||||
cp.setParam(param, value)
|
||||
return cp
|
||||
}
|
||||
|
||||
func (f *Formatter) Param(param string) interface{} {
|
||||
return f.namedParams[param]
|
||||
}
|
||||
|
||||
func (f *Formatter) hasParams() bool {
|
||||
return len(f.namedParams) > 0 || f.model != nil
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatQueryBytes(dst, query []byte, params ...interface{}) []byte {
|
||||
if (params == nil && !f.hasParams()) || bytes.IndexByte(query, '?') == -1 {
|
||||
return append(dst, query...)
|
||||
}
|
||||
return f.append(dst, parser.New(query), params)
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatQuery(dst []byte, query string, params ...interface{}) []byte {
|
||||
if (params == nil && !f.hasParams()) || strings.IndexByte(query, '?') == -1 {
|
||||
return append(dst, query...)
|
||||
}
|
||||
return f.append(dst, parser.NewString(query), params)
|
||||
}
|
||||
|
||||
func (f *Formatter) append(dst []byte, p *parser.Parser, params []interface{}) []byte {
|
||||
var paramsIndex int
|
||||
var namedParamsOnce bool
|
||||
var tableParams *tableParams
|
||||
|
||||
for p.Valid() {
|
||||
b, ok := p.ReadSep('?')
|
||||
if !ok {
|
||||
dst = append(dst, b...)
|
||||
continue
|
||||
}
|
||||
if len(b) > 0 && b[len(b)-1] == '\\' {
|
||||
dst = append(dst, b[:len(b)-1]...)
|
||||
dst = append(dst, '?')
|
||||
continue
|
||||
}
|
||||
dst = append(dst, b...)
|
||||
|
||||
id, numeric := p.ReadIdentifier()
|
||||
if id != "" {
|
||||
if numeric {
|
||||
idx, err := strconv.Atoi(id)
|
||||
if err != nil {
|
||||
goto restore_param
|
||||
}
|
||||
|
||||
if idx >= len(params) {
|
||||
goto restore_param
|
||||
}
|
||||
|
||||
dst = f.appendParam(dst, params[idx])
|
||||
continue
|
||||
}
|
||||
|
||||
if f.namedParams != nil {
|
||||
param, paramOK := f.namedParams[id]
|
||||
if paramOK {
|
||||
dst = f.appendParam(dst, param)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !namedParamsOnce && len(params) > 0 {
|
||||
namedParamsOnce = true
|
||||
tableParams, _ = newTableParams(params[len(params)-1])
|
||||
}
|
||||
|
||||
if tableParams != nil {
|
||||
dst, ok = tableParams.AppendParam(f, dst, id)
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if f.model != nil {
|
||||
dst, ok = f.model.AppendParam(f, dst, id)
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
restore_param:
|
||||
dst = append(dst, '?')
|
||||
dst = append(dst, id...)
|
||||
continue
|
||||
}
|
||||
|
||||
if paramsIndex >= len(params) {
|
||||
dst = append(dst, '?')
|
||||
continue
|
||||
}
|
||||
|
||||
param := params[paramsIndex]
|
||||
paramsIndex++
|
||||
|
||||
dst = f.appendParam(dst, param)
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func (f *Formatter) appendParam(b []byte, param interface{}) []byte {
|
||||
switch param := param.(type) {
|
||||
case QueryAppender:
|
||||
bb, err := param.AppendQuery(f, b)
|
||||
if err != nil {
|
||||
return types.AppendError(b, err)
|
||||
}
|
||||
return bb
|
||||
default:
|
||||
return types.Append(b, param, 1)
|
||||
}
|
||||
}
|
||||
248
vendor/github.com/go-pg/pg/v10/orm/hook.go
generated
vendored
Normal file
248
vendor/github.com/go-pg/pg/v10/orm/hook.go
generated
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type hookStubs struct{}
|
||||
|
||||
var (
|
||||
_ AfterScanHook = (*hookStubs)(nil)
|
||||
_ AfterSelectHook = (*hookStubs)(nil)
|
||||
_ BeforeInsertHook = (*hookStubs)(nil)
|
||||
_ AfterInsertHook = (*hookStubs)(nil)
|
||||
_ BeforeUpdateHook = (*hookStubs)(nil)
|
||||
_ AfterUpdateHook = (*hookStubs)(nil)
|
||||
_ BeforeDeleteHook = (*hookStubs)(nil)
|
||||
_ AfterDeleteHook = (*hookStubs)(nil)
|
||||
)
|
||||
|
||||
func (hookStubs) AfterScan(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hookStubs) AfterSelect(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hookStubs) BeforeInsert(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (hookStubs) AfterInsert(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hookStubs) BeforeUpdate(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (hookStubs) AfterUpdate(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hookStubs) BeforeDelete(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (hookStubs) AfterDelete(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func callHookSlice(
|
||||
ctx context.Context,
|
||||
slice reflect.Value,
|
||||
ptr bool,
|
||||
hook func(context.Context, reflect.Value) (context.Context, error),
|
||||
) (context.Context, error) {
|
||||
var firstErr error
|
||||
sliceLen := slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
v := slice.Index(i)
|
||||
if !ptr {
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
var err error
|
||||
ctx, err = hook(ctx, v)
|
||||
if err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return ctx, firstErr
|
||||
}
|
||||
|
||||
func callHookSlice2(
|
||||
ctx context.Context,
|
||||
slice reflect.Value,
|
||||
ptr bool,
|
||||
hook func(context.Context, reflect.Value) error,
|
||||
) error {
|
||||
var firstErr error
|
||||
if slice.IsValid() {
|
||||
sliceLen := slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
v := slice.Index(i)
|
||||
if !ptr {
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
err := hook(ctx, v)
|
||||
if err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
}
|
||||
return firstErr
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BeforeScanHook interface {
|
||||
BeforeScan(context.Context) error
|
||||
}
|
||||
|
||||
var beforeScanHookType = reflect.TypeOf((*BeforeScanHook)(nil)).Elem()
|
||||
|
||||
func callBeforeScanHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(BeforeScanHook).BeforeScan(ctx)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type AfterScanHook interface {
|
||||
AfterScan(context.Context) error
|
||||
}
|
||||
|
||||
var afterScanHookType = reflect.TypeOf((*AfterScanHook)(nil)).Elem()
|
||||
|
||||
func callAfterScanHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(AfterScanHook).AfterScan(ctx)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type AfterSelectHook interface {
|
||||
AfterSelect(context.Context) error
|
||||
}
|
||||
|
||||
var afterSelectHookType = reflect.TypeOf((*AfterSelectHook)(nil)).Elem()
|
||||
|
||||
func callAfterSelectHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(AfterSelectHook).AfterSelect(ctx)
|
||||
}
|
||||
|
||||
func callAfterSelectHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) error {
|
||||
return callHookSlice2(ctx, slice, ptr, callAfterSelectHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BeforeInsertHook interface {
|
||||
BeforeInsert(context.Context) (context.Context, error)
|
||||
}
|
||||
|
||||
var beforeInsertHookType = reflect.TypeOf((*BeforeInsertHook)(nil)).Elem()
|
||||
|
||||
func callBeforeInsertHook(ctx context.Context, v reflect.Value) (context.Context, error) {
|
||||
return v.Interface().(BeforeInsertHook).BeforeInsert(ctx)
|
||||
}
|
||||
|
||||
func callBeforeInsertHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) (context.Context, error) {
|
||||
return callHookSlice(ctx, slice, ptr, callBeforeInsertHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type AfterInsertHook interface {
|
||||
AfterInsert(context.Context) error
|
||||
}
|
||||
|
||||
var afterInsertHookType = reflect.TypeOf((*AfterInsertHook)(nil)).Elem()
|
||||
|
||||
func callAfterInsertHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(AfterInsertHook).AfterInsert(ctx)
|
||||
}
|
||||
|
||||
func callAfterInsertHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) error {
|
||||
return callHookSlice2(ctx, slice, ptr, callAfterInsertHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BeforeUpdateHook interface {
|
||||
BeforeUpdate(context.Context) (context.Context, error)
|
||||
}
|
||||
|
||||
var beforeUpdateHookType = reflect.TypeOf((*BeforeUpdateHook)(nil)).Elem()
|
||||
|
||||
func callBeforeUpdateHook(ctx context.Context, v reflect.Value) (context.Context, error) {
|
||||
return v.Interface().(BeforeUpdateHook).BeforeUpdate(ctx)
|
||||
}
|
||||
|
||||
func callBeforeUpdateHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) (context.Context, error) {
|
||||
return callHookSlice(ctx, slice, ptr, callBeforeUpdateHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type AfterUpdateHook interface {
|
||||
AfterUpdate(context.Context) error
|
||||
}
|
||||
|
||||
var afterUpdateHookType = reflect.TypeOf((*AfterUpdateHook)(nil)).Elem()
|
||||
|
||||
func callAfterUpdateHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(AfterUpdateHook).AfterUpdate(ctx)
|
||||
}
|
||||
|
||||
func callAfterUpdateHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) error {
|
||||
return callHookSlice2(ctx, slice, ptr, callAfterUpdateHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BeforeDeleteHook interface {
|
||||
BeforeDelete(context.Context) (context.Context, error)
|
||||
}
|
||||
|
||||
var beforeDeleteHookType = reflect.TypeOf((*BeforeDeleteHook)(nil)).Elem()
|
||||
|
||||
func callBeforeDeleteHook(ctx context.Context, v reflect.Value) (context.Context, error) {
|
||||
return v.Interface().(BeforeDeleteHook).BeforeDelete(ctx)
|
||||
}
|
||||
|
||||
func callBeforeDeleteHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) (context.Context, error) {
|
||||
return callHookSlice(ctx, slice, ptr, callBeforeDeleteHook)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type AfterDeleteHook interface {
|
||||
AfterDelete(context.Context) error
|
||||
}
|
||||
|
||||
var afterDeleteHookType = reflect.TypeOf((*AfterDeleteHook)(nil)).Elem()
|
||||
|
||||
func callAfterDeleteHook(ctx context.Context, v reflect.Value) error {
|
||||
return v.Interface().(AfterDeleteHook).AfterDelete(ctx)
|
||||
}
|
||||
|
||||
func callAfterDeleteHookSlice(
|
||||
ctx context.Context, slice reflect.Value, ptr bool,
|
||||
) error {
|
||||
return callHookSlice2(ctx, slice, ptr, callAfterDeleteHook)
|
||||
}
|
||||
345
vendor/github.com/go-pg/pg/v10/orm/insert.go
generated
vendored
Normal file
345
vendor/github.com/go-pg/pg/v10/orm/insert.go
generated
vendored
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type InsertQuery struct {
|
||||
q *Query
|
||||
returningFields []*Field
|
||||
placeholder bool
|
||||
}
|
||||
|
||||
var _ QueryCommand = (*InsertQuery)(nil)
|
||||
|
||||
func NewInsertQuery(q *Query) *InsertQuery {
|
||||
return &InsertQuery{
|
||||
q: q,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *InsertQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *InsertQuery) Operation() QueryOp {
|
||||
return InsertOp
|
||||
}
|
||||
|
||||
func (q *InsertQuery) Clone() QueryCommand {
|
||||
return &InsertQuery{
|
||||
q: q.q.Clone(),
|
||||
placeholder: q.placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *InsertQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
var _ TemplateAppender = (*InsertQuery)(nil)
|
||||
|
||||
func (q *InsertQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
cp := q.Clone().(*InsertQuery)
|
||||
cp.placeholder = true
|
||||
return cp.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
var _ QueryAppender = (*InsertQuery)(nil)
|
||||
|
||||
func (q *InsertQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
|
||||
if len(q.q.with) > 0 {
|
||||
b, err = q.q.appendWith(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, "INSERT INTO "...)
|
||||
if q.q.onConflict != nil {
|
||||
b, err = q.q.appendFirstTableWithAlias(fmter, b)
|
||||
} else {
|
||||
b, err = q.q.appendFirstTable(fmter, b)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = q.appendColumnsValues(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if q.q.onConflict != nil {
|
||||
b = append(b, " ON CONFLICT "...)
|
||||
b, err = q.q.onConflict.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if q.q.onConflictDoUpdate() {
|
||||
if len(q.q.set) > 0 {
|
||||
b, err = q.q.appendSet(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
fields, err := q.q.getDataFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
fields = q.q.tableModel.Table().DataFields
|
||||
}
|
||||
|
||||
b = q.appendSetExcluded(b, fields)
|
||||
}
|
||||
|
||||
if len(q.q.updWhere) > 0 {
|
||||
b = append(b, " WHERE "...)
|
||||
b, err = q.q.appendUpdWhere(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.returning) > 0 {
|
||||
b, err = q.q.appendReturning(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if len(q.returningFields) > 0 {
|
||||
b = appendReturningFields(b, q.returningFields)
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendColumnsValues(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.hasMultiTables() {
|
||||
if q.q.columns != nil {
|
||||
b = append(b, " ("...)
|
||||
b, err = q.q.appendColumns(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, ")"...)
|
||||
}
|
||||
|
||||
b = append(b, " SELECT * FROM "...)
|
||||
b, err = q.q.appendOtherTables(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
if m, ok := q.q.model.(*mapModel); ok {
|
||||
return q.appendMapColumnsValues(b, m.m), nil
|
||||
}
|
||||
|
||||
if !q.q.hasTableModel() {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
fields, err := q.q.getFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
fields = q.q.tableModel.Table().Fields
|
||||
}
|
||||
value := q.q.tableModel.Value()
|
||||
|
||||
b = append(b, " ("...)
|
||||
b = q.appendColumns(b, fields)
|
||||
b = append(b, ") VALUES ("...)
|
||||
if m, ok := q.q.tableModel.(*sliceTableModel); ok {
|
||||
if m.sliceLen == 0 {
|
||||
err = fmt.Errorf("pg: can't bulk-insert empty slice %s", value.Type())
|
||||
return nil, err
|
||||
}
|
||||
b, err = q.appendSliceValues(fmter, b, fields, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
b, err = q.appendValues(fmter, b, fields, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
b = append(b, ")"...)
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendMapColumnsValues(b []byte, m map[string]interface{}) []byte {
|
||||
keys := make([]string, 0, len(m))
|
||||
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
b = append(b, " ("...)
|
||||
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = types.AppendIdent(b, k, 1)
|
||||
}
|
||||
|
||||
b = append(b, ") VALUES ("...)
|
||||
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
if q.placeholder {
|
||||
b = append(b, '?')
|
||||
} else {
|
||||
b = types.Append(b, m[k], 1)
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, ")"...)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendValues(
|
||||
fmter QueryFormatter, b []byte, fields []*Field, strct reflect.Value,
|
||||
) (_ []byte, err error) {
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
app, ok := q.q.modelValues[f.SQLName]
|
||||
if ok {
|
||||
b, err = app.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q.addReturningField(f)
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case q.placeholder:
|
||||
b = append(b, '?')
|
||||
case (f.Default != "" || f.NullZero()) && f.HasZeroValue(strct):
|
||||
b = append(b, "DEFAULT"...)
|
||||
q.addReturningField(f)
|
||||
default:
|
||||
b = f.AppendValue(b, strct, 1)
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range q.q.extraValues {
|
||||
if i > 0 || len(fields) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b, err = v.value.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendSliceValues(
|
||||
fmter QueryFormatter, b []byte, fields []*Field, slice reflect.Value,
|
||||
) (_ []byte, err error) {
|
||||
if q.placeholder {
|
||||
return q.appendValues(fmter, b, fields, reflect.Value{})
|
||||
}
|
||||
|
||||
sliceLen := slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
if i > 0 {
|
||||
b = append(b, "), ("...)
|
||||
}
|
||||
el := indirect(slice.Index(i))
|
||||
b, err = q.appendValues(fmter, b, fields, el)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range q.q.extraValues {
|
||||
if i > 0 || len(fields) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b, err = v.value.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *InsertQuery) addReturningField(field *Field) {
|
||||
if len(q.q.returning) > 0 {
|
||||
return
|
||||
}
|
||||
for _, f := range q.returningFields {
|
||||
if f == field {
|
||||
return
|
||||
}
|
||||
}
|
||||
q.returningFields = append(q.returningFields, field)
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendSetExcluded(b []byte, fields []*Field) []byte {
|
||||
b = append(b, " SET "...)
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, " = EXCLUDED."...)
|
||||
b = append(b, f.Column...)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (q *InsertQuery) appendColumns(b []byte, fields []*Field) []byte {
|
||||
b = appendColumns(b, "", fields)
|
||||
for i, v := range q.q.extraValues {
|
||||
if i > 0 || len(fields) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = types.AppendIdent(b, v.column, 1)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func appendReturningFields(b []byte, fields []*Field) []byte {
|
||||
b = append(b, " RETURNING "...)
|
||||
b = appendColumns(b, "", fields)
|
||||
return b
|
||||
}
|
||||
351
vendor/github.com/go-pg/pg/v10/orm/join.go
generated
vendored
Normal file
351
vendor/github.com/go-pg/pg/v10/orm/join.go
generated
vendored
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type join struct {
|
||||
Parent *join
|
||||
BaseModel TableModel
|
||||
JoinModel TableModel
|
||||
Rel *Relation
|
||||
|
||||
ApplyQuery func(*Query) (*Query, error)
|
||||
Columns []string
|
||||
on []*condAppender
|
||||
}
|
||||
|
||||
func (j *join) AppendOn(app *condAppender) {
|
||||
j.on = append(j.on, app)
|
||||
}
|
||||
|
||||
func (j *join) Select(fmter QueryFormatter, q *Query) error {
|
||||
switch j.Rel.Type {
|
||||
case HasManyRelation:
|
||||
return j.selectMany(fmter, q)
|
||||
case Many2ManyRelation:
|
||||
return j.selectM2M(fmter, q)
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
func (j *join) selectMany(_ QueryFormatter, q *Query) error {
|
||||
q, err := j.manyQuery(q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if q == nil {
|
||||
return nil
|
||||
}
|
||||
return q.Select()
|
||||
}
|
||||
|
||||
func (j *join) manyQuery(q *Query) (*Query, error) {
|
||||
manyModel := newManyModel(j)
|
||||
if manyModel == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
q = q.Model(manyModel)
|
||||
if j.ApplyQuery != nil {
|
||||
var err error
|
||||
q, err = j.ApplyQuery(q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.columns) == 0 {
|
||||
q.columns = append(q.columns, &hasManyColumnsAppender{j})
|
||||
}
|
||||
|
||||
baseTable := j.BaseModel.Table()
|
||||
var where []byte
|
||||
if len(j.Rel.JoinFKs) > 1 {
|
||||
where = append(where, '(')
|
||||
}
|
||||
where = appendColumns(where, j.JoinModel.Table().Alias, j.Rel.JoinFKs)
|
||||
if len(j.Rel.JoinFKs) > 1 {
|
||||
where = append(where, ')')
|
||||
}
|
||||
where = append(where, " IN ("...)
|
||||
where = appendChildValues(
|
||||
where, j.JoinModel.Root(), j.JoinModel.ParentIndex(), j.Rel.BaseFKs)
|
||||
where = append(where, ")"...)
|
||||
q = q.Where(internal.BytesToString(where))
|
||||
|
||||
if j.Rel.Polymorphic != nil {
|
||||
q = q.Where(`? IN (?, ?)`,
|
||||
j.Rel.Polymorphic.Column,
|
||||
baseTable.ModelName, baseTable.TypeName)
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (j *join) selectM2M(fmter QueryFormatter, q *Query) error {
|
||||
q, err := j.m2mQuery(fmter, q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if q == nil {
|
||||
return nil
|
||||
}
|
||||
return q.Select()
|
||||
}
|
||||
|
||||
func (j *join) m2mQuery(fmter QueryFormatter, q *Query) (*Query, error) {
|
||||
m2mModel := newM2MModel(j)
|
||||
if m2mModel == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
q = q.Model(m2mModel)
|
||||
if j.ApplyQuery != nil {
|
||||
var err error
|
||||
q, err = j.ApplyQuery(q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.columns) == 0 {
|
||||
q.columns = append(q.columns, &hasManyColumnsAppender{j})
|
||||
}
|
||||
|
||||
index := j.JoinModel.ParentIndex()
|
||||
baseTable := j.BaseModel.Table()
|
||||
|
||||
//nolint
|
||||
var join []byte
|
||||
join = append(join, "JOIN "...)
|
||||
join = fmter.FormatQuery(join, string(j.Rel.M2MTableName))
|
||||
join = append(join, " AS "...)
|
||||
join = append(join, j.Rel.M2MTableAlias...)
|
||||
join = append(join, " ON ("...)
|
||||
for i, col := range j.Rel.M2MBaseFKs {
|
||||
if i > 0 {
|
||||
join = append(join, ", "...)
|
||||
}
|
||||
join = append(join, j.Rel.M2MTableAlias...)
|
||||
join = append(join, '.')
|
||||
join = types.AppendIdent(join, col, 1)
|
||||
}
|
||||
join = append(join, ") IN ("...)
|
||||
join = appendChildValues(join, j.BaseModel.Root(), index, baseTable.PKs)
|
||||
join = append(join, ")"...)
|
||||
q = q.Join(internal.BytesToString(join))
|
||||
|
||||
joinTable := j.JoinModel.Table()
|
||||
for i, col := range j.Rel.M2MJoinFKs {
|
||||
pk := joinTable.PKs[i]
|
||||
q = q.Where("?.? = ?.?",
|
||||
joinTable.Alias, pk.Column,
|
||||
j.Rel.M2MTableAlias, types.Ident(col))
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (j *join) hasParent() bool {
|
||||
if j.Parent != nil {
|
||||
switch j.Parent.Rel.Type {
|
||||
case HasOneRelation, BelongsToRelation:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (j *join) appendAlias(b []byte) []byte {
|
||||
b = append(b, '"')
|
||||
b = appendAlias(b, j)
|
||||
b = append(b, '"')
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *join) appendAliasColumn(b []byte, column string) []byte {
|
||||
b = append(b, '"')
|
||||
b = appendAlias(b, j)
|
||||
b = append(b, "__"...)
|
||||
b = append(b, column...)
|
||||
b = append(b, '"')
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *join) appendBaseAlias(b []byte) []byte {
|
||||
if j.hasParent() {
|
||||
b = append(b, '"')
|
||||
b = appendAlias(b, j.Parent)
|
||||
b = append(b, '"')
|
||||
return b
|
||||
}
|
||||
return append(b, j.BaseModel.Table().Alias...)
|
||||
}
|
||||
|
||||
func (j *join) appendSoftDelete(b []byte, flags queryFlag) []byte {
|
||||
b = append(b, '.')
|
||||
b = append(b, j.JoinModel.Table().SoftDeleteField.Column...)
|
||||
if hasFlag(flags, deletedFlag) {
|
||||
b = append(b, " IS NOT NULL"...)
|
||||
} else {
|
||||
b = append(b, " IS NULL"...)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func appendAlias(b []byte, j *join) []byte {
|
||||
if j.hasParent() {
|
||||
b = appendAlias(b, j.Parent)
|
||||
b = append(b, "__"...)
|
||||
}
|
||||
b = append(b, j.Rel.Field.SQLName...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *join) appendHasOneColumns(b []byte) []byte {
|
||||
if j.Columns == nil {
|
||||
for i, f := range j.JoinModel.Table().Fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = j.appendAlias(b)
|
||||
b = append(b, '.')
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, " AS "...)
|
||||
b = j.appendAliasColumn(b, f.SQLName)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
for i, column := range j.Columns {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = j.appendAlias(b)
|
||||
b = append(b, '.')
|
||||
b = types.AppendIdent(b, column, 1)
|
||||
b = append(b, " AS "...)
|
||||
b = j.appendAliasColumn(b, column)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *join) appendHasOneJoin(fmter QueryFormatter, b []byte, q *Query) (_ []byte, err error) {
|
||||
isSoftDelete := j.JoinModel.Table().SoftDeleteField != nil && !q.hasFlag(allWithDeletedFlag)
|
||||
|
||||
b = append(b, "LEFT JOIN "...)
|
||||
b = fmter.FormatQuery(b, string(j.JoinModel.Table().SQLNameForSelects))
|
||||
b = append(b, " AS "...)
|
||||
b = j.appendAlias(b)
|
||||
|
||||
b = append(b, " ON "...)
|
||||
|
||||
if isSoftDelete {
|
||||
b = append(b, '(')
|
||||
}
|
||||
|
||||
if len(j.Rel.BaseFKs) > 1 {
|
||||
b = append(b, '(')
|
||||
}
|
||||
for i, baseFK := range j.Rel.BaseFKs {
|
||||
if i > 0 {
|
||||
b = append(b, " AND "...)
|
||||
}
|
||||
b = j.appendAlias(b)
|
||||
b = append(b, '.')
|
||||
b = append(b, j.Rel.JoinFKs[i].Column...)
|
||||
b = append(b, " = "...)
|
||||
b = j.appendBaseAlias(b)
|
||||
b = append(b, '.')
|
||||
b = append(b, baseFK.Column...)
|
||||
}
|
||||
if len(j.Rel.BaseFKs) > 1 {
|
||||
b = append(b, ')')
|
||||
}
|
||||
|
||||
for _, on := range j.on {
|
||||
b = on.AppendSep(b)
|
||||
b, err = on.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if isSoftDelete {
|
||||
b = append(b, ')')
|
||||
}
|
||||
|
||||
if isSoftDelete {
|
||||
b = append(b, " AND "...)
|
||||
b = j.appendAlias(b)
|
||||
b = j.appendSoftDelete(b, q.flags)
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
type hasManyColumnsAppender struct {
|
||||
*join
|
||||
}
|
||||
|
||||
var _ QueryAppender = (*hasManyColumnsAppender)(nil)
|
||||
|
||||
func (q *hasManyColumnsAppender) AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
if q.Rel.M2MTableAlias != "" {
|
||||
b = append(b, q.Rel.M2MTableAlias...)
|
||||
b = append(b, ".*, "...)
|
||||
}
|
||||
|
||||
joinTable := q.JoinModel.Table()
|
||||
|
||||
if q.Columns != nil {
|
||||
for i, column := range q.Columns {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = append(b, joinTable.Alias...)
|
||||
b = append(b, '.')
|
||||
b = types.AppendIdent(b, column, 1)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
b = appendColumns(b, joinTable.Alias, joinTable.Fields)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func appendChildValues(b []byte, v reflect.Value, index []int, fields []*Field) []byte {
|
||||
seen := make(map[string]struct{})
|
||||
walk(v, index, func(v reflect.Value) {
|
||||
start := len(b)
|
||||
|
||||
if len(fields) > 1 {
|
||||
b = append(b, '(')
|
||||
}
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b = f.AppendValue(b, v, 1)
|
||||
}
|
||||
if len(fields) > 1 {
|
||||
b = append(b, ')')
|
||||
}
|
||||
b = append(b, ", "...)
|
||||
|
||||
if _, ok := seen[string(b[start:])]; ok {
|
||||
b = b[:start]
|
||||
} else {
|
||||
seen[string(b[start:])] = struct{}{}
|
||||
}
|
||||
})
|
||||
if len(seen) > 0 {
|
||||
b = b[:len(b)-2] // trim ", "
|
||||
}
|
||||
return b
|
||||
}
|
||||
150
vendor/github.com/go-pg/pg/v10/orm/model.go
generated
vendored
Normal file
150
vendor/github.com/go-pg/pg/v10/orm/model.go
generated
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
var errModelNil = errors.New("pg: Model(nil)")
|
||||
|
||||
type useQueryOne interface {
|
||||
useQueryOne() bool
|
||||
}
|
||||
|
||||
type HooklessModel interface {
|
||||
// Init is responsible to initialize/reset model state.
|
||||
// It is called only once no matter how many rows were returned.
|
||||
Init() error
|
||||
|
||||
// NextColumnScanner returns a ColumnScanner that is used to scan columns
|
||||
// from the current row. It is called once for every row.
|
||||
NextColumnScanner() ColumnScanner
|
||||
|
||||
// AddColumnScanner adds the ColumnScanner to the model.
|
||||
AddColumnScanner(ColumnScanner) error
|
||||
}
|
||||
|
||||
type Model interface {
|
||||
HooklessModel
|
||||
|
||||
AfterScanHook
|
||||
AfterSelectHook
|
||||
|
||||
BeforeInsertHook
|
||||
AfterInsertHook
|
||||
|
||||
BeforeUpdateHook
|
||||
AfterUpdateHook
|
||||
|
||||
BeforeDeleteHook
|
||||
AfterDeleteHook
|
||||
}
|
||||
|
||||
func NewModel(value interface{}) (Model, error) {
|
||||
return newModel(value, false)
|
||||
}
|
||||
|
||||
func newScanModel(values []interface{}) (Model, error) {
|
||||
if len(values) > 1 {
|
||||
return Scan(values...), nil
|
||||
}
|
||||
return newModel(values[0], true)
|
||||
}
|
||||
|
||||
func newModel(value interface{}, scan bool) (Model, error) {
|
||||
switch value := value.(type) {
|
||||
case Model:
|
||||
return value, nil
|
||||
case HooklessModel:
|
||||
return newModelWithHookStubs(value), nil
|
||||
case types.ValueScanner, sql.Scanner:
|
||||
if !scan {
|
||||
return nil, fmt.Errorf("pg: Model(unsupported %T)", value)
|
||||
}
|
||||
return Scan(value), nil
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
if !v.IsValid() {
|
||||
return nil, errModelNil
|
||||
}
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return nil, fmt.Errorf("pg: Model(non-pointer %T)", value)
|
||||
}
|
||||
|
||||
if v.IsNil() {
|
||||
typ := v.Type().Elem()
|
||||
if typ.Kind() == reflect.Struct {
|
||||
return newStructTableModel(GetTable(typ)), nil
|
||||
}
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
v = v.Elem()
|
||||
|
||||
if v.Kind() == reflect.Interface {
|
||||
if !v.IsNil() {
|
||||
v = v.Elem()
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return nil, fmt.Errorf("pg: Model(non-pointer %s)", v.Type().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
if v.Type() != timeType {
|
||||
return newStructTableModelValue(v), nil
|
||||
}
|
||||
case reflect.Slice:
|
||||
elemType := sliceElemType(v)
|
||||
switch elemType.Kind() {
|
||||
case reflect.Struct:
|
||||
if elemType != timeType {
|
||||
return newSliceTableModel(v, elemType), nil
|
||||
}
|
||||
case reflect.Map:
|
||||
if err := validMap(elemType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
slicePtr := v.Addr().Interface().(*[]map[string]interface{})
|
||||
return newMapSliceModel(slicePtr), nil
|
||||
}
|
||||
return newSliceModel(v, elemType), nil
|
||||
case reflect.Map:
|
||||
typ := v.Type()
|
||||
if err := validMap(typ); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapPtr := v.Addr().Interface().(*map[string]interface{})
|
||||
return newMapModel(mapPtr), nil
|
||||
}
|
||||
|
||||
if !scan {
|
||||
return nil, fmt.Errorf("pg: Model(unsupported %T)", value)
|
||||
}
|
||||
return Scan(value), nil
|
||||
}
|
||||
|
||||
type modelWithHookStubs struct {
|
||||
hookStubs
|
||||
HooklessModel
|
||||
}
|
||||
|
||||
func newModelWithHookStubs(m HooklessModel) Model {
|
||||
return modelWithHookStubs{
|
||||
HooklessModel: m,
|
||||
}
|
||||
}
|
||||
|
||||
func validMap(typ reflect.Type) error {
|
||||
if typ.Key().Kind() != reflect.String || typ.Elem().Kind() != reflect.Interface {
|
||||
return fmt.Errorf("pg: Model(unsupported %s, expected *map[string]interface{})",
|
||||
typ.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
27
vendor/github.com/go-pg/pg/v10/orm/model_discard.go
generated
vendored
Normal file
27
vendor/github.com/go-pg/pg/v10/orm/model_discard.go
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type Discard struct {
|
||||
hookStubs
|
||||
}
|
||||
|
||||
var _ Model = (*Discard)(nil)
|
||||
|
||||
func (Discard) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Discard) NextColumnScanner() ColumnScanner {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Discard) AddColumnScanner(ColumnScanner) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Discard) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
return nil
|
||||
}
|
||||
89
vendor/github.com/go-pg/pg/v10/orm/model_func.go
generated
vendored
Normal file
89
vendor/github.com/go-pg/pg/v10/orm/model_func.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
|
||||
type funcModel struct {
|
||||
Model
|
||||
fnv reflect.Value
|
||||
fnIn []reflect.Value
|
||||
}
|
||||
|
||||
var _ Model = (*funcModel)(nil)
|
||||
|
||||
func newFuncModel(fn interface{}) *funcModel {
|
||||
m := &funcModel{
|
||||
fnv: reflect.ValueOf(fn),
|
||||
}
|
||||
|
||||
fnt := m.fnv.Type()
|
||||
if fnt.Kind() != reflect.Func {
|
||||
panic(fmt.Errorf("ForEach expects a %s, got a %s",
|
||||
reflect.Func, fnt.Kind()))
|
||||
}
|
||||
|
||||
if fnt.NumIn() < 1 {
|
||||
panic(fmt.Errorf("ForEach expects at least 1 arg, got %d", fnt.NumIn()))
|
||||
}
|
||||
|
||||
if fnt.NumOut() != 1 {
|
||||
panic(fmt.Errorf("ForEach must return 1 error value, got %d", fnt.NumOut()))
|
||||
}
|
||||
if fnt.Out(0) != errorType {
|
||||
panic(fmt.Errorf("ForEach must return an error, got %T", fnt.Out(0)))
|
||||
}
|
||||
|
||||
if fnt.NumIn() > 1 {
|
||||
initFuncModelScan(m, fnt)
|
||||
return m
|
||||
}
|
||||
|
||||
t0 := fnt.In(0)
|
||||
var v0 reflect.Value
|
||||
if t0.Kind() == reflect.Ptr {
|
||||
t0 = t0.Elem()
|
||||
v0 = reflect.New(t0)
|
||||
} else {
|
||||
v0 = reflect.New(t0).Elem()
|
||||
}
|
||||
|
||||
m.fnIn = []reflect.Value{v0}
|
||||
|
||||
model, ok := v0.Interface().(Model)
|
||||
if ok {
|
||||
m.Model = model
|
||||
return m
|
||||
}
|
||||
|
||||
if v0.Kind() == reflect.Ptr {
|
||||
v0 = v0.Elem()
|
||||
}
|
||||
if v0.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("ForEach accepts a %s, got %s",
|
||||
reflect.Struct, v0.Kind()))
|
||||
}
|
||||
m.Model = newStructTableModelValue(v0)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func initFuncModelScan(m *funcModel, fnt reflect.Type) {
|
||||
m.fnIn = make([]reflect.Value, fnt.NumIn())
|
||||
for i := 0; i < fnt.NumIn(); i++ {
|
||||
m.fnIn[i] = reflect.New(fnt.In(i)).Elem()
|
||||
}
|
||||
m.Model = scanReflectValues(m.fnIn)
|
||||
}
|
||||
|
||||
func (m *funcModel) AddColumnScanner(_ ColumnScanner) error {
|
||||
out := m.fnv.Call(m.fnIn)
|
||||
errv := out[0]
|
||||
if !errv.IsNil() {
|
||||
return errv.Interface().(error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
53
vendor/github.com/go-pg/pg/v10/orm/model_map.go
generated
vendored
Normal file
53
vendor/github.com/go-pg/pg/v10/orm/model_map.go
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type mapModel struct {
|
||||
hookStubs
|
||||
ptr *map[string]interface{}
|
||||
m map[string]interface{}
|
||||
}
|
||||
|
||||
var _ Model = (*mapModel)(nil)
|
||||
|
||||
func newMapModel(ptr *map[string]interface{}) *mapModel {
|
||||
model := &mapModel{
|
||||
ptr: ptr,
|
||||
}
|
||||
if ptr != nil {
|
||||
model.m = *ptr
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
func (m *mapModel) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mapModel) NextColumnScanner() ColumnScanner {
|
||||
if m.m == nil {
|
||||
m.m = make(map[string]interface{})
|
||||
*m.ptr = m.m
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m mapModel) AddColumnScanner(ColumnScanner) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mapModel) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
val, err := types.ReadColumnValue(col, rd, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.m[col.Name] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mapModel) useQueryOne() bool {
|
||||
return true
|
||||
}
|
||||
45
vendor/github.com/go-pg/pg/v10/orm/model_map_slice.go
generated
vendored
Normal file
45
vendor/github.com/go-pg/pg/v10/orm/model_map_slice.go
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package orm
|
||||
|
||||
type mapSliceModel struct {
|
||||
mapModel
|
||||
slice *[]map[string]interface{}
|
||||
}
|
||||
|
||||
var _ Model = (*mapSliceModel)(nil)
|
||||
|
||||
func newMapSliceModel(ptr *[]map[string]interface{}) *mapSliceModel {
|
||||
return &mapSliceModel{
|
||||
slice: ptr,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mapSliceModel) Init() error {
|
||||
slice := *m.slice
|
||||
if len(slice) > 0 {
|
||||
*m.slice = slice[:0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mapSliceModel) NextColumnScanner() ColumnScanner {
|
||||
slice := *m.slice
|
||||
if len(slice) == cap(slice) {
|
||||
m.mapModel.m = make(map[string]interface{})
|
||||
*m.slice = append(slice, m.mapModel.m) //nolint:gocritic
|
||||
return m
|
||||
}
|
||||
|
||||
slice = slice[:len(slice)+1]
|
||||
el := slice[len(slice)-1]
|
||||
if el != nil {
|
||||
m.mapModel.m = el
|
||||
} else {
|
||||
el = make(map[string]interface{})
|
||||
slice[len(slice)-1] = el
|
||||
m.mapModel.m = el
|
||||
}
|
||||
*m.slice = slice
|
||||
return m
|
||||
}
|
||||
|
||||
func (mapSliceModel) useQueryOne() {} //nolint:unused
|
||||
69
vendor/github.com/go-pg/pg/v10/orm/model_scan.go
generated
vendored
Normal file
69
vendor/github.com/go-pg/pg/v10/orm/model_scan.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type scanValuesModel struct {
|
||||
Discard
|
||||
values []interface{}
|
||||
}
|
||||
|
||||
var _ Model = scanValuesModel{}
|
||||
|
||||
//nolint
|
||||
func Scan(values ...interface{}) scanValuesModel {
|
||||
return scanValuesModel{
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
func (scanValuesModel) useQueryOne() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m scanValuesModel) NextColumnScanner() ColumnScanner {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m scanValuesModel) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
if int(col.Index) >= len(m.values) {
|
||||
return fmt.Errorf("pg: no Scan var for column index=%d name=%q",
|
||||
col.Index, col.Name)
|
||||
}
|
||||
return types.Scan(m.values[col.Index], rd, n)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type scanReflectValuesModel struct {
|
||||
Discard
|
||||
values []reflect.Value
|
||||
}
|
||||
|
||||
var _ Model = scanReflectValuesModel{}
|
||||
|
||||
func scanReflectValues(values []reflect.Value) scanReflectValuesModel {
|
||||
return scanReflectValuesModel{
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
func (scanReflectValuesModel) useQueryOne() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m scanReflectValuesModel) NextColumnScanner() ColumnScanner {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m scanReflectValuesModel) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
if int(col.Index) >= len(m.values) {
|
||||
return fmt.Errorf("pg: no Scan var for column index=%d name=%q",
|
||||
col.Index, col.Name)
|
||||
}
|
||||
return types.ScanValue(m.values[col.Index], rd, n)
|
||||
}
|
||||
43
vendor/github.com/go-pg/pg/v10/orm/model_slice.go
generated
vendored
Normal file
43
vendor/github.com/go-pg/pg/v10/orm/model_slice.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type sliceModel struct {
|
||||
Discard
|
||||
slice reflect.Value
|
||||
nextElem func() reflect.Value
|
||||
scan func(reflect.Value, types.Reader, int) error
|
||||
}
|
||||
|
||||
var _ Model = (*sliceModel)(nil)
|
||||
|
||||
func newSliceModel(slice reflect.Value, elemType reflect.Type) *sliceModel {
|
||||
return &sliceModel{
|
||||
slice: slice,
|
||||
scan: types.Scanner(elemType),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *sliceModel) Init() error {
|
||||
if m.slice.IsValid() && m.slice.Len() > 0 {
|
||||
m.slice.Set(m.slice.Slice(0, 0))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceModel) NextColumnScanner() ColumnScanner {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *sliceModel) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
if m.nextElem == nil {
|
||||
m.nextElem = internal.MakeSliceNextElemFunc(m.slice)
|
||||
}
|
||||
v := m.nextElem()
|
||||
return m.scan(v, rd, n)
|
||||
}
|
||||
65
vendor/github.com/go-pg/pg/v10/orm/model_table.go
generated
vendored
Normal file
65
vendor/github.com/go-pg/pg/v10/orm/model_table.go
generated
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type TableModel interface {
|
||||
Model
|
||||
|
||||
IsNil() bool
|
||||
Table() *Table
|
||||
Relation() *Relation
|
||||
AppendParam(QueryFormatter, []byte, string) ([]byte, bool)
|
||||
|
||||
Join(string, func(*Query) (*Query, error)) *join
|
||||
GetJoin(string) *join
|
||||
GetJoins() []join
|
||||
AddJoin(join) *join
|
||||
|
||||
Root() reflect.Value
|
||||
Index() []int
|
||||
ParentIndex() []int
|
||||
Mount(reflect.Value)
|
||||
Kind() reflect.Kind
|
||||
Value() reflect.Value
|
||||
|
||||
setSoftDeleteField() error
|
||||
scanColumn(types.ColumnInfo, types.Reader, int) (bool, error)
|
||||
}
|
||||
|
||||
func newTableModelIndex(typ reflect.Type, root reflect.Value, index []int, rel *Relation) (TableModel, error) {
|
||||
typ = typeByIndex(typ, index)
|
||||
|
||||
if typ.Kind() == reflect.Struct {
|
||||
return &structTableModel{
|
||||
table: GetTable(typ),
|
||||
rel: rel,
|
||||
|
||||
root: root,
|
||||
index: index,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if typ.Kind() == reflect.Slice {
|
||||
structType := indirectType(typ.Elem())
|
||||
if structType.Kind() == reflect.Struct {
|
||||
m := sliceTableModel{
|
||||
structTableModel: structTableModel{
|
||||
table: GetTable(structType),
|
||||
rel: rel,
|
||||
|
||||
root: root,
|
||||
index: index,
|
||||
},
|
||||
}
|
||||
m.init(typ)
|
||||
return &m, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("pg: NewModel(%s)", typ)
|
||||
}
|
||||
111
vendor/github.com/go-pg/pg/v10/orm/model_table_m2m.go
generated
vendored
Normal file
111
vendor/github.com/go-pg/pg/v10/orm/model_table_m2m.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal/pool"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type m2mModel struct {
|
||||
*sliceTableModel
|
||||
baseTable *Table
|
||||
rel *Relation
|
||||
|
||||
buf []byte
|
||||
dstValues map[string][]reflect.Value
|
||||
columns map[string]string
|
||||
}
|
||||
|
||||
var _ TableModel = (*m2mModel)(nil)
|
||||
|
||||
func newM2MModel(j *join) *m2mModel {
|
||||
baseTable := j.BaseModel.Table()
|
||||
joinModel := j.JoinModel.(*sliceTableModel)
|
||||
dstValues := dstValues(joinModel, baseTable.PKs)
|
||||
if len(dstValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
m := &m2mModel{
|
||||
sliceTableModel: joinModel,
|
||||
baseTable: baseTable,
|
||||
rel: j.Rel,
|
||||
|
||||
dstValues: dstValues,
|
||||
columns: make(map[string]string),
|
||||
}
|
||||
if !m.sliceOfPtr {
|
||||
m.strct = reflect.New(m.table.Type).Elem()
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *m2mModel) NextColumnScanner() ColumnScanner {
|
||||
if m.sliceOfPtr {
|
||||
m.strct = reflect.New(m.table.Type).Elem()
|
||||
} else {
|
||||
m.strct.Set(m.table.zeroStruct)
|
||||
}
|
||||
m.structInited = false
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *m2mModel) AddColumnScanner(_ ColumnScanner) error {
|
||||
buf, err := m.modelIDMap(m.buf[:0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.buf = buf
|
||||
|
||||
dstValues, ok := m.dstValues[string(buf)]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"pg: relation=%q does not have base %s with id=%q (check join conditions)",
|
||||
m.rel.Field.GoName, m.baseTable, buf)
|
||||
}
|
||||
|
||||
for _, v := range dstValues {
|
||||
if m.sliceOfPtr {
|
||||
v.Set(reflect.Append(v, m.strct.Addr()))
|
||||
} else {
|
||||
v.Set(reflect.Append(v, m.strct))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *m2mModel) modelIDMap(b []byte) ([]byte, error) {
|
||||
for i, col := range m.rel.M2MBaseFKs {
|
||||
if i > 0 {
|
||||
b = append(b, ',')
|
||||
}
|
||||
if s, ok := m.columns[col]; ok {
|
||||
b = append(b, s...)
|
||||
} else {
|
||||
return nil, fmt.Errorf("pg: %s does not have column=%q",
|
||||
m.sliceTableModel, col)
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (m *m2mModel) ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error {
|
||||
if n > 0 {
|
||||
b, err := rd.ReadFullTemp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.columns[col.Name] = string(b)
|
||||
rd = pool.NewBytesReader(b)
|
||||
} else {
|
||||
m.columns[col.Name] = ""
|
||||
}
|
||||
|
||||
if ok, err := m.sliceTableModel.scanColumn(col, rd, n); ok {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
75
vendor/github.com/go-pg/pg/v10/orm/model_table_many.go
generated
vendored
Normal file
75
vendor/github.com/go-pg/pg/v10/orm/model_table_many.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type manyModel struct {
|
||||
*sliceTableModel
|
||||
baseTable *Table
|
||||
rel *Relation
|
||||
|
||||
buf []byte
|
||||
dstValues map[string][]reflect.Value
|
||||
}
|
||||
|
||||
var _ TableModel = (*manyModel)(nil)
|
||||
|
||||
func newManyModel(j *join) *manyModel {
|
||||
baseTable := j.BaseModel.Table()
|
||||
joinModel := j.JoinModel.(*sliceTableModel)
|
||||
dstValues := dstValues(joinModel, j.Rel.BaseFKs)
|
||||
if len(dstValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
m := manyModel{
|
||||
sliceTableModel: joinModel,
|
||||
baseTable: baseTable,
|
||||
rel: j.Rel,
|
||||
|
||||
dstValues: dstValues,
|
||||
}
|
||||
if !m.sliceOfPtr {
|
||||
m.strct = reflect.New(m.table.Type).Elem()
|
||||
}
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m *manyModel) NextColumnScanner() ColumnScanner {
|
||||
if m.sliceOfPtr {
|
||||
m.strct = reflect.New(m.table.Type).Elem()
|
||||
} else {
|
||||
m.strct.Set(m.table.zeroStruct)
|
||||
}
|
||||
m.structInited = false
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *manyModel) AddColumnScanner(model ColumnScanner) error {
|
||||
m.buf = modelID(m.buf[:0], m.strct, m.rel.JoinFKs)
|
||||
dstValues, ok := m.dstValues[string(m.buf)]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"pg: relation=%q does not have base %s with id=%q (check join conditions)",
|
||||
m.rel.Field.GoName, m.baseTable, m.buf)
|
||||
}
|
||||
|
||||
for i, v := range dstValues {
|
||||
if !m.sliceOfPtr {
|
||||
v.Set(reflect.Append(v, m.strct))
|
||||
continue
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
v.Set(reflect.Append(v, m.strct.Addr()))
|
||||
continue
|
||||
}
|
||||
|
||||
clone := reflect.New(m.strct.Type()).Elem()
|
||||
clone.Set(m.strct)
|
||||
v.Set(reflect.Append(v, clone.Addr()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
156
vendor/github.com/go-pg/pg/v10/orm/model_table_slice.go
generated
vendored
Normal file
156
vendor/github.com/go-pg/pg/v10/orm/model_table_slice.go
generated
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
)
|
||||
|
||||
type sliceTableModel struct {
|
||||
structTableModel
|
||||
|
||||
slice reflect.Value
|
||||
sliceLen int
|
||||
sliceOfPtr bool
|
||||
nextElem func() reflect.Value
|
||||
}
|
||||
|
||||
var _ TableModel = (*sliceTableModel)(nil)
|
||||
|
||||
func newSliceTableModel(slice reflect.Value, elemType reflect.Type) *sliceTableModel {
|
||||
m := &sliceTableModel{
|
||||
structTableModel: structTableModel{
|
||||
table: GetTable(elemType),
|
||||
root: slice,
|
||||
},
|
||||
slice: slice,
|
||||
sliceLen: slice.Len(),
|
||||
nextElem: internal.MakeSliceNextElemFunc(slice),
|
||||
}
|
||||
m.init(slice.Type())
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) init(sliceType reflect.Type) {
|
||||
switch sliceType.Elem().Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
m.sliceOfPtr = true
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
func (*sliceTableModel) useQueryOne() {}
|
||||
|
||||
func (m *sliceTableModel) IsNil() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) AppendParam(fmter QueryFormatter, b []byte, name string) ([]byte, bool) {
|
||||
if field, ok := m.table.FieldsMap[name]; ok {
|
||||
b = append(b, "_data."...)
|
||||
b = append(b, field.Column...)
|
||||
return b, true
|
||||
}
|
||||
return m.structTableModel.AppendParam(fmter, b, name)
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) Join(name string, apply func(*Query) (*Query, error)) *join {
|
||||
return m.join(m.Value(), name, apply)
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) Bind(bind reflect.Value) {
|
||||
m.slice = bind.Field(m.index[len(m.index)-1])
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) Kind() reflect.Kind {
|
||||
return reflect.Slice
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) Value() reflect.Value {
|
||||
return m.slice
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) Init() error {
|
||||
if m.slice.IsValid() && m.slice.Len() > 0 {
|
||||
m.slice.Set(m.slice.Slice(0, 0))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) NextColumnScanner() ColumnScanner {
|
||||
m.strct = m.nextElem()
|
||||
m.structInited = false
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) AddColumnScanner(_ ColumnScanner) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inherit these hooks from structTableModel.
|
||||
var (
|
||||
_ BeforeScanHook = (*sliceTableModel)(nil)
|
||||
_ AfterScanHook = (*sliceTableModel)(nil)
|
||||
)
|
||||
|
||||
func (m *sliceTableModel) AfterSelect(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterSelectHookFlag) {
|
||||
return callAfterSelectHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) BeforeInsert(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeInsertHookFlag) {
|
||||
return callBeforeInsertHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) AfterInsert(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterInsertHookFlag) {
|
||||
return callAfterInsertHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) BeforeUpdate(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeUpdateHookFlag) && !m.IsNil() {
|
||||
return callBeforeUpdateHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) AfterUpdate(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterUpdateHookFlag) {
|
||||
return callAfterUpdateHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) BeforeDelete(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeDeleteHookFlag) && !m.IsNil() {
|
||||
return callBeforeDeleteHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) AfterDelete(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterDeleteHookFlag) && !m.IsNil() {
|
||||
return callAfterDeleteHookSlice(ctx, m.slice, m.sliceOfPtr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *sliceTableModel) setSoftDeleteField() error {
|
||||
sliceLen := m.slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
strct := indirect(m.slice.Index(i))
|
||||
fv := m.table.SoftDeleteField.Value(strct)
|
||||
if err := m.table.SetSoftDeleteField(fv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
399
vendor/github.com/go-pg/pg/v10/orm/model_table_struct.go
generated
vendored
Normal file
399
vendor/github.com/go-pg/pg/v10/orm/model_table_struct.go
generated
vendored
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type structTableModel struct {
|
||||
table *Table
|
||||
rel *Relation
|
||||
joins []join
|
||||
|
||||
root reflect.Value
|
||||
index []int
|
||||
|
||||
strct reflect.Value
|
||||
structInited bool
|
||||
structInitErr error
|
||||
}
|
||||
|
||||
var _ TableModel = (*structTableModel)(nil)
|
||||
|
||||
func newStructTableModel(table *Table) *structTableModel {
|
||||
return &structTableModel{
|
||||
table: table,
|
||||
}
|
||||
}
|
||||
|
||||
func newStructTableModelValue(v reflect.Value) *structTableModel {
|
||||
return &structTableModel{
|
||||
table: GetTable(v.Type()),
|
||||
root: v,
|
||||
strct: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (*structTableModel) useQueryOne() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *structTableModel) String() string {
|
||||
return m.table.String()
|
||||
}
|
||||
|
||||
func (m *structTableModel) IsNil() bool {
|
||||
return !m.strct.IsValid()
|
||||
}
|
||||
|
||||
func (m *structTableModel) Table() *Table {
|
||||
return m.table
|
||||
}
|
||||
|
||||
func (m *structTableModel) Relation() *Relation {
|
||||
return m.rel
|
||||
}
|
||||
|
||||
func (m *structTableModel) AppendParam(fmter QueryFormatter, b []byte, name string) ([]byte, bool) {
|
||||
b, ok := m.table.AppendParam(b, m.strct, name)
|
||||
if ok {
|
||||
return b, true
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "TableName":
|
||||
b = fmter.FormatQuery(b, string(m.table.SQLName))
|
||||
return b, true
|
||||
case "TableAlias":
|
||||
b = append(b, m.table.Alias...)
|
||||
return b, true
|
||||
case "TableColumns":
|
||||
b = appendColumns(b, m.table.Alias, m.table.Fields)
|
||||
return b, true
|
||||
case "Columns":
|
||||
b = appendColumns(b, "", m.table.Fields)
|
||||
return b, true
|
||||
case "TablePKs":
|
||||
b = appendColumns(b, m.table.Alias, m.table.PKs)
|
||||
return b, true
|
||||
case "PKs":
|
||||
b = appendColumns(b, "", m.table.PKs)
|
||||
return b, true
|
||||
}
|
||||
|
||||
return b, false
|
||||
}
|
||||
|
||||
func (m *structTableModel) Root() reflect.Value {
|
||||
return m.root
|
||||
}
|
||||
|
||||
func (m *structTableModel) Index() []int {
|
||||
return m.index
|
||||
}
|
||||
|
||||
func (m *structTableModel) ParentIndex() []int {
|
||||
return m.index[:len(m.index)-len(m.rel.Field.Index)]
|
||||
}
|
||||
|
||||
func (m *structTableModel) Kind() reflect.Kind {
|
||||
return reflect.Struct
|
||||
}
|
||||
|
||||
func (m *structTableModel) Value() reflect.Value {
|
||||
return m.strct
|
||||
}
|
||||
|
||||
func (m *structTableModel) Mount(host reflect.Value) {
|
||||
m.strct = host.FieldByIndex(m.rel.Field.Index)
|
||||
m.structInited = false
|
||||
}
|
||||
|
||||
func (m *structTableModel) initStruct() error {
|
||||
if m.structInited {
|
||||
return m.structInitErr
|
||||
}
|
||||
m.structInited = true
|
||||
|
||||
switch m.strct.Kind() {
|
||||
case reflect.Invalid:
|
||||
m.structInitErr = errModelNil
|
||||
return m.structInitErr
|
||||
case reflect.Interface:
|
||||
m.strct = m.strct.Elem()
|
||||
}
|
||||
|
||||
if m.strct.Kind() == reflect.Ptr {
|
||||
if m.strct.IsNil() {
|
||||
m.strct.Set(reflect.New(m.strct.Type().Elem()))
|
||||
m.strct = m.strct.Elem()
|
||||
} else {
|
||||
m.strct = m.strct.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
m.mountJoins()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) mountJoins() {
|
||||
for i := range m.joins {
|
||||
j := &m.joins[i]
|
||||
switch j.Rel.Type {
|
||||
case HasOneRelation, BelongsToRelation:
|
||||
j.JoinModel.Mount(m.strct)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (structTableModel) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) NextColumnScanner() ColumnScanner {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *structTableModel) AddColumnScanner(_ ColumnScanner) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ BeforeScanHook = (*structTableModel)(nil)
|
||||
|
||||
func (m *structTableModel) BeforeScan(ctx context.Context) error {
|
||||
if !m.table.hasFlag(beforeScanHookFlag) {
|
||||
return nil
|
||||
}
|
||||
return callBeforeScanHook(ctx, m.strct.Addr())
|
||||
}
|
||||
|
||||
var _ AfterScanHook = (*structTableModel)(nil)
|
||||
|
||||
func (m *structTableModel) AfterScan(ctx context.Context) error {
|
||||
if !m.table.hasFlag(afterScanHookFlag) || !m.structInited {
|
||||
return nil
|
||||
}
|
||||
|
||||
var firstErr error
|
||||
|
||||
if err := callAfterScanHook(ctx, m.strct.Addr()); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
|
||||
for _, j := range m.joins {
|
||||
switch j.Rel.Type {
|
||||
case HasOneRelation, BelongsToRelation:
|
||||
if err := j.JoinModel.AfterScan(ctx); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstErr
|
||||
}
|
||||
|
||||
func (m *structTableModel) AfterSelect(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterSelectHookFlag) {
|
||||
return callAfterSelectHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) BeforeInsert(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeInsertHookFlag) {
|
||||
return callBeforeInsertHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) AfterInsert(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterInsertHookFlag) {
|
||||
return callAfterInsertHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) BeforeUpdate(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeUpdateHookFlag) && !m.IsNil() {
|
||||
return callBeforeUpdateHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) AfterUpdate(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterUpdateHookFlag) && !m.IsNil() {
|
||||
return callAfterUpdateHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) BeforeDelete(ctx context.Context) (context.Context, error) {
|
||||
if m.table.hasFlag(beforeDeleteHookFlag) && !m.IsNil() {
|
||||
return callBeforeDeleteHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) AfterDelete(ctx context.Context) error {
|
||||
if m.table.hasFlag(afterDeleteHookFlag) && !m.IsNil() {
|
||||
return callAfterDeleteHook(ctx, m.strct.Addr())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) ScanColumn(
|
||||
col types.ColumnInfo, rd types.Reader, n int,
|
||||
) error {
|
||||
ok, err := m.scanColumn(col, rd, n)
|
||||
if ok {
|
||||
return err
|
||||
}
|
||||
if m.table.hasFlag(discardUnknownColumnsFlag) || col.Name[0] == '_' {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"pg: can't find column=%s in %s "+
|
||||
"(prefix the column with underscore or use discard_unknown_columns)",
|
||||
col.Name, m.table,
|
||||
)
|
||||
}
|
||||
|
||||
func (m *structTableModel) scanColumn(col types.ColumnInfo, rd types.Reader, n int) (bool, error) {
|
||||
// Don't init nil struct if value is NULL.
|
||||
if n == -1 &&
|
||||
!m.structInited &&
|
||||
m.strct.Kind() == reflect.Ptr &&
|
||||
m.strct.IsNil() {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if err := m.initStruct(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
joinName, fieldName := splitColumn(col.Name)
|
||||
if joinName != "" {
|
||||
if join := m.GetJoin(joinName); join != nil {
|
||||
joinCol := col
|
||||
joinCol.Name = fieldName
|
||||
return join.JoinModel.scanColumn(joinCol, rd, n)
|
||||
}
|
||||
if m.table.ModelName == joinName {
|
||||
joinCol := col
|
||||
joinCol.Name = fieldName
|
||||
return m.scanColumn(joinCol, rd, n)
|
||||
}
|
||||
}
|
||||
|
||||
field, ok := m.table.FieldsMap[col.Name]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, field.ScanValue(m.strct, rd, n)
|
||||
}
|
||||
|
||||
func (m *structTableModel) GetJoin(name string) *join {
|
||||
for i := range m.joins {
|
||||
j := &m.joins[i]
|
||||
if j.Rel.Field.GoName == name || j.Rel.Field.SQLName == name {
|
||||
return j
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *structTableModel) GetJoins() []join {
|
||||
return m.joins
|
||||
}
|
||||
|
||||
func (m *structTableModel) AddJoin(j join) *join {
|
||||
m.joins = append(m.joins, j)
|
||||
return &m.joins[len(m.joins)-1]
|
||||
}
|
||||
|
||||
func (m *structTableModel) Join(name string, apply func(*Query) (*Query, error)) *join {
|
||||
return m.join(m.Value(), name, apply)
|
||||
}
|
||||
|
||||
func (m *structTableModel) join(
|
||||
bind reflect.Value, name string, apply func(*Query) (*Query, error),
|
||||
) *join {
|
||||
path := strings.Split(name, ".")
|
||||
index := make([]int, 0, len(path))
|
||||
|
||||
currJoin := join{
|
||||
BaseModel: m,
|
||||
JoinModel: m,
|
||||
}
|
||||
var lastJoin *join
|
||||
var hasColumnName bool
|
||||
|
||||
for _, name := range path {
|
||||
rel, ok := currJoin.JoinModel.Table().Relations[name]
|
||||
if !ok {
|
||||
hasColumnName = true
|
||||
break
|
||||
}
|
||||
|
||||
currJoin.Rel = rel
|
||||
index = append(index, rel.Field.Index...)
|
||||
|
||||
if j := currJoin.JoinModel.GetJoin(name); j != nil {
|
||||
currJoin.BaseModel = j.BaseModel
|
||||
currJoin.JoinModel = j.JoinModel
|
||||
|
||||
lastJoin = j
|
||||
} else {
|
||||
model, err := newTableModelIndex(m.table.Type, bind, index, rel)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
currJoin.Parent = lastJoin
|
||||
currJoin.BaseModel = currJoin.JoinModel
|
||||
currJoin.JoinModel = model
|
||||
|
||||
lastJoin = currJoin.BaseModel.AddJoin(currJoin)
|
||||
}
|
||||
}
|
||||
|
||||
// No joins with such name.
|
||||
if lastJoin == nil {
|
||||
return nil
|
||||
}
|
||||
if apply != nil {
|
||||
lastJoin.ApplyQuery = apply
|
||||
}
|
||||
|
||||
if hasColumnName {
|
||||
column := path[len(path)-1]
|
||||
if column == "_" {
|
||||
if lastJoin.Columns == nil {
|
||||
lastJoin.Columns = make([]string, 0)
|
||||
}
|
||||
} else {
|
||||
lastJoin.Columns = append(lastJoin.Columns, column)
|
||||
}
|
||||
}
|
||||
|
||||
return lastJoin
|
||||
}
|
||||
|
||||
func (m *structTableModel) setSoftDeleteField() error {
|
||||
fv := m.table.SoftDeleteField.Value(m.strct)
|
||||
return m.table.SetSoftDeleteField(fv)
|
||||
}
|
||||
|
||||
func splitColumn(s string) (string, string) {
|
||||
ind := strings.Index(s, "__")
|
||||
if ind == -1 {
|
||||
return "", s
|
||||
}
|
||||
return s[:ind], s[ind+2:]
|
||||
}
|
||||
52
vendor/github.com/go-pg/pg/v10/orm/msgpack.go
generated
vendored
Normal file
52
vendor/github.com/go-pg/pg/v10/orm/msgpack.go
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
func msgpackAppender(_ reflect.Type) types.AppenderFunc {
|
||||
return func(b []byte, v reflect.Value, flags int) []byte {
|
||||
hexEnc := types.NewHexEncoder(b, flags)
|
||||
|
||||
enc := msgpack.GetEncoder()
|
||||
defer msgpack.PutEncoder(enc)
|
||||
|
||||
enc.Reset(hexEnc)
|
||||
if err := enc.EncodeValue(v); err != nil {
|
||||
return types.AppendError(b, err)
|
||||
}
|
||||
|
||||
if err := hexEnc.Close(); err != nil {
|
||||
return types.AppendError(b, err)
|
||||
}
|
||||
|
||||
return hexEnc.Bytes()
|
||||
}
|
||||
}
|
||||
|
||||
func msgpackScanner(_ reflect.Type) types.ScannerFunc {
|
||||
return func(v reflect.Value, rd types.Reader, n int) error {
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
hexDec, err := types.NewHexDecoder(rd, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dec := msgpack.GetDecoder()
|
||||
defer msgpack.PutDecoder(dec)
|
||||
|
||||
dec.Reset(hexDec)
|
||||
if err := dec.DecodeValue(v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
58
vendor/github.com/go-pg/pg/v10/orm/orm.go
generated
vendored
Normal file
58
vendor/github.com/go-pg/pg/v10/orm/orm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
The API in this package is not stable and may change without any notice.
|
||||
*/
|
||||
package orm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
// ColumnScanner is used to scan column values.
|
||||
type ColumnScanner interface {
|
||||
// Scan assigns a column value from a row.
|
||||
//
|
||||
// An error should be returned if the value can not be stored
|
||||
// without loss of information.
|
||||
ScanColumn(col types.ColumnInfo, rd types.Reader, n int) error
|
||||
}
|
||||
|
||||
type QueryAppender interface {
|
||||
AppendQuery(fmter QueryFormatter, b []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type TemplateAppender interface {
|
||||
AppendTemplate(b []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type QueryCommand interface {
|
||||
QueryAppender
|
||||
TemplateAppender
|
||||
String() string
|
||||
Operation() QueryOp
|
||||
Clone() QueryCommand
|
||||
Query() *Query
|
||||
}
|
||||
|
||||
// DB is a common interface for pg.DB and pg.Tx types.
|
||||
type DB interface {
|
||||
Model(model ...interface{}) *Query
|
||||
ModelContext(c context.Context, model ...interface{}) *Query
|
||||
|
||||
Exec(query interface{}, params ...interface{}) (Result, error)
|
||||
ExecContext(c context.Context, query interface{}, params ...interface{}) (Result, error)
|
||||
ExecOne(query interface{}, params ...interface{}) (Result, error)
|
||||
ExecOneContext(c context.Context, query interface{}, params ...interface{}) (Result, error)
|
||||
Query(model, query interface{}, params ...interface{}) (Result, error)
|
||||
QueryContext(c context.Context, model, query interface{}, params ...interface{}) (Result, error)
|
||||
QueryOne(model, query interface{}, params ...interface{}) (Result, error)
|
||||
QueryOneContext(c context.Context, model, query interface{}, params ...interface{}) (Result, error)
|
||||
|
||||
CopyFrom(r io.Reader, query interface{}, params ...interface{}) (Result, error)
|
||||
CopyTo(w io.Writer, query interface{}, params ...interface{}) (Result, error)
|
||||
|
||||
Context() context.Context
|
||||
Formatter() QueryFormatter
|
||||
}
|
||||
1680
vendor/github.com/go-pg/pg/v10/orm/query.go
generated
vendored
Normal file
1680
vendor/github.com/go-pg/pg/v10/orm/query.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
33
vendor/github.com/go-pg/pg/v10/orm/relation.go
generated
vendored
Normal file
33
vendor/github.com/go-pg/pg/v10/orm/relation.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
const (
|
||||
InvalidRelation = iota
|
||||
HasOneRelation
|
||||
BelongsToRelation
|
||||
HasManyRelation
|
||||
Many2ManyRelation
|
||||
)
|
||||
|
||||
type Relation struct {
|
||||
Type int
|
||||
Field *Field
|
||||
JoinTable *Table
|
||||
BaseFKs []*Field
|
||||
JoinFKs []*Field
|
||||
Polymorphic *Field
|
||||
|
||||
M2MTableName types.Safe
|
||||
M2MTableAlias types.Safe
|
||||
M2MBaseFKs []string
|
||||
M2MJoinFKs []string
|
||||
}
|
||||
|
||||
func (r *Relation) String() string {
|
||||
return fmt.Sprintf("relation=%s", r.Field.GoName)
|
||||
}
|
||||
14
vendor/github.com/go-pg/pg/v10/orm/result.go
generated
vendored
Normal file
14
vendor/github.com/go-pg/pg/v10/orm/result.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package orm
|
||||
|
||||
// Result summarizes an executed SQL command.
|
||||
type Result interface {
|
||||
Model() Model
|
||||
|
||||
// RowsAffected returns the number of rows affected by SELECT, INSERT, UPDATE,
|
||||
// or DELETE queries. It returns -1 if query can't possibly affect any rows,
|
||||
// e.g. in case of CREATE or SHOW queries.
|
||||
RowsAffected() int
|
||||
|
||||
// RowsReturned returns the number of rows returned by the query.
|
||||
RowsReturned() int
|
||||
}
|
||||
346
vendor/github.com/go-pg/pg/v10/orm/select.go
generated
vendored
Normal file
346
vendor/github.com/go-pg/pg/v10/orm/select.go
generated
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type SelectQuery struct {
|
||||
q *Query
|
||||
count string
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*SelectQuery)(nil)
|
||||
_ QueryCommand = (*SelectQuery)(nil)
|
||||
)
|
||||
|
||||
func NewSelectQuery(q *Query) *SelectQuery {
|
||||
return &SelectQuery{
|
||||
q: q,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *SelectQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *SelectQuery) Operation() QueryOp {
|
||||
return SelectOp
|
||||
}
|
||||
|
||||
func (q *SelectQuery) Clone() QueryCommand {
|
||||
return &SelectQuery{
|
||||
q: q.q.Clone(),
|
||||
count: q.count,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *SelectQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *SelectQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
return q.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *SelectQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) { //nolint:gocyclo
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
|
||||
cteCount := q.count != "" && (len(q.q.group) > 0 || q.isDistinct())
|
||||
if cteCount {
|
||||
b = append(b, `WITH "_count_wrapper" AS (`...)
|
||||
}
|
||||
|
||||
if len(q.q.with) > 0 {
|
||||
b, err = q.q.appendWith(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.union) > 0 {
|
||||
b = append(b, '(')
|
||||
}
|
||||
|
||||
b = append(b, "SELECT "...)
|
||||
|
||||
if len(q.q.distinctOn) > 0 {
|
||||
b = append(b, "DISTINCT ON ("...)
|
||||
for i, app := range q.q.distinctOn {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b, err = app.AppendQuery(fmter, b)
|
||||
}
|
||||
b = append(b, ") "...)
|
||||
} else if q.q.distinctOn != nil {
|
||||
b = append(b, "DISTINCT "...)
|
||||
}
|
||||
|
||||
if q.count != "" && !cteCount {
|
||||
b = append(b, q.count...)
|
||||
} else {
|
||||
b, err = q.appendColumns(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if q.q.hasTables() {
|
||||
b = append(b, " FROM "...)
|
||||
b, err = q.appendTables(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = q.q.forEachHasOneJoin(func(j *join) error {
|
||||
b = append(b, ' ')
|
||||
b, err = j.appendHasOneJoin(fmter, b, q.q)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, j := range q.q.joins {
|
||||
b, err = j.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.where) > 0 || q.q.isSoftDelete() {
|
||||
b = append(b, " WHERE "...)
|
||||
b, err = q.q.appendWhere(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.group) > 0 {
|
||||
b = append(b, " GROUP BY "...)
|
||||
for i, f := range q.q.group {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b, err = f.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(q.q.having) > 0 {
|
||||
b = append(b, " HAVING "...)
|
||||
for i, f := range q.q.having {
|
||||
if i > 0 {
|
||||
b = append(b, " AND "...)
|
||||
}
|
||||
b = append(b, '(')
|
||||
b, err = f.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, ')')
|
||||
}
|
||||
}
|
||||
|
||||
if q.count == "" {
|
||||
if len(q.q.order) > 0 {
|
||||
b = append(b, " ORDER BY "...)
|
||||
for i, f := range q.q.order {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b, err = f.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if q.q.limit != 0 {
|
||||
b = append(b, " LIMIT "...)
|
||||
b = strconv.AppendInt(b, int64(q.q.limit), 10)
|
||||
}
|
||||
|
||||
if q.q.offset != 0 {
|
||||
b = append(b, " OFFSET "...)
|
||||
b = strconv.AppendInt(b, int64(q.q.offset), 10)
|
||||
}
|
||||
|
||||
if q.q.selFor != nil {
|
||||
b = append(b, " FOR "...)
|
||||
b, err = q.q.selFor.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if cteCount {
|
||||
b = append(b, `) SELECT `...)
|
||||
b = append(b, q.count...)
|
||||
b = append(b, ` FROM "_count_wrapper"`...)
|
||||
}
|
||||
|
||||
if len(q.q.union) > 0 {
|
||||
b = append(b, ")"...)
|
||||
|
||||
for _, u := range q.q.union {
|
||||
b = append(b, u.expr...)
|
||||
b = append(b, '(')
|
||||
b, err = u.query.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, ")"...)
|
||||
}
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
|
||||
func (q SelectQuery) appendColumns(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
start := len(b)
|
||||
|
||||
switch {
|
||||
case q.q.columns != nil:
|
||||
b, err = q.q.appendColumns(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case q.q.hasExplicitTableModel():
|
||||
table := q.q.tableModel.Table()
|
||||
if len(table.Fields) > 10 && isTemplateFormatter(fmter) {
|
||||
b = append(b, table.Alias...)
|
||||
b = append(b, '.')
|
||||
b = types.AppendString(b, fmt.Sprintf("%d columns", len(table.Fields)), 2)
|
||||
} else {
|
||||
b = appendColumns(b, table.Alias, table.Fields)
|
||||
}
|
||||
default:
|
||||
b = append(b, '*')
|
||||
}
|
||||
|
||||
err = q.q.forEachHasOneJoin(func(j *join) error {
|
||||
if len(b) != start {
|
||||
b = append(b, ", "...)
|
||||
start = len(b)
|
||||
}
|
||||
|
||||
b = j.appendHasOneColumns(b)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b = bytes.TrimSuffix(b, []byte(", "))
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *SelectQuery) isDistinct() bool {
|
||||
if q.q.distinctOn != nil {
|
||||
return true
|
||||
}
|
||||
for _, column := range q.q.columns {
|
||||
column, ok := column.(*SafeQueryAppender)
|
||||
if ok {
|
||||
if strings.Contains(column.query, "DISTINCT") ||
|
||||
strings.Contains(column.query, "distinct") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (q *SelectQuery) appendTables(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
tables := q.q.tables
|
||||
|
||||
if q.q.modelHasTableName() {
|
||||
table := q.q.tableModel.Table()
|
||||
b = fmter.FormatQuery(b, string(table.SQLNameForSelects))
|
||||
if table.Alias != "" {
|
||||
b = append(b, " AS "...)
|
||||
b = append(b, table.Alias...)
|
||||
}
|
||||
|
||||
if len(tables) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
} else if len(tables) > 0 {
|
||||
b, err = tables[0].AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if q.q.modelHasTableAlias() {
|
||||
b = append(b, " AS "...)
|
||||
b = append(b, q.q.tableModel.Table().Alias...)
|
||||
}
|
||||
|
||||
tables = tables[1:]
|
||||
if len(tables) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
}
|
||||
|
||||
for i, f := range tables {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
b, err = f.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type joinQuery struct {
|
||||
join *SafeQueryAppender
|
||||
on []*condAppender
|
||||
}
|
||||
|
||||
func (j *joinQuery) AppendOn(app *condAppender) {
|
||||
j.on = append(j.on, app)
|
||||
}
|
||||
|
||||
func (j *joinQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
b = append(b, ' ')
|
||||
|
||||
b, err = j.join.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(j.on) > 0 {
|
||||
b = append(b, " ON "...)
|
||||
for i, on := range j.on {
|
||||
if i > 0 {
|
||||
b = on.AppendSep(b)
|
||||
}
|
||||
b, err = on.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
1560
vendor/github.com/go-pg/pg/v10/orm/table.go
generated
vendored
Normal file
1560
vendor/github.com/go-pg/pg/v10/orm/table.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
248
vendor/github.com/go-pg/pg/v10/orm/table_create.go
generated
vendored
Normal file
248
vendor/github.com/go-pg/pg/v10/orm/table_create.go
generated
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type CreateTableOptions struct {
|
||||
Varchar int // replaces PostgreSQL data type `text` with `varchar(n)`
|
||||
Temp bool
|
||||
IfNotExists bool
|
||||
|
||||
// FKConstraints causes CreateTable to create foreign key constraints
|
||||
// for has one relations. ON DELETE hook can be added using tag
|
||||
// `pg:"on_delete:RESTRICT"` on foreign key field. ON UPDATE hook can be added using tag
|
||||
// `pg:"on_update:CASCADE"`
|
||||
FKConstraints bool
|
||||
}
|
||||
|
||||
type CreateTableQuery struct {
|
||||
q *Query
|
||||
opt *CreateTableOptions
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*CreateTableQuery)(nil)
|
||||
_ QueryCommand = (*CreateTableQuery)(nil)
|
||||
)
|
||||
|
||||
func NewCreateTableQuery(q *Query, opt *CreateTableOptions) *CreateTableQuery {
|
||||
return &CreateTableQuery{
|
||||
q: q,
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) Operation() QueryOp {
|
||||
return CreateTableOp
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) Clone() QueryCommand {
|
||||
return &CreateTableQuery{
|
||||
q: q.q.Clone(),
|
||||
opt: q.opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
return q.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
if q.q.tableModel == nil {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
table := q.q.tableModel.Table()
|
||||
|
||||
b = append(b, "CREATE "...)
|
||||
if q.opt != nil && q.opt.Temp {
|
||||
b = append(b, "TEMP "...)
|
||||
}
|
||||
b = append(b, "TABLE "...)
|
||||
if q.opt != nil && q.opt.IfNotExists {
|
||||
b = append(b, "IF NOT EXISTS "...)
|
||||
}
|
||||
b, err = q.q.appendFirstTable(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, " ("...)
|
||||
|
||||
for i, field := range table.Fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b = append(b, field.Column...)
|
||||
b = append(b, " "...)
|
||||
b = q.appendSQLType(b, field)
|
||||
if field.hasFlag(NotNullFlag) {
|
||||
b = append(b, " NOT NULL"...)
|
||||
}
|
||||
if field.hasFlag(UniqueFlag) {
|
||||
b = append(b, " UNIQUE"...)
|
||||
}
|
||||
if field.Default != "" {
|
||||
b = append(b, " DEFAULT "...)
|
||||
b = append(b, field.Default...)
|
||||
}
|
||||
}
|
||||
|
||||
b = appendPKConstraint(b, table.PKs)
|
||||
b = appendUniqueConstraints(b, table)
|
||||
|
||||
if q.opt != nil && q.opt.FKConstraints {
|
||||
for _, rel := range table.Relations {
|
||||
b = q.appendFKConstraint(fmter, b, rel)
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, ")"...)
|
||||
|
||||
if table.PartitionBy != "" {
|
||||
b = append(b, " PARTITION BY "...)
|
||||
b = append(b, table.PartitionBy...)
|
||||
}
|
||||
|
||||
if table.Tablespace != "" {
|
||||
b = q.appendTablespace(b, table.Tablespace)
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) appendSQLType(b []byte, field *Field) []byte {
|
||||
if field.UserSQLType != "" {
|
||||
return append(b, field.UserSQLType...)
|
||||
}
|
||||
if q.opt != nil && q.opt.Varchar > 0 &&
|
||||
field.SQLType == "text" {
|
||||
b = append(b, "varchar("...)
|
||||
b = strconv.AppendInt(b, int64(q.opt.Varchar), 10)
|
||||
b = append(b, ")"...)
|
||||
return b
|
||||
}
|
||||
if field.hasFlag(PrimaryKeyFlag) {
|
||||
return append(b, pkSQLType(field.SQLType)...)
|
||||
}
|
||||
return append(b, field.SQLType...)
|
||||
}
|
||||
|
||||
func pkSQLType(s string) string {
|
||||
switch s {
|
||||
case pgTypeSmallint:
|
||||
return pgTypeSmallserial
|
||||
case pgTypeInteger:
|
||||
return pgTypeSerial
|
||||
case pgTypeBigint:
|
||||
return pgTypeBigserial
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func appendPKConstraint(b []byte, pks []*Field) []byte {
|
||||
if len(pks) == 0 {
|
||||
return b
|
||||
}
|
||||
|
||||
b = append(b, ", PRIMARY KEY ("...)
|
||||
b = appendColumns(b, "", pks)
|
||||
b = append(b, ")"...)
|
||||
return b
|
||||
}
|
||||
|
||||
func appendUniqueConstraints(b []byte, table *Table) []byte {
|
||||
keys := make([]string, 0, len(table.Unique))
|
||||
for key := range table.Unique {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
b = appendUnique(b, table.Unique[key])
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendUnique(b []byte, fields []*Field) []byte {
|
||||
b = append(b, ", UNIQUE ("...)
|
||||
b = appendColumns(b, "", fields)
|
||||
b = append(b, ")"...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) appendFKConstraint(fmter QueryFormatter, b []byte, rel *Relation) []byte {
|
||||
if rel.Type != HasOneRelation {
|
||||
return b
|
||||
}
|
||||
|
||||
b = append(b, ", FOREIGN KEY ("...)
|
||||
b = appendColumns(b, "", rel.BaseFKs)
|
||||
b = append(b, ")"...)
|
||||
|
||||
b = append(b, " REFERENCES "...)
|
||||
b = fmter.FormatQuery(b, string(rel.JoinTable.SQLName))
|
||||
b = append(b, " ("...)
|
||||
b = appendColumns(b, "", rel.JoinFKs)
|
||||
b = append(b, ")"...)
|
||||
|
||||
if s := onDelete(rel.BaseFKs); s != "" {
|
||||
b = append(b, " ON DELETE "...)
|
||||
b = append(b, s...)
|
||||
}
|
||||
|
||||
if s := onUpdate(rel.BaseFKs); s != "" {
|
||||
b = append(b, " ON UPDATE "...)
|
||||
b = append(b, s...)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (q *CreateTableQuery) appendTablespace(b []byte, tableSpace types.Safe) []byte {
|
||||
b = append(b, " TABLESPACE "...)
|
||||
b = append(b, tableSpace...)
|
||||
return b
|
||||
}
|
||||
|
||||
func onDelete(fks []*Field) string {
|
||||
var onDelete string
|
||||
for _, f := range fks {
|
||||
if f.OnDelete != "" {
|
||||
onDelete = f.OnDelete
|
||||
break
|
||||
}
|
||||
}
|
||||
return onDelete
|
||||
}
|
||||
|
||||
func onUpdate(fks []*Field) string {
|
||||
var onUpdate string
|
||||
for _, f := range fks {
|
||||
if f.OnUpdate != "" {
|
||||
onUpdate = f.OnUpdate
|
||||
break
|
||||
}
|
||||
}
|
||||
return onUpdate
|
||||
}
|
||||
73
vendor/github.com/go-pg/pg/v10/orm/table_drop.go
generated
vendored
Normal file
73
vendor/github.com/go-pg/pg/v10/orm/table_drop.go
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package orm
|
||||
|
||||
type DropTableOptions struct {
|
||||
IfExists bool
|
||||
Cascade bool
|
||||
}
|
||||
|
||||
type DropTableQuery struct {
|
||||
q *Query
|
||||
opt *DropTableOptions
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*DropTableQuery)(nil)
|
||||
_ QueryCommand = (*DropTableQuery)(nil)
|
||||
)
|
||||
|
||||
func NewDropTableQuery(q *Query, opt *DropTableOptions) *DropTableQuery {
|
||||
return &DropTableQuery{
|
||||
q: q,
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) Operation() QueryOp {
|
||||
return DropTableOp
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) Clone() QueryCommand {
|
||||
return &DropTableQuery{
|
||||
q: q.q.Clone(),
|
||||
opt: q.opt,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
return q.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *DropTableQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
if q.q.tableModel == nil {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
b = append(b, "DROP TABLE "...)
|
||||
if q.opt != nil && q.opt.IfExists {
|
||||
b = append(b, "IF EXISTS "...)
|
||||
}
|
||||
b, err = q.q.appendFirstTable(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if q.opt != nil && q.opt.Cascade {
|
||||
b = append(b, " CASCADE"...)
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
29
vendor/github.com/go-pg/pg/v10/orm/table_params.go
generated
vendored
Normal file
29
vendor/github.com/go-pg/pg/v10/orm/table_params.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package orm
|
||||
|
||||
import "reflect"
|
||||
|
||||
type tableParams struct {
|
||||
table *Table
|
||||
strct reflect.Value
|
||||
}
|
||||
|
||||
func newTableParams(strct interface{}) (*tableParams, bool) {
|
||||
v := reflect.ValueOf(strct)
|
||||
if !v.IsValid() {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
v = reflect.Indirect(v)
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return &tableParams{
|
||||
table: GetTable(v.Type()),
|
||||
strct: v,
|
||||
}, true
|
||||
}
|
||||
|
||||
func (m *tableParams) AppendParam(fmter QueryFormatter, b []byte, name string) ([]byte, bool) {
|
||||
return m.table.AppendParam(b, m.strct, name)
|
||||
}
|
||||
136
vendor/github.com/go-pg/pg/v10/orm/tables.go
generated
vendored
Normal file
136
vendor/github.com/go-pg/pg/v10/orm/tables.go
generated
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
var _tables = newTables()
|
||||
|
||||
type tableInProgress struct {
|
||||
table *Table
|
||||
|
||||
init1Once sync.Once
|
||||
init2Once sync.Once
|
||||
}
|
||||
|
||||
func newTableInProgress(table *Table) *tableInProgress {
|
||||
return &tableInProgress{
|
||||
table: table,
|
||||
}
|
||||
}
|
||||
|
||||
func (inp *tableInProgress) init1() bool {
|
||||
var inited bool
|
||||
inp.init1Once.Do(func() {
|
||||
inp.table.init1()
|
||||
inited = true
|
||||
})
|
||||
return inited
|
||||
}
|
||||
|
||||
func (inp *tableInProgress) init2() bool {
|
||||
var inited bool
|
||||
inp.init2Once.Do(func() {
|
||||
inp.table.init2()
|
||||
inited = true
|
||||
})
|
||||
return inited
|
||||
}
|
||||
|
||||
// GetTable returns a Table for a struct type.
|
||||
func GetTable(typ reflect.Type) *Table {
|
||||
return _tables.Get(typ)
|
||||
}
|
||||
|
||||
// RegisterTable registers a struct as SQL table.
|
||||
// It is usually used to register intermediate table
|
||||
// in many to many relationship.
|
||||
func RegisterTable(strct interface{}) {
|
||||
_tables.Register(strct)
|
||||
}
|
||||
|
||||
type tables struct {
|
||||
tables sync.Map
|
||||
|
||||
mu sync.RWMutex
|
||||
inProgress map[reflect.Type]*tableInProgress
|
||||
}
|
||||
|
||||
func newTables() *tables {
|
||||
return &tables{
|
||||
inProgress: make(map[reflect.Type]*tableInProgress),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tables) Register(strct interface{}) {
|
||||
typ := reflect.TypeOf(strct)
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
_ = t.Get(typ)
|
||||
}
|
||||
|
||||
func (t *tables) get(typ reflect.Type, allowInProgress bool) *Table {
|
||||
if typ.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("got %s, wanted %s", typ.Kind(), reflect.Struct))
|
||||
}
|
||||
|
||||
if v, ok := t.tables.Load(typ); ok {
|
||||
return v.(*Table)
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
|
||||
if v, ok := t.tables.Load(typ); ok {
|
||||
t.mu.Unlock()
|
||||
return v.(*Table)
|
||||
}
|
||||
|
||||
var table *Table
|
||||
|
||||
inProgress := t.inProgress[typ]
|
||||
if inProgress == nil {
|
||||
table = newTable(typ)
|
||||
inProgress = newTableInProgress(table)
|
||||
t.inProgress[typ] = inProgress
|
||||
} else {
|
||||
table = inProgress.table
|
||||
}
|
||||
|
||||
t.mu.Unlock()
|
||||
|
||||
inProgress.init1()
|
||||
if allowInProgress {
|
||||
return table
|
||||
}
|
||||
|
||||
if inProgress.init2() {
|
||||
t.mu.Lock()
|
||||
delete(t.inProgress, typ)
|
||||
t.tables.Store(typ, table)
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
func (t *tables) Get(typ reflect.Type) *Table {
|
||||
return t.get(typ, false)
|
||||
}
|
||||
|
||||
func (t *tables) getByName(name types.Safe) *Table {
|
||||
var found *Table
|
||||
t.tables.Range(func(key, value interface{}) bool {
|
||||
t := value.(*Table)
|
||||
if t.SQLName == name {
|
||||
found = t
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return found
|
||||
}
|
||||
48
vendor/github.com/go-pg/pg/v10/orm/types.go
generated
vendored
Normal file
48
vendor/github.com/go-pg/pg/v10/orm/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package orm
|
||||
|
||||
//nolint
|
||||
const (
|
||||
// Date / Time
|
||||
pgTypeTimestamp = "timestamp" // Timestamp without a time zone
|
||||
pgTypeTimestampTz = "timestamptz" // Timestamp with a time zone
|
||||
pgTypeDate = "date" // Date
|
||||
pgTypeTime = "time" // Time without a time zone
|
||||
pgTypeTimeTz = "time with time zone" // Time with a time zone
|
||||
pgTypeInterval = "interval" // Time Interval
|
||||
|
||||
// Network Addresses
|
||||
pgTypeInet = "inet" // IPv4 or IPv6 hosts and networks
|
||||
pgTypeCidr = "cidr" // IPv4 or IPv6 networks
|
||||
pgTypeMacaddr = "macaddr" // MAC addresses
|
||||
|
||||
// Boolean
|
||||
pgTypeBoolean = "boolean"
|
||||
|
||||
// Numeric Types
|
||||
|
||||
// Floating Point Types
|
||||
pgTypeReal = "real" // 4 byte floating point (6 digit precision)
|
||||
pgTypeDoublePrecision = "double precision" // 8 byte floating point (15 digit precision)
|
||||
|
||||
// Integer Types
|
||||
pgTypeSmallint = "smallint" // 2 byte integer
|
||||
pgTypeInteger = "integer" // 4 byte integer
|
||||
pgTypeBigint = "bigint" // 8 byte integer
|
||||
|
||||
// Serial Types
|
||||
pgTypeSmallserial = "smallserial" // 2 byte autoincrementing integer
|
||||
pgTypeSerial = "serial" // 4 byte autoincrementing integer
|
||||
pgTypeBigserial = "bigserial" // 8 byte autoincrementing integer
|
||||
|
||||
// Character Types
|
||||
pgTypeVarchar = "varchar" // variable length string with limit
|
||||
pgTypeChar = "char" // fixed length string (blank padded)
|
||||
pgTypeText = "text" // variable length string without limit
|
||||
|
||||
// JSON Types
|
||||
pgTypeJSON = "json" // text representation of json data
|
||||
pgTypeJSONB = "jsonb" // binary representation of json data
|
||||
|
||||
// Binary Data Types
|
||||
pgTypeBytea = "bytea" // binary string
|
||||
)
|
||||
378
vendor/github.com/go-pg/pg/v10/orm/update.go
generated
vendored
Normal file
378
vendor/github.com/go-pg/pg/v10/orm/update.go
generated
vendored
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type UpdateQuery struct {
|
||||
q *Query
|
||||
omitZero bool
|
||||
placeholder bool
|
||||
}
|
||||
|
||||
var (
|
||||
_ QueryAppender = (*UpdateQuery)(nil)
|
||||
_ QueryCommand = (*UpdateQuery)(nil)
|
||||
)
|
||||
|
||||
func NewUpdateQuery(q *Query, omitZero bool) *UpdateQuery {
|
||||
return &UpdateQuery{
|
||||
q: q,
|
||||
omitZero: omitZero,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) String() string {
|
||||
b, err := q.AppendQuery(defaultFmter, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) Operation() QueryOp {
|
||||
return UpdateOp
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) Clone() QueryCommand {
|
||||
return &UpdateQuery{
|
||||
q: q.q.Clone(),
|
||||
omitZero: q.omitZero,
|
||||
placeholder: q.placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) Query() *Query {
|
||||
return q.q
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) AppendTemplate(b []byte) ([]byte, error) {
|
||||
cp := q.Clone().(*UpdateQuery)
|
||||
cp.placeholder = true
|
||||
return cp.AppendQuery(dummyFormatter{}, b)
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) AppendQuery(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if q.q.stickyErr != nil {
|
||||
return nil, q.q.stickyErr
|
||||
}
|
||||
|
||||
if len(q.q.with) > 0 {
|
||||
b, err = q.q.appendWith(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, "UPDATE "...)
|
||||
|
||||
b, err = q.q.appendFirstTableWithAlias(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = q.mustAppendSet(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isSliceModelWithData := q.q.isSliceModelWithData()
|
||||
if isSliceModelWithData || q.q.hasMultiTables() {
|
||||
b = append(b, " FROM "...)
|
||||
b, err = q.q.appendOtherTables(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isSliceModelWithData {
|
||||
b, err = q.appendSliceModelData(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b, err = q.mustAppendWhere(fmter, b, isSliceModelWithData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(q.q.returning) > 0 {
|
||||
b, err = q.q.appendReturning(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, q.q.stickyErr
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) mustAppendWhere(
|
||||
fmter QueryFormatter, b []byte, isSliceModelWithData bool,
|
||||
) (_ []byte, err error) {
|
||||
b = append(b, " WHERE "...)
|
||||
|
||||
if !isSliceModelWithData {
|
||||
return q.q.mustAppendWhere(fmter, b)
|
||||
}
|
||||
|
||||
if len(q.q.where) > 0 {
|
||||
return q.q.appendWhere(fmter, b)
|
||||
}
|
||||
|
||||
table := q.q.tableModel.Table()
|
||||
err = table.checkPKs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b = appendWhereColumnAndColumn(b, table.Alias, table.PKs)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) mustAppendSet(fmter QueryFormatter, b []byte) (_ []byte, err error) {
|
||||
if len(q.q.set) > 0 {
|
||||
return q.q.appendSet(fmter, b)
|
||||
}
|
||||
|
||||
b = append(b, " SET "...)
|
||||
|
||||
if m, ok := q.q.model.(*mapModel); ok {
|
||||
return q.appendMapSet(b, m.m), nil
|
||||
}
|
||||
|
||||
if !q.q.hasTableModel() {
|
||||
return nil, errModelNil
|
||||
}
|
||||
|
||||
value := q.q.tableModel.Value()
|
||||
if value.Kind() == reflect.Struct {
|
||||
b, err = q.appendSetStruct(fmter, b, value)
|
||||
} else {
|
||||
if value.Len() > 0 {
|
||||
b, err = q.appendSetSlice(b)
|
||||
} else {
|
||||
err = fmt.Errorf("pg: can't bulk-update empty slice %s", value.Type())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendMapSet(b []byte, m map[string]interface{}) []byte {
|
||||
keys := make([]string, 0, len(m))
|
||||
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b = types.AppendIdent(b, k, 1)
|
||||
b = append(b, " = "...)
|
||||
if q.placeholder {
|
||||
b = append(b, '?')
|
||||
} else {
|
||||
b = types.Append(b, m[k], 1)
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendSetStruct(fmter QueryFormatter, b []byte, strct reflect.Value) ([]byte, error) {
|
||||
fields, err := q.q.getFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
fields = q.q.tableModel.Table().DataFields
|
||||
}
|
||||
|
||||
pos := len(b)
|
||||
for _, f := range fields {
|
||||
if q.omitZero && f.NullZero() && f.HasZeroValue(strct) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(b) != pos {
|
||||
b = append(b, ", "...)
|
||||
pos = len(b)
|
||||
}
|
||||
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, " = "...)
|
||||
|
||||
if q.placeholder {
|
||||
b = append(b, '?')
|
||||
continue
|
||||
}
|
||||
|
||||
app, ok := q.q.modelValues[f.SQLName]
|
||||
if ok {
|
||||
b, err = app.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
b = f.AppendValue(b, strct, 1)
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range q.q.extraValues {
|
||||
if i > 0 || len(fields) > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b = append(b, v.column...)
|
||||
b = append(b, " = "...)
|
||||
|
||||
b, err = v.value.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendSetSlice(b []byte) ([]byte, error) {
|
||||
fields, err := q.q.getFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
fields = q.q.tableModel.Table().DataFields
|
||||
}
|
||||
|
||||
var table *Table
|
||||
if q.omitZero {
|
||||
table = q.q.tableModel.Table()
|
||||
}
|
||||
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, " = "...)
|
||||
if q.omitZero && table != nil {
|
||||
b = append(b, "COALESCE("...)
|
||||
}
|
||||
b = append(b, "_data."...)
|
||||
b = append(b, f.Column...)
|
||||
if q.omitZero && table != nil {
|
||||
b = append(b, ", "...)
|
||||
if table.Alias != table.SQLName {
|
||||
b = append(b, table.Alias...)
|
||||
b = append(b, '.')
|
||||
}
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, ")"...)
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendSliceModelData(fmter QueryFormatter, b []byte) ([]byte, error) {
|
||||
columns, err := q.q.getDataFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(columns) > 0 {
|
||||
columns = append(columns, q.q.tableModel.Table().PKs...)
|
||||
} else {
|
||||
columns = q.q.tableModel.Table().Fields
|
||||
}
|
||||
|
||||
return q.appendSliceValues(fmter, b, columns, q.q.tableModel.Value())
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendSliceValues(
|
||||
fmter QueryFormatter, b []byte, fields []*Field, slice reflect.Value,
|
||||
) (_ []byte, err error) {
|
||||
b = append(b, "(VALUES ("...)
|
||||
|
||||
if q.placeholder {
|
||||
b, err = q.appendValues(fmter, b, fields, reflect.Value{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
sliceLen := slice.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
if i > 0 {
|
||||
b = append(b, "), ("...)
|
||||
}
|
||||
b, err = q.appendValues(fmter, b, fields, slice.Index(i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b = append(b, ")) AS _data("...)
|
||||
b = appendColumns(b, "", fields)
|
||||
b = append(b, ")"...)
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (q *UpdateQuery) appendValues(
|
||||
fmter QueryFormatter, b []byte, fields []*Field, strct reflect.Value,
|
||||
) (_ []byte, err error) {
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
app, ok := q.q.modelValues[f.SQLName]
|
||||
if ok {
|
||||
b, err = app.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if q.placeholder {
|
||||
b = append(b, '?')
|
||||
} else {
|
||||
b = f.AppendValue(b, indirect(strct), 1)
|
||||
}
|
||||
|
||||
b = append(b, "::"...)
|
||||
b = append(b, f.SQLType...)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func appendWhereColumnAndColumn(b []byte, alias types.Safe, fields []*Field) []byte {
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, " AND "...)
|
||||
}
|
||||
b = append(b, alias...)
|
||||
b = append(b, '.')
|
||||
b = append(b, f.Column...)
|
||||
b = append(b, " = _data."...)
|
||||
b = append(b, f.Column...)
|
||||
}
|
||||
return b
|
||||
}
|
||||
151
vendor/github.com/go-pg/pg/v10/orm/util.go
generated
vendored
Normal file
151
vendor/github.com/go-pg/pg/v10/orm/util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
func indirect(v reflect.Value) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Interface:
|
||||
return indirect(v.Elem())
|
||||
case reflect.Ptr:
|
||||
return v.Elem()
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func indirectType(t reflect.Type) reflect.Type {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func sliceElemType(v reflect.Value) reflect.Type {
|
||||
elemType := v.Type().Elem()
|
||||
if elemType.Kind() == reflect.Interface && v.Len() > 0 {
|
||||
return indirect(v.Index(0).Elem()).Type()
|
||||
}
|
||||
return indirectType(elemType)
|
||||
}
|
||||
|
||||
func typeByIndex(t reflect.Type, index []int) reflect.Type {
|
||||
for _, x := range index {
|
||||
switch t.Kind() {
|
||||
case reflect.Ptr:
|
||||
t = t.Elem()
|
||||
case reflect.Slice:
|
||||
t = indirectType(t.Elem())
|
||||
}
|
||||
t = t.Field(x).Type
|
||||
}
|
||||
return indirectType(t)
|
||||
}
|
||||
|
||||
func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, ok bool) {
|
||||
if len(index) == 1 {
|
||||
return v.Field(index[0]), true
|
||||
}
|
||||
|
||||
for i, idx := range index {
|
||||
if i > 0 {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return v, false
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
v = v.Field(idx)
|
||||
}
|
||||
return v, true
|
||||
}
|
||||
|
||||
func fieldByIndexAlloc(v reflect.Value, index []int) reflect.Value {
|
||||
if len(index) == 1 {
|
||||
return v.Field(index[0])
|
||||
}
|
||||
|
||||
for i, idx := range index {
|
||||
if i > 0 {
|
||||
v = indirectNil(v)
|
||||
}
|
||||
v = v.Field(idx)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func indirectNil(v reflect.Value) reflect.Value {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func walk(v reflect.Value, index []int, fn func(reflect.Value)) {
|
||||
v = reflect.Indirect(v)
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
sliceLen := v.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
visitField(v.Index(i), index, fn)
|
||||
}
|
||||
default:
|
||||
visitField(v, index, fn)
|
||||
}
|
||||
}
|
||||
|
||||
func visitField(v reflect.Value, index []int, fn func(reflect.Value)) {
|
||||
v = reflect.Indirect(v)
|
||||
if len(index) > 0 {
|
||||
v = v.Field(index[0])
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return
|
||||
}
|
||||
walk(v, index[1:], fn)
|
||||
} else {
|
||||
fn(v)
|
||||
}
|
||||
}
|
||||
|
||||
func dstValues(model TableModel, fields []*Field) map[string][]reflect.Value {
|
||||
fieldIndex := model.Relation().Field.Index
|
||||
m := make(map[string][]reflect.Value)
|
||||
var id []byte
|
||||
walk(model.Root(), model.ParentIndex(), func(v reflect.Value) {
|
||||
id = modelID(id[:0], v, fields)
|
||||
m[string(id)] = append(m[string(id)], v.FieldByIndex(fieldIndex))
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
func modelID(b []byte, v reflect.Value, fields []*Field) []byte {
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ',')
|
||||
}
|
||||
b = f.AppendValue(b, v, 0)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func appendColumns(b []byte, table types.Safe, fields []*Field) []byte {
|
||||
for i, f := range fields {
|
||||
if i > 0 {
|
||||
b = append(b, ", "...)
|
||||
}
|
||||
|
||||
if len(table) > 0 {
|
||||
b = append(b, table...)
|
||||
b = append(b, '.')
|
||||
}
|
||||
b = append(b, f.Column...)
|
||||
}
|
||||
return b
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue