Build query SQL
This commit is contained in:
		
							parent
							
								
									0e25debf63
								
							
						
					
					
						commit
						eb43b539f9
					
				@ -12,13 +12,13 @@ type ConditionInterface interface {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildConditions build conditions
 | 
			
		||||
func BuildConditions(tx *gorm.DB) chan *Builder {
 | 
			
		||||
func BuildConditions(tx *gorm.DB, conds []gorm.ConditionInterface) chan *Builder {
 | 
			
		||||
	queryChan := make(chan *Builder)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		builder := &Builder{}
 | 
			
		||||
 | 
			
		||||
		for i, c := range tx.Statement.Conditions {
 | 
			
		||||
		for i, c := range conds {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				builder.SQL.WriteString(" AND ")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -50,13 +50,35 @@ func GetAssignmentFields(tx *gorm.DB) chan [][]*model.Field {
 | 
			
		||||
	return fieldChan
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mapToFields(value map[string]interface{}, s *schema.Schema, assignableChecker func(*model.Field) bool) (fields []*model.Field) {
 | 
			
		||||
// GetSelectableFields get selectable fields
 | 
			
		||||
func GetSelectableFields(tx *gorm.DB) chan []string {
 | 
			
		||||
	fieldChan := make(chan []string)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		assignableChecker := generateAssignableChecker(selectAttrs(tx.Statement), omitAttrs(tx.Statement))
 | 
			
		||||
		if s := schema.Parse(tx.Statement.Dest); s != nil {
 | 
			
		||||
			columns := []string{}
 | 
			
		||||
			for _, field := range s.Fields {
 | 
			
		||||
				if assignableChecker(field) {
 | 
			
		||||
					columns = append(columns, field.DBName)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			fieldChan <- columns
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		fieldChan <- []string{"*"}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return fieldChan
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mapToFields(value map[string]interface{}, s *schema.Schema, assignableChecker func(*schema.Field) bool) (fields []*model.Field) {
 | 
			
		||||
	// TODO assign those value to dest
 | 
			
		||||
	for k, v := range value {
 | 
			
		||||
		if s != nil {
 | 
			
		||||
			if f := s.FieldByName(k); f != nil {
 | 
			
		||||
				field := &model.Field{Field: f, Value: reflect.ValueOf(v)}
 | 
			
		||||
				if assignableChecker(field) {
 | 
			
		||||
				if assignableChecker(field.Field) {
 | 
			
		||||
					fields = append(fields, field)
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
@ -64,7 +86,7 @@ func mapToFields(value map[string]interface{}, s *schema.Schema, assignableCheck
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		field := &model.Field{Field: &schema.Field{DBName: k}, Value: reflect.ValueOf(v)}
 | 
			
		||||
		if assignableChecker(field) {
 | 
			
		||||
		if assignableChecker(field.Field) {
 | 
			
		||||
			fields = append(fields, field)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -75,7 +97,7 @@ func mapToFields(value map[string]interface{}, s *schema.Schema, assignableCheck
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structToField(value reflect.Value, s *schema.Schema, assignableChecker func(*model.Field) bool) (fields []*model.Field) {
 | 
			
		||||
func structToField(value reflect.Value, s *schema.Schema, assignableChecker func(*schema.Field) bool) (fields []*model.Field) {
 | 
			
		||||
	// TODO use Offset to replace FieldByName?
 | 
			
		||||
	for _, sf := range s.Fields {
 | 
			
		||||
		obj := value
 | 
			
		||||
@ -83,7 +105,7 @@ func structToField(value reflect.Value, s *schema.Schema, assignableChecker func
 | 
			
		||||
			obj = value.FieldByName(bn)
 | 
			
		||||
		}
 | 
			
		||||
		field := &model.Field{Field: sf, Value: obj, IsBlank: model.IsBlank(obj)}
 | 
			
		||||
		if assignableChecker(field) {
 | 
			
		||||
		if assignableChecker(field.Field) {
 | 
			
		||||
			fields = append(fields, field)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -91,8 +113,8 @@ func structToField(value reflect.Value, s *schema.Schema, assignableChecker func
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// generateAssignableChecker generate checker to check if field is assignable or not
 | 
			
		||||
func generateAssignableChecker(selectAttrs []string, omitAttrs []string) func(*model.Field) bool {
 | 
			
		||||
	return func(field *model.Field) bool {
 | 
			
		||||
func generateAssignableChecker(selectAttrs []string, omitAttrs []string) func(*schema.Field) bool {
 | 
			
		||||
	return func(field *schema.Field) bool {
 | 
			
		||||
		if len(selectAttrs) > 0 {
 | 
			
		||||
			for _, attr := range selectAttrs {
 | 
			
		||||
				if field.Name == attr || field.DBName == attr {
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ func BuildGroupCondition(tx *gorm.DB) chan *Builder {
 | 
			
		||||
	go func() {
 | 
			
		||||
		builder := &Builder{}
 | 
			
		||||
		if groupBy := tx.Statement.GroupBy; len(groupBy.Columns) > 0 {
 | 
			
		||||
			builder.SQL.WriteString(" GROUP BY ")
 | 
			
		||||
			builder.SQL.WriteString(strings.Join(tx.Statement.GroupBy.Columns, ", "))
 | 
			
		||||
 | 
			
		||||
			if len(groupBy.Having) > 0 {
 | 
			
		||||
 | 
			
		||||
@ -100,8 +100,68 @@ func (dialect *Dialect) Insert(tx *gorm.DB) (err error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Query query
 | 
			
		||||
func (*Dialect) Query(tx *gorm.DB) error {
 | 
			
		||||
	return nil
 | 
			
		||||
func (dialect *Dialect) Query(tx *gorm.DB) (err error) {
 | 
			
		||||
	var (
 | 
			
		||||
		args           []interface{}
 | 
			
		||||
		tableNameChan  = sqlbuilder.GetTable(tx)
 | 
			
		||||
		conditionsChan = sqlbuilder.BuildConditions(tx, tx.Statement.Conditions)
 | 
			
		||||
		groupChan      = sqlbuilder.BuildGroupCondition(tx)
 | 
			
		||||
		orderChan      = sqlbuilder.BuildOrderCondition(tx)
 | 
			
		||||
		limitChan      = sqlbuilder.BuildLimitCondition(tx)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	s := bytes.NewBufferString("SELECT ")
 | 
			
		||||
 | 
			
		||||
	// FIXME quote, add table
 | 
			
		||||
	columns := tx.Statement.Select.Columns
 | 
			
		||||
	if len(columns) > 0 {
 | 
			
		||||
		args = append(args, tx.Statement.Select.Args...)
 | 
			
		||||
	} else {
 | 
			
		||||
		columns = []string{"*"}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for idx, column := range columns {
 | 
			
		||||
		if idx != 0 {
 | 
			
		||||
			s.WriteString(",")
 | 
			
		||||
		}
 | 
			
		||||
		s.WriteString(column)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.WriteString(" FROM ")
 | 
			
		||||
	s.WriteString(dialect.Quote(<-tableNameChan))
 | 
			
		||||
 | 
			
		||||
	// Join SQL
 | 
			
		||||
	for _, join := range tx.Statement.Joins {
 | 
			
		||||
		if join.Table == "" {
 | 
			
		||||
			builder := <-sqlbuilder.BuildConditions(tx, join.Conditions)
 | 
			
		||||
			_, err = builder.SQL.WriteTo(s)
 | 
			
		||||
			args = append(args, builder.Args...)
 | 
			
		||||
		}
 | 
			
		||||
		// FIXME
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(tx.Statement.Conditions) > 0 {
 | 
			
		||||
		s.WriteString(" WHERE ")
 | 
			
		||||
		builder := <-conditionsChan
 | 
			
		||||
		_, err = builder.SQL.WriteTo(s)
 | 
			
		||||
		args = append(args, builder.Args...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if builder := <-groupChan; builder != nil {
 | 
			
		||||
		_, err = builder.SQL.WriteTo(s)
 | 
			
		||||
		args = append(args, builder.Args)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if builder := <-orderChan; builder != nil {
 | 
			
		||||
		_, err = builder.SQL.WriteTo(s)
 | 
			
		||||
		args = append(args, builder.Args)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if builder := <-limitChan; builder != nil {
 | 
			
		||||
		_, err = builder.SQL.WriteTo(s)
 | 
			
		||||
		args = append(args, builder.Args)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update update
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user