-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add locking methods to the query builder #6105
Conversation
666d97c
to
259c1f9
Compare
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.
Thank you. Please have a look at the failing tests. As far as I can tell, some existing tests are failing due to unnecessary extra whitespaces. We should avoid those.
Furthermore, we definitely need functional tests that at least show me that this new functionality produces syntax that is understood by the database servers we support.
b422ef1
to
295a92e
Compare
Tkx for the CR. Im working on fixing those whitespaces issues, and will add some functional tests, hopefully sometime this week. |
0b6bfa3
to
4a0fb32
Compare
@derrabus Can you point me to a functional test like the ones you asked me to create, pls? |
Have a look at the |
src/Id/TableGenerator.php
Outdated
. ' WHERE sequence_name = ? ' | ||
. ($platform instanceof SQLServerPlatform ? '' : $platform->getWriteLockSQL()); |
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.
We should avoid this kind of instanceof
checks. Why are we changing this deprecated class anyway?
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.
We changed the SQLServerPlatform::getWriteLockSQL()
so that it actually spits out the right SQL, it was spitting out an empty string.
Thus, after changing it, here for MSSQL it was adding both the lock hints after the FROM
(correct for MSQL) and at the end (correct for all others).
So, the test was failing and we had to change it.
Since the class is deprecated anyway, I assumes it would be fine to hack it up. Otherwise we would have to make a deep refactoring to a deprecated class, so that we would use the query builder instead of directly SQL,
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.
Thus, after changing it, here for MSSQL it was adding both the lock hints after the
FROM
(correct for MSQL) and at the end (correct for all others).
But that sounds correct to me, doesn't it?
So, the test was failing and we had to change it.
Which test exactly?
We really cannot keep this, sorry. Not having platform switches all over the codebase is the reason why the platform classes exist.
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.
Thus, after changing it, here for MSSQL it was adding both the lock hints after the FROM (correct for MSQL) and at the end (correct for all others).
But that sounds correct to me, doesn't it?
No, it should only add the extra SQL (the locking bit) either just after the from
or at the end, and for MSSQL it was adding it in both locations.
So, the test was failing and we had to change it.
Which test exactly?
We really cannot keep this, sorry. Not having platform switches all over the codebase is the reason why the platform classes exist.
I don't remember what test was breaking anymore.
Now I replaced building the raw SQL (which was there already) for building the SQL with the query builder, using the locking method I added.
I left my latest changes in a fixup!
commit that should be squashed before merging.
src/Query/QueryLockParser.php
Outdated
use function rtrim; | ||
use function trim; | ||
|
||
final class QueryLockParser |
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.
Naming: This "parser" does not actually parse anything does 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.
Well, it translates from an array of strings (the locks "names") into the appropriate SQL.
I don't like the name either, but couldn't find anything better.
Any suggestion?
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 renamed it to QueryLockBuilder
@derrabus
|
4c6f913
to
c008640
Compare
@derrabus I rebased on 3.7, renamed Please let me know if there is something more to be done. |
This will allow us to create a query that will lock the rows returned until the end of the transaction. This mens we can update these rows with the guarantee that they have not been changed in the meantime by a competing process.
It is currently returning an empty string, but it can be implemented with 'WITH (UPDLOCK, ROWLOCK)'.
This will allow us to create a query that will not wait for a lock to be released on rows, and instead return a row set excluding the rows locked by another transaction.
ed9eda4
to
02edccb
Compare
@derrabus rebased on 3.7 and made the requested changes |
@derrabus added another fixup, hopefully now the tests are all green |
6d657ad
to
510cc44
Compare
510cc44
to
ef72694
Compare
@hgraca, thank you for the pull request. I slightly updated the test suite to actually run the new test against the platforms that support it and slightly modified the code. This helped me make sure that this feature is indeed worth consideration. I would like to take it from here and give the API design a bit more thinking. If you don't mind, I will close this pull request in favor of another one and add you as a co-author and reviewer. |
Perfect, tbh I was a bit stuck with it cozz I can't run the pipeline locally, and cant figure out what's failing in the CI. Tkx for picking this up. |
Closing in favor of #6191. |
Summary
Fix SQLServer getForUpdateSQL()
but it can be implemented with 'WITH (UPDLOCK, ROWLOCK)'.
Add lockForUpdate() to the query builder
returned until the end of the transaction. This mens we can
update these rows with the guarantee that they have not been
changed in the meantime by a competing process.
Add skipLocked() to the query builder
wait for a lock to be released on rows, and instead
return a row set excluding the rows locked by
another transaction.