深夜寂寞看CI,发现BUG一枚,请验收。。。
CI 版本:2.1.2文件:system/database/DB_driver.php
类:CI_DB_driver
方法:compile_binds($sql, $binds)
大约578行左右。
方法的描述是:Compile Bindings
该方法应该是为了实现sql语句的占位符替换成目标数据的功能,如:
INSERT INTO `table` (`colA`, `colB`) VALUES (?,?); 替换成
INSERT INTO `table` (`colA`, `colB`) VALUES (数值1,数值2);
在此方法里还做了数据转意。
/**
* Compile Bindings
*
* @access public
* @param string the sql statement
* @param array an array of bind data
* @return string
*/
function compile_binds($sql, $binds)
{
if (strpos($sql, $this->bind_marker) === FALSE)
{
return $sql;
}
if ( ! is_array($binds))
{
$binds = array($binds);
}
// Get the sql segments around the bind markers
$segments = explode($this->bind_marker, $sql);
// The count of bind should be 1 less then the count of segments
// If there are more bind arguments trim it down
if (count($binds) >= count($segments)) {
$binds = array_slice($binds, 0, count($segments)-1);
}
// Construct the binded query
$result = $segments;
$i = 0;
foreach ($binds as $bind)
{
$result .= $this->escape($bind);
$result .= $segments[++$i];
}
return $result;
}
看着一部分:
if ( ! is_array($binds))
{
$binds = array($binds);
}
看图:http://1.ssdt.sinaapp.com/%E6%9C%AA%E5%91%BD%E5%90%8D.jpg
http://1.ssdt.sinaapp.com/%E6%9C%AA%E5%91%BD%E5%90%8D1.jpg
{:1_1:}今天才下载CI看的,希望一起进步 从注释来看,这个 $binds 应该传递数组或者一个字符串,而不能是 1,2,3,4 这样的字符串,也就是说这个方法不会去拆分逗号分割的字符串。 Hex 发表于 2012-8-11 09:20 static/image/common/back.gif
从注释来看,这个 $binds 应该传递数组或者一个字符串,而不能是 1,2,3,4 这样的字符串,也就是说这个方法 ...
假如就想您说的,不是类似的1,2,3,4字符串,那他为什么要将一个字符串整合成一个一维数组?还要进行foreach??假如sql语句里占位符只能写一个,那为什么不直接替换,而大费周章的去遍历?我没说他会去拆分1,2,3,4,而是相反的将其作为一个数组元素 cyb5201314 发表于 2012-8-11 10:40 static/image/common/back.gif
假如就想您说的,不是类似的1,2,3,4字符串,那他为什么要将一个字符串整合成一个一维数组?还要进行foreac ...
先判断是不是数组,不是数组变成数组,这样的写法比较常见吧,就是为了后续可以统一按数组来处理。
占位符可以写多个,所以 $binds 可以传一个数组过来。 本帖最后由 cyb5201314 于 2012-8-11 15:54 编辑
Hex 发表于 2012-8-11 14:13 static/image/common/back.gif
先判断是不是数组,不是数组变成数组,这样的写法比较常见吧,就是为了后续可以统一按数组来处理。
占位 ...
我知道统一成数组很方便,但是请您看看这下面的代码好吗?$binds = array($binds);这句会把$binds变成一个一维数组,而他下面又对$binds进行了foreach,欲将$binds内的元素按顺序替换到占位符的位置,但是按您讲的,如果只是简单的获取一个数组,而且是一维数组,您觉得这是对的??就算是目标数值是一样的,那也只需要替换一下全部的占位符为目标数值就行了,何必弄成数组,再看下面,他将sql语句用占位符分割了,再遍历$binds的一维数组,将每一个元素连接在分割的sql里,出现的结果就是sql断开了,除非他的功能只能支持占位符为1个数量的,此时$binds可以是一个字符串,刚去英文网站找了已经改过的版本
/**
* Compile Bindings
*
* @param string the sql statement
* @param array an array of bind data
* @return string
*/
public function compile_binds($sql, $binds)
{
if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)
{
return $sql;
}
elseif ( ! is_array($binds))
{
$binds = array($binds);
$bind_count = 1;
}
else
{
// Make sure we're using numeric keys
$binds = array_values($binds);
$bind_count = count($binds);
}
// We'll need the marker length later
$ml = strlen($this->bind_marker);
// Make sure not to replace a chunk inside a string that happens to match the bind marker
if ($c = preg_match_all("/'[^']*'/i", $sql, $matches))
{
$c = preg_match_all('/'.preg_quote($this->bind_marker).'/i',
str_replace($matches,
str_replace($this->bind_marker, str_repeat(' ', $ml), $matches),
$sql, $c),
$matches, PREG_OFFSET_CAPTURE);
// Bind values' count must match the count of markers in the query
if ($bind_count !== $c)
{
return $sql;
}
}
elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
{
return $sql;
}
do
{
$c--;
$sql = substr_replace($sql, $this->escape($binds[$c]), $matches[$c], $ml);
}
while ($c !== 0);
return $sql;
}
cyb5201314 发表于 2012-8-11 15:51 static/image/common/back.gif
我知道统一成数组很方便,但是请您看看这下面的代码好吗?$binds = array($binds);这句会把$binds变成一个 ...
这里的关键就是要看 $binds 是什么。
如果 $binds 是 1,2,3,4 就有问题,如果 $binds 是 array('1','2','3','4') 就没问题。
要看是谁调用的 compile_binds() 方法。调用的时候是如何传参的。 cyb5201314 发表于 2012-8-11 15:51 static/image/common/back.gif
我知道统一成数组很方便,但是请您看看这下面的代码好吗?$binds = array($binds);这句会把$binds变成一个 ...
我刚才又仔细看了下传参,这个参数手册规定是要传递一个数组,类似 array('123', 'abc', 'def') 这样的。
我看了一下,你这个是最新代码库里的代码,不过,感觉 $binds 处理没变,只是改变了一下替换占位符的代码。 看了半天,没懂BUG在哪 我看懂了。
页:
[1]
2