From:             uwendel at mysql dot com
Operating system: Linux
PHP version:      5.3CVS-2008-02-18 (CVS)
PHP Bug Type:     PDO related
Bug description:  Several PDO attributes are documented with the wrong type

Description:
------------
PDO->getAttribute() returns attribute values of different types than
described on http://de.php.net/manual/en/ref.pdo.php .

PDO::ATTR_CLIENT_VERSION

 documented           : integer
 actual type  returned: string
 tested with          : sqlite, mysql, pgsql
 suggestion           : for BC reasons no change, document it

PDO::ATTR_PERSISTENT

 documented           : integer
 actual type returned : boolean
 tested with          : sqlite, mysql, pgsql
 suggestion           : I have no preference myself

PDO::ATTR_SERVER_VERSION

 documented           : integer
 actual type returned : string 
 tested with          : sqlite, mysql, pgsql
 suggestion           : for BC reasons no change, document it

PDO::ATTR_STATEMENT_CLASS

 documented           : integer
 actual type returned : array
 tested with          : sqlite, mysql, pgsql
 suggestion           : update the manual to array

I guess it does not matter what driver you use. For example the type
setting for PDO::ATTR_PERSISTENT/PDO::ATTR_STATEMENT_CLASS happens in
ext/pdo/pdo_dbh.c . However, my point is that the manual and what you
actually find differs. Get it in sync and I'm fine.



Reproduce code:
---------------
---------------PDO::ATTR_CLIENT_VERSION --------------

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("sqlite:/tmp/foo.db");
var_dump($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION));'
string(6) "3.3.17"

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("pgsql:host=localhost port=5432 dbname=phptest user=postgres
password="); var_dump($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION));'
string(5) "8.2.4"

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("mysql:dbname=phptest;unix_socket=/tmp/mysql.sock", "root", "root");
var_dump($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION));'
string(9) "5.1.24-rc"

-------------------- PDO::ATTR_PERSISTENT -----------------

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("pgsql:host=localhost port=5432 dbname=phptest user=postgres
password="); var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT));'
bool(false)

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("mysql:dbname=phptest;unix_socket=/tmp/mysql.sock", "root", "root");
var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT));'
bool(false)

[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("sqlite:/tmp/foo.db");
var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT));'
bool(false)

--------------------------- PDO::ATTR_STATEMENT_CLASS --------------


[EMAIL PROTECTED]:~/php53> sapi/cli/php -r '$pdo=new
PDO("pgsql:host=localhost port=5432 dbname=phptest user=postgres
password="); var_dump($pdo->getAttribute(PDO::ATTR_STATEMENT_CLASS));'
array(1) {
  [0]=>
  string(12) "PDOStatement"
}



---------------------- stripped version of my internal test ----------


--TEST--
PDO Common: PDO->getAttribute()
--SKIPIF--
<?php # vim:ft=php
if (!extension_loaded('pdo')) die('skip');
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false)
putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();

function find_invalid_int($valid_options) {

        do {
                $invalid = mt_rand(-10000, 10000);
        } while (in_array($invalid, $valid_options));

        return $invalid;
}

function set_and_get($offset, $db, $attribute, $value, $quiet = false) {

        $value_type = gettype($value);
        try {

                if ([EMAIL PROTECTED]>setAttribute($attribute, $value)) {
                        if (!$quiet)
                                printf("[%03d] Cannot set attribute '%s' to 
value '%s'\n",
                                        $offset, $attribute, var_export($value, 
true));
                        return false;
                }
                if (gettype($value) != $value_type) {
                                printf("[%03d] Call to PDO::setAttribute(int 
attribute, mixed value)
has changed the type of value from %s to %s, test will not work
properly\n",
                                        $offset, $value_type, gettype($value));
                        return false;
                }

                $tmp = $db->getAttribute($attribute);
                if ($tmp !== $value) {
                        if (!$quiet)
                                printf("[%03d] Attribute '%s' was set to '%s' 
but getAttribute()
reports '%s'\n",
                                        $offset, $attribute, var_export($value, 
true), var_export($tmp,
true));
                        return false;
                }

        } catch (PDOException $e) {
                printf("[%03d] %s, [%s] %s\n",
                        $offset, $e->getMessage(),
                        $db->errorCode(), implode(' ', $db->errorInfo()));
                return false;
        }

        return true;
}

