gorm/clause/where.go

137 lines
2.6 KiB
Go
Raw Normal View History

2020-02-02 09:40:44 +03:00
package clause
// Where where clause
type Where struct {
2020-02-07 18:45:35 +03:00
Exprs []Expression
2020-02-02 09:40:44 +03:00
}
// Name where clause name
func (where Where) Name() string {
return "WHERE"
}
// Build build where clause
func (where Where) Build(builder Builder) {
2020-02-07 18:45:35 +03:00
// Switch position if the first query expression is a single Or condition
for idx, expr := range where.Exprs {
2020-06-06 17:52:08 +03:00
if v, ok := expr.(OrConditions); !ok || len(v.Exprs) > 1 {
2020-02-07 18:45:35 +03:00
if idx != 0 {
where.Exprs[0], where.Exprs[idx] = where.Exprs[idx], where.Exprs[0]
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
break
2020-02-02 09:40:44 +03:00
}
}
2020-02-07 18:45:35 +03:00
for idx, expr := range where.Exprs {
2020-06-06 17:52:08 +03:00
if idx > 0 {
if v, ok := expr.(OrConditions); ok && len(v.Exprs) == 1 {
builder.WriteString(" OR ")
} else {
builder.WriteString(" AND ")
2020-02-02 09:40:44 +03:00
}
}
2020-06-06 17:52:08 +03:00
expr.Build(builder)
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
}
// MergeClause merge where clauses
func (where Where) MergeClause(clause *Clause) {
if w, ok := clause.Expression.(Where); ok {
2020-06-08 04:10:27 +03:00
exprs := make([]Expression, len(w.Exprs)+len(where.Exprs))
copy(exprs, w.Exprs)
copy(exprs[len(w.Exprs):], where.Exprs)
where.Exprs = exprs
2020-02-07 18:45:35 +03:00
}
clause.Expression = where
}
func And(exprs ...Expression) Expression {
if len(exprs) == 0 {
return nil
}
return AndConditions{Exprs: exprs}
}
type AndConditions struct {
Exprs []Expression
}
func (and AndConditions) Build(builder Builder) {
if len(and.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte('(')
2020-02-07 18:45:35 +03:00
}
for idx, c := range and.Exprs {
if idx > 0 {
2020-06-19 20:55:30 +03:00
if orConditions, ok := c.(OrConditions); ok && len(orConditions.Exprs) == 1 {
builder.WriteString(" OR ")
} else {
builder.WriteString(" AND ")
}
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
c.Build(builder)
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
if len(and.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte(')')
2020-02-07 18:45:35 +03:00
}
}
2020-02-02 09:40:44 +03:00
2020-02-07 18:45:35 +03:00
func Or(exprs ...Expression) Expression {
if len(exprs) == 0 {
return nil
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
return OrConditions{Exprs: exprs}
}
2020-02-02 09:40:44 +03:00
2020-02-07 18:45:35 +03:00
type OrConditions struct {
Exprs []Expression
}
func (or OrConditions) Build(builder Builder) {
if len(or.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte('(')
2020-02-07 18:45:35 +03:00
}
for idx, c := range or.Exprs {
if idx > 0 {
2020-03-09 12:07:00 +03:00
builder.WriteString(" OR ")
2020-02-07 18:45:35 +03:00
}
c.Build(builder)
}
if len(or.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte(')')
2020-02-07 18:45:35 +03:00
}
}
func Not(exprs ...Expression) Expression {
if len(exprs) == 0 {
return nil
}
return NotConditions{Exprs: exprs}
}
type NotConditions struct {
Exprs []Expression
2020-02-02 09:40:44 +03:00
}
2020-02-07 18:45:35 +03:00
func (not NotConditions) Build(builder Builder) {
if len(not.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte('(')
2020-02-07 18:45:35 +03:00
}
for idx, c := range not.Exprs {
if idx > 0 {
2020-03-09 12:07:00 +03:00
builder.WriteString(" AND ")
2020-02-07 18:45:35 +03:00
}
if negationBuilder, ok := c.(NegationExpressionBuilder); ok {
negationBuilder.NegationBuild(builder)
} else {
2020-07-05 06:53:10 +03:00
builder.WriteString("NOT ")
2020-02-07 18:45:35 +03:00
c.Build(builder)
}
}
if len(not.Exprs) > 1 {
2020-02-13 19:09:44 +03:00
builder.WriteByte(')')
2020-02-02 09:40:44 +03:00
}
}