mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 20:28:17 +08:00
Merge branch 'master' of https://github.com/gogf/gf
This commit is contained in:
commit
3f4dff462d
@ -8,11 +8,6 @@ package garray
|
|||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
// iInterfaces is used for type assert api for Interfaces.
|
|
||||||
type iInterfaces interface {
|
|
||||||
Interfaces() []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultComparatorInt for int comparison.
|
// defaultComparatorInt for int comparison.
|
||||||
func defaultComparatorInt(a, b int) int {
|
func defaultComparatorInt(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
|
@ -31,7 +31,7 @@ func ExampleStrArray_Walk() {
|
|||||||
// [gf_user gf_user_detail]
|
// [gf_user gf_user_detail]
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleStrArray_NewStrArray() {
|
func ExampleNewStrArray() {
|
||||||
s := garray.NewStrArray()
|
s := garray.NewStrArray()
|
||||||
s.Append("We")
|
s.Append("We")
|
||||||
s.Append("are")
|
s.Append("are")
|
||||||
@ -43,7 +43,7 @@ func ExampleStrArray_NewStrArray() {
|
|||||||
// [We are GF fans]
|
// [We are GF fans]
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleStrArray_NewStrArraySize() {
|
func ExampleNewStrArraySize() {
|
||||||
s := garray.NewStrArraySize(3, 5)
|
s := garray.NewStrArraySize(3, 5)
|
||||||
s.Set(0, "We")
|
s.Set(0, "We")
|
||||||
s.Set(1, "are")
|
s.Set(1, "are")
|
||||||
@ -55,7 +55,7 @@ func ExampleStrArray_NewStrArraySize() {
|
|||||||
// [We are GF] 3 5
|
// [We are GF] 3 5
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleStrArray_NewStrArrayFrom() {
|
func ExampleNewStrArrayFrom() {
|
||||||
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
||||||
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
|
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
|
||||||
|
|
||||||
@ -63,14 +63,6 @@ func ExampleStrArray_NewStrArrayFrom() {
|
|||||||
// [We are GF fans !] 5 5
|
// [We are GF fans !] 5 5
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleStrArray_NewStrArrayFromCopy() {
|
|
||||||
s := garray.NewStrArrayFromCopy(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
|
||||||
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// [We are GF fans !] 5 5
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleStrArray_At() {
|
func ExampleStrArray_At() {
|
||||||
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
||||||
sAt := s.At(2)
|
sAt := s.At(2)
|
@ -376,7 +376,7 @@ func formatSql(sql string, args []interface{}) (newSql string, newArgs []interfa
|
|||||||
return handleArguments(sql, args)
|
return handleArguments(sql, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
type formatWhereInput struct {
|
type formatWhereHolderInput struct {
|
||||||
Where interface{}
|
Where interface{}
|
||||||
Args []interface{}
|
Args []interface{}
|
||||||
OmitNil bool
|
OmitNil bool
|
||||||
@ -386,8 +386,8 @@ type formatWhereInput struct {
|
|||||||
Prefix string // Field prefix, eg: "user.", "order.".
|
Prefix string // Field prefix, eg: "user.", "order.".
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatWhere formats where statement and its arguments for `Where` and `Having` statements.
|
// formatWhereHolder formats where statement and its arguments for `Where` and `Having` statements.
|
||||||
func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interface{}) {
|
func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newArgs []interface{}) {
|
||||||
var (
|
var (
|
||||||
buffer = bytes.NewBuffer(nil)
|
buffer = bytes.NewBuffer(nil)
|
||||||
reflectInfo = utils.OriginValueAndKind(in.Where)
|
reflectInfo = utils.OriginValueAndKind(in.Where)
|
||||||
@ -454,8 +454,8 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
|||||||
var (
|
var (
|
||||||
reflectType = reflectInfo.OriginValue.Type()
|
reflectType = reflectInfo.OriginValue.Type()
|
||||||
structField reflect.StructField
|
structField reflect.StructField
|
||||||
|
data = DataToMapDeep(in.Where)
|
||||||
)
|
)
|
||||||
data := DataToMapDeep(in.Where)
|
|
||||||
if in.Table != "" {
|
if in.Table != "" {
|
||||||
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
|
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
|
||||||
}
|
}
|
||||||
@ -484,9 +484,7 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
// Usually a string.
|
// Usually a string.
|
||||||
|
|
||||||
whereStr := gconv.String(in.Where)
|
whereStr := gconv.String(in.Where)
|
||||||
|
|
||||||
// Is `whereStr` a field name which composed as a key-value condition?
|
// Is `whereStr` a field name which composed as a key-value condition?
|
||||||
// Eg:
|
// Eg:
|
||||||
// Where("id", 1)
|
// Where("id", 1)
|
||||||
@ -514,9 +512,7 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
|||||||
// Regular string and parameter place holder handling.
|
// Regular string and parameter place holder handling.
|
||||||
// Eg:
|
// Eg:
|
||||||
// Where("id in(?) and name=?", g.Slice{1,2,3}, "john")
|
// Where("id in(?) and name=?", g.Slice{1,2,3}, "john")
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if i >= len(in.Args) {
|
if i >= len(in.Args) {
|
||||||
break
|
break
|
||||||
@ -608,13 +604,13 @@ func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, new
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatWhereKeyValueInput struct {
|
type formatWhereKeyValueInput struct {
|
||||||
Db DB
|
Db DB // Db is the underlying DB object for current operation.
|
||||||
Buffer *bytes.Buffer
|
Buffer *bytes.Buffer // Buffer is the sql statement string without Args for current operation.
|
||||||
Args []interface{}
|
Args []interface{} // Args is the full arguments of current operation.
|
||||||
Key string
|
Key string // The field name, eg: "id", "name", etc.
|
||||||
Value interface{}
|
Value interface{} // The field value, can be any types.
|
||||||
OmitEmpty bool
|
OmitEmpty bool // Ignores current condition key if `value` is empty.
|
||||||
Prefix string // Field prefix, eg: "user.", "order.".
|
Prefix string // Field prefix, eg: "user", "order", etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatWhereKeyValue handles each key-value pair of the parameter map.
|
// formatWhereKeyValue handles each key-value pair of the parameter map.
|
||||||
|
@ -95,7 +95,7 @@ func (c *Core) Model(tableNameQueryOrStruct ...interface{}) *Model {
|
|||||||
if len(tableNameQueryOrStruct) > 1 {
|
if len(tableNameQueryOrStruct) > 1 {
|
||||||
conditionStr := gconv.String(tableNameQueryOrStruct[0])
|
conditionStr := gconv.String(tableNameQueryOrStruct[0])
|
||||||
if gstr.Contains(conditionStr, "?") {
|
if gstr.Contains(conditionStr, "?") {
|
||||||
tableStr, extraArgs = formatWhere(c.db, formatWhereInput{
|
tableStr, extraArgs = formatWhereHolder(c.db, formatWhereHolderInput{
|
||||||
Where: conditionStr,
|
Where: conditionStr,
|
||||||
Args: tableNameQueryOrStruct[1:],
|
Args: tableNameQueryOrStruct[1:],
|
||||||
OmitNil: false,
|
OmitNil: false,
|
||||||
|
@ -1,456 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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 (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Where sets the condition statement for the model. The parameter `where` can be type of
|
|
||||||
// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
|
|
||||||
// multiple conditions will be joined into where statement using "AND".
|
|
||||||
// Eg:
|
|
||||||
// Where("uid=10000")
|
|
||||||
// Where("uid", 10000)
|
|
||||||
// Where("money>? AND name like ?", 99999, "vip_%")
|
|
||||||
// Where("uid", 1).Where("name", "john")
|
|
||||||
// Where("status IN (?)", g.Slice{1,2,3})
|
|
||||||
// Where("age IN(?,?)", 18, 50)
|
|
||||||
// Where(User{ Id : 1, UserName : "john"}).
|
|
||||||
func (m *Model) Where(where interface{}, args ...interface{}) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
if model.whereHolder == nil {
|
|
||||||
model.whereHolder = make([]ModelWhereHolder, 0)
|
|
||||||
}
|
|
||||||
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
|
||||||
Operator: whereHolderOperatorWhere,
|
|
||||||
Where: where,
|
|
||||||
Args: args,
|
|
||||||
})
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WherePrefix performs as Where, but it adds prefix to each field in where statement.
|
|
||||||
func (m *Model) WherePrefix(prefix string, where interface{}, args ...interface{}) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
if model.whereHolder == nil {
|
|
||||||
model.whereHolder = make([]ModelWhereHolder, 0)
|
|
||||||
}
|
|
||||||
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
|
||||||
Operator: whereHolderOperatorWhere,
|
|
||||||
Where: where,
|
|
||||||
Args: args,
|
|
||||||
Prefix: prefix,
|
|
||||||
})
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Having sets the having statement for the model.
|
|
||||||
// The parameters of this function usage are as the same as function Where.
|
|
||||||
// See Where.
|
|
||||||
func (m *Model) Having(having interface{}, args ...interface{}) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
model.having = []interface{}{
|
|
||||||
having, args,
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WherePri does the same logic as Model.Where except that if the parameter `where`
|
|
||||||
// is a single condition like int/string/float/slice, it treats the condition as the primary
|
|
||||||
// key value. That is, if primary key is "id" and given `where` parameter as "123", the
|
|
||||||
// WherePri function treats the condition as "id=123", but Model.Where treats the condition
|
|
||||||
// as string "123".
|
|
||||||
func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
|
|
||||||
if len(args) > 0 {
|
|
||||||
return m.Where(where, args...)
|
|
||||||
}
|
|
||||||
newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
|
|
||||||
return m.Where(newWhere[0], newWhere[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wheref builds condition string using fmt.Sprintf and arguments.
|
|
||||||
// Note that if the number of `args` is more than the placeholder in `format`,
|
|
||||||
// the extra `args` will be used as the where condition arguments of the Model.
|
|
||||||
func (m *Model) Wheref(format string, args ...interface{}) *Model {
|
|
||||||
var (
|
|
||||||
placeHolderCount = gstr.Count(format, "?")
|
|
||||||
conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
|
|
||||||
)
|
|
||||||
return m.Where(conditionStr, args[len(args)-placeHolderCount:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereLT builds `column < value` statement.
|
|
||||||
func (m *Model) WhereLT(column string, value interface{}) *Model {
|
|
||||||
return m.Wheref(`%s < ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereLTE builds `column <= value` statement.
|
|
||||||
func (m *Model) WhereLTE(column string, value interface{}) *Model {
|
|
||||||
return m.Wheref(`%s <= ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereGT builds `column > value` statement.
|
|
||||||
func (m *Model) WhereGT(column string, value interface{}) *Model {
|
|
||||||
return m.Wheref(`%s > ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereGTE builds `column >= value` statement.
|
|
||||||
func (m *Model) WhereGTE(column string, value interface{}) *Model {
|
|
||||||
return m.Wheref(`%s >= ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereBetween builds `column BETWEEN min AND max` statement.
|
|
||||||
func (m *Model) WhereBetween(column string, min, max interface{}) *Model {
|
|
||||||
return m.Wheref(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereLike builds `column LIKE like` statement.
|
|
||||||
func (m *Model) WhereLike(column string, like interface{}) *Model {
|
|
||||||
return m.Wheref(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereIn builds `column IN (in)` statement.
|
|
||||||
func (m *Model) WhereIn(column string, in interface{}) *Model {
|
|
||||||
return m.Wheref(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNull builds `columns[0] IS NULL AND columns[1] IS NULL ...` statement.
|
|
||||||
func (m *Model) WhereNull(columns ...string) *Model {
|
|
||||||
model := m
|
|
||||||
for _, column := range columns {
|
|
||||||
model = m.Wheref(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNotBetween builds `column NOT BETWEEN min AND max` statement.
|
|
||||||
func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model {
|
|
||||||
return m.Wheref(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNotLike builds `column NOT LIKE like` statement.
|
|
||||||
func (m *Model) WhereNotLike(column string, like interface{}) *Model {
|
|
||||||
return m.Wheref(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNot builds `column != value` statement.
|
|
||||||
func (m *Model) WhereNot(column string, value interface{}) *Model {
|
|
||||||
return m.Wheref(`%s != ?`, m.db.GetCore().QuoteWord(column), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNotIn builds `column NOT IN (in)` statement.
|
|
||||||
func (m *Model) WhereNotIn(column string, in interface{}) *Model {
|
|
||||||
return m.Wheref(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereNotNull builds `columns[0] IS NOT NULL AND columns[1] IS NOT NULL ...` statement.
|
|
||||||
func (m *Model) WhereNotNull(columns ...string) *Model {
|
|
||||||
model := m
|
|
||||||
for _, column := range columns {
|
|
||||||
model = m.Wheref(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOr adds "OR" condition to the where statement.
|
|
||||||
func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
if model.whereHolder == nil {
|
|
||||||
model.whereHolder = make([]ModelWhereHolder, 0)
|
|
||||||
}
|
|
||||||
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
|
||||||
Operator: whereHolderOperatorOr,
|
|
||||||
Where: where,
|
|
||||||
Args: args,
|
|
||||||
})
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrPrefix performs as WhereOr, but it adds prefix to each field in where statement.
|
|
||||||
func (m *Model) WhereOrPrefix(prefix string, where interface{}, args ...interface{}) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
if model.whereHolder == nil {
|
|
||||||
model.whereHolder = make([]ModelWhereHolder, 0)
|
|
||||||
}
|
|
||||||
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
|
||||||
Operator: whereHolderOperatorOr,
|
|
||||||
Where: where,
|
|
||||||
Args: args,
|
|
||||||
Prefix: prefix,
|
|
||||||
})
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrf builds `OR` condition string using fmt.Sprintf and arguments.
|
|
||||||
func (m *Model) WhereOrf(format string, args ...interface{}) *Model {
|
|
||||||
var (
|
|
||||||
placeHolderCount = gstr.Count(format, "?")
|
|
||||||
conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
|
|
||||||
)
|
|
||||||
return m.WhereOr(conditionStr, args[len(args)-placeHolderCount:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrLT builds `column < value` statement in `OR` conditions..
|
|
||||||
func (m *Model) WhereOrLT(column string, value interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s < ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrLTE builds `column <= value` statement in `OR` conditions..
|
|
||||||
func (m *Model) WhereOrLTE(column string, value interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s <= ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrGT builds `column > value` statement in `OR` conditions..
|
|
||||||
func (m *Model) WhereOrGT(column string, value interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s > ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrGTE builds `column >= value` statement in `OR` conditions..
|
|
||||||
func (m *Model) WhereOrGTE(column string, value interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s >= ?`, column, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrBetween builds `column BETWEEN min AND max` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrLike builds `column LIKE like` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrLike(column string, like interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrIn builds `column IN (in)` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrIn(column string, in interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrNull builds `columns[0] IS NULL OR columns[1] IS NULL ...` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrNull(columns ...string) *Model {
|
|
||||||
model := m
|
|
||||||
for _, column := range columns {
|
|
||||||
model = m.WhereOrf(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrNotBetween builds `column NOT BETWEEN min AND max` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrNotLike(column string, like interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrNotIn builds `column NOT IN (in)` statement.
|
|
||||||
func (m *Model) WhereOrNotIn(column string, in interface{}) *Model {
|
|
||||||
return m.WhereOrf(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhereOrNotNull builds `columns[0] IS NOT NULL OR columns[1] IS NOT NULL ...` statement in `OR` conditions.
|
|
||||||
func (m *Model) WhereOrNotNull(columns ...string) *Model {
|
|
||||||
model := m
|
|
||||||
for _, column := range columns {
|
|
||||||
model = m.WhereOrf(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit sets the "LIMIT" statement for the model.
|
|
||||||
// The parameter `limit` can be either one or two number, if passed two number is passed,
|
|
||||||
// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
|
|
||||||
// statement.
|
|
||||||
func (m *Model) Limit(limit ...int) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
switch len(limit) {
|
|
||||||
case 1:
|
|
||||||
model.limit = limit[0]
|
|
||||||
case 2:
|
|
||||||
model.start = limit[0]
|
|
||||||
model.limit = limit[1]
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset sets the "OFFSET" statement for the model.
|
|
||||||
// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
|
|
||||||
func (m *Model) Offset(offset int) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
model.offset = offset
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distinct forces the query to only return distinct results.
|
|
||||||
func (m *Model) Distinct() *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
model.distinct = "DISTINCT "
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page sets the paging number for the model.
|
|
||||||
// The parameter `page` is started from 1 for paging.
|
|
||||||
// Note that, it differs that the Limit function starts from 0 for "LIMIT" statement.
|
|
||||||
func (m *Model) Page(page, limit int) *Model {
|
|
||||||
model := m.getModel()
|
|
||||||
if page <= 0 {
|
|
||||||
page = 1
|
|
||||||
}
|
|
||||||
model.start = (page - 1) * limit
|
|
||||||
model.limit = limit
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
|
|
||||||
// Note that this function does not change any attribute value of the `m`.
|
|
||||||
//
|
|
||||||
// The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
|
|
||||||
func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
|
|
||||||
autoPrefix := ""
|
|
||||||
if gstr.Contains(m.tables, " JOIN ") {
|
|
||||||
autoPrefix = m.db.GetCore().QuoteWord(m.tablesInit)
|
|
||||||
}
|
|
||||||
if len(m.whereHolder) > 0 {
|
|
||||||
for _, v := range m.whereHolder {
|
|
||||||
if v.Prefix == "" {
|
|
||||||
v.Prefix = autoPrefix
|
|
||||||
}
|
|
||||||
switch v.Operator {
|
|
||||||
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,
|
|
||||||
Schema: m.schema,
|
|
||||||
Table: m.tables,
|
|
||||||
Prefix: v.Prefix,
|
|
||||||
})
|
|
||||||
if len(newWhere) > 0 {
|
|
||||||
conditionWhere = newWhere
|
|
||||||
conditionArgs = newArgs
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
|
|
||||||
case whereHolderOperatorAnd:
|
|
||||||
newWhere, newArgs := formatWhere(m.db, formatWhereInput{
|
|
||||||
Where: v.Where,
|
|
||||||
Args: v.Args,
|
|
||||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
|
||||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
|
||||||
Schema: m.schema,
|
|
||||||
Table: m.tables,
|
|
||||||
Prefix: v.Prefix,
|
|
||||||
})
|
|
||||||
if len(newWhere) > 0 {
|
|
||||||
if len(conditionWhere) == 0 {
|
|
||||||
conditionWhere = newWhere
|
|
||||||
} else if conditionWhere[0] == '(' {
|
|
||||||
conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
|
|
||||||
} else {
|
|
||||||
conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
|
|
||||||
}
|
|
||||||
conditionArgs = append(conditionArgs, newArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
case whereHolderOperatorOr:
|
|
||||||
newWhere, newArgs := formatWhere(m.db, formatWhereInput{
|
|
||||||
Where: v.Where,
|
|
||||||
Args: v.Args,
|
|
||||||
OmitNil: m.option&optionOmitNilWhere > 0,
|
|
||||||
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
|
||||||
Schema: m.schema,
|
|
||||||
Table: m.tables,
|
|
||||||
Prefix: v.Prefix,
|
|
||||||
})
|
|
||||||
if len(newWhere) > 0 {
|
|
||||||
if len(conditionWhere) == 0 {
|
|
||||||
conditionWhere = newWhere
|
|
||||||
} else if conditionWhere[0] == '(' {
|
|
||||||
conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
|
|
||||||
} else {
|
|
||||||
conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
|
|
||||||
}
|
|
||||||
conditionArgs = append(conditionArgs, newArgs...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Soft deletion.
|
|
||||||
softDeletingCondition := m.getConditionForSoftDeleting()
|
|
||||||
if m.rawSql != "" && conditionWhere != "" {
|
|
||||||
if gstr.ContainsI(m.rawSql, " WHERE ") {
|
|
||||||
conditionWhere = " AND " + conditionWhere
|
|
||||||
} else {
|
|
||||||
conditionWhere = " WHERE " + conditionWhere
|
|
||||||
}
|
|
||||||
} else if !m.unscoped && softDeletingCondition != "" {
|
|
||||||
if conditionWhere == "" {
|
|
||||||
conditionWhere = fmt.Sprintf(` WHERE %s`, softDeletingCondition)
|
|
||||||
} else {
|
|
||||||
conditionWhere = fmt.Sprintf(` WHERE (%s) AND %s`, conditionWhere, softDeletingCondition)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if conditionWhere != "" {
|
|
||||||
conditionWhere = " WHERE " + conditionWhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GROUP BY.
|
|
||||||
if m.groupBy != "" {
|
|
||||||
conditionExtra += " GROUP BY " + m.groupBy
|
|
||||||
}
|
|
||||||
// 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,
|
|
||||||
Schema: m.schema,
|
|
||||||
Table: m.tables,
|
|
||||||
Prefix: autoPrefix,
|
|
||||||
})
|
|
||||||
if len(havingStr) > 0 {
|
|
||||||
conditionExtra += " HAVING " + havingStr
|
|
||||||
conditionArgs = append(conditionArgs, havingArgs...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ORDER BY.
|
|
||||||
if m.orderBy != "" {
|
|
||||||
conditionExtra += " ORDER BY " + m.orderBy
|
|
||||||
}
|
|
||||||
// LIMIT.
|
|
||||||
if !isCountStatement {
|
|
||||||
if m.limit != 0 {
|
|
||||||
if m.start >= 0 {
|
|
||||||
conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
|
|
||||||
} else {
|
|
||||||
conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
|
|
||||||
}
|
|
||||||
} else if limit1 {
|
|
||||||
conditionExtra += " LIMIT 1"
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.offset >= 0 {
|
|
||||||
conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.lockInfo != "" {
|
|
||||||
conditionExtra += " " + m.lockInfo
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
@ -111,7 +111,7 @@ func (m *Model) FieldCount(column string, as ...string) *Model {
|
|||||||
if len(as) > 0 && as[0] != "" {
|
if len(as) > 0 && as[0] != "" {
|
||||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(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))
|
return m.appendFieldsByStr(fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model.
|
// FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model.
|
||||||
@ -120,7 +120,7 @@ func (m *Model) FieldSum(column string, as ...string) *Model {
|
|||||||
if len(as) > 0 && as[0] != "" {
|
if len(as) > 0 && as[0] != "" {
|
||||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(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))
|
return m.appendFieldsByStr(fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model.
|
// FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model.
|
||||||
@ -129,7 +129,7 @@ func (m *Model) FieldMin(column string, as ...string) *Model {
|
|||||||
if len(as) > 0 && as[0] != "" {
|
if len(as) > 0 && as[0] != "" {
|
||||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(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))
|
return m.appendFieldsByStr(fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model.
|
// FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model.
|
||||||
@ -138,7 +138,7 @@ func (m *Model) FieldMax(column string, as ...string) *Model {
|
|||||||
if len(as) > 0 && as[0] != "" {
|
if len(as) > 0 && as[0] != "" {
|
||||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(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))
|
return m.appendFieldsByStr(fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model.
|
// FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model.
|
||||||
@ -147,7 +147,7 @@ func (m *Model) FieldAvg(column string, as ...string) *Model {
|
|||||||
if len(as) > 0 && as[0] != "" {
|
if len(as) > 0 && as[0] != "" {
|
||||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(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))
|
return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) appendFieldsByStr(fields string) *Model {
|
func (m *Model) appendFieldsByStr(fields string) *Model {
|
||||||
|
@ -235,7 +235,6 @@ func (m *Model) doInsertWithOption(insertOption int) (result sql.Result, err err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// It converts any data to List type for inserting.
|
// It converts any data to List type for inserting.
|
||||||
switch value := newData.(type) {
|
switch value := newData.(type) {
|
||||||
case Result:
|
case Result:
|
||||||
@ -311,7 +310,6 @@ func (m *Model) doInsertWithOption(insertOption int) (result sql.Result, err err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.db.DoInsert(m.GetCtx(), m.getLink(true), m.tables, list, doInsertOption)
|
return m.db.DoInsert(m.GetCtx(), m.getLink(true), m.tables, list, doInsertOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ func (m *Model) Min(column string) (float64, error) {
|
|||||||
if len(column) == 0 {
|
if len(column) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
value, err := m.Fields(fmt.Sprintf(`MIN(%s)`, m.db.GetCore().QuoteWord(column))).Value()
|
value, err := m.Fields(fmt.Sprintf(`MIN(%s)`, m.QuoteWord(column))).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -385,7 +385,7 @@ func (m *Model) Max(column string) (float64, error) {
|
|||||||
if len(column) == 0 {
|
if len(column) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
value, err := m.Fields(fmt.Sprintf(`MAX(%s)`, m.db.GetCore().QuoteWord(column))).Value()
|
value, err := m.Fields(fmt.Sprintf(`MAX(%s)`, m.QuoteWord(column))).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ func (m *Model) Avg(column string) (float64, error) {
|
|||||||
if len(column) == 0 {
|
if len(column) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
value, err := m.Fields(fmt.Sprintf(`AVG(%s)`, m.db.GetCore().QuoteWord(column))).Value()
|
value, err := m.Fields(fmt.Sprintf(`AVG(%s)`, m.QuoteWord(column))).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -409,7 +409,7 @@ func (m *Model) Sum(column string) (float64, error) {
|
|||||||
if len(column) == 0 {
|
if len(column) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
value, err := m.Fields(fmt.Sprintf(`SUM(%s)`, m.db.GetCore().QuoteWord(column))).Value()
|
value, err := m.Fields(fmt.Sprintf(`SUM(%s)`, m.QuoteWord(column))).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -426,6 +426,61 @@ func (m *Model) UnionAll(unions ...*Model) *Model {
|
|||||||
return m.db.UnionAll(unions...)
|
return m.db.UnionAll(unions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit sets the "LIMIT" statement for the model.
|
||||||
|
// The parameter `limit` can be either one or two number, if passed two number is passed,
|
||||||
|
// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
|
||||||
|
// statement.
|
||||||
|
func (m *Model) Limit(limit ...int) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
switch len(limit) {
|
||||||
|
case 1:
|
||||||
|
model.limit = limit[0]
|
||||||
|
case 2:
|
||||||
|
model.start = limit[0]
|
||||||
|
model.limit = limit[1]
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset sets the "OFFSET" statement for the model.
|
||||||
|
// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
|
||||||
|
func (m *Model) Offset(offset int) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
model.offset = offset
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distinct forces the query to only return distinct results.
|
||||||
|
func (m *Model) Distinct() *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
model.distinct = "DISTINCT "
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page sets the paging number for the model.
|
||||||
|
// The parameter `page` is started from 1 for paging.
|
||||||
|
// Note that, it differs that the Limit function starts from 0 for "LIMIT" statement.
|
||||||
|
func (m *Model) Page(page, limit int) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
if page <= 0 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
model.start = (page - 1) * limit
|
||||||
|
model.limit = limit
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// Having sets the having statement for the model.
|
||||||
|
// The parameters of this function usage are as the same as function Where.
|
||||||
|
// See Where.
|
||||||
|
func (m *Model) Having(having interface{}, args ...interface{}) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
model.having = []interface{}{
|
||||||
|
having, args,
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
// doGetAllBySql does the select statement on the database.
|
// doGetAllBySql does the select statement on the database.
|
||||||
func (m *Model) doGetAllBySql(sql string, args ...interface{}) (result Result, err error) {
|
func (m *Model) doGetAllBySql(sql string, args ...interface{}) (result Result, err error) {
|
||||||
var (
|
var (
|
||||||
@ -520,3 +575,150 @@ func (m *Model) getFormattedSqlAndArgs(queryType int, limit1 bool) (sqlWithHolde
|
|||||||
return sqlWithHolder, conditionArgs
|
return sqlWithHolder, conditionArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
|
||||||
|
// Note that this function does not change any attribute value of the `m`.
|
||||||
|
//
|
||||||
|
// The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
|
||||||
|
func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
|
||||||
|
autoPrefix := ""
|
||||||
|
if gstr.Contains(m.tables, " JOIN ") {
|
||||||
|
autoPrefix = m.db.GetCore().QuoteWord(
|
||||||
|
m.db.GetCore().guessPrimaryTableName(m.tablesInit),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if len(m.whereHolder) > 0 {
|
||||||
|
for _, v := range m.whereHolder {
|
||||||
|
if v.Prefix == "" {
|
||||||
|
v.Prefix = autoPrefix
|
||||||
|
}
|
||||||
|
switch v.Operator {
|
||||||
|
case whereHolderOperatorWhere:
|
||||||
|
if conditionWhere == "" {
|
||||||
|
newWhere, newArgs := formatWhereHolder(m.db, formatWhereHolderInput{
|
||||||
|
Where: v.Where,
|
||||||
|
Args: v.Args,
|
||||||
|
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||||
|
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||||
|
Schema: m.schema,
|
||||||
|
Table: m.tables,
|
||||||
|
Prefix: v.Prefix,
|
||||||
|
})
|
||||||
|
if len(newWhere) > 0 {
|
||||||
|
conditionWhere = newWhere
|
||||||
|
conditionArgs = newArgs
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case whereHolderOperatorAnd:
|
||||||
|
newWhere, newArgs := formatWhereHolder(m.db, formatWhereHolderInput{
|
||||||
|
Where: v.Where,
|
||||||
|
Args: v.Args,
|
||||||
|
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||||
|
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||||
|
Schema: m.schema,
|
||||||
|
Table: m.tables,
|
||||||
|
Prefix: v.Prefix,
|
||||||
|
})
|
||||||
|
if len(newWhere) > 0 {
|
||||||
|
if len(conditionWhere) == 0 {
|
||||||
|
conditionWhere = newWhere
|
||||||
|
} else if conditionWhere[0] == '(' {
|
||||||
|
conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
|
||||||
|
} else {
|
||||||
|
conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
|
||||||
|
}
|
||||||
|
conditionArgs = append(conditionArgs, newArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
case whereHolderOperatorOr:
|
||||||
|
newWhere, newArgs := formatWhereHolder(m.db, formatWhereHolderInput{
|
||||||
|
Where: v.Where,
|
||||||
|
Args: v.Args,
|
||||||
|
OmitNil: m.option&optionOmitNilWhere > 0,
|
||||||
|
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
|
||||||
|
Schema: m.schema,
|
||||||
|
Table: m.tables,
|
||||||
|
Prefix: v.Prefix,
|
||||||
|
})
|
||||||
|
if len(newWhere) > 0 {
|
||||||
|
if len(conditionWhere) == 0 {
|
||||||
|
conditionWhere = newWhere
|
||||||
|
} else if conditionWhere[0] == '(' {
|
||||||
|
conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
|
||||||
|
} else {
|
||||||
|
conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
|
||||||
|
}
|
||||||
|
conditionArgs = append(conditionArgs, newArgs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Soft deletion.
|
||||||
|
softDeletingCondition := m.getConditionForSoftDeleting()
|
||||||
|
if m.rawSql != "" && conditionWhere != "" {
|
||||||
|
if gstr.ContainsI(m.rawSql, " WHERE ") {
|
||||||
|
conditionWhere = " AND " + conditionWhere
|
||||||
|
} else {
|
||||||
|
conditionWhere = " WHERE " + conditionWhere
|
||||||
|
}
|
||||||
|
} else if !m.unscoped && softDeletingCondition != "" {
|
||||||
|
if conditionWhere == "" {
|
||||||
|
conditionWhere = fmt.Sprintf(` WHERE %s`, softDeletingCondition)
|
||||||
|
} else {
|
||||||
|
conditionWhere = fmt.Sprintf(` WHERE (%s) AND %s`, conditionWhere, softDeletingCondition)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if conditionWhere != "" {
|
||||||
|
conditionWhere = " WHERE " + conditionWhere
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GROUP BY.
|
||||||
|
if m.groupBy != "" {
|
||||||
|
conditionExtra += " GROUP BY " + m.groupBy
|
||||||
|
}
|
||||||
|
// HAVING.
|
||||||
|
if len(m.having) > 0 {
|
||||||
|
havingStr, havingArgs := formatWhereHolder(m.db, formatWhereHolderInput{
|
||||||
|
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,
|
||||||
|
Prefix: autoPrefix,
|
||||||
|
})
|
||||||
|
if len(havingStr) > 0 {
|
||||||
|
conditionExtra += " HAVING " + havingStr
|
||||||
|
conditionArgs = append(conditionArgs, havingArgs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ORDER BY.
|
||||||
|
if m.orderBy != "" {
|
||||||
|
conditionExtra += " ORDER BY " + m.orderBy
|
||||||
|
}
|
||||||
|
// LIMIT.
|
||||||
|
if !isCountStatement {
|
||||||
|
if m.limit != 0 {
|
||||||
|
if m.start >= 0 {
|
||||||
|
conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
|
||||||
|
} else {
|
||||||
|
conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
|
||||||
|
}
|
||||||
|
} else if limit1 {
|
||||||
|
conditionExtra += " LIMIT 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.offset >= 0 {
|
||||||
|
conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.lockInfo != "" {
|
||||||
|
conditionExtra += " " + m.lockInfo
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -17,6 +17,15 @@ import (
|
|||||||
"github.com/gogf/gf/v2/util/gutil"
|
"github.com/gogf/gf/v2/util/gutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// QuoteWord checks given string `s` a word,
|
||||||
|
// if true it quotes `s` with security chars of the database
|
||||||
|
// and returns the quoted string; or else it returns `s` without any change.
|
||||||
|
//
|
||||||
|
// The meaning of a `word` can be considered as a column name.
|
||||||
|
func (m *Model) QuoteWord(s string) string {
|
||||||
|
return m.db.GetCore().QuoteWord(s)
|
||||||
|
}
|
||||||
|
|
||||||
// TableFields retrieves and returns the fields information of specified table of current
|
// TableFields retrieves and returns the fields information of specified table of current
|
||||||
// schema.
|
// schema.
|
||||||
//
|
//
|
||||||
|
137
database/gdb/gdb_model_where.go
Normal file
137
database/gdb/gdb_model_where.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Where sets the condition statement for the model. The parameter `where` can be type of
|
||||||
|
// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
|
||||||
|
// multiple conditions will be joined into where statement using "AND".
|
||||||
|
// Eg:
|
||||||
|
// Where("uid=10000")
|
||||||
|
// Where("uid", 10000)
|
||||||
|
// Where("money>? AND name like ?", 99999, "vip_%")
|
||||||
|
// Where("uid", 1).Where("name", "john")
|
||||||
|
// Where("status IN (?)", g.Slice{1,2,3})
|
||||||
|
// Where("age IN(?,?)", 18, 50)
|
||||||
|
// Where(User{ Id : 1, UserName : "john"}).
|
||||||
|
func (m *Model) Where(where interface{}, args ...interface{}) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
if model.whereHolder == nil {
|
||||||
|
model.whereHolder = make([]ModelWhereHolder, 0)
|
||||||
|
}
|
||||||
|
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
||||||
|
Operator: whereHolderOperatorWhere,
|
||||||
|
Where: where,
|
||||||
|
Args: args,
|
||||||
|
})
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePri does the same logic as Model.Where except that if the parameter `where`
|
||||||
|
// is a single condition like int/string/float/slice, it treats the condition as the primary
|
||||||
|
// key value. That is, if primary key is "id" and given `where` parameter as "123", the
|
||||||
|
// WherePri function treats the condition as "id=123", but Model.Where treats the condition
|
||||||
|
// as string "123".
|
||||||
|
func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
|
||||||
|
if len(args) > 0 {
|
||||||
|
return m.Where(where, args...)
|
||||||
|
}
|
||||||
|
newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
|
||||||
|
return m.Where(newWhere[0], newWhere[1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wheref builds condition string using fmt.Sprintf and arguments.
|
||||||
|
// Note that if the number of `args` is more than the placeholder in `format`,
|
||||||
|
// the extra `args` will be used as the where condition arguments of the Model.
|
||||||
|
// Eg:
|
||||||
|
// Wheref(`amount<? and status=%s`, "paid", 100) => WHERE `amount`<100 and status='paid'
|
||||||
|
// Wheref(`amount<%d and status=%s`, 100, "paid") => WHERE `amount`<100 and status='paid'
|
||||||
|
func (m *Model) Wheref(format string, args ...interface{}) *Model {
|
||||||
|
var (
|
||||||
|
placeHolderCount = gstr.Count(format, "?")
|
||||||
|
conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
|
||||||
|
)
|
||||||
|
return m.Where(conditionStr, args[len(args)-placeHolderCount:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereLT builds `column < value` statement.
|
||||||
|
func (m *Model) WhereLT(column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s < ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereLTE builds `column <= value` statement.
|
||||||
|
func (m *Model) WhereLTE(column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s <= ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereGT builds `column > value` statement.
|
||||||
|
func (m *Model) WhereGT(column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s > ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereGTE builds `column >= value` statement.
|
||||||
|
func (m *Model) WhereGTE(column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s >= ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereBetween builds `column BETWEEN min AND max` statement.
|
||||||
|
func (m *Model) WhereBetween(column string, min, max interface{}) *Model {
|
||||||
|
return m.Wheref(`%s BETWEEN ? AND ?`, m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereLike builds `column LIKE like` statement.
|
||||||
|
func (m *Model) WhereLike(column string, like interface{}) *Model {
|
||||||
|
return m.Wheref(`%s LIKE ?`, m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereIn builds `column IN (in)` statement.
|
||||||
|
func (m *Model) WhereIn(column string, in interface{}) *Model {
|
||||||
|
return m.Wheref(`%s IN (?)`, m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNull builds `columns[0] IS NULL AND columns[1] IS NULL ...` statement.
|
||||||
|
func (m *Model) WhereNull(columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.Wheref(`%s IS NULL`, m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNotBetween builds `column NOT BETWEEN min AND max` statement.
|
||||||
|
func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model {
|
||||||
|
return m.Wheref(`%s NOT BETWEEN ? AND ?`, m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNotLike builds `column NOT LIKE like` statement.
|
||||||
|
func (m *Model) WhereNotLike(column string, like interface{}) *Model {
|
||||||
|
return m.Wheref(`%s NOT LIKE ?`, m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNot builds `column != value` statement.
|
||||||
|
func (m *Model) WhereNot(column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s != ?`, m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNotIn builds `column NOT IN (in)` statement.
|
||||||
|
func (m *Model) WhereNotIn(column string, in interface{}) *Model {
|
||||||
|
return m.Wheref(`%s NOT IN (?)`, m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereNotNull builds `columns[0] IS NOT NULL AND columns[1] IS NOT NULL ...` statement.
|
||||||
|
func (m *Model) WhereNotNull(columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.Wheref(`%s IS NOT NULL`, m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
98
database/gdb/gdb_model_where_prefix.go
Normal file
98
database/gdb/gdb_model_where_prefix.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// WherePrefix performs as Where, but it adds prefix to each field in where statement.
|
||||||
|
// Eg:
|
||||||
|
// WherePrefix("order", "status", "paid") => WHERE `order`.`status`='paid'
|
||||||
|
// WherePrefix("order", struct{Status:"paid", "channel":"bank"}) => WHERE `order`.`status`='paid' AND `order`.`channel`='bank'
|
||||||
|
func (m *Model) WherePrefix(prefix string, where interface{}, args ...interface{}) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
if model.whereHolder == nil {
|
||||||
|
model.whereHolder = make([]ModelWhereHolder, 0)
|
||||||
|
}
|
||||||
|
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
||||||
|
Operator: whereHolderOperatorWhere,
|
||||||
|
Where: where,
|
||||||
|
Args: args,
|
||||||
|
Prefix: prefix,
|
||||||
|
})
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixLT builds `prefix.column < value` statement.
|
||||||
|
func (m *Model) WherePrefixLT(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s < ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixLTE builds `prefix.column <= value` statement.
|
||||||
|
func (m *Model) WherePrefixLTE(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s <= ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixGT builds `prefix.column > value` statement.
|
||||||
|
func (m *Model) WherePrefixGT(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s > ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixGTE builds `prefix.column >= value` statement.
|
||||||
|
func (m *Model) WherePrefixGTE(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s >= ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixBetween builds `prefix.column BETWEEN min AND max` statement.
|
||||||
|
func (m *Model) WherePrefixBetween(prefix string, column string, min, max interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s BETWEEN ? AND ?`, m.QuoteWord(prefix), m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixLike builds `prefix.column LIKE like` statement.
|
||||||
|
func (m *Model) WherePrefixLike(prefix string, column string, like interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s LIKE ?`, m.QuoteWord(prefix), m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixIn builds `prefix.column IN (in)` statement.
|
||||||
|
func (m *Model) WherePrefixIn(prefix string, column string, in interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s IN (?)`, m.QuoteWord(prefix), m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNull builds `prefix.columns[0] IS NULL AND prefix.columns[1] IS NULL ...` statement.
|
||||||
|
func (m *Model) WherePrefixNull(prefix string, columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.Wheref(`%s.%s IS NULL`, m.QuoteWord(prefix), m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNotBetween builds `prefix.column NOT BETWEEN min AND max` statement.
|
||||||
|
func (m *Model) WherePrefixNotBetween(prefix string, column string, min, max interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s NOT BETWEEN ? AND ?`, m.QuoteWord(prefix), m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNotLike builds `prefix.column NOT LIKE like` statement.
|
||||||
|
func (m *Model) WherePrefixNotLike(prefix string, column string, like interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s NOT LIKE ?`, m.QuoteWord(prefix), m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNot builds `prefix.column != value` statement.
|
||||||
|
func (m *Model) WherePrefixNot(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s != ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNotIn builds `prefix.column NOT IN (in)` statement.
|
||||||
|
func (m *Model) WherePrefixNotIn(prefix string, column string, in interface{}) *Model {
|
||||||
|
return m.Wheref(`%s.%s NOT IN (?)`, m.QuoteWord(prefix), m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WherePrefixNotNull builds `prefix.columns[0] IS NOT NULL AND prefix.columns[1] IS NOT NULL ...` statement.
|
||||||
|
func (m *Model) WherePrefixNotNull(prefix string, columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.Wheref(`%s.%s IS NOT NULL`, m.QuoteWord(prefix), m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
107
database/gdb/gdb_model_whereor.go
Normal file
107
database/gdb/gdb_model_whereor.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WhereOr adds "OR" condition to the where statement.
|
||||||
|
func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
if model.whereHolder == nil {
|
||||||
|
model.whereHolder = make([]ModelWhereHolder, 0)
|
||||||
|
}
|
||||||
|
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
||||||
|
Operator: whereHolderOperatorOr,
|
||||||
|
Where: where,
|
||||||
|
Args: args,
|
||||||
|
})
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrf builds `OR` condition string using fmt.Sprintf and arguments.
|
||||||
|
// Eg:
|
||||||
|
// WhereOrf(`amount<? and status=%s`, "paid", 100) => WHERE xxx OR `amount`<100 and status='paid'
|
||||||
|
// WhereOrf(`amount<%d and status=%s`, 100, "paid") => WHERE xxx OR `amount`<100 and status='paid'
|
||||||
|
func (m *Model) WhereOrf(format string, args ...interface{}) *Model {
|
||||||
|
var (
|
||||||
|
placeHolderCount = gstr.Count(format, "?")
|
||||||
|
conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
|
||||||
|
)
|
||||||
|
return m.WhereOr(conditionStr, args[len(args)-placeHolderCount:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrLT builds `column < value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrLT(column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s < ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrLTE builds `column <= value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrLTE(column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s <= ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrGT builds `column > value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrGT(column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s > ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrGTE builds `column >= value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrGTE(column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s >= ?`, column, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrBetween builds `column BETWEEN min AND max` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s BETWEEN ? AND ?`, m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrLike builds `column LIKE like` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrLike(column string, like interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s LIKE ?`, m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrIn builds `column IN (in)` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrIn(column string, in interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s IN (?)`, m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrNull builds `columns[0] IS NULL OR columns[1] IS NULL ...` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrNull(columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.WhereOrf(`%s IS NULL`, m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrNotBetween builds `column NOT BETWEEN min AND max` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s NOT BETWEEN ? AND ?`, m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrNotLike(column string, like interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s NOT LIKE ?`, m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrNotIn builds `column NOT IN (in)` statement.
|
||||||
|
func (m *Model) WhereOrNotIn(column string, in interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s NOT IN (?)`, m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrNotNull builds `columns[0] IS NOT NULL OR columns[1] IS NOT NULL ...` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrNotNull(columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.WhereOrf(`%s IS NOT NULL`, m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
93
database/gdb/gdb_model_whereor_prefix.go
Normal file
93
database/gdb/gdb_model_whereor_prefix.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// WhereOrPrefix performs as WhereOr, but it adds prefix to each field in where statement.
|
||||||
|
// Eg:
|
||||||
|
// WhereOrPrefix("order", "status", "paid") => WHERE xxx OR (`order`.`status`='paid')
|
||||||
|
// WhereOrPrefix("order", struct{Status:"paid", "channel":"bank"}) => WHERE xxx OR (`order`.`status`='paid' AND `order`.`channel`='bank')
|
||||||
|
func (m *Model) WhereOrPrefix(prefix string, where interface{}, args ...interface{}) *Model {
|
||||||
|
model := m.getModel()
|
||||||
|
if model.whereHolder == nil {
|
||||||
|
model.whereHolder = make([]ModelWhereHolder, 0)
|
||||||
|
}
|
||||||
|
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
||||||
|
Operator: whereHolderOperatorOr,
|
||||||
|
Where: where,
|
||||||
|
Args: args,
|
||||||
|
Prefix: prefix,
|
||||||
|
})
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixLT builds `prefix.column < value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrPrefixLT(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s < ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixLTE builds `prefix.column <= value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrPrefixLTE(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s <= ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixGT builds `prefix.column > value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrPrefixGT(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s > ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixGTE builds `prefix.column >= value` statement in `OR` conditions..
|
||||||
|
func (m *Model) WhereOrPrefixGTE(prefix string, column string, value interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s >= ?`, m.QuoteWord(prefix), m.QuoteWord(column), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixBetween builds `prefix.column BETWEEN min AND max` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixBetween(prefix string, column string, min, max interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s BETWEEN ? AND ?`, m.QuoteWord(prefix), m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixLike builds `prefix.column LIKE like` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixLike(prefix string, column string, like interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s LIKE ?`, m.QuoteWord(prefix), m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixIn builds `prefix.column IN (in)` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixIn(prefix string, column string, in interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s IN (?)`, m.QuoteWord(prefix), m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixNull builds `prefix.columns[0] IS NULL OR prefix.columns[1] IS NULL ...` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixNull(prefix string, columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.WhereOrf(`%s.%s IS NULL`, m.QuoteWord(prefix), m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixNotBetween builds `prefix.column NOT BETWEEN min AND max` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixNotBetween(prefix string, column string, min, max interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s NOT BETWEEN ? AND ?`, m.QuoteWord(prefix), m.QuoteWord(column), min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixNotLike builds `prefix.column NOT LIKE like` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixNotLike(prefix string, column string, like interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s NOT LIKE ?`, m.QuoteWord(prefix), m.QuoteWord(column), like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixNotIn builds `prefix.column NOT IN (in)` statement.
|
||||||
|
func (m *Model) WhereOrPrefixNotIn(prefix string, column string, in interface{}) *Model {
|
||||||
|
return m.WhereOrf(`%s.%s NOT IN (?)`, m.QuoteWord(prefix), m.QuoteWord(column), in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereOrPrefixNotNull builds `prefix.columns[0] IS NOT NULL OR prefix.columns[1] IS NOT NULL ...` statement in `OR` conditions.
|
||||||
|
func (m *Model) WhereOrPrefixNotNull(prefix string, columns ...string) *Model {
|
||||||
|
model := m
|
||||||
|
for _, column := range columns {
|
||||||
|
model = m.WhereOrf(`%s.%s IS NOT NULL`, m.QuoteWord(prefix), m.QuoteWord(column))
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
@ -1491,3 +1491,88 @@ func Test_DB_Ctx_Logger(t *testing.T) {
|
|||||||
t.AssertNil(err)
|
t.AssertNil(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All types testing.
|
||||||
|
func Test_Types(t *testing.T) {
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||||
|
CREATE TABLE IF NOT EXISTS types (
|
||||||
|
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
%s blob NOT NULL,
|
||||||
|
%s binary(8) NOT NULL,
|
||||||
|
%s date NOT NULL,
|
||||||
|
%s time NOT NULL,
|
||||||
|
%s decimal(5,2) NOT NULL,
|
||||||
|
%s double NOT NULL,
|
||||||
|
%s bit(2) NOT NULL,
|
||||||
|
%s tinyint(1) NOT NULL,
|
||||||
|
%s bool NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
`,
|
||||||
|
"`blob`",
|
||||||
|
"`binary`",
|
||||||
|
"`date`",
|
||||||
|
"`time`",
|
||||||
|
"`decimal`",
|
||||||
|
"`double`",
|
||||||
|
"`bit`",
|
||||||
|
"`tinyint`",
|
||||||
|
"`bool`")); err != nil {
|
||||||
|
gtest.Error(err)
|
||||||
|
}
|
||||||
|
defer dropTable("types")
|
||||||
|
data := g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"blob": "i love gf",
|
||||||
|
"binary": []byte("abcdefgh"),
|
||||||
|
"date": "1880-10-24",
|
||||||
|
"time": "10:00:01",
|
||||||
|
"decimal": -123.456,
|
||||||
|
"double": -123.456,
|
||||||
|
"bit": 2,
|
||||||
|
"tinyint": true,
|
||||||
|
"bool": false,
|
||||||
|
}
|
||||||
|
r, err := db.Model("types").Data(data).Insert()
|
||||||
|
t.AssertNil(err)
|
||||||
|
n, _ := r.RowsAffected()
|
||||||
|
t.Assert(n, 1)
|
||||||
|
|
||||||
|
one, err := db.Model("types").One()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(one["id"].Int(), 1)
|
||||||
|
t.Assert(one["blob"].String(), data["blob"])
|
||||||
|
t.Assert(one["binary"].String(), data["binary"])
|
||||||
|
t.Assert(one["date"].String(), data["date"])
|
||||||
|
t.Assert(one["time"].String(), `0000-01-01 10:00:01`)
|
||||||
|
t.Assert(one["decimal"].String(), -123.46)
|
||||||
|
t.Assert(one["double"].String(), data["double"])
|
||||||
|
t.Assert(one["bit"].Int(), data["bit"])
|
||||||
|
t.Assert(one["tinyint"].Bool(), data["tinyint"])
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
Id int
|
||||||
|
Blob []byte
|
||||||
|
Binary []byte
|
||||||
|
Date *gtime.Time
|
||||||
|
Time *gtime.Time
|
||||||
|
Decimal float64
|
||||||
|
Double float64
|
||||||
|
Bit int8
|
||||||
|
TinyInt bool
|
||||||
|
}
|
||||||
|
var obj *T
|
||||||
|
err = db.Model("types").Scan(&obj)
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(obj.Id, 1)
|
||||||
|
t.Assert(obj.Blob, data["blob"])
|
||||||
|
t.Assert(obj.Binary, data["binary"])
|
||||||
|
t.Assert(obj.Date.Format("Y-m-d"), data["date"])
|
||||||
|
t.Assert(obj.Time.String(), `0000-01-01 10:00:01`)
|
||||||
|
t.Assert(obj.Decimal, -123.46)
|
||||||
|
t.Assert(obj.Double, data["double"])
|
||||||
|
t.Assert(obj.Bit, data["bit"])
|
||||||
|
t.Assert(obj.TinyInt, data["tinyint"])
|
||||||
|
})
|
||||||
|
}
|
@ -1871,9 +1871,9 @@ func Test_Table_Relation_With_MultipleDepends_Embedded(t *testing.T) {
|
|||||||
|
|
||||||
func Test_Table_Relation_WithAll_Embedded_Meta_NameMatchingRule(t *testing.T) {
|
func Test_Table_Relation_WithAll_Embedded_Meta_NameMatchingRule(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
tableUser = "user1"
|
tableUser = "user100"
|
||||||
tableUserDetail = "user_detail1"
|
tableUserDetail = "user_detail100"
|
||||||
tableUserScores = "user_scores1"
|
tableUserScores = "user_scores100"
|
||||||
)
|
)
|
||||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||||
CREATE TABLE IF NOT EXISTS %s (
|
CREATE TABLE IF NOT EXISTS %s (
|
||||||
@ -1910,13 +1910,13 @@ PRIMARY KEY (id)
|
|||||||
defer dropTable(tableUserScores)
|
defer dropTable(tableUserScores)
|
||||||
|
|
||||||
type UserDetail struct {
|
type UserDetail struct {
|
||||||
gmeta.Meta `orm:"table:user_detail1"`
|
gmeta.Meta `orm:"table:user_detail100"`
|
||||||
UserID int `json:"user_id"`
|
UserID int `json:"user_id"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserScores struct {
|
type UserScores struct {
|
||||||
gmeta.Meta `orm:"table:user_scores1"`
|
gmeta.Meta `orm:"table:user_scores100"`
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
UserID int `json:"user_id"`
|
UserID int `json:"user_id"`
|
||||||
Score int `json:"score"`
|
Score int `json:"score"`
|
||||||
@ -1929,7 +1929,7 @@ PRIMARY KEY (id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
gmeta.Meta `orm:"table:user1"`
|
gmeta.Meta `orm:"table:user100"`
|
||||||
UserEmbedded
|
UserEmbedded
|
||||||
UserDetail UserDetail `orm:"with:user_id=id"`
|
UserDetail UserDetail `orm:"with:user_id=id"`
|
||||||
UserScores []*UserScores `orm:"with:user_id=id"`
|
UserScores []*UserScores `orm:"with:user_id=id"`
|
||||||
@ -1960,9 +1960,6 @@ PRIMARY KEY (id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.SetDebug(true)
|
|
||||||
defer db.SetDebug(false)
|
|
||||||
|
|
||||||
// gtest.C(t, func(t *gtest.T) {
|
// gtest.C(t, func(t *gtest.T) {
|
||||||
// var user *User
|
// var user *User
|
||||||
// err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user)
|
// err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user)
|
@ -1,219 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Using filter dose not affect the outside value inside function.
|
|
||||||
func Test_Model_Insert_Filter(t *testing.T) {
|
|
||||||
// map
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
table := createTable()
|
|
||||||
defer dropTable(table)
|
|
||||||
data := g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"uid": 1,
|
|
||||||
"passport": "t1",
|
|
||||||
"password": "25d55ad283aa400af464c76d713c07ad",
|
|
||||||
"nickname": "name_1",
|
|
||||||
"create_time": gtime.Now().String(),
|
|
||||||
}
|
|
||||||
result, err := db.Model(table).Data(data).Insert()
|
|
||||||
t.AssertNil(err)
|
|
||||||
n, _ := result.LastInsertId()
|
|
||||||
t.Assert(n, 1)
|
|
||||||
|
|
||||||
t.Assert(data["uid"], 1)
|
|
||||||
})
|
|
||||||
// slice
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
table := createTable()
|
|
||||||
defer dropTable(table)
|
|
||||||
data := g.List{
|
|
||||||
g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"uid": 1,
|
|
||||||
"passport": "t1",
|
|
||||||
"password": "25d55ad283aa400af464c76d713c07ad",
|
|
||||||
"nickname": "name_1",
|
|
||||||
"create_time": gtime.Now().String(),
|
|
||||||
},
|
|
||||||
g.Map{
|
|
||||||
"id": 2,
|
|
||||||
"uid": 2,
|
|
||||||
"passport": "t1",
|
|
||||||
"password": "25d55ad283aa400af464c76d713c07ad",
|
|
||||||
"nickname": "name_1",
|
|
||||||
"create_time": gtime.Now().String(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := db.Model(table).Data(data).Insert()
|
|
||||||
t.AssertNil(err)
|
|
||||||
n, _ := result.LastInsertId()
|
|
||||||
t.Assert(n, 2)
|
|
||||||
|
|
||||||
t.Assert(data[0]["uid"], 1)
|
|
||||||
t.Assert(data[1]["uid"], 2)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Model_Embedded_Filter(t *testing.T) {
|
|
||||||
table := createTable()
|
|
||||||
defer dropTable(table)
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
type Base struct {
|
|
||||||
Id int
|
|
||||||
Uid int
|
|
||||||
CreateTime string
|
|
||||||
NoneExist string
|
|
||||||
}
|
|
||||||
type User struct {
|
|
||||||
Base
|
|
||||||
Passport string
|
|
||||||
Password string
|
|
||||||
Nickname string
|
|
||||||
}
|
|
||||||
result, err := db.Model(table).Data(User{
|
|
||||||
Passport: "john-test",
|
|
||||||
Password: "123456",
|
|
||||||
Nickname: "John",
|
|
||||||
Base: Base{
|
|
||||||
Id: 100,
|
|
||||||
Uid: 100,
|
|
||||||
CreateTime: gtime.Now().String(),
|
|
||||||
},
|
|
||||||
}).Insert()
|
|
||||||
t.AssertNil(err)
|
|
||||||
n, _ := result.RowsAffected()
|
|
||||||
t.Assert(n, 1)
|
|
||||||
|
|
||||||
var user *User
|
|
||||||
err = db.Model(table).Fields(user).Where("id=100").Scan(&user)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(user.Passport, "john-test")
|
|
||||||
t.Assert(user.Id, 100)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is no longer used as the filter feature is automatically enabled from GoFrame v1.16.0.
|
|
||||||
// func Test_Model_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
|
||||||
// table := createTable()
|
|
||||||
// defer dropTable(table)
|
|
||||||
//
|
|
||||||
// gtest.C(t, func(t *gtest.T) {
|
|
||||||
// type User struct {
|
|
||||||
// Id int
|
|
||||||
// Passport string
|
|
||||||
// Password string
|
|
||||||
// Nickname string
|
|
||||||
// CreateTime string
|
|
||||||
// NoneExistFiled string
|
|
||||||
// }
|
|
||||||
// data := User{
|
|
||||||
// Id: 1,
|
|
||||||
// Passport: "user_1",
|
|
||||||
// Password: "pass_1",
|
|
||||||
// Nickname: "name_1",
|
|
||||||
// CreateTime: "2020-10-10 12:00:01",
|
|
||||||
// }
|
|
||||||
// _, err := db.Model(table).Data(data).Insert()
|
|
||||||
// t.AssertNE(err, nil)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
func Test_Model_Fields_AutoFilterInJoinStatement(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var err error
|
|
||||||
table1 := "user"
|
|
||||||
table2 := "score"
|
|
||||||
table3 := "info"
|
|
||||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
|
||||||
CREATE TABLE IF NOT EXISTS %s (
|
|
||||||
id int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
name varchar(500) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
|
||||||
`, table1,
|
|
||||||
)); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
defer dropTable(table1)
|
|
||||||
_, err = db.Model(table1).Insert(g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"name": "john",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
|
||||||
CREATE TABLE IF NOT EXISTS %s (
|
|
||||||
id int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
user_id int(11) NOT NULL DEFAULT 0,
|
|
||||||
number varchar(500) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
|
||||||
`, table2,
|
|
||||||
)); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
defer dropTable(table2)
|
|
||||||
_, err = db.Model(table2).Insert(g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"user_id": 1,
|
|
||||||
"number": "n",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
|
||||||
CREATE TABLE IF NOT EXISTS %s (
|
|
||||||
id int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
user_id int(11) NOT NULL DEFAULT 0,
|
|
||||||
description varchar(500) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
|
||||||
`, table3,
|
|
||||||
)); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
defer dropTable(table3)
|
|
||||||
_, err = db.Model(table3).Insert(g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"user_id": 1,
|
|
||||||
"description": "brief",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
one, err := db.Model("user").
|
|
||||||
Where("user.id", 1).
|
|
||||||
Fields("score.number,user.name").
|
|
||||||
LeftJoin("score", "user.id=score.user_id").
|
|
||||||
LeftJoin("info", "info.id=info.user_id").
|
|
||||||
Order("user.id asc").
|
|
||||||
One()
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(one), 2)
|
|
||||||
t.Assert(one["name"].String(), "john")
|
|
||||||
t.Assert(one["number"].String(), "n")
|
|
||||||
|
|
||||||
one, err = db.Model("user").
|
|
||||||
LeftJoin("score", "user.id=score.user_id").
|
|
||||||
LeftJoin("info", "info.id=info.user_id").
|
|
||||||
Fields("score.number,user.name").
|
|
||||||
One()
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(one), 2)
|
|
||||||
t.Assert(one["name"].String(), "john")
|
|
||||||
t.Assert(one["number"].String(), "n")
|
|
||||||
})
|
|
||||||
}
|
|
@ -3854,3 +3854,289 @@ func Test_Model_GTime_DefaultValue(t *testing.T) {
|
|||||||
t.AssertNil(err)
|
t.AssertNil(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using filter does not affect the outside value inside function.
|
||||||
|
func Test_Model_Insert_Filter(t *testing.T) {
|
||||||
|
// map
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
table := createTable()
|
||||||
|
defer dropTable(table)
|
||||||
|
data := g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"uid": 1,
|
||||||
|
"passport": "t1",
|
||||||
|
"password": "25d55ad283aa400af464c76d713c07ad",
|
||||||
|
"nickname": "name_1",
|
||||||
|
"create_time": gtime.Now().String(),
|
||||||
|
}
|
||||||
|
result, err := db.Model(table).Data(data).Insert()
|
||||||
|
t.AssertNil(err)
|
||||||
|
n, _ := result.LastInsertId()
|
||||||
|
t.Assert(n, 1)
|
||||||
|
|
||||||
|
t.Assert(data["uid"], 1)
|
||||||
|
})
|
||||||
|
// slice
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
table := createTable()
|
||||||
|
defer dropTable(table)
|
||||||
|
data := g.List{
|
||||||
|
g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"uid": 1,
|
||||||
|
"passport": "t1",
|
||||||
|
"password": "25d55ad283aa400af464c76d713c07ad",
|
||||||
|
"nickname": "name_1",
|
||||||
|
"create_time": gtime.Now().String(),
|
||||||
|
},
|
||||||
|
g.Map{
|
||||||
|
"id": 2,
|
||||||
|
"uid": 2,
|
||||||
|
"passport": "t1",
|
||||||
|
"password": "25d55ad283aa400af464c76d713c07ad",
|
||||||
|
"nickname": "name_1",
|
||||||
|
"create_time": gtime.Now().String(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := db.Model(table).Data(data).Insert()
|
||||||
|
t.AssertNil(err)
|
||||||
|
n, _ := result.LastInsertId()
|
||||||
|
t.Assert(n, 2)
|
||||||
|
|
||||||
|
t.Assert(data[0]["uid"], 1)
|
||||||
|
t.Assert(data[1]["uid"], 2)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Model_Embedded_Filter(t *testing.T) {
|
||||||
|
table := createTable()
|
||||||
|
defer dropTable(table)
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
type Base struct {
|
||||||
|
Id int
|
||||||
|
Uid int
|
||||||
|
CreateTime string
|
||||||
|
NoneExist string
|
||||||
|
}
|
||||||
|
type User struct {
|
||||||
|
Base
|
||||||
|
Passport string
|
||||||
|
Password string
|
||||||
|
Nickname string
|
||||||
|
}
|
||||||
|
result, err := db.Model(table).Data(User{
|
||||||
|
Passport: "john-test",
|
||||||
|
Password: "123456",
|
||||||
|
Nickname: "John",
|
||||||
|
Base: Base{
|
||||||
|
Id: 100,
|
||||||
|
Uid: 100,
|
||||||
|
CreateTime: gtime.Now().String(),
|
||||||
|
},
|
||||||
|
}).Insert()
|
||||||
|
t.AssertNil(err)
|
||||||
|
n, _ := result.RowsAffected()
|
||||||
|
t.Assert(n, 1)
|
||||||
|
|
||||||
|
var user *User
|
||||||
|
err = db.Model(table).Fields(user).Where("id=100").Scan(&user)
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(user.Passport, "john-test")
|
||||||
|
t.Assert(user.Id, 100)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is no longer used as the filter feature is automatically enabled from GoFrame v1.16.0.
|
||||||
|
// func Test_Model_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
||||||
|
// table := createTable()
|
||||||
|
// defer dropTable(table)
|
||||||
|
//
|
||||||
|
// gtest.C(t, func(t *gtest.T) {
|
||||||
|
// type User struct {
|
||||||
|
// Id int
|
||||||
|
// Passport string
|
||||||
|
// Password string
|
||||||
|
// Nickname string
|
||||||
|
// CreateTime string
|
||||||
|
// NoneExistFiled string
|
||||||
|
// }
|
||||||
|
// data := User{
|
||||||
|
// Id: 1,
|
||||||
|
// Passport: "user_1",
|
||||||
|
// Password: "pass_1",
|
||||||
|
// Nickname: "name_1",
|
||||||
|
// CreateTime: "2020-10-10 12:00:01",
|
||||||
|
// }
|
||||||
|
// _, err := db.Model(table).Data(data).Insert()
|
||||||
|
// t.AssertNE(err, nil)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
func Test_Model_Fields_AutoFilterInJoinStatement(t *testing.T) {
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
var err error
|
||||||
|
table1 := "user"
|
||||||
|
table2 := "score"
|
||||||
|
table3 := "info"
|
||||||
|
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||||
|
CREATE TABLE IF NOT EXISTS %s (
|
||||||
|
id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
name varchar(500) NOT NULL DEFAULT '',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
||||||
|
`, table1,
|
||||||
|
)); err != nil {
|
||||||
|
t.AssertNil(err)
|
||||||
|
}
|
||||||
|
defer dropTable(table1)
|
||||||
|
_, err = db.Model(table1).Insert(g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"name": "john",
|
||||||
|
})
|
||||||
|
t.AssertNil(err)
|
||||||
|
|
||||||
|
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||||
|
CREATE TABLE IF NOT EXISTS %s (
|
||||||
|
id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id int(11) NOT NULL DEFAULT 0,
|
||||||
|
number varchar(500) NOT NULL DEFAULT '',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
||||||
|
`, table2,
|
||||||
|
)); err != nil {
|
||||||
|
t.AssertNil(err)
|
||||||
|
}
|
||||||
|
defer dropTable(table2)
|
||||||
|
_, err = db.Model(table2).Insert(g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"user_id": 1,
|
||||||
|
"number": "n",
|
||||||
|
})
|
||||||
|
t.AssertNil(err)
|
||||||
|
|
||||||
|
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||||
|
CREATE TABLE IF NOT EXISTS %s (
|
||||||
|
id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id int(11) NOT NULL DEFAULT 0,
|
||||||
|
description varchar(500) NOT NULL DEFAULT '',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
||||||
|
`, table3,
|
||||||
|
)); err != nil {
|
||||||
|
t.AssertNil(err)
|
||||||
|
}
|
||||||
|
defer dropTable(table3)
|
||||||
|
_, err = db.Model(table3).Insert(g.Map{
|
||||||
|
"id": 1,
|
||||||
|
"user_id": 1,
|
||||||
|
"description": "brief",
|
||||||
|
})
|
||||||
|
t.AssertNil(err)
|
||||||
|
|
||||||
|
one, err := db.Model("user").
|
||||||
|
Where("user.id", 1).
|
||||||
|
Fields("score.number,user.name").
|
||||||
|
LeftJoin("score", "user.id=score.user_id").
|
||||||
|
LeftJoin("info", "info.id=info.user_id").
|
||||||
|
Order("user.id asc").
|
||||||
|
One()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(len(one), 2)
|
||||||
|
t.Assert(one["name"].String(), "john")
|
||||||
|
t.Assert(one["number"].String(), "n")
|
||||||
|
|
||||||
|
one, err = db.Model("user").
|
||||||
|
LeftJoin("score", "user.id=score.user_id").
|
||||||
|
LeftJoin("info", "info.id=info.user_id").
|
||||||
|
Fields("score.number,user.name").
|
||||||
|
One()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(len(one), 2)
|
||||||
|
t.Assert(one["name"].String(), "john")
|
||||||
|
t.Assert(one["number"].String(), "n")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Model_WherePrefix(t *testing.T) {
|
||||||
|
var (
|
||||||
|
table1 = gtime.TimestampNanoStr() + "_table1"
|
||||||
|
table2 = gtime.TimestampNanoStr() + "_table2"
|
||||||
|
)
|
||||||
|
createInitTable(table1)
|
||||||
|
defer dropTable(table1)
|
||||||
|
createInitTable(table2)
|
||||||
|
defer dropTable(table2)
|
||||||
|
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
r, err := db.Model(table1).
|
||||||
|
FieldsPrefix(table1, "*").
|
||||||
|
LeftJoinOnField(table2, "id").
|
||||||
|
WherePrefix(table2, g.Map{
|
||||||
|
"id": g.Slice{1, 2},
|
||||||
|
}).
|
||||||
|
Order("id asc").All()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(len(r), 2)
|
||||||
|
t.Assert(r[0]["id"], "1")
|
||||||
|
t.Assert(r[1]["id"], "2")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Model_WhereOrPrefix(t *testing.T) {
|
||||||
|
var (
|
||||||
|
table1 = gtime.TimestampNanoStr() + "_table1"
|
||||||
|
table2 = gtime.TimestampNanoStr() + "_table2"
|
||||||
|
)
|
||||||
|
createInitTable(table1)
|
||||||
|
defer dropTable(table1)
|
||||||
|
createInitTable(table2)
|
||||||
|
defer dropTable(table2)
|
||||||
|
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
r, err := db.Model(table1).
|
||||||
|
FieldsPrefix(table1, "*").
|
||||||
|
LeftJoinOnField(table2, "id").
|
||||||
|
WhereOrPrefix(table1, g.Map{
|
||||||
|
"id": g.Slice{1, 2},
|
||||||
|
}).
|
||||||
|
WhereOrPrefix(table2, g.Map{
|
||||||
|
"id": g.Slice{8, 9},
|
||||||
|
}).
|
||||||
|
Order("id asc").All()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(len(r), 4)
|
||||||
|
t.Assert(r[0]["id"], "1")
|
||||||
|
t.Assert(r[1]["id"], "2")
|
||||||
|
t.Assert(r[2]["id"], "8")
|
||||||
|
t.Assert(r[3]["id"], "9")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Model_WherePrefixLike(t *testing.T) {
|
||||||
|
var (
|
||||||
|
table1 = gtime.TimestampNanoStr() + "_table1"
|
||||||
|
table2 = gtime.TimestampNanoStr() + "_table2"
|
||||||
|
)
|
||||||
|
createInitTable(table1)
|
||||||
|
defer dropTable(table1)
|
||||||
|
createInitTable(table2)
|
||||||
|
defer dropTable(table2)
|
||||||
|
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
r, err := db.Model(table1).
|
||||||
|
FieldsPrefix(table1, "*").
|
||||||
|
LeftJoinOnField(table2, "id").
|
||||||
|
WherePrefix(table1, g.Map{
|
||||||
|
"id": g.Slice{1, 2, 3},
|
||||||
|
}).
|
||||||
|
WherePrefix(table2, g.Map{
|
||||||
|
"id": g.Slice{3, 4, 5},
|
||||||
|
}).
|
||||||
|
WherePrefixLike(table2, "nickname", "name%").
|
||||||
|
Order("id asc").All()
|
||||||
|
t.AssertNil(err)
|
||||||
|
t.Assert(len(r), 1)
|
||||||
|
t.Assert(r[0]["id"], "3")
|
||||||
|
})
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Model_WherePrefix(t *testing.T) {
|
|
||||||
var (
|
|
||||||
table1 = gtime.TimestampNanoStr() + "_table1"
|
|
||||||
table2 = gtime.TimestampNanoStr() + "_table2"
|
|
||||||
)
|
|
||||||
createInitTable(table1)
|
|
||||||
defer dropTable(table1)
|
|
||||||
createInitTable(table2)
|
|
||||||
defer dropTable(table2)
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
r, err := db.Model(table1).
|
|
||||||
FieldsPrefix(table1, "*").
|
|
||||||
LeftJoinOnField(table2, "id").
|
|
||||||
WherePrefix(table2, g.Map{
|
|
||||||
"id": g.Slice{1, 2},
|
|
||||||
}).
|
|
||||||
Order("id asc").All()
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(r), 2)
|
|
||||||
t.Assert(r[0]["id"], "1")
|
|
||||||
t.Assert(r[1]["id"], "2")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Model_WhereOrPrefix(t *testing.T) {
|
|
||||||
var (
|
|
||||||
table1 = gtime.TimestampNanoStr() + "_table1"
|
|
||||||
table2 = gtime.TimestampNanoStr() + "_table2"
|
|
||||||
)
|
|
||||||
createInitTable(table1)
|
|
||||||
defer dropTable(table1)
|
|
||||||
createInitTable(table2)
|
|
||||||
defer dropTable(table2)
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
r, err := db.Model(table1).
|
|
||||||
FieldsPrefix(table1, "*").
|
|
||||||
LeftJoinOnField(table2, "id").
|
|
||||||
WhereOrPrefix(table1, g.Map{
|
|
||||||
"id": g.Slice{1, 2},
|
|
||||||
}).
|
|
||||||
WhereOrPrefix(table2, g.Map{
|
|
||||||
"id": g.Slice{8, 9},
|
|
||||||
}).
|
|
||||||
Order("id asc").All()
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(r), 4)
|
|
||||||
t.Assert(r[0]["id"], "1")
|
|
||||||
t.Assert(r[1]["id"], "2")
|
|
||||||
t.Assert(r[2]["id"], "8")
|
|
||||||
t.Assert(r[3]["id"], "9")
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// All types testing.
|
|
||||||
func Test_Types(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
|
||||||
CREATE TABLE IF NOT EXISTS types (
|
|
||||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
%s blob NOT NULL,
|
|
||||||
%s binary(8) NOT NULL,
|
|
||||||
%s date NOT NULL,
|
|
||||||
%s time NOT NULL,
|
|
||||||
%s decimal(5,2) NOT NULL,
|
|
||||||
%s double NOT NULL,
|
|
||||||
%s bit(2) NOT NULL,
|
|
||||||
%s tinyint(1) NOT NULL,
|
|
||||||
%s bool NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
`,
|
|
||||||
"`blob`",
|
|
||||||
"`binary`",
|
|
||||||
"`date`",
|
|
||||||
"`time`",
|
|
||||||
"`decimal`",
|
|
||||||
"`double`",
|
|
||||||
"`bit`",
|
|
||||||
"`tinyint`",
|
|
||||||
"`bool`")); err != nil {
|
|
||||||
gtest.Error(err)
|
|
||||||
}
|
|
||||||
defer dropTable("types")
|
|
||||||
data := g.Map{
|
|
||||||
"id": 1,
|
|
||||||
"blob": "i love gf",
|
|
||||||
"binary": []byte("abcdefgh"),
|
|
||||||
"date": "1880-10-24",
|
|
||||||
"time": "10:00:01",
|
|
||||||
"decimal": -123.456,
|
|
||||||
"double": -123.456,
|
|
||||||
"bit": 2,
|
|
||||||
"tinyint": true,
|
|
||||||
"bool": false,
|
|
||||||
}
|
|
||||||
r, err := db.Model("types").Data(data).Insert()
|
|
||||||
t.AssertNil(err)
|
|
||||||
n, _ := r.RowsAffected()
|
|
||||||
t.Assert(n, 1)
|
|
||||||
|
|
||||||
one, err := db.Model("types").One()
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(one["id"].Int(), 1)
|
|
||||||
t.Assert(one["blob"].String(), data["blob"])
|
|
||||||
t.Assert(one["binary"].String(), data["binary"])
|
|
||||||
t.Assert(one["date"].String(), data["date"])
|
|
||||||
t.Assert(one["time"].String(), `0000-01-01 10:00:01`)
|
|
||||||
t.Assert(one["decimal"].String(), -123.46)
|
|
||||||
t.Assert(one["double"].String(), data["double"])
|
|
||||||
t.Assert(one["bit"].Int(), data["bit"])
|
|
||||||
t.Assert(one["tinyint"].Bool(), data["tinyint"])
|
|
||||||
|
|
||||||
type T struct {
|
|
||||||
Id int
|
|
||||||
Blob []byte
|
|
||||||
Binary []byte
|
|
||||||
Date *gtime.Time
|
|
||||||
Time *gtime.Time
|
|
||||||
Decimal float64
|
|
||||||
Double float64
|
|
||||||
Bit int8
|
|
||||||
TinyInt bool
|
|
||||||
}
|
|
||||||
var obj *T
|
|
||||||
err = db.Model("types").Scan(&obj)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(obj.Id, 1)
|
|
||||||
t.Assert(obj.Blob, data["blob"])
|
|
||||||
t.Assert(obj.Binary, data["binary"])
|
|
||||||
t.Assert(obj.Date.Format("Y-m-d"), data["date"])
|
|
||||||
t.Assert(obj.Time.String(), `0000-01-01 10:00:01`)
|
|
||||||
t.Assert(obj.Decimal, -123.46)
|
|
||||||
t.Assert(obj.Double, data["double"])
|
|
||||||
t.Assert(obj.Bit, data["bit"])
|
|
||||||
t.Assert(obj.TinyInt, data["tinyint"])
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Oracle_parseSql(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
o := new(DriverOracle)
|
|
||||||
sql := `UPDATE user SET name='john'`
|
|
||||||
newSql := o.parseSql(sql)
|
|
||||||
t.Assert(newSql, sql)
|
|
||||||
})
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
o := new(DriverOracle)
|
|
||||||
sql := `SELECT * FROM user`
|
|
||||||
newSql := o.parseSql(sql)
|
|
||||||
t.Assert(newSql, sql)
|
|
||||||
})
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
o := new(DriverOracle)
|
|
||||||
sql := `SELECT * FROM user LIMIT 0, 10`
|
|
||||||
newSql := o.parseSql(sql)
|
|
||||||
t.Assert(newSql, `SELECT * FROM (SELECT GFORM.*, ROWNUM ROWNUM_ FROM (SELECT * FROM user ) GFORM WHERE ROWNUM <= 10) WHERE ROWNUM_ >= 0`)
|
|
||||||
})
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
o := new(DriverOracle)
|
|
||||||
sql := `SELECT * FROM user LIMIT 1`
|
|
||||||
newSql := o.parseSql(sql)
|
|
||||||
t.Assert(newSql, `SELECT * FROM (SELECT GFORM.*, ROWNUM ROWNUM_ FROM (SELECT * FROM user ) GFORM WHERE ROWNUM <= 1) WHERE ROWNUM_ >= 0`)
|
|
||||||
})
|
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
o := new(DriverOracle)
|
|
||||||
sql := `SELECT ENAME FROM USER_INFO WHERE ID=2 LIMIT 1`
|
|
||||||
newSql := o.parseSql(sql)
|
|
||||||
t.Assert(newSql, `SELECT * FROM (SELECT GFORM.*, ROWNUM ROWNUM_ FROM (SELECT ENAME FROM USER_INFO WHERE ID=2 ) GFORM WHERE ROWNUM <= 1) WHERE ROWNUM_ >= 0`)
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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 ghttp_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/container/garray"
|
|
||||||
"github.com/gogf/gf/v2/os/genv"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ctx = context.TODO()
|
|
||||||
ports = garray.NewIntArray(true)
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
genv.Set("UNDER_TEST", "1")
|
|
||||||
for i := 7000; i <= 8000; i++ {
|
|
||||||
ports.Append(i)
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user