Issues

ZF-36: Specify fetch mode for internal Zend_Db queries

Description

http://framework.zend.com/developer/ticket/23

Zend_Db_Adapter_Pdo_Mysql::describeTable() assumes that an array is return from the query but this might not be the case if Zend_Db_Adapter::setFetchMode() has been called.

Example: Zend_Db_Adapter::setFetchMode(Zend_Db::FETCH_OBJ)

This is a major problem when using the the Zend_Db_Table since Zend_Db_Adapter_Pdo_Mysql::describeTable() is called in the Zend_Db_Table::_setup().

Suggestion: I would suggest implementing Zend_Db_Adapter::restoreFetchMode() so that components can use their preferred fetch mode without affecting each other.

If needed Zend_Db_Adapter::setFetchMode() could store an stack of previous fetch modes so that the users program won't be affected by components calling each other.

Note: This problem probably exists in all the Zend_Db_Addapter_* classes but has not been verified.

See "Problem Area" below in code from Zend_Db_Adapter_Pdo_Mysql:


        public function describeTable($table) { debug_print_backtrace(); die;

                $sql = "DESCRIBE $table"; 
                $result = $this->fetchAll($sql); 
                $descr = array(); 
                foreach ($result as $key => $val) {

                        $descr[$val['field']] = array( // <--Problem Area: Array Assumed

                                'name' => $val['field'], 
                                'type' => $val['type'],
                                'notnull' => (bool) ($val['null'] === ), // not null is empty, null is yes 
                                'default' => $val['default'],
                                'primary' => (strtolower($val['key']) == 'pri'),
                        );

                } 
                return $descr;
        }

Comments



Possible solution:-

Existing code:-

    public function describeTable($table)
    {
        $sql = "DESCRIBE $table";
        $result = $this->fetchAll($sql);
        $descr = array();
        foreach ($result as $key => $val) {
            $descr[$val['field']] = array(
                'name'    => $val['field'],
                'type'    => $val['type'],
                'notnull' => (bool) ($val['null'] != 'YES'), // not null is NO or empty, null is YES

                'default' => $val['default'],
                'primary' => (strtolower($val['key']) == 'pri'),
            );
        }
        return $descr;
    }

Replace with:-

    public function describeTable($table)
    {
        $sql = "DESCRIBE $table";
        $result = $this->query($sql);
        $result = $result->fetchAll(PDO::FETCH_ASSOC);
        $descr = array();
        foreach ($result as $key => $val) {
            $descr[$val['field']] = array(
                'name'    => $val['field'],
                'type'    => $val['type'],
                'notnull' => (bool) ($val['null'] != 'YES'), // not null is NO or empty, null is YES

                'default' => $val['default'],
                'primary' => (strtolower($val['key']) == 'pri'),
            );
        }
        return $descr;
    }

Changing fix version to 0.8.0.

Changed summary.

The latter solution is best, to specify the fetch mode on a case-by-case basis. It should be applied throughout the Zend_Db classes, everywhere where internal queries depend on a certain fetch mode.

reformat to remove long line

Fixed in revision 3284.