$attributes = array(
        'PDO::ATTR_CASE' =>
                array(
                        'const' => PDO::ATTR_CASE,
                        'type_manual' => 'integer',
                        'type_code' => 'integer',
                ),
        'PDO::ATTR_CLIENT_VERSION' =>
                array(
                        'const' => PDO::ATTR_CLIENT_VERSION,
                        'type_manual' => 'integer',
                        'type_code' => null,
                ),              
        'PDO::ATTR_DRIVER_NAME' =>
                array(
                        'const' => PDO::ATTR_DRIVER_NAME,
                        'type_manual' => 'string',
                        'type_code'     => 'string',
                ),
        'PDO::ATTR_ERRMODE' =>
                array(
                        'const' => PDO::ATTR_ERRMODE,
                        'type_manual' => 'integer',
                        'type_code' => 'integer',
                ),
        'PDO::ATTR_ORACLE_NULLS' =>
                array(
                        'const' => PDO::ATTR_ORACLE_NULLS,
                        'type_manual' => 'integer',
                        'type_code' => 'integer',
                ),
        'PDO::ATTR_PERSISTENT' =>
                array(
                        'const' => PDO::ATTR_PERSISTENT,
                        'type_manual' => 'integer',
                        'type_code' => 'boolean',
                ),
        'PDO::ATTR_SERVER_VERSION' =>
                array(
                        'const' => PDO::ATTR_SERVER_VERSION,
                        'type_manual' => 'integer',
                        'type_code' => null,
                ),
        'PDO::ATTR_STATEMENT_CLASS' =>
                array(
                        'const' => PDO::ATTR_STATEMENT_CLASS,
                        'type_manual'   => 'integer',
                        'type_code' => 'array',
                ),

);

if (version_compare(PHP_VERSION, '5.2.0', '>='))
        $attributes['PDO::ATTR_DEFAULT_FETCH_MODE'] =
                array(
                        'const' => PDO::ATTR_DEFAULT_FETCH_MODE,
                        'type_manual' => 'integer',
                        'type_code' => 'integer',
                );

try {

        foreach ($attributes as $name => $attribute) {
                printf("PDO::getAttribute(%s)\n", $name);
                $setting = $db->getAttribute($attribute['const']);

                $type = gettype($setting);
                switch ($type) {
                        case 'int':
                                $type = 'integer';
                                break;
                        case 'bool':
                                $type = 'boolean';
                                break;
                        default:
                                break;
                }

                if ($type != $attribute['type_manual']) {
                        printf("[005] According to the manual 
PDO::getAttribute(%s) should
return a value of type '%s' found type '%s'\n",
                                $name, $attribute['type_manual'], $type);
                }

                if (!is_null($attribute['type_code']) && ($type !=
$attribute['type_code'])) {
                        printf("[006] According to the code 
PDO::getAttribute(%s) should return
a value of type '%s' found type '%s'\n",
                                $name, $attribute['type_code'], $type);
                }
        }

} catch (PDOException $e) {
        printf("[007] %s, [%s} %s\n",
                $e->getMessage(),
                $db->errorCode(),
                implode(' ', $db->errorInfo()));
}
set_and_get(8, $db, PDO::ATTR_CASE, PDO::CASE_LOWER);
set_and_get(9, $db, PDO::ATTR_CASE, PDO::CASE_NATURAL);
set_and_get(10, $db, PDO::ATTR_CASE, PDO::CASE_UPPER);
set_and_get(11, $db, PDO::ATTR_CASE,
        find_invalid_int(array(PDO::CASE_LOWER, PDO::CASE_NATURAL.
PDO::CASE_UPPER)));

set_and_get(12, $db, PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
set_and_get(13, $db, PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
set_and_get(14, $db, PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// back to what we use for testing...
set_and_get(15, $db, PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
set_and_get(16, $db, PDO::ATTR_ERRMODE,
        find_invalid_int(array(PDO::ERRMODE_SILENT, PDO::ERRMODE_WARNING,
PDO::ERRMODE_EXCEPTION)));

set_and_get(17, $db, PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);
set_and_get(18, $db, PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
set_and_get(19, $db, PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);

class MyPDOStatement extends PDOStatement {
        private function __construct() {
                parent::__construct();
        }
}
set_and_get(21, $db, PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement',
array()));

print "done!";
?>
--EXPECTF--
PDO::getAttribute(PDO::ATTR_CASE)
PDO::getAttribute(PDO::ATTR_CLIENT_VERSION)
PDO::getAttribute(PDO::ATTR_DRIVER_NAME)
PDO::getAttribute(PDO::ATTR_ERRMODE)
PDO::getAttribute(PDO::ATTR_ORACLE_NULLS)
PDO::getAttribute(PDO::ATTR_PERSISTENT)
PDO::getAttribute(PDO::ATTR_SERVER_VERSION)
PDO::getAttribute(PDO::ATTR_STATEMENT_CLASS)
PDO::getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE)
[011] Cannot set attribute '%s' to value '%s'
[016] Cannot set attribute '%s' to value '%s'
done!

Expected result:
----------------
See above

Actual result:
--------------
See above

-- 
Edit bug report at http://bugs.php.net/?id=44158&edit=1
-- 
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=44158&r=trysnapshot52
Try a CVS snapshot (PHP 5.3): 
http://bugs.php.net/fix.php?id=44158&r=trysnapshot53
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=44158&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=44158&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=44158&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=44158&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=44158&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=44158&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=44158&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=44158&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=44158&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=44158&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=44158&r=globals
PHP 4 support discontinued:   http://bugs.php.net/fix.php?id=44158&r=php4
Daylight Savings:             http://bugs.php.net/fix.php?id=44158&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=44158&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=44158&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=44158&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=44158&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=44158&r=mysqlcfg

Reply via email to