Browse Source

...

tags/2.0.0-beta
Qiang Xue 13 years ago
parent
commit
c63c78385e
  1. 2
      framework/YiiBase.php
  2. 2
      framework/base/Application.php
  3. 2
      framework/base/ApplicationComponent.php
  4. 2
      framework/base/Object.php
  5. 2
      framework/db/Migration.php
  6. 2
      framework/db/ar/ActiveRecord.php
  7. 7
      framework/db/dao/ColumnSchema.php
  8. 604
      framework/db/dao/Command.php
  9. 946
      framework/db/dao/Query.php
  10. 20
      framework/db/dao/QueryBuilder.php
  11. 4
      framework/db/dao/Schema.php
  12. 2
      framework/logging/DbTarget.php
  13. 2
      framework/logging/FileTarget.php
  14. 2
      framework/logging/ProfileTarget.php
  15. 4
      framework/logging/Router.php
  16. 4
      framework/logging/Target.php
  17. 2
      framework/logging/WebTarget.php
  18. 4
      framework/validators/CaptchaValidator.php
  19. 2
      framework/validators/StringValidator.php
  20. 33
      tests/unit/framework/db/dao/CommandTest.php

2
framework/YiiBase.php

@ -64,7 +64,7 @@ class YiiBase
/** /**
* @var yii\base\Application the application instance * @var yii\base\Application the application instance
*/ */
public static $app; public static $application;
/** /**
* @var array registered path aliases * @var array registered path aliases
* @see getAlias * @see getAlias

2
framework/base/Application.php

@ -116,7 +116,7 @@ abstract class Application extends Module
*/ */
public function __construct($config = null) public function __construct($config = null)
{ {
\Yii::$app = $this; \Yii::$application = $this;
// set basePath at early as possible to avoid trouble // set basePath at early as possible to avoid trouble
if (is_string($config)) { if (is_string($config)) {

2
framework/base/ApplicationComponent.php

@ -30,7 +30,7 @@ abstract class ApplicationComponent extends Component implements Initable
/** /**
* Initializes the application component. * Initializes the application component.
* This method is invoked after the component is created and its property values are * This method is invoked after the component is created and its property values are
* initialized. The default implementation will call [[Component::attachBehaviors]] * initialized. The default implementation will call [[Component::attachBehaviors()]]
* to attach behaviors declared in [[behaviors]]. * to attach behaviors declared in [[behaviors]].
* If you override this method, make sure to call the parent implementation. * If you override this method, make sure to call the parent implementation.
*/ */

2
framework/base/Object.php

@ -294,7 +294,7 @@ class Object
* $model->init(); * $model->init();
* ~~~ * ~~~
* *
* @return object the created object * @return Object the created object
* @throws Exception if the configuration is invalid. * @throws Exception if the configuration is invalid.
*/ */
public static function newInstance() public static function newInstance()

2
framework/db/Migration.php

@ -120,7 +120,7 @@ abstract class CDbMigration extends yii\base\Component
public function getDbConnection() public function getDbConnection()
{ {
if ($this->_db === null) { if ($this->_db === null) {
$this->_db = Yii::app()->getComponent('db'); $this->_db = \Yii::$application->getComponent('db');
if (!$this->_db instanceof CDbConnection) if (!$this->_db instanceof CDbConnection)
throw new CException(Yii::t('yii', 'The "db" application component must be configured to be a CDbConnection object.')); throw new CException(Yii::t('yii', 'The "db" application component must be configured to be a CDbConnection object.'));
} }

2
framework/db/ar/ActiveRecord.php

@ -611,7 +611,7 @@ abstract class ActiveRecord extends \yii\base\Model
return self::$db; return self::$db;
else else
{ {
self::$db = Yii::app()->getDb(); self::$db = \Yii::$application->getDb();
if (self::$db instanceof CDbConnection) if (self::$db instanceof CDbConnection)
return self::$db; return self::$db;
else else

7
framework/db/dao/ColumnSchema.php

@ -23,7 +23,7 @@ class ColumnSchema extends \yii\base\Component
*/ */
public $name; public $name;
/** /**
* @var string raw name of this column. This is the quoted name that can be used in SQL queries. * @var string raw name of this column. This is the quoted name that can be directly used in SQL queries.
*/ */
public $quotedName; public $quotedName;
/** /**
@ -32,7 +32,8 @@ class ColumnSchema extends \yii\base\Component
public $allowNull; public $allowNull;
/** /**
* @var string logical type of this column. Possible logic types include: * @var string logical type of this column. Possible logic types include:
* string, text, boolean, smallint, integer, bigint, float, decimal, datetime, timestamp, time, date, binary, money * string, text, boolean, smallint, integer, bigint, float, decimal, datetime,
* timestamp, time, date, binary, and money.
*/ */
public $type; public $type;
/** /**
@ -41,7 +42,7 @@ class ColumnSchema extends \yii\base\Component
*/ */
public $phpType; public $phpType;
/** /**
* @var string the DB type of this column. * @var string the DB type of this column. Possible DB types vary according to the DBMS.
*/ */
public $dbType; public $dbType;
/** /**

604
framework/db/dao/Command.php

@ -15,34 +15,23 @@ 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 [[sql]] 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 a SQL statement that returns result data set (such as SELECT), * To execute a SQL statement that returns result data set (such as SELECT),
* use [[queryAll]], [[queryRow]], [[queryColumn]], [[queryScalar]], or [[query]]. * use [[queryAll()]], [[queryRow()]], [[queryColumn()]], [[queryScalar()]], or [[query()]].
* For example, * For example,
* *
* ~~~ * ~~~
* $users = \Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll(); * $users = \Yii::$application->db->createCommand('SELECT * FROM tbl_user')->queryAll();
* ~~~ * ~~~
* *
* Command supports SQL statement preparation and parameter binding. * Command supports SQL statement preparation and parameter binding.
* Call [[bindValue]] to bind a value to a SQL parameter; * Call [[bindValue()]] to bind a value to a SQL parameter;
* Call [[bindParam]] to bind a PHP variable to a SQL parameter. * Call [[bindParam()]] to bind a PHP variable to a 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 [[prepare]] explicitly to prepare a SQL statement. * You may also call [[prepare()]] explicitly to prepare a SQL statement.
*
* Command can be used as a query builder that builds and executes a SQL statement
* from code fragments. For example,
*
* ~~~
* $user = \Yii::app()->db->createCommand()
* ->select('username, password')
* ->from('tbl_user')
* ->where('id=:id', array(':id'=>1))
* ->queryRow();
* ~~~
* *
* @property string $sql the SQL statement to be executed * @property string $sql the SQL statement to be executed
* *
@ -56,10 +45,6 @@ class Command extends \yii\base\Component
*/ */
public $connection; public $connection;
/** /**
* @var Query the database query that this command is currently representing
*/
public $query;
/**
* @var \PDOStatement the PDOStatement object that this command contains * @var \PDOStatement the PDOStatement object that this command contains
*/ */
public $pdoStatement; public $pdoStatement;
@ -68,7 +53,6 @@ class Command extends \yii\base\Component
* @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 * @var string the SQL statement that this command represents
*/ */
@ -80,72 +64,48 @@ class Command extends \yii\base\Component
/** /**
* Constructor. * Constructor.
* Instead of explicitly creating a Command object using `new` operator, * Instead of using the `new` operator, you may use [[Connection::createCommand()]]
* you should use [[Connection::createCommand]] to get a new Command object. * to create a new Command object.
* @param Connection $connection the database connection * @param Connection $connection the database connection
* @param mixed $query the DB query to be executed. This can be: * @param string|array|Query $query the DB query to be executed. This can be:
* *
* - a string representing the SQL statement to be executed * - a string representing the SQL statement to be executed
* - a [[Query]] object representing the SQL query * - a [[Query]] object representing the SQL query
* - an array that will be used to initialize [[Query]] * - an array that will be used to create and initialize the [[Query]] object
* - null (default) if the query needs to be built using query builder methods next.
*/ */
public function __construct($connection, $query = null) public function __construct($connection, $query = null)
{ {
$this->connection = $connection; $this->connection = $connection;
if (is_object($query)) { if (is_array($query)) {
$this->query = $query; $query = Query::newInstance($query);
}
if ($query instanceof Query) {
$this->_sql = $query->getSql($connection);
$this->bindValues($query->params);
} else { } else {
$this->query = new Query; $this->_sql = $query;
if (is_array($query)) {
$this->query->fromArray($query);
} else {
$this->_sql = $query;
}
} }
} }
/** /**
* Cleans up the command and prepares for building a new query.
* This method is mainly used when a command object is being reused
* multiple times for building different queries.
* Calling this method will clean up these properties: [[sql]], [[query]],
* [[pdoStatement]] and [[params]].
* @return Command this command instance
*/
public function reset()
{
$this->query = new Query;
$this->pdoStatement = null;
$this->_params = array();
$this->_sql = null;
return $this;
}
/**
* Returns the SQL statement for this command. * Returns the SQL statement for this command.
* When this method is called, a new SQL statement will be built from [[query]]
* if it has not been done before or if `$rebuild` is `true`.
* @param boolean $rebuild whether to rebuild the SQL statement from [[query]].
* @return string the SQL statement to be executed * @return string the SQL statement to be executed
*/ */
public function getSql($rebuild = false) public function getSql()
{ {
if ($this->_sql === null || $rebuild) {
$this->_sql = $this->query->getSql($this->connection);
}
return $this->_sql; return $this->_sql;
} }
/** /**
* 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 cancelled.
* @param string $value the SQL statement to be set. * @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)
{ {
$this->_sql = $this->connection->expandTablePrefix($value); $this->_sql = $this->connection->expandTablePrefix($value);
$this->_params = array();
$this->cancel(); $this->cancel();
return $this; return $this;
} }
@ -174,7 +134,6 @@ class Command extends \yii\base\Component
/** /**
* Cancels the execution of the SQL statement. * Cancels the execution of the SQL statement.
* This method mainly sets [[pdoStatement]] to be null. * This method mainly sets [[pdoStatement]] to be null.
* Please call [[reset]] if you want to run a different SQL statement.
*/ */
public function cancel() public function cancel()
{ {
@ -183,7 +142,7 @@ class Command extends \yii\base\Component
/** /**
* Binds a parameter to the SQL statement to be executed. * Binds a parameter to the SQL statement to be executed.
* @param mixed $name parameter identifier. For a prepared statement * @param string|integer $name parameter identifier. For a prepared statement
* using named placeholders, this will be a parameter name of * using named placeholders, this will be a parameter name of
* the form `:name`. For a prepared statement using question mark * the form `:name`. For a prepared statement using question mark
* placeholders, this will be the 1-indexed position of the parameter. * placeholders, this will be the 1-indexed position of the parameter.
@ -212,7 +171,7 @@ class Command extends \yii\base\Component
/** /**
* Binds a value to a parameter. * Binds a value to a parameter.
* @param mixed $name Parameter identifier. For a prepared statement * @param string|integer $name Parameter identifier. For a prepared statement
* using named placeholders, this will be a parameter name of * using named placeholders, this will be a parameter name of
* the form `:name`. For a prepared statement using question mark * the form `:name`. For a prepared statement using question mark
* placeholders, this will be the 1-indexed position of the parameter. * placeholders, this will be the 1-indexed position of the parameter.
@ -235,7 +194,7 @@ class Command extends \yii\base\Component
/** /**
* Binds a list of values to the corresponding parameters. * Binds a list of values to the corresponding parameters.
* This is similar to [[bindValue]] except that it binds multiple values at a time. * This is similar to [[bindValue()]] except that it binds multiple values at a time.
* Note that the SQL data type of each value is determined by its PHP type. * Note that the SQL data type of each value is determined by its PHP type.
* @param array $values the values to be bound. This must be given in terms of an associative * @param array $values the values to be bound. This must be given in terms of an associative
* array with array keys being the parameter names, and array values the corresponding parameter values, * array with array keys being the parameter names, and array values the corresponding parameter values,
@ -244,7 +203,13 @@ class Command extends \yii\base\Component
*/ */
public function bindValues($values) public function bindValues($values)
{ {
$this->query->addParams($values); if ($values !== array()) {
$this->prepare();
foreach ($values as $name => $value) {
$this->pdoStatement->bindValue($name, $value, $this->connection->getPdoType(gettype($value)));
$this->_params[$name] = $value;
}
}
return $this; return $this;
} }
@ -253,15 +218,14 @@ class Command extends \yii\base\Component
* This method should only be used for executing non-query SQL statement, such as `INSERT`, `DELETE`, `UPDATE` SQLs. * This method should only be used for executing non-query SQL statement, such as `INSERT`, `DELETE`, `UPDATE` SQLs.
* No result set will be returned. * No result set will be returned.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @return integer number of rows affected by the execution. * @return integer number of rows affected by the execution.
* @throws Exception execution failed * @throws Exception execution failed
*/ */
public function execute($params = array()) public function execute($params = array())
{ {
$sql = $this->getSql(); $sql = $this->getSql();
$params = array_merge($this->query->params, $params);
$this->_params = array_merge($this->_params, $params); $this->_params = array_merge($this->_params, $params);
if ($this->_params === array()) { if ($this->_params === array()) {
$paramLog = ''; $paramLog = '';
@ -303,8 +267,8 @@ 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 a SQL query that returns result set, such as `SELECT`. * This method is for executing a SQL query that returns result set, such as `SELECT`.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @return DataReader the reader object for fetching the query result * @return DataReader the reader object for fetching the query result
* @throws Exception execution failed * @throws Exception execution failed
*/ */
@ -316,8 +280,8 @@ class Command extends \yii\base\Component
/** /**
* Executes the SQL statement and returns ALL rows at once. * Executes the SQL statement and returns ALL rows at once.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php) * @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php)
* for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used. * for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used.
* @return array all rows of the query result. Each array element is an array representing a row of data. * @return array all rows of the query result. Each array element is an array representing a row of data.
@ -333,8 +297,8 @@ class Command extends \yii\base\Component
* Executes the SQL statement and returns the first row of the result. * Executes the SQL statement and returns the first row of the result.
* This method is best used when only the first row of result is needed for a query. * This method is best used when only the first row of result is needed for a query.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php) * @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php)
* for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used. * for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used.
* @return array|boolean the first row (in terms of an array) of the query result. False is returned if the query * @return array|boolean the first row (in terms of an array) of the query result. False is returned if the query
@ -350,9 +314,9 @@ class Command extends \yii\base\Component
* Executes the SQL statement and returns the value of the first column in the first row of data. * Executes the SQL statement and returns the value of the first column in the first row of data.
* This method is best used when only a single value is needed for a query. * This method is best used when only a single value is needed for a query.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @return mixed the value of the first column in the first row of the query result. * @return string|boolean the value of the first column in the first row of the query result.
* False is returned if there is no value. * False is returned if there is no value.
* @throws Exception execution failed * @throws Exception execution failed
*/ */
@ -371,8 +335,8 @@ class Command extends \yii\base\Component
* This method is best used when only the first column of result (i.e. the first element in each row) * This method is best used when only the first column of result (i.e. the first element in each row)
* is needed for a query. * is needed for a query.
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @return array the first column of the query result. Empty array is returned if the query results in nothing. * @return array the first column of the query result. Empty array is returned if the query results in nothing.
* @throws Exception execution failed * @throws Exception execution failed
*/ */
@ -385,8 +349,8 @@ class Command extends \yii\base\Component
* Performs the actual DB query of a SQL statement. * Performs the actual DB query of a SQL statement.
* @param string $method method of PDOStatement to be called * @param string $method method of PDOStatement to be called
* @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 [[bindValues]]. Note that if you pass parameters in this way, any previous call to [[bindParam]] * to [[bindValues()]]. Note that if you pass parameters in this way, any previous call to [[bindParam()]]
* or [[bindValue]] will be ignored. * or [[bindValue()]] will be ignored.
* @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php) * @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php)
* for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used. * for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used.
* @return mixed the method execution result * @return mixed the method execution result
@ -395,7 +359,6 @@ class Command extends \yii\base\Component
{ {
$db = $this->connection; $db = $this->connection;
$sql = $this->getSql(); $sql = $this->getSql();
$params = array_merge($this->query->params, $params);
$this->_params = array_merge($this->_params, $params); $this->_params = array_merge($this->_params, $params);
if ($this->_params === array()) { if ($this->_params === array()) {
$paramLog = ''; $paramLog = '';
@ -406,7 +369,7 @@ class Command extends \yii\base\Component
\Yii::trace("Querying SQL: {$sql}{$paramLog}", __CLASS__); \Yii::trace("Querying SQL: {$sql}{$paramLog}", __CLASS__);
if ($db->queryCachingCount > 0 && $db->queryCachingDuration >= 0 && $method !== '') { if ($db->queryCachingCount > 0 && $db->queryCachingDuration >= 0 && $method !== '') {
$cache = \Yii::app()->getComponent($db->queryCacheID); $cache = \Yii::$application->getComponent($db->queryCacheID);
} }
if (isset($cache)) { if (isset($cache)) {
@ -460,477 +423,4 @@ class Command extends \yii\base\Component
throw new Exception($message, (int)$e->getCode(), $errorInfo); throw new Exception($message, (int)$e->getCode(), $errorInfo);
} }
} }
/**
/**
* Sets the SELECT part of the query.
* @param mixed $columns the columns to be selected. Defaults to '*', meaning all columns.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. array('id', 'name')).
* Columns can contain table prefixes (e.g. "tbl_user.id") and/or column aliases (e.g. "tbl_user.id AS user_id").
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @param boolean $distinct whether to use 'SELECT DISTINCT'.
* @param string $option additional option that should be appended to the 'SELECT' keyword. For example,
* in MySQL, the option 'SQL_CALC_FOUND_ROWS' can be used.
* @return Command the command object itself
*/
public function select($columns = '*', $distinct = false, $option = '')
{
$this->query->select = $columns;
$this->query->distinct = $distinct;
$this->query->selectOption = $option;
return $this;
}
/**
* Sets the FROM part of the query.
* @param mixed $tables the table(s) to be selected from. This can be either a string (e.g. 'tbl_user')
* or an array (e.g. array('tbl_user', 'tbl_profile')) specifying one or several table names.
* Table names can contain schema prefixes (e.g. 'public.tbl_user') and/or table aliases (e.g. 'tbl_user u').
* The method will automatically quote the table names unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Command the command object itself
*/
public function from($tables)
{
$this->query->from = $tables;
return $this;
}
/**
* Sets the WHERE part of the query.
*
* The method requires a $conditions parameter, and optionally a $params parameter
* specifying the values to be bound to the query.
*
* The $conditions parameter should be either a string (e.g. 'id=1') or an array.
* If the latter, it must be in the format `array(operator, operand1, operand2, ...)`,
* where the operator can be one of the followings, and the possible operands depend on the corresponding
* operator:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `array('and', 'id=1', 'id=2')` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `array('and', 'type=1', array('or', 'id=1', 'id=2'))` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing
* the range of the values that the column or DB expression should be in. For example,
* `array('in', 'id', array(1,2,3))` will generate `id IN (1,2,3)`.
* The method will properly quote the column name and escape values in the range.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `array('like', 'name', '%tester%')` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `array('like', 'name', array('%test%', '%sample%'))` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* @param mixed $conditions the conditions that should be put in the WHERE part.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
public function where($conditions, $params = array())
{
$this->query->where = $conditions;
$this->query->addParams($params);
return $this;
}
/**
* Appends an INNER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param mixed $conditions the join condition that should appear in the ON part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
public function join($table, $conditions, $params = array())
{
return $this->joinInternal('JOIN', $table, $conditions, $params);
}
/**
* Appends a LEFT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param mixed $conditions the join condition that should appear in the ON part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
public function leftJoin($table, $conditions, $params = array())
{
return $this->joinInternal('LEFT JOIN', $table, $conditions, $params);
}
/**
* Appends a RIGHT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param mixed $conditions the join condition that should appear in the ON part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
public function rightJoin($table, $conditions, $params = array())
{
return $this->joinInternal('RIGHT JOIN', $table, $conditions, $params);
}
/**
* Appends a CROSS JOIN part to the query.
* Note that not all DBMS support CROSS JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Command the command object itself
*/
public function crossJoin($table)
{
return $this->joinInternal('CROSS JOIN', $table);
}
/**
* Appends a NATURAL JOIN part to the query.
* Note that not all DBMS support NATURAL JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Command the command object itself
*/
public function naturalJoin($table)
{
return $this->joinInternal('NATURAL JOIN', $table);
}
/**
* Sets the GROUP BY part of the query.
* @param mixed $columns the columns to be grouped by.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. array('id', 'name')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Command the command object itself
*/
public function groupBy($columns)
{
$this->query->groupBy = $columns;
return $this;
}
/**
* Sets the HAVING part of the query.
* @param mixed $conditions the conditions to be put after HAVING.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
public function having($conditions, $params = array())
{
$this->query->having = $conditions;
$this->query->addParams($params);
return $this;
}
/**
* Sets the ORDER BY part of the query.
* @param mixed $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array (e.g. array('id ASC', 'name DESC')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Command the command object itself
*/
public function orderBy($columns)
{
$this->query->orderBy = $columns;
return $this;
}
/**
* Sets the LIMIT part of the query.
* @param integer $limit the limit
* @return Command the command object itself
*/
public function limit($limit)
{
$this->query->limit = $limit;
return $this;
}
/**
* Sets the OFFSET part of the query.
* @param integer $offset the offset
* @return Command the command object itself
*/
public function offset($offset)
{
$this->query->offset = $offset;
return $this;
}
/**
* Appends a SQL statement using UNION operator.
* @param string $sql the SQL statement to be appended using UNION
* @return Command the command object itself
*/
public function union($sql)
{
$this->query->union[] = $sql;
return $this->query;
}
/**
* Creates and executes an INSERT SQL statement.
* The method will properly escape the column names, and bind the values to be inserted.
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name=>value) to be inserted into the table.
* @return integer number of rows affected by the execution.
*/
public function insert($table, $columns)
{
$sql = $this->connection->getQueryBuilder()->insert($table, $columns, $params);
return $this->setSql($sql)->execute($params);
}
/**
* Creates and executes an UPDATE SQL statement.
* The method will properly escape the column names and bind the values to be updated.
* @param string $table the table to be updated.
* @param array $columns the column data (name=>value) to be updated.
* @param mixed $conditions the conditions that will be put in the WHERE part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters to be bound to the query.
* @return integer number of rows affected by the execution.
*/
public function update($table, $columns, $conditions = '', $params = array())
{
$sql = $this->connection->getQueryBuilder()->update($table, $columns, $conditions, $params);
return $this->setSql($sql)->execute($params);
}
/**
* Creates and executes a DELETE SQL statement.
* @param string $table the table where the data will be deleted from.
* @param mixed $conditions the conditions that will be put in the WHERE part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters to be bound to the query.
* @return integer number of rows affected by the execution.
*/
public function delete($table, $conditions = '', $params = array())
{
$sql = $this->connection->getQueryBuilder()->delete($table, $conditions);
return $this->setSql($sql)->execute($params);
}
/**
* Builds and executes a SQL statement for creating a new DB table.
*
* The columns in the new table should be specified as name-definition pairs (e.g. 'name'=>'string'),
* where name stands for a column name which will be properly quoted by the method, and definition
* stands for the column type which can contain an abstract DB type.
* The method [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the abstract column types to physical ones. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
*
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly
* inserted into the generated SQL.
*
* @param string $table the name of the table to be created. The name will be properly quoted by the method.
* @param array $columns the columns (name=>definition) in the new table.
* @param string $options additional SQL fragment that will be appended to the generated SQL.
* @return integer number of rows affected by the execution.
*/
public function createTable($table, $columns, $options = null)
{
$sql = $this->connection->getQueryBuilder()->createTable($table, $columns, $options);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for renaming a DB table.
* @param string $table the table to be renamed. The name will be properly quoted by the method.
* @param string $newName the new table name. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function renameTable($table, $newName)
{
$sql = $this->connection->getQueryBuilder()->renameTable($table, $newName);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for dropping a DB table.
* @param string $table the table to be dropped. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function dropTable($table)
{
$sql = $this->connection->getQueryBuilder()->dropTable($table);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for truncating a DB table.
* @param string $table the table to be truncated. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function truncateTable($table)
{
$sql = $this->connection->getQueryBuilder()->truncateTable($table);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for adding a new DB column.
* @param string $table the table that the new column will be added to. The table name will be properly quoted by the method.
* @param string $column the name of the new column. The name will be properly quoted by the method.
* @param string $type the column type. [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the give column type to the physical one. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
* @return integer number of rows affected by the execution.
*/
public function addColumn($table, $column, $type)
{
$sql = $this->connection->getQueryBuilder()->addColumn($table, $column, $type);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for dropping a DB column.
* @param string $table the table whose column is to be dropped. The name will be properly quoted by the method.
* @param string $column the name of the column to be dropped. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function dropColumn($table, $column)
{
$sql = $this->connection->getQueryBuilder()->dropColumn($table, $column);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for renaming a column.
* @param string $table the table whose column is to be renamed. The name will be properly quoted by the method.
* @param string $name the old name of the column. The name will be properly quoted by the method.
* @param string $newName the new name of the column. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function renameColumn($table, $name, $newName)
{
$sql = $this->connection->getQueryBuilder()->renameColumn($table, $name, $newName);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for changing the definition of a column.
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
* @param string $column the name of the column to be changed. The name will be properly quoted by the method.
* @param string $type the column type. [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the give column type to the physical one. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
* @return integer number of rows affected by the execution.
*/
public function alterColumn($table, $column, $type)
{
$sql = $this->connection->getQueryBuilder()->alterColumn($table, $column, $type);
return $this->setSql($sql)->execute();
}
/**
* Builds a SQL statement for adding a foreign key constraint to an existing table.
* The method will properly quote the table and column names.
* @param string $name the name of the foreign key constraint.
* @param string $table the table that the foreign key constraint will be added to.
* @param string $columns the name of the column to that the constraint will be added on. If there are multiple columns, separate them with commas.
* @param string $refTable the table that the foreign key references to.
* @param string $refColumns the name of the column that the foreign key references to. If there are multiple columns, separate them with commas.
* @param string $delete the ON DELETE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @param string $update the ON UPDATE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @return integer number of rows affected by the execution.
*/
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
{
$sql = $this->connection->getQueryBuilder()->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update);
return $this->setSql($sql)->execute();
}
/**
* Builds a SQL statement for dropping a foreign key constraint.
* @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function dropForeignKey($name, $table)
{
$sql = $this->connection->getQueryBuilder()->dropForeignKey($name, $table);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for creating a new index.
* @param string $name the name of the index. The name will be properly quoted by the method.
* @param string $table the table that the new index will be created for. The table name will be properly quoted by the method.
* @param string $column the column(s) that should be included in the index. If there are multiple columns, please separate them
* by commas. The column names will be properly quoted by the method.
* @param boolean $unique whether to add UNIQUE constraint on the created index.
* @return integer number of rows affected by the execution.
*/
public function createIndex($name, $table, $column, $unique = false)
{
$sql = $this->connection->getQueryBuilder()->createIndex($name, $table, $column, $unique);
return $this->setSql($sql)->execute();
}
/**
* Builds and executes a SQL statement for dropping an index.
* @param string $name the name of the index to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose index is to be dropped. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution.
*/
public function dropIndex($name, $table)
{
$sql = $this->connection->getQueryBuilder()->dropIndex($name, $table);
return $this->setSql($sql)->execute();
}
/**
* Appends an JOIN part to the query.
* @param string $type the join type ('join', 'left join', 'right join', 'cross join', 'natural join')
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param mixed $conditions the join condition that should appear in the ON part.
* Please refer to [[where]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Command the command object itself
*/
private function joinInternal($type, $table, $conditions = '', $params = array())
{
$this->query->join[] = array($type, $table, $conditions);
$this->query->addParams($params);
return $this;
}
} }

946
framework/db/dao/Query.php

@ -71,7 +71,7 @@ class Query extends \yii\base\Object
public $join; public $join;
/** /**
* @var string|array the condition to be applied in the GROUP BY clause. * @var string|array the condition to be applied in the GROUP BY clause.
* It can be either a string or an array. Please refer to [[where]] on how to specify the condition. * It can be either a string or an array. Please refer to [[where()]] on how to specify the condition.
*/ */
public $having; public $having;
/** /**
@ -85,17 +85,640 @@ class Query extends \yii\base\Object
* Each union clause can be a string or a `Query` object which refers to the SQL statement. * Each union clause can be a string or a `Query` object which refers to the SQL statement.
*/ */
public $union; public $union;
/**
* @var array the operation that this query represents. This refers to the method call as well as
* the corresponding parameters for constructing non-query SQL statements (e.g. INSERT, CREATE TABLE).
* This property is mainly maintained by methods such as [[insert()]], [[update()]], [[createTable()]].
* When this property is not set, it means this query represents a SELECT statement.
*/
public $operation;
/**
/**
* Sets the SELECT part of the query.
* @param mixed $columns the columns to be selected. Defaults to '*', meaning all columns.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. array('id', 'name')).
* Columns can contain table prefixes (e.g. "tbl_user.id") and/or column aliases (e.g. "tbl_user.id AS user_id").
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @param boolean $distinct whether to use 'SELECT DISTINCT'.
* @param string $option additional option that should be appended to the 'SELECT' keyword. For example,
* in MySQL, the option 'SQL_CALC_FOUND_ROWS' can be used.
* @return Query the query object itself
*/
public function select($columns = '*', $distinct = false, $option = '')
{
$this->select = $columns;
$this->distinct = $distinct;
$this->selectOption = $option;
return $this;
}
/** /**
* @param Connection $connection * Sets the FROM part of the query.
* @return string * @param mixed $tables the table(s) to be selected from. This can be either a string (e.g. 'tbl_user')
* or an array (e.g. array('tbl_user', 'tbl_profile')) specifying one or several table names.
* Table names can contain schema prefixes (e.g. 'public.tbl_user') and/or table aliases (e.g. 'tbl_user u').
* The method will automatically quote the table names unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Query the query object itself
*/ */
public function getSql($connection) public function from($tables)
{ {
return $connection->getQueryBuilder()->build($this); $this->from = $tables;
return $this;
}
/**
* Sets the WHERE part of the query.
*
* The method requires a $condition parameter, and optionally a $params parameter
* specifying the values to be bound to the query.
*
* The $condition parameter should be either a string (e.g. 'id=1') or an array.
* If the latter, it must be in the format of `array(operator, operand1, operand2, ...)`,
* where the operator can be one of the followings, and the possible operands depend on the corresponding
* operator:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `array('and', 'id=1', 'id=2')` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `array('and', 'type=1', array('or', 'id=1', 'id=2'))` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `between`: operand 1 should be the column name, and operand 2 and 3 should be the
* starting and ending values of the range that the column is in.
* For example, `array('between', 'id', 1, 10)` will generate `id BETWEEN 1 AND 10`.
*
* - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
* in the generated condition.
*
* - `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing
* the range of the values that the column or DB expression should be in. For example,
* `array('in', 'id', array(1,2,3))` will generate `id IN (1,2,3)`.
* The method will properly quote the column name and escape values in the range.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `array('like', 'name', '%tester%')` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `array('like', 'name', array('%test%', '%sample%'))` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* @param string|array $condition the conditions that should be put in the WHERE part.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see andWhere()
* @see orWhere()
*/
public function where($condition, $params = array())
{
$this->where = $condition;
$this->addParams($params);
return $this;
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see where()
* @see orWhere()
*/
public function andWhere($condition, $params = array())
{
if ($this->where === null) {
$this->where = $condition;
} else {
$this->where = array('and', $this->where, $condition);
}
$this->addParams($params);
return $this;
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see where()
* @see andWhere()
*/
public function orWhere($condition, $params = array())
{
if ($this->where === null) {
$this->where = $condition;
} else {
$this->where = array('or', $this->where, $condition);
}
$this->addParams($params);
return $this;
}
/**
* Appends an INNER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
*/
public function join($table, $condition, $params = array())
{
$this->join[] = array('JOIN', $table, $condition);
return $this->addParams($params);
}
/**
* Appends a LEFT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
*/
public function leftJoin($table, $condition, $params = array())
{
$this->join[] = array('LEFT JOIN', $table, $condition);
return $this->addParams($params);
}
/**
* Appends a RIGHT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
*/
public function rightJoin($table, $condition, $params = array())
{
$this->join[] = array('RIGHT JOIN', $table, $condition);
return $this->addParams($params);
}
/**
* Appends a CROSS JOIN part to the query.
* Note that not all DBMS support CROSS JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Query the query object itself
*/
public function crossJoin($table)
{
$this->join[] = array('CROSS JOIN', $table);
return $this;
}
/**
* Appends a NATURAL JOIN part to the query.
* Note that not all DBMS support NATURAL JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return Query the query object itself
*/
public function naturalJoin($table)
{
$this->join[] = array('NATURAL JOIN', $table);
return $this;
}
/**
* Sets the GROUP BY part of the query.
* @param string|array $columns the columns to be grouped by.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. array('id', 'name')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Query the query object itself
* @see addGroupBy()
*/
public function groupBy($columns)
{
$this->groupBy = $columns;
return $this;
}
/**
* Adds additional group-by columns to the existing ones.
* @param string|array $columns additional columns to be grouped by.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. array('id', 'name')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Query the query object itself
* @see groupBy()
*/
public function addGroupBy($columns)
{
if (empty($this->groupBy)) {
$this->groupBy = $columns;
} else {
if (!is_array($this->groupBy)) {
$this->groupBy = preg_split('/\s*,\s*/', trim($this->groupBy), -1, PREG_SPLIT_NO_EMPTY);
}
if (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
}
$this->groupBy = array_merge($this->groupBy, $columns);
}
return $this;
}
/**
* Sets the HAVING part of the query.
* @param string|array $condition the conditions to be put after HAVING.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see andHaving()
* @see orHaving()
*/
public function having($condition, $params = array())
{
$this->having = $condition;
$this->addParams($params);
return $this;
}
/**
* Adds an additional HAVING condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new HAVING condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see having()
* @see orHaving()
*/
public function andHaving($condition, $params = array())
{
if ($this->having === null) {
$this->having = $condition;
} else {
$this->having = array('and', $this->having, $condition);
}
$this->addParams($params);
return $this;
} }
/**
* Adds an additional HAVING condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new HAVING condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return Query the query object itself
* @see having()
* @see andHaving()
*/
public function orHaving($condition, $params = array())
{
if ($this->having === null) {
$this->having = $condition;
} else {
$this->having = array('or', $this->having, $condition);
}
$this->addParams($params);
return $this;
}
/**
* Sets the ORDER BY part of the query.
* @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array (e.g. array('id ASC', 'name DESC')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Query the query object itself
* @see addOrderBy()
*/
public function orderBy($columns)
{
$this->orderBy = $columns;
return $this;
}
/**
* Adds additional ORDER BY columns to the query.
* @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array (e.g. array('id ASC', 'name DESC')).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Query the query object itself
* @see orderBy()
*/
public function addOrderBy($columns)
{
if (empty($this->orderBy)) {
$this->orderBy = $columns;
} else {
if (!is_array($this->orderBy)) {
$this->orderBy = preg_split('/\s*,\s*/', trim($this->orderBy), -1, PREG_SPLIT_NO_EMPTY);
}
if (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
}
$this->orderBy = array_merge($this->orderBy, $columns);
}
return $this;
}
/**
* Sets the LIMIT part of the query.
* @param integer $limit the limit
* @return Query the query object itself
*/
public function limit($limit)
{
$this->limit = $limit;
return $this;
}
/**
* Sets the OFFSET part of the query.
* @param integer $offset the offset
* @return Query the query object itself
*/
public function offset($offset)
{
$this->offset = $offset;
return $this;
}
/**
* Appends a SQL statement using UNION operator.
* @param string $sql the SQL statement to be appended using UNION
* @return Query the query object itself
*/
public function union($sql)
{
$this->union[] = $sql;
return $this;
}
/**
* Creates and executes an INSERT SQL statement.
* The method will properly escape the column names, and bind the values to be inserted.
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name=>value) to be inserted into the table.
* @return Query the query object itself
*/
public function insert($table, $columns)
{
$this->operation = array('insert', $table, $columns);
return $this;
}
/**
* Creates and executes an UPDATE SQL statement.
* The method will properly escape the column names and bind the values to be updated.
* @param string $table the table to be updated.
* @param array $columns the column data (name=>value) to be updated.
* @param string|array $condition the conditions that will be put in the WHERE part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters to be bound to the query.
* @return Query the query object itself
*/
public function update($table, $columns, $condition = '', $params = array())
{
$this->operation = array('update', $table, $columns, $condition, $params);
return $this;
}
/**
* Creates and executes a DELETE SQL statement.
* @param string $table the table where the data will be deleted from.
* @param string|array $condition the conditions that will be put in the WHERE part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters to be bound to the query.
* @return Query the query object itself
*/
public function delete($table, $condition = '', $params = array())
{
$this->operation = array('delete', $table, $condition, $params);
return $this;
}
/**
* Builds and executes a SQL statement for creating a new DB table.
*
* The columns in the new table should be specified as name-definition pairs (e.g. 'name'=>'string'),
* where name stands for a column name which will be properly quoted by the method, and definition
* stands for the column type which can contain an abstract DB type.
* The method [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the abstract column types to physical ones. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
*
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly
* inserted into the generated SQL.
*
* @param string $table the name of the table to be created. The name will be properly quoted by the method.
* @param array $columns the columns (name=>definition) in the new table.
* @param string $options additional SQL fragment that will be appended to the generated SQL.
* @return Query the query object itself
*/
public function createTable($table, $columns, $options = null)
{
$this->operation = array('createTable', $table, $columns, $options);
return $this;
}
/**
* Builds and executes a SQL statement for renaming a DB table.
* @param string $table the table to be renamed. The name will be properly quoted by the method.
* @param string $newName the new table name. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function renameTable($table, $newName)
{
$this->operation = array('renameTable', $table, $newName);
return $this;
}
/**
* Builds and executes a SQL statement for dropping a DB table.
* @param string $table the table to be dropped. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function dropTable($table)
{
$this->operation = array('dropTable', $table);
return $this;
}
/**
* Builds and executes a SQL statement for truncating a DB table.
* @param string $table the table to be truncated. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function truncateTable($table)
{
$this->operation = array('truncateTable', $table);
return $this;
}
/**
* Builds and executes a SQL statement for adding a new DB column.
* @param string $table the table that the new column will be added to. The table name will be properly quoted by the method.
* @param string $column the name of the new column. The name will be properly quoted by the method.
* @param string $type the column type. [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the give column type to the physical one. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
* @return Query the query object itself
*/
public function addColumn($table, $column, $type)
{
$this->operation = array('addColumn', $table, $column, $type);
return $this;
}
/**
* Builds and executes a SQL statement for dropping a DB column.
* @param string $table the table whose column is to be dropped. The name will be properly quoted by the method.
* @param string $column the name of the column to be dropped. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function dropColumn($table, $column)
{
$this->operation = array('dropColumn', $table, $column);
return $this;
}
/**
* Builds and executes a SQL statement for renaming a column.
* @param string $table the table whose column is to be renamed. The name will be properly quoted by the method.
* @param string $name the old name of the column. The name will be properly quoted by the method.
* @param string $newName the new name of the column. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function renameColumn($table, $name, $newName)
{
$this->operation = array('renameColumn', $table, $name, $newName);
return $this;
}
/**
* Builds and executes a SQL statement for changing the definition of a column.
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
* @param string $column the name of the column to be changed. The name will be properly quoted by the method.
* @param string $type the column type. [[\yii\db\dao\QueryBuilder::getColumnType()]] will be called
* to convert the give column type to the physical one. For example, `string` will be converted
* as `varchar(255)`, and `string not null` becomes `varchar(255) not null`.
* @return Query the query object itself
*/
public function alterColumn($table, $column, $type)
{
$this->operation = array('alterColumn', $table, $column, $type);
return $this;
}
/**
* Builds a SQL statement for adding a foreign key constraint to an existing table.
* The method will properly quote the table and column names.
* @param string $name the name of the foreign key constraint.
* @param string $table the table that the foreign key constraint will be added to.
* @param string $columns the name of the column to that the constraint will be added on. If there are multiple columns, separate them with commas.
* @param string $refTable the table that the foreign key references to.
* @param string $refColumns the name of the column that the foreign key references to. If there are multiple columns, separate them with commas.
* @param string $delete the ON DELETE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @param string $update the ON UPDATE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @return Query the query object itself
*/
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
{
$this->operation = array('addForeignKey', $name, $table, $columns, $refTable, $refColumns, $delete, $update);
return $this;
}
/**
* Builds a SQL statement for dropping a foreign key constraint.
* @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function dropForeignKey($name, $table)
{
$this->operation = array('dropForeignKey', $name, $table);
return $this;
}
/**
* Builds and executes a SQL statement for creating a new index.
* @param string $name the name of the index. The name will be properly quoted by the method.
* @param string $table the table that the new index will be created for. The table name will be properly quoted by the method.
* @param string $columns the column(s) that should be included in the index. If there are multiple columns, please separate them
* by commas. The column names will be properly quoted by the method.
* @param boolean $unique whether to add UNIQUE constraint on the created index.
* @return Query the query object itself
*/
public function createIndex($name, $table, $columns, $unique = false)
{
$this->operation = array('createIndex', $name, $table, $columns, $unique);
return $this;
}
/**
* Builds and executes a SQL statement for dropping an index.
* @param string $name the name of the index to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose index is to be dropped. The name will be properly quoted by the method.
* @return Query the query object itself
*/
public function dropIndex($name, $table)
{
$this->operation = array('dropIndex', $name, $table);
return $this;
}
/**
* Sets the parameters to be bound to the query.
* @param array list of query parameter values indexed by parameter placeholders.
* For example, `array(':name'=>'Dan', ':age'=>31)`.
* @return Query the query object itself
* @see addParams()
*/
public function params($params)
{
$this->params = $params;
return $this;
}
/**
* Adds additional parameters to be bound to the query.
* @param array list of query parameter values indexed by parameter placeholders.
* For example, `array(':name'=>'Dan', ':age'=>31)`.
* @return Query the query object itself
* @see params()
*/
public function addParams($params) public function addParams($params)
{ {
foreach ($params as $name => $value) { foreach ($params as $name => $value) {
@ -105,8 +728,39 @@ class Query extends \yii\base\Object
$this->params[$name] = $value; $this->params[$name] = $value;
} }
} }
return $this;
}
/**
* Generates and returns the SQL statement according to this query.
* @param Connection $connection the database connection used to generate the SQL statement.
* If this parameter is not given, the `db` application component will be used.
* @return string the generated SQL statement
*/
public function getSql($connection = null)
{
if ($connection === null) {
$connection = \Yii::$application->db;
}
return $connection->getQueryBuilder()->build($this);
}
/**
* Creates a DB command that can be used to execute this query.
* @param Connection $connection the database connection used to generate the SQL statement.
* If this parameter is not given, the `db` application component will be used.
* @return Command the created DB command instance.
*/
public function createCommand($connection = null)
{
if ($connection === null) {
$connection = \Yii::$application->db;
}
return $connection->createCommand($this);
} }
// -----------------------------------------------------
public function mergeWith($query, $useAnd = true) public function mergeWith($query, $useAnd = true)
{ {
$and = $useAnd ? 'AND' : 'OR'; $and = $useAnd ? 'AND' : 'OR';
@ -225,288 +879,6 @@ class Query extends \yii\base\Object
} }
} }
/**
* Appends a condition to the existing {@link condition}.
* The new condition and the existing condition will be concatenated via the specified operator
* which defaults to 'AND'.
* The new condition can also be an array. In this case, all elements in the array
* will be concatenated together via the operator.
* This method handles the case when the existing condition is empty.
* After calling this method, the {@link condition} property will be modified.
* @param mixed $condition the new condition. It can be either a string or an array of strings.
* @param string $operator the operator to join different conditions. Defaults to 'AND'.
* @return Query the criteria object itself
*/
public function addCondition($condition, $operator = 'AND')
{
if (is_array($condition)) {
if ($condition === array()) {
return $this;
}
$condition = '(' . implode(') ' . $operator . ' (', $condition) . ')';
}
if ($this->condition === '') {
$this->condition = $condition;
} else
{
$this->condition = '(' . $this->condition . ') ' . $operator . ' (' . $condition . ')';
}
return $this;
}
/**
* Appends a search condition to the existing {@link condition}.
* The search condition and the existing condition will be concatenated via the specified operator
* which defaults to 'AND'.
* The search condition is generated using the SQL LIKE operator with the given column name and
* search keyword.
* @param string $column the column name (or a valid SQL expression)
* @param string $keyword the search keyword. This interpretation of the keyword is affected by the next parameter.
* @param boolean $escape whether the keyword should be escaped if it contains characters % or _.
* When this parameter is true (default), the special characters % (matches 0 or more characters)
* and _ (matches a single character) will be escaped, and the keyword will be surrounded with a %
* character on both ends. When this parameter is false, the keyword will be directly used for
* matching without any change.
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @param string $like the LIKE operator. Defaults to 'LIKE'. You may also set this to be 'NOT LIKE'.
* @return Query the criteria object itself
*/
public function addSearchCondition($column, $keyword, $escape = true, $operator = 'AND', $like = 'LIKE')
{
if ($keyword == '') {
return $this;
}
if ($escape) {
$keyword = '%' . strtr($keyword, array('%' => '\%', '_' => '\_', '\\' => '\\\\')) . '%';
}
$condition = $column . " $like " . self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $keyword;
return $this->addCondition($condition, $operator);
}
/**
* Appends an IN condition to the existing {@link condition}.
* The IN condition and the existing condition will be concatenated via the specified operator
* which defaults to 'AND'.
* The IN condition is generated by using the SQL IN operator which requires the specified
* column value to be among the given list of values.
* @param string $column the column name (or a valid SQL expression)
* @param array $values list of values that the column value should be in
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
*/
public function addInCondition($column, $values, $operator = 'AND')
{
if (($n = count($values)) < 1) {
return $this->addCondition('0=1', $operator);
} // 0=1 is used because in MSSQL value alone can't be used in WHERE
if ($n === 1) {
$value = reset($values);
if ($value === null) {
return $this->addCondition($column . ' IS NULL');
}
$condition = $column . '=' . self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
} else
{
$params = array();
foreach ($values as $value)
{
$params[] = self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
}
$condition = $column . ' IN (' . implode(', ', $params) . ')';
}
return $this->addCondition($condition, $operator);
}
/**
* Appends an NOT IN condition to the existing {@link condition}.
* The NOT IN condition and the existing condition will be concatenated via the specified operator
* which defaults to 'AND'.
* The NOT IN condition is generated by using the SQL NOT IN operator which requires the specified
* column value to be among the given list of values.
* @param string $column the column name (or a valid SQL expression)
* @param array $values list of values that the column value should not be in
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
*/
public function addNotInCondition($column, $values, $operator = 'AND')
{
if (($n = count($values)) < 1) {
return $this;
}
if ($n === 1) {
$value = reset($values);
if ($value === null) {
return $this->addCondition($column . ' IS NOT NULL');
}
$condition = $column . '!=' . self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
} else
{
$params = array();
foreach ($values as $value)
{
$params[] = self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
}
$condition = $column . ' NOT IN (' . implode(', ', $params) . ')';
}
return $this->addCondition($condition, $operator);
}
/**
* Appends a condition for matching the given list of column values.
* The generated condition will be concatenated to the existing {@link condition}
* via the specified operator which defaults to 'AND'.
* The condition is generated by matching each column and the corresponding value.
* @param array $columns list of column names and values to be matched (name=>value)
* @param string $columnOperator the operator to concatenate multiple column matching condition. Defaults to 'AND'.
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
*/
public function addColumnCondition($columns, $columnOperator = 'AND', $operator = 'AND')
{
$params = array();
foreach ($columns as $name => $value)
{
if ($value === null) {
$params[] = $name . ' IS NULL';
} else
{
$params[] = $name . '=' . self::PARAM_PREFIX . self::$paramCount;
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
}
}
return $this->addCondition(implode(" $columnOperator ", $params), $operator);
}
/**
* Adds a comparison expression to the {@link condition} property.
*
* This method is a helper that appends to the {@link condition} property
* with a new comparison expression. The comparison is done by comparing a column
* with the given value using some comparison operator.
*
* The comparison operator is intelligently determined based on the first few
* characters in the given value. In particular, it recognizes the following operators
* if they appear as the leading characters in the given value:
* <ul>
* <li><code>&lt;</code>: the column must be less than the given value.</li>
* <li><code>&gt;</code>: the column must be greater than the given value.</li>
* <li><code>&lt;=</code>: the column must be less than or equal to the given value.</li>
* <li><code>&gt;=</code>: the column must be greater than or equal to the given value.</li>
* <li><code>&lt;&gt;</code>: the column must not be the same as the given value.
* Note that when $partialMatch is true, this would mean the value must not be a substring
* of the column.</li>
* <li><code>=</code>: the column must be equal to the given value.</li>
* <li>none of the above: the column must be equal to the given value. Note that when $partialMatch
* is true, this would mean the value must be the same as the given value or be a substring of it.</li>
* </ul>
*
* Note that any surrounding white spaces will be removed from the value before comparison.
* When the value is empty, no comparison expression will be added to the search condition.
*
* @param string $column the name of the column to be searched
* @param mixed $value the column value to be compared with. If the value is a string, the aforementioned
* intelligent comparison will be conducted. If the value is an array, the comparison is done
* by exact match of any of the value in the array. If the string or the array is empty,
* the existing search condition will not be modified.
* @param boolean $partialMatch whether the value should consider partial text match (using LIKE and NOT LIKE operators).
* Defaults to false, meaning exact comparison.
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @param boolean $escape whether the value should be escaped if $partialMatch is true and
* the value contains characters % or _. When this parameter is true (default),
* the special characters % (matches 0 or more characters)
* and _ (matches a single character) will be escaped, and the value will be surrounded with a %
* character on both ends. When this parameter is false, the value will be directly used for
* matching without any change.
* @return Query the criteria object itself
*/
public function compare($column, $value, $partialMatch = false, $operator = 'AND', $escape = true)
{
if (is_array($value)) {
if ($value === array()) {
return $this;
}
return $this->addInCondition($column, $value, $operator);
} else
{
$value = "$value";
}
if (preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/', $value, $matches)) {
$value = $matches[2];
$op = $matches[1];
} else
{
$op = '';
}
if ($value === '') {
return $this;
}
if ($partialMatch) {
if ($op === '') {
return $this->addSearchCondition($column, $value, $escape, $operator);
}
if ($op === '<>') {
return $this->addSearchCondition($column, $value, $escape, $operator, 'NOT LIKE');
}
} elseif ($op === '')
{
$op = '=';
}
$this->addCondition($column . $op . self::PARAM_PREFIX . self::$paramCount, $operator);
$this->params[self::PARAM_PREFIX . self::$paramCount++] = $value;
return $this;
}
/**
* Adds a between condition to the {@link condition} property.
*
* The new between condition and the existing condition will be concatenated via
* the specified operator which defaults to 'AND'.
* If one or both values are empty then the condition is not added to the existing condition.
* This method handles the case when the existing condition is empty.
* After calling this method, the {@link condition} property will be modified.
* @param string $column the name of the column to search between.
* @param string $valueStart the beginning value to start the between search.
* @param string $valueEnd the ending value to end the between search.
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
*/
public function addBetweenCondition($column, $valueStart, $valueEnd, $operator = 'AND')
{
if ($valueStart === '' || $valueEnd === '') {
return $this;
}
$paramStart = self::PARAM_PREFIX . self::$paramCount++;
$paramEnd = self::PARAM_PREFIX . self::$paramCount++;
$this->params[$paramStart] = $valueStart;
$this->params[$paramEnd] = $valueEnd;
$condition = "$column BETWEEN $paramStart AND $paramEnd";
if ($this->condition === '') {
$this->condition = $condition;
} else
{
$this->condition = '(' . $this->condition . ') ' . $operator . ' (' . $condition . ')';
}
return $this;
}
public function reset() public function reset()
{ {
$this->select = null; $this->select = null;

20
framework/db/dao/QueryBuilder.php

@ -40,6 +40,10 @@ class QueryBuilder extends \yii\base\Object
$this->schema = $schema; $this->schema = $schema;
} }
/**
* @param Query $query
* @return string
*/
public function build($query) public function build($query)
{ {
$clauses = array( $clauses = array(
@ -126,7 +130,6 @@ class QueryBuilder extends \yii\base\Object
* @param string $table the table where the data will be deleted from. * @param string $table the table where the data will be deleted from.
* @param mixed $conditions the conditions that will be put in the WHERE part. Please * @param mixed $conditions the conditions that will be put in the WHERE part. Please
* refer to {@link where} on how to specify conditions. * refer to {@link where} on how to specify conditions.
* @param array $params the parameters to be bound to the query.
* @return integer number of rows affected by the execution. * @return integer number of rows affected by the execution.
*/ */
public function delete($table, $conditions = '') public function delete($table, $conditions = '')
@ -440,6 +443,10 @@ class QueryBuilder extends \yii\base\Object
protected function buildFrom($query) protected function buildFrom($query)
{ {
if (empty($query->from)) {
return '';
}
$tables = $query->from; $tables = $query->from;
if (is_string($tables) && strpos($tables, '(') !== false) { if (is_string($tables) && strpos($tables, '(') !== false) {
return 'FROM ' . $tables; return 'FROM ' . $tables;
@ -609,7 +616,7 @@ class QueryBuilder extends \yii\base\Object
} }
if (!isset($conditions[1], $conditions[2])) { if (!isset($conditions[1], $conditions[2])) {
return ''; throw new Exception("Operator $operator requires at least two operands.");
} }
$column = $conditions[1]; $column = $conditions[1];
@ -617,6 +624,15 @@ class QueryBuilder extends \yii\base\Object
$column = $this->connection->quoteColumnName($column); $column = $this->connection->quoteColumnName($column);
} }
if ($operator === 'BETWEEN' || $operator === 'NOT BETWEEN') {
if (!isset($conditions[3])) {
throw new Exception("Operator $operator requires three operands.");
}
$value1 = is_string($conditions[2]) ? $this->connection->quoteValue($conditions[2]) : (string)$conditions[2];
$value2 = is_string($conditions[3]) ? $this->connection->quoteValue($conditions[3]) : (string)$conditions[3];
return "$column $operator $value1 AND $value2";
}
$values = $conditions[2]; $values = $conditions[2];
if (!is_array($values)) { if (!is_array($values)) {
$values = array($values); $values = array($values);

4
framework/db/dao/Schema.php

@ -86,7 +86,7 @@ abstract class Schema extends \yii\base\Object
$db->queryCachingDuration = -1; $db->queryCachingDuration = -1;
} }
if (!in_array($name, $db->schemaCachingExclude) && $db->schemaCachingDuration >= 0 && ($cache = \Yii::app()->getComponent($db->schemaCacheID)) !== null) { if (!in_array($name, $db->schemaCachingExclude) && $db->schemaCachingDuration >= 0 && ($cache = \Yii::$application->getComponent($db->schemaCacheID)) !== null) {
$key = __CLASS__ . "/{$db->dsn}/{$db->username}/{$name}"; $key = __CLASS__ . "/{$db->dsn}/{$db->username}/{$name}";
if (($table = $cache->get($key)) === false) { if (($table = $cache->get($key)) === false) {
$table = $this->loadTableSchema($realName); $table = $this->loadTableSchema($realName);
@ -156,7 +156,7 @@ abstract class Schema extends \yii\base\Object
public function refresh() public function refresh()
{ {
$db = $this->connection; $db = $this->connection;
if ($db->schemaCachingDuration >= 0 && ($cache = \Yii::app()->getComponent($db->schemaCacheID)) !== null) { if ($db->schemaCachingDuration >= 0 && ($cache = \Yii::$application->getComponent($db->schemaCacheID)) !== null) {
foreach ($this->_tables as $name => $table) { foreach ($this->_tables as $name => $table) {
$key = __CLASS__ . ":{$db->dsn}/{$db->username}/{$name}"; $key = __CLASS__ . ":{$db->dsn}/{$db->username}/{$name}";
$cache->delete($key); $cache->delete($key);

2
framework/logging/DbTarget.php

@ -71,7 +71,7 @@ class DbTarget extends Target
if ($this->_db !== null) { if ($this->_db !== null) {
return $this->_db; return $this->_db;
} }
$this->_db = \Yii::app()->getComponent($this->connectionID); $this->_db = \Yii::$application->getComponent($this->connectionID);
if (!$this->_db instanceof \yii\db\dao\Connection) { if (!$this->_db instanceof \yii\db\dao\Connection) {
throw new \yii\base\Exception('DbTarget.connectionID must refer to a valid application component ID'); throw new \yii\base\Exception('DbTarget.connectionID must refer to a valid application component ID');
} }

2
framework/logging/FileTarget.php

@ -52,7 +52,7 @@ class FileTarget extends Target
{ {
parent::init(); parent::init();
if ($this->logPath === null) { if ($this->logPath === null) {
$this->logPath = \Yii::app()->getRuntimePath(); $this->logPath = \Yii::$application->getRuntimePath();
} }
if (!is_dir($this->logPath) || !is_writable($this->logPath)) { if (!is_dir($this->logPath) || !is_writable($this->logPath)) {
throw new \yii\base\Exception("Directory '{$this->logPath}' does not exist or is not writable."); throw new \yii\base\Exception("Directory '{$this->logPath}' does not exist or is not writable.");

2
framework/logging/ProfileTarget.php

@ -72,7 +72,7 @@ class CProfileLogRoute extends CWebLogRoute
*/ */
public function processLogs($logs) public function processLogs($logs)
{ {
$app = Yii::app(); $app = \Yii::$application;
if (!($app instanceof CWebApplication) || $app->getRequest()->getIsAjaxRequest()) if (!($app instanceof CWebApplication) || $app->getRequest()->getIsAjaxRequest())
return; return;

4
framework/logging/Router.php

@ -49,7 +49,7 @@ namespace yii\logging;
* as follows: * as follows:
* *
* ~~~ * ~~~
* \Yii::app()->log->targets['file']->enabled = false; * \Yii::$application->log->targets['file']->enabled = false;
* ~~~ * ~~~
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
@ -77,7 +77,7 @@ class Router extends \yii\base\ApplicationComponent
{ {
parent::init(); parent::init();
\Yii::getLogger()->attachEventHandler('onFlush', array($this, 'processMessages')); \Yii::getLogger()->attachEventHandler('onFlush', array($this, 'processMessages'));
if (($app = \Yii::app()) !== null) { if (($app = \Yii::$application) !== null) {
$app->attachEventHandler('onEndRequest', array($this, 'processMessages')); $app->attachEventHandler('onEndRequest', array($this, 'processMessages'));
} }
} }

4
framework/logging/Target.php

@ -128,7 +128,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
if ($this->prefixSession && ($id = session_id()) !== '') { if ($this->prefixSession && ($id = session_id()) !== '') {
$prefix[] = "[$id]"; $prefix[] = "[$id]";
} }
if ($this->prefixUser && ($user = \Yii::app()->getComponent('user', false)) !== null) { if ($this->prefixUser && ($user = \Yii::$application->getComponent('user', false)) !== null) {
$prefix[] = '[' . $user->getName() . ']'; $prefix[] = '[' . $user->getName() . ']';
$prefix[] = '[' . $user->getId() . ']'; $prefix[] = '[' . $user->getId() . ']';
} }
@ -151,7 +151,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
protected function getContextMessage() protected function getContextMessage()
{ {
$context = array(); $context = array();
if ($this->logUser && ($user = \Yii::app()->getComponent('user', false)) !== null) { if ($this->logUser && ($user = \Yii::$application->getComponent('user', false)) !== null) {
$context[] = 'User: ' . $user->getName() . ' (ID: ' . $user->getId() . ')'; $context[] = 'User: ' . $user->getName() . ' (ID: ' . $user->getId() . ')';
} }

2
framework/logging/WebTarget.php

@ -47,7 +47,7 @@ class CWebLogRoute extends CLogRoute
*/ */
protected function render($view, $data) protected function render($view, $data)
{ {
$app = Yii::app(); $app = \Yii::$application;
$isAjax = $app->getRequest()->getIsAjaxRequest(); $isAjax = $app->getRequest()->getIsAjaxRequest();
if ($this->showInFireBug) if ($this->showInFireBug)

4
framework/validators/CaptchaValidator.php

@ -61,13 +61,13 @@ class CaptchaValidator extends Validator
public function getCaptchaAction() public function getCaptchaAction()
{ {
if (strpos($this->captchaAction, '/') !== false) { // contains controller or module if (strpos($this->captchaAction, '/') !== false) { // contains controller or module
$ca = Yii::app()->createController($this->captchaAction); $ca = \Yii::$application->createController($this->captchaAction);
if ($ca !== null) { if ($ca !== null) {
list($controller, $actionID) = $ca; list($controller, $actionID) = $ca;
$action = $controller->createAction($actionID); $action = $controller->createAction($actionID);
} }
} else { } else {
$action = Yii::app()->getController()->createAction($this->captchaAction); $action = \Yii::$application->getController()->createAction($this->captchaAction);
} }
if ($action === null) { if ($action === null) {

2
framework/validators/StringValidator.php

@ -82,7 +82,7 @@ class StringValidator extends Validator
} }
if (function_exists('mb_strlen') && $this->encoding !== false) { if (function_exists('mb_strlen') && $this->encoding !== false) {
$length = mb_strlen($value, $this->encoding ? $this->encoding : Yii::app()->charset); $length = mb_strlen($value, $this->encoding ? $this->encoding : \Yii::$application->charset);
} else { } else {
$length = strlen($value); $length = strlen($value);
} }

33
tests/unit/framework/db/dao/CommandTest.php

@ -13,34 +13,27 @@ class CommandTest extends \yiiunit\MysqlTestCase
{ {
$db = $this->getConnection(false); $db = $this->getConnection(false);
// null
$command = $db->createCommand(); $command = $db->createCommand();
$this->assertEquals("SELECT *\nFROM ", $command->sql); $this->assertEquals(null, $command->sql);
// string
$sql = 'SELECT * FROM yii_post'; $sql = 'SELECT * FROM yii_post';
$command = $db->createCommand($sql); $command = $db->createCommand($sql);
$this->assertEquals($sql, $command->sql); $this->assertEquals($sql, $command->sql);
// Query object
$query = new Query; $query = new Query;
$query->select('id')->from('tbl_user');
$command = $db->createCommand($query); $command = $db->createCommand($query);
$this->assertEquals($query, $command->query); $this->assertEquals("SELECT `id`\nFROM `tbl_user`", $command->sql);
$query = array('select' => 'id', 'from' => 'yii_post'); // array
$command = $db->createCommand($query); $command = $db->createCommand(array(
$this->assertEquals($query, $command->query->toArray()); 'select' => 'name',
} 'from' => 'tbl_user',
));
function testReset() $this->assertEquals("SELECT `name`\nFROM `tbl_user`", $command->sql);
{
$db = $this->getConnection();
$command = $db->createCommand('SELECT * FROM yii_user');
$command->queryRow();
$this->assertNotEquals(null, $command->pdoStatement);
$this->assertEquals('SELECT * FROM yii_user', $command->sql);
$command->reset();
$this->assertEquals(null, $command->pdoStatement);
$this->assertNotEquals('SELECT * FROM yii_user', $command->sql);
} }
function testGetSetSql() function testGetSetSql()

Loading…
Cancel
Save