php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #68156 pg_query_params Sets Boolean False to Blank String
Submitted: 2014-10-05 07:45 UTC Modified: 2017-10-24 08:14 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: nexisentertainment at gmail dot com Assigned:
Status: Open Package: PostgreSQL related
PHP Version: 5.6.1 OS: Debian Linux (Jessie)
Private report: No CVE-ID: None
 [2014-10-05 07:45 UTC] nexisentertainment at gmail dot com
Description:
------------
pg_query_params somehow converts (boolean)false (as a parameter) to a blank string before sending it to postgres.

Note, behavior has not been documented, but has been mentioned by a user comment: http://php.net/manual/en/function.pg-query-params.php#115063

I therefore conclude I am not crazy and imagining things.

May be related to #19575.

Test script:
---------------
<?php
// NOTE:  General layout unabashedly stolen from [FILE] of https://github.com/php/php-src/blob/master/ext/pgsql/tests/bug64609.phpt
$conn_str='user=test password=test host=localhost dbname=test';
error_reporting(E_ALL);
$db = pg_connect($conn_str);
foreach(array(TRUE,FALSE) as $bool) {
    echo "Inserting ".($bool?'true':'false');
    pg_query("BEGIN");
    pg_query("CREATE TABLE test_bool_table (a boolean)");
    $values = array($bool);
    pg_query_params($db,'INSERT INTO test_bool_table (a) VALUES ($1)',$values);
    pg_query("ROLLBACK");
}

Expected result:
----------------
No errors, output of:

  Inserting true
  Inserting false

Actual result:
--------------
Inserting true
Inserting false
Warning: pg_query_params(): Query failed: ERROR: invalid input syntax for type boolean: "" in /host/[NOPE]/htdocs/testpgbug.php on line 13

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-10-05 07:50 UTC] nexisentertainment at gmail dot com
-Summary: pg_query_params Sets Booleans to Blank Strings +Summary: pg_query_params Sets Boolean False to Blank String
 [2014-10-05 07:50 UTC] nexisentertainment at gmail dot com
Should be more clear.
 [2014-10-05 09:30 UTC] nexisentertainment at gmail dot com
Created a simplified test phpt.  Used it to verify the issue still exists on git (commit 429e1b45a7cd2f491e836f4bffa57c72beb6128b).

https://gist.github.com/N3X15/56ab6238a5a8e57bdc32

Can link if someone hates gists.  Will now attempt to sleep.
 [2014-10-17 11:30 UTC] tyrael@php.net
-Assigned To: +Assigned To: yohgaki
 [2014-10-19 02:43 UTC] yohgaki@php.net
-Type: Bug +Type: Feature/Change Request
 [2014-10-19 02:43 UTC] yohgaki@php.net
IIRC, PostgreSQL does not support true/false since 6.x.
http://www.postgresql.org/docs/9.3/static/datatype-boolean.html

Valid literal values for the "true" state are:

TRUE
't'
'true'
'y'
'yes'
'on'
'1'For the "false" state, the following values can be used:
FALSE
'f'
'false'
'n'
'no'
'off'
'0'

So, this behavior is not a bug. It could be feature request.
 [2014-10-21 03:32 UTC] nexisentertainment at gmail dot com
I don't understand how unexpected behavior is not a bug.  There's no note in the documentation about this, and it's heavily implied that the values will be converted to the correct SQL types rather than simply converted to strings and thrown into the query.  In fact, the only notice about this is from a user in the comments.

In any case, '' is NOT a valid literal for false in Postgres.
 [2014-10-21 06:41 UTC] yohgaki@php.net
With prepared query type query, NULL must be handled special way. Therefore, NULL is treated specially. Implicit type conversion for database is evil, since database fields could have much higher precisions.

Except NULL, any values are simply converted to string including bool. ('1' or '').

Bool could be treated specially like NULL, but it's BC. Thus, it's a feature request.

		for(i = 0; i < num_params; i++) {
			if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
				_php_pgsql_free_params(params, num_params);
				RETURN_FALSE;
			}

			if (Z_TYPE_PP(tmp) == IS_NULL) {
				params[i] = NULL;
			} else {
				zval tmp_val = **tmp;
				zval_copy_ctor(&tmp_val);
				convert_to_cstring(&tmp_val);
				if (Z_TYPE(tmp_val) != IS_STRING) {
					php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
					zval_dtor(&tmp_val);
					_php_pgsql_free_params(params, num_params);
					RETURN_FALSE;
				}
				params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
				zval_dtor(&tmp_val);
			}

			zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
		}
 [2014-10-21 06:52 UTC] yohgaki@php.net
There is similar feature/change request. I might be able to write a RFC for more seamless bool handling for next PHP, but I cannot promise.
 [2015-03-21 17:21 UTC] ianbytchek at gmail dot com
The same behaviour in PDO. Unless I'm badly confusing this with something else Postgre has boolean type which accepts TRUE/FALSE values. I've read the comments and understand why it works this way, but that would be really good if we didn't have to treat booleans in any special way, like we don't treat nulls. `TRUE` and `FALSE` in postgre have the exact same meaning and purpose as `true` and `false` in php. More to that, when we load data from postgre, we don't get string or integer representations for booleans, we actually get proper booleans, which makes things inconsistent, e.g., if I load and try to save the same data I will get an error.
 [2017-10-24 08:14 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: yohgaki +Assigned To:
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Nov 23 09:01:28 2024 UTC