7 changed files with 1766 additions and 1 deletions
			
			
		| @ -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; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -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); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -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); | ||||||
|  | 	} | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in new issue