Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 'Duplicate entry' while Save() composite primary key model #6706

Closed
wants to merge 2 commits into from

Conversation

YianAndCode
Copy link

@YianAndCode YianAndCode commented Nov 23, 2023

  • Do only one thing
  • Non breaking API changes
  • Tested

What did this pull request do?

When there is a table with a composite primary key, if one of the primary key values is zero, updating and modifying through Save() will become INSERT, resulting in a Duplicate entry error.

I looked at the implementation of the Save() method and saw that the logic is that when the primary key is a zero value, it will directly return Create(), I feel that changing the judgment condition here to the primary key is a zero value and is an auto-increment primary key would be a little better; but I tried to modify it unsuccessfully. Finally, my modification plan was changed to:

If the primary key is a zero value, then use INSERT INTO ... ON DUPLICATE KEY UPDATE ... to update and modify.

User Case Description

Playground link: go-gorm/playground#664

Copy link
Member

@a631807682 a631807682 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that changing the judgment condition here to the primary key is a zero value and is an auto-increment primary key would be a little better; but I tried to modify it unsuccessfully

This seems to work but why did you modify it unsuccessfully?

@YianAndCode
Copy link
Author

I had tried to modify it:

diff --git a/finisher_api.go b/finisher_api.go
index f80aa6c..00f1eea 100644
--- a/finisher_api.go
+++ b/finisher_api.go
@@ -88,7 +88,7 @@ func (db *DB) Save(value interface{}) (tx *DB) {
 	case reflect.Struct:
 		if err := tx.Statement.Parse(value); err == nil && tx.Statement.Schema != nil {
 			for _, pf := range tx.Statement.Schema.PrimaryFields {
-				if _, isZero := pf.ValueOf(tx.Statement.Context, reflectValue); isZero {
+				if _, isZero := pf.ValueOf(tx.Statement.Context, reflectValue); isZero && pf.AutoIncrement {
 					return tx.callbacks.Create().Execute(tx)
 				}
 			}

It works in gorm-v1.23.4, but in latest version(commit hash 3207ad6, commited at 2023-11-15 GMT+8 21:32:56), this modification will cause the primary key with a zero-value to be ignored in the WHERE condition during Save(), such as the example:

UPDATE `union_pk_models` SET `data`='1700755966' WHERE `pk1` = 1
image

I wonder if in the latest version of the code, the zero-valued primary key is ignored when constructing the WHERE condition of the SQL statement.

So I make another modification plan, as you can see this pull request.

I sincerely hope for your help, thanks a lot!

@YianAndCode
Copy link
Author

BTW, I also encountered something that confused me:
I forked the repo and then ran the unit test without making any modifications, an error was reported, the error message was the same as the tests Action error of this PR.

@jinzhu
Copy link
Member

jinzhu commented Dec 4, 2023

I recommend directly using the Create or Update method in this scenario, as having a primary key with a zero value isn't quite appropriate

@jinzhu jinzhu closed this Dec 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants