File tree Expand file tree Collapse file tree
tests/system/Database/Builder
user_guide_src/source/database Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -58,6 +58,24 @@ protected function _fromTables(): string
5858 return implode (', ' , $ this ->QBFrom );
5959 }
6060
61+ /**
62+ * Compile the SELECT lock clause.
63+ */
64+ protected function compileLockForUpdate (): string
65+ {
66+ if (! $ this ->QBLockForUpdate ) {
67+ return '' ;
68+ }
69+
70+ foreach ($ this ->QBFrom as $ value ) {
71+ if (str_starts_with ($ value , '(SELECT ' )) {
72+ throw new DatabaseException ('MySQLi does not support lockForUpdate() with fromSubquery(). ' );
73+ }
74+ }
75+
76+ return parent ::compileLockForUpdate ();
77+ }
78+
6179 /**
6280 * Generates a platform-specific batch update string from the supplied data
6381 */
Original file line number Diff line number Diff line change 1616use CodeIgniter \Database \BaseBuilder ;
1717use CodeIgniter \Database \Exceptions \DatabaseException ;
1818use CodeIgniter \Database \Exceptions \DataException ;
19+ use CodeIgniter \Database \MySQLi \Builder as MySQLiBuilder ;
1920use CodeIgniter \Database \OCI8 \Builder as OCI8Builder ;
2021use CodeIgniter \Database \Postgre \Builder as PostgreBuilder ;
2122use CodeIgniter \Database \RawSql ;
@@ -440,6 +441,21 @@ public function testLockForUpdateThrowsExceptionWithSQLSRVUnion(): void
440441 $ builder ->union (new SQLSRVBuilder ('jobs ' , $ this ->db ))->lockForUpdate ()->getCompiledSelect ();
441442 }
442443
444+ public function testLockForUpdateThrowsExceptionOnMySQLiSubquery (): void
445+ {
446+ $ this ->db = new MockConnection (['DBDriver ' => 'MySQLi ' ]);
447+
448+ $ subquery = new MySQLiBuilder ('users ' , $ this ->db );
449+ $ builder = new MySQLiBuilder ('jobs ' , $ this ->db );
450+
451+ $ builder ->fromSubquery ($ subquery , 'users_1 ' );
452+
453+ $ this ->expectException (DatabaseException::class);
454+ $ this ->expectExceptionMessage ('MySQLi does not support lockForUpdate() with fromSubquery(). ' );
455+
456+ $ builder ->lockForUpdate ()->getCompiledSelect ();
457+ }
458+
443459 public function testLockForUpdateWithOCI8 (): void
444460 {
445461 $ builder = new OCI8Builder ('users ' , $ this ->db );
Original file line number Diff line number Diff line change @@ -783,6 +783,10 @@ Some databases restrict which query shapes can be used with row locking. When
783783CodeIgniter can detect an unsupported combination, it throws a
784784``DatabaseException ``. See the following warnings for driver-specific behavior.
785785
786+ .. warning :: MySQLi does not support ``lockForUpdate()`` with ``fromSubquery()``
787+ because an outer locking read on a derived table does not lock the underlying
788+ rows as users may expect.
789+
786790.. warning :: Postgre does not support ``lockForUpdate()`` with ``distinct()``,
787791 ``groupBy() ``, ``having() ``, or aggregate helper selections such as
788792 ``selectCount() ``.
You can’t perform that action at this time.
0 commit comments