This commit is contained in:
huangqian 2021-11-18 07:33:29 +08:00
commit 3f4dff462d
188 changed files with 1682 additions and 1710 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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.

View File

@ -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,

View File

@ -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
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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
}

View File

@ -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.
//

View 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
}

View 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
}

View 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
}

View 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
}

View File

@ -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"])
})
}

View File

@ -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)

View File

@ -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")
})
}

View File

@ -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")
})
}

View File

@ -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")
})
}

View File

@ -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"])
})
}

View File

@ -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`)
})
}

View File

@ -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