mirror of https://github.com/go-gorm/gorm.git
Refactor clauses
This commit is contained in:
parent
38d1cd2bf1
commit
6937d713c3
|
@ -24,42 +24,46 @@ type Builder interface {
|
||||||
|
|
||||||
// Clause
|
// Clause
|
||||||
type Clause struct {
|
type Clause struct {
|
||||||
Name string // WHERE
|
Name string // WHERE
|
||||||
Priority float64
|
BeforeExpression Expression
|
||||||
BeforeExpressions []Expression
|
AfterNameExpression Expression
|
||||||
AfterNameExpressions []Expression
|
AfterExpression Expression
|
||||||
AfterExpressions []Expression
|
Expression Expression
|
||||||
Expression Expression
|
Builder ClauseBuilder
|
||||||
Builder ClauseBuilder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build build clause
|
// Build build clause
|
||||||
func (c Clause) Build(builder Builder) {
|
func (c Clause) Build(builder Builder) {
|
||||||
if c.Builder != nil {
|
if c.Builder != nil {
|
||||||
c.Builder(c, builder)
|
c.Builder(c, builder)
|
||||||
} else {
|
} else if c.Expression != nil {
|
||||||
builders := c.BeforeExpressions
|
if c.BeforeExpression != nil {
|
||||||
|
c.BeforeExpression.Build(builder)
|
||||||
|
builder.WriteByte(' ')
|
||||||
|
}
|
||||||
|
|
||||||
if c.Name != "" {
|
if c.Name != "" {
|
||||||
builders = append(builders, Expr{SQL: c.Name})
|
builder.WriteString(c.Name)
|
||||||
|
builder.WriteByte(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
builders = append(builders, c.AfterNameExpressions...)
|
if c.AfterNameExpression != nil {
|
||||||
if c.Expression != nil {
|
c.BeforeExpression.Build(builder)
|
||||||
builders = append(builders, c.Expression)
|
builder.WriteByte(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, expr := range append(builders, c.AfterExpressions...) {
|
c.Expression.Build(builder)
|
||||||
if idx != 0 {
|
|
||||||
builder.WriteByte(' ')
|
if c.AfterExpression != nil {
|
||||||
}
|
builder.WriteByte(' ')
|
||||||
expr.Build(builder)
|
c.AfterExpression.Build(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PrimaryKey string = "@@@priamry_key@@@"
|
PrimaryKey string = "@@@py@@@" // primary key
|
||||||
CurrentTable string = "@@@table@@@"
|
CurrentTable string = "@@@ct@@@" // current table
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFor(t *testing.T) {
|
func TestLocking(t *testing.T) {
|
||||||
results := []struct {
|
results := []struct {
|
||||||
Clauses []clause.Interface
|
Clauses []clause.Interface
|
||||||
Result string
|
Result string
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (where Where) Name() string {
|
||||||
func (where Where) Build(builder Builder) {
|
func (where Where) Build(builder Builder) {
|
||||||
// Switch position if the first query expression is a single Or condition
|
// Switch position if the first query expression is a single Or condition
|
||||||
for idx, expr := range where.Exprs {
|
for idx, expr := range where.Exprs {
|
||||||
if v, ok := expr.(OrConditions); (!ok && expr != nil) || len(v.Exprs) > 1 {
|
if v, ok := expr.(OrConditions); !ok || len(v.Exprs) > 1 {
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
where.Exprs[0], where.Exprs[idx] = where.Exprs[idx], where.Exprs[0]
|
where.Exprs[0], where.Exprs[idx] = where.Exprs[idx], where.Exprs[0]
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,15 @@ func (where Where) Build(builder Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, expr := range where.Exprs {
|
for idx, expr := range where.Exprs {
|
||||||
if expr != nil {
|
if idx > 0 {
|
||||||
if idx > 0 {
|
if v, ok := expr.(OrConditions); ok && len(v.Exprs) == 1 {
|
||||||
if v, ok := expr.(OrConditions); ok && len(v.Exprs) == 1 {
|
builder.WriteString(" OR ")
|
||||||
builder.WriteString(" OR ")
|
} else {
|
||||||
} else {
|
builder.WriteString(" AND ")
|
||||||
builder.WriteString(" AND ")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.Build(builder)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr.Build(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -27,7 +27,7 @@ func TestWhere(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Where{
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Where{
|
||||||
Exprs: []clause.Expression{clause.Or(), clause.Or(clause.Neq{Column: "name", Value: "jinzhu"}), clause.Eq{Column: clause.PrimaryColumn, Value: "1"}, clause.Gt{Column: "age", Value: 18}},
|
Exprs: []clause.Expression{clause.Or(clause.Neq{Column: "name", Value: "jinzhu"}), clause.Eq{Column: clause.PrimaryColumn, Value: "1"}, clause.Gt{Column: "age", Value: 18}},
|
||||||
}},
|
}},
|
||||||
"SELECT * FROM `users` WHERE `users`.`id` = ? OR `name` <> ? AND `age` > ?", []interface{}{"1", "jinzhu", 18},
|
"SELECT * FROM `users` WHERE `users`.`id` = ? OR `name` <> ? AND `age` > ?", []interface{}{"1", "jinzhu", 18},
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,13 +32,14 @@ func (db *DB) Save(value interface{}) (tx *DB) {
|
||||||
for idx, pf := range tx.Statement.Schema.PrimaryFields {
|
for idx, pf := range tx.Statement.Schema.PrimaryFields {
|
||||||
if pv, isZero := pf.ValueOf(reflectValue); isZero {
|
if pv, isZero := pf.ValueOf(reflectValue); isZero {
|
||||||
tx.callbacks.Create().Execute(tx)
|
tx.callbacks.Create().Execute(tx)
|
||||||
where.Exprs[idx] = clause.Eq{Column: pf.DBName, Value: pv}
|
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
where.Exprs[idx] = clause.Eq{Column: pf.DBName, Value: pv}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tx.Statement.AddClause(where)
|
tx.Statement.AddClause(where)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tx.Statement.Selects) == 0 {
|
if len(tx.Statement.Selects) == 0 {
|
||||||
|
|
16
statement.go
16
statement.go
|
@ -201,19 +201,19 @@ func (stmt *Statement) AddVar(writer clause.Writer, vars ...interface{}) {
|
||||||
func (stmt *Statement) AddClause(v clause.Interface) {
|
func (stmt *Statement) AddClause(v clause.Interface) {
|
||||||
if optimizer, ok := v.(StatementModifier); ok {
|
if optimizer, ok := v.(StatementModifier); ok {
|
||||||
optimizer.ModifyStatement(stmt)
|
optimizer.ModifyStatement(stmt)
|
||||||
|
} else {
|
||||||
|
c, ok := stmt.Clauses[v.Name()]
|
||||||
|
if !ok {
|
||||||
|
c.Name = v.Name()
|
||||||
|
}
|
||||||
|
v.MergeClause(&c)
|
||||||
|
stmt.Clauses[v.Name()] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
c, ok := stmt.Clauses[v.Name()]
|
|
||||||
if !ok {
|
|
||||||
c.Name = v.Name()
|
|
||||||
}
|
|
||||||
v.MergeClause(&c)
|
|
||||||
stmt.Clauses[v.Name()] = c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddClauseIfNotExists add clause if not exists
|
// AddClauseIfNotExists add clause if not exists
|
||||||
func (stmt *Statement) AddClauseIfNotExists(v clause.Interface) {
|
func (stmt *Statement) AddClauseIfNotExists(v clause.Interface) {
|
||||||
if c, ok := stmt.Clauses[v.Name()]; !ok && c.Expression == nil {
|
if c, ok := stmt.Clauses[v.Name()]; !ok || c.Expression == nil {
|
||||||
stmt.AddClause(v)
|
stmt.AddClause(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue