1--TEST--
2PDO_Firebird: transaction access mode
3--EXTENSIONS--
4pdo_firebird
5--SKIPIF--
6<?php require('skipif.inc'); ?>
7--XLEAK--
8A bug in firebird causes a memory leak when calling `isc_attach_database()`.
9See https://github.com/FirebirdSQL/firebird/issues/7849
10--FILE--
11<?php
12
13require("testdb.inc");
14$dbh = getDbConnection();
15unset($dbh);
16
17$table = 'transaction_access_mode';
18
19$values = [
20    ['val' => true, 'label' => 'writable'],
21    ['val' => false, 'label' => 'readonly'],
22];
23
24echo "========== Set attr in construct ==========\n";
25
26foreach ($values as $value) {
27    $dbh = new PDO(
28        PDO_FIREBIRD_TEST_DSN,
29        PDO_FIREBIRD_TEST_USER,
30        PDO_FIREBIRD_TEST_PASS,
31        [
32            PDO::FB_WRITABLE_TRANSACTION => $value['val'],
33        ],
34    );
35
36    if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === $value['val']) {
37        echo "OK: {$value['label']}\n";
38    } else {
39        echo "NG: {$value['label']}\n";
40    }
41
42    unset($dbh);
43}
44
45echo "\n";
46echo "========== Set attr in setAttribute and behavior check ==========\n";
47
48$dbh = new PDO(
49    PDO_FIREBIRD_TEST_DSN,
50    PDO_FIREBIRD_TEST_USER,
51    PDO_FIREBIRD_TEST_PASS,
52);
53
54$dbh->query("CREATE TABLE {$table} (val INT)");
55
56echo "writable\n";
57var_dump($dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, true));
58if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === true) {
59    echo "OK: writable\n";
60} else {
61    echo "NG: writable\n";
62}
63$dbh->query("INSERT INTO {$table} VALUES (12)");
64$r = $dbh->query("SELECT * FROM {$table}");
65var_dump($r->fetchAll());
66
67echo "\n";
68
69echo "readonly\n";
70var_dump($dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, false));
71if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === false) {
72    echo "OK: readonly\n";
73} else {
74    echo "NG: readonly\n";
75}
76try {
77    $dbh->query("INSERT INTO {$table} VALUES (19)");
78} catch (PDOException $e) {
79    echo $e->getMessage()."\n";
80}
81$r = $dbh->query("SELECT * FROM {$table}");
82var_dump($r->fetchAll());
83
84echo "\n";
85echo "========== Set attr in setAttribute while transaction ==========\n";
86
87$dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, true);
88$dbh->beginTransaction();
89
90echo "writable to writable\n";
91try {
92    $dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, true);
93} catch (PDOException $e) {
94    echo $e->getMessage()."\n";
95}
96var_dump($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION));
97echo "\n";
98
99echo "writable to readonly\n";
100try {
101    $dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, false);
102} catch (PDOException $e) {
103    echo $e->getMessage()."\n";
104}
105var_dump($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION));
106echo "\n";
107
108$dbh->commit();
109$dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, false);
110$dbh->beginTransaction();
111
112echo "readonly to writable\n";
113try {
114    $dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, true);
115} catch (PDOException $e) {
116    echo $e->getMessage()."\n";
117}
118var_dump($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION));
119echo "\n";
120
121echo "readonly to readonly\n";
122try {
123    $dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, false);
124} catch (PDOException $e) {
125    echo $e->getMessage()."\n";
126}
127var_dump($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION));
128
129unset($dbh);
130?>
131--CLEAN--
132<?php
133require 'testdb.inc';
134$dbh = getDbConnection();
135@$dbh->exec('DROP TABLE transaction_access_mode');
136unset($dbh);
137?>
138--EXPECT--
139========== Set attr in construct ==========
140OK: writable
141OK: readonly
142
143========== Set attr in setAttribute and behavior check ==========
144writable
145bool(true)
146OK: writable
147array(1) {
148  [0]=>
149  array(2) {
150    ["VAL"]=>
151    int(12)
152    [0]=>
153    int(12)
154  }
155}
156
157readonly
158bool(true)
159OK: readonly
160SQLSTATE[42000]: Syntax error or access violation: -817 attempted update during read-only transaction
161array(1) {
162  [0]=>
163  array(2) {
164    ["VAL"]=>
165    int(12)
166    [0]=>
167    int(12)
168  }
169}
170
171========== Set attr in setAttribute while transaction ==========
172writable to writable
173SQLSTATE[HY000]: General error: Cannot change access mode while a transaction is already open
174bool(true)
175
176writable to readonly
177SQLSTATE[HY000]: General error: Cannot change access mode while a transaction is already open
178bool(true)
179
180readonly to writable
181SQLSTATE[HY000]: General error: Cannot change access mode while a transaction is already open
182bool(false)
183
184readonly to readonly
185SQLSTATE[HY000]: General error: Cannot change access mode while a transaction is already open
186bool(false)
187