diff --git a/UPGRADE.md b/UPGRADE.md
index 8fb7172b20a..decf8f4fa85 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -8,6 +8,11 @@ awareness about deprecated code.
# Upgrade to 4.0
+## BC BREAK: Removed lock-related `AbstractPlatform` methods
+
+The methods `AbstractPlatform::getReadLockSQL()`, `::getWriteLockSQL()` and `::getForUpdateSQL()` have been removed
+Use `QueryBuilder::forUpdate()` as a replacement for the latter.
+
## BC BREAK: BIGINT vales are cast to int if possible
`BigIntType` casts values retrieved from the database to int if they're inside
@@ -215,9 +220,11 @@ The following classes have been converted to enums:
1. `Doctrine\DBAL\ColumnCase`,
2. `Doctrine\DBAL\LockMode`,
3. `Doctrine\DBAL\ParameterType`,
-4. `Doctrine\DBAL\TransactionIsolationLevel`,
-5. `Doctrine\DBAL\Platforms\DateIntervalUnit`,
-6. `Doctrine\DBAL\Platforms\TrimMode`.
+4. `Doctrine\DBAL\ArrayParameterType`,
+5. `Doctrine\DBAL\TransactionIsolationLevel`,
+6. `Doctrine\DBAL\Platforms\DateIntervalUnit`,
+7. `Doctrine\DBAL\Platforms\TrimMode`.
+8. `Doctrine\DBAL\Query\ForUpdate\ConflictResolutionMode`
The corresponding class constants are now instances of their enum type.
diff --git a/psalm.xml.dist b/psalm.xml.dist
index c15dddaf5b7..183443139bf 100644
--- a/psalm.xml.dist
+++ b/psalm.xml.dist
@@ -53,10 +53,6 @@
-
-
-
-
diff --git a/src/Platforms/AbstractMySQLPlatform.php b/src/Platforms/AbstractMySQLPlatform.php
index 0a0ad9ad6a7..475f6266f86 100644
--- a/src/Platforms/AbstractMySQLPlatform.php
+++ b/src/Platforms/AbstractMySQLPlatform.php
@@ -739,11 +739,6 @@ public function getSetTransactionIsolationSQL(TransactionIsolationLevel $level):
return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
- public function getReadLockSQL(): string
- {
- return 'LOCK IN SHARE MODE';
- }
-
protected function initializeDoctrineTypeMappings(): void
{
$this->doctrineTypeMapping = [
diff --git a/src/Platforms/AbstractPlatform.php b/src/Platforms/AbstractPlatform.php
index 6dcf3ba0ede..360501816e1 100644
--- a/src/Platforms/AbstractPlatform.php
+++ b/src/Platforms/AbstractPlatform.php
@@ -33,7 +33,6 @@
use Doctrine\DBAL\Types;
use Doctrine\DBAL\Types\Exception\TypeNotFound;
use Doctrine\DBAL\Types\Type;
-use Doctrine\Deprecations\Deprecation;
use function addcslashes;
use function array_map;
@@ -701,23 +700,6 @@ public function getBitOrComparisonExpression(string $value1, string $value2): st
*/
abstract public function getCurrentDatabaseExpression(): string;
- /**
- * Returns the FOR UPDATE expression.
- *
- * @deprecated This API is not portable. Use {@link QueryBuilder::forUpdate()}` instead.
- */
- public function getForUpdateSQL(): string
- {
- Deprecation::triggerIfCalledFromOutside(
- 'doctrine/dbal',
- 'https://github.com/doctrine/dbal/pull/6191',
- '%s is deprecated as non-portable.',
- __METHOD__,
- );
-
- return 'FOR UPDATE';
- }
-
/**
* Honors that some SQL vendors such as MsSql use table hints for locking instead of the
* ANSI SQL FOR UPDATE specification.
@@ -729,45 +711,6 @@ public function appendLockHint(string $fromClause, LockMode $lockMode): string
return $fromClause;
}
- /**
- * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock.
- *
- * This defaults to the ANSI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database
- * vendors allow to lighten this constraint up to be a real read lock.
- *
- * @deprecated This API is not portable.
- */
- public function getReadLockSQL(): string
- {
- Deprecation::trigger(
- 'doctrine/dbal',
- 'https://github.com/doctrine/dbal/pull/6191',
- '%s is deprecated as non-portable.',
- __METHOD__,
- );
-
- return $this->getForUpdateSQL();
- }
-
- /**
- * Returns the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows.
- *
- * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ANSI SQL standard.
- *
- * @deprecated This API is not portable.
- */
- public function getWriteLockSQL(): string
- {
- Deprecation::trigger(
- 'doctrine/dbal',
- 'https://github.com/doctrine/dbal/pull/6191',
- '%s is deprecated as non-portable.',
- __METHOD__,
- );
-
- return $this->getForUpdateSQL();
- }
-
/**
* Returns the SQL snippet to drop an existing table.
*/
diff --git a/src/Platforms/DB2Platform.php b/src/Platforms/DB2Platform.php
index 31cdfb677b7..a00b24bb702 100644
--- a/src/Platforms/DB2Platform.php
+++ b/src/Platforms/DB2Platform.php
@@ -564,12 +564,6 @@ public function createSelectSQLBuilder(): SelectSQLBuilder
return new DefaultSelectSQLBuilder($this, 'WITH RR USE AND KEEP UPDATE LOCKS', null);
}
- /** @deprecated This API is not portable. */
- public function getForUpdateSQL(): string
- {
- return ' WITH RR USE AND KEEP UPDATE LOCKS';
- }
-
public function getDummySelectSQL(string $expression = '1'): string
{
return sprintf('SELECT %s FROM sysibm.sysdummy1', $expression);
diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php
index c080eea72c9..166ee7547fb 100644
--- a/src/Platforms/PostgreSQLPlatform.php
+++ b/src/Platforms/PostgreSQLPlatform.php
@@ -685,11 +685,6 @@ public function getTruncateTableSQL(string $tableName, bool $cascade = false): s
return $sql;
}
- public function getReadLockSQL(): string
- {
- return 'FOR SHARE';
- }
-
protected function initializeDoctrineTypeMappings(): void
{
$this->doctrineTypeMapping = [
diff --git a/src/Platforms/SQLServerPlatform.php b/src/Platforms/SQLServerPlatform.php
index 6078fe7baad..506fe52bbea 100644
--- a/src/Platforms/SQLServerPlatform.php
+++ b/src/Platforms/SQLServerPlatform.php
@@ -1096,12 +1096,6 @@ public function appendLockHint(string $fromClause, LockMode $lockMode): string
};
}
- /** @deprecated This API is not portable. */
- public function getForUpdateSQL(): string
- {
- return ' ';
- }
-
protected function createReservedKeywordsList(): KeywordList
{
return new SQLServerKeywords();
diff --git a/src/Platforms/SQLitePlatform.php b/src/Platforms/SQLitePlatform.php
index 0cca9c67eb6..2f91c277328 100644
--- a/src/Platforms/SQLitePlatform.php
+++ b/src/Platforms/SQLitePlatform.php
@@ -415,11 +415,6 @@ public function getTruncateTableSQL(string $tableName, bool $cascade = false): s
return 'DELETE FROM ' . $tableIdentifier->getQuotedName($this);
}
- public function getForUpdateSQL(): string
- {
- return '';
- }
-
/** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
public function getInlineColumnCommentSQL(string $comment): string
{
diff --git a/src/Query/ForUpdate.php b/src/Query/ForUpdate.php
index f511f6404be..24a853e924a 100644
--- a/src/Query/ForUpdate.php
+++ b/src/Query/ForUpdate.php
@@ -4,15 +4,17 @@
namespace Doctrine\DBAL\Query;
+use Doctrine\DBAL\Query\ForUpdate\ConflictResolutionMode;
+
/** @internal */
final class ForUpdate
{
public function __construct(
- private readonly int $conflictResolutionMode,
+ private readonly ConflictResolutionMode $conflictResolutionMode,
) {
}
- public function getConflictResolutionMode(): int
+ public function getConflictResolutionMode(): ConflictResolutionMode
{
return $this->conflictResolutionMode;
}
diff --git a/src/Query/ForUpdate/ConflictResolutionMode.php b/src/Query/ForUpdate/ConflictResolutionMode.php
index f968f7b941d..f45f774bddc 100644
--- a/src/Query/ForUpdate/ConflictResolutionMode.php
+++ b/src/Query/ForUpdate/ConflictResolutionMode.php
@@ -4,24 +4,15 @@
namespace Doctrine\DBAL\Query\ForUpdate;
-final class ConflictResolutionMode
+enum ConflictResolutionMode
{
/**
* Wait for the row to be unlocked
*/
- public const ORDINARY = 0;
+ case ORDINARY;
/**
* Skip the row if it is locked
*/
- public const SKIP_LOCKED = 1;
-
- /**
- * This class cannot be instantiated.
- *
- * @codeCoverageIgnore
- */
- private function __construct()
- {
- }
+ case SKIP_LOCKED;
}
diff --git a/src/Query/QueryBuilder.php b/src/Query/QueryBuilder.php
index a2710592f52..52fc06d88f4 100644
--- a/src/Query/QueryBuilder.php
+++ b/src/Query/QueryBuilder.php
@@ -492,7 +492,7 @@ public function getMaxResults(): ?int
*
* @return $this
*/
- public function forUpdate(int $conflictResolutionMode = ConflictResolutionMode::ORDINARY): self
+ public function forUpdate(ConflictResolutionMode $conflictResolutionMode = ConflictResolutionMode::ORDINARY): self
{
$this->forUpdate = new ForUpdate($conflictResolutionMode);
diff --git a/tests/Platforms/DB2PlatformTest.php b/tests/Platforms/DB2PlatformTest.php
index a5f17eb76b0..57320ba85d5 100644
--- a/tests/Platforms/DB2PlatformTest.php
+++ b/tests/Platforms/DB2PlatformTest.php
@@ -321,7 +321,6 @@ public function testGeneratesSQLSnippets(): void
);
self::assertEquals("'1987/05/02' - 10 YEAR", $this->platform->getDateSubYearsExpression("'1987/05/02'", '10'));
- self::assertEquals(' WITH RR USE AND KEEP UPDATE LOCKS', $this->platform->getForUpdateSQL());
self::assertEquals(
'LOCATE(substring_column, string_column)',