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