Fix label count (#8267)
* fix label count * fix vendor * fix import order * update xorm to fix bug * fix tests * fix mssql bugtokarchuk/v1.17
parent
7cccada51e
commit
29dda47cbb
@ -1,19 +1,20 @@ |
||||
module github.com/go-xorm/xorm |
||||
|
||||
go 1.11 |
||||
|
||||
require ( |
||||
github.com/cockroachdb/apd v1.1.0 // indirect |
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 |
||||
github.com/go-sql-driver/mysql v1.4.1 |
||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect |
||||
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect |
||||
github.com/jackc/pgx v3.3.0+incompatible |
||||
github.com/kr/pretty v0.1.0 // indirect |
||||
github.com/jackc/pgx v3.6.0+incompatible |
||||
github.com/lib/pq v1.0.0 |
||||
github.com/mattn/go-sqlite3 v1.10.0 |
||||
github.com/pkg/errors v0.8.1 // indirect |
||||
github.com/satori/go.uuid v1.2.0 // indirect |
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect |
||||
github.com/stretchr/testify v1.3.0 |
||||
github.com/ziutek/mymysql v1.5.4 |
||||
xorm.io/builder v0.3.5 |
||||
xorm.io/builder v0.3.6 |
||||
xorm.io/core v0.7.0 |
||||
) |
||||
|
@ -0,0 +1,97 @@ |
||||
// 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 xorm |
||||
|
||||
import ( |
||||
"fmt" |
||||
|
||||
"xorm.io/builder" |
||||
"xorm.io/core" |
||||
) |
||||
|
||||
func (statement *Statement) writeArg(w *builder.BytesWriter, arg interface{}) error { |
||||
switch argv := arg.(type) { |
||||
case string: |
||||
if _, err := w.WriteString("'" + argv + "'"); err != nil { |
||||
return err |
||||
} |
||||
case bool: |
||||
if statement.Engine.dialect.DBType() == core.MSSQL { |
||||
if argv { |
||||
if _, err := w.WriteString("1"); err != nil { |
||||
return err |
||||
} |
||||
} else { |
||||
if _, err := w.WriteString("0"); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} else { |
||||
if argv { |
||||
if _, err := w.WriteString("true"); err != nil { |
||||
return err |
||||
} |
||||
} else { |
||||
if _, err := w.WriteString("false"); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
case *builder.Builder: |
||||
if _, err := w.WriteString("("); err != nil { |
||||
return err |
||||
} |
||||
if err := argv.WriteTo(w); err != nil { |
||||
return err |
||||
} |
||||
if _, err := w.WriteString(")"); err != nil { |
||||
return err |
||||
} |
||||
default: |
||||
if _, err := w.WriteString(fmt.Sprintf("%v", argv)); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (statement *Statement) writeArgs(w *builder.BytesWriter, args []interface{}) error { |
||||
for i, arg := range args { |
||||
if err := statement.writeArg(w, arg); err != nil { |
||||
return err |
||||
} |
||||
|
||||
if i+1 != len(args) { |
||||
if _, err := w.WriteString(","); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func writeStrings(w *builder.BytesWriter, cols []string, leftQuote, rightQuote string) error { |
||||
for i, colName := range cols { |
||||
if len(leftQuote) > 0 && colName[0] != '`' { |
||||
if _, err := w.WriteString(leftQuote); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
if _, err := w.WriteString(colName); err != nil { |
||||
return err |
||||
} |
||||
if len(rightQuote) > 0 && colName[len(colName)-1] != '`' { |
||||
if _, err := w.WriteString(rightQuote); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
if i+1 != len(cols) { |
||||
if _, err := w.WriteString(","); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
@ -0,0 +1,35 @@ |
||||
// 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 xorm |
||||
|
||||
import "strings" |
||||
|
||||
type columnMap []string |
||||
|
||||
func (m columnMap) contain(colName string) bool { |
||||
if len(m) == 0 { |
||||
return false |
||||
} |
||||
|
||||
n := len(colName) |
||||
for _, mk := range m { |
||||
if len(mk) != n { |
||||
continue |
||||
} |
||||
if strings.EqualFold(mk, colName) { |
||||
return true |
||||
} |
||||
} |
||||
|
||||
return false |
||||
} |
||||
|
||||
func (m *columnMap) add(colName string) bool { |
||||
if m.contain(colName) { |
||||
return false |
||||
} |
||||
*m = append(*m, colName) |
||||
return true |
||||
} |
@ -0,0 +1,112 @@ |
||||
// 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 xorm |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strings" |
||||
|
||||
"xorm.io/builder" |
||||
) |
||||
|
||||
type ErrUnsupportedExprType struct { |
||||
tp string |
||||
} |
||||
|
||||
func (err ErrUnsupportedExprType) Error() string { |
||||
return fmt.Sprintf("Unsupported expression type: %v", err.tp) |
||||
} |
||||
|
||||
type exprParam struct { |
||||
colName string |
||||
arg interface{} |
||||
} |
||||
|
||||
type exprParams struct { |
||||
colNames []string |
||||
args []interface{} |
||||
} |
||||
|
||||
func (exprs *exprParams) Len() int { |
||||
return len(exprs.colNames) |
||||
} |
||||
|
||||
func (exprs *exprParams) addParam(colName string, arg interface{}) { |
||||
exprs.colNames = append(exprs.colNames, colName) |
||||
exprs.args = append(exprs.args, arg) |
||||
} |
||||
|
||||
func (exprs *exprParams) isColExist(colName string) bool { |
||||
for _, name := range exprs.colNames { |
||||
if strings.EqualFold(trimQuote(name), trimQuote(colName)) { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
func (exprs *exprParams) getByName(colName string) (exprParam, bool) { |
||||
for i, name := range exprs.colNames { |
||||
if strings.EqualFold(name, colName) { |
||||
return exprParam{name, exprs.args[i]}, true |
||||
} |
||||
} |
||||
return exprParam{}, false |
||||
} |
||||
|
||||
func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error { |
||||
for _, expr := range exprs.args { |
||||
switch arg := expr.(type) { |
||||
case *builder.Builder: |
||||
if _, err := w.WriteString("("); err != nil { |
||||
return err |
||||
} |
||||
if err := arg.WriteTo(w); err != nil { |
||||
return err |
||||
} |
||||
if _, err := w.WriteString(")"); err != nil { |
||||
return err |
||||
} |
||||
default: |
||||
if _, err := w.WriteString(fmt.Sprintf("%v", arg)); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (exprs *exprParams) writeNameArgs(w *builder.BytesWriter) error { |
||||
for i, colName := range exprs.colNames { |
||||
if _, err := w.WriteString(colName); err != nil { |
||||
return err |
||||
} |
||||
if _, err := w.WriteString("="); err != nil { |
||||
return err |
||||
} |
||||
|
||||
switch arg := exprs.args[i].(type) { |
||||
case *builder.Builder: |
||||
if _, err := w.WriteString("("); err != nil { |
||||
return err |
||||
} |
||||
if err := arg.WriteTo(w); err != nil { |
||||
return err |
||||
} |
||||
if _, err := w.WriteString("("); err != nil { |
||||
return err |
||||
} |
||||
default: |
||||
w.Append(exprs.args[i]) |
||||
} |
||||
|
||||
if i+1 != len(exprs.colNames) { |
||||
if _, err := w.WriteString(","); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
@ -0,0 +1,19 @@ |
||||
// 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 xorm |
||||
|
||||
func trimQuote(s string) string { |
||||
if len(s) == 0 { |
||||
return s |
||||
} |
||||
|
||||
if s[0] == '`' { |
||||
s = s[1:] |
||||
} |
||||
if len(s) > 0 && s[len(s)-1] == '`' { |
||||
return s[:len(s)-1] |
||||
} |
||||
return s |
||||
} |
@ -1 +1 @@ |
||||
go test -db=mssql -conn_str="server=localhost;user id=sa;password=yourStrong(!)Password;database=xorm_test" |
||||
go test -db=mssql -conn_str="server=localhost;user id=sa;password=MwantsaSecurePassword1;database=xorm_test" |
@ -1,37 +1,90 @@ |
||||
--- |
||||
kind: pipeline |
||||
name: go1.10 |
||||
|
||||
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} |
||||
path: src/xorm.io/builder |
||||
|
||||
steps: |
||||
- name: test |
||||
pull: default |
||||
image: golang:1.10 |
||||
commands: |
||||
- go get -u github.com/golang/lint/golint |
||||
- go get -u golang.org/x/lint/golint |
||||
- go get -u github.com/stretchr/testify/assert |
||||
- go get -u github.com/go-xorm/sqlfiddle |
||||
- golint ./... |
||||
- go vet |
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic |
||||
when: |
||||
event: |
||||
- push |
||||
- tag |
||||
- pull_request |
||||
|
||||
--- |
||||
kind: pipeline |
||||
name: go1.11 |
||||
|
||||
steps: |
||||
- name: test |
||||
pull: default |
||||
image: golang:1.11 |
||||
commands: |
||||
- go get -u golang.org/x/lint/golint |
||||
- golint ./... |
||||
- go vet |
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic |
||||
environment: |
||||
GOPROXY: https://goproxy.cn |
||||
GO111MODULE: "on" |
||||
when: |
||||
event: [ push, tag, pull_request ] |
||||
|
||||
codecov: |
||||
image: robertstettner/drone-codecov |
||||
group: build |
||||
secrets: [ codecov_token ] |
||||
files: |
||||
- coverage.txt |
||||
event: |
||||
- push |
||||
- tag |
||||
- pull_request |
||||
|
||||
--- |
||||
kind: pipeline |
||||
name: go1.12 |
||||
|
||||
steps: |
||||
- name: test |
||||
pull: default |
||||
image: golang:1.12 |
||||
commands: |
||||
- go get -u golang.org/x/lint/golint |
||||
- golint ./... |
||||
- go vet |
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic |
||||
environment: |
||||
GOPROXY: https://goproxy.cn |
||||
GO111MODULE: "on" |
||||
when: |
||||
event: |
||||
- push |
||||
- tag |
||||
- pull_request |
||||
|
||||
--- |
||||
kind: pipeline |
||||
name: go1.13 |
||||
|
||||
steps: |
||||
- name: test |
||||
pull: default |
||||
image: golang:1.13 |
||||
commands: |
||||
- go get -u golang.org/x/lint/golint |
||||
- golint ./... |
||||
- go vet |
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic |
||||
environment: |
||||
GOPROXY: https://goproxy.cn |
||||
GO111MODULE: "on" |
||||
when: |
||||
event: [ push, pull_request ] |
||||
event: |
||||
- push |
||||
- tag |
||||
- pull_request |
@ -0,0 +1,42 @@ |
||||
// 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 |
||||
|
||||
// InnerJoin sets inner join
|
||||
func (b *Builder) InnerJoin(joinTable, joinCond interface{}) *Builder { |
||||
return b.Join("INNER", joinTable, joinCond) |
||||
} |
||||
|
||||
// LeftJoin sets left join SQL
|
||||
func (b *Builder) LeftJoin(joinTable, joinCond interface{}) *Builder { |
||||
return b.Join("LEFT", joinTable, joinCond) |
||||
} |
||||
|
||||
// RightJoin sets right join SQL
|
||||
func (b *Builder) RightJoin(joinTable, joinCond interface{}) *Builder { |
||||
return b.Join("RIGHT", joinTable, joinCond) |
||||
} |
||||
|
||||
// CrossJoin sets cross join SQL
|
||||
func (b *Builder) CrossJoin(joinTable, joinCond interface{}) *Builder { |
||||
return b.Join("CROSS", joinTable, joinCond) |
||||
} |
||||
|
||||
// FullJoin sets full join SQL
|
||||
func (b *Builder) FullJoin(joinTable, joinCond interface{}) *Builder { |
||||
return b.Join("FULL", joinTable, joinCond) |
||||
} |
||||
|
||||
// Join sets join table and conditions
|
||||
func (b *Builder) Join(joinType string, joinTable, 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 |
||||
} |
@ -1,119 +0,0 @@ |
||||
// 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 |
||||
} |
@ -0,0 +1,42 @@ |
||||
// 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 |
||||
|
||||
import ( |
||||
"io" |
||||
"strings" |
||||
) |
||||
|
||||
// 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 { |
||||
*strings.Builder |
||||
args []interface{} |
||||
} |
||||
|
||||
// NewWriter creates a new string writer
|
||||
func NewWriter() *BytesWriter { |
||||
w := &BytesWriter{ |
||||
Builder: &strings.Builder{}, |
||||
} |
||||
return w |
||||
} |
||||
|
||||
// Append appends args to Writer
|
||||
func (w *BytesWriter) Append(args ...interface{}) { |
||||
w.args = append(w.args, args...) |
||||
} |
||||
|
||||
// Args returns args
|
||||
func (w *BytesWriter) Args() []interface{} { |
||||
return w.args |
||||
} |
Loading…
Reference in new issue