2021-01-17 21:46:25 +08:00
|
|
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
2020-03-13 17:21:30 +08:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
|
|
|
|
package gdb
|
|
|
|
|
|
|
|
import (
|
2020-04-27 21:18:42 +08:00
|
|
|
"fmt"
|
2021-11-13 23:23:55 +08:00
|
|
|
|
2021-10-11 21:41:56 +08:00
|
|
|
"github.com/gogf/gf/v2/container/gset"
|
2024-09-13 16:50:38 +08:00
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
2021-10-11 21:41:56 +08:00
|
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
2020-03-13 17:21:30 +08:00
|
|
|
)
|
|
|
|
|
2021-08-12 19:42:44 +08:00
|
|
|
// Fields appends `fieldNamesOrMapStruct` to the operation fields of the model, multiple fields joined using char ','.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
2021-10-29 15:12:31 +08:00
|
|
|
//
|
2024-09-13 16:50:38 +08:00
|
|
|
// Example:
|
2021-10-29 15:12:31 +08:00
|
|
|
// Fields("id", "name", "age")
|
|
|
|
// Fields([]string{"id", "name", "age"})
|
|
|
|
// Fields(map[string]interface{}{"id":1, "name":"john", "age":18})
|
2024-09-13 16:50:38 +08:00
|
|
|
// Fields(User{Id: 1, Name: "john", Age: 18}).
|
2020-11-06 20:52:16 +08:00
|
|
|
func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model {
|
|
|
|
length := len(fieldNamesOrMapStruct)
|
|
|
|
if length == 0 {
|
|
|
|
return m
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
fields := m.filterFieldsFrom(m.tablesInit, fieldNamesOrMapStruct...)
|
2022-05-25 16:22:46 +08:00
|
|
|
if len(fields) == 0 {
|
|
|
|
return m
|
2020-10-10 14:00:10 +08:00
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(fields...)
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
2021-10-29 15:12:31 +08:00
|
|
|
// FieldsPrefix performs as function Fields but add extra prefix for each field.
|
2023-11-20 20:47:26 +08:00
|
|
|
func (m *Model) FieldsPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model {
|
2024-09-13 16:50:38 +08:00
|
|
|
fields := m.filterFieldsFrom(
|
|
|
|
m.getTableNameByPrefixOrAlias(prefixOrAlias),
|
|
|
|
fieldNamesOrMapStruct...,
|
|
|
|
)
|
2022-05-25 16:22:46 +08:00
|
|
|
if len(fields) == 0 {
|
|
|
|
return m
|
|
|
|
}
|
2024-10-21 09:22:31 +08:00
|
|
|
for i, field := range fields {
|
|
|
|
fields[i] = prefixOrAlias + "." + gconv.String(field)
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(fields...)
|
2021-10-29 15:12:31 +08:00
|
|
|
}
|
|
|
|
|
2021-08-12 19:42:44 +08:00
|
|
|
// FieldsEx appends `fieldNamesOrMapStruct` to the excluded operation fields of the model,
|
|
|
|
// multiple fields joined using char ','.
|
2020-06-04 17:29:16 +08:00
|
|
|
// Note that this function supports only single table operations.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
2021-10-29 15:12:31 +08:00
|
|
|
//
|
2024-09-13 16:50:38 +08:00
|
|
|
// Example:
|
|
|
|
// FieldsEx("id", "name", "age")
|
|
|
|
// FieldsEx([]string{"id", "name", "age"})
|
|
|
|
// FieldsEx(map[string]interface{}{"id":1, "name":"john", "age":18})
|
|
|
|
// FieldsEx(User{Id: 1, Name: "john", Age: 18}).
|
2020-11-06 20:52:16 +08:00
|
|
|
func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model {
|
2023-11-20 20:47:26 +08:00
|
|
|
return m.doFieldsEx(m.tablesInit, fieldNamesOrMapStruct...)
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
|
2023-11-20 20:47:26 +08:00
|
|
|
func (m *Model) doFieldsEx(table string, fieldNamesOrMapStruct ...interface{}) *Model {
|
2020-11-06 20:52:16 +08:00
|
|
|
length := len(fieldNamesOrMapStruct)
|
|
|
|
if length == 0 {
|
|
|
|
return m
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
fields := m.filterFieldsFrom(table, fieldNamesOrMapStruct...)
|
2022-05-25 16:22:46 +08:00
|
|
|
if len(fields) == 0 {
|
|
|
|
return m
|
2020-10-10 14:00:10 +08:00
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
|
|
|
model.fieldsEx = append(model.fieldsEx, fields...)
|
|
|
|
return model
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
2021-10-29 15:12:31 +08:00
|
|
|
// FieldsExPrefix performs as function FieldsEx but add extra prefix for each field.
|
2023-11-20 20:47:26 +08:00
|
|
|
func (m *Model) FieldsExPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model {
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.doFieldsEx(
|
|
|
|
m.getTableNameByPrefixOrAlias(prefixOrAlias),
|
|
|
|
fieldNamesOrMapStruct...,
|
|
|
|
)
|
2024-10-21 09:22:31 +08:00
|
|
|
for i, field := range model.fieldsEx {
|
|
|
|
model.fieldsEx[i] = prefixOrAlias + "." + gconv.String(field)
|
|
|
|
}
|
2021-10-29 15:12:31 +08:00
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
2021-08-12 19:42:44 +08:00
|
|
|
// FieldCount formats and appends commonly used field `COUNT(column)` to the select fields of model.
|
|
|
|
func (m *Model) FieldCount(column string, as ...string) *Model {
|
|
|
|
asStr := ""
|
|
|
|
if len(as) > 0 && as[0] != "" {
|
|
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(
|
2024-09-13 16:50:38 +08:00
|
|
|
fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr),
|
|
|
|
)
|
2021-08-12 19:42:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model.
|
|
|
|
func (m *Model) FieldSum(column string, as ...string) *Model {
|
|
|
|
asStr := ""
|
|
|
|
if len(as) > 0 && as[0] != "" {
|
|
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(
|
2024-09-13 16:50:38 +08:00
|
|
|
fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr),
|
|
|
|
)
|
2021-08-12 19:42:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model.
|
|
|
|
func (m *Model) FieldMin(column string, as ...string) *Model {
|
|
|
|
asStr := ""
|
|
|
|
if len(as) > 0 && as[0] != "" {
|
|
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(
|
2024-09-13 16:50:38 +08:00
|
|
|
fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr),
|
|
|
|
)
|
2021-08-12 19:42:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model.
|
|
|
|
func (m *Model) FieldMax(column string, as ...string) *Model {
|
|
|
|
asStr := ""
|
|
|
|
if len(as) > 0 && as[0] != "" {
|
|
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(
|
2024-09-13 16:50:38 +08:00
|
|
|
fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr),
|
|
|
|
)
|
2021-08-12 19:42:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model.
|
|
|
|
func (m *Model) FieldAvg(column string, as ...string) *Model {
|
|
|
|
asStr := ""
|
|
|
|
if len(as) > 0 && as[0] != "" {
|
|
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
model := m.getModel()
|
2024-10-21 09:22:31 +08:00
|
|
|
return model.appendToFields(
|
2024-09-13 16:50:38 +08:00
|
|
|
fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr),
|
|
|
|
)
|
2021-08-12 19:42:44 +08:00
|
|
|
}
|
|
|
|
|
2021-05-02 12:17:06 +08:00
|
|
|
// GetFieldsStr retrieves and returns all fields from the table, joined with char ','.
|
2021-07-08 15:42:51 +08:00
|
|
|
// The optional parameter `prefix` specifies the prefix for each field, eg: GetFieldsStr("u.").
|
2020-09-02 20:37:02 +08:00
|
|
|
func (m *Model) GetFieldsStr(prefix ...string) string {
|
2020-03-13 17:21:30 +08:00
|
|
|
prefixStr := ""
|
|
|
|
if len(prefix) > 0 {
|
|
|
|
prefixStr = prefix[0]
|
|
|
|
}
|
2021-07-06 13:14:33 +08:00
|
|
|
tableFields, err := m.TableFields(m.tablesInit)
|
2020-04-27 21:18:42 +08:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if len(tableFields) == 0 {
|
|
|
|
panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
|
|
|
|
}
|
|
|
|
fieldsArray := make([]string, len(tableFields))
|
|
|
|
for k, v := range tableFields {
|
|
|
|
fieldsArray[v.Index] = k
|
|
|
|
}
|
|
|
|
newFields := ""
|
|
|
|
for _, k := range fieldsArray {
|
|
|
|
if len(newFields) > 0 {
|
|
|
|
newFields += ","
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2020-04-27 21:18:42 +08:00
|
|
|
newFields += prefixStr + k
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2021-05-21 13:25:53 +08:00
|
|
|
newFields = m.db.GetCore().QuoteString(newFields)
|
2020-04-27 21:18:42 +08:00
|
|
|
return newFields
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
2021-05-02 12:17:06 +08:00
|
|
|
// GetFieldsExStr retrieves and returns fields which are not in parameter `fields` from the table,
|
2020-03-13 17:21:30 +08:00
|
|
|
// joined with char ','.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The parameter `fields` specifies the fields that are excluded.
|
|
|
|
// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u.").
|
2024-09-13 16:50:38 +08:00
|
|
|
func (m *Model) GetFieldsExStr(fields string, prefix ...string) (string, error) {
|
2020-03-13 17:21:30 +08:00
|
|
|
prefixStr := ""
|
|
|
|
if len(prefix) > 0 {
|
|
|
|
prefixStr = prefix[0]
|
|
|
|
}
|
2021-07-06 20:59:09 +08:00
|
|
|
tableFields, err := m.TableFields(m.tablesInit)
|
2020-04-27 21:18:42 +08:00
|
|
|
if err != nil {
|
2024-09-13 16:50:38 +08:00
|
|
|
return "", err
|
2020-04-27 21:18:42 +08:00
|
|
|
}
|
|
|
|
if len(tableFields) == 0 {
|
2024-09-13 16:50:38 +08:00
|
|
|
return "", gerror.Newf(`empty table fields for table "%s"`, m.tables)
|
2020-04-27 21:18:42 +08:00
|
|
|
}
|
|
|
|
fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ","))
|
|
|
|
fieldsArray := make([]string, len(tableFields))
|
|
|
|
for k, v := range tableFields {
|
|
|
|
fieldsArray[v.Index] = k
|
|
|
|
}
|
|
|
|
newFields := ""
|
|
|
|
for _, k := range fieldsArray {
|
|
|
|
if fieldsExSet.Contains(k) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if len(newFields) > 0 {
|
|
|
|
newFields += ","
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2020-04-27 21:18:42 +08:00
|
|
|
newFields += prefixStr + k
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2021-05-21 13:25:53 +08:00
|
|
|
newFields = m.db.GetCore().QuoteString(newFields)
|
2024-09-13 16:50:38 +08:00
|
|
|
return newFields, nil
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2020-07-17 14:28:50 +08:00
|
|
|
|
|
|
|
// HasField determine whether the field exists in the table.
|
2020-07-21 12:37:04 +08:00
|
|
|
func (m *Model) HasField(field string) (bool, error) {
|
2022-05-10 16:31:56 +08:00
|
|
|
return m.db.GetCore().HasField(m.GetCtx(), m.tablesInit, field)
|
2020-07-21 13:28:25 +08:00
|
|
|
}
|
2022-05-25 16:22:46 +08:00
|
|
|
|
2023-11-20 20:47:26 +08:00
|
|
|
// getFieldsFrom retrieves, filters and returns fields name from table `table`.
|
2024-10-21 09:22:31 +08:00
|
|
|
func (m *Model) filterFieldsFrom(table string, fieldNamesOrMapStruct ...any) []any {
|
2022-05-25 16:22:46 +08:00
|
|
|
length := len(fieldNamesOrMapStruct)
|
|
|
|
if length == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
switch {
|
|
|
|
// String slice.
|
|
|
|
case length >= 2:
|
2023-11-20 20:47:26 +08:00
|
|
|
return m.mappingAndFilterToTableFields(
|
2024-10-21 09:22:31 +08:00
|
|
|
table, fieldNamesOrMapStruct, true,
|
2023-11-20 20:47:26 +08:00
|
|
|
)
|
2022-05-25 16:22:46 +08:00
|
|
|
|
|
|
|
// It needs type asserting.
|
|
|
|
case length == 1:
|
|
|
|
structOrMap := fieldNamesOrMapStruct[0]
|
|
|
|
switch r := structOrMap.(type) {
|
|
|
|
case string:
|
2024-10-21 09:22:31 +08:00
|
|
|
return m.mappingAndFilterToTableFields(table, []any{r}, false)
|
2022-05-25 16:22:46 +08:00
|
|
|
|
|
|
|
case []string:
|
2024-10-21 09:22:31 +08:00
|
|
|
return m.mappingAndFilterToTableFields(table, gconv.Interfaces(r), true)
|
2022-05-25 16:22:46 +08:00
|
|
|
|
|
|
|
case Raw, *Raw:
|
2024-10-21 09:22:31 +08:00
|
|
|
return []any{structOrMap}
|
2022-05-25 16:22:46 +08:00
|
|
|
|
|
|
|
default:
|
2023-11-20 20:47:26 +08:00
|
|
|
return m.mappingAndFilterToTableFields(table, getFieldsFromStructOrMap(structOrMap), true)
|
2022-05-25 16:22:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-21 09:22:31 +08:00
|
|
|
func (m *Model) appendToFields(fields ...any) *Model {
|
|
|
|
if len(fields) == 0 {
|
|
|
|
return m
|
2022-05-25 16:22:46 +08:00
|
|
|
}
|
2024-10-21 09:22:31 +08:00
|
|
|
model := m.getModel()
|
|
|
|
model.fields = append(model.fields, fields...)
|
|
|
|
return model
|
2022-05-25 16:22:46 +08:00
|
|
|
}
|
|
|
|
|
2024-09-13 16:50:38 +08:00
|
|
|
func (m *Model) isFieldInFieldsEx(field string) bool {
|
|
|
|
for _, v := range m.fieldsEx {
|
|
|
|
if v == field {
|
|
|
|
return true
|
2022-05-25 16:22:46 +08:00
|
|
|
}
|
|
|
|
}
|
2024-09-13 16:50:38 +08:00
|
|
|
return false
|
2022-05-25 16:22:46 +08:00
|
|
|
}
|