According to <https://www.php.net/manual/en/pdo.error-handling.php>.
. Don't ignore invalid escape sequences. (sjon)
- PDO:
+ . Changed default PDO error mode to exceptions. (AllenJB)
. Fixed bug #77849 (Disable cloning of PDO handle/connection objects).
(camporter)
now ignored.
- PDO:
+ . The default error handling mode has been changed from "silent" to
+ "exceptions". See https://www.php.net/manual/en/pdo.error-handling.php
+ for details of behavior changes and how to explicitly set this attribute.
+ RFC: https://wiki.php.net/rfc/pdo_default_errmode
. The method PDOStatement::setFetchMode() now accepts the following signature:
PDOStatement::setFetchMode($mode, $classname, $params)
}
dbh->auto_commit = pdo_attr_lval(options, PDO_ATTR_AUTOCOMMIT, 1);
+ dbh->error_mode = pdo_attr_lval(options, PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
php_error_docref(NULL, E_ERROR, "Out of memory");
--FILE--
<?php
$pdo = new PDO("sqlite:".__DIR__."/foo.db");
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$attrs = array(PDO::ATTR_STATEMENT_CLASS, PDO::ATTR_STRINGIFY_FETCHES, PDO::NULL_TO_STRING);
?>
--EXPECTF--
Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
+
+Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
+
+Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
+
+Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: attribute value must be an integer in %s on line %d
+
+Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
bool(true)
bool(true)
if (!$db) {
die("Could not create PDO object (DSN=$dsn, user=$user)\n");
}
+ // Ignore errors about non-existant tables
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
// clean up any crufty test tables we might have left behind
// on a previous run
NOTE: if any of `PDO_MYSQL_TEST_[HOST|DB|SOCKET|ENGINE|CHARSET]` is part of
`PDO_MYSQL_TEST_DSN`, the values must match. That is, for example, for
`PDO_MYSQL_TEST_DSN = mysql:dbname=test` you MUST set `PDO_MYSQL_TEST_DB=test`.
+
+## MySQL User Permissions
+
+The MySQL user used to run the tests must have full permissions on the test
+database, plus the following additional permissions:
+
+* SUPER: Required to [create functions if binary logging is enabled](https://dev.mysql.com/doc/refman/8.0/en/stored-programs-logging.html#sa38412929)
+* SELECT permissions on performance_schema.session_connect_attrs
$dsn = MySQLPDOTest::getDSN(array('dbname' => $db), 'dbname=' . $invalid_db);
try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
$tmp = $e->getMessage();
- if (!stristr($tmp, '42000') && !stristr($tmp, '1049'))
+ // 1044 may occur here if running tests using a custom user that does not have access to all databases
+ if (!stristr($tmp, '42000') && !stristr($tmp, '1049') && !stristr($tmp, '1044'))
printf("[022] Cannot find proper error codes: %s\n", $tmp);
}
try {
$db = new PDO($dsn, $user, $pass, array($option => $value));
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
if (!is_object($db) || ($value !== ($tmp = @$db->getAttribute($option))))
printf("[%03d] Expecting '%s'/%s got '%s'/%s' for options '%s'\n",
$offset,
printf("[003] [TODO][CHANGEREQUEST] Please, lets not ignore invalid options and bail out!\n");
$db = new PDO($dsn, $user, $pass);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
foreach ($valid_options as $option => $name) {
/* TODO getAttribute() is pretty poor in supporting the options, suppress errors */
$tmp = @$db->getAttribute($option);
set_option_and_check(34, PDO::MYSQL_ATTR_DIRECT_QUERY, 0, 'PDO::MYSQL_ATTR_DIRECT_QUERY');
} catch (PDOException $e) {
- printf("[001] %s, [%s] %s\n",
+ printf("[001] %s, [%s] %s Line: %s\n",
$e->getMessage(),
(is_object($db)) ? $db->errorCode() : 'n/a',
- (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a');
+ (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a',
+ $e->getLine());
}
print "done!";
$table = sprintf("test_%s", md5(mt_rand(0, PHP_INT_MAX)));
$db = new PDO($dsn, $user, $pass);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->exec(sprintf('DROP TABLE IF EXISTS %s', $table));
$create = sprintf('CREATE TABLE %s(id INT)', $table);
$db->exec($create);
// New connection, does not allow multiple statements.
$db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => false));
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $db->query(sprintf('SELECT * FROM %s; INSERT INTO %s(id) VALUES (3)', $table, $table));
var_dump($stmt);
$info = $db->errorInfo();
$db->exec(sprintf('DROP TABLE IF EXISTS %s', $table));
print "done!";
?>
---EXPECT--
+--EXPECTF--
string(5) "00000"
array(2) {
[0]=>
string(1) "1"
}
}
+
+Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO %s(id) VALUES (3)' at line 1 in %s on line %d
bool(false)
string(5) "42000"
array(2) {
<?php
require __DIR__ . '/mysql_pdo_test.inc';
$db = MySQLPDOTest::factory();
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
@$db->exec('DROP TABLE IF EXISTS test');
?>
--EXPECTF--
$user = PDO_MYSQL_TEST_USER;
$pass = PDO_MYSQL_TEST_PASS;
$db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi));
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
test_proc($db);
$db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi));
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
require __DIR__ . '/mysql_pdo_test.inc';
MySQLPDOTest::dropTestTable();
?>
---EXPECT--
+--EXPECTF--
Native PS...
Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to false
}
}
bool(false)
+
+Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO test (id, label) VALUES (99, 'x')' at line 1 in %s on line %d
string(5) "42000"
Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to true
$db1 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$db2 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
+ $db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
+ $db2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db1->exec('SET @pdo_persistent_connection=1');
$stmt = $db2->query('SELECT @pdo_persistent_connection as _pers');
$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
$db1 = NULL; /* should be equal to closing to my understanding */
$db1 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
+ $db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$stmt = $db1->query('SELECT CONNECTION_ID() as _con1');
$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
$con1 = $tmp['_con1'];
}
$db1 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => false));
+ $db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$stmt = $db1->query('SELECT CONNECTION_ID() as _con1');
$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
$con1 = $tmp['_con1'];
@$db2 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
+ $db2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$stmt = $db2->query('SELECT CONNECTION_ID() as _con2');
$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
$con2 = $tmp['_con2'];
<?php
$db = new PDO('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
+
$db->exec('CREATE TABLE testing (id INTEGER , name VARCHAR)');
$db->exec('INSERT INTO testing VALUES(1, "php")');
$db->exec('INSERT INTO testing VALUES(2, "")');
}
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: function 'nothing' not found or invalid function name in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: function '' not found or invalid function name in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: no array or string given in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: no array or string given in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: class 'PDOStatement' does not have a method 'foo' in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
array(2) {
[0]=>
}
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: non-static method bar::test2() cannot be called statically in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: non-static method bar::test3() cannot be called statically in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: class 'bar' does not have a method 'inexistent' in %s on line %d
+
+Warning: PDOStatement::fetchAll(): SQLSTATE[HY000]: General error in %s on line %d
bool(false)
echo "Creating new PDO" . PHP_EOL;
$db = new PDO('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db->exec("CREATE TABLE dog ( id INTEGER PRIMARY KEY, name TEXT, annoying INTEGER )");
echo "Creating new PDO with Extended Result Codes turned on" . PHP_EOL;
$db = new PDO('sqlite::memory:', '', '', [PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES => TRUE]);
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db->exec("CREATE TABLE dog ( id INTEGER PRIMARY KEY, name TEXT, annoying INTEGER )");
<?php
$db = new PDO('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->beginTransaction();
$db->query('DROP TABLE foobar');
?>
---EXPECT--
+--EXPECTF--
int(0)
+
+Warning: PDO::query(): SQLSTATE[HY000]: General error: 6 database table is locked in %s on line %d