php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44190 SELECT 1 and PDO::FETCH_BOTH
Submitted: 2008-02-20 19:01 UTC Modified: 2008-02-21 14:18 UTC
From: uwendel at mysql dot com Assigned:
Status: Not a bug Package: PDO related
PHP Version: 5.3CVS-2008-02-20 (CVS) OS: Linux 64
Private report: No CVE-ID: None
 [2008-02-20 19:01 UTC] uwendel at mysql dot com
Description:
------------
"PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set",
http://de.php.net/manual/en/function.PDOStatement-fetch.php

[1] This looks like a wrong result for PDO::FETCH_BOTH to me: 

 SELECT 1 -> 
 array(1 => "1", 2 => "2")

Looks as if PDO uses the "1" as an index offset and does not start the column numbering at 0 but at "1". 

[2] Try the same with SELECT 2 and you see what I mean:

 SELECT 2 ->
 array(2 => "2", 3 => "2")

I'd rather expect something like:

 SELECT 1 ->
 array(0 => "1", 1 => "1")

Or in pseudo-code:

 FETCH::BOTH == array_merge(FETCH::ASSOC, FETCH_NUM)









Reproduce code:
---------------
[1] LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client/lib sapi/cli/php -r '$pdo=new PDO("oci:dbname=//localhost:1521/XE", "SYSTEM", "oracle"); var_dump($pdo->query("SELECT 1 FROM DUAL")->fetch(PDO::FETCH_BOTH));'
array(2) {
  [1]=>
  string(1) "1"
  [2]=>
  string(1) "1"
}

[2] nixnutz@ulflinux:~/php53> LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client/lib sapi/cli/php -r '$pdo=new PDO("sqlite:/tmp/foo.db"); var_dump($pdo->query("SELECT 2")->fetch(PDO::FETCH_BOTH));'
array(2) {
  [2]=>
  string(1) "2"
  [3]=>
  string(1) "2"
}



This is my failing MySQL test, don't know if its for use of you. Someone would need to port it to all other drivers to make it useful.

--TEST--
MySQL PDOStatement->fetch()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('mysql_pdo_test.inc');
MySQLPDOTest::skip();
$db = MySQLPDOTest::factory();
?>
--FILE--
<?php
	require_once('mysql_pdo_test.inc');
	$db = MySQLPDOTest::factory();

	function fetch($offset, &$db, $query, $expect = null) {

		try {
			$stmt = $db->query('SELECT 1');
			$num = $stmt->fetch(PDO::FETCH_NUM);

			$stmt = $db->query('SELECT 1');
			$assoc = $stmt->fetch(PDO::FETCH_ASSOC);

			$stmt = $db->query('SELECT 1');
			$both = $stmt->fetch(PDO::FETCH_BOTH);

			$computed_both = array_merge($num, $assoc);
			if ($computed_both != $both) {
				printf("[%03d] Suspicious FETCH_BOTH result, dumping\n", $offset);
				var_dump($computed_both);
				var_dump($both);
			}

			if (!is_null($expect) && ($expect != $both)) {
				printf("[%03d] Expected differes from returned data, dumping\n", $offset);
				var_dump($expect);
				var_dump($both);
			}

		} catch (PDOException $e) {

			printf("[%03d] %s, [%s] %s\n",
				$offset,
				$e->getMessage(), $db->errroCode(), implode(' ', $db->errorInfo()));

		}

	}

	try {

		fetch(2, &$db, 'SELECT 1', array(0 => '1', '1' => '1'));

	} catch (PDOException $e) {
		printf("[001] %s [%s] %s\n",
			$e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo()));
	}
	print "done!";
--BUGFREE_EXPECTF--
done!
--EXPECTF--
[002] Suspicious FETCH_BOTH result, dumping
array(2) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "1"
}
array(2) {
  [1]=>
  string(1) "1"
  [2]=>
  string(1) "1"
}
[002] Expected differes from returned data, dumping
array(2) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "1"
}
array(2) {
  [1]=>
  string(1) "1"
  [2]=>
  string(1) "1"
}
done!


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-02-21 13:16 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

The name of the column conflicts with numeric indexes.
 [2008-02-21 13:48 UTC] uwendel at mysql dot com
Sure, the name does conflict with the column index. That's the purpose of the test.

According to the manual PDO::FETCH_BOTH is said to return an array indexed by:

 a) column name
 b) 0-indexed column number

If you have only one column, the 0-indexed column number is 0. But the current implementation does not reflect that.

Let's compute the result manually for a query like SELECT 1 AS "1" FROM DUAL and apply the rules from the manual.

 a) column name - "1"
 b) 0-indexed column number - 0

Putting that together you get:

 array([a] "1" => "1", [b] 0 => "1")


And its not like this:

 a) column name - "1"
 b) 0-indexed, hmm, lets consider the column name as an offset - 2

This result remains wrong:

 array([a] "1" => "1", [b] 2 => "1")
 [2008-02-21 14:18 UTC] uwendel at mysql dot com
Ok, got it. The fun is stuff like SELECT 1, 2.

What about a hint in the documentation?
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Fri Jan 28 12:03:42 2022 UTC