mirror of
https://gitee.com/johng/gf.git
synced 2024-12-01 19:57:40 +08:00
files renaming for package gdb
This commit is contained in:
parent
f2ef7454c2
commit
732664a1ff
@ -1,434 +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
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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.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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
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
|
||||
}
|
@ -6,97 +6,6 @@
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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')
|
@ -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,98 +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")
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
db.SetDebug(true)
|
||||
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,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`)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user