mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
merge IgnoreEmptySliceWhere feature into OmitEmptyWhere
This commit is contained in:
@ -402,13 +402,12 @@ func formatSql(sql string, args []interface{}) (newSql string, newArgs []interfa
|
||||
}
|
||||
|
||||
type formatWhereInput struct {
|
||||
Where interface{}
|
||||
Args []interface{}
|
||||
OmitNil bool
|
||||
OmitEmpty bool
|
||||
IgnoreEmptySliceWhere bool
|
||||
Schema string
|
||||
Table string
|
||||
Where interface{}
|
||||
Args []interface{}
|
||||
OmitNil bool
|
||||
OmitEmpty bool
|
||||
Schema string
|
||||
Table string
|
||||
}
|
||||
|
||||
// formatWhere formats where statement and its arguments for `Where` and `Having` statements.
|
||||
@ -432,12 +431,11 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
}
|
||||
}
|
||||
newArgs = formatWhereKeyValue(formatWhereKeyValueInput{
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: key,
|
||||
Value: value,
|
||||
IgnoreEmptySliceWhere: in.IgnoreEmptySliceWhere,
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
|
||||
@ -458,12 +456,12 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
}
|
||||
}
|
||||
newArgs = formatWhereKeyValue(formatWhereKeyValueInput{
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: ketStr,
|
||||
Value: value,
|
||||
IgnoreEmptySliceWhere: in.IgnoreEmptySliceWhere,
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: ketStr,
|
||||
Value: value,
|
||||
OmitEmpty: in.OmitEmpty,
|
||||
})
|
||||
return true
|
||||
})
|
||||
@ -490,12 +488,12 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
continue
|
||||
}
|
||||
newArgs = formatWhereKeyValue(formatWhereKeyValueInput{
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: foundKey,
|
||||
Value: foundValue,
|
||||
IgnoreEmptySliceWhere: in.IgnoreEmptySliceWhere,
|
||||
Db: db,
|
||||
Buffer: buffer,
|
||||
Args: newArgs,
|
||||
Key: foundKey,
|
||||
Value: foundValue,
|
||||
OmitEmpty: in.OmitEmpty,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -507,13 +505,13 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
whereStr = gconv.String(in.Where)
|
||||
)
|
||||
// Eg:
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// IgnoreEmptySliceWhere().Where("id", []int{}).One() -> SELECT xxx FROM xxx
|
||||
if in.IgnoreEmptySliceWhere && len(in.Args) == 1 && utils.IsArray(in.Args[0]) {
|
||||
if gstr.Count(whereStr, "?") == 0 && utils.IsEmpty(in.Args[0]) {
|
||||
in.Args = in.Args[:0]
|
||||
break
|
||||
}
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// Where("name", "").All() -> SELECT xxx FROM xxx WHERE `name`=''
|
||||
// OmitEmpty().Where("id", []int{}).All() -> SELECT xxx FROM xxx
|
||||
// OmitEmpty().("name", "").All() -> SELECT xxx FROM xxx
|
||||
if in.OmitEmpty && len(in.Args) == 1 && gstr.Count(whereStr, "?") == 0 && utils.IsEmpty(in.Args[0]) {
|
||||
in.Args = in.Args[:0]
|
||||
break
|
||||
}
|
||||
for {
|
||||
if i >= len(in.Args) {
|
||||
@ -608,17 +606,31 @@ func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, new
|
||||
}
|
||||
|
||||
type formatWhereKeyValueInput struct {
|
||||
Db DB
|
||||
Buffer *bytes.Buffer
|
||||
Args []interface{}
|
||||
Key string
|
||||
Value interface{}
|
||||
IgnoreEmptySliceWhere bool
|
||||
Db DB
|
||||
Buffer *bytes.Buffer
|
||||
Args []interface{}
|
||||
Key string
|
||||
Value interface{}
|
||||
OmitEmpty bool
|
||||
}
|
||||
|
||||
// formatWhereKeyValue handles each key-value pair of the parameter map.
|
||||
func formatWhereKeyValue(in formatWhereKeyValueInput) (newArgs []interface{}) {
|
||||
quotedKey := in.Db.GetCore().QuoteWord(in.Key)
|
||||
var (
|
||||
quotedKey = in.Db.GetCore().QuoteWord(in.Key)
|
||||
holderCount = gstr.Count(quotedKey, "?")
|
||||
)
|
||||
// Eg:
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// Where("name", "").All() -> SELECT xxx FROM xxx WHERE `name`=''
|
||||
// OmitEmpty().Where("id", []int{}).All() -> SELECT xxx FROM xxx
|
||||
// OmitEmpty().("name", "").All() -> SELECT xxx FROM xxx
|
||||
if in.OmitEmpty && holderCount == 0 && gutil.IsEmpty(in.Value) {
|
||||
return in.Args
|
||||
}
|
||||
if in.Buffer.Len() > 0 {
|
||||
in.Buffer.WriteString(" AND ")
|
||||
}
|
||||
// If the value is type of slice, and there's only one '?' holder in
|
||||
// the key string, it automatically adds '?' holder chars according to its arguments count
|
||||
// and converts it to "IN" statement.
|
||||
@ -629,22 +641,11 @@ func formatWhereKeyValue(in formatWhereKeyValueInput) (newArgs []interface{}) {
|
||||
switch reflectKind {
|
||||
// Slice argument.
|
||||
case reflect.Slice, reflect.Array:
|
||||
count := gstr.Count(quotedKey, "?")
|
||||
// Eg:
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// IgnoreEmptySliceWhere().Where("id", []int{}).One() -> SELECT xxx FROM xxx
|
||||
if count == 0 && reflectValue.Len() == 0 && in.IgnoreEmptySliceWhere {
|
||||
return in.Args
|
||||
}
|
||||
|
||||
if in.Buffer.Len() > 0 {
|
||||
in.Buffer.WriteString(" AND ")
|
||||
}
|
||||
if count == 0 {
|
||||
if holderCount == 0 {
|
||||
in.Buffer.WriteString(quotedKey + " IN(?)")
|
||||
in.Args = append(in.Args, in.Value)
|
||||
} else {
|
||||
if count != reflectValue.Len() {
|
||||
if holderCount != reflectValue.Len() {
|
||||
in.Buffer.WriteString(quotedKey)
|
||||
in.Args = append(in.Args, in.Value)
|
||||
} else {
|
||||
@ -654,9 +655,6 @@ func formatWhereKeyValue(in formatWhereKeyValueInput) (newArgs []interface{}) {
|
||||
}
|
||||
|
||||
default:
|
||||
if in.Buffer.Len() > 0 {
|
||||
in.Buffer.WriteString(" AND ")
|
||||
}
|
||||
if in.Value == nil || empty.IsNil(reflectValue) {
|
||||
if gregex.IsMatchString(regularFieldNameRegPattern, in.Key) {
|
||||
// The key is a single field name.
|
||||
|
||||
@ -340,13 +340,12 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
|
||||
case whereHolderOperatorWhere:
|
||||
if conditionWhere == "" {
|
||||
newWhere, newArgs := formatWhere(m.db, formatWhereInput{
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
IgnoreEmptySliceWhere: m.option&optionIgnoreEmptySliceWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
})
|
||||
if len(newWhere) > 0 {
|
||||
conditionWhere = newWhere
|
||||
@ -358,13 +357,12 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
|
||||
|
||||
case whereHolderOperatorAnd:
|
||||
newWhere, newArgs := formatWhere(m.db, formatWhereInput{
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
IgnoreEmptySliceWhere: m.option&optionIgnoreEmptySliceWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
})
|
||||
if len(newWhere) > 0 {
|
||||
if len(conditionWhere) == 0 {
|
||||
@ -379,13 +377,12 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
|
||||
|
||||
case whereHolderOperatorOr:
|
||||
newWhere, newArgs := formatWhere(m.db, formatWhereInput{
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
IgnoreEmptySliceWhere: m.option&optionIgnoreEmptySliceWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
Where: v.Where,
|
||||
Args: v.Args,
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
})
|
||||
if len(newWhere) > 0 {
|
||||
if len(conditionWhere) == 0 {
|
||||
@ -427,13 +424,12 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
|
||||
// HAVING.
|
||||
if len(m.having) > 0 {
|
||||
havingStr, havingArgs := formatWhere(m.db, formatWhereInput{
|
||||
Where: m.having[0],
|
||||
Args: gconv.Interfaces(m.having[1]),
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
IgnoreEmptySliceWhere: m.option&optionIgnoreEmptySliceWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
Where: m.having[0],
|
||||
Args: gconv.Interfaces(m.having[1]),
|
||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||
Schema: m.schema,
|
||||
Table: m.tables,
|
||||
})
|
||||
if len(havingStr) > 0 {
|
||||
conditionExtra += " HAVING " + havingStr
|
||||
|
||||
@ -7,27 +7,14 @@
|
||||
package gdb
|
||||
|
||||
const (
|
||||
optionOmitNil = optionOmitNilWhere | optionOmitNilData
|
||||
optionOmitEmpty = optionOmitEmptyWhere | optionOmitEmptyData
|
||||
optionOmitEmptyWhere = 1 << iota // 8
|
||||
optionOmitEmptyData // 16
|
||||
optionOmitNilWhere // 32
|
||||
optionOmitNilData // 64
|
||||
optionIgnoreEmptySliceWhere // 128
|
||||
optionOmitNil = optionOmitNilWhere | optionOmitNilData
|
||||
optionOmitEmpty = optionOmitEmptyWhere | optionOmitEmptyData
|
||||
optionOmitEmptyWhere = 1 << iota // 8
|
||||
optionOmitEmptyData // 16
|
||||
optionOmitNilWhere // 32
|
||||
optionOmitNilData // 64
|
||||
)
|
||||
|
||||
// IgnoreEmptySliceWhere sets optionIgnoreEmptySliceWhere option for the model, which automatically filers
|
||||
// the where parameters for `empty` slice values.
|
||||
//
|
||||
// Eg:
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// OmitEmptyWhereSlice().Where("id", []int{}).One() -> SELECT xxx FROM xxx
|
||||
func (m *Model) IgnoreEmptySliceWhere() *Model {
|
||||
model := m.getModel()
|
||||
model.option = model.option | optionIgnoreEmptySliceWhere
|
||||
return model
|
||||
}
|
||||
|
||||
// OmitEmpty sets optionOmitEmpty option for the model, which automatically filers
|
||||
// the data and where parameters for `empty` values.
|
||||
func (m *Model) OmitEmpty() *Model {
|
||||
@ -38,6 +25,12 @@ func (m *Model) OmitEmpty() *Model {
|
||||
|
||||
// OmitEmptyWhere sets optionOmitEmptyWhere option for the model, which automatically filers
|
||||
// the Where/Having parameters for `empty` values.
|
||||
//
|
||||
// Eg:
|
||||
// Where("id", []int{}).All() -> SELECT xxx FROM xxx WHERE 0=1
|
||||
// Where("name", "").All() -> SELECT xxx FROM xxx WHERE `name`=''
|
||||
// OmitEmpty().Where("id", []int{}).All() -> SELECT xxx FROM xxx
|
||||
// OmitEmpty().("name", "").All() -> SELECT xxx FROM xxx
|
||||
func (m *Model) OmitEmptyWhere() *Model {
|
||||
model := m.getModel()
|
||||
model.option = model.option | optionOmitEmptyWhere
|
||||
|
||||
@ -3676,11 +3676,27 @@ func Test_Model_FieldAvg(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_IgnoreEmptySliceWhere(t *testing.T) {
|
||||
func Test_Model_OmitEmptyWhere(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
// Key-Value where.
|
||||
// Basic type where.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).Where("id", 0).Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 0)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Where("nickname", "").Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
// Slice where.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).Where("id", g.Slice{1, 2, 3}).Count()
|
||||
t.AssertNil(err)
|
||||
@ -3692,19 +3708,20 @@ func Test_Model_IgnoreEmptySliceWhere(t *testing.T) {
|
||||
t.Assert(count, 0)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).IgnoreEmptySliceWhere().Where("id", g.Slice{}).Count()
|
||||
count, err := db.Model(table).OmitEmptyWhere().Where("id", g.Slice{}).Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).Where("id", g.Slice{}).IgnoreEmptySliceWhere().Count()
|
||||
count, err := db.Model(table).Where("id", g.Slice{}).OmitEmptyWhere().Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
// Struct Where.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type Input struct {
|
||||
Id []int
|
||||
Id []int
|
||||
Name []string
|
||||
}
|
||||
count, err := db.Model(table).Where(Input{}).Count()
|
||||
t.AssertNil(err)
|
||||
@ -3712,16 +3729,18 @@ func Test_Model_IgnoreEmptySliceWhere(t *testing.T) {
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type Input struct {
|
||||
Id []int
|
||||
Id []int
|
||||
Name []string
|
||||
}
|
||||
count, err := db.Model(table).Where(Input{}).IgnoreEmptySliceWhere().Count()
|
||||
count, err := db.Model(table).Where(Input{}).OmitEmptyWhere().Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
// Map Where.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
count, err := db.Model(table).Where(g.Map{
|
||||
"id": []int{},
|
||||
"id": []int{},
|
||||
"nickname": []string{},
|
||||
}).Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 0)
|
||||
@ -3732,7 +3751,7 @@ func Test_Model_IgnoreEmptySliceWhere(t *testing.T) {
|
||||
}
|
||||
count, err := db.Model(table).Where(g.Map{
|
||||
"id": []int{},
|
||||
}).IgnoreEmptySliceWhere().Count()
|
||||
}).OmitEmptyWhere().Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, TableSize)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user