mirror of
https://github.com/yiisoft/yii2.git
synced 2026-03-08 08:17:24 +01:00
w
This commit is contained in:
148
framework/db/dao/ColumnSchema.php
Normal file
148
framework/db/dao/ColumnSchema.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* CDbColumnSchema class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2011 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CDbColumnSchema class describes the column meta data of a database table.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @version $Id: CDbColumnSchema.php 3099 2011-03-19 01:26:47Z qiang.xue $
|
||||
* @package system.db.schema
|
||||
* @since 1.0
|
||||
*/
|
||||
class CDbColumnSchema extends CComponent
|
||||
{
|
||||
/**
|
||||
* @var string name of this column (without quotes).
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string raw name of this column. This is the quoted name that can be used in SQL queries.
|
||||
*/
|
||||
public $rawName;
|
||||
/**
|
||||
* @var boolean whether this column can be null.
|
||||
*/
|
||||
public $allowNull;
|
||||
/**
|
||||
* @var string the DB type of this column.
|
||||
*/
|
||||
public $dbType;
|
||||
/**
|
||||
* @var string the PHP type of this column.
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var mixed default value of this column
|
||||
*/
|
||||
public $defaultValue;
|
||||
/**
|
||||
* @var integer size of the column.
|
||||
*/
|
||||
public $size;
|
||||
/**
|
||||
* @var integer precision of the column data, if it is numeric.
|
||||
*/
|
||||
public $precision;
|
||||
/**
|
||||
* @var integer scale of the column data, if it is numeric.
|
||||
*/
|
||||
public $scale;
|
||||
/**
|
||||
* @var boolean whether this column is a primary key
|
||||
*/
|
||||
public $isPrimaryKey;
|
||||
/**
|
||||
* @var boolean whether this column is a foreign key
|
||||
*/
|
||||
public $isForeignKey;
|
||||
/**
|
||||
* @var boolean whether this column is auto-incremental
|
||||
* @since 1.1.7
|
||||
*/
|
||||
public $autoIncrement = false;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the column with its DB type and default value.
|
||||
* This sets up the column's PHP type, size, precision, scale as well as default value.
|
||||
* @param string $dbType the column's DB type
|
||||
* @param mixed $defaultValue the default value
|
||||
*/
|
||||
public function init($dbType, $defaultValue)
|
||||
{
|
||||
$this->dbType = $dbType;
|
||||
$this->extractType($dbType);
|
||||
$this->extractLimit($dbType);
|
||||
if ($defaultValue !== null)
|
||||
$this->extractDefault($defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the PHP type from DB type.
|
||||
* @param string $dbType DB type
|
||||
*/
|
||||
protected function extractType($dbType)
|
||||
{
|
||||
if (stripos($dbType, 'int') !== false && stripos($dbType, 'unsigned int') === false)
|
||||
$this->type = 'integer';
|
||||
elseif (stripos($dbType, 'bool') !== false)
|
||||
$this->type = 'boolean';
|
||||
elseif (preg_match('/(real|floa|doub)/i', $dbType))
|
||||
$this->type = 'double';
|
||||
else
|
||||
$this->type = 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts size, precision and scale information from column's DB type.
|
||||
* @param string $dbType the column's DB type
|
||||
*/
|
||||
protected function extractLimit($dbType)
|
||||
{
|
||||
if (strpos($dbType, '(') && preg_match('/\((.*)\)/', $dbType, $matches))
|
||||
{
|
||||
$values = explode(',', $matches[1]);
|
||||
$this->size = $this->precision = (int)$values[0];
|
||||
if (isset($values[1]))
|
||||
$this->scale = (int)$values[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the default value for the column.
|
||||
* The value is typecasted to correct PHP type.
|
||||
* @param mixed $defaultValue the default value obtained from metadata
|
||||
*/
|
||||
protected function extractDefault($defaultValue)
|
||||
{
|
||||
$this->defaultValue = $this->typecast($defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the input value to the type that this column is of.
|
||||
* @param mixed $value input value
|
||||
* @return mixed converted value
|
||||
*/
|
||||
public function typecast($value)
|
||||
{
|
||||
if (gettype($value) === $this->type || $value === null || $value instanceof CDbExpression)
|
||||
return $value;
|
||||
if ($value === '')
|
||||
return $this->type === 'string' ? '' : null;
|
||||
switch ($this->type)
|
||||
{
|
||||
case 'string': return (string)$value;
|
||||
case 'integer': return (integer)$value;
|
||||
case 'boolean': return (boolean)$value;
|
||||
case 'double':
|
||||
default: return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\db\dao;
|
||||
|
||||
/**
|
||||
* Command represents a SQL statement to be executed against a database.
|
||||
*
|
||||
@@ -40,7 +42,7 @@
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Command extends CComponent
|
||||
class Command extends \yii\base\Component
|
||||
{
|
||||
/**
|
||||
* @var array the parameters (name=>value) to be bound to the current query.
|
||||
|
||||
61
framework/db/dao/Expression.php
Normal file
61
framework/db/dao/Expression.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Expression class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2012 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\db\dao;
|
||||
|
||||
/**
|
||||
* Expression represents a DB expression that does not need escaping or quoting.
|
||||
* When an Expression object is embedded within a SQL statement or fragment,
|
||||
* it will be replaced with the [[expression]] property value without any
|
||||
* DB escaping or quoting. For example,
|
||||
*
|
||||
* ~~~
|
||||
* $expression = new Expression('NOW()');
|
||||
* $sql = 'SELECT ' . $expression; // SELECT NOW()
|
||||
* ~~~
|
||||
*
|
||||
* An expression can also be bound with parameters specified via [[params]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Expression
|
||||
{
|
||||
/**
|
||||
* @var string the DB expression
|
||||
*/
|
||||
public $expression;
|
||||
/**
|
||||
* @var array list of parameters that should be bound for this expression.
|
||||
* The keys are placeholders appearing in [[expression]] and the values
|
||||
* are the corresponding parameter values.
|
||||
*/
|
||||
public $params = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string $expression the DB expression
|
||||
* @param array $params parameters
|
||||
*/
|
||||
public function __construct($expression, $params = array())
|
||||
{
|
||||
$this->expression = $expression;
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* String magic method
|
||||
* @return string the DB expression
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->expression;
|
||||
}
|
||||
}
|
||||
520
framework/db/dao/Query.php
Normal file
520
framework/db/dao/Query.php
Normal file
@@ -0,0 +1,520 @@
|
||||
<?php
|
||||
/**
|
||||
* Query class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2012 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\db\dao;
|
||||
|
||||
/**
|
||||
* Query represents the components in a DB query.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Query extends CComponent
|
||||
{
|
||||
/**
|
||||
* @var mixed the columns being selected. This refers to the SELECT clause in an SQL
|
||||
* statement. The property can be either a string (column names separated by commas)
|
||||
* or an array of column names. Defaults to '*', meaning all columns.
|
||||
*/
|
||||
public $select;
|
||||
|
||||
public $from;
|
||||
/**
|
||||
* @var boolean whether to select distinct rows of data only. If this is set true,
|
||||
* the SELECT clause would be changed to SELECT DISTINCT.
|
||||
*/
|
||||
public $distinct;
|
||||
/**
|
||||
* @var string query condition. This refers to the WHERE clause in an SQL statement.
|
||||
* For example, <code>age>31 AND team=1</code>.
|
||||
*/
|
||||
public $where;
|
||||
/**
|
||||
* @var integer maximum number of records to be returned. If less than 0, it means no limit.
|
||||
*/
|
||||
public $limit;
|
||||
/**
|
||||
* @var integer zero-based offset from where the records are to be returned. If less than 0, it means starting from the beginning.
|
||||
*/
|
||||
public $offset;
|
||||
/**
|
||||
* @var string how to sort the query results. This refers to the ORDER BY clause in an SQL statement.
|
||||
*/
|
||||
public $orderBy;
|
||||
/**
|
||||
* @var string how to group the query results. This refers to the GROUP BY clause in an SQL statement.
|
||||
* For example, <code>'projectID, teamID'</code>.
|
||||
*/
|
||||
public $groupBy;
|
||||
/**
|
||||
* @var string how to join with other tables. This refers to the JOIN clause in an SQL statement.
|
||||
* For example, <code>'LEFT JOIN users ON users.id=authorID'</code>.
|
||||
*/
|
||||
public $join;
|
||||
/**
|
||||
* @var string the condition to be applied with GROUP-BY clause.
|
||||
* For example, <code>'SUM(revenue)<50000'</code>.
|
||||
*/
|
||||
public $having;
|
||||
/**
|
||||
* @var array list of query parameter values indexed by parameter placeholders.
|
||||
* For example, <code>array(':name'=>'Dan', ':age'=>31)</code>.
|
||||
*/
|
||||
public $params;
|
||||
|
||||
public $union;
|
||||
|
||||
|
||||
public function getSql($connection)
|
||||
{
|
||||
return $connection->getQueryBuilder()->build($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @since 1.0.9
|
||||
*/
|
||||
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
|
||||
* @since 1.0.10
|
||||
*/
|
||||
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
|
||||
* @since 1.0.10
|
||||
*/
|
||||
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
|
||||
* @since 1.1.1
|
||||
*/
|
||||
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
|
||||
* @since 1.0.10
|
||||
*/
|
||||
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><</code>: the column must be less than the given value.</li>
|
||||
* <li><code>></code>: the column must be greater than the given value.</li>
|
||||
* <li><code><=</code>: the column must be less than or equal to the given value.</li>
|
||||
* <li><code>>=</code>: the column must be greater than or equal to the given value.</li>
|
||||
* <li><code><></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
|
||||
* @since 1.1.1
|
||||
*/
|
||||
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
|
||||
* @since 1.1.2
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$result = array();
|
||||
foreach (array('select', 'condition', 'params', 'limit', 'offset', 'order', 'group', 'join', 'having', 'distinct', 'scopes', 'with', 'alias', 'index', 'together') as $name)
|
||||
$result[$name] = $this->$name;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
402
framework/db/dao/QueryBuilder.php
Normal file
402
framework/db/dao/QueryBuilder.php
Normal file
@@ -0,0 +1,402 @@
|
||||
<?php
|
||||
/**
|
||||
* This file contains the Command class.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2012 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\db\dao;
|
||||
|
||||
/**
|
||||
* QueryBuilder builds a SQL statement based on the specification given as a [[Query]] object.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class QueryBuilder extends \yii\base\Component
|
||||
{
|
||||
private $_connection;
|
||||
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
$this->_connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CDbConnection the connection associated with this command
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->_connection;
|
||||
}
|
||||
|
||||
public function build($query)
|
||||
{
|
||||
$clauses = array(
|
||||
$this->buildSelect($query->select, $query->distinct),
|
||||
$this->buildFrom($query->from),
|
||||
$this->buildJoin($query->join),
|
||||
$this->buildWhere($query->where),
|
||||
$this->buildGroupBy($query->groupBy),
|
||||
$this->buildHaving($query->having),
|
||||
$this->buildOrderBy($query->orderBy),
|
||||
$this->buildLimit($query->offset, $query->limit),
|
||||
$this->buildUnion($query->union),
|
||||
);
|
||||
|
||||
return implode("\n", array_filter($clauses));
|
||||
}
|
||||
|
||||
protected function buildSelect($columns, $distinct)
|
||||
{
|
||||
$select = $distinct ? 'SELECT DISTINCT' : 'SELECT';
|
||||
|
||||
if (empty($columns)) {
|
||||
return $select . ' *';
|
||||
}
|
||||
|
||||
if (is_string($columns)) {
|
||||
if (strpos($columns, '(') !== false) {
|
||||
return $select . ' ' . $columns;
|
||||
}
|
||||
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
foreach ($columns as $i => $column) {
|
||||
if (is_object($column)) {
|
||||
$columns[$i] = (string)$column;
|
||||
}
|
||||
elseif (strpos($column, '(') === false) {
|
||||
if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $column, $matches)) {
|
||||
$columns[$i] = $this->_connection->quoteColumnName($matches[1]) . ' AS ' . $this->_connection->quoteColumnName($matches[2]);
|
||||
}
|
||||
else {
|
||||
$columns[$i] = $this->_connection->quoteColumnName($column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $select . ' ' . implode(', ', $columns);
|
||||
}
|
||||
|
||||
protected function buildFrom($tables)
|
||||
{
|
||||
if (is_string($tables) && strpos($tables, '(') !== false) {
|
||||
return $tables;
|
||||
}
|
||||
|
||||
if (!is_array($tables)) {
|
||||
$tables = preg_split('/\s*,\s*/', trim($tables), -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
foreach ($tables as $i => $table) {
|
||||
if (strpos($table, '(') === false) {
|
||||
if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $table, $matches)) { // with alias
|
||||
$tables[$i] = $this->_connection->quoteTableName($matches[1]) . ' ' . $this->_connection->quoteTableName($matches[2]);
|
||||
}
|
||||
else {
|
||||
$tables[$i] = $this->_connection->quoteTableName($table);
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(', ', $tables);
|
||||
}
|
||||
|
||||
$this->buildJoin($query->join),
|
||||
$this->buildWhere($query->where),
|
||||
$this->buildGroupBy($query->groupBy),
|
||||
$this->buildHaving($query->having),
|
||||
$this->buildOrderBy($query->orderBy),
|
||||
$this->buildLimit($query->offset, $query->limit),
|
||||
|
||||
|
||||
if (isset($query['union']))
|
||||
$sql .= "\nUNION (\n" . (is_array($query['union']) ? implode("\n) UNION (\n", $query['union']) : $query['union']) . ')';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 of the format <code>array(operator, operand1, operand2, ...)</code>,
|
||||
* where the operator can be one of the followings, and the possible operands depend on the corresponding
|
||||
* operator:
|
||||
* <ul>
|
||||
* <li><code>and</code>: 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 same 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.</li>
|
||||
* <li><code>or</code>: similar as the <code>and</code> operator except that the operands are concatenated using OR.</li>
|
||||
* <li><code>in</code>: 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.</li>
|
||||
* <li><code>not in</code>: similar as the <code>in</code> operator except that IN is replaced with NOT IN in the generated condition.</li>
|
||||
* <li><code>like</code>: 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.</li>
|
||||
* <li><code>not like</code>: similar as the <code>like</code> operator except that LIKE is replaced with NOT LIKE in the generated condition.</li>
|
||||
* <li><code>or like</code>: similar as the <code>like</code> operator except that OR is used to concatenated the LIKE predicates.</li>
|
||||
* <li><code>or not like</code>: similar as the <code>not like</code> operator except that OR is used to concatenated the NOT LIKE predicates.</li>
|
||||
* </ul>
|
||||
* @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
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function where($conditions, $params = array())
|
||||
{
|
||||
$this->_query['where'] = $this->processConditions($conditions);
|
||||
foreach ($params as $name => $value)
|
||||
$this->params[$name] = $value;
|
||||
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 {@link where} on how to specify conditions.
|
||||
* @param array $params the parameters (name=>value) to be bound to the query
|
||||
* @return Command the command object itself
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function join($table, $conditions, $params = array())
|
||||
{
|
||||
return $this->joinInternal('join', $table, $conditions, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function group($columns)
|
||||
{
|
||||
if (is_string($columns) && strpos($columns, '(') !== false)
|
||||
$this->_query['group'] = $columns;
|
||||
else
|
||||
{
|
||||
if (!is_array($columns))
|
||||
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($columns as $i => $column)
|
||||
{
|
||||
if (is_object($column))
|
||||
$columns[$i] = (string)$column;
|
||||
elseif (strpos($column, '(') === false)
|
||||
$columns[$i] = $this->_connection->quoteColumnName($column);
|
||||
}
|
||||
$this->_query['group'] = implode(', ', $columns);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HAVING part of the query.
|
||||
* @param mixed $conditions the conditions to be put after HAVING.
|
||||
* Please refer to {@link where} on how to specify conditions.
|
||||
* @param array $params the parameters (name=>value) to be bound to the query
|
||||
* @return Command the command object itself
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function having($conditions, $params = array())
|
||||
{
|
||||
$this->_query['having'] = $this->processConditions($conditions);
|
||||
foreach ($params as $name => $value)
|
||||
$this->params[$name] = $value;
|
||||
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
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function order($columns)
|
||||
{
|
||||
if (is_string($columns) && strpos($columns, '(') !== false)
|
||||
$this->_query['order'] = $columns;
|
||||
else
|
||||
{
|
||||
if (!is_array($columns))
|
||||
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($columns as $i => $column)
|
||||
{
|
||||
if (is_object($column))
|
||||
$columns[$i] = (string)$column;
|
||||
elseif (strpos($column, '(') === false)
|
||||
{
|
||||
if (preg_match('/^(.*?)\s+(asc|desc)$/i', $column, $matches))
|
||||
$columns[$i] = $this->_connection->quoteColumnName($matches[1]) . ' ' . strtoupper($matches[2]);
|
||||
else
|
||||
$columns[$i] = $this->_connection->quoteColumnName($column);
|
||||
}
|
||||
}
|
||||
$this->_query['order'] = implode(', ', $columns);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LIMIT part of the query.
|
||||
* @param integer $limit the limit
|
||||
* @param integer $offset the offset
|
||||
* @return Command the command object itself
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function limit($limit, $offset = null)
|
||||
{
|
||||
$this->_query['limit'] = (int)$limit;
|
||||
if ($offset !== null)
|
||||
$this->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
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function union($sql)
|
||||
{
|
||||
if (isset($this->_query['union']) && is_string($this->_query['union']))
|
||||
$this->_query['union'] = array($this->_query['union']);
|
||||
|
||||
$this->_query['union'][] = $sql;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the condition string that will be put in the WHERE part
|
||||
* @param mixed $conditions the conditions that will be put in the WHERE part.
|
||||
* @return string the condition string to put in the WHERE part
|
||||
*/
|
||||
private function buildConditions($conditions)
|
||||
{
|
||||
if (!is_array($conditions))
|
||||
return $conditions;
|
||||
elseif ($conditions === array())
|
||||
return '';
|
||||
$n = count($conditions);
|
||||
$operator = strtoupper($conditions[0]);
|
||||
if ($operator === 'OR' || $operator === 'AND')
|
||||
{
|
||||
$parts = array();
|
||||
for ($i = 1;$i < $n;++$i)
|
||||
{
|
||||
$condition = $this->processConditions($conditions[$i]);
|
||||
if ($condition !== '')
|
||||
$parts[] = '(' . $condition . ')';
|
||||
}
|
||||
return $parts === array() ? '' : implode(' ' . $operator . ' ', $parts);
|
||||
}
|
||||
|
||||
if (!isset($conditions[1], $conditions[2]))
|
||||
return '';
|
||||
|
||||
$column = $conditions[1];
|
||||
if (strpos($column, '(') === false)
|
||||
$column = $this->_connection->quoteColumnName($column);
|
||||
|
||||
$values = $conditions[2];
|
||||
if (!is_array($values))
|
||||
$values = array($values);
|
||||
|
||||
if ($operator === 'IN' || $operator === 'NOT IN')
|
||||
{
|
||||
if ($values === array())
|
||||
return $operator === 'IN' ? '0=1' : '';
|
||||
foreach ($values as $i => $value)
|
||||
{
|
||||
if (is_string($value))
|
||||
$values[$i] = $this->_connection->quoteValue($value);
|
||||
else
|
||||
$values[$i] = (string)$value;
|
||||
}
|
||||
return $column . ' ' . $operator . ' (' . implode(', ', $values) . ')';
|
||||
}
|
||||
|
||||
if ($operator === 'LIKE' || $operator === 'NOT LIKE' || $operator === 'OR LIKE' || $operator === 'OR NOT LIKE')
|
||||
{
|
||||
if ($values === array())
|
||||
return $operator === 'LIKE' || $operator === 'OR LIKE' ? '0=1' : '';
|
||||
|
||||
if ($operator === 'LIKE' || $operator === 'NOT LIKE')
|
||||
$andor = ' AND ';
|
||||
else
|
||||
{
|
||||
$andor = ' OR ';
|
||||
$operator = $operator === 'OR LIKE' ? 'LIKE' : 'NOT LIKE';
|
||||
}
|
||||
$expressions = array();
|
||||
foreach ($values as $value)
|
||||
$expressions[] = $column . ' ' . $operator . ' ' . $this->_connection->quoteValue($value);
|
||||
return implode($andor, $expressions);
|
||||
}
|
||||
|
||||
throw new CDbException(Yii::t('yii', 'Unknown operator "{operator}".', array('{operator}' => $operator)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@link where} on how to specify conditions.
|
||||
* @param array $params the parameters (name=>value) to be bound to the query
|
||||
* @return Command the command object itself
|
||||
* @since 1.1.6
|
||||
*/
|
||||
private function joinInternal($type, $table, $conditions = '', $params = array())
|
||||
{
|
||||
if (strpos($table, '(') === false)
|
||||
{
|
||||
if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $table, $matches)) // with alias
|
||||
$table = $this->_connection->quoteTableName($matches[1]) . ' ' . $this->_connection->quoteTableName($matches[2]);
|
||||
else
|
||||
$table = $this->_connection->quoteTableName($table);
|
||||
}
|
||||
|
||||
$conditions = $this->processConditions($conditions);
|
||||
if ($conditions != '')
|
||||
$conditions = ' ON ' . $conditions;
|
||||
|
||||
if (isset($this->_query['join']) && is_string($this->_query['join']))
|
||||
$this->_query['join'] = array($this->_query['join']);
|
||||
|
||||
$this->_query['join'][] = strtoupper($type) . ' ' . $table . $conditions;
|
||||
|
||||
foreach ($params as $name => $value)
|
||||
$this->params[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
556
framework/db/dao/Schema.php
Normal file
556
framework/db/dao/Schema.php
Normal file
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
/**
|
||||
* CDbSchema class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2011 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CDbSchema is the base class for retrieving metadata information.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @version $Id: CDbSchema.php 3359 2011-07-18 11:25:17Z qiang.xue $
|
||||
* @package system.db.schema
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class CDbSchema extends CComponent
|
||||
{
|
||||
/**
|
||||
* @var array the abstract column types mapped to physical column types.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public $columnTypes = array();
|
||||
|
||||
private $_tableNames = array();
|
||||
private $_tables = array();
|
||||
private $_connection;
|
||||
private $_builder;
|
||||
private $_cacheExclude = array();
|
||||
|
||||
/**
|
||||
* Loads the metadata for the specified table.
|
||||
* @param string $name table name
|
||||
* @return CDbTableSchema driver dependent table metadata, null if the table does not exist.
|
||||
*/
|
||||
abstract protected function loadTable($name);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param CDbConnection $conn database connection.
|
||||
*/
|
||||
public function __construct($conn)
|
||||
{
|
||||
$this->_connection = $conn;
|
||||
foreach ($conn->schemaCachingExclude as $name)
|
||||
$this->_cacheExclude[$name] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CDbConnection database connection. The connection is active.
|
||||
*/
|
||||
public function getDbConnection()
|
||||
{
|
||||
return $this->_connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the metadata for the named table.
|
||||
* @param string $name table name
|
||||
* @return CDbTableSchema table metadata. Null if the named table does not exist.
|
||||
*/
|
||||
public function getTable($name)
|
||||
{
|
||||
if (isset($this->_tables[$name]))
|
||||
return $this->_tables[$name];
|
||||
else
|
||||
{
|
||||
if ($this->_connection->tablePrefix !== null && strpos($name, '{{') !== false)
|
||||
$realName = preg_replace('/\{\{(.*?)\}\}/', $this->_connection->tablePrefix . '$1', $name);
|
||||
else
|
||||
$realName = $name;
|
||||
|
||||
// temporarily disable query caching
|
||||
if ($this->_connection->queryCachingDuration > 0)
|
||||
{
|
||||
$qcDuration = $this->_connection->queryCachingDuration;
|
||||
$this->_connection->queryCachingDuration = 0;
|
||||
}
|
||||
|
||||
if (!isset($this->_cacheExclude[$name]) && ($duration = $this->_connection->schemaCachingDuration) > 0 && $this->_connection->schemaCacheID !== false && ($cache = Yii::app()->getComponent($this->_connection->schemaCacheID)) !== null)
|
||||
{
|
||||
$key = 'yii:dbschema' . $this->_connection->connectionString . ':' . $this->_connection->username . ':' . $name;
|
||||
if (($table = $cache->get($key)) === false)
|
||||
{
|
||||
$table = $this->loadTable($realName);
|
||||
if ($table !== null)
|
||||
$cache->set($key, $table, $duration);
|
||||
}
|
||||
$this->_tables[$name] = $table;
|
||||
}
|
||||
else
|
||||
$this->_tables[$name] = $table = $this->loadTable($realName);
|
||||
|
||||
if (isset($qcDuration)) // re-enable query caching
|
||||
$this->_connection->queryCachingDuration = $qcDuration;
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata for all tables in the database.
|
||||
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
|
||||
* @return array the metadata for all tables in the database.
|
||||
* Each array element is an instance of {@link CDbTableSchema} (or its child class).
|
||||
* The array keys are table names.
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public function getTables($schema = '')
|
||||
{
|
||||
$tables = array();
|
||||
foreach ($this->getTableNames($schema) as $name)
|
||||
{
|
||||
if (($table = $this->getTable($name)) !== null)
|
||||
$tables[$name] = $table;
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all table names in the database.
|
||||
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
|
||||
* If not empty, the returned table names will be prefixed with the schema name.
|
||||
* @return array all table names in the database.
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public function getTableNames($schema = '')
|
||||
{
|
||||
if (!isset($this->_tableNames[$schema]))
|
||||
$this->_tableNames[$schema] = $this->findTableNames($schema);
|
||||
return $this->_tableNames[$schema];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CDbCommandBuilder the SQL command builder for this connection.
|
||||
*/
|
||||
public function getCommandBuilder()
|
||||
{
|
||||
if ($this->_builder !== null)
|
||||
return $this->_builder;
|
||||
else
|
||||
return $this->_builder = $this->createCommandBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the schema.
|
||||
* This method resets the loaded table metadata and command builder
|
||||
* so that they can be recreated to reflect the change of schema.
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
if (($duration = $this->_connection->schemaCachingDuration) > 0 && $this->_connection->schemaCacheID !== false && ($cache = Yii::app()->getComponent($this->_connection->schemaCacheID)) !== null)
|
||||
{
|
||||
foreach (array_keys($this->_tables) as $name)
|
||||
{
|
||||
if (!isset($this->_cacheExclude[$name]))
|
||||
{
|
||||
$key = 'yii:dbschema' . $this->_connection->connectionString . ':' . $this->_connection->username . ':' . $name;
|
||||
$cache->delete($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_tables = array();
|
||||
$this->_tableNames = array();
|
||||
$this->_builder = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes a table name for use in a query.
|
||||
* If the table name contains schema prefix, the prefix will also be properly quoted.
|
||||
* @param string $name table name
|
||||
* @return string the properly quoted table name
|
||||
* @see quoteSimpleTableName
|
||||
*/
|
||||
public function quoteTableName($name)
|
||||
{
|
||||
if (strpos($name, '.') === false)
|
||||
return $this->quoteSimpleTableName($name);
|
||||
$parts = explode('.', $name);
|
||||
foreach ($parts as $i => $part)
|
||||
$parts[$i] = $this->quoteSimpleTableName($part);
|
||||
return implode('.', $parts);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes a simple table name for use in a query.
|
||||
* A simple table name does not schema prefix.
|
||||
* @param string $name table name
|
||||
* @return string the properly quoted table name
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function quoteSimpleTableName($name)
|
||||
{
|
||||
return "'" . $name . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes a column name for use in a query.
|
||||
* If the column name contains prefix, the prefix will also be properly quoted.
|
||||
* @param string $name column name
|
||||
* @return string the properly quoted column name
|
||||
* @see quoteSimpleColumnName
|
||||
*/
|
||||
public function quoteColumnName($name)
|
||||
{
|
||||
if (($pos = strrpos($name, '.')) !== false)
|
||||
{
|
||||
$prefix = $this->quoteTableName(substr($name, 0, $pos)) . '.';
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
else
|
||||
$prefix = '';
|
||||
return $prefix . ($name === '*' ? $name : $this->quoteSimpleColumnName($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes a simple column name for use in a query.
|
||||
* A simple column name does not contain prefix.
|
||||
* @param string $name column name
|
||||
* @return string the properly quoted column name
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function quoteSimpleColumnName($name)
|
||||
{
|
||||
return '"' . $name . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two table names.
|
||||
* The table names can be either quoted or unquoted. This method
|
||||
* will consider both cases.
|
||||
* @param string $name1 table name 1
|
||||
* @param string $name2 table name 2
|
||||
* @return boolean whether the two table names refer to the same table.
|
||||
*/
|
||||
public function compareTableNames($name1, $name2)
|
||||
{
|
||||
$name1 = str_replace(array('"', '`', "'"), '', $name1);
|
||||
$name2 = str_replace(array('"', '`', "'"), '', $name2);
|
||||
if (($pos = strrpos($name1, '.')) !== false)
|
||||
$name1 = substr($name1, $pos + 1);
|
||||
if (($pos = strrpos($name2, '.')) !== false)
|
||||
$name2 = substr($name2, $pos + 1);
|
||||
if ($this->_connection->tablePrefix !== null)
|
||||
{
|
||||
if (strpos($name1, '{') !== false)
|
||||
$name1 = $this->_connection->tablePrefix . str_replace(array('{', '}'), '', $name1);
|
||||
if (strpos($name2, '{') !== false)
|
||||
$name2 = $this->_connection->tablePrefix . str_replace(array('{', '}'), '', $name2);
|
||||
}
|
||||
return $name1 === $name2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the sequence value of a table's primary key.
|
||||
* The sequence will be reset such that the primary key of the next new row inserted
|
||||
* will have the specified value or 1.
|
||||
* @param CDbTableSchema $table the table schema whose primary key sequence will be reset
|
||||
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
|
||||
* the next new row's primary key will have a value 1.
|
||||
* @since 1.1
|
||||
*/
|
||||
public function resetSequence($table, $value = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables integrity check.
|
||||
* @param boolean $check whether to turn on or off the integrity check.
|
||||
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
|
||||
* @since 1.1
|
||||
*/
|
||||
public function checkIntegrity($check = true, $schema = '')
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a command builder for the database.
|
||||
* This method may be overridden by child classes to create a DBMS-specific command builder.
|
||||
* @return CDbCommandBuilder command builder instance
|
||||
*/
|
||||
protected function createCommandBuilder()
|
||||
{
|
||||
return new CDbCommandBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all table names in the database.
|
||||
* This method should be overridden by child classes in order to support this feature
|
||||
* because the default implementation simply throws an exception.
|
||||
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
|
||||
* If not empty, the returned table names will be prefixed with the schema name.
|
||||
* @return array all table names in the database.
|
||||
* @since 1.0.2
|
||||
*/
|
||||
protected function findTableNames($schema = '')
|
||||
{
|
||||
throw new CDbException(Yii::t('yii', '{class} does not support fetching all table names.',
|
||||
array('{class}' => get_class($this))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an abstract column type into a physical column type.
|
||||
* The conversion is done using the type map specified in {@link columnTypes}.
|
||||
* These abstract column types are supported (using MySQL as example to explain the corresponding
|
||||
* physical types):
|
||||
* <ul>
|
||||
* <li>pk: an auto-incremental primary key type, will be converted into "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY"</li>
|
||||
* <li>string: string type, will be converted into "varchar(255)"</li>
|
||||
* <li>text: a long string type, will be converted into "text"</li>
|
||||
* <li>integer: integer type, will be converted into "int(11)"</li>
|
||||
* <li>boolean: boolean type, will be converted into "tinyint(1)"</li>
|
||||
* <li>float: float number type, will be converted into "float"</li>
|
||||
* <li>decimal: decimal number type, will be converted into "decimal"</li>
|
||||
* <li>datetime: datetime type, will be converted into "datetime"</li>
|
||||
* <li>timestamp: timestamp type, will be converted into "timestamp"</li>
|
||||
* <li>time: time type, will be converted into "time"</li>
|
||||
* <li>date: date type, will be converted into "date"</li>
|
||||
* <li>binary: binary data type, will be converted into "blob"</li>
|
||||
* </ul>
|
||||
*
|
||||
* If the abstract type contains two or more parts separated by spaces (e.g. "string NOT NULL"), then only
|
||||
* the first part will be converted, and the rest of the parts will be appended to the conversion result.
|
||||
* For example, 'string NOT NULL' is converted to 'varchar(255) NOT NULL'.
|
||||
* @param string $type abstract column type
|
||||
* @return string physical column type.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function getColumnType($type)
|
||||
{
|
||||
if (isset($this->columnTypes[$type]))
|
||||
return $this->columnTypes[$type];
|
||||
elseif (($pos = strpos($type, ' ')) !== false)
|
||||
{
|
||||
$t = substr($type, 0, $pos);
|
||||
return (isset($this->columnTypes[$t]) ? $this->columnTypes[$t] : $t) . substr($type, $pos);
|
||||
}
|
||||
else
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 {@link getColumnType} method will be invoked to convert any abstract type into a physical one.
|
||||
*
|
||||
* 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 string the SQL statement for creating a new DB table.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function createTable($table, $columns, $options = null)
|
||||
{
|
||||
$cols = array();
|
||||
foreach ($columns as $name => $type)
|
||||
{
|
||||
if (is_string($name))
|
||||
$cols[] = "\t" . $this->quoteColumnName($name) . ' ' . $this->getColumnType($type);
|
||||
else
|
||||
$cols[] = "\t" . $type;
|
||||
}
|
||||
$sql = "CREATE TABLE " . $this->quoteTableName($table) . " (\n" . implode(",\n", $cols) . "\n)";
|
||||
return $options === null ? $sql : $sql . ' ' . $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for renaming a DB table.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function renameTable($table, $newName)
|
||||
{
|
||||
return 'RENAME TABLE ' . $this->quoteTableName($table) . ' TO ' . $this->quoteTableName($newName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for dropping a DB table.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function dropTable($table)
|
||||
{
|
||||
return "DROP TABLE " . $this->quoteTableName($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for truncating a DB table.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function truncateTable($table)
|
||||
{
|
||||
return "TRUNCATE TABLE " . $this->quoteTableName($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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. The {@link getColumnType} method will be invoked to convert abstract column type (if any)
|
||||
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
|
||||
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
|
||||
* @return string the SQL statement for adding a new column.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function addColumn($table, $column, $type)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table)
|
||||
. ' ADD ' . $this->quoteColumnName($column) . ' '
|
||||
. $this->getColumnType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for dropping a DB column.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function dropColumn($table, $column)
|
||||
{
|
||||
return "ALTER TABLE " . $this->quoteTableName($table)
|
||||
. " DROP COLUMN " . $this->quoteColumnName($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for renaming a DB column.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function renameColumn($table, $name, $newName)
|
||||
{
|
||||
return "ALTER TABLE " . $this->quoteTableName($table)
|
||||
. " RENAME COLUMN " . $this->quoteColumnName($name)
|
||||
. " TO " . $this->quoteColumnName($newName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 new column type. The {@link getColumnType} method will be invoked to convert abstract column type (if any)
|
||||
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
|
||||
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
|
||||
* @return string the SQL statement for changing the definition of a column.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function alterColumn($table, $column, $type)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' CHANGE '
|
||||
. $this->quoteColumnName($column) . ' '
|
||||
. $this->quoteColumnName($column) . ' '
|
||||
. $this->getColumnType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 string the SQL statement for adding a foreign key constraint to an existing table.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
|
||||
{
|
||||
$columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($columns as $i => $col)
|
||||
$columns[$i] = $this->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)
|
||||
. ' FOREIGN KEY (' . implode(', ', $columns) . ')'
|
||||
. ' REFERENCES ' . $this->quoteTableName($refTable)
|
||||
. ' (' . implode(', ', $refColumns) . ')';
|
||||
if ($delete !== null)
|
||||
$sql .= ' ON DELETE ' . $delete;
|
||||
if ($update !== null)
|
||||
$sql .= ' ON UPDATE ' . $update;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 string the SQL statement for dropping a foreign key constraint.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function dropForeignKey($name, $table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->quoteTableName($table)
|
||||
. ' DROP CONSTRAINT ' . $this->quoteColumnName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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. Each column name will be properly quoted by the method, unless a parenthesis is found in the name.
|
||||
* @param boolean $unique whether to add UNIQUE constraint on the created index.
|
||||
* @return string the SQL statement for creating a new index.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function createIndex($name, $table, $column, $unique = false)
|
||||
{
|
||||
$cols = array();
|
||||
$columns = preg_split('/\s*,\s*/', $column, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($columns as $col)
|
||||
{
|
||||
if (strpos($col, '(') !== false)
|
||||
$cols[] = $col;
|
||||
else
|
||||
$cols[] = $this->quoteColumnName($col);
|
||||
}
|
||||
return ($unique ? 'CREATE UNIQUE INDEX ' : 'CREATE INDEX ')
|
||||
. $this->quoteTableName($name) . ' ON '
|
||||
. $this->quoteTableName($table) . ' (' . implode(', ', $cols) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds 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 string the SQL statement for dropping an index.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
public function dropIndex($name, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $this->quoteTableName($name) . ' ON ' . $this->quoteTableName($table);
|
||||
}
|
||||
}
|
||||
76
framework/db/dao/TableSchema.php
Normal file
76
framework/db/dao/TableSchema.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* CDbTableSchema class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright © 2008-2011 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CDbTableSchema is the base class for representing the metadata of a database table.
|
||||
*
|
||||
* It may be extended by different DBMS driver to provide DBMS-specific table metadata.
|
||||
*
|
||||
* CDbTableSchema provides the following information about a table:
|
||||
* <ul>
|
||||
* <li>{@link name}</li>
|
||||
* <li>{@link rawName}</li>
|
||||
* <li>{@link columns}</li>
|
||||
* <li>{@link primaryKey}</li>
|
||||
* <li>{@link foreignKeys}</li>
|
||||
* <li>{@link sequenceName}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @version $Id: CDbTableSchema.php 2799 2011-01-01 19:31:13Z qiang.xue $
|
||||
* @package system.db.schema
|
||||
* @since 1.0
|
||||
*/
|
||||
class CDbTableSchema extends CComponent
|
||||
{
|
||||
/**
|
||||
* @var string name of this table.
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string raw name of this table. This is the quoted version of table name with optional schema name. It can be directly used in SQLs.
|
||||
*/
|
||||
public $rawName;
|
||||
/**
|
||||
* @var string|array primary key name of this table. If composite key, an array of key names is returned.
|
||||
*/
|
||||
public $primaryKey;
|
||||
/**
|
||||
* @var string sequence name for the primary key. Null if no sequence.
|
||||
*/
|
||||
public $sequenceName;
|
||||
/**
|
||||
* @var array foreign keys of this table. The array is indexed by column name. Each value is an array of foreign table name and foreign column name.
|
||||
*/
|
||||
public $foreignKeys = array();
|
||||
/**
|
||||
* @var array column metadata of this table. Each array element is a CDbColumnSchema object, indexed by column names.
|
||||
*/
|
||||
public $columns = array();
|
||||
|
||||
/**
|
||||
* Gets the named column metadata.
|
||||
* This is a convenient method for retrieving a named column even if it does not exist.
|
||||
* @param string $name column name
|
||||
* @return CDbColumnSchema metadata of the named column. Null if the named column does not exist.
|
||||
*/
|
||||
public function getColumn($name)
|
||||
{
|
||||
return isset($this->columns[$name]) ? $this->columns[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array list of column names
|
||||
*/
|
||||
public function getColumnNames()
|
||||
{
|
||||
return array_keys($this->columns);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user