Skip to content

Commit adec730

Browse files
Merge branch '6.3' into 6.4
* 6.3: [Cache][Lock] Fix PDO store not creating table + add tests Closes symfony#51936-Added Missing translations for Czech (cs) in validators.cs.xlf file Added missing translations in turkish and updated validators.tr.xlf [Serializer] Fix denormalizing date intervals having both weeks and days [Validator] updated Turkish translation [Serializer] Fix denormalize constructor arguments Add some more non-countable English nouns Add hint that changing input arguments has no effect [DomCrawler] Revert "bug symfony#52579 UriResolver support path with colons" [VarExporter] Fix handling mangled property names returned by __sleep() Update Github template for 7.1
2 parents 6f06151 + bb03b99 commit adec730

File tree

27 files changed

+349
-79
lines changed

27 files changed

+349
-79
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
| Q | A
22
| ------------- | ---
3-
| Branch? | 6.4 for features / 5.4 or 6.3 for bug fixes <!-- see below -->
3+
| Branch? | 7.1 for features / 5.4, 6.3, 6.4, or 7.0 for bug fixes <!-- see below -->
44
| Bug fix? | yes/no
55
| New feature? | yes/no <!-- please update src/**/CHANGELOG.md files -->
66
| Deprecations? | yes/no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->

src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ private function getServerVersion(): string
389389
return $this->serverVersion;
390390
}
391391

392-
$conn = $this->conn->getWrappedConnection();
392+
// The condition should be removed once support for DBAL <3.3 is dropped
393+
$conn = method_exists($this->conn, 'getNativeConnection') ? $this->conn->getNativeConnection() : $this->conn->getWrappedConnection();
393394
if ($conn instanceof ServerInfoAwareConnection) {
394395
return $this->serverVersion = $conn->getServerVersion();
395396
}

src/Symfony/Component/Cache/Adapter/PdoAdapter.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ protected function doSave(array $values, int $lifetime): array|bool
286286
try {
287287
$stmt = $conn->prepare($sql);
288288
} catch (\PDOException) {
289-
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
289+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
290290
$this->createTable();
291291
}
292292
$stmt = $conn->prepare($sql);
@@ -321,7 +321,7 @@ protected function doSave(array $values, int $lifetime): array|bool
321321
try {
322322
$stmt->execute();
323323
} catch (\PDOException) {
324-
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
324+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
325325
$this->createTable();
326326
}
327327
$stmt->execute();
@@ -369,4 +369,21 @@ private function getServerVersion(): string
369369
{
370370
return $this->serverVersion ??= $this->conn->getAttribute(\PDO::ATTR_SERVER_VERSION);
371371
}
372+
373+
private function isTableMissing(\PDOException $exception): bool
374+
{
375+
$driver = $this->driver;
376+
$code = $exception->getCode();
377+
378+
switch (true) {
379+
case 'pgsql' === $driver && '42P01' === $code:
380+
case 'sqlite' === $driver && str_contains($exception->getMessage(), 'no such table:'):
381+
case 'oci' === $driver && 942 === $code:
382+
case 'sqlsrv' === $driver && 208 === $code:
383+
case 'mysql' === $driver && 1146 === $code:
384+
return true;
385+
default:
386+
return false;
387+
}
388+
}
372389
}

src/Symfony/Component/Cache/Tests/Adapter/DoctrineDbalAdapterTest.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
use Symfony\Component\Cache\Tests\Fixtures\DriverWrapper;
2424

2525
/**
26+
* @requires extension pdo_sqlite
27+
*
2628
* @group time-sensitive
2729
*/
2830
class DoctrineDbalAdapterTest extends AdapterTestCase
@@ -31,10 +33,6 @@ class DoctrineDbalAdapterTest extends AdapterTestCase
3133

3234
public static function setUpBeforeClass(): void
3335
{
34-
if (!\extension_loaded('pdo_sqlite')) {
35-
self::markTestSkipped('Extension pdo_sqlite required.');
36-
}
37-
3836
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
3937
}
4038

@@ -106,13 +104,12 @@ public function testConfigureSchemaTableExists()
106104
}
107105

