1--TEST--
2mysqli_stmt_execute() - bind in execute
3--EXTENSIONS--
4mysqli
5--SKIPIF--
6<?php
7require_once 'skipifconnectfailure.inc';
8?>
9--FILE--
10<?php
11require_once "connect.inc";
12
13require 'table.inc';
14
15mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
16
17// first, control case
18$id = 1;
19$abc = 'abc';
20$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
21$stmt->bind_param('sss', ...[&$abc, 42, $id]);
22$stmt->execute();
23assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
24$stmt = null;
25
26// 1. same as the control case, but skipping the middle-man (bind_param)
27$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
28$stmt->execute([&$abc, 42, $id]);
29assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
30$stmt = null;
31
32// 2. param number has to match - missing 1 parameter
33$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
34try {
35    $stmt->execute([&$abc, 42]);
36} catch (ValueError $e) {
37    echo '[001] '.$e->getMessage()."\n";
38}
39$stmt = null;
40
41// 3. Too many parameters
42$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
43try {
44    $stmt->execute([&$abc, null, $id, 24]);
45} catch (ValueError $e) {
46    echo '[002] '.$e->getMessage()."\n";
47}
48$stmt = null;
49
50// 4. param number has to match - missing all parameters
51$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
52try {
53    $stmt->execute([]);
54} catch (ValueError $e) {
55    echo '[003] '.$e->getMessage()."\n";
56}
57$stmt = null;
58
59// 5. param number has to match - missing argument to execute()
60$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
61try {
62    $stmt->execute();
63} catch (mysqli_sql_exception $e) {
64    echo '[004] '.$e->getMessage()."\n";
65}
66$stmt = null;
67
68// 6. wrong argument to execute()
69$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
70try {
71    $stmt->execute(42);
72} catch (TypeError $e) {
73    echo '[005] '.$e->getMessage()."\n";
74}
75$stmt = null;
76
77// 7. objects are not arrays and are not accepted
78$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
79try {
80    $stmt->execute((object)[&$abc, 42, $id]);
81} catch (TypeError $e) {
82    echo '[006] '.$e->getMessage()."\n";
83}
84$stmt = null;
85
86// 8. arrays by reference work too
87$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
88$arr = [&$abc, 42, $id];
89$arr2 = &$arr;
90$stmt->execute($arr2);
91assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
92$stmt = null;
93
94// 9. no placeholders in statement. nothing to bind in an empty array
95$stmt = $link->prepare('SELECT label FROM test WHERE id=1');
96$stmt->execute([]);
97assert($stmt->get_result()->fetch_assoc() === ['label'=>'a']);
98$stmt = null;
99
100// 10. once bound the values are persisted. Just like in PDO
101$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
102$stmt->execute(['abc', 42, $id]);
103assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
104$stmt->execute(); // no argument here. Values are already bound
105assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
106try {
107    $stmt->execute([]); // no params here. PDO doesn't throw an error, but mysqli does
108} catch (ValueError $e) {
109    echo '[007] '.$e->getMessage()."\n";
110}
111$stmt = null;
112
113// 11. mixing binding styles not possible. Also, NULL should stay NULL when bound as string
114$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
115$stmt->bind_param('sss', ...['abc', 42, null]);
116$stmt->execute([null, null, $id]);
117assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>null, 'num' => null]);
118$stmt = null;
119
120// 12. Only list arrays are allowed
121$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
122try {
123    $stmt->execute(['A'=>'abc', 2=>42, null=>$id]);
124} catch (ValueError $e) {
125    echo '[008] '.$e->getMessage()."\n";
126}
127$stmt = null;
128
129
130mysqli_close($link);
131?>
132--CLEAN--
133<?php
134require_once "clean_table.inc";
135?>
136--EXPECT--
137[001] mysqli_stmt::execute(): Argument #1 ($params) must consist of exactly 3 elements, 2 present
138[002] mysqli_stmt::execute(): Argument #1 ($params) must consist of exactly 3 elements, 4 present
139[003] mysqli_stmt::execute(): Argument #1 ($params) must consist of exactly 3 elements, 0 present
140[004] No data supplied for parameters in prepared statement
141[005] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, int given
142[006] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, stdClass given
143[007] mysqli_stmt::execute(): Argument #1 ($params) must consist of exactly 3 elements, 0 present
144[008] mysqli_stmt::execute(): Argument #1 ($params) must be a list array
145