Skip to content

Commit

Permalink
Fix GH-12767: Fixed to be able to change autocommit mode using setAtt…
Browse files Browse the repository at this point in the history
…ribute

Signed-off-by: Gina Peter Banyard <girgias@php.net>
  • Loading branch information
SakiTakamachi authored and Girgias committed Dec 18, 2023
1 parent abf4c11 commit 933dccb
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
4 changes: 4 additions & 0 deletions NEWS
Expand Up @@ -20,6 +20,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)

Expand Down
24 changes: 24 additions & 0 deletions ext/pdo_odbc/odbc_driver.c
Expand Up @@ -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";
Expand Down
53 changes: 53 additions & 0 deletions ext/pdo_odbc/tests/autocommit.phpt
@@ -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!
119 changes: 119 additions & 0 deletions ext/pdo_odbc/tests/autocommit_change_mode.phpt
@@ -0,0 +1,119 @@
--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);
echo "Success\n\n";

echo "auto commit OFF from ON\n";
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
echo "Success\n\n";

echo "auto commit OFF from OFF\n";
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
echo "Success\n\n";

echo "auto commit ON from OFF\n";
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
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) {
echo $e->getMessage()."\n\n";
}

echo "auto commit OFF from ON, expect error\n";
try {
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
} catch (PDOException $e) {
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) {
echo $e->getMessage()."\n\n";
}

echo "auto commit OFF from OFF, expect error\n";
try {
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
} catch (PDOException $e) {
echo $e->getMessage()."\n\n";
}

echo "end transaction\n";
$db->rollback();
echo "\n";

echo "done!";
?>
--EXPECT--
========== not in transaction ==========
auto commit ON from ON
Success

auto commit OFF from ON
Success

auto commit OFF from OFF
Success

auto commit ON from OFF
Success

========== in transaction ==========
begin transaction

auto commit ON from ON, expect error
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open

auto commit OFF from ON, expect error
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
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open

auto commit OFF from OFF, expect error
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open

end transaction

done!

0 comments on commit 933dccb

Please sign in to comment.