-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
[10.x] Fix createOrFirst
on transactions
#48144
[10.x] Fix createOrFirst
on transactions
#48144
Conversation
…action savepoint if needed
* @param \Closure(): TModelValue $scope | ||
* @return TModelValue | ||
*/ | ||
public function withSavepointIfNeeded(Closure $scope): mixed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about adding this public method. I thought about just wrapping the insert part in a DB::transaction(fn)
, but not sure what y'all would think of that. I initially had it as protected
, but I needed the same logic in the relationship part of the feature.
Let me know what y'all think. Open to suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For MySQL/SQLServer/SQLite, this is not necessary; Postgres just needs it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I figured it wouldn't be a problem to wrap in savepoint transactions for the other drivers as well. It doesn't seem to hurt.
@@ -580,7 +580,9 @@ public function firstOrCreate(array $attributes = [], array $values = []) | |||
public function createOrFirst(array $attributes = [], array $values = []) | |||
{ | |||
try { | |||
return $this->create(array_merge($attributes, $values)); | |||
return $this->withSavepointIfNeeded(function () use ($attributes, $values) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really liked how it read before: createOrFirst
was essentially calling create()
then first()
, now it has more noise. I thought about pushing the savepoint to the create()
method, which would keep this part as it was, but then it would be a bigger change.
Marking this as draft as there some failing tests need to be updated. |
@crynobone fixed the tests. Not sure why the SQLServer suite is failing, but seems to be failing on other PRs too, btw. Should I mark this PR as ready for review? |
We may need this: mpyw/laravel-unique-violation-detector@0049281 |
While this feature is highly beneficial, it seems to have a considerable impact. Personally, I feel it might have been better suited for Laravel 11. Even though it's already been incorporated into 10.20.0, might we consider reverting it and then reintroducing it as a target for version 11? |
@taylorotwell Can I have your opinion? |
Yeah, I think I had to comment out this line here to run the SQLServer tests (unrelated to the changes in |
@tonysm any ideas on what to do about the SQL Server tests? |
@taylorotwell I just tested it over here. If I comment out this line, the SQLServer tests pass locally. With that in, it looks like all of them are broken. I found this reference from Drupal, where they are using a Either way, it seems unrelated to the changes in the |
Looks like there are some flaky tests also unrelated to |
Added
withSavepointIfNeeded(fn)
method to the Eloquent query Builder that wraps the given scope in a transaction if there's a transaction going onChanged
create
orattach
parts of thecreateOrFirst
within a save point transaction using thewithSavePointIfNeeded
methodFixes #48143
Looks like we need to wrap the insert part of a the
createOrFirst
within a save point transaction for PostgreSQL, because otherwise the find part will fail.