Skip to content

Commit 0c419a0

Browse files
Merge branch '6.3' into 6.4
* 6.3: [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] Fix denormalize constructor arguments Add some more non-countable English nouns Add hint that changing input arguments has no effect [DomCrawler] Revert "bug #52579 UriResolver support path with colons" [VarExporter] Fix handling mangled property names returned by __sleep() Update Github template for 7.1
2 parents 37f8ee1 + 7e39c3c commit 0c419a0

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
@@ -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
}

Tests/Store/DoctrineDbalStoreTest.php

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

7676
/**
77-
* @dataProvider provideDsn
77+
* @dataProvider provideDsnWithSQLite
7878
*/
79-
public function testDsn(string $dsn, string $file = null)
79+
public function testDsnWithSQLite(string $dsn, string $file = null)
8080
{
8181
$key = new Key(uniqid(__METHOD__, true));
8282

@@ -92,12 +92,36 @@ public function testDsn(string $dsn, string $file = null)
9292
}
9393
}
9494

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

103127
/**

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é <[email protected]>
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)