github.com/wangyougui/gf/v2@v2.6.5/database/gdb/gdb_model_fields.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/wangyougui/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"fmt"
    11  
    12  	"github.com/wangyougui/gf/v2/container/gset"
    13  	"github.com/wangyougui/gf/v2/text/gstr"
    14  	"github.com/wangyougui/gf/v2/util/gconv"
    15  )
    16  
    17  // Fields appends `fieldNamesOrMapStruct` to the operation fields of the model, multiple fields joined using char ','.
    18  // The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
    19  //
    20  // Eg:
    21  // Fields("id", "name", "age")
    22  // Fields([]string{"id", "name", "age"})
    23  // Fields(map[string]interface{}{"id":1, "name":"john", "age":18})
    24  // Fields(User{ Id: 1, Name: "john", Age: 18}).
    25  func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model {
    26  	length := len(fieldNamesOrMapStruct)
    27  	if length == 0 {
    28  		return m
    29  	}
    30  	fields := m.getFieldsFrom(m.tablesInit, fieldNamesOrMapStruct...)
    31  	if len(fields) == 0 {
    32  		return m
    33  	}
    34  	return m.appendFieldsByStr(gstr.Join(fields, ","))
    35  }
    36  
    37  // FieldsPrefix performs as function Fields but add extra prefix for each field.
    38  func (m *Model) FieldsPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model {
    39  	fields := m.getFieldsFrom(m.getTableNameByPrefixOrAlias(prefixOrAlias), fieldNamesOrMapStruct...)
    40  	if len(fields) == 0 {
    41  		return m
    42  	}
    43  	gstr.PrefixArray(fields, prefixOrAlias+".")
    44  	return m.appendFieldsByStr(gstr.Join(fields, ","))
    45  }
    46  
    47  // FieldsEx appends `fieldNamesOrMapStruct` to the excluded operation fields of the model,
    48  // multiple fields joined using char ','.
    49  // Note that this function supports only single table operations.
    50  // The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
    51  //
    52  // Also see Fields.
    53  func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model {
    54  	return m.doFieldsEx(m.tablesInit, fieldNamesOrMapStruct...)
    55  }
    56  func (m *Model) doFieldsEx(table string, fieldNamesOrMapStruct ...interface{}) *Model {
    57  	length := len(fieldNamesOrMapStruct)
    58  	if length == 0 {
    59  		return m
    60  	}
    61  	fields := m.getFieldsFrom(table, fieldNamesOrMapStruct...)
    62  	if len(fields) == 0 {
    63  		return m
    64  	}
    65  	return m.appendFieldsExByStr(gstr.Join(fields, ","))
    66  }
    67  
    68  // FieldsExPrefix performs as function FieldsEx but add extra prefix for each field.
    69  func (m *Model) FieldsExPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model {
    70  	model := m.doFieldsEx(m.getTableNameByPrefixOrAlias(prefixOrAlias), fieldNamesOrMapStruct...)
    71  	array := gstr.SplitAndTrim(model.fieldsEx, ",")
    72  	gstr.PrefixArray(array, prefixOrAlias+".")
    73  	model.fieldsEx = gstr.Join(array, ",")
    74  	return model
    75  }
    76  
    77  // FieldCount formats and appends commonly used field `COUNT(column)` to the select fields of model.
    78  func (m *Model) FieldCount(column string, as ...string) *Model {
    79  	asStr := ""
    80  	if len(as) > 0 && as[0] != "" {
    81  		asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
    82  	}
    83  	return m.appendFieldsByStr(fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr))
    84  }
    85  
    86  // FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model.
    87  func (m *Model) FieldSum(column string, as ...string) *Model {
    88  	asStr := ""
    89  	if len(as) > 0 && as[0] != "" {
    90  		asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
    91  	}
    92  	return m.appendFieldsByStr(fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr))
    93  }
    94  
    95  // FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model.
    96  func (m *Model) FieldMin(column string, as ...string) *Model {
    97  	asStr := ""
    98  	if len(as) > 0 && as[0] != "" {
    99  		asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
   100  	}
   101  	return m.appendFieldsByStr(fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr))
   102  }
   103  
   104  // FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model.
   105  func (m *Model) FieldMax(column string, as ...string) *Model {
   106  	asStr := ""
   107  	if len(as) > 0 && as[0] != "" {
   108  		asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
   109  	}
   110  	return m.appendFieldsByStr(fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr))
   111  }
   112  
   113  // FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model.
   114  func (m *Model) FieldAvg(column string, as ...string) *Model {
   115  	asStr := ""
   116  	if len(as) > 0 && as[0] != "" {
   117  		asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
   118  	}
   119  	return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr))
   120  }
   121  
   122  // GetFieldsStr retrieves and returns all fields from the table, joined with char ','.
   123  // The optional parameter `prefix` specifies the prefix for each field, eg: GetFieldsStr("u.").
   124  func (m *Model) GetFieldsStr(prefix ...string) string {
   125  	prefixStr := ""
   126  	if len(prefix) > 0 {
   127  		prefixStr = prefix[0]
   128  	}
   129  	tableFields, err := m.TableFields(m.tablesInit)
   130  	if err != nil {
   131  		panic(err)
   132  	}
   133  	if len(tableFields) == 0 {
   134  		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
   135  	}
   136  	fieldsArray := make([]string, len(tableFields))
   137  	for k, v := range tableFields {
   138  		fieldsArray[v.Index] = k
   139  	}
   140  	newFields := ""
   141  	for _, k := range fieldsArray {
   142  		if len(newFields) > 0 {
   143  			newFields += ","
   144  		}
   145  		newFields += prefixStr + k
   146  	}
   147  	newFields = m.db.GetCore().QuoteString(newFields)
   148  	return newFields
   149  }
   150  
   151  // GetFieldsExStr retrieves and returns fields which are not in parameter `fields` from the table,
   152  // joined with char ','.
   153  // The parameter `fields` specifies the fields that are excluded.
   154  // The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u.").
   155  func (m *Model) GetFieldsExStr(fields string, prefix ...string) string {
   156  	prefixStr := ""
   157  	if len(prefix) > 0 {
   158  		prefixStr = prefix[0]
   159  	}
   160  	tableFields, err := m.TableFields(m.tablesInit)
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	if len(tableFields) == 0 {
   165  		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
   166  	}
   167  	fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ","))
   168  	fieldsArray := make([]string, len(tableFields))
   169  	for k, v := range tableFields {
   170  		fieldsArray[v.Index] = k
   171  	}
   172  	newFields := ""
   173  	for _, k := range fieldsArray {
   174  		if fieldsExSet.Contains(k) {
   175  			continue
   176  		}
   177  		if len(newFields) > 0 {
   178  			newFields += ","
   179  		}
   180  		newFields += prefixStr + k
   181  	}
   182  	newFields = m.db.GetCore().QuoteString(newFields)
   183  	return newFields
   184  }
   185  
   186  // HasField determine whether the field exists in the table.
   187  func (m *Model) HasField(field string) (bool, error) {
   188  	return m.db.GetCore().HasField(m.GetCtx(), m.tablesInit, field)
   189  }
   190  
   191  // getFieldsFrom retrieves, filters and returns fields name from table `table`.
   192  func (m *Model) getFieldsFrom(table string, fieldNamesOrMapStruct ...interface{}) []string {
   193  	length := len(fieldNamesOrMapStruct)
   194  	if length == 0 {
   195  		return nil
   196  	}
   197  	switch {
   198  	// String slice.
   199  	case length >= 2:
   200  		return m.mappingAndFilterToTableFields(
   201  			table, gconv.Strings(fieldNamesOrMapStruct), true,
   202  		)
   203  
   204  	// It needs type asserting.
   205  	case length == 1:
   206  		structOrMap := fieldNamesOrMapStruct[0]
   207  		switch r := structOrMap.(type) {
   208  		case string:
   209  			return m.mappingAndFilterToTableFields(table, []string{r}, false)
   210  
   211  		case []string:
   212  			return m.mappingAndFilterToTableFields(table, r, true)
   213  
   214  		case Raw, *Raw:
   215  			return []string{gconv.String(structOrMap)}
   216  
   217  		default:
   218  			return m.mappingAndFilterToTableFields(table, getFieldsFromStructOrMap(structOrMap), true)
   219  		}
   220  
   221  	default:
   222  		return nil
   223  	}
   224  }
   225  
   226  func (m *Model) appendFieldsByStr(fields string) *Model {
   227  	if fields != "" {
   228  		model := m.getModel()
   229  		if model.fields == defaultFields {
   230  			model.fields = ""
   231  		}
   232  		if model.fields != "" {
   233  			model.fields += ","
   234  		}
   235  		model.fields += fields
   236  		return model
   237  	}
   238  	return m
   239  }
   240  
   241  func (m *Model) appendFieldsExByStr(fieldsEx string) *Model {
   242  	if fieldsEx != "" {
   243  		model := m.getModel()
   244  		if model.fieldsEx != "" {
   245  			model.fieldsEx += ","
   246  		}
   247  		model.fieldsEx += fieldsEx
   248  		return model
   249  	}
   250  	return m
   251  }