From 50752401a7c16f8e1f4bbe7ef52bc8fb5b17418f Mon Sep 17 00:00:00 2001 From: AllenJB Date: Mon, 4 May 2020 20:24:06 +0200 Subject: Change the default PDO error mode to exceptions According to . --- ext/pdo/pdo_dbh.c | 1 + ext/pdo/tests/bug_44159.phpt | 9 +++++++++ ext/pdo/tests/pdo_test.inc | 2 ++ ext/pdo_mysql/tests/README.md | 8 ++++++++ ext/pdo_mysql/tests/pdo_mysql___construct.phpt | 3 ++- ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt | 7 +++++-- .../tests/pdo_mysql_attr_multi_statements.phpt | 6 +++++- ext/pdo_mysql/tests/pdo_mysql_exec.phpt | 1 + .../tests/pdo_mysql_multi_stmt_nextrowset.phpt | 6 +++++- ext/pdo_mysql/tests/pdo_mysql_pconnect.phpt | 5 +++++ ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt | 18 ++++++++++++++++++ .../tests/pdo_sqlite_extendederror_attr.phpt | 2 ++ ext/pdo_sqlite/tests/pdo_sqlite_transaction.phpt | 5 ++++- 13 files changed, 67 insertions(+), 6 deletions(-) (limited to 'ext') diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 4ff5da3e13..769fe25f9d 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -340,6 +340,7 @@ PHP_METHOD(PDO, __construct) } 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"); diff --git a/ext/pdo/tests/bug_44159.phpt b/ext/pdo/tests/bug_44159.phpt index bd7aca0e93..5f23f910eb 100644 --- a/ext/pdo/tests/bug_44159.phpt +++ b/ext/pdo/tests/bug_44159.phpt @@ -12,6 +12,7 @@ try { --FILE-- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $attrs = array(PDO::ATTR_STATEMENT_CLASS, PDO::ATTR_STRINGIFY_FETCHES, PDO::NULL_TO_STRING); @@ -26,15 +27,23 @@ foreach ($attrs as $attr) { ?> --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) diff --git a/ext/pdo/tests/pdo_test.inc b/ext/pdo/tests/pdo_test.inc index 2238123d40..aa1d1eadcb 100644 --- a/ext/pdo/tests/pdo_test.inc +++ b/ext/pdo/tests/pdo_test.inc @@ -37,6 +37,8 @@ class PDOTest { 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 diff --git a/ext/pdo_mysql/tests/README.md b/ext/pdo_mysql/tests/README.md index afdac4189a..dd3b93b592 100644 --- a/ext/pdo_mysql/tests/README.md +++ b/ext/pdo_mysql/tests/README.md @@ -31,3 +31,11 @@ PDO_MYSQL_TEST_CHARSET 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 diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt index 7412402125..bff3fcbe5a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt @@ -150,7 +150,8 @@ MySQLPDOTest::skip(); $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); } diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt index ac5f7f6911..efbf3c51c8 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt @@ -18,6 +18,7 @@ MySQLPDOTest::skip(); 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, @@ -81,6 +82,7 @@ MySQLPDOTest::skip(); 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); @@ -155,10 +157,11 @@ MySQLPDOTest::skip(); 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!"; diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt index 65b5e1bdc9..62de8ad1ca 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt @@ -19,6 +19,7 @@ error_reporting=E_ALL $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); @@ -35,6 +36,7 @@ error_reporting=E_ALL // 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(); @@ -49,7 +51,7 @@ error_reporting=E_ALL $db->exec(sprintf('DROP TABLE IF EXISTS %s', $table)); print "done!"; ?> ---EXPECT-- +--EXPECTF-- string(5) "00000" array(2) { [0]=> @@ -70,6 +72,8 @@ array(1) { 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) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_exec.phpt b/ext/pdo_mysql/tests/pdo_mysql_exec.phpt index c6f3d54ddd..a670be737f 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_exec.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_exec.phpt @@ -176,6 +176,7 @@ MySQLPDOTest::skip(); setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); @$db->exec('DROP TABLE IF EXISTS test'); ?> --EXPECTF-- diff --git a/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt index 74ab7858d4..368f588cfd 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt @@ -50,12 +50,14 @@ if (!MySQLPDOTest::isPDOMySQLnd()) $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); @@ -86,7 +88,7 @@ if (!MySQLPDOTest::isPDOMySQLnd()) require __DIR__ . '/mysql_pdo_test.inc'; MySQLPDOTest::dropTestTable(); ?> ---EXPECT-- +--EXPECTF-- Native PS... Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to false @@ -172,6 +174,8 @@ array(3) { } } 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 diff --git a/ext/pdo_mysql/tests/pdo_mysql_pconnect.phpt b/ext/pdo_mysql/tests/pdo_mysql_pconnect.phpt index 4d95c73cdc..51e5b7b44a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_pconnect.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_pconnect.phpt @@ -18,6 +18,8 @@ MySQLPDOTest::skip(); $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); @@ -37,6 +39,7 @@ MySQLPDOTest::skip(); $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']; @@ -60,11 +63,13 @@ MySQLPDOTest::skip(); } $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']; diff --git a/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt b/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt index 525e29b953..4463dbb3ec 100644 --- a/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt +++ b/ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt @@ -8,6 +8,8 @@ if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; 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, "")'); @@ -91,18 +93,28 @@ array(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]=> @@ -118,10 +130,16 @@ array(2) { } 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) diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt index 50b939b6eb..5ea4a2def1 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt @@ -7,6 +7,7 @@ PDO_sqlite: Testing PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES 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 )"); @@ -23,6 +24,7 @@ echo sprintf("Second Error Info: SQLSTATE Error Code: (%s), Driver Specific Erro 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 )"); diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_transaction.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_transaction.phpt index 493fff78d8..478121e721 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_transaction.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_transaction.phpt @@ -6,6 +6,7 @@ PDO_sqlite: Testing transaction setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $db->beginTransaction(); @@ -24,5 +25,7 @@ var_dump($r->rowCount()); $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 -- cgit v1.2.1