xref: /PHP-8.3/ext/mysqli/tests/bug79375.phpt (revision a21edc52)
1--TEST--
2Bug #79375: mysqli_store_result does not report error from lock wait timeout
3--EXTENSIONS--
4mysqli
5--SKIPIF--
6<?php
7if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
8require_once 'skipifconnectfailure.inc';
9if (!defined('MYSQLI_STORE_RESULT_COPY_DATA')) die('skip requires mysqlnd');
10?>
11--FILE--
12<?php
13
14require_once 'connect.inc';
15mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
16$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
17$mysqli2 = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
18
19$mysqli->query('DROP TABLE IF EXISTS test');
20$mysqli->query('CREATE TABLE test (first int) ENGINE = InnoDB');
21$mysqli->query('INSERT INTO test VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)');
22
23function testStmtStoreResult(mysqli $mysqli, string $name) {
24    $mysqli->query("SET innodb_lock_wait_timeout = 1");
25    $mysqli->query("START TRANSACTION");
26    $query = "SELECT first FROM test WHERE first = 1 FOR UPDATE";
27    echo "Running query on $name\n";
28    $stmt = $mysqli->prepare($query);
29    $stmt->execute();
30    try {
31        $stmt->store_result();
32        echo "Got {$stmt->num_rows} for $name\n";
33    } catch(mysqli_sql_exception $e) {
34        echo $e->getMessage()."\n";
35    }
36}
37function testStmtGetResult(mysqli $mysqli, string $name) {
38    $mysqli->query("SET innodb_lock_wait_timeout = 1");
39    $mysqli->query("START TRANSACTION");
40    $query = "SELECT first FROM test WHERE first = 1 FOR UPDATE";
41    echo "Running query on $name\n";
42    $stmt = $mysqli->prepare($query);
43    $stmt->execute();
44    try {
45        $res = $stmt->get_result();
46        echo "Got {$res->num_rows} for $name\n";
47    } catch(mysqli_sql_exception $e) {
48        echo $e->getMessage()."\n";
49    }
50}
51function testNormalQuery(mysqli $mysqli, string $name) {
52    $mysqli->query("SET innodb_lock_wait_timeout = 1");
53    $mysqli->query("START TRANSACTION");
54    $query = "SELECT first FROM test WHERE first = 1 FOR UPDATE";
55    echo "Running query on $name\n";
56    try {
57        $res = $mysqli->query($query);
58        echo "Got {$res->num_rows} for $name\n";
59    } catch(mysqli_sql_exception $e) {
60        echo $e->getMessage()."\n";
61    }
62}
63function testStmtUseResult(mysqli $mysqli, string $name) {
64    $mysqli->query("SET innodb_lock_wait_timeout = 1");
65    $mysqli->query("START TRANSACTION");
66    $query = "SELECT first FROM test WHERE first = 1 FOR UPDATE";
67    echo "Running query on $name\n";
68    $stmt = $mysqli->prepare($query);
69    $stmt->execute();
70    try {
71        $stmt->fetch(); // should throw an error
72        $stmt->fetch();
73        echo "Got {$stmt->num_rows} for $name\n";
74    } catch (mysqli_sql_exception $e) {
75        echo $e->getMessage()."\n";
76    }
77}
78function testResultFetchRow(mysqli $mysqli, string $name) {
79    $mysqli->query("SET innodb_lock_wait_timeout = 1");
80    $mysqli->query("START TRANSACTION");
81    $query = "SELECT first FROM test WHERE first = 1 FOR UPDATE";
82    echo "Running query on $name\n";
83    $res = $mysqli->query($query, MYSQLI_USE_RESULT);
84    try {
85        $res->fetch_row();
86        $res->fetch_row();
87        echo "Got {$res->num_rows} for $name\n";
88    } catch(mysqli_sql_exception $e) {
89        echo $e->getMessage()."\n";
90    }
91}
92
93testStmtStoreResult($mysqli, 'first connection');
94testStmtStoreResult($mysqli2, 'second connection');
95
96$mysqli->close();
97$mysqli2->close();
98
99echo "\n";
100//  try it again for get_result
101$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
102$mysqli2 = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
103
104testStmtGetResult($mysqli, 'first connection');
105testStmtGetResult($mysqli2, 'second connection');
106
107$mysqli->close();
108$mysqli2->close();
109
110echo "\n";
111//  try it again with unprepared query
112$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
113$mysqli2 = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
114
115testNormalQuery($mysqli, 'first connection');
116testNormalQuery($mysqli2, 'second connection');
117
118$mysqli->close();
119$mysqli2->close();
120
121echo "\n";
122//  try it again with unprepared query
123$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
124$mysqli2 = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
125
126testStmtUseResult($mysqli, 'first connection');
127testStmtUseResult($mysqli2, 'second connection');
128
129$mysqli->close();
130$mysqli2->close();
131
132echo "\n";
133//  try it again using fetch_row on a result object
134$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
135$mysqli2 = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
136
137testResultFetchRow($mysqli, 'first connection');
138testResultFetchRow($mysqli2, 'second connection');
139
140$mysqli->close();
141$mysqli2->close();
142
143?>
144--CLEAN--
145<?php
146    require_once 'clean_table.inc';
147?>
148--EXPECTF--
149Running query on first connection
150Got %d for first connection
151Running query on second connection
152Lock wait timeout exceeded; try restarting transaction
153
154Running query on first connection
155Got %d for first connection
156Running query on second connection
157Lock wait timeout exceeded; try restarting transaction
158
159Running query on first connection
160Got %d for first connection
161Running query on second connection
162Lock wait timeout exceeded; try restarting transaction
163
164Running query on first connection
165Got %d for first connection
166Running query on second connection
167Lock wait timeout exceeded; try restarting transaction
168
169Running query on first connection
170Got 1 for first connection
171Running query on second connection
172Lock wait timeout exceeded; try restarting transaction
173