Skip to content

feat: add Query Builder lock wait modifiers#10349

Open
memleakd wants to merge 2 commits into
codeigniter4:4.8from
memleakd:feat/query-builder-lock-wait-modifiers
Open

feat: add Query Builder lock wait modifiers#10349
memleakd wants to merge 2 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>
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants