github.com/gogf/gf/v2@v2.7.4/database/gdb/gdb_model_builder.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"fmt"
    11  )
    12  
    13  // WhereBuilder holds multiple where conditions in a group.
    14  type WhereBuilder struct {
    15  	model       *Model        // A WhereBuilder should be bound to certain Model.
    16  	whereHolder []WhereHolder // Condition strings for where operation.
    17  }
    18  
    19  // WhereHolder is the holder for where condition preparing.
    20  type WhereHolder struct {
    21  	Type     string        // Type of this holder.
    22  	Operator int           // Operator for this holder.
    23  	Where    interface{}   // Where parameter, which can commonly be type of string/map/struct.
    24  	Args     []interface{} // Arguments for where parameter.
    25  	Prefix   string        // Field prefix, eg: "user.", "order.".
    26  }
    27  
    28  // Builder creates and returns a WhereBuilder. Please note that the builder is chain-safe.
    29  func (m *Model) Builder() *WhereBuilder {
    30  	b := &WhereBuilder{
    31  		model:       m,
    32  		whereHolder: make([]WhereHolder, 0),
    33  	}
    34  	return b
    35  }
    36  
    37  // getBuilder creates and returns a cloned WhereBuilder of current WhereBuilder
    38  func (b *WhereBuilder) getBuilder() *WhereBuilder {
    39  	return b.Clone()
    40  }
    41  
    42  // Clone clones and returns a WhereBuilder that is a copy of current one.
    43  func (b *WhereBuilder) Clone() *WhereBuilder {
    44  	newBuilder := b.model.Builder()
    45  	newBuilder.whereHolder = make([]WhereHolder, len(b.whereHolder))
    46  	copy(newBuilder.whereHolder, b.whereHolder)
    47  	return newBuilder
    48  }
    49  
    50  // Build builds current WhereBuilder and returns the condition string and parameters.
    51  func (b *WhereBuilder) Build() (conditionWhere string, conditionArgs []interface{}) {
    52  	var (
    53  		ctx                         = b.model.GetCtx()
    54  		autoPrefix                  = b.model.getAutoPrefix()
    55  		tableForMappingAndFiltering = b.model.tables
    56  	)
    57  	if len(b.whereHolder) > 0 {
    58  		for _, holder := range b.whereHolder {
    59  			if holder.Prefix == "" {
    60  				holder.Prefix = autoPrefix
    61  			}
    62  			switch holder.Operator {
    63  			case whereHolderOperatorWhere, whereHolderOperatorAnd:
    64  				newWhere, newArgs := formatWhereHolder(ctx, b.model.db, formatWhereHolderInput{
    65  					WhereHolder: holder,
    66  					OmitNil:     b.model.option&optionOmitNilWhere > 0,
    67  					OmitEmpty:   b.model.option&optionOmitEmptyWhere > 0,
    68  					Schema:      b.model.schema,
    69  					Table:       tableForMappingAndFiltering,
    70  				})
    71  				if len(newWhere) > 0 {
    72  					if len(conditionWhere) == 0 {
    73  						conditionWhere = newWhere
    74  					} else if conditionWhere[0] == '(' {
    75  						conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
    76  					} else {
    77  						conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
    78  					}
    79  					conditionArgs = append(conditionArgs, newArgs...)
    80  				}
    81  
    82  			case whereHolderOperatorOr:
    83  				newWhere, newArgs := formatWhereHolder(ctx, b.model.db, formatWhereHolderInput{
    84  					WhereHolder: holder,
    85  					OmitNil:     b.model.option&optionOmitNilWhere > 0,
    86  					OmitEmpty:   b.model.option&optionOmitEmptyWhere > 0,
    87  					Schema:      b.model.schema,
    88  					Table:       tableForMappingAndFiltering,
    89  				})
    90  				if len(newWhere) > 0 {
    91  					if len(conditionWhere) == 0 {
    92  						conditionWhere = newWhere
    93  					} else if conditionWhere[0] == '(' {
    94  						conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
    95  					} else {
    96  						conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
    97  					}
    98  					conditionArgs = append(conditionArgs, newArgs...)
    99  				}
   100  			}
   101  		}
   102  	}
   103  	return
   104  }
   105  
   106  // convertWhereBuilder converts parameter `where` to condition string and parameters if `where` is also a WhereBuilder.
   107  func (b *WhereBuilder) convertWhereBuilder(where interface{}, args []interface{}) (newWhere interface{}, newArgs []interface{}) {
   108  	var builder *WhereBuilder
   109  	switch v := where.(type) {
   110  	case WhereBuilder:
   111  		builder = &v
   112  
   113  	case *WhereBuilder:
   114  		builder = v
   115  	}
   116  	if builder != nil {
   117  		conditionWhere, conditionArgs := builder.Build()
   118  		if conditionWhere != "" && (len(b.whereHolder) == 0 || len(builder.whereHolder) > 1) {
   119  			conditionWhere = "(" + conditionWhere + ")"
   120  		}
   121  		return conditionWhere, conditionArgs
   122  	}
   123  	return where, args
   124  }