mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
add FieldCount/FieldSum/FieldMax/FieldMin/FieldAvg functions for gdb.Model
This commit is contained in:
@ -31,6 +31,7 @@ func (c *Core) SlaveLink(schema ...string) (Link, error) {
|
||||
|
||||
// QuoteWord checks given string `s` a word, if true quotes it with security chars of the database
|
||||
// and returns the quoted string; or else return `s` without any change.
|
||||
// The meaning of a `word` can be considered as a column name.
|
||||
func (c *Core) QuoteWord(s string) string {
|
||||
charLeft, charRight := c.db.GetChars()
|
||||
return doQuoteWord(s, charLeft, charRight)
|
||||
@ -38,6 +39,7 @@ func (c *Core) QuoteWord(s string) string {
|
||||
|
||||
// QuoteString quotes string with quote chars. Strings like:
|
||||
// "user", "user u", "user,user_detail", "user u, user_detail ut", "u.id asc".
|
||||
// The meaning of a `string` can be considered as part of a statement string including columns.
|
||||
func (c *Core) QuoteString(s string) string {
|
||||
charLeft, charRight := c.db.GetChars()
|
||||
return doQuoteString(s, charLeft, charRight)
|
||||
|
||||
@ -73,6 +73,7 @@ const (
|
||||
whereHolderOperatorWhere = 1
|
||||
whereHolderOperatorAnd = 2
|
||||
whereHolderOperatorOr = 3
|
||||
defaultFields = "*"
|
||||
)
|
||||
|
||||
// Table is alias of Core.Model.
|
||||
@ -130,7 +131,7 @@ func (c *Core) Model(tableNameQueryOrStruct ...interface{}) *Model {
|
||||
db: c.db,
|
||||
tablesInit: tableStr,
|
||||
tables: tableStr,
|
||||
fields: "*",
|
||||
fields: defaultFields,
|
||||
start: -1,
|
||||
offset: -1,
|
||||
filter: true,
|
||||
|
||||
@ -237,10 +237,13 @@ func (m *Model) WhereOrNotNull(columns ...string) *Model {
|
||||
}
|
||||
|
||||
// Group sets the "GROUP BY" statement for the model.
|
||||
func (m *Model) Group(groupBy string) *Model {
|
||||
model := m.getModel()
|
||||
model.groupBy = m.db.GetCore().QuoteString(groupBy)
|
||||
return model
|
||||
func (m *Model) Group(groupBy ...string) *Model {
|
||||
if len(groupBy) > 0 {
|
||||
model := m.getModel()
|
||||
model.groupBy = m.db.GetCore().QuoteString(gstr.Join(groupBy, ","))
|
||||
return model
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// And adds "AND" condition to the where statement.
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
)
|
||||
|
||||
// Fields sets the operation fields of the model, multiple fields joined using char ','.
|
||||
// Fields appends `fieldNamesOrMapStruct` to the operation fields of the model, multiple fields joined using char ','.
|
||||
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
||||
func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model {
|
||||
length := len(fieldNamesOrMapStruct)
|
||||
@ -24,26 +24,32 @@ func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model {
|
||||
switch {
|
||||
// String slice.
|
||||
case length >= 2:
|
||||
model := m.getModel()
|
||||
model.fields = gstr.Join(m.mappingAndFilterToTableFields(gconv.Strings(fieldNamesOrMapStruct), true), ",")
|
||||
return model
|
||||
// It need type asserting.
|
||||
return m.appendFieldsByStr(gstr.Join(
|
||||
m.mappingAndFilterToTableFields(gconv.Strings(fieldNamesOrMapStruct), true),
|
||||
",",
|
||||
))
|
||||
// It needs type asserting.
|
||||
case length == 1:
|
||||
model := m.getModel()
|
||||
switch r := fieldNamesOrMapStruct[0].(type) {
|
||||
case string:
|
||||
model.fields = gstr.Join(m.mappingAndFilterToTableFields([]string{r}, false), ",")
|
||||
return m.appendFieldsByStr(gstr.Join(
|
||||
m.mappingAndFilterToTableFields([]string{r}, false), ",",
|
||||
))
|
||||
case []string:
|
||||
model.fields = gstr.Join(m.mappingAndFilterToTableFields(r, true), ",")
|
||||
return m.appendFieldsByStr(gstr.Join(
|
||||
m.mappingAndFilterToTableFields(r, true), ",",
|
||||
))
|
||||
default:
|
||||
model.fields = gstr.Join(m.mappingAndFilterToTableFields(gutil.Keys(r), true), ",")
|
||||
return m.appendFieldsByStr(gstr.Join(
|
||||
m.mappingAndFilterToTableFields(gutil.Keys(r), true), ",",
|
||||
))
|
||||
}
|
||||
return model
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
|
||||
// FieldsEx appends `fieldNamesOrMapStruct` to the excluded operation fields of the model,
|
||||
// multiple fields joined using char ','.
|
||||
// Note that this function supports only single table operations.
|
||||
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
||||
func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model {
|
||||
@ -70,6 +76,78 @@ func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model {
|
||||
return m
|
||||
}
|
||||
|
||||
// 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]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`COUNT(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
// 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]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`SUM(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
// 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]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`MIN(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
// 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]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`MAX(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
// 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]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
func (m *Model) appendFieldsByStr(fields string) *Model {
|
||||
if fields != "" {
|
||||
model := m.getModel()
|
||||
if model.fields == defaultFields {
|
||||
model.fields = ""
|
||||
}
|
||||
if model.fields != "" {
|
||||
model.fields += ","
|
||||
}
|
||||
model.fields += fields
|
||||
return model
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Model) appendFieldsExByStr(fieldsEx string) *Model {
|
||||
if fieldsEx != "" {
|
||||
model := m.getModel()
|
||||
if model.fieldsEx != "" {
|
||||
model.fieldsEx += ","
|
||||
}
|
||||
model.fieldsEx += fieldsEx
|
||||
return model
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Filter marks filtering the fields which does not exist in the fields of the operated table.
|
||||
// Note that this function supports only single table operations.
|
||||
// Deprecated, filter feature is automatically enabled from GoFrame v1.16.0, it is so no longer used.
|
||||
|
||||
@ -3768,3 +3768,55 @@ func Test_Model_Handler(t *testing.T) {
|
||||
t.Assert(all[2]["id"], 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldCount(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
all, err := db.Model(table).Fields("id").FieldCount("id", "total").Group("id").OrderAsc("id").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(all), TableSize)
|
||||
t.Assert(all[0]["id"], 1)
|
||||
t.Assert(all[0]["total"], 1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldMax(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
all, err := db.Model(table).Fields("id").FieldMax("id", "total").Group("id").OrderAsc("id").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(all), TableSize)
|
||||
t.Assert(all[0]["id"], 1)
|
||||
t.Assert(all[0]["total"], 1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldMin(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
all, err := db.Model(table).Fields("id").FieldMin("id", "total").Group("id").OrderAsc("id").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(all), TableSize)
|
||||
t.Assert(all[0]["id"], 1)
|
||||
t.Assert(all[0]["total"], 1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldAvg(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
all, err := db.Model(table).Fields("id").FieldAvg("id", "total").Group("id").OrderAsc("id").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(all), TableSize)
|
||||
t.Assert(all[0]["id"], 1)
|
||||
t.Assert(all[0]["total"], 1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -153,13 +153,17 @@ func (m *middleware) callHandlerFunc(funcInfo handlerFuncInfo) {
|
||||
switch len(results) {
|
||||
case 1:
|
||||
if !results[0].IsNil() {
|
||||
m.request.handlerResponse.Error = results[0].Interface().(error)
|
||||
if err, ok := results[0].Interface().(error); ok {
|
||||
m.request.handlerResponse.Error = err
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
m.request.handlerResponse.Object = results[0].Interface()
|
||||
if !results[1].IsNil() {
|
||||
m.request.handlerResponse.Error = results[1].Interface().(error)
|
||||
if err, ok := results[1].Interface().(error); ok {
|
||||
m.request.handlerResponse.Error = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,9 +24,9 @@ import (
|
||||
// required-if format: required-if:field,value,... brief: Required unless all given field and its value are equal.
|
||||
// required-unless format: required-unless:field,value,... brief: Required unless all given field and its value are not equal.
|
||||
// required-with format: required-with:field1,field2,... brief: Required if any of given fields are not empty.
|
||||
// required-with-all format: required-with-all:field1,field2,... brief: Required if all of given fields are not empty.
|
||||
// required-with-all format: required-with-all:field1,field2,... brief: Required if all given fields are not empty.
|
||||
// required-without format: required-without:field1,field2,... brief: Required if any of given fields are empty.
|
||||
// required-without-all format: required-without-all:field1,field2,...brief: Required if all of given fields are empty.
|
||||
// required-without-all format: required-without-all:field1,field2,...brief: Required if all given fields are empty.
|
||||
// bail format: bail brief: Stop validating when this field's validation failed.
|
||||
// date format: date brief: Standard date, like: 2006-01-02, 20060102, 2006.01.02
|
||||
// date-format format: date-format:format brief: Custom date format.
|
||||
|
||||
Reference in New Issue
Block a user