diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 8265c540a..099ada0c3 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -812,13 +812,19 @@ func (c *Core) DoUpdate(link Link, table string, data interface{}, condition str switch value := v.(type) { case *Counter: if value.Value != 0 { - column := c.db.QuoteWord(value.Field) + column := k + if value.Field != "" { + column = c.db.QuoteWord(value.Field) + } fields = append(fields, fmt.Sprintf("%s=%s+?", column, column)) params = append(params, value.Value) } case Counter: if value.Value != 0 { - column := c.db.QuoteWord(value.Field) + column := k + if value.Field != "" { + column = c.db.QuoteWord(value.Field) + } fields = append(fields, fmt.Sprintf("%s=%s+?", column, column)) params = append(params, value.Value) } @@ -829,7 +835,6 @@ func (c *Core) DoUpdate(link Link, table string, data interface{}, condition str fields = append(fields, c.db.QuoteWord(k)+"=?") params = append(params, v) } - } } updates = strings.Join(fields, ",") diff --git a/database/gdb/gdb_model.go b/database/gdb/gdb_model.go index 4b109534f..ae734d69e 100644 --- a/database/gdb/gdb_model.go +++ b/database/gdb/gdb_model.go @@ -39,6 +39,7 @@ type Model struct { data interface{} // Data for operation, which can be type of map/[]map/struct/*struct/string, etc. batch int // Batch number for batch Insert/Replace/Save operations. filter bool // Filter data and where key-value pairs according to the fields of the table. + distinct string // Force the query to only return distinct results. lockInfo string // Lock for update or in shared lock. cacheEnabled bool // Enable sql result cache feature. cacheDuration time.Duration // Cache TTL duration. diff --git a/database/gdb/gdb_model_condition.go b/database/gdb/gdb_model_condition.go index a78c43047..3ece170d8 100644 --- a/database/gdb/gdb_model_condition.go +++ b/database/gdb/gdb_model_condition.go @@ -7,6 +7,7 @@ package gdb import ( + "fmt" "strings" ) @@ -58,7 +59,125 @@ func (m *Model) WherePri(where interface{}, args ...interface{}) *Model { return m.Where(newWhere[0], newWhere[1:]...) } +// WhereBetween builds `xxx BETWEEN x AND y` statement. +func (m *Model) WhereBetween(column string, min, max interface{}) *Model { + return m.Where(fmt.Sprintf(`%s BETWEEN ? AND ?`, m.db.QuoteWord(column)), min, max) +} + +// WhereLike builds `xxx LIKE x` statement. +func (m *Model) WhereLike(column string, like interface{}) *Model { + return m.Where(fmt.Sprintf(`%s LIKE ?`, m.db.QuoteWord(column)), like) +} + +// WhereIn builds `xxx IN (x)` statement. +func (m *Model) WhereIn(column string, in interface{}) *Model { + return m.Where(fmt.Sprintf(`%s IN (?)`, m.db.QuoteWord(column)), in) +} + +// WhereNull builds `xxx IS NULL` statement. +func (m *Model) WhereNull(columns ...string) *Model { + model := m + for _, column := range columns { + model = m.Where(fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(column))) + } + return model +} + +// WhereNotBetween builds `xxx NOT BETWEEN x AND y` statement. +func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model { + return m.Where(fmt.Sprintf(`%s NOT BETWEEN ? AND ?`, m.db.QuoteWord(column)), min, max) +} + +// WhereNotLike builds `xxx NOT LIKE x` statement. +func (m *Model) WhereNotLike(column string, like interface{}) *Model { + return m.Where(fmt.Sprintf(`%s NOT LIKE ?`, m.db.QuoteWord(column)), like) +} + +// WhereNotIn builds `xxx NOT IN (x)` statement. +func (m *Model) WhereNotIn(column string, in interface{}) *Model { + return m.Where(fmt.Sprintf(`%s NOT IN (?)`, m.db.QuoteWord(column)), in) +} + +// WhereNotNull builds `xxx IS NOT NULL` statement. +func (m *Model) WhereNotNull(columns ...string) *Model { + model := m + for _, column := range columns { + model = m.Where(fmt.Sprintf(`%s IS NOT NULL`, m.db.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([]*whereHolder, 0) + } + model.whereHolder = append(model.whereHolder, &whereHolder{ + operator: whereHolderOr, + where: where, + args: args, + }) + return model +} + +// WhereOrBetween builds `xxx BETWEEN x AND y` statement in `OR` conditions. +func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s BETWEEN ? AND ?`, m.db.QuoteWord(column)), min, max) +} + +// WhereOrLike builds `xxx LIKE x` statement in `OR` conditions. +func (m *Model) WhereOrLike(column string, like interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s LIKE ?`, m.db.QuoteWord(column)), like) +} + +// WhereOrIn builds `xxx IN (x)` statement in `OR` conditions. +func (m *Model) WhereOrIn(column string, in interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s IN (?)`, m.db.QuoteWord(column)), in) +} + +// WhereOrNull builds `xxx IS NULL` statement in `OR` conditions. +func (m *Model) WhereOrNull(columns ...string) *Model { + model := m + for _, column := range columns { + model = m.WhereOr(fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(column))) + } + return model +} + +// WhereOrNotBetween builds `xxx NOT BETWEEN x AND y` statement in `OR` conditions. +func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s NOT BETWEEN ? AND ?`, m.db.QuoteWord(column)), min, max) +} + +// WhereOrNotLike builds `xxx NOT LIKE x` statement in `OR` conditions. +func (m *Model) WhereOrNotLike(column string, like interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s NOT LIKE ?`, m.db.QuoteWord(column)), like) +} + +// WhereOrNotIn builds `xxx NOT IN (x)` statement. +func (m *Model) WhereOrNotIn(column string, in interface{}) *Model { + return m.WhereOr(fmt.Sprintf(`%s NOT IN (?)`, m.db.QuoteWord(column)), in) +} + +// WhereOrNotNull builds `xxx IS NOT NULL` statement in `OR` conditions. +func (m *Model) WhereOrNotNull(columns ...string) *Model { + model := m + for _, column := range columns { + model = m.WhereOr(fmt.Sprintf(`%s IS NOT NULL`, m.db.QuoteWord(column))) + } + return model +} + +// Group sets the "GROUP BY" statement for the model. +func (m *Model) Group(groupBy string) *Model { + model := m.getModel() + model.groupBy = m.db.QuoteString(groupBy) + return model +} + // And adds "AND" condition to the where statement. +// Deprecated, use Where instead. func (m *Model) And(where interface{}, args ...interface{}) *Model { model := m.getModel() if model.whereHolder == nil { @@ -73,24 +192,9 @@ func (m *Model) And(where interface{}, args ...interface{}) *Model { } // Or adds "OR" condition to the where statement. +// Deprecated, use WhereOr instead. func (m *Model) Or(where interface{}, args ...interface{}) *Model { - model := m.getModel() - if model.whereHolder == nil { - model.whereHolder = make([]*whereHolder, 0) - } - model.whereHolder = append(model.whereHolder, &whereHolder{ - operator: whereHolderOr, - where: where, - args: args, - }) - return model -} - -// Group sets the "GROUP BY" statement for the model. -func (m *Model) Group(groupBy string) *Model { - model := m.getModel() - model.groupBy = m.db.QuoteString(groupBy) - return model + return m.WhereOr(where, args...) } // GroupBy is alias of Model.Group. @@ -102,11 +206,41 @@ func (m *Model) GroupBy(groupBy string) *Model { // Order sets the "ORDER BY" statement for the model. func (m *Model) Order(orderBy ...string) *Model { + if len(orderBy) == 0 { + return m + } model := m.getModel() model.orderBy = m.db.QuoteString(strings.Join(orderBy, " ")) return model } +// OrderAsc sets the "ORDER BY xxx ASC" statement for the model. +func (m *Model) OrderAsc(column string) *Model { + if len(column) == 0 { + return m + } + model := m.getModel() + model.orderBy = m.db.QuoteWord(column) + " ASC" + return model +} + +// OrderDesc sets the "ORDER BY xxx DESC" statement for the model. +func (m *Model) OrderDesc(column string) *Model { + if len(column) == 0 { + return m + } + model := m.getModel() + model.orderBy = m.db.QuoteWord(column) + " DESC" + return model +} + +// OrderRandom sets the "ORDER BY RANDOM()" statement for the model. +func (m *Model) OrderRandom(orderBy ...string) *Model { + model := m.getModel() + model.orderBy = "RAND()" + return model +} + // OrderBy is alias of Model.Order. // See Model.Order. // Deprecated, use Order instead. @@ -138,6 +272,13 @@ func (m *Model) Offset(offset int) *Model { 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. diff --git a/database/gdb/gdb_model_fields.go b/database/gdb/gdb_model_fields.go index c10e00461..4d278358d 100644 --- a/database/gdb/gdb_model_fields.go +++ b/database/gdb/gdb_model_fields.go @@ -14,17 +14,6 @@ import ( "github.com/gogf/gf/util/gutil" ) -// Filter marks filtering the fields which does not exist in the fields of the operated table. -// Note that this function supports only single table operations. -func (m *Model) Filter() *Model { - if gstr.Contains(m.tables, " ") { - panic("function Filter supports only single table operations") - } - model := m.getModel() - model.filter = true - return model -} - // Fields sets the operation fields of the model, multiple fields joined using char ','. // The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct. func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model { @@ -81,13 +70,25 @@ func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model { return m } +// Filter marks filtering the fields which does not exist in the fields of the operated table. +// Note that this function supports only single table operations. +func (m *Model) Filter() *Model { + if gstr.Contains(m.tables, " ") { + panic("function Filter supports only single table operations") + } + model := m.getModel() + model.filter = true + return model +} + +// FieldsStr retrieves and returns all fields from the table, joined with char ','. +// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsStr("u."). // Deprecated, use GetFieldsStr instead. -// This function name confuses the user that it was a chaining function. func (m *Model) FieldsStr(prefix ...string) string { return m.GetFieldsStr(prefix...) } -// FieldsStr retrieves and returns all fields from the table, joined with char ','. +// GetFieldsStr retrieves and returns all fields from the table, joined with char ','. // The optional parameter `prefix` specifies the prefix for each field, eg: FieldsStr("u."). func (m *Model) GetFieldsStr(prefix ...string) string { prefixStr := "" @@ -116,13 +117,16 @@ func (m *Model) GetFieldsStr(prefix ...string) string { return newFields } +// FieldsExStr retrieves and returns fields which are not in parameter `fields` from the table, +// joined with char ','. +// The parameter `fields` specifies the fields that are excluded. +// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u."). // Deprecated, use GetFieldsExStr instead. -// This function name confuses the user that it was a chaining function. func (m *Model) FieldsExStr(fields string, prefix ...string) string { return m.GetFieldsExStr(fields, prefix...) } -// FieldsExStr retrieves and returns fields which are not in parameter `fields` from the table, +// GetFieldsExStr retrieves and returns fields which are not in parameter `fields` from the table, // joined with char ','. // The parameter `fields` specifies the fields that are excluded. // The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u."). diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index b0959d304..d67978b72 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -109,6 +109,18 @@ func (m *Model) Insert(data ...interface{}) (result sql.Result, err error) { return m.doInsertWithOption(insertOptionDefault) } +// InsertAndGetId performs action Insert and returns the last insert id that automatically generated. +func (m *Model) InsertAndGetId(data ...interface{}) (lastInsertId int64, err error) { + if len(data) > 0 { + return m.Data(data...).InsertAndGetId() + } + result, err := m.doInsertWithOption(insertOptionDefault) + if err != nil { + return 0, err + } + return result.LastInsertId() +} + // InsertIgnore does "INSERT IGNORE INTO ..." statement for the model. // The optional parameter `data` is the same as the parameter of Model.Data function, // see Model.Data. diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 962592b33..31fd0007d 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -19,7 +19,7 @@ import ( // Select is alias of Model.All. // See Model.All. -// Deprecated. +// Deprecated, use All instead. func (m *Model) Select(where ...interface{}) (Result, error) { return m.All(where...) } @@ -50,7 +50,8 @@ func (m *Model) doGetAll(limit1 bool, where ...interface{}) (Result, error) { // DISTINCT t.user_id uid return m.doGetAllBySql( fmt.Sprintf( - "SELECT %s FROM %s%s", + "SELECT %s%s FROM %s%s", + m.distinct, m.getFieldsFiltered(), m.tables, conditionWhere+conditionExtra, @@ -182,7 +183,7 @@ func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) { } // Array queries and returns data values as slice from database. -// Note that if there're multiple columns in the result, it returns just one column values randomly. +// Note that if there are multiple columns in the result, it returns just one column values randomly. // // If the optional parameter `fieldsAndWhere` is given, the fieldsAndWhere[0] is the selected fields // and fieldsAndWhere[1:] is treated as where condition fields. @@ -334,7 +335,7 @@ func (m *Model) Count(where ...interface{}) (int, error) { if m.fields != "" && m.fields != "*" { // DO NOT quote the m.fields here, in case of fields like: // DISTINCT t.user_id uid - countFields = fmt.Sprintf(`COUNT(%s)`, m.fields) + countFields = fmt.Sprintf(`COUNT(%s%s)`, m.distinct, m.fields) } conditionWhere, conditionExtra, conditionArgs := m.formatCondition(false, true) s := fmt.Sprintf("SELECT %s FROM %s%s", countFields, m.tables, conditionWhere+conditionExtra) @@ -353,6 +354,62 @@ func (m *Model) Count(where ...interface{}) (int, error) { return 0, nil } +// CountColumn does "SELECT COUNT(x) FROM ..." statement for the model. +func (m *Model) CountColumn(column string) (int, error) { + if len(column) == 0 { + return 0, nil + } + return m.Fields(column).Count() +} + +// Min does "SELECT MIN(x) FROM ..." statement for the model. +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.QuoteWord(column))).Value() + if err != nil { + return 0, err + } + return value.Float64(), err +} + +// Max does "SELECT MAX(x) FROM ..." statement for the model. +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.QuoteWord(column))).Value() + if err != nil { + return 0, err + } + return value.Float64(), err +} + +// Avg does "SELECT AVG(x) FROM ..." statement for the model. +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.QuoteWord(column))).Value() + if err != nil { + return 0, err + } + return value.Float64(), err +} + +// Sum does "SELECT SUM(x) FROM ..." statement for the model. +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.QuoteWord(column))).Value() + if err != nil { + return 0, err + } + return value.Float64(), err +} + // FindOne retrieves and returns a single Record by Model.WherePri and Model.One. // Also see Model.WherePri and Model.One. func (m *Model) FindOne(where ...interface{}) (Record, error) { diff --git a/database/gdb/gdb_model_update.go b/database/gdb/gdb_model_update.go index b1f15ff62..ad65e723f 100644 --- a/database/gdb/gdb_model_update.go +++ b/database/gdb/gdb_model_update.go @@ -89,3 +89,19 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro m.mergeArguments(conditionArgs)..., ) } + +// Increment increments a column's value by a given amount. +func (m *Model) Increment(column string, amount float64) (sql.Result, error) { + return m.getModel().Data(column, &Counter{ + Field: column, + Value: amount, + }).Update() +} + +// Decrement decrements a column's value by a given amount. +func (m *Model) Decrement(column string, amount float64) (sql.Result, error) { + return m.getModel().Data(column, &Counter{ + Field: column, + Value: -amount, + }).Update() +} diff --git a/database/gdb/gdb_model_utility.go b/database/gdb/gdb_model_utility.go index 93890326b..944946bb6 100644 --- a/database/gdb/gdb_model_utility.go +++ b/database/gdb/gdb_model_utility.go @@ -18,16 +18,6 @@ import ( "time" ) -// getModel creates and returns a cloned model of current model if `safe` is true, or else it returns -// the current model. -func (m *Model) getModel() *Model { - if !m.safe { - return m - } else { - return m.Clone() - } -} - // TableFields retrieves and returns the fields information of specified table of current // schema. // @@ -47,6 +37,16 @@ func (m *Model) TableFields(table string, schema ...string) (fields map[string]* return m.db.TableFields(link, table, schema...) } +// getModel creates and returns a cloned model of current model if `safe` is true, or else it returns +// the current model. +func (m *Model) getModel() *Model { + if !m.safe { + return m + } else { + return m.Clone() + } +} + // mappingAndFilterToTableFields mappings and changes given field name to really table field name. // Eg: // ID -> id diff --git a/database/gdb/gdb_z_mysql_model_test.go b/database/gdb/gdb_z_mysql_model_test.go index 0eb1b454a..e74123571 100644 --- a/database/gdb/gdb_z_mysql_model_test.go +++ b/database/gdb/gdb_z_mysql_model_test.go @@ -2778,6 +2778,11 @@ func Test_Model_Distinct(t *testing.T) { t.AssertNil(err) t.Assert(len(all), 2) }) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Where("id > 1").Distinct().Count() + t.AssertNil(err) + t.Assert(count, 9) + }) } func Test_Model_Min_Max(t *testing.T) { @@ -3321,3 +3326,292 @@ func Test_Model_Fields_AutoFilterInJoinStatement(t *testing.T) { t.Assert(one["number"].String(), "n") }) } + +func Test_Model_WhereIn(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereIn("id", g.Slice{1, 2, 3, 4}).WhereIn("id", g.Slice{3, 4, 5}).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 2) + t.Assert(result[0]["id"], 3) + t.Assert(result[1]["id"], 4) + }) +} + +func Test_Model_WhereNotIn(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereNotIn("id", g.Slice{1, 2, 3, 4}).WhereNotIn("id", g.Slice{3, 4, 5}).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 5) + t.Assert(result[0]["id"], 6) + t.Assert(result[1]["id"], 7) + }) +} + +func Test_Model_WhereOrIn(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrIn("id", g.Slice{1, 2, 3, 4}).WhereOrIn("id", g.Slice{3, 4, 5}).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 5) + t.Assert(result[0]["id"], 1) + t.Assert(result[4]["id"], 5) + }) +} + +func Test_Model_WhereOrNotIn(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrNotIn("id", g.Slice{1, 2, 3, 4}).WhereOrNotIn("id", g.Slice{3, 4, 5}).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 8) + t.Assert(result[0]["id"], 1) + t.Assert(result[4]["id"], 7) + }) +} + +func Test_Model_WhereBetween(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereBetween("id", 1, 4).WhereBetween("id", 3, 5).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 2) + t.Assert(result[0]["id"], 3) + t.Assert(result[1]["id"], 4) + }) +} + +func Test_Model_WhereNotBetween(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereNotBetween("id", 2, 8).WhereNotBetween("id", 3, 100).OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 1) + t.Assert(result[0]["id"], 1) + }) +} + +func Test_Model_WhereOrBetween(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrBetween("id", 1, 4).WhereOrBetween("id", 3, 5).OrderDesc("id").All() + t.AssertNil(err) + t.Assert(len(result), 5) + t.Assert(result[0]["id"], 5) + t.Assert(result[4]["id"], 1) + }) +} + +func Test_Model_WhereOrNotBetween(t *testing.T) { + table := createInitTable() + defer dropTable(table) + //db.SetDebug(true) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrNotBetween("id", 1, 4).WhereOrNotBetween("id", 3, 5).OrderDesc("id").All() + t.AssertNil(err) + t.Assert(len(result), 8) + t.Assert(result[0]["id"], 10) + t.Assert(result[4]["id"], 6) + }) +} + +func Test_Model_WhereLike(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereLike("nickname", "name%").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["id"], 1) + t.Assert(result[TableSize-1]["id"], TableSize) + }) +} + +func Test_Model_WhereNotLike(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereNotLike("nickname", "name%").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 0) + }) +} + +func Test_Model_WhereOrLike(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrLike("nickname", "namexxx%").WhereOrLike("nickname", "name%").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["id"], 1) + t.Assert(result[TableSize-1]["id"], TableSize) + }) +} + +func Test_Model_WhereOrNotLike(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrNotLike("nickname", "namexxx%").WhereOrNotLike("nickname", "name%").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["id"], 1) + t.Assert(result[TableSize-1]["id"], TableSize) + }) +} + +func Test_Model_WhereNull(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereNull("nickname").WhereNull("passport").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), 0) + }) +} + +func Test_Model_WhereNotNull(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereNotNull("nickname").WhereNotNull("passport").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["id"], 1) + t.Assert(result[TableSize-1]["id"], TableSize) + }) +} + +func Test_Model_WhereOrNull(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrNull("nickname").WhereOrNull("passport").OrderAsc("id").OrderRandom().All() + t.AssertNil(err) + t.Assert(len(result), 0) + }) +} + +func Test_Model_WhereOrNotNull(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereOrNotNull("nickname").WhereOrNotNull("passport").OrderAsc("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["id"], 1) + t.Assert(result[TableSize-1]["id"], TableSize) + }) +} + +func Test_Model_Min_Max_Avg_Sum(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Min("id") + t.AssertNil(err) + t.Assert(result, 1) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Max("id") + t.AssertNil(err) + t.Assert(result, TableSize) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Avg("id") + t.AssertNil(err) + t.Assert(result, 5.5) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Sum("id") + t.AssertNil(err) + t.Assert(result, 55) + }) +} + +func Test_Model_CountColumn(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).CountColumn("id") + t.AssertNil(err) + t.Assert(result, TableSize) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).CountColumn("id") + t.AssertNil(err) + t.Assert(result, 3) + }) +} + +func Test_Model_InsertAndGetId(t *testing.T) { + table := createTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + id, err := db.Model(table).Data(g.Map{ + "id": 1, + "passport": "user_1", + "password": "pass_1", + "nickname": "name_1", + }).InsertAndGetId() + t.AssertNil(err) + t.Assert(id, 1) + }) + gtest.C(t, func(t *gtest.T) { + id, err := db.Model(table).Data(g.Map{ + "passport": "user_2", + "password": "pass_2", + "nickname": "name_2", + }).InsertAndGetId() + t.AssertNil(err) + t.Assert(id, 2) + }) +} + +func Test_Model_Increment_Decrement(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Where("id", 1).Increment("id", 100) + t.AssertNil(err) + rows, _ := result.RowsAffected() + t.Assert(rows, 1) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Where("id", 101).Decrement("id", 10) + t.AssertNil(err) + rows, _ := result.RowsAffected() + t.Assert(rows, 1) + }) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Where("id", 91).Count() + t.AssertNil(err) + t.Assert(count, 1) + }) +}