diff options
Diffstat (limited to 'vendor/xorm.io/builder')
30 files changed, 2939 insertions, 0 deletions
diff --git a/vendor/xorm.io/builder/.drone.yml b/vendor/xorm.io/builder/.drone.yml new file mode 100644 index 0000000000..ca40377721 --- /dev/null +++ b/vendor/xorm.io/builder/.drone.yml @@ -0,0 +1,37 @@ +workspace: + base: /go + path: src/github.com/go-xorm/builder + +clone: + git: + image: plugins/git:next + depth: 50 + tags: true + +matrix: + GO_VERSION: + - 1.8 + - 1.9 + - 1.10 + - 1.11 + +pipeline: + test: + image: golang:${GO_VERSION} + commands: + - go get -u github.com/golang/lint/golint + - go get -u github.com/stretchr/testify/assert + - go get -u github.com/go-xorm/sqlfiddle + - golint ./... + - go test -v -race -coverprofile=coverage.txt -covermode=atomic + when: + event: [ push, tag, pull_request ] + +codecov: + image: robertstettner/drone-codecov + group: build + secrets: [ codecov_token ] + files: + - coverage.txt + when: + event: [ push, pull_request ]
\ No newline at end of file diff --git a/vendor/xorm.io/builder/LICENSE b/vendor/xorm.io/builder/LICENSE new file mode 100644 index 0000000000..614d5e2829 --- /dev/null +++ b/vendor/xorm.io/builder/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016 The Xorm Authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the {organization} nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/xorm.io/builder/README.md b/vendor/xorm.io/builder/README.md new file mode 100644 index 0000000000..cf516d1fd5 --- /dev/null +++ b/vendor/xorm.io/builder/README.md @@ -0,0 +1,206 @@ +# SQL builder + +[![GitCI.cn](https://gitci.cn/api/badges/go-xorm/builder/status.svg)](https://gitci.cn/go-xorm/builder) [![codecov](https://codecov.io/gh/go-xorm/builder/branch/master/graph/badge.svg)](https://codecov.io/gh/go-xorm/builder) +[![](https://goreportcard.com/badge/github.com/go-xorm/builder)](https://goreportcard.com/report/github.com/go-xorm/builder) + +Package builder is a lightweight and fast SQL builder for Go and XORM. + +Make sure you have installed Go 1.8+ and then: + + go get github.com/go-xorm/builder + +# Insert + +```Go +sql, args, err := builder.Insert(Eq{"c": 1, "d": 2}).Into("table1").ToSQL() + +// INSERT INTO table1 SELECT * FROM table2 +sql, err := builder.Insert().Into("table1").Select().From("table2").ToBoundSQL() + +// INSERT INTO table1 (a, b) SELECT b, c FROM table2 +sql, err = builder.Insert("a, b").Into("table1").Select("b, c").From("table2").ToBoundSQL() +``` + +# Select + +```Go +// Simple Query +sql, args, err := Select("c, d").From("table1").Where(Eq{"a": 1}).ToSQL() +// With join +sql, args, err = Select("c, d").From("table1").LeftJoin("table2", Eq{"table1.id": 1}.And(Lt{"table2.id": 3})). + RightJoin("table3", "table2.id = table3.tid").Where(Eq{"a": 1}).ToSQL() +// From sub query +sql, args, err := Select("sub.id").From(Select("c").From("table1").Where(Eq{"a": 1}), "sub").Where(Eq{"b": 1}).ToSQL() +// From union query +sql, args, err = Select("sub.id").From( + Select("id").From("table1").Where(Eq{"a": 1}).Union("all", Select("id").From("table1").Where(Eq{"a": 2})),"sub"). + Where(Eq{"b": 1}).ToSQL() +// With order by +sql, args, err = Select("a", "b", "c").From("table1").Where(Eq{"f1": "v1", "f2": "v2"}). + OrderBy("a ASC").ToSQL() +// With limit. +// Be careful! You should set up specific dialect for builder before performing a query with LIMIT +sql, args, err = Dialect(MYSQL).Select("a", "b", "c").From("table1").OrderBy("a ASC"). + Limit(5, 10).ToSQL() +``` + +# Update + +```Go +sql, args, err := Update(Eq{"a": 2}).From("table1").Where(Eq{"a": 1}).ToSQL() +``` + +# Delete + +```Go +sql, args, err := Delete(Eq{"a": 1}).From("table1").ToSQL() +``` + +# Union + +```Go +sql, args, err := Select("*").From("a").Where(Eq{"status": "1"}). + Union("all", Select("*").From("a").Where(Eq{"status": "2"})). + Union("distinct", Select("*").From("a").Where(Eq{"status": "3"})). + Union("", Select("*").From("a").Where(Eq{"status": "4"})). + ToSQL() +``` + +# Conditions + +* `Eq` is a redefine of a map, you can give one or more conditions to `Eq` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Eq{"a":1}) +// a=? [1] +sql, args, _ := ToSQL(Eq{"b":"c"}.And(Eq{"c": 0})) +// b=? AND c=? ["c", 0] +sql, args, _ := ToSQL(Eq{"b":"c", "c":0}) +// b=? AND c=? ["c", 0] +sql, args, _ := ToSQL(Eq{"b":"c"}.Or(Eq{"b":"d"})) +// b=? OR b=? ["c", "d"] +sql, args, _ := ToSQL(Eq{"b": []string{"c", "d"}}) +// b IN (?,?) ["c", "d"] +sql, args, _ := ToSQL(Eq{"b": 1, "c":[]int{2, 3}}) +// b=? AND c IN (?,?) [1, 2, 3] +``` + +* `Neq` is the same to `Eq` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Neq{"a":1}) +// a<>? [1] +sql, args, _ := ToSQL(Neq{"b":"c"}.And(Neq{"c": 0})) +// b<>? AND c<>? ["c", 0] +sql, args, _ := ToSQL(Neq{"b":"c", "c":0}) +// b<>? AND c<>? ["c", 0] +sql, args, _ := ToSQL(Neq{"b":"c"}.Or(Neq{"b":"d"})) +// b<>? OR b<>? ["c", "d"] +sql, args, _ := ToSQL(Neq{"b": []string{"c", "d"}}) +// b NOT IN (?,?) ["c", "d"] +sql, args, _ := ToSQL(Neq{"b": 1, "c":[]int{2, 3}}) +// b<>? AND c NOT IN (?,?) [1, 2, 3] +``` + +* `Gt`, `Gte`, `Lt`, `Lte` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Gt{"a", 1}.And(Gte{"b", 2})) +// a>? AND b>=? [1, 2] +sql, args, _ := ToSQL(Lt{"a", 1}.Or(Lte{"b", 2})) +// a<? OR b<=? [1, 2] +``` + +* `Like` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Like{"a", "c"}) +// a LIKE ? [%c%] +``` + +* `Expr` you can customerize your sql with `Expr` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Expr("a = ? ", 1)) +// a = ? [1] +sql, args, _ := ToSQL(Eq{"a": Expr("select id from table where c = ?", 1)}) +// a=(select id from table where c = ?) [1] +``` + +* `In` and `NotIn` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(In("a", 1, 2, 3)) +// a IN (?,?,?) [1,2,3] +sql, args, _ := ToSQL(In("a", []int{1, 2, 3})) +// a IN (?,?,?) [1,2,3] +sql, args, _ := ToSQL(In("a", Expr("select id from b where c = ?", 1)))) +// a IN (select id from b where c = ?) [1] +``` + +* `IsNull` and `NotNull` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(IsNull{"a"}) +// a IS NULL [] +sql, args, _ := ToSQL(NotNull{"b"}) + // b IS NOT NULL [] +``` + +* `And(conds ...Cond)`, And can connect one or more condtions via And + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(And(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2})) +// a=? AND b LIKE ? AND d<>? [1, %c%, 2] +``` + +* `Or(conds ...Cond)`, Or can connect one or more conditions via Or + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Or(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2})) +// a=? OR b LIKE ? OR d<>? [1, %c%, 2] +sql, args, _ := ToSQL(Or(Eq{"a":1}, And(Like{"b", "c"}, Neq{"d", 2}))) +// a=? OR (b LIKE ? AND d<>?) [1, %c%, 2] +``` + +* `Between` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Between{"a", 1, 2}) +// a BETWEEN 1 AND 2 +``` + +* Define yourself conditions + +Since `Cond` is an interface. + +```Go +type Cond interface { + WriteTo(Writer) error + And(...Cond) Cond + Or(...Cond) Cond + IsValid() bool +} +``` + +You can define yourself conditions and compose with other `Cond`.
\ No newline at end of file diff --git a/vendor/xorm.io/builder/builder.go b/vendor/xorm.io/builder/builder.go new file mode 100644 index 0000000000..ffe86d4dcb --- /dev/null +++ b/vendor/xorm.io/builder/builder.go @@ -0,0 +1,394 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + sql2 "database/sql" + "fmt" + "sort" +) + +type optype byte + +const ( + condType optype = iota // only conditions + selectType // select + insertType // insert + updateType // update + deleteType // delete + unionType // union +) + +const ( + POSTGRES = "postgres" + SQLITE = "sqlite3" + MYSQL = "mysql" + MSSQL = "mssql" + ORACLE = "oracle" +) + +type join struct { + joinType string + joinTable string + joinCond Cond +} + +type union struct { + unionType string + builder *Builder +} + +type limit struct { + limitN int + offset int +} + +// Builder describes a SQL statement +type Builder struct { + optype + dialect string + isNested bool + into string + from string + subQuery *Builder + cond Cond + selects []string + joins []join + unions []union + limitation *limit + insertCols []string + insertVals []interface{} + updates []Eq + orderBy string + groupBy string + having string +} + +// Dialect sets the db dialect of Builder. +func Dialect(dialect string) *Builder { + builder := &Builder{cond: NewCond(), dialect: dialect} + return builder +} + +// MySQL is shortcut of Dialect(MySQL) +func MySQL() *Builder { + return Dialect(MYSQL) +} + +// MsSQL is shortcut of Dialect(MsSQL) +func MsSQL() *Builder { + return Dialect(MSSQL) +} + +// Oracle is shortcut of Dialect(Oracle) +func Oracle() *Builder { + return Dialect(ORACLE) +} + +// Postgres is shortcut of Dialect(Postgres) +func Postgres() *Builder { + return Dialect(POSTGRES) +} + +// SQLite is shortcut of Dialect(SQLITE) +func SQLite() *Builder { + return Dialect(SQLITE) +} + +// Where sets where SQL +func (b *Builder) Where(cond Cond) *Builder { + if b.cond.IsValid() { + b.cond = b.cond.And(cond) + } else { + b.cond = cond + } + return b +} + +// From sets from subject(can be a table name in string or a builder pointer) and its alias +func (b *Builder) From(subject interface{}, alias ...string) *Builder { + switch subject.(type) { + case *Builder: + b.subQuery = subject.(*Builder) + + if len(alias) > 0 { + b.from = alias[0] + } else { + b.isNested = true + } + case string: + b.from = subject.(string) + + if len(alias) > 0 { + b.from = b.from + " " + alias[0] + } + } + + return b +} + +// TableName returns the table name +func (b *Builder) TableName() string { + if b.optype == insertType { + return b.into + } + return b.from +} + +// Into sets insert table name +func (b *Builder) Into(tableName string) *Builder { + b.into = tableName + return b +} + +// Join sets join table and conditions +func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder { + switch joinCond.(type) { + case Cond: + b.joins = append(b.joins, join{joinType, joinTable, joinCond.(Cond)}) + case string: + b.joins = append(b.joins, join{joinType, joinTable, Expr(joinCond.(string))}) + } + + return b +} + +// Union sets union conditions +func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder { + var builder *Builder + if b.optype != unionType { + builder = &Builder{cond: NewCond()} + builder.optype = unionType + builder.dialect = b.dialect + builder.selects = b.selects + + currentUnions := b.unions + // erase sub unions (actually append to new Builder.unions) + b.unions = nil + + for e := range currentUnions { + currentUnions[e].builder.dialect = b.dialect + } + + builder.unions = append(append(builder.unions, union{"", b}), currentUnions...) + } else { + builder = b + } + + if unionCond != nil { + if unionCond.dialect == "" && builder.dialect != "" { + unionCond.dialect = builder.dialect + } + + builder.unions = append(builder.unions, union{unionTp, unionCond}) + } + + return builder +} + +// Limit sets limitN condition +func (b *Builder) Limit(limitN int, offset ...int) *Builder { + b.limitation = &limit{limitN: limitN} + + if len(offset) > 0 { + b.limitation.offset = offset[0] + } + + return b +} + +// InnerJoin sets inner join +func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder { + return b.Join("INNER", joinTable, joinCond) +} + +// LeftJoin sets left join SQL +func (b *Builder) LeftJoin(joinTable string, joinCond interface{}) *Builder { + return b.Join("LEFT", joinTable, joinCond) +} + +// RightJoin sets right join SQL +func (b *Builder) RightJoin(joinTable string, joinCond interface{}) *Builder { + return b.Join("RIGHT", joinTable, joinCond) +} + +// CrossJoin sets cross join SQL +func (b *Builder) CrossJoin(joinTable string, joinCond interface{}) *Builder { + return b.Join("CROSS", joinTable, joinCond) +} + +// FullJoin sets full join SQL +func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder { + return b.Join("FULL", joinTable, joinCond) +} + +// Select sets select SQL +func (b *Builder) Select(cols ...string) *Builder { + b.selects = cols + if b.optype == condType { + b.optype = selectType + } + return b +} + +// And sets AND condition +func (b *Builder) And(cond Cond) *Builder { + b.cond = And(b.cond, cond) + return b +} + +// Or sets OR condition +func (b *Builder) Or(cond Cond) *Builder { + b.cond = Or(b.cond, cond) + return b +} + +type insertColsSorter struct { + cols []string + vals []interface{} +} + +func (s insertColsSorter) Len() int { + return len(s.cols) +} +func (s insertColsSorter) Swap(i, j int) { + s.cols[i], s.cols[j] = s.cols[j], s.cols[i] + s.vals[i], s.vals[j] = s.vals[j], s.vals[i] +} + +func (s insertColsSorter) Less(i, j int) bool { + return s.cols[i] < s.cols[j] +} + +// Insert sets insert SQL +func (b *Builder) Insert(eq ...interface{}) *Builder { + if len(eq) > 0 { + var paramType = -1 + for _, e := range eq { + switch t := e.(type) { + case Eq: + if paramType == -1 { + paramType = 0 + } + if paramType != 0 { + break + } + for k, v := range t { + b.insertCols = append(b.insertCols, k) + b.insertVals = append(b.insertVals, v) + } + case string: + if paramType == -1 { + paramType = 1 + } + if paramType != 1 { + break + } + b.insertCols = append(b.insertCols, t) + } + } + } + + if len(b.insertCols) == len(b.insertVals) { + sort.Sort(insertColsSorter{ + cols: b.insertCols, + vals: b.insertVals, + }) + } + b.optype = insertType + return b +} + +// Update sets update SQL +func (b *Builder) Update(updates ...Eq) *Builder { + b.updates = make([]Eq, 0, len(updates)) + for _, update := range updates { + if update.IsValid() { + b.updates = append(b.updates, update) + } + } + b.optype = updateType + return b +} + +// Delete sets delete SQL +func (b *Builder) Delete(conds ...Cond) *Builder { + b.cond = b.cond.And(conds...) + b.optype = deleteType + return b +} + +// WriteTo implements Writer interface +func (b *Builder) WriteTo(w Writer) error { + switch b.optype { + /*case condType: + return b.cond.WriteTo(w)*/ + case selectType: + return b.selectWriteTo(w) + case insertType: + return b.insertWriteTo(w) + case updateType: + return b.updateWriteTo(w) + case deleteType: + return b.deleteWriteTo(w) + case unionType: + return b.unionWriteTo(w) + } + + return ErrNotSupportType +} + +// ToSQL convert a builder to SQL and args +func (b *Builder) ToSQL() (string, []interface{}, error) { + w := NewWriter() + if err := b.WriteTo(w); err != nil { + return "", nil, err + } + + // in case of sql.NamedArg in args + for e := range w.args { + if namedArg, ok := w.args[e].(sql2.NamedArg); ok { + w.args[e] = namedArg.Value + } + } + + var sql = w.writer.String() + var err error + + switch b.dialect { + case ORACLE, MSSQL: + // This is for compatibility with different sql drivers + for e := range w.args { + w.args[e] = sql2.Named(fmt.Sprintf("p%d", e+1), w.args[e]) + } + + var prefix string + if b.dialect == ORACLE { + prefix = ":p" + } else { + prefix = "@p" + } + + if sql, err = ConvertPlaceholder(sql, prefix); err != nil { + return "", nil, err + } + case POSTGRES: + if sql, err = ConvertPlaceholder(sql, "$"); err != nil { + return "", nil, err + } + } + + return sql, w.args, nil +} + +// ToBoundSQL +func (b *Builder) ToBoundSQL() (string, error) { + w := NewWriter() + if err := b.WriteTo(w); err != nil { + return "", err + } + + return ConvertToBoundSQL(w.writer.String(), w.args) +} diff --git a/vendor/xorm.io/builder/builder_delete.go b/vendor/xorm.io/builder/builder_delete.go new file mode 100644 index 0000000000..317cc3ff9e --- /dev/null +++ b/vendor/xorm.io/builder/builder_delete.go @@ -0,0 +1,27 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" +) + +// Delete creates a delete Builder +func Delete(conds ...Cond) *Builder { + builder := &Builder{cond: NewCond()} + return builder.Delete(conds...) +} + +func (b *Builder) deleteWriteTo(w Writer) error { + if len(b.from) <= 0 { + return ErrNoTableName + } + + if _, err := fmt.Fprintf(w, "DELETE FROM %s WHERE ", b.from); err != nil { + return err + } + + return b.cond.WriteTo(w) +} diff --git a/vendor/xorm.io/builder/builder_insert.go b/vendor/xorm.io/builder/builder_insert.go new file mode 100644 index 0000000000..202cad51d8 --- /dev/null +++ b/vendor/xorm.io/builder/builder_insert.go @@ -0,0 +1,89 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "bytes" + "fmt" +) + +// Insert creates an insert Builder +func Insert(eq ...interface{}) *Builder { + builder := &Builder{cond: NewCond()} + return builder.Insert(eq...) +} + +func (b *Builder) insertSelectWriteTo(w Writer) error { + if _, err := fmt.Fprintf(w, "INSERT INTO %s ", b.into); err != nil { + return err + } + + if len(b.insertCols) > 0 { + fmt.Fprintf(w, "(") + for _, col := range b.insertCols { + fmt.Fprintf(w, col) + } + fmt.Fprintf(w, ") ") + } + + return b.selectWriteTo(w) +} + +func (b *Builder) insertWriteTo(w Writer) error { + if len(b.into) <= 0 { + return ErrNoTableName + } + if len(b.insertCols) <= 0 && b.from == "" { + return ErrNoColumnToInsert + } + + if b.into != "" && b.from != "" { + return b.insertSelectWriteTo(w) + } + + if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.into); err != nil { + return err + } + + var args = make([]interface{}, 0) + var bs []byte + var valBuffer = bytes.NewBuffer(bs) + + for i, col := range b.insertCols { + value := b.insertVals[i] + fmt.Fprint(w, col) + if e, ok := value.(expr); ok { + fmt.Fprintf(valBuffer, "(%s)", e.sql) + args = append(args, e.args...) + } else { + fmt.Fprint(valBuffer, "?") + args = append(args, value) + } + + if i != len(b.insertCols)-1 { + if _, err := fmt.Fprint(w, ","); err != nil { + return err + } + if _, err := fmt.Fprint(valBuffer, ","); err != nil { + return err + } + } + } + + if _, err := fmt.Fprint(w, ") Values ("); err != nil { + return err + } + + if _, err := w.Write(valBuffer.Bytes()); err != nil { + return err + } + if _, err := fmt.Fprint(w, ")"); err != nil { + return err + } + + w.Append(args...) + + return nil +} diff --git a/vendor/xorm.io/builder/builder_limit.go b/vendor/xorm.io/builder/builder_limit.go new file mode 100644 index 0000000000..82435dacbd --- /dev/null +++ b/vendor/xorm.io/builder/builder_limit.go @@ -0,0 +1,100 @@ +// Copyright 2018 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "strings" +) + +func (b *Builder) limitWriteTo(w Writer) error { + if strings.TrimSpace(b.dialect) == "" { + return ErrDialectNotSetUp + } + + if b.limitation != nil { + limit := b.limitation + if limit.offset < 0 || limit.limitN <= 0 { + return ErrInvalidLimitation + } + // erase limit condition + b.limitation = nil + ow := w.(*BytesWriter) + + switch strings.ToLower(strings.TrimSpace(b.dialect)) { + case ORACLE: + if len(b.selects) == 0 { + b.selects = append(b.selects, "*") + } + + var final *Builder + selects := b.selects + b.selects = append(selects, "ROWNUM RN") + + var wb *Builder + if b.optype == unionType { + wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN"). + From(b, "at") + } else { + wb = b + } + + if limit.offset == 0 { + final = Dialect(b.dialect).Select(selects...).From(wb, "at"). + Where(Lte{"at.RN": limit.limitN}) + } else { + sub := Dialect(b.dialect).Select("*"). + From(b, "at").Where(Lte{"at.RN": limit.offset + limit.limitN}) + + final = Dialect(b.dialect).Select(selects...).From(sub, "att"). + Where(Gt{"att.RN": limit.offset}) + } + + return final.WriteTo(ow) + case SQLITE, MYSQL, POSTGRES: + // if type UNION, we need to write previous content back to current writer + if b.optype == unionType { + if err := b.WriteTo(ow); err != nil { + return err + } + } + + if limit.offset == 0 { + fmt.Fprint(ow, " LIMIT ", limit.limitN) + } else { + fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset) + } + case MSSQL: + if len(b.selects) == 0 { + b.selects = append(b.selects, "*") + } + + var final *Builder + selects := b.selects + b.selects = append(append([]string{fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset, b.selects[0])}, + b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN") + + var wb *Builder + if b.optype == unionType { + wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN"). + From(b, "at") + } else { + wb = b + } + + if limit.offset == 0 { + final = Dialect(b.dialect).Select(selects...).From(wb, "at") + } else { + final = Dialect(b.dialect).Select(selects...).From(wb, "at").Where(Gt{"at.RN": limit.offset}) + } + + return final.WriteTo(ow) + default: + return ErrNotSupportType + } + } + + return nil +} diff --git a/vendor/xorm.io/builder/builder_select.go b/vendor/xorm.io/builder/builder_select.go new file mode 100644 index 0000000000..c33b38698b --- /dev/null +++ b/vendor/xorm.io/builder/builder_select.go @@ -0,0 +1,145 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" +) + +// Select creates a select Builder +func Select(cols ...string) *Builder { + builder := &Builder{cond: NewCond()} + return builder.Select(cols...) +} + +func (b *Builder) selectWriteTo(w Writer) error { + if len(b.from) <= 0 && !b.isNested { + return ErrNoTableName + } + + // perform limit before writing to writer when b.dialect between ORACLE and MSSQL + // this avoid a duplicate writing problem in simple limit query + if b.limitation != nil && (b.dialect == ORACLE || b.dialect == MSSQL) { + return b.limitWriteTo(w) + } + + if _, err := fmt.Fprint(w, "SELECT "); err != nil { + return err + } + if len(b.selects) > 0 { + for i, s := range b.selects { + if _, err := fmt.Fprint(w, s); err != nil { + return err + } + if i != len(b.selects)-1 { + if _, err := fmt.Fprint(w, ","); err != nil { + return err + } + } + } + } else { + if _, err := fmt.Fprint(w, "*"); err != nil { + return err + } + } + + if b.subQuery == nil { + if _, err := fmt.Fprint(w, " FROM ", b.from); err != nil { + return err + } + } else { + if b.cond.IsValid() && len(b.from) <= 0 { + return ErrUnnamedDerivedTable + } + if b.subQuery.dialect != "" && b.dialect != b.subQuery.dialect { + return ErrInconsistentDialect + } + + // dialect of sub-query will inherit from the main one (if not set up) + if b.dialect != "" && b.subQuery.dialect == "" { + b.subQuery.dialect = b.dialect + } + + switch b.subQuery.optype { + case selectType, unionType: + fmt.Fprint(w, " FROM (") + if err := b.subQuery.WriteTo(w); err != nil { + return err + } + + if len(b.from) == 0 { + fmt.Fprintf(w, ")") + } else { + fmt.Fprintf(w, ") %v", b.from) + } + default: + return ErrUnexpectedSubQuery + } + } + + for _, v := range b.joins { + if _, err := fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable); err != nil { + return err + } + + if err := v.joinCond.WriteTo(w); err != nil { + return err + } + } + + if b.cond.IsValid() { + if _, err := fmt.Fprint(w, " WHERE "); err != nil { + return err + } + + if err := b.cond.WriteTo(w); err != nil { + return err + } + } + + if len(b.groupBy) > 0 { + if _, err := fmt.Fprint(w, " GROUP BY ", b.groupBy); err != nil { + return err + } + } + + if len(b.having) > 0 { + if _, err := fmt.Fprint(w, " HAVING ", b.having); err != nil { + return err + } + } + + if len(b.orderBy) > 0 { + if _, err := fmt.Fprint(w, " ORDER BY ", b.orderBy); err != nil { + return err + } + } + + if b.limitation != nil { + if err := b.limitWriteTo(w); err != nil { + return err + } + } + + return nil +} + +// OrderBy orderBy SQL +func (b *Builder) OrderBy(orderBy string) *Builder { + b.orderBy = orderBy + return b +} + +// GroupBy groupby SQL +func (b *Builder) GroupBy(groupby string) *Builder { + b.groupBy = groupby + return b +} + +// Having having SQL +func (b *Builder) Having(having string) *Builder { + b.having = having + return b +} diff --git a/vendor/xorm.io/builder/builder_union.go b/vendor/xorm.io/builder/builder_union.go new file mode 100644 index 0000000000..4ba9216178 --- /dev/null +++ b/vendor/xorm.io/builder/builder_union.go @@ -0,0 +1,47 @@ +// Copyright 2018 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "strings" +) + +func (b *Builder) unionWriteTo(w Writer) error { + if b.limitation != nil || b.cond.IsValid() || + b.orderBy != "" || b.having != "" || b.groupBy != "" { + return ErrNotUnexpectedUnionConditions + } + + for idx, u := range b.unions { + current := u.builder + if current.optype != selectType { + return ErrUnsupportedUnionMembers + } + + if len(b.unions) == 1 { + if err := current.selectWriteTo(w); err != nil { + return err + } + } else { + if b.dialect != "" && b.dialect != current.dialect { + return ErrInconsistentDialect + } + + if idx != 0 { + fmt.Fprint(w, fmt.Sprintf(" UNION %v ", strings.ToUpper(u.unionType))) + } + fmt.Fprint(w, "(") + + if err := current.selectWriteTo(w); err != nil { + return err + } + + fmt.Fprint(w, ")") + } + } + + return nil +} diff --git a/vendor/xorm.io/builder/builder_update.go b/vendor/xorm.io/builder/builder_update.go new file mode 100644 index 0000000000..37b4551526 --- /dev/null +++ b/vendor/xorm.io/builder/builder_update.go @@ -0,0 +1,46 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" +) + +// Update creates an update Builder +func Update(updates ...Eq) *Builder { + builder := &Builder{cond: NewCond()} + return builder.Update(updates...) +} + +func (b *Builder) updateWriteTo(w Writer) error { + if len(b.from) <= 0 { + return ErrNoTableName + } + if len(b.updates) <= 0 { + return ErrNoColumnToUpdate + } + + if _, err := fmt.Fprintf(w, "UPDATE %s SET ", b.from); err != nil { + return err + } + + for i, s := range b.updates { + if err := s.opWriteTo(",", w); err != nil { + return err + } + + if i != len(b.updates)-1 { + if _, err := fmt.Fprint(w, ","); err != nil { + return err + } + } + } + + if _, err := fmt.Fprint(w, " WHERE "); err != nil { + return err + } + + return b.cond.WriteTo(w) +} diff --git a/vendor/xorm.io/builder/cond.go b/vendor/xorm.io/builder/cond.go new file mode 100644 index 0000000000..e44173bbd5 --- /dev/null +++ b/vendor/xorm.io/builder/cond.go @@ -0,0 +1,74 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "io" +) + +// Writer defines the interface +type Writer interface { + io.Writer + Append(...interface{}) +} + +var _ Writer = NewWriter() + +// BytesWriter implments Writer and save SQL in bytes.Buffer +type BytesWriter struct { + writer *StringBuilder + args []interface{} +} + +// NewWriter creates a new string writer +func NewWriter() *BytesWriter { + w := &BytesWriter{ + writer: &StringBuilder{}, + } + return w +} + +// Write writes data to Writer +func (s *BytesWriter) Write(buf []byte) (int, error) { + return s.writer.Write(buf) +} + +// Append appends args to Writer +func (s *BytesWriter) Append(args ...interface{}) { + s.args = append(s.args, args...) +} + +// Cond defines an interface +type Cond interface { + WriteTo(Writer) error + And(...Cond) Cond + Or(...Cond) Cond + IsValid() bool +} + +type condEmpty struct{} + +var _ Cond = condEmpty{} + +// NewCond creates an empty condition +func NewCond() Cond { + return condEmpty{} +} + +func (condEmpty) WriteTo(w Writer) error { + return nil +} + +func (condEmpty) And(conds ...Cond) Cond { + return And(conds...) +} + +func (condEmpty) Or(conds ...Cond) Cond { + return Or(conds...) +} + +func (condEmpty) IsValid() bool { + return false +} diff --git a/vendor/xorm.io/builder/cond_and.go b/vendor/xorm.io/builder/cond_and.go new file mode 100644 index 0000000000..e30bd186cd --- /dev/null +++ b/vendor/xorm.io/builder/cond_and.go @@ -0,0 +1,61 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +type condAnd []Cond + +var _ Cond = condAnd{} + +// And generates AND conditions +func And(conds ...Cond) Cond { + var result = make(condAnd, 0, len(conds)) + for _, cond := range conds { + if cond == nil || !cond.IsValid() { + continue + } + result = append(result, cond) + } + return result +} + +func (and condAnd) WriteTo(w Writer) error { + for i, cond := range and { + _, isOr := cond.(condOr) + _, isExpr := cond.(expr) + wrap := isOr || isExpr + if wrap { + fmt.Fprint(w, "(") + } + + err := cond.WriteTo(w) + if err != nil { + return err + } + + if wrap { + fmt.Fprint(w, ")") + } + + if i != len(and)-1 { + fmt.Fprint(w, " AND ") + } + } + + return nil +} + +func (and condAnd) And(conds ...Cond) Cond { + return And(and, And(conds...)) +} + +func (and condAnd) Or(conds ...Cond) Cond { + return Or(and, Or(conds...)) +} + +func (and condAnd) IsValid() bool { + return len(and) > 0 +} diff --git a/vendor/xorm.io/builder/cond_between.go b/vendor/xorm.io/builder/cond_between.go new file mode 100644 index 0000000000..10e0b83152 --- /dev/null +++ b/vendor/xorm.io/builder/cond_between.go @@ -0,0 +1,65 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +// Between implmentes between condition +type Between struct { + Col string + LessVal interface{} + MoreVal interface{} +} + +var _ Cond = Between{} + +// WriteTo write data to Writer +func (between Between) WriteTo(w Writer) error { + if _, err := fmt.Fprintf(w, "%s BETWEEN ", between.Col); err != nil { + return err + } + if lv, ok := between.LessVal.(expr); ok { + if err := lv.WriteTo(w); err != nil { + return err + } + } else { + if _, err := fmt.Fprint(w, "?"); err != nil { + return err + } + w.Append(between.LessVal) + } + + if _, err := fmt.Fprint(w, " AND "); err != nil { + return err + } + + if mv, ok := between.MoreVal.(expr); ok { + if err := mv.WriteTo(w); err != nil { + return err + } + } else { + if _, err := fmt.Fprint(w, "?"); err != nil { + return err + } + w.Append(between.MoreVal) + } + + return nil +} + +// And implments And with other conditions +func (between Between) And(conds ...Cond) Cond { + return And(between, And(conds...)) +} + +// Or implments Or with other conditions +func (between Between) Or(conds ...Cond) Cond { + return Or(between, Or(conds...)) +} + +// IsValid tests if the condition is valid +func (between Between) IsValid() bool { + return len(between.Col) > 0 +} diff --git a/vendor/xorm.io/builder/cond_compare.go b/vendor/xorm.io/builder/cond_compare.go new file mode 100644 index 0000000000..1c293719c0 --- /dev/null +++ b/vendor/xorm.io/builder/cond_compare.go @@ -0,0 +1,160 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +// WriteMap writes conditions' SQL to Writer, op could be =, <>, >, <, <=, >= and etc. +func WriteMap(w Writer, data map[string]interface{}, op string) error { + var args = make([]interface{}, 0, len(data)) + var i = 0 + keys := make([]string, 0, len(data)) + for k := range data { + keys = append(keys, k) + } + + for _, k := range keys { + v := data[k] + switch v.(type) { + case expr: + if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil { + return err + } + + if err := v.(expr).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case *Builder: + if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil { + return err + } + + if err := v.(*Builder).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + default: + if _, err := fmt.Fprintf(w, "%s%s?", k, op); err != nil { + return err + } + args = append(args, v) + } + if i != len(data)-1 { + if _, err := fmt.Fprint(w, " AND "); err != nil { + return err + } + } + i = i + 1 + } + w.Append(args...) + return nil +} + +// Lt defines < condition +type Lt map[string]interface{} + +var _ Cond = Lt{} + +// WriteTo write SQL to Writer +func (lt Lt) WriteTo(w Writer) error { + return WriteMap(w, lt, "<") +} + +// And implements And with other conditions +func (lt Lt) And(conds ...Cond) Cond { + return condAnd{lt, And(conds...)} +} + +// Or implements Or with other conditions +func (lt Lt) Or(conds ...Cond) Cond { + return condOr{lt, Or(conds...)} +} + +// IsValid tests if this Eq is valid +func (lt Lt) IsValid() bool { + return len(lt) > 0 +} + +// Lte defines <= condition +type Lte map[string]interface{} + +var _ Cond = Lte{} + +// WriteTo write SQL to Writer +func (lte Lte) WriteTo(w Writer) error { + return WriteMap(w, lte, "<=") +} + +// And implements And with other conditions +func (lte Lte) And(conds ...Cond) Cond { + return And(lte, And(conds...)) +} + +// Or implements Or with other conditions +func (lte Lte) Or(conds ...Cond) Cond { + return Or(lte, Or(conds...)) +} + +// IsValid tests if this Eq is valid +func (lte Lte) IsValid() bool { + return len(lte) > 0 +} + +// Gt defines > condition +type Gt map[string]interface{} + +var _ Cond = Gt{} + +// WriteTo write SQL to Writer +func (gt Gt) WriteTo(w Writer) error { + return WriteMap(w, gt, ">") +} + +// And implements And with other conditions +func (gt Gt) And(conds ...Cond) Cond { + return And(gt, And(conds...)) +} + +// Or implements Or with other conditions +func (gt Gt) Or(conds ...Cond) Cond { + return Or(gt, Or(conds...)) +} + +// IsValid tests if this Eq is valid +func (gt Gt) IsValid() bool { + return len(gt) > 0 +} + +// Gte defines >= condition +type Gte map[string]interface{} + +var _ Cond = Gte{} + +// WriteTo write SQL to Writer +func (gte Gte) WriteTo(w Writer) error { + return WriteMap(w, gte, ">=") +} + +// And implements And with other conditions +func (gte Gte) And(conds ...Cond) Cond { + return And(gte, And(conds...)) +} + +// Or implements Or with other conditions +func (gte Gte) Or(conds ...Cond) Cond { + return Or(gte, Or(conds...)) +} + +// IsValid tests if this Eq is valid +func (gte Gte) IsValid() bool { + return len(gte) > 0 +} diff --git a/vendor/xorm.io/builder/cond_eq.go b/vendor/xorm.io/builder/cond_eq.go new file mode 100644 index 0000000000..79d795e6dd --- /dev/null +++ b/vendor/xorm.io/builder/cond_eq.go @@ -0,0 +1,112 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "sort" +) + +// Incr implements a type used by Eq +type Incr int + +// Decr implements a type used by Eq +type Decr int + +// Eq defines equals conditions +type Eq map[string]interface{} + +var _ Cond = Eq{} + +func (eq Eq) opWriteTo(op string, w Writer) error { + var i = 0 + for _, k := range eq.sortedKeys() { + v := eq[k] + switch v.(type) { + case []int, []int64, []string, []int32, []int16, []int8, []uint, []uint64, []uint32, []uint16, []interface{}: + if err := In(k, v).WriteTo(w); err != nil { + return err + } + case expr: + if _, err := fmt.Fprintf(w, "%s=(", k); err != nil { + return err + } + + if err := v.(expr).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case *Builder: + if _, err := fmt.Fprintf(w, "%s=(", k); err != nil { + return err + } + + if err := v.(*Builder).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case Incr: + if _, err := fmt.Fprintf(w, "%s=%s+?", k, k); err != nil { + return err + } + w.Append(int(v.(Incr))) + case Decr: + if _, err := fmt.Fprintf(w, "%s=%s-?", k, k); err != nil { + return err + } + w.Append(int(v.(Decr))) + default: + if _, err := fmt.Fprintf(w, "%s=?", k); err != nil { + return err + } + w.Append(v) + } + if i != len(eq)-1 { + if _, err := fmt.Fprint(w, op); err != nil { + return err + } + } + i = i + 1 + } + return nil +} + +// WriteTo writes SQL to Writer +func (eq Eq) WriteTo(w Writer) error { + return eq.opWriteTo(" AND ", w) +} + +// And implements And with other conditions +func (eq Eq) And(conds ...Cond) Cond { + return And(eq, And(conds...)) +} + +// Or implements Or with other conditions +func (eq Eq) Or(conds ...Cond) Cond { + return Or(eq, Or(conds...)) +} + +// IsValid tests if this Eq is valid +func (eq Eq) IsValid() bool { + return len(eq) > 0 +} + +// sortedKeys returns all keys of this Eq sorted with sort.Strings. +// It is used internally for consistent ordering when generating +// SQL, see https://github.com/go-xorm/builder/issues/10 +func (eq Eq) sortedKeys() []string { + keys := make([]string, 0, len(eq)) + for key := range eq { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} diff --git a/vendor/xorm.io/builder/cond_expr.go b/vendor/xorm.io/builder/cond_expr.go new file mode 100644 index 0000000000..e5ed572b15 --- /dev/null +++ b/vendor/xorm.io/builder/cond_expr.go @@ -0,0 +1,39 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +type expr struct { + sql string + args []interface{} +} + +var _ Cond = expr{} + +// Expr generate customerize SQL +func Expr(sql string, args ...interface{}) Cond { + return expr{sql, args} +} + +func (expr expr) WriteTo(w Writer) error { + if _, err := fmt.Fprint(w, expr.sql); err != nil { + return err + } + w.Append(expr.args...) + return nil +} + +func (expr expr) And(conds ...Cond) Cond { + return And(expr, And(conds...)) +} + +func (expr expr) Or(conds ...Cond) Cond { + return Or(expr, Or(conds...)) +} + +func (expr expr) IsValid() bool { + return len(expr.sql) > 0 +} diff --git a/vendor/xorm.io/builder/cond_if.go b/vendor/xorm.io/builder/cond_if.go new file mode 100644 index 0000000000..af9eb321fd --- /dev/null +++ b/vendor/xorm.io/builder/cond_if.go @@ -0,0 +1,49 @@ +// Copyright 2019 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +type condIf struct { + condition bool + condTrue Cond + condFalse Cond +} + +var _ Cond = condIf{} + +// If returns Cond via condition +func If(condition bool, condTrue Cond, condFalse ...Cond) Cond { + var c = condIf{ + condition: condition, + condTrue: condTrue, + } + if len(condFalse) > 0 { + c.condFalse = condFalse[0] + } + return c +} + +func (condIf condIf) WriteTo(w Writer) error { + if condIf.condition { + return condIf.condTrue.WriteTo(w) + } else if condIf.condFalse != nil { + return condIf.condFalse.WriteTo(w) + } + return nil +} + +func (condIf condIf) And(conds ...Cond) Cond { + return And(condIf, And(conds...)) +} + +func (condIf condIf) Or(conds ...Cond) Cond { + return Or(condIf, Or(conds...)) +} + +func (condIf condIf) IsValid() bool { + if condIf.condition { + return condIf.condTrue != nil + } + return condIf.condFalse != nil +} diff --git a/vendor/xorm.io/builder/cond_in.go b/vendor/xorm.io/builder/cond_in.go new file mode 100644 index 0000000000..f6366d35c2 --- /dev/null +++ b/vendor/xorm.io/builder/cond_in.go @@ -0,0 +1,237 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "reflect" + "strings" +) + +type condIn struct { + col string + vals []interface{} +} + +var _ Cond = condIn{} + +// In generates IN condition +func In(col string, values ...interface{}) Cond { + return condIn{col, values} +} + +func (condIn condIn) handleBlank(w Writer) error { + _, err := fmt.Fprint(w, "0=1") + return err +} + +func (condIn condIn) WriteTo(w Writer) error { + if len(condIn.vals) <= 0 { + return condIn.handleBlank(w) + } + + switch condIn.vals[0].(type) { + case []int8: + vals := condIn.vals[0].([]int8) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int16: + vals := condIn.vals[0].([]int16) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int: + vals := condIn.vals[0].([]int) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int32: + vals := condIn.vals[0].([]int32) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int64: + vals := condIn.vals[0].([]int64) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint8: + vals := condIn.vals[0].([]uint8) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint16: + vals := condIn.vals[0].([]uint16) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint: + vals := condIn.vals[0].([]uint) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint32: + vals := condIn.vals[0].([]uint32) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint64: + vals := condIn.vals[0].([]uint64) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []string: + vals := condIn.vals[0].([]string) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []interface{}: + vals := condIn.vals[0].([]interface{}) + if len(vals) <= 0 { + return condIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + w.Append(vals...) + case expr: + val := condIn.vals[0].(expr) + if _, err := fmt.Fprintf(w, "%s IN (", condIn.col); err != nil { + return err + } + if err := val.WriteTo(w); err != nil { + return err + } + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case *Builder: + bd := condIn.vals[0].(*Builder) + if _, err := fmt.Fprintf(w, "%s IN (", condIn.col); err != nil { + return err + } + if err := bd.WriteTo(w); err != nil { + return err + } + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + default: + v := reflect.ValueOf(condIn.vals[0]) + if v.Kind() == reflect.Slice { + l := v.Len() + if l == 0 { + return condIn.handleBlank(w) + } + + questionMark := strings.Repeat("?,", l) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + + for i := 0; i < l; i++ { + w.Append(v.Index(i).Interface()) + } + } else { + questionMark := strings.Repeat("?,", len(condIn.vals)) + if _, err := fmt.Fprintf(w, "%s IN (%s)", condIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + w.Append(condIn.vals...) + } + } + return nil +} + +func (condIn condIn) And(conds ...Cond) Cond { + return And(condIn, And(conds...)) +} + +func (condIn condIn) Or(conds ...Cond) Cond { + return Or(condIn, Or(conds...)) +} + +func (condIn condIn) IsValid() bool { + return len(condIn.col) > 0 && len(condIn.vals) > 0 +} diff --git a/vendor/xorm.io/builder/cond_like.go b/vendor/xorm.io/builder/cond_like.go new file mode 100644 index 0000000000..e34202f8b0 --- /dev/null +++ b/vendor/xorm.io/builder/cond_like.go @@ -0,0 +1,41 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +// Like defines like condition +type Like [2]string + +var _ Cond = Like{"", ""} + +// WriteTo write SQL to Writer +func (like Like) WriteTo(w Writer) error { + if _, err := fmt.Fprintf(w, "%s LIKE ?", like[0]); err != nil { + return err + } + // FIXME: if use other regular express, this will be failed. but for compatible, keep this + if like[1][0] == '%' || like[1][len(like[1])-1] == '%' { + w.Append(like[1]) + } else { + w.Append("%" + like[1] + "%") + } + return nil +} + +// And implements And with other conditions +func (like Like) And(conds ...Cond) Cond { + return And(like, And(conds...)) +} + +// Or implements Or with other conditions +func (like Like) Or(conds ...Cond) Cond { + return Or(like, Or(conds...)) +} + +// IsValid tests if this condition is valid +func (like Like) IsValid() bool { + return len(like[0]) > 0 && len(like[1]) > 0 +} diff --git a/vendor/xorm.io/builder/cond_neq.go b/vendor/xorm.io/builder/cond_neq.go new file mode 100644 index 0000000000..3a8f3136d9 --- /dev/null +++ b/vendor/xorm.io/builder/cond_neq.go @@ -0,0 +1,94 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "sort" +) + +// Neq defines not equal conditions +type Neq map[string]interface{} + +var _ Cond = Neq{} + +// WriteTo writes SQL to Writer +func (neq Neq) WriteTo(w Writer) error { + var args = make([]interface{}, 0, len(neq)) + var i = 0 + for _, k := range neq.sortedKeys() { + v := neq[k] + switch v.(type) { + case []int, []int64, []string, []int32, []int16, []int8: + if err := NotIn(k, v).WriteTo(w); err != nil { + return err + } + case expr: + if _, err := fmt.Fprintf(w, "%s<>(", k); err != nil { + return err + } + + if err := v.(expr).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case *Builder: + if _, err := fmt.Fprintf(w, "%s<>(", k); err != nil { + return err + } + + if err := v.(*Builder).WriteTo(w); err != nil { + return err + } + + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + default: + if _, err := fmt.Fprintf(w, "%s<>?", k); err != nil { + return err + } + args = append(args, v) + } + if i != len(neq)-1 { + if _, err := fmt.Fprint(w, " AND "); err != nil { + return err + } + } + i = i + 1 + } + w.Append(args...) + return nil +} + +// And implements And with other conditions +func (neq Neq) And(conds ...Cond) Cond { + return And(neq, And(conds...)) +} + +// Or implements Or with other conditions +func (neq Neq) Or(conds ...Cond) Cond { + return Or(neq, Or(conds...)) +} + +// IsValid tests if this condition is valid +func (neq Neq) IsValid() bool { + return len(neq) > 0 +} + +// sortedKeys returns all keys of this Neq sorted with sort.Strings. +// It is used internally for consistent ordering when generating +// SQL, see https://github.com/go-xorm/builder/issues/10 +func (neq Neq) sortedKeys() []string { + keys := make([]string, 0, len(neq)) + for key := range neq { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} diff --git a/vendor/xorm.io/builder/cond_not.go b/vendor/xorm.io/builder/cond_not.go new file mode 100644 index 0000000000..667dfe7293 --- /dev/null +++ b/vendor/xorm.io/builder/cond_not.go @@ -0,0 +1,77 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +// Not defines NOT condition +type Not [1]Cond + +var _ Cond = Not{} + +// WriteTo writes SQL to Writer +func (not Not) WriteTo(w Writer) error { + if _, err := fmt.Fprint(w, "NOT "); err != nil { + return err + } + switch not[0].(type) { + case condAnd, condOr: + if _, err := fmt.Fprint(w, "("); err != nil { + return err + } + case Eq: + if len(not[0].(Eq)) > 1 { + if _, err := fmt.Fprint(w, "("); err != nil { + return err + } + } + case Neq: + if len(not[0].(Neq)) > 1 { + if _, err := fmt.Fprint(w, "("); err != nil { + return err + } + } + } + + if err := not[0].WriteTo(w); err != nil { + return err + } + + switch not[0].(type) { + case condAnd, condOr: + if _, err := fmt.Fprint(w, ")"); err != nil { + return err + } + case Eq: + if len(not[0].(Eq)) > 1 { + if _, err := fmt.Fprint(w, ")"); err != nil { + return err + } + } + case Neq: + if len(not[0].(Neq)) > 1 { + if _, err := fmt.Fprint(w, ")"); err != nil { + return err + } + } + } + + return nil +} + +// And implements And with other conditions +func (not Not) And(conds ...Cond) Cond { + return And(not, And(conds...)) +} + +// Or implements Or with other conditions +func (not Not) Or(conds ...Cond) Cond { + return Or(not, Or(conds...)) +} + +// IsValid tests if this condition is valid +func (not Not) IsValid() bool { + return not[0] != nil && not[0].IsValid() +} diff --git a/vendor/xorm.io/builder/cond_notin.go b/vendor/xorm.io/builder/cond_notin.go new file mode 100644 index 0000000000..dc3ac49a35 --- /dev/null +++ b/vendor/xorm.io/builder/cond_notin.go @@ -0,0 +1,234 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "fmt" + "reflect" + "strings" +) + +type condNotIn condIn + +var _ Cond = condNotIn{} + +// NotIn generate NOT IN condition +func NotIn(col string, values ...interface{}) Cond { + return condNotIn{col, values} +} + +func (condNotIn condNotIn) handleBlank(w Writer) error { + _, err := fmt.Fprint(w, "0=0") + return err +} + +func (condNotIn condNotIn) WriteTo(w Writer) error { + if len(condNotIn.vals) <= 0 { + return condNotIn.handleBlank(w) + } + + switch condNotIn.vals[0].(type) { + case []int8: + vals := condNotIn.vals[0].([]int8) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int16: + vals := condNotIn.vals[0].([]int16) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int: + vals := condNotIn.vals[0].([]int) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int32: + vals := condNotIn.vals[0].([]int32) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []int64: + vals := condNotIn.vals[0].([]int64) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint8: + vals := condNotIn.vals[0].([]uint8) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint16: + vals := condNotIn.vals[0].([]uint16) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint: + vals := condNotIn.vals[0].([]uint) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint32: + vals := condNotIn.vals[0].([]uint32) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []uint64: + vals := condNotIn.vals[0].([]uint64) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []string: + vals := condNotIn.vals[0].([]string) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + for _, val := range vals { + w.Append(val) + } + case []interface{}: + vals := condNotIn.vals[0].([]interface{}) + if len(vals) <= 0 { + return condNotIn.handleBlank(w) + } + questionMark := strings.Repeat("?,", len(vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + w.Append(vals...) + case expr: + val := condNotIn.vals[0].(expr) + if _, err := fmt.Fprintf(w, "%s NOT IN (", condNotIn.col); err != nil { + return err + } + if err := val.WriteTo(w); err != nil { + return err + } + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + case *Builder: + val := condNotIn.vals[0].(*Builder) + if _, err := fmt.Fprintf(w, "%s NOT IN (", condNotIn.col); err != nil { + return err + } + if err := val.WriteTo(w); err != nil { + return err + } + if _, err := fmt.Fprintf(w, ")"); err != nil { + return err + } + default: + v := reflect.ValueOf(condNotIn.vals[0]) + if v.Kind() == reflect.Slice { + l := v.Len() + if l == 0 { + return condNotIn.handleBlank(w) + } + + questionMark := strings.Repeat("?,", l) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + + for i := 0; i < l; i++ { + w.Append(v.Index(i).Interface()) + } + } else { + questionMark := strings.Repeat("?,", len(condNotIn.vals)) + if _, err := fmt.Fprintf(w, "%s NOT IN (%s)", condNotIn.col, questionMark[:len(questionMark)-1]); err != nil { + return err + } + w.Append(condNotIn.vals...) + } + } + return nil +} + +func (condNotIn condNotIn) And(conds ...Cond) Cond { + return And(condNotIn, And(conds...)) +} + +func (condNotIn condNotIn) Or(conds ...Cond) Cond { + return Or(condNotIn, Or(conds...)) +} + +func (condNotIn condNotIn) IsValid() bool { + return len(condNotIn.col) > 0 && len(condNotIn.vals) > 0 +} diff --git a/vendor/xorm.io/builder/cond_null.go b/vendor/xorm.io/builder/cond_null.go new file mode 100644 index 0000000000..bf2aaf8518 --- /dev/null +++ b/vendor/xorm.io/builder/cond_null.go @@ -0,0 +1,59 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +// IsNull defines IS NULL condition +type IsNull [1]string + +var _ Cond = IsNull{""} + +// WriteTo write SQL to Writer +func (isNull IsNull) WriteTo(w Writer) error { + _, err := fmt.Fprintf(w, "%s IS NULL", isNull[0]) + return err +} + +// And implements And with other conditions +func (isNull IsNull) And(conds ...Cond) Cond { + return And(isNull, And(conds...)) +} + +// Or implements Or with other conditions +func (isNull IsNull) Or(conds ...Cond) Cond { + return Or(isNull, Or(conds...)) +} + +// IsValid tests if this condition is valid +func (isNull IsNull) IsValid() bool { + return len(isNull[0]) > 0 +} + +// NotNull defines NOT NULL condition +type NotNull [1]string + +var _ Cond = NotNull{""} + +// WriteTo write SQL to Writer +func (notNull NotNull) WriteTo(w Writer) error { + _, err := fmt.Fprintf(w, "%s IS NOT NULL", notNull[0]) + return err +} + +// And implements And with other conditions +func (notNull NotNull) And(conds ...Cond) Cond { + return And(notNull, And(conds...)) +} + +// Or implements Or with other conditions +func (notNull NotNull) Or(conds ...Cond) Cond { + return Or(notNull, Or(conds...)) +} + +// IsValid tests if this condition is valid +func (notNull NotNull) IsValid() bool { + return len(notNull[0]) > 0 +} diff --git a/vendor/xorm.io/builder/cond_or.go b/vendor/xorm.io/builder/cond_or.go new file mode 100644 index 0000000000..52442653a8 --- /dev/null +++ b/vendor/xorm.io/builder/cond_or.go @@ -0,0 +1,69 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "fmt" + +type condOr []Cond + +var _ Cond = condOr{} + +// Or sets OR conditions +func Or(conds ...Cond) Cond { + var result = make(condOr, 0, len(conds)) + for _, cond := range conds { + if cond == nil || !cond.IsValid() { + continue + } + result = append(result, cond) + } + return result +} + +// WriteTo implments Cond +func (o condOr) WriteTo(w Writer) error { + for i, cond := range o { + var needQuote bool + switch cond.(type) { + case condAnd, expr: + needQuote = true + case Eq: + needQuote = (len(cond.(Eq)) > 1) + case Neq: + needQuote = (len(cond.(Neq)) > 1) + } + + if needQuote { + fmt.Fprint(w, "(") + } + + err := cond.WriteTo(w) + if err != nil { + return err + } + + if needQuote { + fmt.Fprint(w, ")") + } + + if i != len(o)-1 { + fmt.Fprint(w, " OR ") + } + } + + return nil +} + +func (o condOr) And(conds ...Cond) Cond { + return And(o, And(conds...)) +} + +func (o condOr) Or(conds ...Cond) Cond { + return Or(o, Or(conds...)) +} + +func (o condOr) IsValid() bool { + return len(o) > 0 +} diff --git a/vendor/xorm.io/builder/doc.go b/vendor/xorm.io/builder/doc.go new file mode 100644 index 0000000000..162b150f10 --- /dev/null +++ b/vendor/xorm.io/builder/doc.go @@ -0,0 +1,120 @@ +// Copyright 2016 The XORM Authors. All rights reserved. +// Use of this source code is governed by a BSD +// license that can be found in the LICENSE file. + +/* + +Package builder is a simple and powerful sql builder for Go. + +Make sure you have installed Go 1.1+ and then: + + go get github.com/go-xorm/builder + +WARNNING: Currently, only query conditions are supported. Below is the supported conditions. + +1. Eq is a redefine of a map, you can give one or more conditions to Eq + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Eq{"a":1}) + // a=? [1] + sql, args, _ := ToSQL(Eq{"b":"c"}.And(Eq{"c": 0})) + // b=? AND c=? ["c", 0] + sql, args, _ := ToSQL(Eq{"b":"c", "c":0}) + // b=? AND c=? ["c", 0] + sql, args, _ := ToSQL(Eq{"b":"c"}.Or(Eq{"b":"d"})) + // b=? OR b=? ["c", "d"] + sql, args, _ := ToSQL(Eq{"b": []string{"c", "d"}}) + // b IN (?,?) ["c", "d"] + sql, args, _ := ToSQL(Eq{"b": 1, "c":[]int{2, 3}}) + // b=? AND c IN (?,?) [1, 2, 3] + +2. Neq is the same to Eq + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Neq{"a":1}) + // a<>? [1] + sql, args, _ := ToSQL(Neq{"b":"c"}.And(Neq{"c": 0})) + // b<>? AND c<>? ["c", 0] + sql, args, _ := ToSQL(Neq{"b":"c", "c":0}) + // b<>? AND c<>? ["c", 0] + sql, args, _ := ToSQL(Neq{"b":"c"}.Or(Neq{"b":"d"})) + // b<>? OR b<>? ["c", "d"] + sql, args, _ := ToSQL(Neq{"b": []string{"c", "d"}}) + // b NOT IN (?,?) ["c", "d"] + sql, args, _ := ToSQL(Neq{"b": 1, "c":[]int{2, 3}}) + // b<>? AND c NOT IN (?,?) [1, 2, 3] + +3. Gt, Gte, Lt, Lte + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Gt{"a", 1}.And(Gte{"b", 2})) + // a>? AND b>=? [1, 2] + sql, args, _ := ToSQL(Lt{"a", 1}.Or(Lte{"b", 2})) + // a<? OR b<=? [1, 2] + +4. Like + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Like{"a", "c"}) + // a LIKE ? [%c%] + +5. Expr you can customerize your sql with Expr + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Expr("a = ? ", 1)) + // a = ? [1] + sql, args, _ := ToSQL(Eq{"a": Expr("select id from table where c = ?", 1)}) + // a=(select id from table where c = ?) [1] + +6. In and NotIn + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(In("a", 1, 2, 3)) + // a IN (?,?,?) [1,2,3] + sql, args, _ := ToSQL(In("a", []int{1, 2, 3})) + // a IN (?,?,?) [1,2,3] + sql, args, _ := ToSQL(In("a", Expr("select id from b where c = ?", 1)))) + // a IN (select id from b where c = ?) [1] + +7. IsNull and NotNull + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(IsNull{"a"}) + // a IS NULL [] + sql, args, _ := ToSQL(NotNull{"b"}) + // b IS NOT NULL [] + +8. And(conds ...Cond), And can connect one or more condtions via AND + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(And(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2})) + // a=? AND b LIKE ? AND d<>? [1, %c%, 2] + +9. Or(conds ...Cond), Or can connect one or more conditions via Or + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Or(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2})) + // a=? OR b LIKE ? OR d<>? [1, %c%, 2] + sql, args, _ := ToSQL(Or(Eq{"a":1}, And(Like{"b", "c"}, Neq{"d", 2}))) + // a=? OR (b LIKE ? AND d<>?) [1, %c%, 2] + +10. Between + + import . "github.com/go-xorm/builder" + + sql, args, _ := ToSQL(Between("a", 1, 2)) + // a BETWEEN 1 AND 2 + +11. define yourself conditions +Since Cond is a interface, you can define yourself conditions and compare with them +*/ +package builder diff --git a/vendor/xorm.io/builder/error.go b/vendor/xorm.io/builder/error.go new file mode 100644 index 0000000000..d830ee9955 --- /dev/null +++ b/vendor/xorm.io/builder/error.go @@ -0,0 +1,40 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import "errors" + +var ( + // ErrNotSupportType not supported SQL type error + ErrNotSupportType = errors.New("Not supported SQL type") + // ErrNoNotInConditions no NOT IN params error + ErrNoNotInConditions = errors.New("No NOT IN conditions") + // ErrNoInConditions no IN params error + ErrNoInConditions = errors.New("No IN conditions") + // ErrNeedMoreArguments need more arguments + ErrNeedMoreArguments = errors.New("Need more sql arguments") + // ErrNoTableName no table name + ErrNoTableName = errors.New("No table indicated") + // ErrNoColumnToInsert no column to update + ErrNoColumnToUpdate = errors.New("No column(s) to update") + // ErrNoColumnToInsert no column to update + ErrNoColumnToInsert = errors.New("No column(s) to insert") + // ErrNotSupportDialectType not supported dialect type error + ErrNotSupportDialectType = errors.New("Not supported dialect type") + // ErrNotUnexpectedUnionConditions using union in a wrong way + ErrNotUnexpectedUnionConditions = errors.New("Unexpected conditional fields in UNION query") + // ErrUnsupportedUnionMembers unexpected members in UNION query + ErrUnsupportedUnionMembers = errors.New("Unexpected members in UNION query") + // ErrUnexpectedSubQuery Unexpected sub-query in SELECT query + ErrUnexpectedSubQuery = errors.New("Unexpected sub-query in SELECT query") + // ErrDialectNotSetUp dialect is not setup yet + ErrDialectNotSetUp = errors.New("Dialect is not setup yet, try to use `Dialect(dbType)` at first") + // ErrInvalidLimitation offset or limit is not correct + ErrInvalidLimitation = errors.New("Offset or limit is not correct") + // ErrUnnamedDerivedTable Every derived table must have its own alias + ErrUnnamedDerivedTable = errors.New("Every derived table must have its own alias") + // ErrInconsistentDialect Inconsistent dialect in same builder + ErrInconsistentDialect = errors.New("Inconsistent dialect in same builder") +) diff --git a/vendor/xorm.io/builder/go.mod b/vendor/xorm.io/builder/go.mod new file mode 100644 index 0000000000..35e43b329f --- /dev/null +++ b/vendor/xorm.io/builder/go.mod @@ -0,0 +1,6 @@ +module xorm.io/builder + +require ( + github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a + github.com/stretchr/testify v1.3.0 +) diff --git a/vendor/xorm.io/builder/go.sum b/vendor/xorm.io/builder/go.sum new file mode 100644 index 0000000000..468ba4a2d5 --- /dev/null +++ b/vendor/xorm.io/builder/go.sum @@ -0,0 +1,9 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/xorm.io/builder/sql.go b/vendor/xorm.io/builder/sql.go new file mode 100644 index 0000000000..0834242768 --- /dev/null +++ b/vendor/xorm.io/builder/sql.go @@ -0,0 +1,156 @@ +// Copyright 2018 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + sql2 "database/sql" + "fmt" + "reflect" + "time" +) + +func condToSQL(cond Cond) (string, []interface{}, error) { + if cond == nil || !cond.IsValid() { + return "", nil, nil + } + + w := NewWriter() + if err := cond.WriteTo(w); err != nil { + return "", nil, err + } + return w.writer.String(), w.args, nil +} + +func condToBoundSQL(cond Cond) (string, error) { + if cond == nil || !cond.IsValid() { + return "", nil + } + + w := NewWriter() + if err := cond.WriteTo(w); err != nil { + return "", err + } + return ConvertToBoundSQL(w.writer.String(), w.args) +} + +// ToSQL convert a builder or conditions to SQL and args +func ToSQL(cond interface{}) (string, []interface{}, error) { + switch cond.(type) { + case Cond: + return condToSQL(cond.(Cond)) + case *Builder: + return cond.(*Builder).ToSQL() + } + return "", nil, ErrNotSupportType +} + +// ToBoundSQL convert a builder or conditions to parameters bound SQL +func ToBoundSQL(cond interface{}) (string, error) { + switch cond.(type) { + case Cond: + return condToBoundSQL(cond.(Cond)) + case *Builder: + return cond.(*Builder).ToBoundSQL() + } + return "", ErrNotSupportType +} + +func noSQLQuoteNeeded(a interface{}) bool { + switch a.(type) { + case int, int8, int16, int32, int64: + return true + case uint, uint8, uint16, uint32, uint64: + return true + case float32, float64: + return true + case bool: + return true + case string: + return false + case time.Time, *time.Time: + return false + } + + t := reflect.TypeOf(a) + switch t.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.Bool: + return true + case reflect.String: + return false + } + + return false +} + +// ConvertToBoundSQL will convert SQL and args to a bound SQL +func ConvertToBoundSQL(sql string, args []interface{}) (string, error) { + buf := StringBuilder{} + var i, j, start int + for ; i < len(sql); i++ { + if sql[i] == '?' { + _, err := buf.WriteString(sql[start:i]) + if err != nil { + return "", err + } + start = i + 1 + + if len(args) == j { + return "", ErrNeedMoreArguments + } + + arg := args[j] + if namedArg, ok := arg.(sql2.NamedArg); ok { + arg = namedArg.Value + } + + if noSQLQuoteNeeded(arg) { + _, err = fmt.Fprint(&buf, arg) + } else { + _, err = fmt.Fprintf(&buf, "'%v'", arg) + } + if err != nil { + return "", err + } + j = j + 1 + } + } + _, err := buf.WriteString(sql[start:]) + if err != nil { + return "", err + } + return buf.String(), nil +} + +// ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix +func ConvertPlaceholder(sql, prefix string) (string, error) { + buf := StringBuilder{} + var i, j, start int + for ; i < len(sql); i++ { + if sql[i] == '?' { + if _, err := buf.WriteString(sql[start:i]); err != nil { + return "", err + } + + start = i + 1 + j = j + 1 + + if _, err := buf.WriteString(fmt.Sprintf("%v%d", prefix, j)); err != nil { + return "", err + } + } + } + + if _, err := buf.WriteString(sql[start:]); err != nil { + return "", err + } + + return buf.String(), nil +} diff --git a/vendor/xorm.io/builder/string_builder.go b/vendor/xorm.io/builder/string_builder.go new file mode 100644 index 0000000000..d4de8717e7 --- /dev/null +++ b/vendor/xorm.io/builder/string_builder.go @@ -0,0 +1,119 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package builder + +import ( + "unicode/utf8" + "unsafe" +) + +// A StringBuilder is used to efficiently build a string using Write methods. +// It minimizes memory copying. The zero value is ready to use. +// Do not copy a non-zero Builder. +type StringBuilder struct { + addr *StringBuilder // of receiver, to detect copies by value + buf []byte +} + +// noescape hides a pointer from escape analysis. noescape is +// the identity function but escape analysis doesn't think the +// output depends on the input. noescape is inlined and currently +// compiles down to zero instructions. +// USE CAREFULLY! +// This was copied from the runtime; see issues 23382 and 7921. +//go:nosplit +func noescape(p unsafe.Pointer) unsafe.Pointer { + x := uintptr(p) + return unsafe.Pointer(x ^ 0) +} + +func (b *StringBuilder) copyCheck() { + if b.addr == nil { + // This hack works around a failing of Go's escape analysis + // that was causing b to escape and be heap allocated. + // See issue 23382. + // TODO: once issue 7921 is fixed, this should be reverted to + // just "b.addr = b". + b.addr = (*StringBuilder)(noescape(unsafe.Pointer(b))) + } else if b.addr != b { + panic("strings: illegal use of non-zero Builder copied by value") + } +} + +// String returns the accumulated string. +func (b *StringBuilder) String() string { + return *(*string)(unsafe.Pointer(&b.buf)) +} + +// Len returns the number of accumulated bytes; b.Len() == len(b.String()). +func (b *StringBuilder) Len() int { return len(b.buf) } + +// Reset resets the Builder to be empty. +func (b *StringBuilder) Reset() { + b.addr = nil + b.buf = nil +} + +// grow copies the buffer to a new, larger buffer so that there are at least n +// bytes of capacity beyond len(b.buf). +func (b *StringBuilder) grow(n int) { + buf := make([]byte, len(b.buf), 2*cap(b.buf)+n) + copy(buf, b.buf) + b.buf = buf +} + +// Grow grows b's capacity, if necessary, to guarantee space for +// another n bytes. After Grow(n), at least n bytes can be written to b +// without another allocation. If n is negative, Grow panics. +func (b *StringBuilder) Grow(n int) { + b.copyCheck() + if n < 0 { + panic("strings.Builder.Grow: negative count") + } + if cap(b.buf)-len(b.buf) < n { + b.grow(n) + } +} + +// Write appends the contents of p to b's buffer. +// Write always returns len(p), nil. +func (b *StringBuilder) Write(p []byte) (int, error) { + b.copyCheck() + b.buf = append(b.buf, p...) + return len(p), nil +} + +// WriteByte appends the byte c to b's buffer. +// The returned error is always nil. +func (b *StringBuilder) WriteByte(c byte) error { + b.copyCheck() + b.buf = append(b.buf, c) + return nil +} + +// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer. +// It returns the length of r and a nil error. +func (b *StringBuilder) WriteRune(r rune) (int, error) { + b.copyCheck() + if r < utf8.RuneSelf { + b.buf = append(b.buf, byte(r)) + return 1, nil + } + l := len(b.buf) + if cap(b.buf)-l < utf8.UTFMax { + b.grow(utf8.UTFMax) + } + n := utf8.EncodeRune(b.buf[l:l+utf8.UTFMax], r) + b.buf = b.buf[:l+n] + return n, nil +} + +// WriteString appends the contents of s to b's buffer. +// It returns the length of s and a nil error. +func (b *StringBuilder) WriteString(s string) (int, error) { + b.copyCheck() + b.buf = append(b.buf, s...) + return len(s), nil +} |