8000 [Lock] PDOStore checks for wrong error code in PDOException for MySQL · Issue #54091 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[Lock] PDOStore checks for wrong error code in PDOException for MySQL #54091
Closed
@edomato

Description

@edomato

Symfony version(s) affected

5.4 and above

Description

The isTableMissing() method checks for the error code 1146 for MySQL when the table used to store the locks doesn't exists, but the code in PDOException is "42S02" for that server.

PHP documentation says that for the PDOException, the code is the SQLSTATE error code.

The stacktrace that PHP throws is:

PHP Fatal error:  Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'testdb.lock_keys' doesn't exist in /app/vendor/symfony/lock/Store/PdoStore.php:140
Stack trace:
#0 /app/vendor/symfony/lock/Store/PdoStore.php(140): PDOStatement->execute()
#1 /app/vendor/symfony/lock/Store/PdoStore.php(117): Symfony\Component\Lock\Store\PdoStore->putOffExpiration()
#2 /app/vendor/symfony/lock/Lock.php(85): Symfony\Component\Lock\Store\PdoStore->save()
#3 /app/lock_test.php(11): Symfony\Component\Lock\Lock->acquire()
#4 {main}

Next Symfony\Component\Lock\Exception\LockAcquiringException: Failed to acquire the "test-lock" lock. in /app/vendor/symfony/lock/Lock.php:116
Stack trace:
#0 /app/lock_test.php(11): Symfony\Component\Lock\Lock->acquire()
#1 {main}
  thrown in /app/vendor/symfony/lock/Lock.php on line 116

As you can see, SQLSTATE is effectively 42S02

And if you inspect the $errorInfo array of the PDOException it has the content

'errorInfo' => 
  array (
    0 => '42S02',
    1 => 1146,
    2 => 'Table \'testdb.lock_keys\' doesn\'t exist',
  )

This array contains the PDO::errorInfo() array which PHP manuals says that:

Element 0 is SQLSTATE error code (a five characters alphanumeric identifier defined in t 6652 he ANSI SQL standard).
Element 1 is Driver-specific error code.
Element 2 is Driver-specific error message.

So, if we want to use the driver-specific error code (the 1146) we shouldn't check for the Exception code but the errorInfo array.

Thanks.
Ernesto

How to reproduce

I used Docker to test the component with this simple script:

<?php

require_once 'vendor/autoload.php';

$pdo = new PDO('mysql:host=mysql;dbname=testdb', 'testUser', 'testPass');
$store = new \Symfony\Component\Lock\Store\PdoStore($pdo);
$factory = new \Symfony\Component\Lock\LockFactory($store);

$lock = $factory->createLock('test-lock');

if ($lock->acquire()) {
    echo "Lock acquired\n";

    $lock->release();
} else {
    echo "Couldn't acquire lock\n";
}

PHP version 8.2.16
MySQL version 8.3.0
MariaDB version 11.3.2

Possible Solution

Either user the SQLSTATE error code for MySQL which is "42S02", or the second element of array erroInfo of the PDOException class which is 1146 as expected.

I consider that the most trivial solution is the first one 😄

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0