mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
ext/pdo: Fixed PDO::setAttribute() and PDO::getAttribute() (#12793)
This commit is contained in:
parent
e502aaf0c5
commit
866aa12bcd
12
NEWS
12
NEWS
@ -34,6 +34,18 @@ Opcache:
|
||||
. If JIT is enabled, PHP will now exit with a fatal error on startup in case
|
||||
of JIT startup initialization issues. (danog)
|
||||
|
||||
PDO:
|
||||
. Fixed setAttribute and getAttribute (SakiTakamachi)
|
||||
|
||||
PDO_DBLIB:
|
||||
. Fixed setAttribute and getAttribute (SakiTakamachi)
|
||||
|
||||
PDO_FIREBIRD:
|
||||
. Fixed setAttribute and getAttribute (SakiTakamachi)
|
||||
|
||||
PDO_MYSQL:
|
||||
. Fixed setAttribute and getAttribute (SakiTakamachi)
|
||||
|
||||
PDO_PGSQL:
|
||||
. Fixed GH-12423, DSN credentials being prioritized over the user/password
|
||||
PDO constructor arguments. (SakiTakamachi)
|
||||
|
21
UPGRADING
21
UPGRADING
@ -26,6 +26,17 @@ PHP 8.4 UPGRADE NOTES
|
||||
Consult sections 2. New Features and 6. New Functions for a list of
|
||||
newly implemented methods and constants.
|
||||
|
||||
- PDO_DBLIB:
|
||||
. setAttribute, DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER and DBLIB_ATTR_DATETIME_CONVERT
|
||||
have been changed to set value as a bool.
|
||||
|
||||
- PDO_FIREBIRD:
|
||||
. getAttribute, ATTR_AUTOCOMMIT has been changed to get the value as a bool.
|
||||
|
||||
- PDO_MYSQL:
|
||||
. getAttribute, ATTR_AUTOCOMMIT, ATTR_EMULATE_PREPARES, MYSQL_ATTR_DIRECT_QUERY have
|
||||
been changed to get values as bool.
|
||||
|
||||
- PDO_PGSQL:
|
||||
. The DSN's credentials, when set, are given priority over their PDO
|
||||
constructor counterparts, being closer to the documentation states.
|
||||
@ -139,6 +150,16 @@ PHP 8.4 UPGRADE NOTES
|
||||
. The behavior of mb_strcut is more consistent now on invalid UTF-8 and UTF-16
|
||||
strings. (For valid UTF-8 and UTF-16 strings, there is no change.)
|
||||
|
||||
- PDO:
|
||||
. getAttribute, enabled to get the value of ATTR_STRINGIFY_FETCHES.
|
||||
|
||||
- PDO_FIREBIRD:
|
||||
. getAttribute, enabled to get values of FB_ATTR_DATE_FORMAT, FB_ATTR_TIME_FORMAT,
|
||||
FB_ATTR_TIMESTAMP_FORMAT.
|
||||
|
||||
- PDO_MYSQL:
|
||||
. getAttribute, enabled to get the value of ATTR_FETCH_TABLE_NAMES.
|
||||
|
||||
- PGSQL:
|
||||
. pg_select, the conditions arguments accepts an empty array and is optional.
|
||||
|
||||
|
@ -911,8 +911,13 @@ PHP_METHOD(PDO, getAttribute)
|
||||
add_next_index_zval(return_value, &dbh->def_stmt_ctor_args);
|
||||
}
|
||||
return;
|
||||
|
||||
case PDO_ATTR_DEFAULT_FETCH_MODE:
|
||||
RETURN_LONG(dbh->default_fetch_type);
|
||||
|
||||
case PDO_ATTR_STRINGIFY_FETCHES:
|
||||
RETURN_BOOL(dbh->stringify);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -290,10 +290,10 @@ static bool dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||
}
|
||||
return SUCCEED == dbsettime(lval);
|
||||
case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
|
||||
if (!pdo_get_long_param(&lval, val)) {
|
||||
if (!pdo_get_bool_param(&bval, val)) {
|
||||
return false;
|
||||
}
|
||||
H->stringify_uniqueidentifier = lval;
|
||||
H->stringify_uniqueidentifier = bval;
|
||||
return true;
|
||||
case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS:
|
||||
if (!pdo_get_bool_param(&bval, val)) {
|
||||
@ -302,10 +302,10 @@ static bool dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||
H->skip_empty_rowsets = bval;
|
||||
return true;
|
||||
case PDO_DBLIB_ATTR_DATETIME_CONVERT:
|
||||
if (!pdo_get_long_param(&lval, val)) {
|
||||
if (!pdo_get_bool_param(&bval, val)) {
|
||||
return false;
|
||||
}
|
||||
H->datetime_convert = lval;
|
||||
H->datetime_convert = bval;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1080,7 +1080,7 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||
char tmp[INFO_BUF_LEN];
|
||||
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
ZVAL_LONG(val,dbh->auto_commit);
|
||||
ZVAL_BOOL(val,dbh->auto_commit);
|
||||
return 1;
|
||||
|
||||
case PDO_ATTR_CONNECTION_STATUS:
|
||||
@ -1124,6 +1124,18 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||
ZVAL_BOOL(val, H->fetch_table_names);
|
||||
return 1;
|
||||
|
||||
case PDO_FB_ATTR_DATE_FORMAT:
|
||||
ZVAL_STRING(val, H->date_format);
|
||||
return 1;
|
||||
|
||||
case PDO_FB_ATTR_TIME_FORMAT:
|
||||
ZVAL_STRING(val, H->time_format);
|
||||
return 1;
|
||||
|
||||
case PDO_FB_ATTR_TIMESTAMP_FORMAT:
|
||||
ZVAL_STRING(val, H->timestamp_format);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -91,30 +91,30 @@ echo "done!";
|
||||
--EXPECT--
|
||||
========== not in manually transaction ==========
|
||||
auto commit ON from ON
|
||||
int(1)
|
||||
bool(true)
|
||||
Success
|
||||
|
||||
auto commit OFF from ON
|
||||
int(0)
|
||||
bool(false)
|
||||
Success
|
||||
|
||||
auto commit OFF from OFF
|
||||
int(0)
|
||||
bool(false)
|
||||
Success
|
||||
|
||||
auto commit ON from OFF
|
||||
int(1)
|
||||
bool(true)
|
||||
Success
|
||||
|
||||
========== in manually transaction ==========
|
||||
begin transaction
|
||||
|
||||
auto commit ON from ON, expect error
|
||||
int(1)
|
||||
bool(true)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
auto commit OFF from ON, expect error
|
||||
int(1)
|
||||
bool(true)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
end transaction
|
||||
@ -122,11 +122,11 @@ auto commit OFF
|
||||
begin transaction
|
||||
|
||||
auto commit ON from OFF, expect error
|
||||
int(0)
|
||||
bool(false)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
auto commit OFF from OFF, expect error
|
||||
int(0)
|
||||
bool(false)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
end transaction
|
||||
|
@ -532,7 +532,7 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_
|
||||
break;
|
||||
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
ZVAL_LONG(return_value, dbh->auto_commit);
|
||||
ZVAL_BOOL(return_value, dbh->auto_commit);
|
||||
break;
|
||||
|
||||
case PDO_ATTR_DEFAULT_STR_PARAM:
|
||||
@ -545,7 +545,7 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_
|
||||
|
||||
case PDO_ATTR_EMULATE_PREPARES:
|
||||
case PDO_MYSQL_ATTR_DIRECT_QUERY:
|
||||
ZVAL_LONG(return_value, H->emulate_prepare);
|
||||
ZVAL_BOOL(return_value, H->emulate_prepare);
|
||||
break;
|
||||
|
||||
#ifndef PDO_USE_MYSQLND
|
||||
@ -576,6 +576,10 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_
|
||||
}
|
||||
#endif
|
||||
|
||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||
ZVAL_BOOL(return_value, H->fetch_table_names);
|
||||
break;
|
||||
|
||||
default:
|
||||
PDO_DBG_RETURN(0);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ $pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$attrs = [
|
||||
// Extensive test: default value and set+get values
|
||||
PDO::ATTR_EMULATE_PREPARES => array(null, 1, 0),
|
||||
PDO::MYSQL_ATTR_DIRECT_QUERY => array(null, 0, 1),
|
||||
PDO::ATTR_EMULATE_PREPARES => array(null, true, false),
|
||||
PDO::MYSQL_ATTR_DIRECT_QUERY => array(null, false, true),
|
||||
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => array(null, false, true),
|
||||
|
||||
// Just test the default
|
||||
@ -67,16 +67,16 @@ foreach ($attrs as $a => $vals) {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
bool(true)
|
||||
OK
|
||||
OK
|
||||
int(0)
|
||||
bool(false)
|
||||
OK
|
||||
OK
|
||||
bool(true)
|
||||
OK
|
||||
OK
|
||||
int(1)
|
||||
bool(true)
|
||||
ERR
|
||||
ERR
|
||||
int(2)
|
||||
@ -93,9 +93,9 @@ array(1) {
|
||||
[0]=>
|
||||
string(12) "PDOStatement"
|
||||
}
|
||||
ERR
|
||||
bool(false)
|
||||
ERR
|
||||
string(5) "mysql"
|
||||
ERR
|
||||
bool(false)
|
||||
ERR
|
||||
int(4)
|
||||
|
@ -54,15 +54,15 @@ MySQLPDOTest::skip();
|
||||
|
||||
$defaults = [
|
||||
PDO::ATTR_PERSISTENT => false,
|
||||
PDO::ATTR_AUTOCOMMIT => 1,
|
||||
PDO::ATTR_AUTOCOMMIT => true,
|
||||
/* TODO - why is this a valid option if getAttribute() does not support it?! */
|
||||
PDO::ATTR_TIMEOUT => false,
|
||||
PDO::ATTR_EMULATE_PREPARES => 1,
|
||||
PDO::ATTR_EMULATE_PREPARES => true,
|
||||
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
|
||||
/* TODO getAttribute() does not handle it */
|
||||
PDO::MYSQL_ATTR_LOCAL_INFILE => false,
|
||||
/* TODO getAttribute() does not handle it */
|
||||
PDO::MYSQL_ATTR_DIRECT_QUERY => 1,
|
||||
PDO::MYSQL_ATTR_DIRECT_QUERY => true,
|
||||
PDO::MYSQL_ATTR_INIT_COMMAND => '',
|
||||
];
|
||||
|
||||
@ -151,8 +151,8 @@ MySQLPDOTest::skip();
|
||||
set_option_and_check(24, PDO::MYSQL_ATTR_INIT_COMMAND, '', 'PDO::MYSQL_ATTR_INIT_COMMAND');
|
||||
set_option_and_check(25, PDO::MYSQL_ATTR_INIT_COMMAND, 'INSERT INTO nonexistent(invalid) VALUES (1)', 'PDO::MYSQL_ATTR_INIT_COMMAND');
|
||||
|
||||
set_option_and_check(33, PDO::MYSQL_ATTR_DIRECT_QUERY, 1, 'PDO::MYSQL_ATTR_DIRECT_QUERY');
|
||||
set_option_and_check(34, PDO::MYSQL_ATTR_DIRECT_QUERY, 0, 'PDO::MYSQL_ATTR_DIRECT_QUERY');
|
||||
set_option_and_check(33, PDO::MYSQL_ATTR_DIRECT_QUERY, true, 'PDO::MYSQL_ATTR_DIRECT_QUERY');
|
||||
set_option_and_check(34, PDO::MYSQL_ATTR_DIRECT_QUERY, false, 'PDO::MYSQL_ATTR_DIRECT_QUERY');
|
||||
|
||||
if (defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) {
|
||||
set_option_and_check(35, PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY, null, 'PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY');
|
||||
|
@ -13,7 +13,7 @@ MySQLPDOTest::skip();
|
||||
$db = MySQLPDOTest::factory();
|
||||
|
||||
// autocommit should be on by default
|
||||
if (1 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
if (true !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
printf("[001] Expecting int/1 got %s\n", var_export($tmp, true));
|
||||
|
||||
// lets see if the server agrees to that
|
||||
@ -33,7 +33,7 @@ MySQLPDOTest::skip();
|
||||
if (!$db->query('SET autocommit = 1'))
|
||||
printf("[005] Cannot turn on server autocommit mode, %s\n", var_export($db->errorInfo(), true));
|
||||
|
||||
if (0 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
if (false !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
printf("[006] Expecting int/0 got %s\n", var_export($tmp, true));
|
||||
|
||||
// off -> on
|
||||
@ -47,7 +47,7 @@ MySQLPDOTest::skip();
|
||||
if (!$row['_autocommit'])
|
||||
printf("[009] Server autocommit mode should be on, got '%s'\n", var_export($row['_autocommit']));
|
||||
|
||||
if (1 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
if (true !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
printf("[010] Expecting int/1 got %s\n", var_export($tmp, true));
|
||||
|
||||
$table = 'pdo_mysql_attr_autocommit';
|
||||
|
@ -15,12 +15,14 @@ MySQLPDOTest::skip();
|
||||
$table = 'pdo_mysql_attr_fetch_table_names';
|
||||
MySQLPDOTest::createTestTable($table, $db);
|
||||
|
||||
$db->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, 1);
|
||||
$db->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
|
||||
var_dump($db->getAttribute(PDO::ATTR_FETCH_TABLE_NAMES));
|
||||
$stmt = $db->query("SELECT label FROM {$table} LIMIT 1");
|
||||
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
$stmt->closeCursor();
|
||||
|
||||
$db->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, 0);
|
||||
$db->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, false);
|
||||
var_dump($db->getAttribute(PDO::ATTR_FETCH_TABLE_NAMES));
|
||||
$stmt = $db->query("SELECT label FROM {$table} LIMIT 1");
|
||||
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
$stmt->closeCursor();
|
||||
@ -34,6 +36,7 @@ $db = MySQLPDOTest::factory();
|
||||
$db->query('DROP TABLE IF EXISTS pdo_mysql_attr_fetch_table_names');
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
@ -41,6 +44,7 @@ array(1) {
|
||||
string(1) "a"
|
||||
}
|
||||
}
|
||||
bool(false)
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
|
@ -16,14 +16,14 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
|
||||
MySQLPDOTest::createTestTable($table, $db, MySQLPDOTest::detect_transactional_mysql_engine($db));
|
||||
|
||||
if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[001] Autocommit should be on by default\n");
|
||||
|
||||
if (false == $db->beginTransaction())
|
||||
printf("[002] Cannot start a transaction, [%s] [%s]\n",
|
||||
$db->errorCode(), implode(' ', $db->errorInfo()));
|
||||
|
||||
if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[003] Autocommit should be on by default, beginTransaction() shall not impact it\n");
|
||||
|
||||
if (0 == $db->exec("DELETE FROM {$table}"))
|
||||
@ -50,7 +50,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
if (!$db->commit())
|
||||
printf("[008] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo()));
|
||||
|
||||
if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[009] Autocommit should be on after commit()\n");
|
||||
|
||||
if (!($stmt = $db->query(sprintf('SELECT id, label FROM %s WHERE id = %d', $table, $row['id']))))
|
||||
@ -91,7 +91,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
if (!$db->rollback())
|
||||
printf("[018] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo()));
|
||||
|
||||
if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[019] Autocommit should be on after rollback\n");
|
||||
|
||||
if (!($stmt = $db->query(sprintf('SELECT id, label FROM %s WHERE id = %d', $table, $row['id']))))
|
||||
@ -132,7 +132,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
|
||||
// Turn off autocommit using a server variable
|
||||
$db->exec('SET @@autocommit = 0');
|
||||
if (1 === $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true === $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[028] I'm confused, how can autocommit be on? Didn't I say I want to manually control transactions?\n");
|
||||
|
||||
if (!$db->beginTransaction())
|
||||
@ -155,7 +155,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
printf("[031] Cannot start a transaction, [%s] [%s]\n",
|
||||
$db->errorCode(), implode(' ', $db->errorInfo()));
|
||||
|
||||
if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
if (true !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT))
|
||||
printf("[032] Autocommit should be on my default, beginTransaction() should not change that\n");
|
||||
|
||||
if (0 == $db->exec("DELETE FROM {$table}"))
|
||||
|
@ -35,7 +35,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
|
||||
// pdo_transaction_transitions should check this as well...
|
||||
// ... just to be sure the most basic stuff really works we check it again...
|
||||
if (1 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
if (true !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT)))
|
||||
printf("[003] According to the manual we should be back to autocommit mode, got %s/%s\n",
|
||||
gettype($tmp), var_export($tmp, true));
|
||||
|
||||
|
@ -43,7 +43,7 @@ MySQLPDOTest::skipNotTransactionalEngine();
|
||||
return true;
|
||||
}
|
||||
|
||||
set_and_get(1, $db, PDO::ATTR_AUTOCOMMIT, 1);
|
||||
set_and_get(1, $db, PDO::ATTR_AUTOCOMMIT, true);
|
||||
/*
|
||||
set_and_get(2, $db, PDO::ATTR_AUTOCOMMIT, 0);
|
||||
set_and_get(3, $db, PDO::ATTR_AUTOCOMMIT, -1);
|
||||
|
@ -93,8 +93,8 @@ $db->exec('DROP TABLE IF EXISTS pdo_mysql_rollback');
|
||||
$db->exec('DROP TABLE IF EXISTS pdo_mysql_rollback_2');
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(0)
|
||||
int(1)
|
||||
int(0)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
done!
|
||||
|
@ -384,7 +384,7 @@ static int odbc_handle_get_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||
case PDO_ATTR_CONNECTION_STATUS:
|
||||
break;
|
||||
case PDO_ODBC_ATTR_ASSUME_UTF8:
|
||||
ZVAL_BOOL(val, H->assume_utf8 ? 1 : 0);
|
||||
ZVAL_BOOL(val, H->assume_utf8);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
@ -95,6 +95,6 @@ array(1) {
|
||||
ERR
|
||||
ERR
|
||||
string(5) "pgsql"
|
||||
ERR
|
||||
bool(true)
|
||||
ERR
|
||||
int(4)
|
||||
|
Loading…
Reference in New Issue
Block a user