Skip to content

feat: add Query Builder lock wait modifiers#10349

Merged
paulbalandan merged 3 commits into
codeigniter4:4.8from
memleakd:feat/query-builder-lock-wait-modifiers
Jul 7, 2026
Merged

feat: add Query Builder lock wait modifiers#10349
paulbalandan merged 3 commits into
codeigniter4:4.8from
memleakd:feat/query-builder-lock-wait-modifiers

Conversation

@memleakd

Copy link
Copy Markdown
Contributor

Description

This PR adds nowait() and skipLocked() methods to Query Builder for pessimistic SELECT locks.

They can be used together with lockForUpdate() or sharedLock() to control what should happen when selected rows cannot be locked immediately.

Example:

$db->transaction(static function ($db): void {
    $jobs = $db->table('jobs')
        ->where('status', 'pending')
        ->orderBy('id', 'ASC')
        ->limit(10)
        ->lockForUpdate()
        ->skipLocked()
        ->get()
        ->getResultArray();

    // Mark or update the claimed jobs before committing the transaction...
});

Unsupported combinations throw a DatabaseException, the same way existing pessimistic lock limitations are handled.

Supported combinations:

  • lockForUpdate()->nowait(): MySQLi, Postgre, OCI8, SQLSRV
  • lockForUpdate()->skipLocked(): MySQLi, Postgre, OCI8, SQLSRV
  • sharedLock()->nowait(): Postgre, SQLSRV
  • sharedLock()->skipLocked(): Postgre

SQLSRV uses table hints for this feature. For skipLocked(), it uses READCOMMITTEDLOCK and READPAST, with the documented SQL Server limitation that some locks may still be waited on.

Tests were added for generated SQL, unsupported combinations, reset behavior, and exists() / countAllResults() handling.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

Add nowait() and skipLocked() for pessimistic SELECT locks.

- Support driver-specific SQL generation for MySQLi, Postgre, OCI8, and SQLSRV.
- Reject unsupported lock/wait combinations explicitly.
- Preserve lock wait state across compiled selects, exists(), and countAllResults().
- Document driver support and SQLSRV READPAST behavior.
- Add focused Query Builder tests for generated SQL, reset behavior, and unsupported combinations.

Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@github-actions github-actions Bot added the 4.8 PRs that target the `4.8` branch. label Jun 29, 2026
Comment thread system/Database/SQLSRV/Builder.php Outdated
Comment thread system/Database/BaseBuilder.php
Comment thread user_guide_src/source/database/query_builder.rst Outdated
- Avoid incompatible SQLSRV table hints for lockForUpdate()->skipLocked()
- Add live SQLSRV coverage for skip locked execution
- Document pessimistic lock and wait modifier driver support
- Clarify that existence/count probes do not apply locking modifiers

Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I've suggested two small user guide details, but overall this looks good. Thanks!

Comment thread user_guide_src/source/database/query_builder.rst Outdated
Comment thread user_guide_src/source/database/query_builder.rst Outdated
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@paulbalandan paulbalandan merged commit 7111c24 into codeigniter4:4.8 Jul 7, 2026
57 checks passed
@paulbalandan

Copy link
Copy Markdown
Member

Thank you, @memleakd

@memleakd memleakd deleted the feat/query-builder-lock-wait-modifiers branch July 7, 2026 09:13
@memleakd

memleakd commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Thank you @michalsn @paulbalandan

@paulbalandan paulbalandan added the new feature PRs for new features label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.8 PRs that target the `4.8` branch. new feature PRs for new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants