mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: add PDO::ATTR_AUTOCOMMIT to getAttribute Fix GH-12767: Fixed to be able to change autocommit mode using setAttribute
This commit is contained in:
commit
dcef7039e8
4 changed files with 219 additions and 1 deletions
4
NEWS
4
NEWS
|
@ -28,6 +28,10 @@ PHP NEWS
|
|||
. Added workaround for SELinux mprotect execheap issue.
|
||||
See https://bugzilla.kernel.org/show_bug.cgi?id=218258. (ilutov)
|
||||
|
||||
- PDO_ODBC:
|
||||
. Fixed bug GH-12767 (Unable to turn on autocommit mode with setAttribute()).
|
||||
(SakiTakamachi)
|
||||
|
||||
- PHPDBG:
|
||||
. Fixed bug GH-12962 (Double free of init_file in phpdbg_prompt.c). (nielsdos)
|
||||
|
||||
|
|
|
@ -344,6 +344,30 @@ static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
|||
}
|
||||
H->assume_utf8 = bval;
|
||||
return true;
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
if (!pdo_get_bool_param(&bval, val)) {
|
||||
return false;
|
||||
}
|
||||
if (dbh->in_txn) {
|
||||
pdo_raise_impl_error(dbh, NULL, "HY000", "Cannot change autocommit mode while a transaction is already open");
|
||||
return false;
|
||||
}
|
||||
if (dbh->auto_commit ^ bval) {
|
||||
dbh->auto_commit = bval;
|
||||
RETCODE rc = SQLSetConnectAttr(
|
||||
H->dbc,
|
||||
SQL_ATTR_AUTOCOMMIT,
|
||||
dbh->auto_commit ? (SQLPOINTER) SQL_AUTOCOMMIT_ON : (SQLPOINTER) SQL_AUTOCOMMIT_OFF,
|
||||
SQL_IS_INTEGER
|
||||
);
|
||||
if (rc != SQL_SUCCESS) {
|
||||
pdo_odbc_drv_error(
|
||||
dbh->auto_commit ? "SQLSetConnectAttr AUTOCOMMIT = ON" : "SQLSetConnectAttr AUTOCOMMIT = OFF"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
strcpy(H->einfo.last_err_msg, "Unknown Attribute");
|
||||
H->einfo.what = "setAttribute";
|
||||
|
@ -386,7 +410,9 @@ static int odbc_handle_get_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
|||
case PDO_ODBC_ATTR_ASSUME_UTF8:
|
||||
ZVAL_BOOL(val, H->assume_utf8 ? 1 : 0);
|
||||
return 1;
|
||||
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
ZVAL_BOOL(val, dbh->auto_commit);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
53
ext/pdo_odbc/tests/autocommit.phpt
Normal file
53
ext/pdo_odbc/tests/autocommit.phpt
Normal file
|
@ -0,0 +1,53 @@
|
|||
--TEST--
|
||||
PDO ODBC auto commit mode
|
||||
--EXTENSIONS--
|
||||
pdo_odbc
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--XLEAK--
|
||||
A bug in msodbcsql causes a memory leak when reconnecting after closing. See GH-12306
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
|
||||
$table = 'autocommit_pdo_odbc';
|
||||
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("CREATE TABLE {$table} (id INT, name VARCHAR(255))");
|
||||
unset($db);
|
||||
|
||||
$db = new PDO(getenv('PDOTEST_DSN'), getenv('PDOTEST_USER'), getenv('PDOTEST_PASS'), [
|
||||
PDO::ATTR_AUTOCOMMIT => 0,
|
||||
]);
|
||||
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
|
||||
$db->query("INSERT INTO {$table} (id, name) VALUES (1, 'test')");
|
||||
unset($db);
|
||||
|
||||
$db = new PDO(getenv('PDOTEST_DSN'), getenv('PDOTEST_USER'), getenv('PDOTEST_PASS'));
|
||||
|
||||
$r = $db->query("SELECT * FROM {$table}");
|
||||
var_dump($r->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
||||
echo "done!";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("DROP TABLE IF EXISTS autocommit_pdo_odbc");
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["id"]=>
|
||||
string(1) "1"
|
||||
["name"]=>
|
||||
string(4) "test"
|
||||
}
|
||||
}
|
||||
done!
|
135
ext/pdo_odbc/tests/autocommit_change_mode.phpt
Normal file
135
ext/pdo_odbc/tests/autocommit_change_mode.phpt
Normal file
|
@ -0,0 +1,135 @@
|
|||
--TEST--
|
||||
PDO ODBC auto commit mode
|
||||
--EXTENSIONS--
|
||||
pdo_odbc
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
echo "========== not in transaction ==========\n";
|
||||
|
||||
echo "auto commit ON from ON\n";
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo "Success\n\n";
|
||||
|
||||
echo "auto commit OFF from ON\n";
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo "Success\n\n";
|
||||
|
||||
echo "auto commit OFF from OFF\n";
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo "Success\n\n";
|
||||
|
||||
echo "auto commit ON from OFF\n";
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo "Success\n\n";
|
||||
|
||||
echo "========== in transaction ==========\n";
|
||||
|
||||
echo "begin transaction\n";
|
||||
$db->beginTransaction();
|
||||
echo "\n";
|
||||
|
||||
echo "auto commit ON from ON, expect error\n";
|
||||
try {
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
} catch (PDOException $e) {
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "auto commit OFF from ON, expect error\n";
|
||||
try {
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
} catch (PDOException $e) {
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "end transaction\n";
|
||||
$db->rollback();
|
||||
|
||||
echo "auto commit OFF\n";
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
|
||||
echo "begin transaction\n";
|
||||
$db->beginTransaction();
|
||||
echo "\n";
|
||||
|
||||
echo "auto commit ON from OFF, expect error\n";
|
||||
try {
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
} catch (PDOException $e) {
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "auto commit OFF from OFF, expect error\n";
|
||||
try {
|
||||
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
} catch (PDOException $e) {
|
||||
var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "end transaction\n";
|
||||
$db->rollback();
|
||||
echo "\n";
|
||||
|
||||
echo "done!";
|
||||
?>
|
||||
--EXPECT--
|
||||
========== not in transaction ==========
|
||||
auto commit ON from ON
|
||||
bool(true)
|
||||
Success
|
||||
|
||||
auto commit OFF from ON
|
||||
bool(false)
|
||||
Success
|
||||
|
||||
auto commit OFF from OFF
|
||||
bool(false)
|
||||
Success
|
||||
|
||||
auto commit ON from OFF
|
||||
bool(true)
|
||||
Success
|
||||
|
||||
========== in transaction ==========
|
||||
begin transaction
|
||||
|
||||
auto commit ON from ON, expect error
|
||||
bool(true)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
auto commit OFF from ON, expect error
|
||||
bool(true)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
end transaction
|
||||
auto commit OFF
|
||||
begin transaction
|
||||
|
||||
auto commit ON from OFF, expect error
|
||||
bool(false)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
auto commit OFF from OFF, expect error
|
||||
bool(false)
|
||||
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
|
||||
|
||||
end transaction
|
||||
|
||||
done!
|
Loading…
Add table
Add a link
Reference in a new issue