用户
 找回密码
 入住 CI 中国社区
搜索
查看: 4639|回复: 2
收起左侧

[讨论/交流] BUG?数据库维护类表达异常,无法定义“多列的非主键”!

[复制链接]
发表于 2013-2-14 19:35:09 | 显示全部楼层 |阅读模式
如题!
“多列的非主键必须通过数组来传递”
我参照中文手册上的做法和示例,无法设置“多列的非主键”。故意设置一个错误,观察到实际生成的代码是设置了两个单独的 “非主键”
CI版本:2.1.3
  • Apache/2.2.22 (Win32) PHP/5.2.17
  • 数据库客户端版本: libmysql - 5.0.51a
  • PHP 扩展: mysqli

  • 服务器: localhost via TCP/IP
  • 软件: MySQL
  • 软件版本: 5.5.29-log - MySQL Community Server (GPL)
  • 协议版本: 10

请问有其他人遇到这种情况吗?这是一个BUG,还是因为我的数据库版本有问题?
你可以试一下下面这段代码,如果支持“设置多列的主键”,不会报错如果不支持会出现错误信息“Duplicate key name 'taxonomy'”
PHP复制代码
 
        $fields=array(
                        'term_taxonomy_id' => array(
                                            'type' => 'BIGINT',
                                            'constraint' => 20,
                                            'unsigned' => TRUE,
                                            'auto_increment' => TRUE,
                                            ),
                        'term_id' => array(
                                            'type' => 'BIGINT',
                                            'constraint' => 20,
                                            'unsigned' => TRUE,
                                            'default' => 0
                                            ),
                        'taxonomy' => array(
                                            'type' => 'VARCHAR',
                                            'constraint' => 32,
                                            'default' => ''
                                            ),
                        'description' => array(
                                                'type' => 'LONGTEXT'
                                                ),
                        'parent' => array(
                                            'type' => 'BIGINT',
                                            'constraint' => 20,
                                            'unsigned' => TRUE,
                                            'default' => 0
                                            ),
                        'count' => array(
                                            'type' => 'BIGINT',
                                            'constraint' => 20,
                                            'default' => 0
                                            ),
                        );
        $this->dbforge->add_key('term_taxonomy_id',TRUE);
        $this->dbforge->add_key('taxonomy',TRUE);
        $this->dbforge->add_key('taxonomy');
        $this->dbforge->add_key(array('term_id','taxonomy'));//问题所在!!!!
        $this->dbforge->add_field($fields);
        $this->dbforge->create_table('term_taxonomy');
 
复制代码



本帖被以下淘专辑推荐:

 楼主| 发表于 2013-2-14 21:37:47 | 显示全部楼层
找到原因了,可以确定是源代码错误,也就是说,这是一个BUG!
修正方法(以2.1.3版本为例,其他CI版本请参考修改):
打开systerm/database/DB_forge.php
搜索“function add_key($key = '', $primary = FALSE)”(98行左右),然后将此函数的第一个if判断语句注释起来或删除,即可修正此错误!
修正后的add_key方法的代码如下:
PHP复制代码
 
    function add_key($key = '', $primary = FALSE)
    {
        /*if (is_array($key))
        {
            foreach ($key as $one)
            {
                $this->add_key($one, $primary);
            }
 
            return;
        }*/

 
        if ($key == '')
        {
            show_error('Key information is required for that operation.');
        }
 
        if ($primary === TRUE)
        {
            $this->primary_keys[] = $key;
        }
        else
        {
            $this->keys[] = $key;
        }
    }
 
复制代码


 楼主| 发表于 2013-2-14 21:48:53 | 显示全部楼层
本帖最后由 Altair 于 2013-2-14 21:50 编辑

原因分析(仅以mysql数据库环境为例):
PHP复制代码
 
//systerm/database/DB_forge.php   第181行
    function create_table($table = '', $if_not_exists = FALSE)
    {
        if ($table == '')
        {
            show_error('A table name is required for that operation.');
        }
 
        if (count($this->fields) == 0)
        {
            show_error('Field information is required.');
        }
 
        $sql = $this->_create_table($this->db->dbprefix.$table, $this->fields, $this->primary_keys, $this->keys, $if_not_exists);
 
        $this->_reset();
        return $this->db->query($sql);
    }
 
复制代码

分析上述代码可以确定,问题解决的关键集中在_create_table()函数上
PHP复制代码
 
//systerm/database/drivers/mysql/mysql_forge.php 第160行开始
    function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
    {
        $sql = 'CREATE TABLE ';
 
        if ($if_not_exists === TRUE)
        {
            $sql .= 'IF NOT EXISTS ';
        }
 
        $sql .= $this->db->_escape_identifiers($table)." (";
 
        $sql .= $this->_process_fields($fields);
 
        if (count($primary_keys) > 0)
        {
            $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys));
            $primary_keys = $this->db->_protect_identifiers($primary_keys);
            $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")";
        }
 
        if (is_array($keys) && count($keys) > 0)
        {
            foreach ($keys as $key)
            {
复制代码

                if (is_array($key))
                {
                    $key_name = $this->db->_protect_identifiers(implode('_', $key));
                    $key = $this->db->_protect_identifiers($key);
                }
PHP复制代码
 
                else
                {
                    $key_name = $this->db->_protect_identifiers($key);
                    $key = array($key_name);
                }
 
                $sql .= ",\n\tKEY {$key_name} (" . implode(', ', $key) . ")";
            }
        }
 
        $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};";
 
        return $sql;
    }
 
复制代码

通过对以上红色高亮区域的代码分析可以确定,允许$key是一个数组,即在add_key方法中,不应该也不允许对$key是否为数组的情况进行区分
完{:soso_e130:}

本版积分规则