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