108106
/**
109-
* @dataProvider provideDsn
107+
* @dataProvider provideDsnWithSQLite
110108
*/
111-
public function testDsn(string $dsn, string $file = null)
109+
public function testDsnWithSQLite(string $dsn, string $file = null)
112110
{
113111
try {
114112
$pool = new DoctrineDbalAdapter($dsn);
115-
$pool->createTable();
116113

117114
$item = $pool->getItem('key');
118115
$item->set('value');
@@ -124,12 +121,35 @@ public function testDsn(string $dsn, string $file = null)
124121
}
125122
}
126123

127-
public static function provideDsn()
124+
public static function provideDsnWithSQLite()
128125
{
129126
$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
130-
yield ['sqlite://localhost/'.$dbFile.'1', $dbFile.'1'];
131-
yield ['sqlite3:///'.$dbFile.'3', $dbFile.'3'];
132-
yield ['sqlite://localhost/:memory:'];
127+
yield 'SQLite file' => ['sqlite://localhost/'.$dbFile.'1', $dbFile.'1'];
128+
yield 'SQLite3 file' => ['sqlite3:///'.$dbFile.'3', $dbFile.'3'];
129+
yield 'SQLite in memory' => ['sqlite://localhost/:memory:'];
130+
}
131+
132+
/**
133+
* @requires extension pdo_pgsql
134+
*
135+
* @group integration
136+
*/
137+
public function testDsnWithPostgreSQL()
138+
{
139+
if (!$host = getenv('POSTGRES_HOST')) {
140+
$this->markTestSkipped('Missing POSTGRES_HOST env variable');
141+
}
142+
143+
try {
144+
$pool = new DoctrineDbalAdapter('pgsql://postgres:password@'.$host);
145+
146+
$item = $pool->getItem('key');
147+
$item->set('value');
148+
$this->assertTrue($pool->save($item));
149+
} finally {
150+
$pdo = new \PDO('pgsql:host='.$host.';user=postgres;password=password');
151+
$pdo->exec('DROP TABLE IF EXISTS cache_items');
152+
}
133153
}
134154

135155
protected function isPruned(DoctrineDbalAdapter $cache, string $name): bool

src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Symfony\Component\Cache\Adapter\PdoAdapter;
1616

1717
/**
18+
* @requires extension pdo_sqlite
19+
*
1820
* @group time-sensitive
1921
*/
2022
class PdoAdapterTest extends AdapterTestCase
@@ -23,10 +25,6 @@ class PdoAdapterTest extends AdapterTestCase
2325

2426
public static function setUpBeforeClass(): void
2527
{
26-
if (!\extension_loaded('pdo_sqlite')) {
27-
self::markTestSkipped('Extension pdo_sqlite required.');
28-
}
29-
3028
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
3129

3230
$pool = new PdoAdapter('sqlite:'.self::$dbFile);
@@ -68,13 +66,12 @@ public function testCleanupExpiredItems()
6866
}
6967

7068
/**
71-
* @dataProvider provideDsn
69+
* @dataProvider provideDsnSQLite
7270
*/
73-
public function testDsn(string $dsn, string $file = null)
71+
public function testDsnWithSQLite(string $dsn, string $file = null)
7472
{
7573
try {
7674
$pool = new PdoAdapter($dsn);
77-
$pool->createTable();
7875

7976
$item = $pool->getItem('key');
8077
$item->set('value');
@@ -86,11 +83,36 @@ public function testDsn(string $dsn, string $file = null)
8683
}
8784
}
8885

89-
public static function provideDsn()
86+
public static function provideDsnSQLite()
9087
{
9188
$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
92-
yield ['sqlite:'.$dbFile.'2', $dbFile.'2'];
93-
yield ['sqlite::memory:'];
89+
yield 'SQLite file' => ['sqlite:'.$dbFile.'2', $dbFile.'2'];
90+
yield 'SQLite in memory' => ['sqlite::memory:'];
91+
}
92+
93+
/**
94+
* @requires extension pdo_pgsql
95+
*
96+
* @group integration
97+
*/
98+
public function testDsnWithPostgreSQL()
99+
{
100+
if (!$host = getenv('POSTGRES_HOST')) {
101+
$this->markTestSkipped('Missing POSTGRES_HOST env variable');
102+
}
103+
104+
$dsn = 'pgsql:host='.$host.';user=postgres;password=password';
105+
106+
try {
107+
$pool = new PdoAdapter($dsn);
108+
109+
$item = $pool->getItem('key');
110+
$item->set('value');
111+
$this->assertTrue($pool->save($item));
112+
} finally {
113+
$pdo = new \PDO($dsn);
114+
$pdo->exec('DROP TABLE IF EXISTS cache_items');
115+
}
94116
}
95117

96118
protected function isPruned(PdoAdapter $cache, string $name): bool

src/Symfony/Component/Console/Event/ConsoleCommandEvent.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
namespace Symfony\Component\Console\Event;
1313

1414
/**
15-
* Allows to do things before the command is executed, like skipping the command or changing the input.
15+
* Allows to do things before the command is executed, like skipping the command or executing code before the command is
16+
* going to be executed.
17+
*
18+
* Changing the input arguments will have no effect.
1619
*
1720
* @author Fabien Potencier <[email protected]>
1821
*/

src/Symfony/Component/DomCrawler/Tests/UriResolverTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ public static function provideResolverTests()
8585
['foo', 'http://localhost?bar=1', 'http://localhost/foo'],
8686
['foo', 'http://localhost#bar', 'http://localhost/foo'],
8787

88-
['foo:1', 'http://localhost', 'http://localhost/foo:1'],
89-
['/bar:1', 'http://localhost', 'http://localhost/bar:1'],
90-
['foo/bar:1', 'http://localhost', 'http://localhost/foo/bar:1'],
88+
['http://', 'http://localhost', 'http://'],
9189
];
9290
}
9391
}

src/Symfony/Component/DomCrawler/UriResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static function resolve(string $uri, ?string $baseUri): string
3333
$uri = trim($uri);
3434

3535
// absolute URL?
36-
if (\is_string(parse_url($uri, \PHP_URL_SCHEME))) {
36+
if (null !== parse_url($uri, \PHP_URL_SCHEME)) {
3737
return $uri;
3838
}
3939

src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public static function createHandler(object|string $connection, array $options =
7878
}
7979

8080
$connection = DriverManager::getConnection($params, $config);
81+
// The condition should be removed once support for DBAL <3.3 is dropped
8182
$connection = method_exists($connection, 'getNativeConnection') ? $connection->getNativeConnection() : $connection->getWrappedConnection();
8283
// no break;
8384

src/Symfony/Component/Lock/Store/PdoStore.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public function save(Key $key)
9595
try {
9696
$stmt = $conn->prepare($sql);
9797
} catch (\PDOException) {
98-
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
98+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
9999
$this->createTable();
100100
}
101101
$stmt = $conn->prepare($sql);
@@ -107,8 +107,18 @@ public function save(Key $key)
107107
try {
108108
$stmt->execute();
109109
} catch (\PDOException) {
110-
// the lock is already acquired. It could be us. Let's try to put off.
111-
$this->putOffExpiration($key, $this->initialTtl);
110+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
111+
$this->createTable();
112+
113+
try {
114+
$stmt->execute();
115+
} catch (\PDOException $e) {
116+
$this->putOffExpiration($key, $this->initialTtl);
117+
}
118+
} else {
119+
// the lock is already acquired. It could be us. Let's try to put off.
120+
$this->putOffExpiration($key, $this->initialTtl);
121+
}
112122
}
113123

114124
$this->randomlyPrune();
@@ -238,4 +248,21 @@ private function getCurrentTimestampStatement(): string
238248
default => (string) time(),
239249
};
240250
}
251+
252+
private function isTableMissing(\PDOException $exception): bool
253+
{
254+
$driver = $this->getDriver();
255+
$code = $exception->getCode();
256+
257+
switch (true) {
258+
case 'pgsql' === $driver && '42P01' === $code:
259+
case 'sqlite' === $driver && str_contains($exception->getMessage(), 'no such table:'):
260+
case 'oci' === $driver && 942 === $code:
261+
case 'sqlsrv' === $driver && 208 === $code:
262+
case 'mysql' === $driver && 1146 === $code:
263+
return true;
264+
default:
265+
return false;
266+
}
267+
}
241268
}

0 commit comments

Comments
 (0)