Refactor clauses

This commit is contained in:
Jinzhu 2020-06-06 22:52:08 +08:00
parent 38d1cd2bf1
commit 6937d713c3
6 changed files with 46 additions and 43 deletions

View File

@ -25,10 +25,9 @@ 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
} }
@ -37,29 +36,34 @@ type Clause struct {
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 {
if c.Name != "" { c.BeforeExpression.Build(builder)
builders = append(builders, Expr{SQL: c.Name})
}
builders = append(builders, c.AfterNameExpressions...)
if c.Expression != nil {
builders = append(builders, c.Expression)
}
for idx, expr := range append(builders, c.AfterExpressions...) {
if idx != 0 {
builder.WriteByte(' ') builder.WriteByte(' ')
} }
expr.Build(builder)
if c.Name != "" {
builder.WriteString(c.Name)
builder.WriteByte(' ')
}
if c.AfterNameExpression != nil {
c.BeforeExpression.Build(builder)
builder.WriteByte(' ')
}
c.Expression.Build(builder)
if c.AfterExpression != nil {
builder.WriteByte(' ')
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 (

View File

@ -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

View File

@ -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,7 +23,6 @@ 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 ")
@ -34,7 +33,6 @@ func (where Where) Build(builder Builder) {
expr.Build(builder) expr.Build(builder)
} }
}
return return
} }

View File

@ -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},
}, },

View File

@ -32,14 +32,15 @@ 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 {
tx.Statement.Selects = append(tx.Statement.Selects, "*") tx.Statement.Selects = append(tx.Statement.Selects, "*")

View File

@ -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()] c, ok := stmt.Clauses[v.Name()]
if !ok { if !ok {
c.Name = v.Name() c.Name = v.Name()
} }
v.MergeClause(&c) v.MergeClause(&c)
stmt.Clauses[v.Name()] = 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)
} }
} }