Add group builder
This commit is contained in:
		
							parent
							
								
									23457d28ce
								
							
						
					
					
						commit
						1f501c36d7
					
				
							
								
								
									
										2
									
								
								api.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								api.go
									
									
									
									
									
								
							@ -40,7 +40,7 @@ func (s *DB) Joins(query string, args ...interface{}) *DB {
 | 
			
		||||
// Group specify the group method on the find
 | 
			
		||||
func (s *DB) Group(column string) *DB {
 | 
			
		||||
	tx := s.init()
 | 
			
		||||
	tx.Statement.GroupBy.GroupByColumns = append(tx.Statement.GroupBy.GroupByColumns, column)
 | 
			
		||||
	tx.Statement.GroupBy.Columns = append(tx.Statement.GroupBy.Columns, column)
 | 
			
		||||
	return tx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										110
									
								
								dialects/common/sqlbuilder/conditions.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								dialects/common/sqlbuilder/conditions.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
package sqlbuilder
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ConditionInterface condition interface
 | 
			
		||||
type ConditionInterface interface {
 | 
			
		||||
	ToSQL(*gorm.DB) (string, []interface{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildConditions build conditions
 | 
			
		||||
func BuildConditions(tx *gorm.DB) chan *Builder {
 | 
			
		||||
	queryChan := make(chan *Builder)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		builder := &Builder{}
 | 
			
		||||
 | 
			
		||||
		for i, c := range tx.Statement.Conditions {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			buildCondition(tx, c, builder)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		queryChan <- builder
 | 
			
		||||
	}()
 | 
			
		||||
	return queryChan
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func buildCondition(tx *gorm.DB, c gorm.ConditionInterface, builder *Builder) {
 | 
			
		||||
	switch cond := c.(type) {
 | 
			
		||||
	case gorm.And:
 | 
			
		||||
		builder.SQL.WriteString("(")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			buildCondition(tx, v, builder)
 | 
			
		||||
		}
 | 
			
		||||
		builder.SQL.WriteString(")")
 | 
			
		||||
	case gorm.Or:
 | 
			
		||||
		builder.SQL.WriteString("(")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" OR ")
 | 
			
		||||
			}
 | 
			
		||||
			buildCondition(tx, v, builder)
 | 
			
		||||
		}
 | 
			
		||||
		builder.SQL.WriteString(")")
 | 
			
		||||
	case gorm.Not:
 | 
			
		||||
		builder.SQL.WriteString("NOT (")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			buildCondition(tx, v, builder)
 | 
			
		||||
		}
 | 
			
		||||
		builder.SQL.WriteString(")")
 | 
			
		||||
	case gorm.Raw:
 | 
			
		||||
		builder.SQL.WriteString(cond.SQL)
 | 
			
		||||
		builder.Args = append(builder.Args, cond.Args...)
 | 
			
		||||
	case gorm.Eq:
 | 
			
		||||
		if cond.Value == nil {
 | 
			
		||||
			builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			builder.SQL.WriteString(" IS NULL")
 | 
			
		||||
		} else {
 | 
			
		||||
			builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			builder.SQL.WriteString(" = ?")
 | 
			
		||||
			builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
		}
 | 
			
		||||
	case gorm.Neq:
 | 
			
		||||
		if cond.Value == nil {
 | 
			
		||||
			builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			builder.SQL.WriteString(" IS NOT NULL")
 | 
			
		||||
		} else {
 | 
			
		||||
			builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			builder.SQL.WriteString(" <> ?")
 | 
			
		||||
			builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
		}
 | 
			
		||||
	case gorm.Gt:
 | 
			
		||||
		builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		builder.SQL.WriteString(" > ?")
 | 
			
		||||
		builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
	case gorm.Gte:
 | 
			
		||||
		builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		builder.SQL.WriteString(" >= ?")
 | 
			
		||||
		builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
	case gorm.Lt:
 | 
			
		||||
		builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		builder.SQL.WriteString(" < ?")
 | 
			
		||||
		builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
	case gorm.Lte:
 | 
			
		||||
		builder.SQL.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		builder.SQL.WriteString(" <= ?")
 | 
			
		||||
		builder.Args = append(builder.Args, cond.Value)
 | 
			
		||||
	default:
 | 
			
		||||
		if sqlCond, ok := cond.(ConditionInterface); ok {
 | 
			
		||||
			sql, as := sqlCond.ToSQL(tx)
 | 
			
		||||
			builder.SQL.WriteString(sql)
 | 
			
		||||
			builder.Args = append(builder.Args, as...)
 | 
			
		||||
		} else {
 | 
			
		||||
			tx.AddError(fmt.Errorf("unsupported condition: %#v", cond))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								dialects/common/sqlbuilder/group.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								dialects/common/sqlbuilder/group.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
package sqlbuilder
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// BuildGroupCondition build group condition
 | 
			
		||||
func BuildGroupCondition(tx *gorm.DB) chan *Builder {
 | 
			
		||||
	groupChan := make(chan *Builder)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		builder := &Builder{}
 | 
			
		||||
		if groupBy := tx.Statement.GroupBy; len(groupBy.Columns) > 0 {
 | 
			
		||||
			builder.SQL.WriteString(strings.Join(tx.Statement.GroupBy.Columns, ", "))
 | 
			
		||||
 | 
			
		||||
			if len(groupBy.Having) > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" HAVING ")
 | 
			
		||||
				for i, having := range groupBy.Having {
 | 
			
		||||
					if i > 0 {
 | 
			
		||||
						builder.SQL.WriteString(" AND ")
 | 
			
		||||
					}
 | 
			
		||||
					buildCondition(tx, having, builder)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		groupChan <- builder
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return groupChan
 | 
			
		||||
}
 | 
			
		||||
@ -1,112 +1,9 @@
 | 
			
		||||
package sqlbuilder
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
import "bytes"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func buildCondition(tx *gorm.DB, c gorm.ConditionInterface, s *bytes.Buffer) []interface{} {
 | 
			
		||||
	args := []interface{}{}
 | 
			
		||||
 | 
			
		||||
	switch cond := c.(type) {
 | 
			
		||||
	case gorm.And:
 | 
			
		||||
		s.WriteString("(")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				s.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			args = append(args, buildCondition(tx, v, s)...)
 | 
			
		||||
		}
 | 
			
		||||
		s.WriteString(")")
 | 
			
		||||
	case gorm.Or:
 | 
			
		||||
		s.WriteString("(")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				s.WriteString(" OR ")
 | 
			
		||||
			}
 | 
			
		||||
			args = append(args, buildCondition(tx, v, s)...)
 | 
			
		||||
		}
 | 
			
		||||
		s.WriteString(")")
 | 
			
		||||
	case gorm.Not:
 | 
			
		||||
		s.WriteString("NOT (")
 | 
			
		||||
		for i, v := range cond {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				s.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			args = append(args, buildCondition(tx, v, s)...)
 | 
			
		||||
		}
 | 
			
		||||
		s.WriteString(")")
 | 
			
		||||
	case gorm.Raw:
 | 
			
		||||
		s.WriteString(cond.SQL)
 | 
			
		||||
		args = append(args, cond.Args...)
 | 
			
		||||
	case gorm.Eq:
 | 
			
		||||
		if cond.Value == nil {
 | 
			
		||||
			s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			s.WriteString(" IS NULL")
 | 
			
		||||
		} else {
 | 
			
		||||
			s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			s.WriteString(" = ?")
 | 
			
		||||
			args = append(args, cond.Value)
 | 
			
		||||
		}
 | 
			
		||||
	case gorm.Neq:
 | 
			
		||||
		if cond.Value == nil {
 | 
			
		||||
			s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			s.WriteString(" IS NOT NULL")
 | 
			
		||||
		} else {
 | 
			
		||||
			s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
			s.WriteString(" <> ?")
 | 
			
		||||
			args = append(args, cond.Value)
 | 
			
		||||
		}
 | 
			
		||||
	case gorm.Gt:
 | 
			
		||||
		s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		s.WriteString(" > ?")
 | 
			
		||||
		args = append(args, cond.Value)
 | 
			
		||||
	case gorm.Gte:
 | 
			
		||||
		s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		s.WriteString(" >= ?")
 | 
			
		||||
		args = append(args, cond.Value)
 | 
			
		||||
	case gorm.Lt:
 | 
			
		||||
		s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		s.WriteString(" < ?")
 | 
			
		||||
		args = append(args, cond.Value)
 | 
			
		||||
	case gorm.Lte:
 | 
			
		||||
		s.WriteString(tx.Dialect().Quote(cond.Column))
 | 
			
		||||
		s.WriteString(" <= ?")
 | 
			
		||||
		args = append(args, cond.Value)
 | 
			
		||||
	default:
 | 
			
		||||
		if sqlCond, ok := cond.(ConditionInterface); ok {
 | 
			
		||||
			sql, as := sqlCond.ToSQL(tx)
 | 
			
		||||
			s.WriteString(sql)
 | 
			
		||||
			args = append(args, as)
 | 
			
		||||
		} else {
 | 
			
		||||
			tx.AddError(fmt.Errorf("unsupported condition: %#v", cond))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return args
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConditionInterface condition interface
 | 
			
		||||
type ConditionInterface interface {
 | 
			
		||||
	ToSQL(*gorm.DB) (string, []interface{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildConditions build conditions
 | 
			
		||||
func BuildConditions(tx *gorm.DB) chan string {
 | 
			
		||||
	queryChan := make(chan string)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		s := bytes.NewBufferString("")
 | 
			
		||||
		args := []interface{}{}
 | 
			
		||||
 | 
			
		||||
		for i, c := range tx.Statement.Conditions {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				s.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
			args = append(args, buildCondition(tx, c, s)...)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	return queryChan
 | 
			
		||||
// Builder sql builder
 | 
			
		||||
type Builder struct {
 | 
			
		||||
	SQL  bytes.Buffer
 | 
			
		||||
	Args []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -47,8 +47,8 @@ type Join struct {
 | 
			
		||||
 | 
			
		||||
// GroupBy group by statement
 | 
			
		||||
type GroupBy struct {
 | 
			
		||||
	GroupByColumns []string
 | 
			
		||||
	Having         []ConditionInterface
 | 
			
		||||
	Columns []string
 | 
			
		||||
	Having  []ConditionInterface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OrderCondition order condition, could be string or sql expr
 | 
			
		||||
@ -84,7 +84,7 @@ func (stmt *Statement) Clone() *Statement {
 | 
			
		||||
// BuildCondition build condition
 | 
			
		||||
func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) ConditionInterface {
 | 
			
		||||
	if sql, ok := query.(string); ok {
 | 
			
		||||
		return Raw{Value: sql, Args: args}
 | 
			
		||||
		return Raw{SQL: sql, Args: args}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	andConds := And([]ConditionInterface{ConditionInterface(query)})
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user