37 changed files with 897 additions and 108 deletions
			
			
		| @ -0,0 +1,116 @@ | ||||
| <?php | ||||
| /** | ||||
|  * @link http://www.yiiframework.com/ | ||||
|  * @copyright Copyright (c) 2008 Yii Software LLC | ||||
|  * @license http://www.yiiframework.com/license/ | ||||
|  */ | ||||
| 
 | ||||
| namespace yii\db\cubrid; | ||||
| 
 | ||||
| use yii\base\InvalidParamException; | ||||
| 
 | ||||
| /** | ||||
|  * QueryBuilder is the query builder for CUBRID databases (version 9.1.x and higher). | ||||
|  * | ||||
|  * @author Carsten Brandt <mail@cebe.cc> | ||||
|  * @since 2.0 | ||||
|  */ | ||||
| class QueryBuilder extends \yii\db\QueryBuilder | ||||
| { | ||||
| 	/** | ||||
| 	 * @var array mapping from abstract column types (keys) to physical column types (values). | ||||
| 	 */ | ||||
| 	public $typeMap = array( | ||||
| 		Schema::TYPE_PK => 'int NOT NULL AUTO_INCREMENT PRIMARY KEY', | ||||
| 		Schema::TYPE_STRING => 'varchar(255)', | ||||
| 		Schema::TYPE_TEXT => 'varchar', | ||||
| 		Schema::TYPE_SMALLINT => 'smallint', | ||||
| 		Schema::TYPE_INTEGER => 'int', | ||||
| 		Schema::TYPE_BIGINT => 'bigint', | ||||
| 		Schema::TYPE_FLOAT => 'float(7)', | ||||
| 		Schema::TYPE_DECIMAL => 'decimal(10,0)', | ||||
| 		Schema::TYPE_DATETIME => 'datetime', | ||||
| 		Schema::TYPE_TIMESTAMP => 'timestamp', | ||||
| 		Schema::TYPE_TIME => 'time', | ||||
| 		Schema::TYPE_DATE => 'date', | ||||
| 		Schema::TYPE_BINARY => 'blob', | ||||
| 		Schema::TYPE_BOOLEAN => 'smallint', | ||||
| 		Schema::TYPE_MONEY => 'decimal(19,4)', | ||||
| 	); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a SQL statement for resetting 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 string $tableName the name of the table 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. | ||||
| 	 * @return string the SQL statement for resetting sequence | ||||
| 	 * @throws InvalidParamException if the table does not exist or there is no sequence associated with the table. | ||||
| 	 */ | ||||
| 	public function resetSequence($tableName, $value = null) | ||||
| 	{ | ||||
| 		$table = $this->db->getTableSchema($tableName); | ||||
| 		if ($table !== null && $table->sequenceName !== null) { | ||||
| 			$tableName = $this->db->quoteTableName($tableName); | ||||
| 			if ($value === null) { | ||||
| 				$key = reset($table->primaryKey); | ||||
| 				$value = (int)$this->db->createCommand("SELECT MAX(`$key`) FROM " . $this->db->schema->quoteTableName($tableName))->queryScalar() + 1; | ||||
| 			} else { | ||||
| 				$value = (int)$value; | ||||
| 			} | ||||
| 			return "ALTER TABLE " . $this->db->schema->quoteTableName($tableName) . " AUTO_INCREMENT=$value;"; | ||||
| 		} elseif ($table === null) { | ||||
| 			throw new InvalidParamException("Table not found: $tableName"); | ||||
| 		} else { | ||||
| 			throw new InvalidParamException("There is not sequence associated with table '$tableName'."); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Generates a batch INSERT SQL statement. | ||||
| 	 * For example, | ||||
| 	 * | ||||
| 	 * ~~~ | ||||
| 	 * $connection->createCommand()->batchInsert('tbl_user', array('name', 'age'), array( | ||||
| 	 *     array('Tom', 30), | ||||
| 	 *     array('Jane', 20), | ||||
| 	 *     array('Linda', 25), | ||||
| 	 * ))->execute(); | ||||
| 	 * ~~~ | ||||
| 	 * | ||||
| 	 * Note that the values in each row must match the corresponding column names. | ||||
| 	 * | ||||
| 	 * @param string $table the table that new rows will be inserted into. | ||||
| 	 * @param array $columns the column names | ||||
| 	 * @param array $rows the rows to be batch inserted into the table | ||||
| 	 * @return string the batch INSERT SQL statement | ||||
| 	 */ | ||||
| 	public function batchInsert($table, $columns, $rows) | ||||
| 	{ | ||||
| 		if (($tableSchema = $this->db->getTableSchema($table)) !== null) { | ||||
| 			$columnSchemas = $tableSchema->columns; | ||||
| 		} else { | ||||
| 			$columnSchemas = array(); | ||||
| 		} | ||||
| 
 | ||||
| 		foreach ($columns as $i => $name) { | ||||
| 			$columns[$i] = $this->db->quoteColumnName($name); | ||||
| 		} | ||||
| 
 | ||||
| 		$values = array(); | ||||
| 		foreach ($rows as $row) { | ||||
| 			$vs = array(); | ||||
| 			foreach ($row as $i => $value) { | ||||
| 				if (!is_array($value) && isset($columnSchemas[$columns[$i]])) { | ||||
| 					$value = $columnSchemas[$columns[$i]]->typecast($value); | ||||
| 				} | ||||
| 				$vs[] = is_string($value) ? $this->db->quoteValue($value) : $value; | ||||
| 			} | ||||
| 			$values[] = '(' . implode(', ', $vs) . ')'; | ||||
| 		} | ||||
| 
 | ||||
| 		return 'INSERT INTO ' . $this->db->quoteTableName($table) | ||||
| 			. ' (' . implode(', ', $columns) . ') VALUES ' . implode(', ', $values); | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,259 @@ | ||||
| <?php | ||||
| /** | ||||
|  * @link http://www.yiiframework.com/ | ||||
|  * @copyright Copyright (c) 2008 Yii Software LLC | ||||
|  * @license http://www.yiiframework.com/license/ | ||||
|  */ | ||||
| 
 | ||||
| namespace yii\db\cubrid; | ||||
| 
 | ||||
| use yii\base\NotSupportedException; | ||||
| use yii\db\Expression; | ||||
| use yii\db\TableSchema; | ||||
| use yii\db\ColumnSchema; | ||||
| 
 | ||||
| /** | ||||
|  * Schema is the class for retrieving metadata from a CUBRID database (version 9.1.x and higher). | ||||
|  * | ||||
|  * @author Carsten Brandt <mail@cebe.cc> | ||||
|  * @since 2.0 | ||||
|  */ | ||||
| class Schema extends \yii\db\Schema | ||||
| { | ||||
| 	/** | ||||
| 	 * @var array mapping from physical column types (keys) to abstract column types (values) | ||||
| 	 * Please refer to [CUBRID manual](http://www.cubrid.org/manual/91/en/sql/datatype.html) for | ||||
| 	 * details on data types. | ||||
| 	 */ | ||||
| 	public $typeMap = array( | ||||
| 		// Numeric data types | ||||
| 		'short' => self::TYPE_SMALLINT, | ||||
| 		'smallint' => self::TYPE_SMALLINT, | ||||
| 		'int' => self::TYPE_INTEGER, | ||||
| 		'integer' => self::TYPE_INTEGER, | ||||
| 		'bigint' => self::TYPE_BIGINT, | ||||
| 		'numeric' => self::TYPE_DECIMAL, | ||||
| 		'decimal' => self::TYPE_DECIMAL, | ||||
| 		'float' => self::TYPE_FLOAT, | ||||
| 		'real' => self::TYPE_FLOAT, | ||||
| 		'double' => self::TYPE_FLOAT, | ||||
| 		'double precision' => self::TYPE_FLOAT, | ||||
| 		'monetary' => self::TYPE_MONEY, | ||||
| 		// Date/Time data types | ||||
| 		'date' => self::TYPE_DATE, | ||||
| 		'time' => self::TYPE_TIME, | ||||
| 		'timestamp' => self::TYPE_TIMESTAMP, | ||||
| 		'datetime' => self::TYPE_DATETIME, | ||||
| 		// String data types | ||||
| 		'char' => self::TYPE_STRING, | ||||
| 		'varchar' => self::TYPE_STRING, | ||||
| 		'char varying' => self::TYPE_STRING, | ||||
| 		'nchar' => self::TYPE_STRING, | ||||
| 		'nchar varying' => self::TYPE_STRING, | ||||
| 		'string' => self::TYPE_STRING, | ||||
| 		// BLOB/CLOB data types | ||||
| 		'blob' => self::TYPE_BINARY, | ||||
| 		'clob' => self::TYPE_BINARY, | ||||
| 		// Bit string data types | ||||
| 		'bit' => self::TYPE_STRING, | ||||
| 		'bit varying' => self::TYPE_STRING, | ||||
| 		// Collection data types (considered strings for now, may add support for them later) | ||||
| 		'set' => self::TYPE_STRING, | ||||
| 		'multiset' => self::TYPE_STRING, | ||||
| 		'list' => self::TYPE_STRING, | ||||
| 		'sequence' => self::TYPE_STRING, | ||||
| 		'enum' => self::TYPE_STRING, | ||||
| 	); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Quotes a table name for use in a query. | ||||
| 	 * A simple table name has no schema prefix. | ||||
| 	 * @param string $name table name | ||||
| 	 * @return string the properly quoted table name | ||||
| 	 */ | ||||
| 	public function quoteSimpleTableName($name) | ||||
| 	{ | ||||
| 		return strpos($name, "`") !== false ? $name : "`" . $name . "`"; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Quotes a column name for use in a query. | ||||
| 	 * A simple column name has no prefix. | ||||
| 	 * @param string $name column name | ||||
| 	 * @return string the properly quoted column name | ||||
| 	 */ | ||||
| 	public function quoteSimpleColumnName($name) | ||||
| 	{ | ||||
| 		return strpos($name, '`') !== false || $name === '*' ? $name : '`' . $name . '`'; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Quotes a string value for use in a query. | ||||
| 	 * Note that if the parameter is not a string, it will be returned without change. | ||||
| 	 * @param string $str string to be quoted | ||||
| 	 * @return string the properly quoted string | ||||
| 	 * @see http://www.php.net/manual/en/function.PDO-quote.php | ||||
| 	 */ | ||||
| 	public function quoteValue($str) | ||||
| 	{ | ||||
| 		if (!is_string($str)) { | ||||
| 			return $str; | ||||
| 		} | ||||
| 
 | ||||
| 		$this->db->open(); | ||||
| 		// workaround for broken PDO::quote() implementation in CUBRID 9.1.0 http://jira.cubrid.org/browse/APIS-658 | ||||
| 		if (version_compare($this->db->pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION), '9.1.0', '<=')) { | ||||
| 			return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'"; | ||||
| 		} else { | ||||
| 			return $this->db->pdo->quote($str); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a query builder for the CUBRID database. | ||||
| 	 * @return QueryBuilder query builder instance | ||||
| 	 */ | ||||
| 	public function createQueryBuilder() | ||||
| 	{ | ||||
| 		return new QueryBuilder($this->db); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Loads the metadata for the specified table. | ||||
| 	 * @param string $name table name | ||||
| 	 * @return TableSchema driver dependent table metadata. Null if the table does not exist. | ||||
| 	 */ | ||||
| 	protected function loadTableSchema($name) | ||||
| 	{ | ||||
| 		$this->db->open(); | ||||
| 		$tableInfo = $this->db->pdo->cubrid_schema(\PDO::CUBRID_SCH_TABLE, $name); | ||||
| 
 | ||||
| 		if (isset($tableInfo[0]['NAME'])) { | ||||
| 			$table = new TableSchema(); | ||||
| 			$table->name = $tableInfo[0]['NAME']; | ||||
| 
 | ||||
| 			$sql = 'SHOW FULL COLUMNS FROM ' . $this->quoteSimpleTableName($table->name); | ||||
| 			$columns = $this->db->createCommand($sql)->queryAll(); | ||||
| 
 | ||||
| 			foreach ($columns as $info) { | ||||
| 				$column = $this->loadColumnSchema($info); | ||||
| 				$table->columns[$column->name] = $column; | ||||
| 				if ($column->isPrimaryKey) { | ||||
| 					$table->primaryKey[] = $column->name; | ||||
| 					if ($column->autoIncrement) { | ||||
| 						$table->sequenceName = ''; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			$foreignKeys = $this->db->pdo->cubrid_schema(\PDO::CUBRID_SCH_IMPORTED_KEYS, $table->name); | ||||
| 			foreach($foreignKeys as $key) { | ||||
| 				if (isset($table->foreignKeys[$key['FK_NAME']])) { | ||||
| 					$table->foreignKeys[$key['FK_NAME']][$key['FKCOLUMN_NAME']] = $key['PKCOLUMN_NAME']; | ||||
| 				} else { | ||||
| 					$table->foreignKeys[$key['FK_NAME']] = array( | ||||
| 						$key['PKTABLE_NAME'], | ||||
| 						$key['FKCOLUMN_NAME'] => $key['PKCOLUMN_NAME'] | ||||
| 					); | ||||
| 				} | ||||
| 			} | ||||
| 			$table->foreignKeys = array_values($table->foreignKeys); | ||||
| 
 | ||||
| 			return $table; | ||||
| 		} else { | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Loads the column information into a [[ColumnSchema]] object. | ||||
| 	 * @param array $info column information | ||||
| 	 * @return ColumnSchema the column schema object | ||||
| 	 */ | ||||
| 	protected function loadColumnSchema($info) | ||||
| 	{ | ||||
| 		$column = new ColumnSchema(); | ||||
| 
 | ||||
| 		$column->name = $info['Field']; | ||||
| 		$column->allowNull = $info['Null'] === 'YES'; | ||||
| 		$column->isPrimaryKey = strpos($info['Key'], 'PRI') !== false; | ||||
| 		$column->autoIncrement = stripos($info['Extra'], 'auto_increment') !== false; | ||||
| 
 | ||||
| 		$column->dbType = strtolower($info['Type']); | ||||
| 		$column->unsigned = strpos($column->dbType, 'unsigned') !== false; | ||||
| 
 | ||||
| 		$column->type = self::TYPE_STRING; | ||||
| 		if (preg_match('/^([\w ]+)(?:\(([^\)]+)\))?/', $column->dbType, $matches)) { | ||||
| 			$type = $matches[1]; | ||||
| 			if (isset($this->typeMap[$type])) { | ||||
| 				$column->type = $this->typeMap[$type]; | ||||
| 			} | ||||
| 			if (!empty($matches[2])) { | ||||
| 				if ($type === 'enum') { | ||||
| 					$values = explode(',', $matches[2]); | ||||
| 					foreach ($values as $i => $value) { | ||||
| 						$values[$i] = trim($value, "'"); | ||||
| 					} | ||||
| 					$column->enumValues = $values; | ||||
| 				} else { | ||||
| 					$values = explode(',', $matches[2]); | ||||
| 					$column->size = $column->precision = (int)$values[0]; | ||||
| 					if (isset($values[1])) { | ||||
| 						$column->scale = (int)$values[1]; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		$column->phpType = $this->getColumnPhpType($column); | ||||
| 
 | ||||
| 		if ($column->type === 'timestamp' && $info['Default'] === 'CURRENT_TIMESTAMP' || | ||||
| 			$column->type === 'datetime' && $info['Default'] === 'SYS_DATETIME' || | ||||
| 			$column->type === 'date' && $info['Default'] === 'SYS_DATE' || | ||||
| 			$column->type === 'time' && $info['Default'] === 'SYS_TIME') { | ||||
| 			$column->defaultValue = new Expression($info['Default']); | ||||
| 		} else { | ||||
| 			$column->defaultValue = $column->typecast($info['Default']); | ||||
| 		} | ||||
| 
 | ||||
| 		return $column; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 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. | ||||
| 	 * @return array all table names in the database. The names have NO schema name prefix. | ||||
| 	 */ | ||||
| 	protected function findTableNames($schema = '') | ||||
| 	{ | ||||
| 		$this->db->open(); | ||||
| 		$tables = $this->db->pdo->cubrid_schema(\PDO::CUBRID_SCH_TABLE); | ||||
| 		$tableNames = array(); | ||||
| 		foreach($tables as $table) { | ||||
| 			// do not list system tables | ||||
| 			if ($table['TYPE'] != 0) { | ||||
| 				$tableNames[] = $table['NAME']; | ||||
| 			} | ||||
| 		} | ||||
| 		return $tableNames; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Determines the PDO type for the give PHP data value. | ||||
| 	 * @param mixed $data the data whose PDO type is to be determined | ||||
| 	 * @return integer the PDO type | ||||
| 	 * @see http://www.php.net/manual/en/pdo.constants.php | ||||
| 	 */ | ||||
| 	public function getPdoType($data) | ||||
| 	{ | ||||
| 		static $typeMap = array( | ||||
| 			'boolean' => \PDO::PARAM_INT, // CUBRID PDO does not support PARAM_BOOL | ||||
| 			'integer' => \PDO::PARAM_INT, | ||||
| 			'string' => \PDO::PARAM_STR, | ||||
| 			'resource' => \PDO::PARAM_LOB, | ||||
| 			'NULL' => \PDO::PARAM_NULL, | ||||
| 		); | ||||
| 		$type = gettype($data); | ||||
| 		return isset($typeMap[$type]) ? $typeMap[$type] : \PDO::PARAM_STR; | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,110 @@ | ||||
| /** | ||||
|  * This is the database schema for testing CUBRID support of Yii DAO and Active Record. | ||||
|  * The database setup in config.php is required to perform then relevant tests: | ||||
|  */ | ||||
| 
 | ||||
| DROP TABLE IF EXISTS tbl_composite_fk; | ||||
| DROP TABLE IF EXISTS tbl_order_item; | ||||
| DROP TABLE IF EXISTS tbl_item; | ||||
| DROP TABLE IF EXISTS tbl_order; | ||||
| DROP TABLE IF EXISTS tbl_category; | ||||
| DROP TABLE IF EXISTS tbl_customer; | ||||
| DROP TABLE IF EXISTS tbl_type; | ||||
| DROP TABLE IF EXISTS tbl_constraints; | ||||
| 
 | ||||
| CREATE TABLE `tbl_constraints` | ||||
| ( | ||||
|   `id` integer not null, | ||||
|   `field1` varchar(255) | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
| CREATE TABLE `tbl_customer` ( | ||||
|   `id` int(11) NOT NULL AUTO_INCREMENT, | ||||
|   `email` varchar(128) NOT NULL, | ||||
|   `name` varchar(128) NOT NULL, | ||||
|   `address` string, | ||||
|   `status` int (11) DEFAULT 0, | ||||
|   PRIMARY KEY (`id`) | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_category` ( | ||||
|   `id` int(11) NOT NULL AUTO_INCREMENT, | ||||
|   `name` varchar(128) NOT NULL, | ||||
|   PRIMARY KEY (`id`) | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_item` ( | ||||
|   `id` int(11) NOT NULL AUTO_INCREMENT, | ||||
|   `name` varchar(128) NOT NULL, | ||||
|   `category_id` int(11) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   CONSTRAINT `FK_item_category_id` FOREIGN KEY (`category_id`) REFERENCES `tbl_category` (`id`) ON DELETE CASCADE | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_order` ( | ||||
|   `id` int(11) NOT NULL AUTO_INCREMENT, | ||||
|   `customer_id` int(11) NOT NULL, | ||||
|   `create_time` int(11) NOT NULL, | ||||
|   `total` decimal(10,0) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   CONSTRAINT `FK_order_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `tbl_customer` (`id`) ON DELETE CASCADE | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_order_item` ( | ||||
|   `order_id` int(11) NOT NULL, | ||||
|   `item_id` int(11) NOT NULL, | ||||
|   `quantity` int(11) NOT NULL, | ||||
|   `subtotal` decimal(10,0) NOT NULL, | ||||
|   PRIMARY KEY (`order_id`,`item_id`), | ||||
|   CONSTRAINT `FK_order_item_order_id` FOREIGN KEY (`order_id`) REFERENCES `tbl_order` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `FK_order_item_item_id` FOREIGN KEY (`item_id`) REFERENCES `tbl_item` (`id`) ON DELETE CASCADE | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_type` ( | ||||
|   `int_col` int(11) NOT NULL, | ||||
|   `int_col2` int(11) DEFAULT '1', | ||||
|   `char_col` char(100) NOT NULL, | ||||
|   `char_col2` varchar(100) DEFAULT 'something', | ||||
|   `char_col3` string, | ||||
|   `enum_col` enum('a', 'b'), | ||||
|   `float_col` double NOT NULL, | ||||
|   `float_col2` double DEFAULT '1.23', | ||||
|   `blob_col` blob, | ||||
|   `numeric_col` decimal(5,2) DEFAULT '33.22', | ||||
|   `time` timestamp NOT NULL DEFAULT '2002-01-01 00:00:00', | ||||
|   `bool_col` smallint NOT NULL, | ||||
|   `bool_col2` smallint DEFAULT 1 | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE `tbl_composite_fk` ( | ||||
|   `id` int(11) NOT NULL, | ||||
|   `order_id` int(11) NOT NULL, | ||||
|   `item_id` int(11) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   CONSTRAINT `FK_composite_fk_order_item` FOREIGN KEY (`order_id`,`item_id`) REFERENCES `tbl_order_item` (`order_id`,`item_id`) ON DELETE CASCADE | ||||
| ); | ||||
| 
 | ||||
| INSERT INTO tbl_customer (email, name, address, status) VALUES ('user1@example.com', 'user1', 'address1', 1); | ||||
| INSERT INTO tbl_customer (email, name, address, status) VALUES ('user2@example.com', 'user2', 'address2', 1); | ||||
| INSERT INTO tbl_customer (email, name, address, status) VALUES ('user3@example.com', 'user3', 'address3', 2); | ||||
| 
 | ||||
| INSERT INTO tbl_category (name) VALUES ('Books'); | ||||
| INSERT INTO tbl_category (name) VALUES ('Movies'); | ||||
| 
 | ||||
| INSERT INTO tbl_item (name, category_id) VALUES ('Agile Web Application Development with Yii1.1 and PHP5', 1); | ||||
| INSERT INTO tbl_item (name, category_id) VALUES ('Yii 1.1 Application Development Cookbook', 1); | ||||
| INSERT INTO tbl_item (name, category_id) VALUES ('Ice Age', 2); | ||||
| INSERT INTO tbl_item (name, category_id) VALUES ('Toy Story', 2); | ||||
| INSERT INTO tbl_item (name, category_id) VALUES ('Cars', 2); | ||||
| 
 | ||||
| INSERT INTO tbl_order (customer_id, create_time, total) VALUES (1, 1325282384, 110.0); | ||||
| INSERT INTO tbl_order (customer_id, create_time, total) VALUES (2, 1325334482, 33.0); | ||||
| INSERT INTO tbl_order (customer_id, create_time, total) VALUES (2, 1325502201, 40.0); | ||||
| 
 | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (1, 1, 1, 30.0); | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (1, 2, 2, 40.0); | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 4, 1, 10.0); | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0); | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); | ||||
| INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); | ||||
| @ -0,0 +1,89 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace yiiunit\framework\db; | ||||
| 
 | ||||
| use yii\caching\FileCache; | ||||
| use yii\db\Schema; | ||||
| 
 | ||||
| class SchemaTest extends DatabaseTestCase | ||||
| { | ||||
| 
 | ||||
| 	public function testGetPDOType() | ||||
| 	{ | ||||
| 		$values = array( | ||||
| 			array(null, \PDO::PARAM_NULL), | ||||
| 			array('', \PDO::PARAM_STR), | ||||
| 			array('hello', \PDO::PARAM_STR), | ||||
| 			array(0, \PDO::PARAM_INT), | ||||
| 			array(1, \PDO::PARAM_INT), | ||||
| 			array(1337, \PDO::PARAM_INT), | ||||
| 			array(true, \PDO::PARAM_BOOL), | ||||
| 			array(false, \PDO::PARAM_BOOL), | ||||
| 			array($fp=fopen(__FILE__, 'rb'), \PDO::PARAM_LOB), | ||||
| 		); | ||||
| 
 | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		foreach($values as $value) { | ||||
| 			$this->assertEquals($value[1], $schema->getPdoType($value[0])); | ||||
| 		} | ||||
| 		fclose($fp); | ||||
| 	} | ||||
| 
 | ||||
| 	public function testFindTableNames() | ||||
| 	{ | ||||
| 		/** @var Schema $schema */ | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		$tables = $schema->getTableNames(); | ||||
| 		$this->assertTrue(in_array('tbl_customer', $tables)); | ||||
| 		$this->assertTrue(in_array('tbl_category', $tables)); | ||||
| 		$this->assertTrue(in_array('tbl_item', $tables)); | ||||
| 		$this->assertTrue(in_array('tbl_order', $tables)); | ||||
| 		$this->assertTrue(in_array('tbl_order_item', $tables)); | ||||
| 		$this->assertTrue(in_array('tbl_type', $tables)); | ||||
| 	} | ||||
| 
 | ||||
| 	public function testGetTableSchemas() | ||||
| 	{ | ||||
| 		/** @var Schema $schema */ | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		$tables = $schema->getTableSchemas(); | ||||
| 		$this->assertEquals(count($schema->getTableNames()), count($tables)); | ||||
| 		foreach($tables as $table) { | ||||
| 			$this->assertInstanceOf('yii\db\TableSchema', $table); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public function testGetNonExistingTableSchema() | ||||
| 	{ | ||||
| 		$this->assertNull($this->getConnection()->schema->getTableSchema('nonexisting_table')); | ||||
| 	} | ||||
| 
 | ||||
| 	public function testSchemaCache() | ||||
| 	{ | ||||
| 		/** @var Schema $schema */ | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		$schema->db->enableSchemaCache = true; | ||||
| 		$schema->db->schemaCache = new FileCache(); | ||||
| 		$noCacheTable = $schema->getTableSchema('tbl_type', true); | ||||
| 		$cachedTable = $schema->getTableSchema('tbl_type', true); | ||||
| 		$this->assertEquals($noCacheTable, $cachedTable); | ||||
| 	} | ||||
| 
 | ||||
| 	public function testCompositeFk() | ||||
| 	{ | ||||
| 		/** @var Schema $schema */ | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		$table = $schema->getTableSchema('tbl_composite_fk'); | ||||
| 
 | ||||
| 		$this->assertCount(1, $table->foreignKeys); | ||||
| 		$this->assertTrue(isset($table->foreignKeys[0])); | ||||
| 		$this->assertEquals('tbl_order_item', $table->foreignKeys[0][0]); | ||||
| 		$this->assertEquals('order_id', $table->foreignKeys[0]['order_id']); | ||||
| 		$this->assertEquals('item_id', $table->foreignKeys[0]['item_id']); | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yiiunit\framework\db\ActiveRecordTest; | ||||
| 
 | ||||
| class CubridActiveRecordTest extends ActiveRecordTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| } | ||||
| @ -0,0 +1,72 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yiiunit\framework\db\CommandTest; | ||||
| 
 | ||||
| class CubridCommandTest extends CommandTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| 
 | ||||
| 	public function testBindParamValue() | ||||
| 	{ | ||||
| 		$db = $this->getConnection(); | ||||
| 
 | ||||
| 		// bindParam | ||||
| 		$sql = 'INSERT INTO tbl_customer(email, name, address) VALUES (:email, :name, :address)'; | ||||
| 		$command = $db->createCommand($sql); | ||||
| 		$email = 'user4@example.com'; | ||||
| 		$name = 'user4'; | ||||
| 		$address = 'address4'; | ||||
| 		$command->bindParam(':email', $email); | ||||
| 		$command->bindParam(':name', $name); | ||||
| 		$command->bindParam(':address', $address); | ||||
| 		$command->execute(); | ||||
| 
 | ||||
| 		$sql = 'SELECT name FROM tbl_customer WHERE email=:email'; | ||||
| 		$command = $db->createCommand($sql); | ||||
| 		$command->bindParam(':email', $email); | ||||
| 		$this->assertEquals($name, $command->queryScalar()); | ||||
| 
 | ||||
| 		$sql = "INSERT INTO tbl_type (int_col, char_col, char_col2, enum_col, float_col, blob_col, numeric_col, bool_col, bool_col2) VALUES (:int_col, '', :char_col, :enum_col, :float_col, CHAR_TO_BLOB(:blob_col), :numeric_col, :bool_col, :bool_col2)"; | ||||
| 		$command = $db->createCommand($sql); | ||||
| 		$intCol = 123; | ||||
| 		$charCol = 'abc'; | ||||
| 		$enumCol = 'a'; | ||||
| 		$floatCol = 1.23; | ||||
| 		$blobCol = "\x10\x11\x12"; | ||||
| 		$numericCol = '1.23'; | ||||
| 		$boolCol = false; | ||||
| 		$boolCol2 = true; | ||||
| 		$command->bindParam(':int_col', $intCol); | ||||
| 		$command->bindParam(':char_col', $charCol); | ||||
| 		$command->bindParam(':enum_col', $enumCol); | ||||
| 		$command->bindParam(':float_col', $floatCol); | ||||
| 		$command->bindParam(':blob_col', $blobCol); | ||||
| 		$command->bindParam(':numeric_col', $numericCol); | ||||
| 		$command->bindParam(':bool_col', $boolCol); | ||||
| 		$command->bindParam(':bool_col2', $boolCol2); | ||||
| 		$this->assertEquals(1, $command->execute()); | ||||
| 
 | ||||
| 		$sql = 'SELECT * FROM tbl_type'; | ||||
| 		$row = $db->createCommand($sql)->queryOne(); | ||||
| 		$this->assertEquals($intCol, $row['int_col']); | ||||
| 		$this->assertEquals($enumCol, $row['enum_col']); | ||||
| 		$this->assertEquals($charCol, $row['char_col2']); | ||||
| 		$this->assertEquals($floatCol, $row['float_col']); | ||||
| 		$this->assertEquals($blobCol, fread($row['blob_col'], 3)); | ||||
| 		$this->assertEquals($numericCol, $row['numeric_col']); | ||||
| 		$this->assertEquals($boolCol, $row['bool_col']); | ||||
| 		$this->assertEquals($boolCol2, $row['bool_col2']); | ||||
| 
 | ||||
| 		// bindValue | ||||
| 		$sql = 'INSERT INTO tbl_customer(email, name, address) VALUES (:email, \'user5\', \'address5\')'; | ||||
| 		$command = $db->createCommand($sql); | ||||
| 		$command->bindValue(':email', 'user5@example.com'); | ||||
| 		$command->execute(); | ||||
| 
 | ||||
| 		$sql = 'SELECT email FROM tbl_customer WHERE name=:name'; | ||||
| 		$command = $db->createCommand($sql); | ||||
| 		$command->bindValue(':name', 'user5'); | ||||
| 		$this->assertEquals('user5@example.com', $command->queryScalar()); | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yiiunit\framework\db\ConnectionTest; | ||||
| 
 | ||||
| class CubridConnectionTest extends ConnectionTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| 
 | ||||
| 	public function testQuoteValue() | ||||
| 	{ | ||||
| 		$connection = $this->getConnection(false); | ||||
| 		$this->assertEquals(123, $connection->quoteValue(123)); | ||||
| 		$this->assertEquals("'string'", $connection->quoteValue('string')); | ||||
| 		$this->assertEquals("'It''s interesting'", $connection->quoteValue("It's interesting")); | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,80 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yii\base\NotSupportedException; | ||||
| use yii\db\sqlite\Schema; | ||||
| use yiiunit\framework\db\QueryBuilderTest; | ||||
| 
 | ||||
| class CubridQueryBuilderTest extends QueryBuilderTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * this is not used as a dataprovider for testGetColumnType to speed up the test | ||||
| 	 * when used as dataprovider every single line will cause a reconnect with the database which is not needed here | ||||
| 	 */ | ||||
| 	public function columnTypes() | ||||
| 	{ | ||||
| 		return array( | ||||
| 			array(Schema::TYPE_PK, 'int NOT NULL AUTO_INCREMENT PRIMARY KEY'), | ||||
| 			array(Schema::TYPE_PK . '(8)', 'int NOT NULL AUTO_INCREMENT PRIMARY KEY'), | ||||
| 			array(Schema::TYPE_PK . ' CHECK (value > 5)', 'int NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_PK . '(8) CHECK (value > 5)', 'int NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_STRING, 'varchar(255)'), | ||||
| 			array(Schema::TYPE_STRING . '(32)', 'varchar(32)'), | ||||
| 			array(Schema::TYPE_STRING . ' CHECK (value LIKE "test%")', 'varchar(255) CHECK (value LIKE "test%")'), | ||||
| 			array(Schema::TYPE_STRING . '(32) CHECK (value LIKE "test%")', 'varchar(32) CHECK (value LIKE "test%")'), | ||||
| 			array(Schema::TYPE_STRING . ' NOT NULL', 'varchar(255) NOT NULL'), | ||||
| 			array(Schema::TYPE_TEXT, 'varchar'), | ||||
| 			array(Schema::TYPE_TEXT . '(255)', 'varchar'), | ||||
| 			array(Schema::TYPE_TEXT . ' CHECK (value LIKE "test%")', 'varchar CHECK (value LIKE "test%")'), | ||||
| 			array(Schema::TYPE_TEXT . '(255) CHECK (value LIKE "test%")', 'varchar CHECK (value LIKE "test%")'), | ||||
| 			array(Schema::TYPE_TEXT . ' NOT NULL', 'varchar NOT NULL'), | ||||
| 			array(Schema::TYPE_TEXT . '(255) NOT NULL', 'varchar NOT NULL'), | ||||
| 			array(Schema::TYPE_SMALLINT, 'smallint'), | ||||
| 			array(Schema::TYPE_SMALLINT . '(8)', 'smallint'), | ||||
| 			array(Schema::TYPE_INTEGER, 'int'), | ||||
| 			array(Schema::TYPE_INTEGER . '(8)', 'int'), | ||||
| 			array(Schema::TYPE_INTEGER . ' CHECK (value > 5)', 'int CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_INTEGER . '(8) CHECK (value > 5)', 'int CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_INTEGER . ' NOT NULL', 'int NOT NULL'), | ||||
| 			array(Schema::TYPE_BIGINT, 'bigint'), | ||||
| 			array(Schema::TYPE_BIGINT . '(8)', 'bigint'), | ||||
| 			array(Schema::TYPE_BIGINT . ' CHECK (value > 5)', 'bigint CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_BIGINT . '(8) CHECK (value > 5)', 'bigint CHECK (value > 5)'), | ||||
| 			array(Schema::TYPE_BIGINT . ' NOT NULL', 'bigint NOT NULL'), | ||||
| 			array(Schema::TYPE_FLOAT, 'float(7)'), | ||||
| 			array(Schema::TYPE_FLOAT . '(16)', 'float(16)'), | ||||
| 			array(Schema::TYPE_FLOAT . ' CHECK (value > 5.6)', 'float(7) CHECK (value > 5.6)'), | ||||
| 			array(Schema::TYPE_FLOAT . '(16) CHECK (value > 5.6)', 'float(16) CHECK (value > 5.6)'), | ||||
| 			array(Schema::TYPE_FLOAT . ' NOT NULL', 'float(7) NOT NULL'), | ||||
| 			array(Schema::TYPE_DECIMAL, 'decimal(10,0)'), | ||||
| 			array(Schema::TYPE_DECIMAL . '(12,4)', 'decimal(12,4)'), | ||||
| 			array(Schema::TYPE_DECIMAL . ' CHECK (value > 5.6)', 'decimal(10,0) CHECK (value > 5.6)'), | ||||
| 			array(Schema::TYPE_DECIMAL . '(12,4) CHECK (value > 5.6)', 'decimal(12,4) CHECK (value > 5.6)'), | ||||
| 			array(Schema::TYPE_DECIMAL . ' NOT NULL', 'decimal(10,0) NOT NULL'), | ||||
| 			array(Schema::TYPE_DATETIME, 'datetime'), | ||||
| 			array(Schema::TYPE_DATETIME . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "datetime CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), | ||||
| 			array(Schema::TYPE_DATETIME . ' NOT NULL', 'datetime NOT NULL'), | ||||
| 			array(Schema::TYPE_TIMESTAMP, 'timestamp'), | ||||
| 			array(Schema::TYPE_TIMESTAMP . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "timestamp CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), | ||||
| 			array(Schema::TYPE_TIMESTAMP . ' NOT NULL', 'timestamp NOT NULL'), | ||||
| 			array(Schema::TYPE_TIME, 'time'), | ||||
| 			array(Schema::TYPE_TIME . " CHECK(value BETWEEN '12:00:00' AND '13:01:01')", "time CHECK(value BETWEEN '12:00:00' AND '13:01:01')"), | ||||
| 			array(Schema::TYPE_TIME . ' NOT NULL', 'time NOT NULL'), | ||||
| 			array(Schema::TYPE_DATE, 'date'), | ||||
| 			array(Schema::TYPE_DATE . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "date CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), | ||||
| 			array(Schema::TYPE_DATE . ' NOT NULL', 'date NOT NULL'), | ||||
| 			array(Schema::TYPE_BINARY, 'blob'), | ||||
| 			array(Schema::TYPE_BOOLEAN, 'smallint'), | ||||
| 			array(Schema::TYPE_BOOLEAN . ' NOT NULL DEFAULT 1', 'smallint NOT NULL DEFAULT 1'), | ||||
| 			array(Schema::TYPE_MONEY, 'decimal(19,4)'), | ||||
| 			array(Schema::TYPE_MONEY . '(16,2)', 'decimal(16,2)'), | ||||
| 			array(Schema::TYPE_MONEY . ' CHECK (value > 0.0)', 'decimal(19,4) CHECK (value > 0.0)'), | ||||
| 			array(Schema::TYPE_MONEY . '(16,2) CHECK (value > 0.0)', 'decimal(16,2) CHECK (value > 0.0)'), | ||||
| 			array(Schema::TYPE_MONEY . ' NOT NULL', 'decimal(19,4) NOT NULL'), | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yiiunit\framework\db\QueryTest; | ||||
| 
 | ||||
| class CubridQueryTest extends QueryTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| } | ||||
| @ -0,0 +1,31 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\cubrid; | ||||
| 
 | ||||
| use yiiunit\framework\db\SchemaTest; | ||||
| 
 | ||||
| class CubridSchemaTest extends SchemaTest | ||||
| { | ||||
| 	public $driverName = 'cubrid'; | ||||
| 
 | ||||
| 	public function testGetPDOType() | ||||
| 	{ | ||||
| 		$values = array( | ||||
| 			null => \PDO::PARAM_NULL, | ||||
| 			'' => \PDO::PARAM_STR, | ||||
| 			'hello' => \PDO::PARAM_STR, | ||||
| 			0 => \PDO::PARAM_INT, | ||||
| 			1 => \PDO::PARAM_INT, | ||||
| 			1337 => \PDO::PARAM_INT, | ||||
| 			true => \PDO::PARAM_INT, // CUBRID PDO does not support PARAM_BOOL | ||||
| 			false => \PDO::PARAM_INT, // CUBRID PDO does not support PARAM_BOOL | ||||
| 		); | ||||
| 
 | ||||
| 		$schema = $this->getConnection()->schema; | ||||
| 
 | ||||
| 		foreach($values as $value => $type) { | ||||
| 			$this->assertEquals($type, $schema->getPdoType($value)); | ||||
| 		} | ||||
| 		$this->assertEquals(\PDO::PARAM_LOB, $schema->getPdoType($fp=fopen(__FILE__, 'rb'))); | ||||
| 		fclose($fp); | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,14 @@ | ||||
| <?php | ||||
| namespace yiiunit\framework\db\sqlite; | ||||
| 
 | ||||
| use yiiunit\framework\db\SchemaTest; | ||||
| 
 | ||||
| class SqliteSchemaTest extends SchemaTest | ||||
| { | ||||
| 	protected $driverName = 'sqlite'; | ||||
| 
 | ||||
| 	public function testCompositeFk() | ||||
| 	{ | ||||
| 		$this->markTestSkipped('sqlite does not allow getting enough information about composite FK.'); | ||||
| 	} | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue