首页  >  文章  >  php教程  >  pdo数据库驱动存在一个Bug,影响3.1.3及以下版本[严重]

pdo数据库驱动存在一个Bug,影响3.1.3及以下版本[严重]

WBOY
WBOY原创
2016-06-07 11:44:191250浏览

pdo数据库驱动存在一个无法获取数据表主键的Bug,导致此Bug的原因并非逻辑缺陷,而是TP开发人员的粗心大意
ThinkPHP pdo数据库驱动存在一个无法获取数据表主键的Bug,此Bug会导致所有与数据表主键有关的操作发生错乱、失败甚至无法预料的结果(数据表主键为id或者Model里自定义pk则不受影响).如果你的数据表主键不是"id",对数据库进行一系列依赖主键的操作会发生错误.

Bug影响版本:3.1.3及以下

Bug位置:Extend/Driver/Db/DbPdo.class.php或:Lib/Driver/Db/DbPdo.class.php代码位置:定位到函数getFieldspublic function getFields($tableName) {<br>         $this->initConnect(true);<br>         if(C('DB_DESCRIBE_TABLE_SQL')) {<br>             // 定义特殊的字段查询SQL<br>             $sql   = str_replace('%table%',$tableName,C('DB_DESCRIBE_TABLE_SQL'));<br>         }else{<br>             switch($this->dbType) {<br>                 case 'MSSQL':<br>                 case 'SQLSRV':<br>                     $sql   = "SELECT   column_name as 'Name',   data_type as 'Type',   column_default as 'Default',   is_nullable as 'Null'<br>         FROM    information_schema.tables AS t<br>         JOIN    information_schema.columns AS c<br>         ON  t.table_catalog = c.table_catalog<br>         AND t.table_schema  = c.table_schema<br>         AND t.table_name    = c.table_name<br>         WHERE   t.table_name = '$tableName'";<br>                     break;<br>                 case 'SQLITE':<br>                     $sql   = 'PRAGMA table_info ('.$tableName.') ';<br>                     break;<br>                 case 'ORACLE':<br>                 case 'OCI':<br>                     $sql   = "SELECT a.column_name \"Name\",data_type \"Type\",decode(nullable,'Y',0,1) notnull,data_default \"Default\",decode(a.column_name,b.column_name,1,0) \"pk\" "<br>                       ."FROM user_tab_columns a,(SELECT column_name FROM user_constraints c,user_cons_columns col "<br>                       ."WHERE c.constraint_name=col.constraint_name AND c.constraint_type='P' and c.table_name='".strtoupper($tableName)<br>                       ."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)";<br>                     break;<br>                 case 'PGSQL':<br>                     $sql   = 'select fields_name as "Name",fields_type as "Type",fields_not_null as "Null",fields_key_name as "Key",fields_default as "Default",fields_default as "Extra" from table_msg('.$tableName.');';<br>                     break;<br>                 case 'IBASE':<br>                     break;<br>                 case 'MYSQL':<br>                 default:<br>                     $sql   = 'DESCRIBE '.$tableName;//备注: 驱动类不只针对mysql,不能加``<br>             }<br>         }<br>         $result = $this->query($sql);<br>         $info   =   array();<br>         if($result) {<br>             foreach ($result as $key => $val) {<br>                 $val            =   array_change_key_case($val);<br>                 $val['name']    =   isset($val['name'])?$val['name']:"";<br>                 $val['type']    =   isset($val['type'])?$val['type']:"";<br>                 $name           =   isset($val['field'])?$val['field']:$val['name'];<br>                 $info[$name]    =   array(<br>                     'name'    => $name ,<br>                     'type'    => $val['type'],<br>                     'notnull' => (bool)(((isset($val['null'])) && ($val['null'] === '')) || ((isset($val['notnull'])) && ($val['notnull'] === ''))), // not null is empty, null is yes<br>                     'default' => isset($val['default'])? $val['default'] :(isset($val['dflt_value'])?$val['dflt_value']:""),<br>                     'primary' => isset($val['dey'])?strtolower($val['dey']) == 'pri':(isset($val['pk'])?$val['pk']:false),<br>                     'autoinc' => isset($val['extra'])?strtolower($val['extra']) == 'auto_increment':(isset($val['key'])?$val['key']:false),<br>                 );<br>             }<br>         }<br>         return $info;<br>     }定位到此行:'primary' => isset($val['dey'])?strtolower($val['dey']) == 'pri':(isset($val['pk'])?$val['pk']:false),你会看到原本为"key"的数组键名被错输为"dey",没错,导致此Bug的问题就出现在此行代码.

解决办法:将dey修改为key,修改后代码为:'primary' => isset($val['key'])?strtolower($val['key']) == 'pri':(isset($val['pk'])?$val['pk']:false),

AD:真正免费,域名+虚机+企业邮箱=0元

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn