php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #43925 Incorrect argument counter in prepared statements with pgsql
Submitted: 2008-01-24 00:11 UTC Modified: 2008-10-23 18:57 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: pronoia at beibob dot de Assigned: felipe
Status: Closed Package: PDO related
PHP Version: 5.2.5 OS: FreeBSD 6.3
Private report: No CVE-ID:
 [2008-01-24 00:11 UTC] pronoia at beibob dot de
Description:
------------
Executing a prepared statement that includes identical named placeholders among others breaks postgresql's PREPARE command.

PDO->prepare does not translate the number of unique placeholders in the statement correctly. Looks like it increments the argument number on the basis of the placeholder's position index instead using an unique index (see therefor pgsql log entries in the actual result section).

pdo_pgsql
My postgresql version is 8.2.5

Reproduce code:
---------------
Table Setup
CREATE TABLE nodes
(
   id   integer NOT NULL PRIMARY KEY
 , root integer NOT NULL
 , lft  integer NOT NULL
 , rgt  integer NOT NULL
);

INSERT INTO nodes (id, root, lft, rgt) VALUES (1, 1, 1, 6);
INSERT INTO nodes (id, root, lft, rgt) VALUES (2, 1, 2, 3);
INSERT INTO nodes (id, root, lft, rgt) VALUES (3, 1, 4, 5);

// Assumes that $Dbh is pdo object
// Let pgsql log all statements, so we can see the prepared statement as it is seen by the postgresql server
$Dbh->query("SET log_statement = 'all'");
$Stmt = $Dbh->prepare('SELECT * FROM nodes WHERE (lft > :left OR rgt > :left) AND root = :rootId');
$Stmt->bindValue('left',   1, PDO::PARAM_INT);
$Stmt->bindValue('rootId', 1, PDO::PARAM_INT);

if (!$Stmt->execute())
   print_r($Stmt->errorInfo());

// And a second one to get it clearly
$Stmt = $Dbh->prepare('SELECT * FROM nodes WHERE (lft > :left OR rgt > :left OR rgt > :left) AND root = :rootId');
$Stmt->bindValue('left',   1, PDO::PARAM_INT);
$Stmt->bindValue('rootId', 1, PDO::PARAM_INT);

if (!$Stmt->execute())
   print_r($Stmt->errorInfo());




Expected result:
----------------
no error

In the pgsql log:
STATEMENT: SELECT * FROM nodes WHERE (lft > $1 OR rgt > $1) AND root = $2

STATEMENT: SELECT * FROM nodes WHERE (lft > $1 OR rgt > $1 OR rgt > $1) AND root = $2

Actual result:
--------------
Array
(
    [0] => 42P18
    [1] => 7
    [2] => ERROR:  could not determine data type of parameter $2
)

Array
(
    [0] => 42P18
    [1] => 7
    [2] => ERROR:  could not determine data type of parameter $2
)

And in the pgsql log:
STATEMENT: SELECT * FROM nodes WHERE (lft > $1 OR rgt > $1) AND root = $3
STATEMENT: SELECT * FROM nodes WHERE (lft > $1 OR rgt > $1 OR rgt > $1) AND root = $4


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-10-23 18:57 UTC] felipe@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 15:01:54 2014 UTC