Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:63041 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 15677 invoked from network); 17 Sep 2012 17:45:23 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 Sep 2012 17:45:23 -0000 Authentication-Results: pb1.pair.com header.from=wfitch@meetme.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=wfitch@meetme.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain meetme.com designates 74.125.149.71 as permitted sender) X-PHP-List-Original-Sender: wfitch@meetme.com X-Host-Fingerprint: 74.125.149.71 na3sys009aog103.obsmtp.com Linux 2.5 (sometimes 2.4) (4) Received: from [74.125.149.71] ([74.125.149.71:58166] helo=na3sys009aog103.obsmtp.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 50/A6-07072-1B167505 for ; Mon, 17 Sep 2012 13:45:22 -0400 Received: from mail-vc0-f170.google.com ([209.85.220.170]) (using TLSv1) by na3sys009aob103.postini.com ([74.125.148.12]) with SMTP ID DSNKUFdhrmKI4qKOH/2Ie2OYRa8QRvArBtDt@postini.com; Mon, 17 Sep 2012 10:45:21 PDT Received: by vcbfk26 with SMTP id fk26so8381224vcb.29 for ; Mon, 17 Sep 2012 10:45:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:sender:x-originating-ip:date:x-google-sender-auth :message-id:subject:from:to:cc:content-type:x-gm-message-state; bh=Yxxk98FGiqxjZspa8rv6116Cp+Jk8kqzQXBZpiwYMdE=; b=nlr6qtqv16WBBozptRvzGPcRbekhe7HGb1pgEdWOjg3u50K0nak2SID3JxphNpyCcS +GDtHjipeGkRmTIND5uVn9q+oMPxedjvA0rb1Oih0H6XPhk1tc8+smhddkSWXcxJpVfy 22z0a4SlfhFLJmD3kzzpuis5sPpbhZMMZwMkYkdLiRlzRTDKQuyaqPyNTq4lU0g2VMcS kHeru4cfZhwONBIHZ6TaZjaBnfjE79jZR0qD9f9I5qwdgUu7BFcmO2WZ78f69+DuGXN/ 5yafnsplpAs69TY+AG8JhC+R/xK9oX8FZvf5cUaSe0opwb7vR5YYqJw97kJeZWd6iwBB UahA== MIME-Version: 1.0 Received: by 10.52.17.19 with SMTP id k19mr3850719vdd.0.1347903917511; Mon, 17 Sep 2012 10:45:17 -0700 (PDT) Sender: wfitch@meetme.com Received: by 10.58.132.161 with HTTP; Mon, 17 Sep 2012 10:45:17 -0700 (PDT) X-Originating-IP: [204.145.120.11] Date: Mon, 17 Sep 2012 13:45:17 -0400 X-Google-Sender-Auth: -tkWQrAdi_5ODolBNwHi2QFhoMI Message-ID: To: Ilia Alshanestsky , Wez Furlong , Edin Kadribasic Cc: internals@lists.php.net Content-Type: multipart/mixed; boundary=bcaec504091231d5a004c9e95613 X-Gm-Message-State: ALoCoQnNqXD0ZAEla7LL/w8romm+MDwRFeP/cw1c7VmHZFX+X762eX7mtpPUClsGwSoz4APToba9 Subject: pdo_pgsql Boolean Issues From: willfitch@php.net (Will Fitch) --bcaec504091231d5a004c9e95613 Content-Type: multipart/alternative; boundary=bcaec504091231d59204c9e95611 --bcaec504091231d59204c9e95611 Content-Type: text/plain; charset=ISO-8859-1 Hi, all - There's a bug in the current version of 5.3 and 5.4 with pdo_pgsql and boolean PDO types. Here's a summary of the issue: The following cases cause pgsql boolean types to be converted to an incompatible (long) format: 1. PQprepare is not available (HAVE_PQPREPARE is undefined). This happens when the libpq version < 8.0 2. PQprepare is available, but either PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT or PDO_ATTR_EMULATE_PREPARES are true (emulation handled by PDO, and the parameter hook pgsql_stmt_param_hook just skips parameter checks) This results in PDO converting the parameter to a long (default behavior for boolean). Take the following example: $pdo = new PDO($dsn); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); $query = $pdo->prepare( 'SELECT :foo IS FALSE as val_is_false' ); $query->bindValue( ':foo', false, PDO::PARAM_BOOL ); $query->execute( ); print_r($query->errorInfo()); This results in the following: Array ( [0] => 42804 [1] => 7 [2] => 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: 1. Do we have PQprepare and is emulation turned off? If so, let the driver handle via PQprepare and PQexec 2. Is PQprepare unavailable? If so, modify the original param by replacing the long 1 or 0 format to "t" or "f" 3. Is PQprepare available and emulation turned on? If so, modify the original param by replacing the long 1 or 0 format to "t" or "f" While I've spent the better part of a week trying to determine the best solution, I want to run this by Ilia, Wez and/or Edin for input. Anyone else on the list is also encouraged to provide feedback as well. - Will --bcaec504091231d59204c9e95611 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hi, all -

There's a bug in the current version of 5.= 3 and 5.4 with pdo_pgsql and boolean PDO types. =A0Here's a summary of = the issue:

The following cases cause pgsql boolean= types to be converted to an incompatible (long) format:

1. PQprepare is not available (HAVE_PQPREPARE is undefi= ned). This happens when the libpq version < 8.0
2. PQprepare i= s available, but either PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT or= =A0PDO_ATTR_EMULATE_PREPARES are true (emulation handled by PDO, and the pa= rameter hook=A0pgsql_stmt_param_hook just skips parameter checks)

This results in PDO converting the parameter to a long = (default behavior for boolean). =A0Take the following example:
$pdo =3D new PDO($dsn);
$pdo->setAttribute(PDO::A= TTR_EMULATE_PREPARES, true);=A0
$query =3D $pdo->prepare( 'SELECT :foo IS FALSE as val_is_= false' );
$query->bindValue( ':foo', false, PDO::P= ARAM_BOOL );
$query->execute( );
print_r($query->= errorInfo());

This results in the following:

Array
(
=A0 =A0 [0] =3D> 42804
=A0 =A0 [1] =3D> 7
=A0 =A0 [2] =3D> ERROR: =A0argument of = IS FALSE must be type boolean, not type integer at character 8
)

This happens because true and false a= re converted to their long formats (1 and 0 respectively), which are invali= d values for Postgres. =A0However, in the sole event that PQprepare is avai= lable and emulation is disabled, boolean parameters are correctly converted= to "t" and "f". =A0

As noted in bug #62593, disabling emulation fixes the i= ssue. =A0There are a couple of issues with this approach, though. =A0First,= it forces you to make multiple calls to the server when you actually only = need to escape input. =A0Second, and most important in my case, when using = middleware like pgbouncer, it's not possible to use true prepared state= ments. =A0The calls from PQprepare and PQexec will have separate handles.

The attached patch updates the driver to behave like so= :

1. Do we have PQprepare and is emulation turned = off? =A0If so, let the driver handle via PQprepare and PQexec
2. = Is PQprepare unavailable? If so, modify the original param by replacing the= long 1 or 0 format to "t" or "f"
3. Is PQprepare available and emulation turned on? If so, modify the o= riginal param by replacing the long 1 or 0 format to "t" or "= ;f"

While I've spent the better part of a= week trying to determine the best solution, I want to run this by Ilia, We= z and/or Edin for input. =A0Anyone else on the list is also encouraged to p= rovide feedback as well.

- Will
--bcaec504091231d59204c9e95611-- --bcaec504091231d5a004c9e95613--