Build query SQL

This commit is contained in:
Jinzhu 2018-03-16 11:16:22 +08:00
parent 0e25debf63
commit eb43b539f9
4 changed files with 94 additions and 11 deletions

View File

@ -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 ")
}

View File

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

View File

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

View File

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