mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-01 20:19:42 +08:00
w
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -460,6 +460,11 @@ class Connection extends \yii\base\ApplicationComponent
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryBuilder()
|
||||
{
|
||||
return $this->getSchema()->getQueryBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the last inserted row or sequence value.
|
||||
* @param string $sequenceName name of the sequence object (required by some DBMS)
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\db\dao;
|
||||
|
||||
/**
|
||||
* DataReader represents a forward-only stream of rows from a query result set.
|
||||
*
|
||||
|
||||
@ -16,7 +16,7 @@ namespace yii\db\dao;
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Query extends CComponent
|
||||
class Query extends \yii\base\Component
|
||||
{
|
||||
/**
|
||||
* @var mixed the columns being selected. This refers to the SELECT clause in an SQL
|
||||
@ -72,7 +72,7 @@ class Query extends CComponent
|
||||
* @var array list of query parameter values indexed by parameter placeholders.
|
||||
* For example, <code>array(':name'=>'Dan', ':age'=>31)</code>.
|
||||
*/
|
||||
public $params;
|
||||
public $params = array();
|
||||
|
||||
public $union;
|
||||
|
||||
@ -82,6 +82,18 @@ class Query extends CComponent
|
||||
return $connection->getQueryBuilder()->build($this);
|
||||
}
|
||||
|
||||
public function addParams($params)
|
||||
{
|
||||
foreach ($params as $name => $value) {
|
||||
if (is_integer($name)) {
|
||||
$this->params[] = $value;
|
||||
}
|
||||
else {
|
||||
$this->params[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a condition to the existing {@link condition}.
|
||||
* The new condition and the existing condition will be concatenated via the specified operator
|
||||
@ -360,157 +372,6 @@ class Query extends CComponent
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges with another criteria.
|
||||
* In general, the merging makes the resulting criteria more restrictive.
|
||||
* For example, if both criterias have conditions, they will be 'AND' together.
|
||||
* Also, the criteria passed as the parameter takes precedence in case
|
||||
* two options cannot be merged (e.g. LIMIT, OFFSET).
|
||||
* @param Query $criteria the criteria to be merged with.
|
||||
* @param boolean $useAnd whether to use 'AND' to merge condition and having options.
|
||||
* If false, 'OR' will be used instead. Defaults to 'AND'. This parameter has been
|
||||
* available since version 1.0.6.
|
||||
* @since 1.0.5
|
||||
*/
|
||||
public function mergeWith($criteria, $useAnd = true)
|
||||
{
|
||||
$and = $useAnd ? 'AND' : 'OR';
|
||||
if (is_array($criteria))
|
||||
$criteria = new self($criteria);
|
||||
if ($this->select !== $criteria->select)
|
||||
{
|
||||
if ($this->select === '*')
|
||||
$this->select = $criteria->select;
|
||||
elseif ($criteria->select !== '*')
|
||||
{
|
||||
$select1 = is_string($this->select) ? preg_split('/\s*,\s*/', trim($this->select), -1, PREG_SPLIT_NO_EMPTY) : $this->select;
|
||||
$select2 = is_string($criteria->select) ? preg_split('/\s*,\s*/', trim($criteria->select), -1, PREG_SPLIT_NO_EMPTY) : $criteria->select;
|
||||
$this->select = array_merge($select1, array_diff($select2, $select1));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->condition !== $criteria->condition)
|
||||
{
|
||||
if ($this->condition === '')
|
||||
$this->condition = $criteria->condition;
|
||||
elseif ($criteria->condition !== '')
|
||||
$this->condition = "( {$this->condition}) $and ( {$criteria->condition})";
|
||||
}
|
||||
|
||||
if ($this->params !== $criteria->params)
|
||||
$this->params = array_merge($this->params, $criteria->params);
|
||||
|
||||
if ($criteria->limit > 0)
|
||||
$this->limit = $criteria->limit;
|
||||
|
||||
if ($criteria->offset >= 0)
|
||||
$this->offset = $criteria->offset;
|
||||
|
||||
if ($criteria->alias !== null)
|
||||
$this->alias = $criteria->alias;
|
||||
|
||||
if ($this->order !== $criteria->order)
|
||||
{
|
||||
if ($this->order === '')
|
||||
$this->order = $criteria->order;
|
||||
elseif ($criteria->order !== '')
|
||||
$this->order = $criteria->order . ', ' . $this->order;
|
||||
}
|
||||
|
||||
if ($this->group !== $criteria->group)
|
||||
{
|
||||
if ($this->group === '')
|
||||
$this->group = $criteria->group;
|
||||
elseif ($criteria->group !== '')
|
||||
$this->group .= ', ' . $criteria->group;
|
||||
}
|
||||
|
||||
if ($this->join !== $criteria->join)
|
||||
{
|
||||
if ($this->join === '')
|
||||
$this->join = $criteria->join;
|
||||
elseif ($criteria->join !== '')
|
||||
$this->join .= ' ' . $criteria->join;
|
||||
}
|
||||
|
||||
if ($this->having !== $criteria->having)
|
||||
{
|
||||
if ($this->having === '')
|
||||
$this->having = $criteria->having;
|
||||
elseif ($criteria->having !== '')
|
||||
$this->having = "( {$this->having}) $and ( {$criteria->having})";
|
||||
}
|
||||
|
||||
if ($criteria->distinct > 0)
|
||||
$this->distinct = $criteria->distinct;
|
||||
|
||||
if ($criteria->together !== null)
|
||||
$this->together = $criteria->together;
|
||||
|
||||
if ($criteria->index !== null)
|
||||
$this->index = $criteria->index;
|
||||
|
||||
if (empty($this->scopes))
|
||||
$this->scopes = $criteria->scopes;
|
||||
elseif (!empty($criteria->scopes))
|
||||
{
|
||||
$scopes1 = (array)$this->scopes;
|
||||
$scopes2 = (array)$criteria->scopes;
|
||||
foreach ($scopes1 as $k => $v)
|
||||
{
|
||||
if (is_integer($k))
|
||||
$scopes[] = $v;
|
||||
elseif (isset($scopes2[$k]))
|
||||
$scopes[] = array($k => $v);
|
||||
else
|
||||
$scopes[$k] = $v;
|
||||
}
|
||||
foreach ($scopes2 as $k => $v)
|
||||
{
|
||||
if (is_integer($k))
|
||||
$scopes[] = $v;
|
||||
elseif (isset($scopes1[$k]))
|
||||
$scopes[] = array($k => $v);
|
||||
else
|
||||
$scopes[$k] = $v;
|
||||
}
|
||||
$this->scopes = $scopes;
|
||||
}
|
||||
|
||||
if (empty($this->with))
|
||||
$this->with = $criteria->with;
|
||||
elseif (!empty($criteria->with))
|
||||
{
|
||||
$this->with = (array)$this->with;
|
||||
foreach ((array)$criteria->with as $k => $v)
|
||||
{
|
||||
if (is_integer($k))
|
||||
$this->with[] = $v;
|
||||
elseif (isset($this->with[$k]))
|
||||
{
|
||||
$excludes = array();
|
||||
foreach (array('joinType', 'on') as $opt)
|
||||
{
|
||||
if (isset($this->with[$k][$opt]))
|
||||
$excludes[$opt] = $this->with[$k][$opt];
|
||||
if (isset($v[$opt]))
|
||||
$excludes[$opt] = ($opt === 'on' && isset($excludes[$opt]) && $v[$opt] !== $excludes[$opt]) ?
|
||||
"($excludes[$opt]) AND $v[$opt]" : $v[$opt];
|
||||
unset($this->with[$k][$opt]);
|
||||
unset($v[$opt]);
|
||||
}
|
||||
$this->with[$k] = new self($this->with[$k]);
|
||||
$this->with[$k]->mergeWith($v, $useAnd);
|
||||
$this->with[$k] = $this->with[$k]->toArray();
|
||||
if (count($excludes) !== 0)
|
||||
$this->with[$k] = CMap::mergeArray($this->with[$k], $excludes);
|
||||
}
|
||||
else
|
||||
$this->with[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array the array representation of the criteria
|
||||
* @since 1.0.6
|
||||
|
||||
@ -42,7 +42,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
|
||||
public function __construct($schema)
|
||||
{
|
||||
$this->connection = $schema->getDbConnection();
|
||||
$this->connection = $schema->connection;
|
||||
$this->schema = $schema;
|
||||
}
|
||||
|
||||
@ -59,8 +59,98 @@ class QueryBuilder extends \yii\base\Component
|
||||
$this->buildOrderBy($query),
|
||||
$this->buildLimit($query),
|
||||
);
|
||||
$sql = implode("\n", array_filter($clauses));
|
||||
if ($this->connection->tablePrefix !== null && strpos($sql, '{') !== false) {
|
||||
$sql = preg_replace('/{{(.*?)}}/', $this->connection->tablePrefix . '\1', $sql);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
return implode("\n", array_filter($clauses));
|
||||
/**
|
||||
* 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.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function insert($table, $columns, &$params = array())
|
||||
{
|
||||
$names = array();
|
||||
$placeholders = array();
|
||||
$count = 0;
|
||||
foreach ($columns as $name => $value) {
|
||||
$names[] = $this->schema->quoteColumnName($name);
|
||||
if ($value instanceof Expression) {
|
||||
$placeholders[] = $value->expression;
|
||||
foreach ($value->params as $n => $v) {
|
||||
$params[$n] = $v;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$placeholders[] = ':p' . $count;
|
||||
$params[':p' . $count] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return 'INSERT INTO ' . $this->schema->quoteTableName($table)
|
||||
. ' (' . implode(', ', $names) . ') VALUES ('
|
||||
. implode(', ', $placeholders) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@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.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function update($table, $columns, $conditions = '', &$params = array())
|
||||
{
|
||||
$lines = array();
|
||||
$count = 0;
|
||||
foreach ($columns as $name => $value) {
|
||||
if ($value instanceof Expression) {
|
||||
$lines[] = $this->schema->quoteSimpleColumnName($name) . '=' . $value->expression;
|
||||
foreach ($value->params as $n => $v) {
|
||||
$params[$n] = $v;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$lines[] = $this->schema->quoteSimpleColumnName($name) . '=:p' . $count;
|
||||
$params[':p' . $count] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$sql = 'UPDATE ' . $this->schema->quoteTableName($table) . ' SET ' . implode(', ', $lines);
|
||||
if (($where = $this->buildCondition($conditions)) != '') {
|
||||
$sql .= ' WHERE ' . $where;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@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.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function delete($table, $conditions = '')
|
||||
{
|
||||
$sql = 'DELETE FROM ' . $this->schema->quoteTableName($table);
|
||||
if (($where = $this->buildCondition($conditions)) != '') {
|
||||
$sql .= ' WHERE ' . $where;
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +191,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function renameTable($table, $newName)
|
||||
{
|
||||
return 'RENAME TABLE ' . $this->quoteTableName($table) . ' TO ' . $this->quoteTableName($newName);
|
||||
return 'RENAME TABLE ' . $this->schema->quoteTableName($table) . ' TO ' . $this->schema->quoteTableName($newName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,7 +201,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function dropTable($table)
|
||||
{
|
||||
return "DROP TABLE " . $this->quoteTableName($table);
|
||||
return "DROP TABLE " . $this->schema->quoteTableName($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,7 +211,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function truncateTable($table)
|
||||
{
|
||||
return "TRUNCATE TABLE " . $this->quoteTableName($table);
|
||||
return "TRUNCATE TABLE " . $this->schema->quoteTableName($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,8 +226,8 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function addColumn($table, $column, $type)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table)
|
||||
. ' ADD ' . $this->quoteColumnName($column) . ' '
|
||||
return 'ALTER TABLE ' . $this->schema->quoteTableName($table)
|
||||
. ' ADD ' . $this->schema->quoteColumnName($column) . ' '
|
||||
. $this->getColumnType($type);
|
||||
}
|
||||
|
||||
@ -150,8 +240,8 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function dropColumn($table, $column)
|
||||
{
|
||||
return "ALTER TABLE " . $this->quoteTableName($table)
|
||||
. " DROP COLUMN " . $this->quoteSimpleColumnName($column);
|
||||
return "ALTER TABLE " . $this->schema->quoteTableName($table)
|
||||
. " DROP COLUMN " . $this->schema->quoteSimpleColumnName($column);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,9 +254,9 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function renameColumn($table, $name, $newName)
|
||||
{
|
||||
return "ALTER TABLE " . $this->quoteTableName($table)
|
||||
. " RENAME COLUMN " . $this->quoteSimpleColumnName($name)
|
||||
. " TO " . $this->quoteSimpleColumnName($newName);
|
||||
return "ALTER TABLE " . $this->schema->quoteTableName($table)
|
||||
. " RENAME COLUMN " . $this->schema->quoteSimpleColumnName($name)
|
||||
. " TO " . $this->schema->quoteSimpleColumnName($newName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,9 +270,9 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function alterColumn($table, $column, $type)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' CHANGE '
|
||||
. $this->quoteSimpleColumnName($column) . ' '
|
||||
. $this->quoteSimpleColumnName($column) . ' '
|
||||
return 'ALTER TABLE ' . $this->schema->quoteTableName($table) . ' CHANGE '
|
||||
. $this->schema->quoteSimpleColumnName($column) . ' '
|
||||
. $this->schema->quoteSimpleColumnName($column) . ' '
|
||||
. $this->getColumnType($type);
|
||||
}
|
||||
|
||||
@ -202,14 +292,14 @@ class QueryBuilder extends \yii\base\Component
|
||||
{
|
||||
$columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($columns as $i => $col)
|
||||
$columns[$i] = $this->quoteColumnName($col);
|
||||
$columns[$i] = $this->schema->quoteColumnName($col);
|
||||
$refColumns = preg_split('/\s*,\s*/', $refColumns, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($refColumns as $i => $col)
|
||||
$refColumns[$i] = $this->quoteColumnName($col);
|
||||
$sql = 'ALTER TABLE ' . $this->quoteTableName($table)
|
||||
. ' ADD CONSTRAINT ' . $this->quoteColumnName($name)
|
||||
$refColumns[$i] = $this->schema->quoteColumnName($col);
|
||||
$sql = 'ALTER TABLE ' . $this->schema->quoteTableName($table)
|
||||
. ' ADD CONSTRAINT ' . $this->schema->quoteColumnName($name)
|
||||
. ' FOREIGN KEY (' . implode(', ', $columns) . ')'
|
||||
. ' REFERENCES ' . $this->quoteTableName($refTable)
|
||||
. ' REFERENCES ' . $this->schema->quoteTableName($refTable)
|
||||
. ' (' . implode(', ', $refColumns) . ')';
|
||||
if ($delete !== null)
|
||||
$sql .= ' ON DELETE ' . $delete;
|
||||
@ -226,8 +316,8 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function dropForeignKey($name, $table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table)
|
||||
. ' DROP CONSTRAINT ' . $this->quoteColumnName($name);
|
||||
return 'ALTER TABLE ' . $this->schema->quoteTableName($table)
|
||||
. ' DROP CONSTRAINT ' . $this->schema->quoteColumnName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,11 +338,11 @@ class QueryBuilder extends \yii\base\Component
|
||||
if (strpos($col, '(') !== false)
|
||||
$cols[] = $col;
|
||||
else
|
||||
$cols[] = $this->quoteColumnName($col);
|
||||
$cols[] = $this->schema->quoteColumnName($col);
|
||||
}
|
||||
return ($unique ? 'CREATE UNIQUE INDEX ' : 'CREATE INDEX ')
|
||||
. $this->quoteTableName($name) . ' ON '
|
||||
. $this->quoteTableName($table) . ' (' . implode(', ', $cols) . ')';
|
||||
. $this->schema->quoteTableName($name) . ' ON '
|
||||
. $this->schema->quoteTableName($table) . ' (' . implode(', ', $cols) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,7 +353,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
*/
|
||||
public function dropIndex($name, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $this->quoteTableName($name) . ' ON ' . $this->quoteTableName($table);
|
||||
return 'DROP INDEX ' . $this->schema->quoteTableName($name) . ' ON ' . $this->schema->quoteTableName($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,6 +420,9 @@ class QueryBuilder extends \yii\base\Component
|
||||
protected function buildSelect($query)
|
||||
{
|
||||
$select = $query->distinct ? 'SELECT DISTINCT' : 'SELECT';
|
||||
if ($query->selectOption != '') {
|
||||
$select .= ' ' . $query->selectOption;
|
||||
}
|
||||
|
||||
$columns = $query->select;
|
||||
if (empty($columns)) {
|
||||
@ -408,7 +501,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
}
|
||||
$joins[$i] = strtoupper($join[0]) . ' ' . $table;
|
||||
if (isset($join[2])) { // join condition
|
||||
$condition = $this->processCondition($join[2]);
|
||||
$condition = $this->buildCondition($join[2]);
|
||||
$joins[$i] .= ' ON ' . $condition;
|
||||
}
|
||||
}
|
||||
@ -423,7 +516,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
|
||||
protected function buildWhere($query)
|
||||
{
|
||||
$where = $this->processConditions($query->where);
|
||||
$where = $this->buildCondition($query->where);
|
||||
return empty($where) ? '' : 'WHERE ' . $where;
|
||||
}
|
||||
|
||||
@ -453,7 +546,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
|
||||
protected function buildHaving($query)
|
||||
{
|
||||
$having = $this->processConditions($query->having);
|
||||
$having = $this->buildCondition($query->having);
|
||||
return empty($having) ? '' : 'HAVING ' . $having;
|
||||
}
|
||||
|
||||
@ -515,7 +608,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
return "UNION (\n" . implode("\n) UNION (\n", $unions) . "\n)";
|
||||
}
|
||||
|
||||
protected function processCondition($conditions)
|
||||
protected function buildCondition($conditions)
|
||||
{
|
||||
if (!is_array($conditions)) {
|
||||
return $conditions;
|
||||
@ -529,7 +622,7 @@ class QueryBuilder extends \yii\base\Component
|
||||
if ($operator === 'OR' || $operator === 'AND') {
|
||||
$parts = array();
|
||||
for ($i = 1; $i < $n; ++$i) {
|
||||
$condition = $this->processCondition($conditions[$i]);
|
||||
$condition = $this->buildCondition($conditions[$i]);
|
||||
if ($condition !== '') {
|
||||
$parts[] = '(' . $condition . ')';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user