...ve format in emulation mode
From the internals list:
The following cases cause pgsql boolean types to be converted to an incompatible (long) format:
This results in PDO converting the parameter to a long (default behavior for boolean). Take the following example:
$pdo = new PDO($dsn);
$query = $pdo->prepare( 'SELECT :foo IS FALSE as val_is_false' );
$query->bindValue( ':foo', false, PDO::PARAM_BOOL );
This results in the following:
 => 42804
 => 7
 => ERROR: argument of IS FALSE must be type boolean, not type integer at character 8
This happens because true and false are converted to their long formats (1 and 0 respectively), which are invalid values for Postgres. However, in the sole event that PQprepare is available and emulation is disabled, boolean parameters are correctly converted to "t" and "f".
As noted in bug #62593, disabling emulation fixes the issue. There are a couple of issues with this approach, though. First, it forces you to make multiple calls to the server when you actually only need to escape input. Second, and most important in my case, when using middleware like pgbouncer, it's not possible to use true prepared statements. The calls from PQprepare and PQexec will have separate handles.
The attached patch updates the driver to behave like so:
Thanks! We need a test for that.
There actually is one, and it currently fails: bug_33876.phpt. This actually makes that specific test pass.
Bug #62593 Updated pdo_pgsql driver to convert boolean values to pg n…
…ative format in emulation mode
Bug #62593 Added test for change
I went ahead and added a new test for this bug. Some of the tests from #33876 aren't relevant to this and I'd like to confirm this specific test only.
Bug #62593 Updated test to take errors produced by other tests into a…
for the sake of completeness, can you add something like this to the test case?
$value = false;
$query->bindParam(':foo', $value, PDO::PARAM_BOOL);
so that we can assert that we didn't change the value of $value?
Bug #62593 Updated to always treat zval by value
Bug #62593 Updated test to verify bindParam doesn't change original v…
@wez I had to update SEPARATE_ZVAL_IF_NOT_REF to SEPARATE_ZVAL; otherwise, the original value gets modified on bindParam. I've updated the test to verify bindValue and bindParam behave as expected.
Hmmm, ok, next possible wrinkle then; can you try something like Example 3 from the manual crossed with the above?
but where the parameter is a bool?
You'll need to define a procedure with an OUT parameter; in this case we expect $value to get modified; want to make sure we didn't break that :-)
Haha. Well, there are a couple of issues here. First, PDO_PARAM_INTPUT_OUTPUT doesn't work for most drivers (see https://bugs.php.net/bug.php?id=43887). I have updated to specifically skip conversion of the param_type is hashed with PDO_PARAM_INPUT_OUTPUT. This event could cause a memory leak otherwise, so this is good. This does not, however, address the other bug and probably shouldn't.
I did not add the INOUT test as it will fail regardless.
Bug #62593 Updated to account for INOUT parameters
Bug #62593 Corrected code format (spacing)
@wez any other issues you can think of? I'm going to commit the test with the example 3 code but commented out. When we are able to address the other bug, the comments can be removed.
@wez @lstrojny If there are no further issues with this, could we get this merged? It is a show-stopper for those of us attempting to upgrade from 5.2 to 5.3/5.4.
The code looks good to me. I'm a little out of touch with getting things merged these days, so will need to appeal to @lstrojny and others to get it merged.
Thanks, @wez. I appreciate your feedback
@lstrojny Can we get this merged/queued for merging?
I rebased it and currently waiting for Johannes approval for 5.3.