mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +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"
|
||||
|
||||
// iInterfaces is used for type assert api for Interfaces.
|
||||
type iInterfaces interface {
|
||||
Interfaces() []interface{}
|
||||
}
|
||||
|
||||
// defaultComparatorInt for int comparison.
|
||||
func defaultComparatorInt(a, b int) int {
|
||||
if a < b {
|
||||
|
@ -31,7 +31,7 @@ func ExampleStrArray_Walk() {
|
||||
// [gf_user gf_user_detail]
|
||||
}
|
||||
|
||||
func ExampleStrArray_NewStrArray() {
|
||||
func ExampleNewStrArray() {
|
||||
s := garray.NewStrArray()
|
||||
s.Append("We")
|
||||
s.Append("are")
|
||||
@ -43,7 +43,7 @@ func ExampleStrArray_NewStrArray() {
|
||||
// [We are GF fans]
|
||||
}
|
||||
|
||||
func ExampleStrArray_NewStrArraySize() {
|
||||
func ExampleNewStrArraySize() {
|
||||
s := garray.NewStrArraySize(3, 5)
|
||||
s.Set(0, "We")
|
||||
s.Set(1, "are")
|
||||
@ -55,7 +55,7 @@ func ExampleStrArray_NewStrArraySize() {
|
||||
// [We are GF] 3 5
|
||||
}
|
||||
|
||||
func ExampleStrArray_NewStrArrayFrom() {
|
||||
func ExampleNewStrArrayFrom() {
|
||||
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
||||
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
|
||||
|
||||
@ -63,14 +63,6 @@ func ExampleStrArray_NewStrArrayFrom() {
|
||||
// [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() {
|
||||
s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"})
|
||||
sAt := s.At(2)
|
@ -376,7 +376,7 @@ func formatSql(sql string, args []interface{}) (newSql string, newArgs []interfa
|
||||
return handleArguments(sql, args)
|
||||
}
|
||||
|
||||
type formatWhereInput struct {
|
||||
type formatWhereHolderInput struct {
|
||||
Where interface{}
|
||||
Args []interface{}
|
||||
OmitNil bool
|
||||
@ -386,8 +386,8 @@ type formatWhereInput struct {
|
||||
Prefix string // Field prefix, eg: "user.", "order.".
|
||||
}
|
||||
|
||||
// formatWhere formats where statement and its arguments for `Where` and `Having` statements.
|
||||
func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interface{}) {
|
||||
// formatWhereHolder formats where statement and its arguments for `Where` and `Having` statements.
|
||||
func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newArgs []interface{}) {
|
||||
var (
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
reflectInfo = utils.OriginValueAndKind(in.Where)
|
||||
@ -454,8 +454,8 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
var (
|
||||
reflectType = reflectInfo.OriginValue.Type()
|
||||
structField reflect.StructField
|
||||
data = DataToMapDeep(in.Where)
|
||||
)
|
||||
data := DataToMapDeep(in.Where)
|
||||
if in.Table != "" {
|
||||
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:
|
||||
// Usually a string.
|
||||
|
||||
whereStr := gconv.String(in.Where)
|
||||
|
||||
// Is `whereStr` a field name which composed as a key-value condition?
|
||||
// Eg:
|
||||
// Where("id", 1)
|
||||
@ -514,9 +512,7 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
||||
// Regular string and parameter place holder handling.
|
||||
// Eg:
|
||||
// Where("id in(?) and name=?", g.Slice{1,2,3}, "john")
|
||||
|
||||
i := 0
|
||||
|
||||
for {
|
||||
if i >= len(in.Args) {
|
||||
break
|
||||
@ -608,13 +604,13 @@ func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, new
|
||||
}
|
||||
|
||||
type formatWhereKeyValueInput struct {
|
||||
Db DB
|
||||
Buffer *bytes.Buffer
|
||||
Args []interface{}
|
||||
Key string
|
||||
Value interface{}
|
||||
OmitEmpty bool
|
||||
Prefix string // Field prefix, eg: "user.", "order.".
|
||||
Db DB // Db is the underlying DB object for current operation.
|
||||
Buffer *bytes.Buffer // Buffer is the sql statement string without Args for current operation.
|
||||
Args []interface{} // Args is the full arguments of current operation.
|
||||
Key string // The field name, eg: "id", "name", etc.
|
||||
Value interface{} // The field value, can be any types.
|
||||
OmitEmpty bool // Ignores current condition key if `value` is empty.
|
||||
Prefix string // Field prefix, eg: "user", "order", etc.
|
||||
}
|
||||
|
||||
// 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 {
|
||||
conditionStr := gconv.String(tableNameQueryOrStruct[0])
|
||||
if gstr.Contains(conditionStr, "?") {
|
||||
tableStr, extraArgs = formatWhere(c.db, formatWhereInput{
|
||||
tableStr, extraArgs = formatWhereHolder(c.db, formatWhereHolderInput{
|
||||
Where: conditionStr,
|
||||
Args: tableNameQueryOrStruct[1:],
|
||||
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] != "" {
|
||||
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.
|
||||
@ -120,7 +120,7 @@ func (m *Model) FieldSum(column string, as ...string) *Model {
|
||||
if len(as) > 0 && as[0] != "" {
|
||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`SUM(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
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.
|
||||
@ -129,7 +129,7 @@ func (m *Model) FieldMin(column string, as ...string) *Model {
|
||||
if len(as) > 0 && as[0] != "" {
|
||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`MIN(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
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.
|
||||
@ -138,7 +138,7 @@ func (m *Model) FieldMax(column string, as ...string) *Model {
|
||||
if len(as) > 0 && as[0] != "" {
|
||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`MAX(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
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.
|
||||
@ -147,7 +147,7 @@ func (m *Model) FieldAvg(column string, as ...string) *Model {
|
||||
if len(as) > 0 && as[0] != "" {
|
||||
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
||||
}
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.db.GetCore().QuoteWord(column), asStr))
|
||||
return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr))
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// It converts any data to List type for inserting.
|
||||
switch value := newData.(type) {
|
||||
case Result:
|
||||
@ -311,7 +310,6 @@ func (m *Model) doInsertWithOption(insertOption int) (result sql.Result, err err
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
@ -385,7 +385,7 @@ func (m *Model) Max(column string) (float64, error) {
|
||||
if len(column) == 0 {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
@ -397,7 +397,7 @@ func (m *Model) Avg(column string) (float64, error) {
|
||||
if len(column) == 0 {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
@ -409,7 +409,7 @@ func (m *Model) Sum(column string) (float64, error) {
|
||||
if len(column) == 0 {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
@ -426,6 +426,61 @@ func (m *Model) UnionAll(unions ...*Model) *Model {
|
||||
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.
|
||||
func (m *Model) doGetAllBySql(sql string, args ...interface{}) (result Result, err error) {
|
||||
var (
|
||||
@ -520,3 +575,150 @@ func (m *Model) getFormattedSqlAndArgs(queryType int, limit1 bool) (sqlWithHolde
|
||||
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"
|
||||
)
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
var (
|
||||
tableUser = "user1"
|
||||
tableUserDetail = "user_detail1"
|
||||
tableUserScores = "user_scores1"
|
||||
tableUser = "user100"
|
||||
tableUserDetail = "user_detail100"
|
||||
tableUserScores = "user_scores100"
|
||||
)
|
||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||
CREATE TABLE IF NOT EXISTS %s (
|
||||
@ -1910,13 +1910,13 @@ PRIMARY KEY (id)
|
||||
defer dropTable(tableUserScores)
|
||||
|
||||
type UserDetail struct {
|
||||
gmeta.Meta `orm:"table:user_detail1"`
|
||||
gmeta.Meta `orm:"table:user_detail100"`
|
||||
UserID int `json:"user_id"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type UserScores struct {
|
||||
gmeta.Meta `orm:"table:user_scores1"`
|
||||
gmeta.Meta `orm:"table:user_scores100"`
|
||||
ID int `json:"id"`
|
||||
UserID int `json:"user_id"`
|
||||
Score int `json:"score"`
|
||||
@ -1929,7 +1929,7 @@ PRIMARY KEY (id)
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gmeta.Meta `orm:"table:user1"`
|
||||
gmeta.Meta `orm:"table:user100"`
|
||||
UserEmbedded
|
||||
UserDetail UserDetail `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) {
|
||||
// var user *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)
|
||||
})
|
||||
}
|
||||
|
||||
// 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