Fix join table name quote bug #1534

Merged
lunny merged 4 commits from lunny/fix_join_table_quote into master 2020-02-25 00:01:40 +00:00
18 changed files with 276 additions and 200 deletions

View File

@ -45,11 +45,8 @@ type Dialect interface {
DataSourceName() string
IsReserved(string) bool
Quote(string) string
Quoter() schemas.Quoter
AndStr() string
OrStr() string
EqStr() string
RollBackStr() string
AutoIncrStr() string
@ -101,7 +98,7 @@ type Base struct {
// String generate column description string according dialect
func String(d Dialect, col *schemas.Column) string {
sql := d.Quote(col.Name) + " "
sql := d.Quoter().Quote(col.Name) + " "
sql += d.SQLType(col) + " "
@ -129,7 +126,7 @@ func String(d Dialect, col *schemas.Column) string {
// StringNoPk generate column description string according dialect without primary keys
func StringNoPk(d Dialect, col *schemas.Column) string {
sql := d.Quote(col.Name) + " "
sql := d.Quoter().Quote(col.Name) + " "
sql += d.SQLType(col) + " "
@ -186,18 +183,6 @@ func (b *Base) DataSourceName() string {
return b.dataSourceName
}
func (b *Base) AndStr() string {
return "AND"
}
func (b *Base) OrStr() string {
return "OR"
}
func (b *Base) EqStr() string {
return "="
}
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}
@ -207,7 +192,7 @@ func (db *Base) SupportDropIfExists() bool {
}
func (db *Base) DropTableSQL(tableName string) string {
quote := db.dialect.Quote
quote := db.dialect.Quoter().Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
}
@ -226,14 +211,15 @@ func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
}
func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
quote := db.dialect.Quoter().Quote
query := fmt.Sprintf(
"SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?",
db.dialect.Quote("COLUMN_NAME"),
db.dialect.Quote("INFORMATION_SCHEMA"),
db.dialect.Quote("COLUMNS"),
db.dialect.Quote("TABLE_SCHEMA"),
db.dialect.Quote("TABLE_NAME"),
db.dialect.Quote("COLUMN_NAME"),
quote("COLUMN_NAME"),
quote("INFORMATION_SCHEMA"),
quote("COLUMNS"),
quote("TABLE_SCHEMA"),
quote("TABLE_NAME"),
quote("COLUMN_NAME"),
)
return db.HasRecords(query, db.uri.DBName, tableName, colName)
}
@ -263,8 +249,7 @@ func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, cha
}*/
func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
quotes := db.dialect.Quote("")
quote := db.dialect.Quote
quoter := db.dialect.Quoter()
var unique string
var idxName string
if index.Type == schemas.UniqueType {
@ -272,12 +257,12 @@ func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
}
idxName = index.XName(tableName)
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
quote(idxName), quote(tableName),
quote(strings.Join(index.Cols, fmt.Sprintf("%c,%c", quotes[1], quotes[0]))))
quoter.Quote(idxName), quoter.Quote(tableName),
quoter.Quote(strings.Join(index.Cols, quoter.ReverseQuote(","))))
}
func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string {
quote := db.dialect.Quote
quote := db.dialect.Quoter().Quote
var name string
if index.IsRegular {
name = index.XName(tableName)
@ -298,11 +283,10 @@ func (b *Base) CreateTableSQL(table *schemas.Table, tableName, storeEngine, char
tableName = table.Name
}
sql += b.dialect.Quote(tableName)
quoter := b.dialect.Quoter()
sql += quoter.Quote(tableName)
sql += " ("
quotes := b.dialect.Quote("")
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
@ -322,7 +306,7 @@ func (b *Base) CreateTableSQL(table *schemas.Table, tableName, storeEngine, char
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += b.dialect.Quote(strings.Join(pkList, fmt.Sprintf("%c,%c", quotes[1], quotes[0])))
sql += quoter.Quote(strings.Join(pkList, quoter.ReverseQuote(",")))
sql += " ), "
}

View File

@ -21,11 +21,12 @@ type QuoteFilter struct {
}
func (s *QuoteFilter) Do(sql string, dialect Dialect, table *schemas.Table) string {
dummy := dialect.Quote("")
if len(dummy) != 2 {
quoter := dialect.Quoter()
if quoter.IsEmpty() {
return sql
}
prefix, suffix := dummy[0], dummy[1]
prefix, suffix := quoter[0][0], quoter[1][0]
raw := []byte(sql)
for i, cnt := 0, 0; i < len(raw); i = i + 1 {
if raw[i] == '`' {
@ -38,32 +39,7 @@ func (s *QuoteFilter) Do(sql string, dialect Dialect, table *schemas.Table) stri
}
}
return string(raw)
}
// IdFilter filter SQL replace (id) to primary key column name
type IdFilter struct {
}
type Quoter struct {
dialect Dialect
}
func NewQuoter(dialect Dialect) *Quoter {
return &Quoter{dialect}
}
func (q *Quoter) Quote(content string) string {
return q.dialect.Quote(content)
}
func (i *IdFilter) Do(sql string, dialect Dialect, table *schemas.Table) string {
quoter := NewQuoter(dialect)
if table != nil && len(table.PrimaryKeys) == 1 {
sql = strings.Replace(sql, " `(id)` ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
sql = strings.Replace(sql, " "+quoter.Quote("(id)")+" ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
return strings.Replace(sql, " (id) ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
}
return sql
}
// SeqFilter filter SQL replace ?, ? ... to $1, $2 ...

View File

@ -286,8 +286,8 @@ func (db *mssql) IsReserved(name string) bool {
return ok
}
func (db *mssql) Quote(name string) string {
return "[" + name + "]"
func (db *mssql) Quoter() schemas.Quoter {
return schemas.Quoter{"[", "]"}
}
func (db *mssql) SupportEngine() bool {
@ -503,7 +503,7 @@ func (db *mssql) CreateTableSQL(table *schemas.Table, tableName, storeEngine, ch
sql = "IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '" + tableName + "' ) CREATE TABLE "
sql += db.Quote(tableName) + " ("
sql += db.Quoter().Quote(tableName) + " ("
pkList := table.PrimaryKeys
@ -534,7 +534,7 @@ func (db *mssql) ForUpdateSQL(query string) string {
}
func (db *mssql) Filters() []Filter {
return []Filter{&IdFilter{}, &QuoteFilter{}}
return []Filter{&QuoteFilter{}}
}
type odbcDriver struct {

View File

@ -275,8 +275,8 @@ func (db *mysql) IsReserved(name string) bool {
return ok
}
func (db *mysql) Quote(name string) string {
return "`" + name + "`"
func (db *mysql) Quoter() schemas.Quoter {
return schemas.Quoter{"`", "`"}
}
func (db *mysql) SupportEngine() bool {
@ -512,9 +512,9 @@ func (db *mysql) CreateTableSQL(table *schemas.Table, tableName, storeEngine, ch
tableName = table.Name
}
quotes := db.Quote("")
quoter := db.Quoter()
sql += db.Quote(tableName)
sql += quoter.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
@ -536,7 +536,7 @@ func (db *mysql) CreateTableSQL(table *schemas.Table, tableName, storeEngine, ch
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += db.Quote(strings.Join(pkList, fmt.Sprintf("%c,%c", quotes[1], quotes[0])))
sql += quoter.Quote(strings.Join(pkList, quoter.ReverseQuote(",")))
sql += " ), "
}
@ -562,7 +562,7 @@ func (db *mysql) CreateTableSQL(table *schemas.Table, tableName, storeEngine, ch
}
func (db *mysql) Filters() []Filter {
return []Filter{&IdFilter{}}
return []Filter{}
}
type mymysqlDriver struct {

View File

@ -552,8 +552,8 @@ func (db *oracle) IsReserved(name string) bool {
return ok
}
func (db *oracle) Quote(name string) string {
return "[" + name + "]"
func (db *oracle) Quoter() schemas.Quoter {
return schemas.Quoter{"[", "]"}
}
func (db *oracle) SupportEngine() bool {
@ -582,7 +582,8 @@ func (db *oracle) CreateTableSQL(table *schemas.Table, tableName, storeEngine, c
tableName = table.Name
}
sql += db.Quote(tableName) + " ("
quoter := db.Quoter()
sql += quoter.Quote(tableName) + " ("
pkList := table.PrimaryKeys
@ -597,11 +598,9 @@ func (db *oracle) CreateTableSQL(table *schemas.Table, tableName, storeEngine, c
sql += ", "
}
quotes := db.Quote("")
if len(pkList) > 0 {
sql += "PRIMARY KEY ( "
sql += db.Quote(strings.Join(pkList, fmt.Sprintf("%c,%c", quotes[1], quotes[0])))
sql += quoter.Quote(strings.Join(pkList, quoter.ReverseQuote(",")))
sql += " ), "
}
@ -849,7 +848,7 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*schemas.Index, error
}
func (db *oracle) Filters() []Filter {
return []Filter{&QuoteFilter{}, &SeqFilter{Prefix: ":", Start: 1}, &IdFilter{}}
return []Filter{&QuoteFilter{}, &SeqFilter{Prefix: ":", Start: 1}}
}
type goracleDriver struct {

View File

@ -859,9 +859,8 @@ func (db *postgres) IsReserved(name string) bool {
return ok
}
func (db *postgres) Quote(name string) string {
name = strings.Replace(name, ".", `"."`, -1)
return "\"" + name + "\""
func (db *postgres) Quoter() schemas.Quoter {
return schemas.Quoter{`"`, `"`}
}
func (db *postgres) AutoIncrStr() string {
@ -911,7 +910,6 @@ func (db *postgres) ModifyColumnSQL(tableName string, col *schemas.Column) strin
}
func (db *postgres) DropIndexSQL(tableName string, index *schemas.Index) string {
quote := db.Quote
idxName := index.Name
tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".")
@ -928,7 +926,7 @@ func (db *postgres) DropIndexSQL(tableName string, index *schemas.Index) string
if db.uri.Schema != "" {
idxName = db.uri.Schema + "." + idxName
}
return fmt.Sprintf("DROP INDEX %v", quote(idxName))
return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName))
}
func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
@ -1161,7 +1159,7 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*schemas.Index, err
}
func (db *postgres) Filters() []Filter {
return []Filter{&IdFilter{}, &QuoteFilter{}, &SeqFilter{Prefix: "$", Start: 1}}
return []Filter{&QuoteFilter{}, &SeqFilter{Prefix: "$", Start: 1}}
}
type pqDriver struct {

View File

@ -199,8 +199,8 @@ func (db *sqlite3) IsReserved(name string) bool {
return ok
}
func (db *sqlite3) Quote(name string) string {
return "`" + name + "`"
func (db *sqlite3) Quoter() schemas.Quoter {
return schemas.Quoter{"`", "`"}
}
func (db *sqlite3) AutoIncrStr() string {
@ -231,7 +231,6 @@ func (db *sqlite3) TableCheckSQL(tableName string) (string, []interface{}) {
func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string {
// var unique string
quote := db.Quote
idxName := index.Name
if !strings.HasPrefix(idxName, "UQE_") &&
@ -242,7 +241,7 @@ func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string {
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
}
}
return fmt.Sprintf("DROP INDEX %v", quote(idxName))
return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName))
}
func (db *sqlite3) ForUpdateSQL(query string) string {
@ -478,7 +477,7 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*schemas.Index, erro
}
func (db *sqlite3) Filters() []Filter {
return []Filter{&IdFilter{}}
return []Filter{}
}
type sqlite3Driver struct {

View File

@ -193,10 +193,7 @@ func (engine *Engine) SupportInsertMany() bool {
func (engine *Engine) quoteColumns(columnStr string) string {
columns := strings.Split(columnStr, ",")
for i := 0; i < len(columns); i++ {
columns[i] = engine.Quote(strings.TrimSpace(columns[i]))
}
return strings.Join(columns, ",")
return engine.dialect.Quoter().Join(columns, ",")
}
// Quote Use QuoteStr quote the string sql
@ -222,53 +219,13 @@ func (engine *Engine) QuoteTo(buf *strings.Builder, value string) {
if value == "" {
return
}
quoteTo(buf, engine.dialect.Quote(""), value)
}
func quoteTo(buf *strings.Builder, quotePair string, value string) {
if len(quotePair) < 2 { // no quote
_, _ = buf.WriteString(value)
return
}
prefix, suffix := quotePair[0], quotePair[1]
i := 0
for i < len(value) {
// start of a token; might be already quoted
if value[i] == '.' {
_ = buf.WriteByte('.')
i++
} else if value[i] == prefix || value[i] == '`' {
// Has quotes; skip/normalize `name` to prefix+name+sufix
var ch byte
if value[i] == prefix {
ch = suffix
} else {
ch = '`'
}
i++
_ = buf.WriteByte(prefix)
for ; i < len(value) && value[i] != ch; i++ {
_ = buf.WriteByte(value[i])
}
_ = buf.WriteByte(suffix)
i++
} else {
// Requires quotes
_ = buf.WriteByte(prefix)
for ; i < len(value) && value[i] != '.'; i++ {
_ = buf.WriteByte(value[i])
}
_ = buf.WriteByte(suffix)
}
}
engine.dialect.Quoter().QuoteTo(buf, value)
}
/*
func (engine *Engine) quote(sql string) string {
return engine.dialect.Quote(sql)
}
}*/
// SqlType will be deprecated, please use SQLType instead
//
@ -530,8 +487,8 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...dia
}
cols := table.ColumnsSeq()
colNames := engine.dialect.Quote(strings.Join(cols, engine.dialect.Quote(", ")))
destColNames := dialect.Quote(strings.Join(cols, dialect.Quote(", ")))
colNames := engine.dialect.Quoter().Join(cols, ", ")
destColNames := dialect.Quoter().Join(cols, ", ")
rows, err := engine.DB().Query("SELECT " + colNames + " FROM " + engine.Quote(table.Name))
if err != nil {
@ -546,7 +503,7 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...dia
return err
}
_, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(table.Name)+" ("+destColNames+") VALUES (")
_, err = io.WriteString(w, "INSERT INTO "+dialect.Quoter().Quote(table.Name)+" ("+destColNames+") VALUES (")
if err != nil {
return err
}
@ -617,7 +574,7 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...dia
// FIXME: Hack for postgres
if string(dialect.DBType()) == schemas.POSTGRES && table.AutoIncrColumn() != nil {
_, err = io.WriteString(w, "SELECT setval('"+table.Name+"_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") + 1 FROM "+dialect.Quote(table.Name)+"), 1), false);\n")
_, err = io.WriteString(w, "SELECT setval('"+table.Name+"_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") + 1 FROM "+dialect.Quoter().Quote(table.Name)+"), 1), false);\n")
if err != nil {
return err
}

165
schemas/quote.go Normal file
View File

@ -0,0 +1,165 @@
// Copyright 2020 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 schemas
import (
"fmt"
"strings"
)
// Quoter represents two quote characters
type Quoter [2]string
// CommonQuoter represetns a common quoter
var CommonQuoter = Quoter{"`", "`"}
func (q Quoter) IsEmpty() bool {
return q[0] == "" && q[1] == ""
}
func (q Quoter) Quote(s string) string {
var buf strings.Builder
q.QuoteTo(&buf, s)
return buf.String()
}
func (q Quoter) Replace(sql string, newQuoter Quoter) string {
if q.IsEmpty() {
return sql
}
if newQuoter.IsEmpty() {
var buf strings.Builder
for i := 0; i < len(sql); i = i + 1 {
if sql[i] != q[0][0] && sql[i] != q[1][0] {
_ = buf.WriteByte(sql[i])
}
}
return buf.String()
}
prefix, suffix := newQuoter[0][0], newQuoter[1][0]
var buf strings.Builder
for i, cnt := 0, 0; i < len(sql); i = i + 1 {
if cnt == 0 && sql[i] == q[0][0] {
_ = buf.WriteByte(prefix)
cnt = 1
} else if cnt == 1 && sql[i] == q[1][0] {
_ = buf.WriteByte(suffix)
cnt = 0
} else {
_ = buf.WriteByte(sql[i])
}
}
return buf.String()
}
func (q Quoter) ReverseQuote(s string) string {
reverseQuoter := Quoter{q[1], q[0]}
return reverseQuoter.Quote(s)
}
// Trim removes quotes from s
func (q Quoter) Trim(s string) string {
if len(s) < 2 {
return s
}
if s[0:1] == q[0] {
s = s[1:]
}
if len(s) > 0 && s[len(s)-1:] == q[0] {
return s[:len(s)-1]
}
return s
}
func TrimSpaceJoin(a []string, sep string) string {
switch len(a) {
case 0:
return ""
case 1:
return a[0]
}
n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ {
n += len(a[i])
}
var b strings.Builder
b.Grow(n)
b.WriteString(strings.TrimSpace(a[0]))
for _, s := range a[1:] {
b.WriteString(sep)
b.WriteString(strings.TrimSpace(s))
}
return b.String()
}
func (q Quoter) Join(s []string, splitter string) string {
//return fmt.Sprintf("%s%s%s", q[0], TrimSpaceJoin(s, fmt.Sprintf("%s%s%s", q[1], splitter, q[0])), q[1])
return q.Quote(TrimSpaceJoin(s, fmt.Sprintf("%s%s%s", q[1], splitter, q[0])))
}
func (q Quoter) QuoteTo(buf *strings.Builder, value string) {
if q.IsEmpty() {
buf.WriteString(value)
return
}
prefix, suffix := q[0][0], q[1][0]
lastCh := 0 // 0 prefix, 1 char, 2 suffix
i := 0
for i < len(value) {
// start of a token; might be already quoted
if value[i] == '.' {
_ = buf.WriteByte('.')
lastCh = 1
i++
} else if value[i] == prefix || value[i] == '`' {
// Has quotes; skip/normalize `name` to prefix+name+sufix
var ch byte
if value[i] == prefix {
ch = suffix
} else {
ch = '`'
}
_ = buf.WriteByte(prefix)
i++
lastCh = 0
for ; i < len(value) && value[i] != ch && value[i] != ' '; i++ {
_ = buf.WriteByte(value[i])
lastCh = 1
}
_ = buf.WriteByte(suffix)
lastCh = 2
i++
} else if value[i] == ' ' {
if lastCh != 2 {
_ = buf.WriteByte(suffix)
lastCh = 2
}
// a AS b or a b
for ; i < len(value); i++ {
if value[i] != ' ' && value[i-1] == ' ' && (len(value) > i+1 && !strings.EqualFold(value[i:i+2], "AS")) {
break
}
_ = buf.WriteByte(value[i])
lastCh = 1
}
} else {
// Requires quotes
_ = buf.WriteByte(prefix)
for ; i < len(value) && value[i] != '.' && value[i] != ' '; i++ {
_ = buf.WriteByte(value[i])
lastCh = 1
}
_ = buf.WriteByte(suffix)
lastCh = 2
}
}
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
package schemas
import (
"strings"
@ -12,10 +12,11 @@ import (
)
func TestQuoteTo(t *testing.T) {
var quoter = Quoter{"[", "]"}
test := func(t *testing.T, expected string, value string) {
buf := &strings.Builder{}
quoteTo(buf, "[]", value)
quoter.QuoteTo(buf, value)
assert.EqualValues(t, expected, buf.String())
}
@ -35,7 +36,12 @@ func TestQuoteTo(t *testing.T) {
test(t, `["myschema].[mytable"]`, `"myschema.mytable"`)
test(t, "[message_user] AS [sender]", "`message_user` AS `sender`")
assert.EqualValues(t, "[a],[b]", quoter.Join([]string{"a", " b"}, ","))
buf := &strings.Builder{}
quoteTo(buf, "", "noquote")
quoter = Quoter{"", ""}
quoter.QuoteTo(buf, "noquote")
assert.EqualValues(t, "noquote", buf.String())
}

View File

@ -137,13 +137,13 @@ func TestIn(t *testing.T) {
idsStr = idsStr[:len(idsStr)-1]
users := make([]Userinfo, 0)
err = testEngine.In("(id)", ids[0], ids[1], ids[2]).Find(&users)
err = testEngine.In("id", ids[0], ids[1], ids[2]).Find(&users)
assert.NoError(t, err)
fmt.Println(users)
assert.EqualValues(t, 3, len(users))
users = make([]Userinfo, 0)
err = testEngine.In("(id)", ids).Find(&users)
err = testEngine.In("id", ids).Find(&users)
assert.NoError(t, err)
fmt.Println(users)
assert.EqualValues(t, 3, len(users))
@ -161,7 +161,7 @@ func TestIn(t *testing.T) {
idsInterface = append(idsInterface, id)
}
err = testEngine.Where(department+" = ?", "dev").In("(id)", idsInterface...).Find(&users)
err = testEngine.Where(department+" = ?", "dev").In("id", idsInterface...).Find(&users)
assert.NoError(t, err)
fmt.Println(users)
assert.EqualValues(t, 3, len(users))
@ -175,11 +175,11 @@ func TestIn(t *testing.T) {
dev := testEngine.GetColumnMapper().Obj2Table("Dev")
err = testEngine.In("(id)", 1).In("(id)", 2).In(department, dev).Find(&users)
err = testEngine.In("id", 1).In("id", 2).In(department, dev).Find(&users)
assert.NoError(t, err)
fmt.Println(users)
cnt, err = testEngine.In("(id)", ids[0]).Update(&Userinfo{Departname: "dev-"})
cnt, err = testEngine.In("id", ids[0]).Update(&Userinfo{Departname: "dev-"})
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)
@ -189,11 +189,11 @@ func TestIn(t *testing.T) {
assert.True(t, has)
assert.EqualValues(t, "dev-", user.Departname)
cnt, err = testEngine.In("(id)", ids[0]).Update(&Userinfo{Departname: "dev"})
cnt, err = testEngine.In("id", ids[0]).Update(&Userinfo{Departname: "dev"})
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)
cnt, err = testEngine.In("(id)", ids[1]).Delete(&Userinfo{})
cnt, err = testEngine.In("id", ids[1]).Delete(&Userinfo{})
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)
}

View File

@ -77,14 +77,14 @@ func TestWhere(t *testing.T) {
assertSync(t, new(Userinfo))
users := make([]Userinfo, 0)
err := testEngine.Where("(id) > ?", 2).Find(&users)
err := testEngine.Where("id > ?", 2).Find(&users)
if err != nil {
t.Error(err)
panic(err)
}
fmt.Println(users)
err = testEngine.Where("(id) > ?", 2).And("(id) < ?", 10).Find(&users)
err = testEngine.Where("id > ?", 2).And("id < ?", 10).Find(&users)
if err != nil {
t.Error(err)
panic(err)
@ -312,12 +312,12 @@ func TestOrderSameMapper(t *testing.T) {
assertSync(t, new(Userinfo))
users := make([]Userinfo, 0)
err := testEngine.OrderBy("(id) desc").Find(&users)
err := testEngine.OrderBy("id desc").Find(&users)
assert.NoError(t, err)
fmt.Println(users)
users2 := make([]Userinfo, 0)
err = testEngine.Asc("(id)", "Username").Desc("Height").Find(&users2)
err = testEngine.Asc("id", "Username").Desc("Height").Find(&users2)
assert.NoError(t, err)
fmt.Println(users2)
}
@ -790,8 +790,12 @@ func TestFindJoin(t *testing.T) {
DeviceId int64
}
type Order struct {
Id int64
}
assert.NoError(t, prepareEngine())
assertSync(t, new(SceneItem), new(DeviceUserPrivrels))
assertSync(t, new(SceneItem), new(DeviceUserPrivrels), new(Order))
var scenes []SceneItem
err := testEngine.Join("LEFT OUTER", "device_user_privrels", "device_user_privrels.device_id=scene_item.device_id").
@ -802,6 +806,10 @@ func TestFindJoin(t *testing.T) {
err = testEngine.Join("LEFT OUTER", new(DeviceUserPrivrels), "device_user_privrels.device_id=scene_item.device_id").
Where("scene_item.type=?", 3).Or("device_user_privrels.user_id=?", 339).Find(&scenes)
assert.NoError(t, err)
scenes = make([]SceneItem, 0)
err = testEngine.Join("INNER", "order", "`scene_item`.device_id=`order`.id").Find(&scenes)
assert.NoError(t, err)
}
func TestJoinFindLimit(t *testing.T) {

View File

@ -201,7 +201,7 @@ func TestInsertDefault(t *testing.T) {
_, err = testEngine.Omit(testEngine.GetColumnMapper().Obj2Table("Status")).Insert(&di2)
assert.NoError(t, err)
has, err := testEngine.Desc("(id)").Get(di)
has, err := testEngine.Desc("id").Get(di)
assert.NoError(t, err)
if !has {
err = errors.New("error with no data")
@ -247,7 +247,7 @@ func TestInsertDefault2(t *testing.T) {
t.Error(err)
}
has, err := testEngine.Desc("(id)").Get(di)
has, err := testEngine.Desc("id").Get(di)
if err != nil {
t.Error(err)
}
@ -257,7 +257,7 @@ func TestInsertDefault2(t *testing.T) {
panic(err)
}
has, err = testEngine.NoAutoCondition().Desc("(id)").Get(&di2)
has, err = testEngine.NoAutoCondition().Desc("id").Get(&di2)
if err != nil {
t.Error(err)
}
@ -330,7 +330,7 @@ func TestInsertCreated(t *testing.T) {
t.Fatal(err)
}
has, err := testEngine.Desc("(id)").Get(di)
has, err := testEngine.Desc("id").Get(di)
if err != nil {
t.Fatal(err)
}
@ -352,7 +352,7 @@ func TestInsertCreated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
has, err = testEngine.Desc("(id)").Get(di2)
has, err = testEngine.Desc("id").Get(di2)
if err != nil {
t.Fatal(err)
}
@ -374,7 +374,7 @@ func TestInsertCreated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
has, err = testEngine.Desc("(id)").Get(di3)
has, err = testEngine.Desc("id").Get(di3)
if err != nil {
t.Fatal(err)
}
@ -396,7 +396,7 @@ func TestInsertCreated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
has, err = testEngine.Desc("(id)").Get(di4)
has, err = testEngine.Desc("id").Get(di4)
if err != nil {
t.Fatal(err)
}
@ -418,7 +418,7 @@ func TestInsertCreated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
has, err = testEngine.Desc("(id)").Get(di5)
has, err = testEngine.Desc("id").Get(di5)
if err != nil {
t.Fatal(err)
}
@ -442,7 +442,7 @@ func TestInsertCreated(t *testing.T) {
t.Fatal(err)
}
has, err = testEngine.Desc("(id)").Get(di6)
has, err = testEngine.Desc("id").Get(di6)
if err != nil {
t.Fatal(err)
}
@ -517,7 +517,7 @@ func TestCreatedJsonTime(t *testing.T) {
if err != nil {
t.Fatal(err)
}
has, err := testEngine.Desc("(id)").Get(di5)
has, err := testEngine.Desc("id").Get(di5)
if err != nil {
t.Fatal(err)
}

View File

@ -17,15 +17,12 @@ func TestTransaction(t *testing.T) {
assert.NoError(t, prepareEngine())
assertSync(t, new(Userinfo))
counter := func() {
total, err := testEngine.Count(&Userinfo{})
if err != nil {
t.Error(err)
}
fmt.Printf("----now total %v records\n", total)
counter := func(t *testing.T) {
_, err := testEngine.Count(&Userinfo{})
assert.NoError(t, err)
}
counter()
counter(t)
//defer counter()
session := testEngine.NewSession()
@ -39,7 +36,7 @@ func TestTransaction(t *testing.T) {
assert.NoError(t, err)
user2 := Userinfo{Username: "yyy"}
_, err = session.Where("(id) = ?", 0).Update(&user2)
_, err = session.Where("id = ?", 0).Update(&user2)
assert.NoError(t, err)
_, err = session.Delete(&user2)
@ -119,7 +116,7 @@ func TestCombineTransactionSameMapper(t *testing.T) {
assert.NoError(t, err)
user2 := Userinfo{Username: "zzz"}
_, err = session.Where("(id) = ?", 0).Update(&user2)
_, err = session.Where("id = ?", 0).Update(&user2)
assert.NoError(t, err)
_, err = session.Exec("delete from "+testEngine.TableName("`Userinfo`", true)+" where `Username` = ?", user2.Username)

View File

@ -137,7 +137,7 @@ func TestForUpdate(t *testing.T) {
// use lock
fList := make([]ForUpdate, 0)
session1.ForUpdate()
session1.Where("(id) = ?", 1)
session1.Where("id = ?", 1)
err = session1.Find(&fList)
switch {
case err != nil:
@ -158,7 +158,7 @@ func TestForUpdate(t *testing.T) {
wg.Add(1)
go func() {
f2 := new(ForUpdate)
session2.Where("(id) = ?", 1).ForUpdate()
session2.Where("id = ?", 1).ForUpdate()
has, err := session2.Get(f2) // wait release lock
switch {
case err != nil:
@ -175,7 +175,7 @@ func TestForUpdate(t *testing.T) {
wg.Add(1)
go func() {
f3 := new(ForUpdate)
session3.Where("(id) = ?", 1)
session3.Where("id = ?", 1)
has, err := session3.Get(f3) // wait release lock
switch {
case err != nil:
@ -193,7 +193,7 @@ func TestForUpdate(t *testing.T) {
f := new(ForUpdate)
f.Name = "updated by session1"
session1.Where("(id) = ?", 1)
session1.Where("id = ?", 1)
session1.Update(f)
// release lock

View File

@ -618,7 +618,7 @@ func (statement *Statement) Cols(columns ...string) *Statement {
newColumns := statement.colmap2NewColsWithQuote()
statement.ColumnStr = strings.Join(newColumns, ", ")
statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.quote("*"), "*", -1)
statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.dialect.Quoter().Quote("*"), "*", -1)
return statement
}
@ -765,6 +765,11 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition
statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
default:
tbName := statement.Engine.TableName(tablename, true)
if !isSubQuery(tbName) {
var buf strings.Builder
statement.Engine.QuoteTo(&buf, tbName)
tbName = buf.String()
}
fmt.Fprintf(&buf, "%s ON %v", tbName, condition)
}

View File

@ -9,6 +9,7 @@ import (
"strings"
"xorm.io/builder"
"xorm.io/xorm/schemas"
)
type ErrUnsupportedExprType struct {
@ -40,7 +41,7 @@ func (exprs *exprParams) addParam(colName string, arg interface{}) {
func (exprs *exprParams) isColExist(colName string) bool {
for _, name := range exprs.colNames {
if strings.EqualFold(trimQuote(name), trimQuote(colName)) {
if strings.EqualFold(schemas.CommonQuoter.Trim(name), schemas.CommonQuoter.Trim(colName)) {
return true
}
}

View File

@ -1,19 +0,0 @@
// 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
}