xref: /PHP-8.3/ext/pdo_pgsql/tests/bug_33876.phpt (revision 4f84b159)
1--TEST--
2PDO PgSQL Bug #33876 (PDO misquotes/miscasts bool(false))
3--EXTENSIONS--
4pdo
5pdo_pgsql
6--SKIPIF--
7<?php
8require __DIR__ . '/config.inc';
9require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
10PDOTest::skip();
11?>
12--FILE--
13<?php
14require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
15$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
16$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
17
18$db->exec("SET LC_MESSAGES='C'");
19$db->exec('CREATE TABLE b33876 (foo varchar(5) NOT NULL, bar bool NOT NULL)');
20$db->exec("INSERT INTO b33876 VALUES('false','f')");
21$db->exec("INSERT INTO b33876 VALUES('true', 't')");
22
23$res = $db->prepare('SELECT foo from b33876 where bar = ?');
24
25# this is the portable approach to binding a bool
26$res->bindValue(1, false, PDO::PARAM_BOOL);
27if (!$res->execute())
28    print_r($res->errorInfo());
29else
30    print_r($res->fetchAll(PDO::FETCH_ASSOC));
31
32# this is the portable approach to binding a bool
33$res->bindValue(1, true, PDO::PARAM_BOOL);
34if (!$res->execute())
35    print_r($res->errorInfo());
36else
37    print_r($res->fetchAll(PDO::FETCH_ASSOC));
38
39
40# true gets cast to string (because the implied default is string)
41# true-as-string is 1, so this "works"
42if (!$res->execute(array(true)))
43    print_r($res->errorInfo());
44else
45    print_r($res->fetchAll(PDO::FETCH_ASSOC));
46
47# Expected to fail; unless told otherwise, PDO assumes string inputs
48# false -> "" as string, which pgsql doesn't like
49if (!$res->execute(array(false)))
50    print_r(normalizeErrorInfo($res->errorInfo()));
51else
52    print_r($res->fetchAll(PDO::FETCH_ASSOC));
53
54# And now using emulator prepares
55echo "EMUL\n";
56
57
58$res = $db->prepare('SELECT foo from b33876 where bar = ?', array(
59    PDO::ATTR_EMULATE_PREPARES => true));
60
61# this is the portable approach to binding a bool
62$res->bindValue(1, false, PDO::PARAM_BOOL);
63if (!$res->execute())
64    print_r($res->errorInfo());
65else
66    print_r($res->fetchAll(PDO::FETCH_ASSOC));
67
68# this is the portable approach to binding a bool
69$res->bindValue(1, true, PDO::PARAM_BOOL);
70if (!$res->execute())
71    print_r($res->errorInfo());
72else
73    print_r($res->fetchAll(PDO::FETCH_ASSOC));
74
75
76# true gets cast to string (because the implied default is string)
77# true-as-string is 1, so this "works"
78if (!$res->execute(array(true)))
79    print_r($res->errorInfo());
80else
81    print_r($res->fetchAll(PDO::FETCH_ASSOC));
82
83# Expected to fail; unless told otherwise, PDO assumes string inputs
84# false -> "" as string, which pgsql doesn't like
85if (!$res->execute(array(false))) {
86    print_r(normalizeErrorInfo($res->errorInfo()));
87} else {
88    print_r($res->fetchAll(PDO::FETCH_ASSOC));
89}
90
91function normalizeErrorInfo(array $err): array {
92    // Strip additional lines outputted by recent PgSQL versions
93    $err[2] = trim(current(explode("\n", $err[2])));
94    return $err;
95}
96
97?>
98--CLEAN--
99<?php
100require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
101$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
102$db->query('DROP TABLE IF EXISTS b33876 CASCADE');
103?>
104--EXPECTF--
105Array
106(
107    [0] => Array
108        (
109            [foo] => false
110        )
111
112)
113Array
114(
115    [0] => Array
116        (
117            [foo] => true
118        )
119
120)
121Array
122(
123    [0] => Array
124        (
125            [foo] => true
126        )
127
128)
129Array
130(
131    [0] => 22P02
132    [1] => 7
133    [2] => %s:  %sboolean%s
134)
135EMUL
136Array
137(
138    [0] => Array
139        (
140            [foo] => false
141        )
142
143)
144Array
145(
146    [0] => Array
147        (
148            [foo] => true
149        )
150
151)
152Array
153(
154    [0] => Array
155        (
156            [foo] => true
157        )
158
159)
160Array
161(
162    [0] => 22P02
163    [1] => 7
164    [2] => %s:  %sboolean%s
165)
166