mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-09 08:02:48 +08:00
改进对存储过程调用的支持 改进getRealSql的调用机制 改进数据表字段使用中划线的参数绑定支持
This commit is contained in:
@@ -316,7 +316,7 @@ abstract class Builder
|
|||||||
throw new Exception('where express error:' . $exp);
|
throw new Exception('where express error:' . $exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$bindName = $bindName ?: 'where_' . str_replace('.', '_', $field);
|
$bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field);
|
||||||
if (preg_match('/\W/', $bindName)) {
|
if (preg_match('/\W/', $bindName)) {
|
||||||
// 处理带非单词字符的字段名
|
// 处理带非单词字符的字段名
|
||||||
$bindName = md5($bindName);
|
$bindName = md5($bindName);
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ abstract class Connection
|
|||||||
PDO::ATTR_EMULATE_PREPARES => false,
|
PDO::ATTR_EMULATE_PREPARES => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 绑定参数
|
||||||
|
protected $bind = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 架构函数 读取数据库配置信息
|
* 架构函数 读取数据库配置信息
|
||||||
* @access public
|
* @access public
|
||||||
@@ -319,22 +322,26 @@ abstract class Connection
|
|||||||
/**
|
/**
|
||||||
* 执行查询 返回数据集
|
* 执行查询 返回数据集
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $sql sql指令
|
* @param string $sql sql指令
|
||||||
* @param array $bind 参数绑定
|
* @param array $bind 参数绑定
|
||||||
* @param boolean $master 是否在主服务器读操作
|
* @param bool $master 是否在主服务器读操作
|
||||||
* @param bool|string $class 指定返回的数据集对象
|
* @param bool $class 是否返回PDO对象
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws BindParamException
|
* @throws BindParamException
|
||||||
* @throws PDOException
|
* @throws PDOException
|
||||||
*/
|
*/
|
||||||
public function query($sql, $bind = [], $master = false, $class = false)
|
public function query($sql, $bind = [], $master = false, $pdo = false)
|
||||||
{
|
{
|
||||||
$this->initConnect($master);
|
$this->initConnect($master);
|
||||||
if (!$this->linkID) {
|
if (!$this->linkID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 根据参数绑定组装最终的SQL语句
|
|
||||||
$this->queryStr = $this->getRealSql($sql, $bind);
|
// 记录SQL语句
|
||||||
|
$this->queryStr = $sql;
|
||||||
|
if ($bind) {
|
||||||
|
$this->bind = $bind;
|
||||||
|
}
|
||||||
|
|
||||||
//释放前次的查询结果
|
//释放前次的查询结果
|
||||||
if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
|
if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
|
||||||
@@ -349,16 +356,22 @@ abstract class Connection
|
|||||||
if (empty($this->PDOStatement)) {
|
if (empty($this->PDOStatement)) {
|
||||||
$this->PDOStatement = $this->linkID->prepare($sql);
|
$this->PDOStatement = $this->linkID->prepare($sql);
|
||||||
}
|
}
|
||||||
|
// 是否为存储过程调用
|
||||||
|
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
|
||||||
// 参数绑定
|
// 参数绑定
|
||||||
$this->bindValue($bind);
|
if ($procedure) {
|
||||||
|
$this->bindParam($bind);
|
||||||
|
} else {
|
||||||
|
$this->bindValue($bind);
|
||||||
|
}
|
||||||
// 执行查询
|
// 执行查询
|
||||||
$this->PDOStatement->execute();
|
$this->PDOStatement->execute();
|
||||||
// 调试结束
|
// 调试结束
|
||||||
$this->debug(false);
|
$this->debug(false);
|
||||||
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
|
// 返回结果集
|
||||||
return $this->getResult($class, $procedure);
|
return $this->getResult($class, $procedure);
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e) {
|
||||||
throw new PDOException($e, $this->config, $this->queryStr);
|
throw new PDOException($e, $this->config, $this->getLastsql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,8 +390,12 @@ abstract class Connection
|
|||||||
if (!$this->linkID) {
|
if (!$this->linkID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 根据参数绑定组装最终的SQL语句
|
|
||||||
$this->queryStr = $this->getRealSql($sql, $bind);
|
// 记录SQL语句
|
||||||
|
$this->queryStr = $sql;
|
||||||
|
if ($bind) {
|
||||||
|
$this->bind = $bind;
|
||||||
|
}
|
||||||
|
|
||||||
//释放前次的查询结果
|
//释放前次的查询结果
|
||||||
if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
|
if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
|
||||||
@@ -393,8 +410,14 @@ abstract class Connection
|
|||||||
if (empty($this->PDOStatement)) {
|
if (empty($this->PDOStatement)) {
|
||||||
$this->PDOStatement = $this->linkID->prepare($sql);
|
$this->PDOStatement = $this->linkID->prepare($sql);
|
||||||
}
|
}
|
||||||
// 参数绑定操作
|
// 是否为存储过程调用
|
||||||
$this->bindValue($bind);
|
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
|
||||||
|
// 参数绑定
|
||||||
|
if ($procedure) {
|
||||||
|
$this->bindParam($bind);
|
||||||
|
} else {
|
||||||
|
$this->bindValue($bind);
|
||||||
|
}
|
||||||
// 执行语句
|
// 执行语句
|
||||||
$this->PDOStatement->execute();
|
$this->PDOStatement->execute();
|
||||||
// 调试结束
|
// 调试结束
|
||||||
@@ -403,7 +426,7 @@ abstract class Connection
|
|||||||
$this->numRows = $this->PDOStatement->rowCount();
|
$this->numRows = $this->PDOStatement->rowCount();
|
||||||
return $this->numRows;
|
return $this->numRows;
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e) {
|
||||||
throw new PDOException($e, $this->config, $this->queryStr);
|
throw new PDOException($e, $this->config, $this->getLastsql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,23 +439,21 @@ abstract class Connection
|
|||||||
*/
|
*/
|
||||||
public function getRealSql($sql, array $bind = [])
|
public function getRealSql($sql, array $bind = [])
|
||||||
{
|
{
|
||||||
if ($bind) {
|
foreach ($bind as $key => $val) {
|
||||||
foreach ($bind as $key => $val) {
|
$value = is_array($val) ? $val[0] : $val;
|
||||||
$value = is_array($val) ? $val[0] : $val;
|
$type = is_array($val) ? $val[1] : PDO::PARAM_STR;
|
||||||
$type = is_array($val) ? $val[1] : PDO::PARAM_STR;
|
if (PDO::PARAM_STR == $type) {
|
||||||
if (PDO::PARAM_STR == $type) {
|
$value = $this->quote($value);
|
||||||
$value = $this->quote($value);
|
} elseif (PDO::PARAM_INT == $type) {
|
||||||
} elseif (PDO::PARAM_INT == $type) {
|
$value = (float) $value;
|
||||||
$value = (float) $value;
|
|
||||||
}
|
|
||||||
// 判断占位符
|
|
||||||
$sql = is_numeric($key) ?
|
|
||||||
substr_replace($sql, $value, strpos($sql, '?'), 1) :
|
|
||||||
str_replace(
|
|
||||||
[':' . $key . ')', ':' . $key . ',', ':' . $key . ' '],
|
|
||||||
[$value . ')', $value . ',', $value . ' '],
|
|
||||||
$sql . ' ');
|
|
||||||
}
|
}
|
||||||
|
// 判断占位符
|
||||||
|
$sql = is_numeric($key) ?
|
||||||
|
substr_replace($sql, $value, strpos($sql, '?'), 1) :
|
||||||
|
str_replace(
|
||||||
|
[':' . $key . ')', ':' . $key . ',', ':' . $key . ' '],
|
||||||
|
[$value . ')', $value . ',', $value . ' '],
|
||||||
|
$sql . ' ');
|
||||||
}
|
}
|
||||||
return rtrim($sql);
|
return rtrim($sql);
|
||||||
}
|
}
|
||||||
@@ -444,7 +465,7 @@ abstract class Connection
|
|||||||
* @access public
|
* @access public
|
||||||
* @param array $bind 要绑定的参数列表
|
* @param array $bind 要绑定的参数列表
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \think\Exception
|
* @throws BindParamException
|
||||||
*/
|
*/
|
||||||
protected function bindValue(array $bind = [])
|
protected function bindValue(array $bind = [])
|
||||||
{
|
{
|
||||||
@@ -463,7 +484,34 @@ abstract class Connection
|
|||||||
throw new BindParamException(
|
throw new BindParamException(
|
||||||
"Error occurred when binding parameters '{$param}'",
|
"Error occurred when binding parameters '{$param}'",
|
||||||
$this->config,
|
$this->config,
|
||||||
$this->queryStr,
|
$this->getLastsql(),
|
||||||
|
$bind
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储过程的输入输出参数绑定
|
||||||
|
* @access public
|
||||||
|
* @param array $bind 要绑定的参数列表
|
||||||
|
* @return void
|
||||||
|
* @throws BindParamException
|
||||||
|
*/
|
||||||
|
protected function bindParam($bind)
|
||||||
|
{
|
||||||
|
foreach ($bind as $key => $val) {
|
||||||
|
if (is_numeric($key)) {
|
||||||
|
$key = $key + 1;
|
||||||
|
}
|
||||||
|
array_unshift($val, $key);
|
||||||
|
$result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val);
|
||||||
|
if (!$result) {
|
||||||
|
$param = array_shift($val);
|
||||||
|
throw new BindParamException(
|
||||||
|
"Error occurred when binding parameters '{$param}'",
|
||||||
|
$this->config,
|
||||||
|
$this->getLastsql(),
|
||||||
$bind
|
$bind
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -473,19 +521,19 @@ abstract class Connection
|
|||||||
/**
|
/**
|
||||||
* 获得数据集
|
* 获得数据集
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param bool|string $class true 返回PDOStatement 字符串用于指定返回的类名
|
* @param bool $pdo 是否返回PDOStatement
|
||||||
* @param bool $procedure 是否存储过程
|
* @param bool $procedure 是否存储过程
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
protected function getResult($class = '', $procedure = false)
|
protected function getResult($pdo = false, $procedure = false)
|
||||||
{
|
{
|
||||||
if (true === $class) {
|
if ($pdo) {
|
||||||
// 返回PDOStatement对象处理
|
// 返回PDOStatement对象处理
|
||||||
return $this->PDOStatement;
|
return $this->PDOStatement;
|
||||||
}
|
}
|
||||||
if ($procedure) {
|
if ($procedure) {
|
||||||
// 存储过程返回结果
|
// 存储过程返回结果
|
||||||
return $this->procedure($class);
|
return $this->procedure();
|
||||||
}
|
}
|
||||||
$result = $this->PDOStatement->fetchAll($this->fetchType);
|
$result = $this->PDOStatement->fetchAll($this->fetchType);
|
||||||
$this->numRows = count($result);
|
$this->numRows = count($result);
|
||||||
@@ -500,14 +548,13 @@ abstract class Connection
|
|||||||
/**
|
/**
|
||||||
* 获得存储过程数据集
|
* 获得存储过程数据集
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param bool|string $class true 返回PDOStatement 字符串用于指定返回的类名
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function procedure($class)
|
protected function procedure()
|
||||||
{
|
{
|
||||||
$item = [];
|
$item = [];
|
||||||
do {
|
do {
|
||||||
$result = $this->getResult($class);
|
$result = $this->getResult();
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$item[] = $result;
|
$item[] = $result;
|
||||||
}
|
}
|
||||||
@@ -698,7 +745,7 @@ abstract class Connection
|
|||||||
*/
|
*/
|
||||||
public function getLastSql()
|
public function getLastSql()
|
||||||
{
|
{
|
||||||
return $this->queryStr;
|
return $this->getRealSql($this->queryStr, $this->bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -736,7 +783,7 @@ abstract class Connection
|
|||||||
$error = '';
|
$error = '';
|
||||||
}
|
}
|
||||||
if ('' != $this->queryStr) {
|
if ('' != $this->queryStr) {
|
||||||
$error .= "\n [ SQL语句 ] : " . $this->queryStr;
|
$error .= "\n [ SQL语句 ] : " . $this->getLastsql();
|
||||||
}
|
}
|
||||||
return $error;
|
return $error;
|
||||||
}
|
}
|
||||||
@@ -771,7 +818,7 @@ abstract class Connection
|
|||||||
// 记录操作结束时间
|
// 记录操作结束时间
|
||||||
Debug::remark('queryEndTime', 'time');
|
Debug::remark('queryEndTime', 'time');
|
||||||
$runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime');
|
$runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime');
|
||||||
$sql = $sql ?: $this->queryStr;
|
$sql = $sql ?: $this->getLastsql();
|
||||||
$log = $sql . ' [ RunTime:' . $runtime . 's ]';
|
$log = $sql . ' [ RunTime:' . $runtime . 's ]';
|
||||||
$result = [];
|
$result = [];
|
||||||
// SQL性能分析
|
// SQL性能分析
|
||||||
|
|||||||
Reference in New Issue
Block a user