Skip to content

Commit 2cc592e

Browse files
Merge branch '6.4' into 7.0
* 6.4: [FrameworkBundle] Add TemplateController to the list of allowed controllers for fragments [Cache][Lock] Fix PDO store not creating table + add tests Closes #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] Remove wrong final tags [Serializer] Fix denormalize constructor arguments Add some more non-countable English nouns Add hint that changing input arguments has no effect register the virtual request stack together with common profiling services Don't lose checkpoint state when lock is acquired from another [DomCrawler] Revert "bug #52579 UriResolver support path with colons" [VarExporter] Fix handling mangled property names returned by __sleep() Update Github template for 7.1 Fix memory limit in PhpSubprocess unit test
2 parents 2c792bc + 0c419a0 commit 2cc592e

File tree

3 files changed

+91
-16
lines changed

3 files changed

+91
-16
lines changed

Store/PdoStore.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function save(Key $key): void
9292
try {
9393
$stmt = $conn->prepare($sql);
9494
} catch (\PDOException) {
95-
if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
95+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
9696
$this->createTable();
9797
}
9898
$stmt = $conn->prepare($sql);
@@ -104,8 +104,18 @@ public function save(Key $key): void
104104
try {
105105
$stmt->execute();
106106
} catch (\PDOException) {
107-
// the lock is already acquired. It could be us. Let's try to put off.
108-
$this->putOffExpiration($key, $this->initialTtl);
107+
if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) {
108+
$this->createTable();
109+
110+
try {
111+
$stmt->execute();
112+
} catch (\PDOException $e) {
113+
$this->putOffExpiration($key, $this->initialTtl);
114+
}
115+
} else {
116+
// the lock is already acquired. It could be us. Let's try to put off.
117+
$this->putOffExpiration($key, $this->initialTtl);
118+
}
109119
}
110120

111121
$this->randomlyPrune();
@@ -229,4 +239,21 @@ private function getCurrentTimestampStatement(): string
229239
default => (string) time(),
230240
};
231241
}
242+
243+
private function isTableMissing(\PDOException $exception): bool
244+
{
245+
$driver = $this->getDriver();
246+
$code = $exception->getCode();
247+
248+
switch (true) {
249+
case 'pgsql' === $driver && '42P01' === $code:
250+
case 'sqlite' === $driver && str_contains($exception->getMessage(), 'no such table:'):
251+
case 'oci' === $driver && 942 === $code:
252+
case 'sqlsrv' === $driver && 208 === $code:
253+
case 'mysql' === $driver && 1146 === $code:
254+
return true;
255+
default:
256+
return false;
257+
}
258+
}
232259
}

Tests/Store/DoctrineDbalStoreTest.php

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ public function testAbortAfterExpiration()
7070
}
7171

7272
/**
73-
* @dataProvider provideDsn
73+
* @dataProvider provideDsnWithSQLite
7474
*/
75-
public function testDsn(string $dsn, string $file = null)
75+
public function testDsnWithSQLite(string $dsn, string $file = null)
7676
{
7777
$key = new Key(uniqid(__METHOD__, true));
7878

@@ -88,12 +88,36 @@ public function testDsn(string $dsn, string $file = null)
8888
}
8989
}
9090

91-
public static function provideDsn()
91+
public static function provideDsnWithSQLite()
9292
{
9393
$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
94-
yield ['sqlite://localhost/'.$dbFile.'1', $dbFile.'1'];
95-
yield ['sqlite3:///'.$dbFile.'3', $dbFile.'3'];
96-
yield ['sqlite://localhost/:memory:'];
94+
yield 'SQLite file' => ['sqlite://localhost/'.$dbFile.'1', $dbFile.'1'];
95+
yield 'SQLite3 file' => ['sqlite3:///'.$dbFile.'3', $dbFile.'3'];
96+
yield 'SQLite in memory' => ['sqlite://localhost/:memory:'];
97+
}
98+
99+
/**
100+
* @requires extension pdo_pgsql
101+
*
102+
* @group integration
103+
*/
104+
public function testDsnWithPostgreSQL()
105+
{
106+
if (!$host = getenv('POSTGRES_HOST')) {
107+
$this->markTestSkipped('Missing POSTGRES_HOST env variable');
108+
}
109+
110+
$key = new Key(uniqid(__METHOD__, true));
111+
112+
try {
113+
$store = new DoctrineDbalStore('pgsql://postgres:password@'.$host);
114+
115+
$store->save($key);
116+
$this->assertTrue($store->exists($key));
117+
} finally {
118+
$pdo = new \PDO('pgsql:host='.$host.';user=postgres;password=password');
119+
$pdo->exec('DROP TABLE IF EXISTS lock_keys');
120+
}
97121
}
98122

99123
/**

Tests/Store/PdoStoreTest.php

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
* @author Jérémy Derussé <jeremy@derusse.com>
2121
*
2222
* @requires extension pdo_sqlite
23-
*
24-
* @group integration
2523
*/
2624
class PdoStoreTest extends AbstractStoreTestCase
2725
{
@@ -72,9 +70,9 @@ public function testInvalidTtlConstruct()
7270
}
7371

7472
/**
75-
* @dataProvider provideDsn
73+
* @dataProvider provideDsnWithSQLite
7674
*/
77-
public function testDsn(string $dsn, string $file = null)
75+
public function testDsnWithSQLite(string $dsn, string $file = null)
7876
{
7977
$key = new Key(uniqid(__METHOD__, true));
8078

@@ -90,10 +88,36 @@ public function testDsn(string $dsn, string $file = null)
9088
}
9189
}
9290

93-
public static function provideDsn()
91+
public static function provideDsnWithSQLite()
9492
{
9593
$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
96-
yield ['sqlite:'.$dbFile.'2', $dbFile.'2'];
97-
yield ['sqlite::memory:'];
94+
yield 'SQLite file' => ['sqlite:'.$dbFile.'2', $dbFile.'2'];
95+
yield 'SQLite in memory' => ['sqlite::memory:'];
96+
}
97+
98+
/**
99+
* @requires extension pdo_pgsql
100+
*
101+
* @group integration
102+
*/
103+
public function testDsnWithPostgreSQL()
104+
{
105+
if (!$host = getenv('POSTGRES_HOST')) {
106+
$this->markTestSkipped('Missing POSTGRES_HOST env variable');
107+
}
108+
109+
$key = new Key(uniqid(__METHOD__, true));
110+
111+
$dsn = 'pgsql:host='.$host.';user=postgres;password=password';
112+
113+
try {
114+
$store = new PdoStore($dsn);
115+
116+
$store->save($key);
117+
$this->assertTrue($store->exists($key));
118+
} finally {
119+
$pdo = new \PDO($dsn);
120+
$pdo->exec('DROP TABLE IF EXISTS lock_keys');
121+
}
98122
}
99123
}

0 commit comments

Comments
 (0)