1--TEST--
2mysqli_stmt_attr_set() - mysqlnd does not check for invalid codes
3--EXTENSIONS--
4mysqli
5--SKIPIF--
6<?php
7require_once 'skipifconnectfailure.inc';
8?>
9--FILE--
10<?php
11    require 'table.inc';
12
13    $stmt = mysqli_stmt_init($link);
14    try {
15        mysqli_stmt_attr_set($stmt, 0, 0);
16    } catch (\Throwable $e) {
17        echo get_class($e) . ': ' . $e->getMessage() . PHP_EOL;
18    }
19
20    $stmt->prepare("SELECT * FROM test");
21    // Invalid Attribute (2nd argument)
22    try {
23        mysqli_stmt_attr_set($stmt, -1, 0);
24    } catch (\ValueError $e) {
25        echo $e->getMessage() . \PHP_EOL;
26    }
27    // Invalid mode for MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
28    try {
29        $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, -1);
30    } catch (\ValueError $e) {
31        echo $e->getMessage() . \PHP_EOL;
32    }
33    $stmt->close();
34
35    //
36    // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
37    //
38    // expecting max_length not to be set and be 0 in all cases
39    $stmt = mysqli_stmt_init($link);
40    $stmt->prepare("SELECT label FROM test");
41    $stmt->execute();
42    $stmt->store_result();
43    $res = $stmt->result_metadata();
44    $fields = $res->fetch_fields();
45    foreach ($fields as $meta) {
46        if ($meta->max_length !== 0)
47            printf("[007] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
48    }
49    $res->close();
50    $stmt->close();
51
52    // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH is no longer supported, expect no change in behavior.
53    $stmt = mysqli_stmt_init($link);
54    $stmt->prepare("SELECT label FROM test");
55    var_dump($stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1));
56    $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
57    if ($res !== 1)
58        printf("[007.1] max_length should be 1, got %s\n", $res);
59    $stmt->execute();
60    $stmt->store_result();
61    $res = $stmt->result_metadata();
62    $fields = $res->fetch_fields();
63    foreach ($fields as $meta) {
64        if ($meta->max_length !== 0)
65            printf("[008] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
66    }
67    $res->close();
68    $stmt->close();
69
70    // expecting max_length not to be set
71    $stmt = mysqli_stmt_init($link);
72    $stmt->prepare("SELECT label FROM test");
73    $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 0);
74    $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
75    if ($res !== 0)
76        printf("[008.1] max_length should be 0, got %s\n", $res);
77    $stmt->execute();
78    $stmt->store_result();
79    $res = $stmt->result_metadata();
80    $fields = $res->fetch_fields();
81    foreach ($fields as $meta) {
82        if ($meta->max_length !== 0)
83            printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
84    }
85    $res->close();
86    $stmt->close();
87
88    //
89    // Cursors
90    //
91
92
93    $stmt = mysqli_stmt_init($link);
94    $stmt->prepare("SELECT id, label FROM test");
95
96    // Invalid cursor type
97    try {
98        $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, -1);
99    } catch (\ValueError $e) {
100        echo $e->getMessage() . \PHP_EOL;
101    }
102
103    if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
104        printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
105
106    if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
107        printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
108
109    $stmt->close();
110
111    $stmt = mysqli_stmt_init($link);
112    $stmt->prepare("SELECT id, label FROM test");
113    $stmt->execute();
114    $id = $label = NULL;
115    $stmt->bind_result($id, $label);
116    $results = array();
117    while ($stmt->fetch())
118        $results[$id] = $label;
119    $stmt->close();
120    if (empty($results))
121        printf("[015] Results should not be empty, subsequent tests will probably fail!\n");
122
123    $stmt = mysqli_stmt_init($link);
124    $stmt->prepare("SELECT id, label FROM test");
125    if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
126        printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
127    $stmt->execute();
128    $id = $label = NULL;
129    $stmt->bind_result($id, $label);
130    $results2 = array();
131    while ($stmt->fetch())
132        $results2[$id] = $label;
133    $stmt->close();
134    if ($results != $results2) {
135        printf("[017] Results should not differ. Dumping both result sets.\n");
136        var_dump($results);
137        var_dump($results2);
138    }
139
140    $stmt = mysqli_stmt_init($link);
141    $stmt->prepare("SELECT id, label FROM test");
142    if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
143        printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
144    $stmt->execute();
145    $id = $label = NULL;
146    $stmt->bind_result($id, $label);
147    $results2 = array();
148    while ($stmt->fetch())
149        $results2[$id] = $label;
150    $stmt->close();
151    if ($results != $results2) {
152        printf("[019] Results should not differ. Dumping both result sets.\n");
153        var_dump($results);
154        var_dump($results2);
155    }
156
157    mysqli_close($link);
158    print "done!";
159?>
160--CLEAN--
161<?php
162    require_once 'clean_table.inc';
163?>
164--EXPECT--
165Error: mysqli_stmt object is not fully initialized
166mysqli_stmt_attr_set(): Argument #2 ($attribute) must be either MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH or MYSQLI_STMT_ATTR_CURSOR_TYPE
167mysqli_stmt::attr_set(): Argument #2 ($value) must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
168bool(true)
169mysqli_stmt::attr_set(): Argument #2 ($value) must be one of the MYSQLI_CURSOR_TYPE_* constants for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE
170done!
171