diff --git a/contracts/database/db/db.go b/contracts/database/db/db.go index 82930f5b3..d29759989 100644 --- a/contracts/database/db/db.go +++ b/contracts/database/db/db.go @@ -50,7 +50,7 @@ type Query interface { // OrderBy(column string) Query // orderByDesc // OrderByRaw(query string, args ...any) Query - // OrWhere(query any, args ...any) Query + OrWhere(query any, args ...any) Query // OrWhereLike() // OrWhereNotLike // Pluck(column string, dest any) error diff --git a/database/db/conditions.go b/database/db/conditions.go index 8dc6d3e37..9931e05e8 100644 --- a/database/db/conditions.go +++ b/database/db/conditions.go @@ -8,5 +8,5 @@ type Conditions struct { type Where struct { query any args []any - // or bool + or bool } diff --git a/database/db/query.go b/database/db/query.go index 63dbb6284..ad19822d9 100644 --- a/database/db/query.go +++ b/database/db/query.go @@ -3,6 +3,7 @@ package db import ( "context" databasesql "database/sql" + "fmt" "reflect" "sort" @@ -147,6 +148,18 @@ func (r *Query) Insert(data any) (*db.Result, error) { }, nil } +func (r *Query) OrWhere(query any, args ...any) db.Query { + q := NewQuery(r.ctx, r.driver, r.builder, r.logger, r.conditions.table) + q.conditions = r.conditions + q.conditions.where = append(r.conditions.where, Where{ + query: query, + args: args, + or: true, + }) + + return q +} + func (r *Query) Update(data any) (*db.Result, error) { mapData, err := convertToMap(data) if err != nil { @@ -198,23 +211,12 @@ func (r *Query) buildDelete() (sql string, args []any, err error) { builder = builder.PlaceholderFormat(placeholderFormat) } - for _, where := range r.conditions.where { - query, ok := where.query.(string) - if ok { - if !str.Of(query).Trim().Contains(" ", "?") { - if len(where.args) > 1 { - builder = builder.Where(sq.Eq{query: where.args}) - } else if len(where.args) == 1 { - builder = builder.Where(sq.Eq{query: where.args[0]}) - } - continue - } - } - - builder = builder.Where(where.query, where.args...) + sqlizer, err := r.buildWheres(r.conditions.where) + if err != nil { + return "", nil, err } - return builder.ToSql() + return builder.Where(sqlizer).ToSql() } func (r *Query) buildInsert(data []map[string]any) (sql string, args []any, err error) { @@ -257,24 +259,12 @@ func (r *Query) buildSelect() (sql string, args []any, err error) { } builder = builder.From(r.conditions.table) - - for _, where := range r.conditions.where { - query, ok := where.query.(string) - if ok { - if !str.Of(query).Trim().Contains(" ", "?") { - if len(where.args) > 1 { - builder = builder.Where(sq.Eq{query: where.args}) - } else if len(where.args) == 1 { - builder = builder.Where(sq.Eq{query: where.args[0]}) - } - continue - } - } - - builder = builder.Where(where.query, where.args...) + sqlizer, err := r.buildWheres(r.conditions.where) + if err != nil { + return "", nil, err } - return builder.ToSql() + return builder.Where(sqlizer).ToSql() } func (r *Query) buildUpdate(data map[string]any) (sql string, args []any, err error) { @@ -287,25 +277,72 @@ func (r *Query) buildUpdate(data map[string]any) (sql string, args []any, err er builder = builder.PlaceholderFormat(placeholderFormat) } - for _, where := range r.conditions.where { - query, ok := where.query.(string) - if ok { - if !str.Of(query).Trim().Contains(" ", "?") { - if len(where.args) > 1 { - builder = builder.Where(sq.Eq{query: where.args}) - } else if len(where.args) == 1 { - builder = builder.Where(sq.Eq{query: where.args[0]}) - } - continue + sqlizer, err := r.buildWheres(r.conditions.where) + if err != nil { + return "", nil, err + } + + return builder.Where(sqlizer).SetMap(data).ToSql() +} + +func (r *Query) buildWhere(where Where) (any, []any) { + query, ok := where.query.(string) + if ok { + if !str.Of(query).Trim().Contains(" ", "?") { + if len(where.args) > 1 { + return sq.Eq{query: where.args}, nil + } else if len(where.args) == 1 { + return sq.Eq{query: where.args[0]}, nil } } + } + + return where.query, where.args +} - builder = builder.Where(where.query, where.args...) +func (r *Query) buildWheres(wheres []Where) (sq.Sqlizer, error) { + if len(wheres) == 0 { + return nil, nil } - builder = builder.SetMap(data) + var sqlizers []sq.Sqlizer + for _, where := range wheres { + query, args := r.buildWhere(where) - return builder.ToSql() + sqlizer, err := r.toSqlizer(query, args) + if err != nil { + return nil, err + } + + if where.or && len(sqlizers) > 0 { + // If it's an OR condition and we have previous conditions, + // wrap the previous conditions in an AND and create an OR condition + if len(sqlizers) == 1 { + sqlizers = []sq.Sqlizer{ + sq.Or{ + sqlizers[0], + sqlizer, + }, + } + } else { + sqlizers = []sq.Sqlizer{ + sq.Or{ + sq.And(sqlizers), + sqlizer, + }, + } + } + } else { + // For regular WHERE conditions or the first condition + sqlizers = append(sqlizers, sqlizer) + } + } + + if len(sqlizers) == 1 { + return sqlizers[0], nil + } + + return sq.And(sqlizers), nil } func (r *Query) placeholderFormat() database.PlaceholderFormat { @@ -319,3 +356,16 @@ func (r *Query) placeholderFormat() database.PlaceholderFormat { func (r *Query) trace(sql string, args []any, rowsAffected int64, err error) { r.logger.Trace(r.ctx, carbon.Now(), r.driver.Explain(sql, args...), rowsAffected, err) } + +func (r *Query) toSqlizer(query any, args []any) (sq.Sqlizer, error) { + switch q := query.(type) { + case map[string]any: + return sq.Eq(q), nil + case string: + return sq.Expr(q, args...), nil + case sq.Sqlizer: + return q, nil + default: + return nil, errors.DatabaseUnsupportedType.Args(fmt.Sprintf("%T", query), "string-keyed map or string or squirrel.Sqlizer") + } +} diff --git a/database/db/query_test.go b/database/db/query_test.go index 35da87414..ab28394ad 100644 --- a/database/db/query_test.go +++ b/database/db/query_test.go @@ -56,9 +56,9 @@ func (s *QueryTestSuite) TestDelete() { mockResult.On("RowsAffected").Return(int64(1), nil) s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return(mockResult, nil).Once() - s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return("DELETE FROM users WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE name = \"John\" AND id = 1", int64(1), nil).Return().Once() + s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return(mockResult, nil).Once() + s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return("DELETE FROM users WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE (name = \"John\" AND id = 1)", int64(1), nil).Return().Once() result, err := s.query.Where("name", "John").Where("id", 1).Delete() s.Nil(err) @@ -69,9 +69,9 @@ func (s *QueryTestSuite) TestDelete() { s.Run("failed to exec", func() { s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return(nil, assert.AnError).Once() - s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return("DELETE FROM users WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE name = \"John\" AND id = 1", int64(-1), assert.AnError).Return().Once() + s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return(nil, assert.AnError).Once() + s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return("DELETE FROM users WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE (name = \"John\" AND id = 1)", int64(-1), assert.AnError).Return().Once() _, err := s.query.Where("name", "John").Where("id", 1).Delete() s.Equal(assert.AnError, err) @@ -82,9 +82,9 @@ func (s *QueryTestSuite) TestDelete() { mockResult.On("RowsAffected").Return(int64(0), assert.AnError).Once() s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return(mockResult, nil).Once() - s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE name = ? AND id = ?", "John", 1).Return("DELETE FROM users WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE name = \"John\" AND id = 1", int64(-1), assert.AnError).Return().Once() + s.mockBuilder.EXPECT().Exec("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return(mockResult, nil).Once() + s.mockDriver.EXPECT().Explain("DELETE FROM users WHERE (name = ? AND id = ?)", "John", 1).Return("DELETE FROM users WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "DELETE FROM users WHERE (name = \"John\" AND id = 1)", int64(-1), assert.AnError).Return().Once() _, err := s.query.Where("name", "John").Where("id", 1).Delete() s.Equal(assert.AnError, err) @@ -292,9 +292,9 @@ func (s *QueryTestSuite) TestUpdate() { mockResult.On("RowsAffected").Return(int64(1), nil) s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return(mockResult, nil).Once() - s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1", int64(1), nil).Return().Once() + s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return(mockResult, nil).Once() + s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)", int64(1), nil).Return().Once() result, err := s.query.Where("name", "John").Where("id", 1).Update(user) s.Nil(err) @@ -314,9 +314,9 @@ func (s *QueryTestSuite) TestUpdate() { mockResult.On("RowsAffected").Return(int64(1), nil) s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("UPDATE users SET age = ?, name = ?, phone = ? WHERE name = ? AND id = ?", 25, "John", "1234567890", "John", 1).Return(mockResult, nil).Once() - s.mockDriver.EXPECT().Explain("UPDATE users SET age = ?, name = ?, phone = ? WHERE name = ? AND id = ?", 25, "John", "1234567890", "John", 1).Return("UPDATE users SET age = 25, name = \"John\", phone = \"1234567890\" WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET age = 25, name = \"John\", phone = \"1234567890\" WHERE name = \"John\" AND id = 1", int64(1), nil).Return().Once() + s.mockBuilder.EXPECT().Exec("UPDATE users SET age = ?, name = ?, phone = ? WHERE (name = ? AND id = ?)", 25, "John", "1234567890", "John", 1).Return(mockResult, nil).Once() + s.mockDriver.EXPECT().Explain("UPDATE users SET age = ?, name = ?, phone = ? WHERE (name = ? AND id = ?)", 25, "John", "1234567890", "John", 1).Return("UPDATE users SET age = 25, name = \"John\", phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET age = 25, name = \"John\", phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)", int64(1), nil).Return().Once() result, err := s.query.Where("name", "John").Where("id", 1).Update(user) s.Nil(err) @@ -333,9 +333,9 @@ func (s *QueryTestSuite) TestUpdate() { } s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return(nil, assert.AnError).Once() - s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1", int64(-1), assert.AnError).Return().Once() + s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return(nil, assert.AnError).Once() + s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)", int64(-1), assert.AnError).Return().Once() result, err := s.query.Where("name", "John").Where("id", 1).Update(user) s.Nil(result) @@ -353,9 +353,9 @@ func (s *QueryTestSuite) TestUpdate() { mockResult.On("RowsAffected").Return(int64(0), assert.AnError).Once() s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return(mockResult, nil).Once() - s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE name = ? AND id = ?", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1").Once() - s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE name = \"John\" AND id = 1", int64(-1), assert.AnError).Return().Once() + s.mockBuilder.EXPECT().Exec("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return(mockResult, nil).Once() + s.mockDriver.EXPECT().Explain("UPDATE users SET phone = ? WHERE (name = ? AND id = ?)", "1234567890", "John", 1).Return("UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, s.now, "UPDATE users SET phone = \"1234567890\" WHERE (name = \"John\" AND id = 1)", int64(-1), assert.AnError).Return().Once() result, err := s.query.Where("name", "John").Where("id", 1).Update(user) s.Nil(result) @@ -367,19 +367,19 @@ func (s *QueryTestSuite) TestWhere() { now := carbon.Now() carbon.SetTestNow(now) - s.Run("simple where condition", func() { + s.Run("simple condition", func() { var user TestUser s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() - s.mockBuilder.EXPECT().Get(&user, "SELECT * FROM users WHERE name = ?", "John").Return(nil).Once() - s.mockDriver.EXPECT().Explain("SELECT * FROM users WHERE name = ?", "John").Return("SELECT * FROM users WHERE name = \"John\"").Once() - s.mockLogger.EXPECT().Trace(s.ctx, now, "SELECT * FROM users WHERE name = \"John\"", int64(1), nil).Return().Once() + s.mockBuilder.EXPECT().Get(&user, "SELECT * FROM users WHERE (name = ? AND age = ?)", "John", 25).Return(nil).Once() + s.mockDriver.EXPECT().Explain("SELECT * FROM users WHERE (name = ? AND age = ?)", "John", 25).Return("SELECT * FROM users WHERE (name = \"John\" AND age = 25)").Once() + s.mockLogger.EXPECT().Trace(s.ctx, now, "SELECT * FROM users WHERE (name = \"John\" AND age = 25)", int64(1), nil).Return().Once() - err := s.query.Where("name", "John").First(&user) + err := s.query.Where("name", "John").Where("age", 25).First(&user) s.Nil(err) }) - s.Run("where with multiple arguments", func() { + s.Run("multiple arguments", func() { var users []TestUser s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() @@ -391,7 +391,7 @@ func (s *QueryTestSuite) TestWhere() { s.Nil(err) }) - s.Run("where with raw query", func() { + s.Run("raw query", func() { var users []TestUser s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() @@ -402,6 +402,37 @@ func (s *QueryTestSuite) TestWhere() { err := s.query.Where("age > ?", 18).Get(&users) s.Nil(err) }) + + // s.Run("nested condition", func() { + // var users []TestUser + + // s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() + // s.mockBuilder.EXPECT().Select(&users, "SELECT * FROM users WHERE age IN (?,?) AND name = ?", 25, 30, "John").Return(nil).Once() + // s.mockDriver.EXPECT().Explain("SELECT * FROM users WHERE age IN (?,?) AND name = ?", 25, 30, "John").Return("SELECT * FROM users WHERE age IN (25,30) AND name = \"John\"").Once() + // s.mockLogger.EXPECT().Trace(s.ctx, s.now, "SELECT * FROM users WHERE age IN (25,30) AND name = \"John\"", int64(0), nil).Return().Once() + + // err := s.query.Where(func(query db.Query) { + // query.Where("age", []int{25, 30}).Where("name", "John") + // }).Get(&users) + // s.Nil(err) + // }) +} + +func (s *QueryTestSuite) TestOrWhere() { + now := carbon.Now() + carbon.SetTestNow(now) + + s.Run("simple condition", func() { + var user TestUser + + s.mockDriver.EXPECT().Config().Return(database.Config{}).Once() + s.mockBuilder.EXPECT().Get(&user, "SELECT * FROM users WHERE (((name = ? AND age = ?) OR age = ?) OR name = ?)", "John", 25, 30, "Jane").Return(nil).Once() + s.mockDriver.EXPECT().Explain("SELECT * FROM users WHERE (((name = ? AND age = ?) OR age = ?) OR name = ?)", "John", 25, 30, "Jane").Return("SELECT * FROM users WHERE (((name = \"John\" AND age = 25) OR age = 30) OR name = \"Jane\")").Once() + s.mockLogger.EXPECT().Trace(s.ctx, now, "SELECT * FROM users WHERE (((name = \"John\" AND age = 25) OR age = 30) OR name = \"Jane\")", int64(1), nil).Return().Once() + + err := s.query.Where("name", "John").Where("age", 25).OrWhere("age", 30).OrWhere("name", "Jane").First(&user) + s.Nil(err) + }) } // MockResult implements sql.Result interface for testing diff --git a/event/console/listener_make_command.go b/event/console/listener_make_command.go index 870dc66f5..15e5bbec5 100644 --- a/event/console/listener_make_command.go +++ b/event/console/listener_make_command.go @@ -47,7 +47,8 @@ func (r *ListenerMakeCommand) Handle(ctx console.Context) error { } if err := file.PutContent(m.GetFilePath(), r.populateStub(r.getStub(), m.GetPackageName(), m.GetStructName())); err != nil { - return err + ctx.Error(err.Error()) + return nil } ctx.Success("Listener created successfully") diff --git a/mocks/database/db/Query.go b/mocks/database/db/Query.go index dc413a4df..8b52a9de6 100644 --- a/mocks/database/db/Query.go +++ b/mocks/database/db/Query.go @@ -227,6 +227,65 @@ func (_c *Query_Insert_Call) RunAndReturn(run func(interface{}) (*db.Result, err return _c } +// OrWhere provides a mock function with given fields: query, args +func (_m *Query) OrWhere(query interface{}, args ...interface{}) db.Query { + var _ca []interface{} + _ca = append(_ca, query) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for OrWhere") + } + + var r0 db.Query + if rf, ok := ret.Get(0).(func(interface{}, ...interface{}) db.Query); ok { + r0 = rf(query, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(db.Query) + } + } + + return r0 +} + +// Query_OrWhere_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OrWhere' +type Query_OrWhere_Call struct { + *mock.Call +} + +// OrWhere is a helper method to define mock.On call +// - query interface{} +// - args ...interface{} +func (_e *Query_Expecter) OrWhere(query interface{}, args ...interface{}) *Query_OrWhere_Call { + return &Query_OrWhere_Call{Call: _e.mock.On("OrWhere", + append([]interface{}{query}, args...)...)} +} + +func (_c *Query_OrWhere_Call) Run(run func(query interface{}, args ...interface{})) *Query_OrWhere_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(interface{}), variadicArgs...) + }) + return _c +} + +func (_c *Query_OrWhere_Call) Return(_a0 db.Query) *Query_OrWhere_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Query_OrWhere_Call) RunAndReturn(run func(interface{}, ...interface{}) db.Query) *Query_OrWhere_Call { + _c.Call.Return(run) + return _c +} + // Update provides a mock function with given fields: data func (_m *Query) Update(data interface{}) (*db.Result, error) { ret := _m.Called(data) diff --git a/tests/db_test.go b/tests/db_test.go index 5148ce5fb..1c7d29863 100644 --- a/tests/db_test.go +++ b/tests/db_test.go @@ -13,6 +13,7 @@ import ( type DBTestSuite struct { suite.Suite + now carbon.DateTime queries map[string]*TestQuery } @@ -24,6 +25,7 @@ func TestDBTestSuite(t *testing.T) { } func (s *DBTestSuite) SetupSuite() { + s.now = carbon.NewDateTime(carbon.FromDateTime(2025, 1, 2, 3, 4, 5)) s.queries = NewTestQueryBuilder().All("", false) for _, query := range s.queries { query.CreateTable(TestTableProducts) @@ -39,8 +41,6 @@ func (s *DBTestSuite) TearDownSuite() { } func (s *DBTestSuite) TestInsert_First_Get() { - now := carbon.NewDateTime(carbon.FromDateTime(2025, 1, 2, 3, 4, 5)) - for driver, query := range s.queries { s.Run(driver, func() { s.Run("single struct", func() { @@ -48,8 +48,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { Name: "single struct", Model: Model{ Timestamps: Timestamps{ - CreatedAt: now, - UpdatedAt: now, + CreatedAt: s.now, + UpdatedAt: s.now, }, }, }) @@ -62,8 +62,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { s.NoError(err) s.True(product.ID > 0) s.Equal("single struct", product.Name) - s.Equal(now, product.CreatedAt) - s.Equal(now, product.UpdatedAt) + s.Equal(s.now, product.CreatedAt) + s.Equal(s.now, product.UpdatedAt) s.False(product.DeletedAt.Valid) }) @@ -73,8 +73,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { Name: "multiple structs1", Model: Model{ Timestamps: Timestamps{ - CreatedAt: now, - UpdatedAt: now, + CreatedAt: s.now, + UpdatedAt: s.now, }, }, }, @@ -96,8 +96,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { s.Run("single map", func() { result, err := query.DB().Table("products").Insert(map[string]any{ "name": "single map", - "created_at": now, - "updated_at": &now, + "created_at": s.now, + "updated_at": &s.now, }) s.NoError(err) s.Equal(int64(1), result.RowsAffected) @@ -106,8 +106,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { err = query.DB().Table("products").Where("name", "single map").Where("deleted_at", nil).First(&product) s.NoError(err) s.Equal("single map", product.Name) - s.Equal(now, product.CreatedAt) - s.Equal(now, product.UpdatedAt) + s.Equal(s.now, product.CreatedAt) + s.Equal(s.now, product.UpdatedAt) s.False(product.DeletedAt.Valid) }) @@ -115,8 +115,8 @@ func (s *DBTestSuite) TestInsert_First_Get() { result, err := query.DB().Table("products").Insert([]map[string]any{ { "name": "multiple map1", - "created_at": now, - "updated_at": &now, + "created_at": s.now, + "updated_at": &s.now, }, { "name": "multiple map2", @@ -137,8 +137,6 @@ func (s *DBTestSuite) TestInsert_First_Get() { } func (s *DBTestSuite) TestUpdate_Delete() { - now := carbon.NewDateTime(carbon.FromDateTime(2025, 1, 2, 3, 4, 5)) - for driver, query := range s.queries { s.Run(driver, func() { result, err := query.DB().Table("products").Insert([]Product{ @@ -146,8 +144,8 @@ func (s *DBTestSuite) TestUpdate_Delete() { Name: "update structs1", Model: Model{ Timestamps: Timestamps{ - CreatedAt: now, - UpdatedAt: now, + CreatedAt: s.now, + UpdatedAt: s.now, }, }, }, @@ -206,13 +204,12 @@ func (s *DBTestSuite) TestUpdate_Delete() { func (s *DBTestSuite) TestWhere() { for driver, query := range s.queries { s.Run(driver, func() { - now := carbon.NewDateTime(carbon.FromDateTime(2025, 1, 2, 3, 4, 5)) query.DB().Table("products").Insert(Product{ Name: "where model", Model: Model{ Timestamps: Timestamps{ - CreatedAt: now, - UpdatedAt: now, + CreatedAt: s.now, + UpdatedAt: s.now, }, }, }) @@ -242,6 +239,30 @@ func (s *DBTestSuite) TestWhere() { } } +func (s *DBTestSuite) TestOrWhere() { + for driver, query := range s.queries { + s.Run(driver, func() { + query.DB().Table("products").Insert([]Product{ + { + Name: "or where model", + }, + { + Name: "or where model1", + }, + }) + + s.Run("simple where condition", func() { + var products []Product + err := query.DB().Table("products").Where("name", "or where model").OrWhere("name", "or where model1").Get(&products) + s.NoError(err) + s.Equal(2, len(products)) + s.Equal("or where model", products[0].Name) + s.Equal("or where model1", products[1].Name) + }) + }) + } +} + func TestDB_Connection(t *testing.T) { t.Parallel() postgresTestQuery := NewTestQueryBuilder().Postgres("", false)