From 732664a1ff6c84b3466afc5bf9b6489b185027d3 Mon Sep 17 00:00:00 2001 From: John Guo Date: Wed, 17 Nov 2021 22:01:17 +0800 Subject: [PATCH] files renaming for package gdb --- database/gdb/gdb_model_condition.go | 434 ------------------ database/gdb/gdb_model_insert.go | 2 - database/gdb/gdb_model_select.go | 202 ++++++++ database/gdb/gdb_model_where.go | 137 ++++++ database/gdb/gdb_model_where_prefix.go | 98 ++++ database/gdb/gdb_model_whereor.go | 107 +++++ ..._prefix.go => gdb_model_whereor_prefix.go} | 91 ---- ...ethod_test.go => gdb_z_mysql_core_test.go} | 85 ++++ ...est.go => gdb_z_mysql_feature_ctx_test.go} | 0 ...gdb_z_mysql_feature_model_for_dao_test.go} | 0 ...=> gdb_z_mysql_feature_model_join_test.go} | 0 ... gdb_z_mysql_feature_model_struct_test.go} | 0 ...db_z_mysql_feature_model_subquery_test.go} | 0 ...o => gdb_z_mysql_feature_raw_type_test.go} | 0 ...o => gdb_z_mysql_feature_scanlist_test.go} | 0 ...gdb_z_mysql_feature_time_maintain_test.go} | 0 ...t.go => gdb_z_mysql_feature_union_test.go} | 0 ...st.go => gdb_z_mysql_feature_with_test.go} | 15 +- database/gdb/gdb_z_mysql_model_filter_test.go | 219 --------- ...asic_test.go => gdb_z_mysql_model_test.go} | 286 ++++++++++++ .../gdb_z_mysql_model_where_prefix_test.go | 98 ---- database/gdb/gdb_z_mysql_types_test.go | 101 ---- database/gdb/gdb_z_oracle_internal_test.go | 50 -- 23 files changed, 921 insertions(+), 1004 deletions(-) delete mode 100644 database/gdb/gdb_model_condition.go create mode 100644 database/gdb/gdb_model_where.go create mode 100644 database/gdb/gdb_model_where_prefix.go create mode 100644 database/gdb/gdb_model_whereor.go rename database/gdb/{gdb_model_condition_prefix.go => gdb_model_whereor_prefix.go} (52%) rename database/gdb/{gdb_z_mysql_method_test.go => gdb_z_mysql_core_test.go} (94%) rename database/gdb/{gdb_z_mysql_ctx_test.go => gdb_z_mysql_feature_ctx_test.go} (100%) rename database/gdb/{gdb_z_mysql_model_for_dao_test.go => gdb_z_mysql_feature_model_for_dao_test.go} (100%) rename database/gdb/{gdb_z_mysql_model_join_test.go => gdb_z_mysql_feature_model_join_test.go} (100%) rename database/gdb/{gdb_z_mysql_model_struct_test.go => gdb_z_mysql_feature_model_struct_test.go} (100%) rename database/gdb/{gdb_z_mysql_model_subquery_test.go => gdb_z_mysql_feature_model_subquery_test.go} (100%) rename database/gdb/{gdb_z_mysql_raw_type_test.go => gdb_z_mysql_feature_raw_type_test.go} (100%) rename database/gdb/{gdb_z_mysql_association_scanlist_test.go => gdb_z_mysql_feature_scanlist_test.go} (100%) rename database/gdb/{gdb_z_mysql_time_maintain_test.go => gdb_z_mysql_feature_time_maintain_test.go} (100%) rename database/gdb/{gdb_z_mysql_union_test.go => gdb_z_mysql_feature_union_test.go} (100%) rename database/gdb/{gdb_z_mysql_association_with_test.go => gdb_z_mysql_feature_with_test.go} (99%) delete mode 100644 database/gdb/gdb_z_mysql_model_filter_test.go rename database/gdb/{gdb_z_mysql_model_basic_test.go => gdb_z_mysql_model_test.go} (93%) delete mode 100644 database/gdb/gdb_z_mysql_model_where_prefix_test.go delete mode 100644 database/gdb/gdb_z_mysql_types_test.go delete mode 100644 database/gdb/gdb_z_oracle_internal_test.go diff --git a/database/gdb/gdb_model_condition.go b/database/gdb/gdb_model_condition.go deleted file mode 100644 index ac34d470e..000000000 --- a/database/gdb/gdb_model_condition.go +++ /dev/null @@ -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 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 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 -} diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index 6ec74ba70..0333c2445 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -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) } diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 12b5c5056..9e4006c61 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -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 +} diff --git a/database/gdb/gdb_model_where.go b/database/gdb/gdb_model_where.go new file mode 100644 index 000000000..3a123c71e --- /dev/null +++ b/database/gdb/gdb_model_where.go @@ -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 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 +} diff --git a/database/gdb/gdb_model_where_prefix.go b/database/gdb/gdb_model_where_prefix.go new file mode 100644 index 000000000..a8cc761db --- /dev/null +++ b/database/gdb/gdb_model_where_prefix.go @@ -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 +} diff --git a/database/gdb/gdb_model_whereor.go b/database/gdb/gdb_model_whereor.go new file mode 100644 index 000000000..3b0016f45 --- /dev/null +++ b/database/gdb/gdb_model_whereor.go @@ -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 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 +} diff --git a/database/gdb/gdb_model_condition_prefix.go b/database/gdb/gdb_model_whereor_prefix.go similarity index 52% rename from database/gdb/gdb_model_condition_prefix.go rename to database/gdb/gdb_model_whereor_prefix.go index 4ffbc7e72..74189a807 100644 --- a/database/gdb/gdb_model_condition_prefix.go +++ b/database/gdb/gdb_model_whereor_prefix.go @@ -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') diff --git a/database/gdb/gdb_z_mysql_method_test.go b/database/gdb/gdb_z_mysql_core_test.go similarity index 94% rename from database/gdb/gdb_z_mysql_method_test.go rename to database/gdb/gdb_z_mysql_core_test.go index b16a91f55..750645e86 100644 --- a/database/gdb/gdb_z_mysql_method_test.go +++ b/database/gdb/gdb_z_mysql_core_test.go @@ -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"]) + }) +} diff --git a/database/gdb/gdb_z_mysql_ctx_test.go b/database/gdb/gdb_z_mysql_feature_ctx_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_ctx_test.go rename to database/gdb/gdb_z_mysql_feature_ctx_test.go diff --git a/database/gdb/gdb_z_mysql_model_for_dao_test.go b/database/gdb/gdb_z_mysql_feature_model_for_dao_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_model_for_dao_test.go rename to database/gdb/gdb_z_mysql_feature_model_for_dao_test.go diff --git a/database/gdb/gdb_z_mysql_model_join_test.go b/database/gdb/gdb_z_mysql_feature_model_join_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_model_join_test.go rename to database/gdb/gdb_z_mysql_feature_model_join_test.go diff --git a/database/gdb/gdb_z_mysql_model_struct_test.go b/database/gdb/gdb_z_mysql_feature_model_struct_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_model_struct_test.go rename to database/gdb/gdb_z_mysql_feature_model_struct_test.go diff --git a/database/gdb/gdb_z_mysql_model_subquery_test.go b/database/gdb/gdb_z_mysql_feature_model_subquery_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_model_subquery_test.go rename to database/gdb/gdb_z_mysql_feature_model_subquery_test.go diff --git a/database/gdb/gdb_z_mysql_raw_type_test.go b/database/gdb/gdb_z_mysql_feature_raw_type_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_raw_type_test.go rename to database/gdb/gdb_z_mysql_feature_raw_type_test.go diff --git a/database/gdb/gdb_z_mysql_association_scanlist_test.go b/database/gdb/gdb_z_mysql_feature_scanlist_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_association_scanlist_test.go rename to database/gdb/gdb_z_mysql_feature_scanlist_test.go diff --git a/database/gdb/gdb_z_mysql_time_maintain_test.go b/database/gdb/gdb_z_mysql_feature_time_maintain_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_time_maintain_test.go rename to database/gdb/gdb_z_mysql_feature_time_maintain_test.go diff --git a/database/gdb/gdb_z_mysql_union_test.go b/database/gdb/gdb_z_mysql_feature_union_test.go similarity index 100% rename from database/gdb/gdb_z_mysql_union_test.go rename to database/gdb/gdb_z_mysql_feature_union_test.go diff --git a/database/gdb/gdb_z_mysql_association_with_test.go b/database/gdb/gdb_z_mysql_feature_with_test.go similarity index 99% rename from database/gdb/gdb_z_mysql_association_with_test.go rename to database/gdb/gdb_z_mysql_feature_with_test.go index d0aeb549b..243e83d76 100644 --- a/database/gdb/gdb_z_mysql_association_with_test.go +++ b/database/gdb/gdb_z_mysql_feature_with_test.go @@ -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) diff --git a/database/gdb/gdb_z_mysql_model_filter_test.go b/database/gdb/gdb_z_mysql_model_filter_test.go deleted file mode 100644 index 1d5c59ff5..000000000 --- a/database/gdb/gdb_z_mysql_model_filter_test.go +++ /dev/null @@ -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") - }) -} diff --git a/database/gdb/gdb_z_mysql_model_basic_test.go b/database/gdb/gdb_z_mysql_model_test.go similarity index 93% rename from database/gdb/gdb_z_mysql_model_basic_test.go rename to database/gdb/gdb_z_mysql_model_test.go index 0e242397f..783971780 100644 --- a/database/gdb/gdb_z_mysql_model_basic_test.go +++ b/database/gdb/gdb_z_mysql_model_test.go @@ -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") + }) +} diff --git a/database/gdb/gdb_z_mysql_model_where_prefix_test.go b/database/gdb/gdb_z_mysql_model_where_prefix_test.go deleted file mode 100644 index 8c6357677..000000000 --- a/database/gdb/gdb_z_mysql_model_where_prefix_test.go +++ /dev/null @@ -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") - }) -} diff --git a/database/gdb/gdb_z_mysql_types_test.go b/database/gdb/gdb_z_mysql_types_test.go deleted file mode 100644 index f184dfb3c..000000000 --- a/database/gdb/gdb_z_mysql_types_test.go +++ /dev/null @@ -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"]) - }) -} diff --git a/database/gdb/gdb_z_oracle_internal_test.go b/database/gdb/gdb_z_oracle_internal_test.go deleted file mode 100644 index 1c01aadd7..000000000 --- a/database/gdb/gdb_z_oracle_internal_test.go +++ /dev/null @@ -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`) - }) -}