Skip to content

Commit 933dccb

Browse files
SakiTakamachiGirgias
authored andcommitted
Fix GH-12767: Fixed to be able to change autocommit mode using setAttribute
Signed-off-by: Gina Peter Banyard <girgias@php.net>
1 parent abf4c11 commit 933dccb

File tree

4 files changed

+200
-0
lines changed

4 files changed

+200
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ PHP NEWS
2020
. Added workaround for SELinux mprotect execheap issue.
2121
See https://bugzilla.kernel.org/show_bug.cgi?id=218258. (ilutov)
2222

23+
- PDO_ODBC:
24+
. Fixed bug GH-12767 (Unable to turn on autocommit mode with setAttribute()).
25+
(SakiTakamachi)
26+
2327
- PHPDBG:
2428
. Fixed bug GH-12962 (Double free of init_file in phpdbg_prompt.c). (nielsdos)
2529

ext/pdo_odbc/odbc_driver.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,30 @@ static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
344344
}
345345
H->assume_utf8 = bval;
346346
return true;
347+
case PDO_ATTR_AUTOCOMMIT:
348+
if (!pdo_get_bool_param(&bval, val)) {
349+
return false;
350+
}
351+
if (dbh->in_txn) {
352+
pdo_raise_impl_error(dbh, NULL, "HY000", "Cannot change autocommit mode while a transaction is already open");
353+
return false;
354+
}
355+
if (dbh->auto_commit ^ bval) {
356+
dbh->auto_commit = bval;
357+
RETCODE rc = SQLSetConnectAttr(
358+
H->dbc,
359+
SQL_ATTR_AUTOCOMMIT,
360+
dbh->auto_commit ? (SQLPOINTER) SQL_AUTOCOMMIT_ON : (SQLPOINTER) SQL_AUTOCOMMIT_OFF,
361+
SQL_IS_INTEGER
362+
);
363+
if (rc != SQL_SUCCESS) {
364+
pdo_odbc_drv_error(
365+
dbh->auto_commit ? "SQLSetConnectAttr AUTOCOMMIT = ON" : "SQLSetConnectAttr AUTOCOMMIT = OFF"
366+
);
367+
return false;
368+
}
369+
}
370+
return true;
347371
default:
348372
strcpy(H->einfo.last_err_msg, "Unknown Attribute");
349373
H->einfo.what = "setAttribute";

ext/pdo_odbc/tests/autocommit.phpt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
PDO ODBC auto commit mode
3+
--EXTENSIONS--
4+
pdo_odbc
5+
--SKIPIF--
6+
<?php
7+
require 'ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
?>
10+
--XLEAK--
11+
A bug in msodbcsql causes a memory leak when reconnecting after closing. See GH-12306
12+
--FILE--
13+
<?php
14+
require 'ext/pdo/tests/pdo_test.inc';
15+
16+
$table = 'autocommit_pdo_odbc';
17+
18+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
19+
$db->exec("CREATE TABLE {$table} (id INT, name VARCHAR(255))");
20+
unset($db);
21+
22+
$db = new PDO(getenv('PDOTEST_DSN'), getenv('PDOTEST_USER'), getenv('PDOTEST_PASS'), [
23+
PDO::ATTR_AUTOCOMMIT => 0,
24+
]);
25+
26+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
27+
$db->query("INSERT INTO {$table} (id, name) VALUES (1, 'test')");
28+
unset($db);
29+
30+
$db = new PDO(getenv('PDOTEST_DSN'), getenv('PDOTEST_USER'), getenv('PDOTEST_PASS'));
31+
32+
$r = $db->query("SELECT * FROM {$table}");
33+
var_dump($r->fetchAll(PDO::FETCH_ASSOC));
34+
35+
echo "done!";
36+
?>
37+
--CLEAN--
38+
<?php
39+
require 'ext/pdo/tests/pdo_test.inc';
40+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
41+
$db->exec("DROP TABLE IF EXISTS autocommit_pdo_odbc");
42+
?>
43+
--EXPECT--
44+
array(1) {
45+
[0]=>
46+
array(2) {
47+
["id"]=>
48+
string(1) "1"
49+
["name"]=>
50+
string(4) "test"
51+
}
52+
}
53+
done!
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
--TEST--
2+
PDO ODBC auto commit mode
3+
--EXTENSIONS--
4+
pdo_odbc
5+
--SKIPIF--
6+
<?php
7+
require 'ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
?>
10+
--FILE--
11+
<?php
12+
require 'ext/pdo/tests/pdo_test.inc';
13+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
14+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
15+
16+
echo "========== not in transaction ==========\n";
17+
18+
echo "auto commit ON from ON\n";
19+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
20+
echo "Success\n\n";
21+
22+
echo "auto commit OFF from ON\n";
23+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
24+
echo "Success\n\n";
25+
26+
echo "auto commit OFF from OFF\n";
27+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
28+
echo "Success\n\n";
29+
30+
echo "auto commit ON from OFF\n";
31+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
32+
echo "Success\n\n";
33+
34+
echo "========== in transaction ==========\n";
35+
36+
echo "begin transaction\n";
37+
$db->beginTransaction();
38+
echo "\n";
39+
40+
echo "auto commit ON from ON, expect error\n";
41+
try {
42+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
43+
} catch (PDOException $e) {
44+
echo $e->getMessage()."\n\n";
45+
}
46+
47+
echo "auto commit OFF from ON, expect error\n";
48+
try {
49+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
50+
} catch (PDOException $e) {
51+
echo $e->getMessage()."\n\n";
52+
}
53+
54+
echo "end transaction\n";
55+
$db->rollback();
56+
57+
echo "auto commit OFF\n";
58+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
59+
60+
echo "begin transaction\n";
61+
$db->beginTransaction();
62+
echo "\n";
63+
64+
echo "auto commit ON from OFF, expect error\n";
65+
try {
66+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
67+
} catch (PDOException $e) {
68+
echo $e->getMessage()."\n\n";
69+
}
70+
71+
echo "auto commit OFF from OFF, expect error\n";
72+
try {
73+
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
74+
} catch (PDOException $e) {
75+
echo $e->getMessage()."\n\n";
76+
}
77+
78+
echo "end transaction\n";
79+
$db->rollback();
80+
echo "\n";
81+
82+
echo "done!";
83+
?>
84+
--EXPECT--
85+
========== not in transaction ==========
86+
auto commit ON from ON
87+
Success
88+
89+
auto commit OFF from ON
90+
Success
91+
92+
auto commit OFF from OFF
93+
Success
94+
95+
auto commit ON from OFF
96+
Success
97+
98+
========== in transaction ==========
99+
begin transaction
100+
101+
auto commit ON from ON, expect error
102+
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
103+
104+
auto commit OFF from ON, expect error
105+
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
106+
107+
end transaction
108+
auto commit OFF
109+
begin transaction
110+
111+
auto commit ON from OFF, expect error
112+
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
113+
114+
auto commit OFF from OFF, expect error
115+
SQLSTATE[HY000]: General error: Cannot change autocommit mode while a transaction is already open
116+
117+
end transaction
118+
119+
done!

0 commit comments

Comments
 (0)