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 test (foo varchar(5) NOT NULL, bar bool NOT NULL)'); 20$db->exec("INSERT INTO test VALUES('false','f')"); 21$db->exec("INSERT INTO test VALUES('true', 't')"); 22 23$res = $db->prepare('SELECT foo from test 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 test 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--EXPECTF-- 99Array 100( 101 [0] => Array 102 ( 103 [foo] => false 104 ) 105 106) 107Array 108( 109 [0] => Array 110 ( 111 [foo] => true 112 ) 113 114) 115Array 116( 117 [0] => Array 118 ( 119 [foo] => true 120 ) 121 122) 123Array 124( 125 [0] => 22P02 126 [1] => 7 127 [2] => %s: %sboolean%s 128) 129EMUL 130Array 131( 132 [0] => Array 133 ( 134 [foo] => false 135 ) 136 137) 138Array 139( 140 [0] => Array 141 ( 142 [foo] => true 143 ) 144 145) 146Array 147( 148 [0] => Array 149 ( 150 [foo] => true 151 ) 152 153) 154Array 155( 156 [0] => 22P02 157 [1] => 7 158 [2] => %s: %sboolean%s 159) 160