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:
Gina Peter Banyard 2023-12-18 00:26:56 +00:00
commit dcef7039e8
No known key found for this signature in database
GPG key ID: 3306078E3194AEBD
4 changed files with 219 additions and 1 deletions

4
NEWS
View file

@ -28,6 +28,10 @@ PHP NEWS
. Added workaround for SELinux mprotect execheap issue. . Added workaround for SELinux mprotect execheap issue.
See https://bugzilla.kernel.org/show_bug.cgi?id=218258. (ilutov) 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: - PHPDBG:
. Fixed bug GH-12962 (Double free of init_file in phpdbg_prompt.c). (nielsdos) . Fixed bug GH-12962 (Double free of init_file in phpdbg_prompt.c). (nielsdos)

View file

@ -344,6 +344,30 @@ static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
} }
H->assume_utf8 = bval; H->assume_utf8 = bval;
return true; 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: default:
strcpy(H->einfo.last_err_msg, "Unknown Attribute"); strcpy(H->einfo.last_err_msg, "Unknown Attribute");
H->einfo.what = "setAttribute"; 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: case PDO_ODBC_ATTR_ASSUME_UTF8:
ZVAL_BOOL(val, H->assume_utf8 ? 1 : 0); ZVAL_BOOL(val, H->assume_utf8 ? 1 : 0);
return 1; return 1;
case PDO_ATTR_AUTOCOMMIT:
ZVAL_BOOL(val, dbh->auto_commit);
return 1;
} }
return 0; return 0;
} }

View 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!

View 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!