|
|
@ -1,6 +1,6 @@ |
|
|
|
<?php |
|
|
|
<?php |
|
|
|
/** |
|
|
|
/** |
|
|
|
* This file contains the Command class. |
|
|
|
* Command class file. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Qiang Xue <qiang.xue@gmail.com> |
|
|
|
* @author Qiang Xue <qiang.xue@gmail.com> |
|
|
|
* @link http://www.yiiframework.com/ |
|
|
|
* @link http://www.yiiframework.com/ |
|
|
@ -16,30 +16,28 @@ use yii\db\Exception; |
|
|
|
* Command represents a SQL statement to be executed against a database. |
|
|
|
* Command represents a SQL statement to be executed against a database. |
|
|
|
* |
|
|
|
* |
|
|
|
* A command object is usually created by calling [[Connection::createCommand]]. |
|
|
|
* A command object is usually created by calling [[Connection::createCommand]]. |
|
|
|
* The SQL statement it represents can be set via the [[text]] property. |
|
|
|
* The SQL statement it represents can be set via the [[sql]] property. |
|
|
|
* |
|
|
|
* |
|
|
|
* To execute a non-query SQL (such as insert, delete, update), call [[execute]]. |
|
|
|
* To execute a non-query SQL (such as INSERT, DELETE, UPDATE), call [[execute]]. |
|
|
|
* To execute an SQL statement that returns result data set (such as SELECT), |
|
|
|
* To execute a SQL statement that returns result data set (such as SELECT), |
|
|
|
* use [[query]], [[queryRow]], [[queryColumn]], or [[queryScalar]]. |
|
|
|
* use [[query]], [[queryRow]], [[queryColumn]], or [[queryScalar]]. |
|
|
|
* |
|
|
|
* |
|
|
|
* If an SQL statement returns results (such as a SELECT SQL), the results |
|
|
|
* Command supports SQL statement preparation and parameter binding. |
|
|
|
* can be accessed via the returned {@link CDbDataReader}. |
|
|
|
* Call [[bindValue]] to bind a value to a SQL parameter; |
|
|
|
* |
|
|
|
* Call [[bindParam]] to bind a PHP variable to a SQL parameter. |
|
|
|
* Command supports SQL statment preparation and parameter binding. |
|
|
|
|
|
|
|
* Call {@link bindParam} to bind a PHP variable to a parameter in SQL. |
|
|
|
|
|
|
|
* Call {@link bindValue} to bind a value to an SQL parameter. |
|
|
|
|
|
|
|
* When binding a parameter, the SQL statement is automatically prepared. |
|
|
|
* When binding a parameter, the SQL statement is automatically prepared. |
|
|
|
* You may also call {@link prepare} to explicitly prepare an SQL statement. |
|
|
|
* You may also call [[prepare]] to explicitly prepare a SQL statement. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Command can also be used as a query builder that builds and executes a SQL statement |
|
|
|
|
|
|
|
* from code fragments. For example, |
|
|
|
* |
|
|
|
* |
|
|
|
* Starting from version 1.1.6, Command can also be used as a query builder |
|
|
|
* ~~~ |
|
|
|
* that builds a SQL statement from code fragments. For example, |
|
|
|
|
|
|
|
* <pre> |
|
|
|
|
|
|
|
* $user = \Yii::app()->db->createCommand() |
|
|
|
* $user = \Yii::app()->db->createCommand() |
|
|
|
* ->select('username, password') |
|
|
|
* ->select('username, password') |
|
|
|
* ->from('tbl_user') |
|
|
|
* ->from('tbl_user') |
|
|
|
* ->where('id=:id', array(':id'=>1)) |
|
|
|
* ->where('id=:id', array(':id'=>1)) |
|
|
|
* ->queryRow(); |
|
|
|
* ->queryRow(); |
|
|
|
* </pre> |
|
|
|
* ~~~ |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Qiang Xue <qiang.xue@gmail.com> |
|
|
|
* @author Qiang Xue <qiang.xue@gmail.com> |
|
|
|
* @since 2.0 |
|
|
|
* @since 2.0 |
|
|
@ -50,24 +48,36 @@ class Command extends \yii\base\Component |
|
|
|
* @var array the parameters (name=>value) to be bound to the current query. |
|
|
|
* @var array the parameters (name=>value) to be bound to the current query. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public $params = array(); |
|
|
|
public $params = array(); |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @var Connection the DB connection that this command is associated with |
|
|
|
|
|
|
|
*/ |
|
|
|
public $connection; |
|
|
|
public $connection; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @var Query the database query that this command is currently representing |
|
|
|
|
|
|
|
*/ |
|
|
|
public $query; |
|
|
|
public $query; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @var \PDOStatement the PDOStatement object that this command contains |
|
|
|
|
|
|
|
*/ |
|
|
|
public $pdoStatement; |
|
|
|
public $pdoStatement; |
|
|
|
|
|
|
|
|
|
|
|
private $_sql; |
|
|
|
|
|
|
|
private $_paramLog = array(); |
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Set the default fetch mode for this statement |
|
|
|
* @var mixed the default fetch mode for this command. |
|
|
|
* @param mixed $mode fetch mode |
|
|
|
|
|
|
|
* @return Command |
|
|
|
|
|
|
|
* @see http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php |
|
|
|
* @see http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public $fetchMode = \PDO::FETCH_ASSOC; |
|
|
|
public $fetchMode = \PDO::FETCH_ASSOC; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|
|
|
|
* @var string the SQL statement that this command represents |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private $_sql; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @var array the parameter log information |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private $_paramLog = array(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Constructor. |
|
|
|
* Constructor. |
|
|
|
* @param CDbConnection $connection the database connection |
|
|
|
* @param Connection $connection the database connection |
|
|
|
* @param mixed $query the DB query to be executed. This can be either |
|
|
|
* @param mixed $query the DB query to be executed. This can be either |
|
|
|
* a string representing a SQL statement, or an array whose name-value pairs |
|
|
|
* a string representing a SQL statement, or an array whose name-value pairs |
|
|
|
* will be used to set the corresponding properties of the created command object. |
|
|
|
* will be used to set the corresponding properties of the created command object. |
|
|
@ -91,13 +101,11 @@ class Command extends \yii\base\Component |
|
|
|
$this->connection = $connection; |
|
|
|
$this->connection = $connection; |
|
|
|
if (is_object($query)) { |
|
|
|
if (is_object($query)) { |
|
|
|
$this->query = $query; |
|
|
|
$this->query = $query; |
|
|
|
} |
|
|
|
} else { |
|
|
|
else { |
|
|
|
|
|
|
|
$this->query = new Query; |
|
|
|
$this->query = new Query; |
|
|
|
if (is_array($query)) { |
|
|
|
if (is_array($query)) { |
|
|
|
$this->query->fromArray($query); |
|
|
|
$this->query->fromArray($query); |
|
|
|
} |
|
|
|
} else { |
|
|
|
else { |
|
|
|
|
|
|
|
$this->_sql = $query; |
|
|
|
$this->_sql = $query; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -109,15 +117,14 @@ class Command extends \yii\base\Component |
|
|
|
* multiple times for building different queries. |
|
|
|
* multiple times for building different queries. |
|
|
|
* Calling this method will clean up all internal states of the command object. |
|
|
|
* Calling this method will clean up all internal states of the command object. |
|
|
|
* @return Command this command instance |
|
|
|
* @return Command this command instance |
|
|
|
* @since 1.1.6 |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public function reset() |
|
|
|
public function reset() |
|
|
|
{ |
|
|
|
{ |
|
|
|
$this->_sql = null; |
|
|
|
|
|
|
|
$this->query = new Query; |
|
|
|
$this->query = new Query; |
|
|
|
$this->pdoStatement = null; |
|
|
|
$this->pdoStatement = null; |
|
|
|
$this->_paramLog = array(); |
|
|
|
|
|
|
|
$this->params = array(); |
|
|
|
$this->params = array(); |
|
|
|
|
|
|
|
$this->_paramLog = array(); |
|
|
|
|
|
|
|
$this->_sql = null; |
|
|
|
return $this; |
|
|
|
return $this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -135,15 +142,14 @@ class Command extends \yii\base\Component |
|
|
|
/** |
|
|
|
/** |
|
|
|
* Specifies the SQL statement to be executed. |
|
|
|
* Specifies the SQL statement to be executed. |
|
|
|
* Any previous execution will be terminated or cancel. |
|
|
|
* Any previous execution will be terminated or cancel. |
|
|
|
* @param string $value the SQL statement to be executed |
|
|
|
* @param string $value the SQL statement to be set. |
|
|
|
* @return Command this command instance |
|
|
|
* @return Command this command instance |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public function setSql($value) |
|
|
|
public function setSql($value) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ($this->connection->tablePrefix !== null && strpos($value, '{') !== false) { |
|
|
|
if ($this->connection->tablePrefix !== null && strpos($value, '{{') !== false) { |
|
|
|
$this->_sql = preg_replace('/{{(.*?)}}/', $this->connection->tablePrefix . '\1', $value); |
|
|
|
$this->_sql = preg_replace('/{{(.*?)}}/', $this->connection->tablePrefix . '\1', $value); |
|
|
|
} |
|
|
|
} else { |
|
|
|
else { |
|
|
|
|
|
|
|
$this->_sql = $value; |
|
|
|
$this->_sql = $value; |
|
|
|
} |
|
|
|
} |
|
|
|
$this->cancel(); |
|
|
|
$this->cancel(); |
|
|
@ -160,15 +166,16 @@ class Command extends \yii\base\Component |
|
|
|
public function prepare() |
|
|
|
public function prepare() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ($this->pdoStatement == null) { |
|
|
|
if ($this->pdoStatement == null) { |
|
|
|
|
|
|
|
$sql = $this->getSql(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
$this->pdoStatement = $this->connection->pdo->prepare($this->getSql()); |
|
|
|
$this->pdoStatement = $this->connection->pdo->prepare($sql); |
|
|
|
$this->_paramLog = array(); |
|
|
|
$this->_paramLog = array(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch(\Exception $e) { |
|
|
|
catch(\Exception $e) { |
|
|
|
\Yii::log('Error in preparing SQL: ' . $this->getSql(), CLogger::LEVEL_ERROR, 'system.db.Command'); |
|
|
|
\Yii::error("Failed to prepare SQL ($sql): " . $e->getMessage(), __CLASS__); |
|
|
|
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; |
|
|
|
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; |
|
|
|
throw new Exception('Unable to prepare the SQL statement: {error}', |
|
|
|
$message = YII_DEBUG ? 'Failed to prepare SQL: ' . $e->getMessage() : 'Failed to prepare SQL.'; |
|
|
|
array('{error}' => $e->getMessage()), (int)$e->getCode(), $errorInfo); |
|
|
|
throw new Exception($message, (int)$e->getCode(), $errorInfo); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -197,14 +204,15 @@ class Command extends \yii\base\Component |
|
|
|
public function bindParam($name, &$value, $dataType = null, $length = null, $driverOptions = null) |
|
|
|
public function bindParam($name, &$value, $dataType = null, $length = null, $driverOptions = null) |
|
|
|
{ |
|
|
|
{ |
|
|
|
$this->prepare(); |
|
|
|
$this->prepare(); |
|
|
|
if ($dataType === null) |
|
|
|
if ($dataType === null) { |
|
|
|
$this->pdoStatement->bindParam($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
$this->pdoStatement->bindParam($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
elseif ($length === null) |
|
|
|
} elseif ($length === null) { |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType); |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType); |
|
|
|
elseif ($driverOptions === null) |
|
|
|
} elseif ($driverOptions === null) { |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType, $length); |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType, $length); |
|
|
|
else |
|
|
|
} else { |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType, $length, $driverOptions); |
|
|
|
$this->pdoStatement->bindParam($name, $value, $dataType, $length, $driverOptions); |
|
|
|
|
|
|
|
} |
|
|
|
$this->_paramLog[$name] =& $value; |
|
|
|
$this->_paramLog[$name] =& $value; |
|
|
|
return $this; |
|
|
|
return $this; |
|
|
|
} |
|
|
|
} |
|
|
@ -223,10 +231,11 @@ class Command extends \yii\base\Component |
|
|
|
public function bindValue($name, $value, $dataType = null) |
|
|
|
public function bindValue($name, $value, $dataType = null) |
|
|
|
{ |
|
|
|
{ |
|
|
|
$this->prepare(); |
|
|
|
$this->prepare(); |
|
|
|
if ($dataType === null) |
|
|
|
if ($dataType === null) { |
|
|
|
$this->pdoStatement->bindValue($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
$this->pdoStatement->bindValue($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
else |
|
|
|
} else { |
|
|
|
$this->pdoStatement->bindValue($name, $value, $dataType); |
|
|
|
$this->pdoStatement->bindValue($name, $value, $dataType); |
|
|
|
|
|
|
|
} |
|
|
|
$this->_paramLog[$name] = $value; |
|
|
|
$this->_paramLog[$name] = $value; |
|
|
|
return $this; |
|
|
|
return $this; |
|
|
|
} |
|
|
|
} |
|
|
@ -244,8 +253,7 @@ class Command extends \yii\base\Component |
|
|
|
public function bindValues($values) |
|
|
|
public function bindValues($values) |
|
|
|
{ |
|
|
|
{ |
|
|
|
$this->prepare(); |
|
|
|
$this->prepare(); |
|
|
|
foreach ($values as $name => $value) |
|
|
|
foreach ($values as $name => $value) { |
|
|
|
{ |
|
|
|
|
|
|
|
$this->pdoStatement->bindValue($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
$this->pdoStatement->bindValue($name, $value, $this->connection->getPdoType(gettype($value))); |
|
|
|
$this->_paramLog[$name] = $value; |
|
|
|
$this->_paramLog[$name] = $value; |
|
|
|
} |
|
|
|
} |
|
|
@ -311,7 +319,7 @@ class Command extends \yii\base\Component |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Executes the SQL statement and returns query result. |
|
|
|
* Executes the SQL statement and returns query result. |
|
|
|
* This method is for executing an SQL query that returns result set. |
|
|
|
* This method is for executing a SQL query that returns result set. |
|
|
|
* @param array $params input parameters (name=>value) for the SQL execution. This is an alternative |
|
|
|
* @param array $params input parameters (name=>value) for the SQL execution. This is an alternative |
|
|
|
* to {@link bindParam} and {@link bindValue}. If you have multiple input parameters, passing |
|
|
|
* to {@link bindParam} and {@link bindValue}. If you have multiple input parameters, passing |
|
|
|
* them in this way can improve the performance. Note that if you pass parameters in this way, |
|
|
|
* them in this way can improve the performance. Note that if you pass parameters in this way, |
|
|
|