diff --git a/contrib/drivers/mysql/mysql_z_unit_model_test.go b/contrib/drivers/mysql/mysql_z_unit_model_test.go index 9be10ff1313..d28f461c241 100644 --- a/contrib/drivers/mysql/mysql_z_unit_model_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_model_test.go @@ -2812,6 +2812,28 @@ func Test_Model_OnDuplicate(t *testing.T) { }) } +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} + func Test_Model_OnDuplicateEx(t *testing.T) { table := createInitTable() defer dropTable(table) diff --git a/contrib/drivers/pgsql/pgsql_format_upsert.go b/contrib/drivers/pgsql/pgsql_format_upsert.go index c4c8af91122..3734b406f2d 100644 --- a/contrib/drivers/pgsql/pgsql_format_upsert.go +++ b/contrib/drivers/pgsql/pgsql_format_upsert.go @@ -8,7 +8,6 @@ package pgsql import ( "fmt" - "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" @@ -40,6 +39,30 @@ func (d *Driver) FormatUpsert(columns []string, list gdb.List, option gdb.DoInse d.Core.QuoteWord(k), v, ) + case gdb.Counter: + operator, columnVal := "+", v.(gdb.Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(v.(gdb.Counter).Field), + operator, + gconv.String(columnVal), + ) + case *gdb.Counter: + operator, columnVal := "+", v.(*gdb.Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(v.(*gdb.Counter).Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=EXCLUDED.%s", diff --git a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go index d7748f07f17..3a51ba264dc 100644 --- a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go +++ b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go @@ -521,6 +521,28 @@ func Test_Model_OnDuplicate(t *testing.T) { }) } +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} + func Test_Model_OnDuplicateEx(t *testing.T) { table := createInitTable() defer dropTable(table) diff --git a/contrib/drivers/sqlite/sqlite_format_upsert.go b/contrib/drivers/sqlite/sqlite_format_upsert.go index 5821144a13e..dd9a246e0be 100644 --- a/contrib/drivers/sqlite/sqlite_format_upsert.go +++ b/contrib/drivers/sqlite/sqlite_format_upsert.go @@ -40,6 +40,31 @@ func (d *Driver) FormatUpsert(columns []string, list gdb.List, option gdb.DoInse d.Core.QuoteWord(k), v, ) + + case gdb.Counter: + operator, columnVal := "+", v.(gdb.Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(v.(gdb.Counter).Field), + operator, + gconv.String(columnVal), + ) + case *gdb.Counter: + operator, columnVal := "+", v.(*gdb.Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(v.(*gdb.Counter).Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=EXCLUDED.%s", diff --git a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go index 19e97bfa51a..03e8465c7fc 100644 --- a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go +++ b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go @@ -4324,3 +4324,25 @@ func Test_OrderRandom(t *testing.T) { t.Assert(len(result), TableSize) }) } + +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index 045d11c65af..71b4bb0d74b 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -388,6 +388,30 @@ func (c *Core) FormatUpsert(columns []string, list List, option DoInsertOption) c.QuoteWord(k), v, ) + case Counter: + operator, columnVal := "+", v.(Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=%s%s%s", + c.QuoteWord(k), + c.QuoteWord(v.(Counter).Field), + operator, + gconv.String(columnVal), + ) + case *Counter: + operator, columnVal := "+", v.(*Counter).Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=%s%s%s", + c.QuoteWord(k), + c.QuoteWord(v.(*Counter).Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=VALUES(%s)",