Qiang Xue
13 years ago
8 changed files with 5526 additions and 0 deletions
@ -0,0 +1,39 @@
|
||||
<?php |
||||
/** |
||||
* CDbException 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* CDbException represents an exception that is caused by some DB-related operations. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @version $Id: CDbException.php 2799 2011-01-01 19:31:13Z qiang.xue $ |
||||
* @package system.db |
||||
* @since 1.0 |
||||
*/ |
||||
class CDbException extends CException |
||||
{ |
||||
/** |
||||
* @var mixed the error info provided by a PDO exception. This is the same as returned |
||||
* by {@link http://www.php.net/manual/en/pdo.errorinfo.php PDO::errorInfo}. |
||||
* @since 1.1.4 |
||||
*/ |
||||
public $errorInfo; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* @param string $message PDO error message |
||||
* @param integer $code PDO error code |
||||
* @param mixed $errorInfo PDO error info |
||||
*/ |
||||
public function __construct($message, $code = 0, $errorInfo = null) |
||||
{ |
||||
$this->errorInfo = $errorInfo; |
||||
parent::__construct($message, $code); |
||||
} |
||||
} |
@ -0,0 +1,387 @@
|
||||
<?php |
||||
/** |
||||
* CMysqlSchema 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* CDbMigration is the base class for representing a database migration. |
||||
* |
||||
* CDbMigration is designed to be used together with the "yiic migrate" command. |
||||
* |
||||
* Each child class of CDbMigration represents an individual database migration which |
||||
* is identified by the child class name. |
||||
* |
||||
* Within each migration, the {@link up} method contains the logic for "upgrading" |
||||
* the database used in an application; while the {@link down} method contains "downgrading" |
||||
* logic. The "yiic migrate" command manages all available migrations in an application. |
||||
* |
||||
* CDbMigration provides a set of convenient methods for manipulating database data and schema. |
||||
* For example, the {@link insert} method can be used to easily insert a row of data into |
||||
* a database table; the {@link createTable} method can be used to create a database table. |
||||
* Compared with the same methods in {@link CDbCommand}, these methods will display extra |
||||
* information showing the method parameters and execution time, which may be useful when |
||||
* applying migrations. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @version $Id: CDbMigration.php 3218 2011-05-13 00:06:44Z alexander.makarow $ |
||||
* @package system.db |
||||
* @since 1.1.6 |
||||
*/ |
||||
abstract class CDbMigration extends CComponent |
||||
{ |
||||
private $_db; |
||||
|
||||
/** |
||||
* This method contains the logic to be executed when applying this migration. |
||||
* Child classes may implement this method to provide actual migration logic. |
||||
* @return boolean |
||||
*/ |
||||
public function up() |
||||
{ |
||||
$transaction = $this->getDbConnection()->beginTransaction(); |
||||
try |
||||
{ |
||||
if ($this->safeUp() === false) |
||||
{ |
||||
$transaction->rollBack(); |
||||
return false; |
||||
} |
||||
$transaction->commit(); |
||||
} |
||||
catch(Exception $e) |
||||
{ |
||||
echo "Exception: " . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n"; |
||||
echo $e->getTraceAsString() . "\n"; |
||||
$transaction->rollBack(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method contains the logic to be executed when removing this migration. |
||||
* The default implementation throws an exception indicating the migration cannot be removed. |
||||
* Child classes may override this method if the corresponding migrations can be removed. |
||||
* @return boolean |
||||
*/ |
||||
public function down() |
||||
{ |
||||
$transaction = $this->getDbConnection()->beginTransaction(); |
||||
try |
||||
{ |
||||
if ($this->safeDown() === false) |
||||
{ |
||||
$transaction->rollBack(); |
||||
return false; |
||||
} |
||||
$transaction->commit(); |
||||
} |
||||
catch(Exception $e) |
||||
{ |
||||
echo "Exception: " . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n"; |
||||
echo $e->getTraceAsString() . "\n"; |
||||
$transaction->rollBack(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method contains the logic to be executed when applying this migration. |
||||
* This method differs from {@link up} in that the DB logic implemented here will |
||||
* be enclosed within a DB transaction. |
||||
* Child classes may implement this method instead of {@link up} if the DB logic |
||||
* needs to be within a transaction. |
||||
* @return boolean |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function safeUp() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* This method contains the logic to be executed when removing this migration. |
||||
* This method differs from {@link down} in that the DB logic implemented here will |
||||
* be enclosed within a DB transaction. |
||||
* Child classes may implement this method instead of {@link up} if the DB logic |
||||
* needs to be within a transaction. |
||||
* @return boolean |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function safeDown() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Returns the currently active database connection. |
||||
* By default, the 'db' application component will be returned and activated. |
||||
* You can call {@link setDbConnection} to switch to a different database connection. |
||||
* Methods such as {@link insert}, {@link createTable} will use this database connection |
||||
* to perform DB queries. |
||||
* @return CDbConnection the currently active database connection |
||||
*/ |
||||
public function getDbConnection() |
||||
{ |
||||
if ($this->_db === null) |
||||
{ |
||||
$this->_db = Yii::app()->getComponent('db'); |
||||
if (!$this->_db instanceof CDbConnection) |
||||
throw new CException(Yii::t('yii', 'The "db" application component must be configured to be a CDbConnection object.')); |
||||
} |
||||
return $this->_db; |
||||
} |
||||
|
||||
/** |
||||
* Sets the currently active database connection. |
||||
* The database connection will be used by the methods such as {@link insert}, {@link createTable}. |
||||
* @param CDbConnection $db the database connection component |
||||
*/ |
||||
public function setDbConnection($db) |
||||
{ |
||||
$this->_db = $db; |
||||
} |
||||
|
||||
/** |
||||
* Executes a SQL statement. |
||||
* This method executes the specified SQL statement using {@link dbConnection}. |
||||
* @param string $sql the SQL statement to be executed |
||||
* @param array $params input parameters (name=>value) for the SQL execution. See {@link CDbCommand::execute} for more details. |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function execute($sql, $params = array()) |
||||
{ |
||||
echo " > execute SQL: $sql ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand($sql)->execute($params); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Creates and executes an INSERT SQL statement. |
||||
* The method will properly escape the column names, and bind the values to be inserted. |
||||
* @param string $table the table that new rows will be inserted into. |
||||
* @param array $columns the column data (name=>value) to be inserted into the table. |
||||
*/ |
||||
public function insert($table, $columns) |
||||
{ |
||||
echo " > insert into $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->insert($table, $columns); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Creates and executes an UPDATE SQL statement. |
||||
* The method will properly escape the column names and bind the values to be updated. |
||||
* @param string $table the table to be updated. |
||||
* @param array $columns the column data (name=>value) to be updated. |
||||
* @param mixed $conditions the conditions that will be put in the WHERE part. Please |
||||
* refer to {@link CDbCommand::where} on how to specify conditions. |
||||
* @param array $params the parameters to be bound to the query. |
||||
*/ |
||||
public function update($table, $columns, $conditions = '', $params = array()) |
||||
{ |
||||
echo " > update $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->update($table, $columns, $conditions, $params); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Creates and executes a DELETE SQL statement. |
||||
* @param string $table the table where the data will be deleted from. |
||||
* @param mixed $conditions the conditions that will be put in the WHERE part. Please |
||||
* refer to {@link CDbCommand::where} on how to specify conditions. |
||||
* @param array $params the parameters to be bound to the query. |
||||
*/ |
||||
public function delete($table, $conditions = '', $params = array()) |
||||
{ |
||||
echo " > delete from $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->delete($table, $conditions, $params); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for creating a new DB table. |
||||
* |
||||
* The columns in the new table should be specified as name-definition pairs (e.g. 'name'=>'string'), |
||||
* where name stands for a column name which will be properly quoted by the method, and definition |
||||
* stands for the column type which can contain an abstract DB type. |
||||
* The {@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. |
||||
*/ |
||||
public function createTable($table, $columns, $options = null) |
||||
{ |
||||
echo " > create table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->createTable($table, $columns, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for renaming a DB table. |
||||
* @param string $table the table to be renamed. The name will be properly quoted by the method. |
||||
* @param string $newName the new table name. The name will be properly quoted by the method. |
||||
*/ |
||||
public function renameTable($table, $newName) |
||||
{ |
||||
echo " > rename table $table to $newName ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->renameTable($table, $newName); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for dropping a DB table. |
||||
* @param string $table the table to be dropped. The name will be properly quoted by the method. |
||||
*/ |
||||
public function dropTable($table) |
||||
{ |
||||
echo " > drop table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->dropTable($table); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for truncating a DB table. |
||||
* @param string $table the table to be truncated. The name will be properly quoted by the method. |
||||
*/ |
||||
public function truncateTable($table) |
||||
{ |
||||
echo " > truncate table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->truncateTable($table); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for adding a new DB column. |
||||
* @param string $table the table that the new column will be added to. The table name will be properly quoted by the method. |
||||
* @param string $column the name of the new column. The name will be properly quoted by the method. |
||||
* @param string $type the column type. 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'. |
||||
*/ |
||||
public function addColumn($table, $column, $type) |
||||
{ |
||||
echo " > add column $column $type to table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->addColumn($table, $column, $type); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for dropping a DB column. |
||||
* @param string $table the table whose column is to be dropped. The name will be properly quoted by the method. |
||||
* @param string $column the name of the column to be dropped. The name will be properly quoted by the method. |
||||
*/ |
||||
public function dropColumn($table, $column) |
||||
{ |
||||
echo " > drop column $column from table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->dropColumn($table, $column); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for renaming a column. |
||||
* @param string $table the table whose column is to be renamed. The name will be properly quoted by the method. |
||||
* @param string $name the old name of the column. The name will be properly quoted by the method. |
||||
* @param string $newName the new name of the column. The name will be properly quoted by the method. |
||||
*/ |
||||
public function renameColumn($table, $name, $newName) |
||||
{ |
||||
echo " > rename column $name in table $table to $newName ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->renameColumn($table, $name, $newName); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for changing the definition of a column. |
||||
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method. |
||||
* @param string $column the name of the column to be changed. The name will be properly quoted by the method. |
||||
* @param string $type the 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'. |
||||
*/ |
||||
public function alterColumn($table, $column, $type) |
||||
{ |
||||
echo " > alter column $column in table $table to $type ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->alterColumn($table, $column, $type); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* 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 |
||||
*/ |
||||
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null) |
||||
{ |
||||
echo " > add foreign key $name: $table ($columns) references $refTable ($refColumns) ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* 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. |
||||
*/ |
||||
public function dropForeignKey($name, $table) |
||||
{ |
||||
echo " > drop foreign key $name from table $table ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->dropForeignKey($name, $table); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for creating a new index. |
||||
* @param string $name the name of the index. The name will be properly quoted by the method. |
||||
* @param string $table the table that the new index will be created for. The table name will be properly quoted by the method. |
||||
* @param string $column the column(s) that should be included in the index. If there are multiple columns, please separate them |
||||
* by commas. The column names will be properly quoted by the method. |
||||
* @param boolean $unique whether to add UNIQUE constraint on the created index. |
||||
*/ |
||||
public function createIndex($name, $table, $column, $unique = false) |
||||
{ |
||||
echo " > create" . ($unique ? ' unique' : '') . " index $name on $table ($column) ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->createIndex($name, $table, $column, $unique); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Builds and executes a SQL statement for dropping an index. |
||||
* @param string $name the name of the index to be dropped. The name will be properly quoted by the method. |
||||
* @param string $table the table whose index is to be dropped. The name will be properly quoted by the method. |
||||
*/ |
||||
public function dropIndex($name, $table) |
||||
{ |
||||
echo " > drop index $name ..."; |
||||
$time = microtime(true); |
||||
$this->getDbConnection()->createCommand()->dropIndex($name, $table); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,97 @@
|
||||
<?php |
||||
/** |
||||
* CActiveRecordBehavior 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* CActiveRecordBehavior is the base class for behaviors that can be attached to {@link CActiveRecord}. |
||||
* Compared with {@link CModelBehavior}, CActiveRecordBehavior attaches to more events |
||||
* that are only defined by {@link CActiveRecord}. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @version $Id: CActiveRecordBehavior.php 2799 2011-01-01 19:31:13Z qiang.xue $ |
||||
* @package system.db.ar |
||||
* @since 1.0.2 |
||||
*/ |
||||
class CActiveRecordBehavior extends CModelBehavior |
||||
{ |
||||
/** |
||||
* Declares events and the corresponding event handler methods. |
||||
* If you override this method, make sure you merge the parent result to the return value. |
||||
* @return array events (array keys) and the corresponding event handler methods (array values). |
||||
* @see CBehavior::events |
||||
*/ |
||||
public function events() |
||||
{ |
||||
return array_merge(parent::events(), array( |
||||
'onBeforeSave' => 'beforeSave', |
||||
'onAfterSave' => 'afterSave', |
||||
'onBeforeDelete' => 'beforeDelete', |
||||
'onAfterDelete' => 'afterDelete', |
||||
'onBeforeFind' => 'beforeFind', |
||||
'onAfterFind' => 'afterFind', |
||||
)); |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onBeforeSave} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* You may set {@link CModelEvent::isValid} to be false to quit the saving process. |
||||
* @param CModelEvent $event event parameter |
||||
*/ |
||||
public function beforeSave($event) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onAfterSave} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* @param CModelEvent $event event parameter |
||||
*/ |
||||
public function afterSave($event) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onBeforeDelete} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* You may set {@link CModelEvent::isValid} to be false to quit the deletion process. |
||||
* @param CEvent $event event parameter |
||||
*/ |
||||
public function beforeDelete($event) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onAfterDelete} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* @param CEvent $event event parameter |
||||
*/ |
||||
public function afterDelete($event) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onBeforeFind} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* @param CEvent $event event parameter |
||||
* @since 1.0.9 |
||||
*/ |
||||
public function beforeFind($event) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Responds to {@link CActiveRecord::onAfterFind} event. |
||||
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. |
||||
* @param CEvent $event event parameter |
||||
*/ |
||||
public function afterFind($event) |
||||
{ |
||||
} |
||||
} |
@ -0,0 +1,792 @@
|
||||
<?php |
||||
/** |
||||
* Connection 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* Connection represents a connection to a database. |
||||
* |
||||
* Connection works together with {@link CDbCommand}, {@link CDbDataReader} |
||||
* and {@link CDbTransaction} to provide data access to various DBMS |
||||
* in a common set of APIs. They are a thin wrapper of the {@link http://www.php.net/manual/en/ref.pdo.php PDO} |
||||
* PHP extension. |
||||
* |
||||
* To establish a connection, set {@link setActive active} to true after |
||||
* specifying {@link connectionString}, {@link username} and {@link password}. |
||||
* |
||||
* The following example shows how to create a Connection instance and establish |
||||
* the actual connection: |
||||
* <pre> |
||||
* $connection=new Connection($dsn,$username,$password); |
||||
* $connection->active=true; |
||||
* </pre> |
||||
* |
||||
* After the DB connection is established, one can execute an SQL statement like the following: |
||||
* <pre> |
||||
* $command=$connection->createCommand($sqlStatement); |
||||
* $command->execute(); // a non-query SQL statement execution |
||||
* // or execute an SQL query and fetch the result set |
||||
* $reader=$command->query(); |
||||
* |
||||
* // each $row is an array representing a row of data |
||||
* foreach($reader as $row) ... |
||||
* </pre> |
||||
* |
||||
* One can do prepared SQL execution and bind parameters to the prepared SQL: |
||||
* <pre> |
||||
* $command=$connection->createCommand($sqlStatement); |
||||
* $command->bindParam($name1,$value1); |
||||
* $command->bindParam($name2,$value2); |
||||
* $command->execute(); |
||||
* </pre> |
||||
* |
||||
* To use transaction, do like the following: |
||||
* <pre> |
||||
* $transaction=$connection->beginTransaction(); |
||||
* try |
||||
* { |
||||
* $connection->createCommand($sql1)->execute(); |
||||
* $connection->createCommand($sql2)->execute(); |
||||
* //.... other SQL executions |
||||
* $transaction->commit(); |
||||
* } |
||||
* catch(Exception $e) |
||||
* { |
||||
* $transaction->rollBack(); |
||||
* } |
||||
* </pre> |
||||
* |
||||
* Connection also provides a set of methods to support setting and querying |
||||
* of certain DBMS attributes, such as {@link getNullConversion nullConversion}. |
||||
* |
||||
* Since Connection implements the interface IApplicationComponent, it can |
||||
* be used as an application component and be configured in application configuration, |
||||
* like the following, |
||||
* <pre> |
||||
* array( |
||||
* 'components'=>array( |
||||
* 'db'=>array( |
||||
* 'class'=>'Connection', |
||||
* 'connectionString'=>'sqlite:path/to/dbfile', |
||||
* ), |
||||
* ), |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class Connection extends \yii\base\ApplicationComponent |
||||
{ |
||||
/** |
||||
* @var string The Data Source Name, or DSN, contains the information required to connect to the database. |
||||
* @see http://www.php.net/manual/en/function.PDO-construct.php |
||||
* |
||||
* Note that if your database is using GBK or BIG5 charset, we highly recommend you |
||||
* to upgrade to PHP 5.3.6+ and specify charset via DSN like the following to prevent |
||||
* from hacking: `mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;`. |
||||
*/ |
||||
public $dsn; |
||||
/** |
||||
* @var string the username for establishing DB connection. Defaults to empty string. |
||||
*/ |
||||
public $username = ''; |
||||
/** |
||||
* @var string the password for establishing DB connection. Defaults to empty string. |
||||
*/ |
||||
public $password = ''; |
||||
/** |
||||
* @var integer number of seconds that table metadata can remain valid in cache. |
||||
* Use 0 or negative value to indicate not caching schema. |
||||
* If greater than 0 and the primary cache is enabled, the table metadata will be cached. |
||||
* @see schemaCachingExclude |
||||
*/ |
||||
public $schemaCachingDuration = 0; |
||||
/** |
||||
* @var array list of tables whose metadata should NOT be cached. Defaults to empty array. |
||||
* @see schemaCachingDuration |
||||
*/ |
||||
public $schemaCachingExclude = array(); |
||||
/** |
||||
* @var string the ID of the cache application component that is used to cache the table metadata. |
||||
* Defaults to 'cache' which refers to the primary cache application component. |
||||
* Set this property to false if you want to disable caching table metadata. |
||||
* @since 1.0.10 |
||||
*/ |
||||
public $schemaCacheID = 'cache'; |
||||
/** |
||||
* @var integer number of seconds that query results can remain valid in cache. |
||||
* Use 0 or negative value to indicate not caching query results (the default behavior). |
||||
* |
||||
* In order to enable query caching, this property must be a positive |
||||
* integer and {@link queryCacheID} must point to a valid cache component ID. |
||||
* |
||||
* The method {@link cache()} is provided as a convenient way of setting this property |
||||
* and {@link queryCachingDependency} on the fly. |
||||
* |
||||
* @see cache |
||||
* @see queryCachingDependency |
||||
* @see queryCacheID |
||||
* @since 1.1.7 |
||||
*/ |
||||
public $queryCachingDuration = 0; |
||||
/** |
||||
* @var CCacheDependency the dependency that will be used when saving query results into cache. |
||||
* @see queryCachingDuration |
||||
* @since 1.1.7 |
||||
*/ |
||||
public $queryCachingDependency; |
||||
/** |
||||
* @var integer the number of SQL statements that need to be cached next. |
||||
* If this is 0, then even if query caching is enabled, no query will be cached. |
||||
* Note that each time after executing a SQL statement (whether executed on DB server or fetched from |
||||
* query cache), this property will be reduced by 1 until 0. |
||||
* @since 1.1.7 |
||||
*/ |
||||
public $queryCachingCount = 0; |
||||
/** |
||||
* @var string the ID of the cache application component that is used for query caching. |
||||
* Defaults to 'cache' which refers to the primary cache application component. |
||||
* Set this property to false if you want to disable query caching. |
||||
* @since 1.1.7 |
||||
*/ |
||||
public $queryCacheID = 'cache'; |
||||
/** |
||||
* @var boolean whether the database connection should be automatically established |
||||
* the component is being initialized. Defaults to true. Note, this property is only |
||||
* effective when the Connection object is used as an application component. |
||||
*/ |
||||
public $autoConnect = true; |
||||
/** |
||||
* @var string the charset used for database connection. The property is only used |
||||
* for MySQL and PostgreSQL databases. Defaults to null, meaning using default charset |
||||
* as specified by the database. |
||||
* |
||||
* Note that if you're using GBK or BIG5 then it's highly recommended to |
||||
* update to PHP 5.3.6+ and to specify charset via DSN like |
||||
* 'mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;'. |
||||
*/ |
||||
public $charset; |
||||
/** |
||||
* @var boolean whether to turn on prepare emulation. Defaults to false, meaning PDO |
||||
* will use the native prepare support if available. For some databases (such as MySQL), |
||||
* this may need to be set true so that PDO can emulate the prepare support to bypass |
||||
* the buggy native prepare support. Note, this property is only effective for PHP 5.1.3 or above. |
||||
* The default value is null, which will not change the ATTR_EMULATE_PREPARES value of PDO. |
||||
*/ |
||||
public $emulatePrepare; |
||||
/** |
||||
* @var boolean whether to log the values that are bound to a prepare SQL statement. |
||||
* Defaults to false. During development, you may consider setting this property to true |
||||
* so that parameter values bound to SQL statements are logged for debugging purpose. |
||||
* You should be aware that logging parameter values could be expensive and have significant |
||||
* impact on the performance of your application. |
||||
* @since 1.0.5 |
||||
*/ |
||||
public $enableParamLogging = false; |
||||
/** |
||||
* @var boolean whether to enable profiling the SQL statements being executed. |
||||
* Defaults to false. This should be mainly enabled and used during development |
||||
* to find out the bottleneck of SQL executions. |
||||
* @since 1.0.6 |
||||
*/ |
||||
public $enableProfiling = false; |
||||
/** |
||||
* @var string the default prefix for table names. Defaults to null, meaning no table prefix. |
||||
* By setting this property, any token like '{{tableName}}' in {@link CDbCommand::text} will |
||||
* be replaced by 'prefixTableName', where 'prefix' refers to this property value. |
||||
* @since 1.1.0 |
||||
*/ |
||||
public $tablePrefix; |
||||
/** |
||||
* @var array list of SQL statements that should be executed right after the DB connection is established. |
||||
* @since 1.1.1 |
||||
*/ |
||||
public $initSQLs; |
||||
/** |
||||
* @var array mapping between PDO driver and schema class name. |
||||
* A schema class can be specified using path alias. |
||||
* @since 1.1.6 |
||||
*/ |
||||
public $driverMap = array( |
||||
'pgsql' => 'CPgsqlSchema', // PostgreSQL |
||||
'mysqli' => 'CMysqlSchema', // MySQL |
||||
'mysql' => 'CMysqlSchema', // MySQL |
||||
'sqlite' => 'CSqliteSchema', // sqlite 3 |
||||
'sqlite2' => 'CSqliteSchema', // sqlite 2 |
||||
'mssql' => 'CMssqlSchema', // Mssql driver on windows hosts |
||||
'dblib' => 'CMssqlSchema', // dblib drivers on linux (and maybe others os) hosts |
||||
'sqlsrv' => 'CMssqlSchema', // Mssql |
||||
'oci' => 'COciSchema', // Oracle driver |
||||
); |
||||
|
||||
/** |
||||
* @var string Custom PDO wrapper class. |
||||
* @since 1.1.8 |
||||
*/ |
||||
public $pdoClass = 'PDO'; |
||||
|
||||
private $_attributes = array(); |
||||
private $_active = false; |
||||
private $_pdo; |
||||
private $_transaction; |
||||
private $_schema; |
||||
|
||||
|
||||
/** |
||||
* Constructor. |
||||
* Note, the DB connection is not established when this connection |
||||
* instance is created. Set {@link setActive active} property to true |
||||
* to establish the connection. |
||||
* @param string $dsn The Data Source Name, or DSN, contains the information required to connect to the database. |
||||
* @param string $username The user name for the DSN string. |
||||
* @param string $password The password for the DSN string. |
||||
* @see http://www.php.net/manual/en/function.PDO-construct.php |
||||
*/ |
||||
public function __construct($dsn = '', $username = '', $password = '') |
||||
{ |
||||
$this->connectionString = $dsn; |
||||
$this->username = $username; |
||||
$this->password = $password; |
||||
} |
||||
|
||||
/** |
||||
* Close the connection when serializing. |
||||
* @return array |
||||
*/ |
||||
public function __sleep() |
||||
{ |
||||
$this->close(); |
||||
return array_keys(get_object_vars($this)); |
||||
} |
||||
|
||||
/** |
||||
* Returns a list of available PDO drivers. |
||||
* @return array list of available PDO drivers |
||||
* @see http://www.php.net/manual/en/function.PDO-getAvailableDrivers.php |
||||
*/ |
||||
public static function getAvailableDrivers() |
||||
{ |
||||
return PDO::getAvailableDrivers(); |
||||
} |
||||
|
||||
/** |
||||
* Initializes the component. |
||||
* This method is required by {@link IApplicationComponent} and is invoked by application |
||||
* when the Connection is used as an application component. |
||||
* If you override this method, make sure to call the parent implementation |
||||
* so that the component can be marked as initialized. |
||||
*/ |
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
if ($this->autoConnect) |
||||
$this->setActive(true); |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the DB connection is established. |
||||
* @return boolean whether the DB connection is established |
||||
*/ |
||||
public function getActive() |
||||
{ |
||||
return $this->_active; |
||||
} |
||||
|
||||
/** |
||||
* Open or close the DB connection. |
||||
* @param boolean $value whether to open or close DB connection |
||||
* @throws CException if connection fails |
||||
*/ |
||||
public function setActive($value) |
||||
{ |
||||
if ($value != $this->_active) |
||||
{ |
||||
if ($value) |
||||
$this->open(); |
||||
else |
||||
$this->close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the parameters about query caching. |
||||
* This method can be used to enable or disable query caching. |
||||
* By setting the $duration parameter to be 0, the query caching will be disabled. |
||||
* Otherwise, query results of the new SQL statements executed next will be saved in cache |
||||
* and remain valid for the specified duration. |
||||
* If the same query is executed again, the result may be fetched from cache directly |
||||
* without actually executing the SQL statement. |
||||
* @param integer $duration the number of seconds that query results may remain valid in cache. |
||||
* If this is 0, the caching will be disabled. |
||||
* @param CCacheDependency $dependency the dependency that will be used when saving the query results into cache. |
||||
* @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1, |
||||
* meaning that the next SQL query will be cached. |
||||
* @return Connection the connection instance itself. |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function cache($duration, $dependency = null, $queryCount = 1) |
||||
{ |
||||
$this->queryCachingDuration = $duration; |
||||
$this->queryCachingDependency = $dependency; |
||||
$this->queryCachingCount = $queryCount; |
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Opens DB connection if it is currently not |
||||
* @throws CException if connection fails |
||||
*/ |
||||
protected function open() |
||||
{ |
||||
if ($this->_pdo === null) |
||||
{ |
||||
if (empty($this->connectionString)) |
||||
throw new CDbException(Yii::t('yii', 'Connection.connectionString cannot be empty.')); |
||||
try |
||||
{ |
||||
Yii::trace('Opening DB connection', 'system.db.Connection'); |
||||
$this->_pdo = $this->createPdoInstance(); |
||||
$this->initConnection($this->_pdo); |
||||
$this->_active = true; |
||||
} |
||||
catch(PDOException $e) |
||||
{ |
||||
if (YII_DEBUG) |
||||
{ |
||||
throw new CDbException(Yii::t('yii', 'Connection failed to open the DB connection: {error}', |
||||
array('{error}' => $e->getMessage())), (int)$e->getCode(), $e->errorInfo); |
||||
} |
||||
else |
||||
{ |
||||
Yii::log($e->getMessage(), CLogger::LEVEL_ERROR, 'exception.CDbException'); |
||||
throw new CDbException(Yii::t('yii', 'Connection failed to open the DB connection.'), (int)$e->getCode(), $e->errorInfo); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Closes the currently active DB connection. |
||||
* It does nothing if the connection is already closed. |
||||
*/ |
||||
protected function close() |
||||
{ |
||||
Yii::trace('Closing DB connection', 'system.db.Connection'); |
||||
$this->_pdo = null; |
||||
$this->_active = false; |
||||
$this->_schema = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates the PDO instance. |
||||
* When some functionalities are missing in the pdo driver, we may use |
||||
* an adapter class to provides them. |
||||
* @return PDO the pdo instance |
||||
* @since 1.0.4 |
||||
*/ |
||||
protected function createPdoInstance() |
||||
{ |
||||
$pdoClass = $this->pdoClass; |
||||
if (($pos = strpos($this->connectionString, ':')) !== false) |
||||
{ |
||||
$driver = strtolower(substr($this->connectionString, 0, $pos)); |
||||
if ($driver === 'mssql' || $driver === 'dblib' || $driver === 'sqlsrv') |
||||
$pdoClass = 'CMssqlPdoAdapter'; |
||||
} |
||||
return new $pdoClass($this->connectionString, $this->username, |
||||
$this->password, $this->_attributes); |
||||
} |
||||
|
||||
/** |
||||
* Initializes the open db connection. |
||||
* This method is invoked right after the db connection is established. |
||||
* The default implementation is to set the charset for MySQL and PostgreSQL database connections. |
||||
* @param PDO $pdo the PDO instance |
||||
*/ |
||||
protected function initConnection($pdo) |
||||
{ |
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
||||
if ($this->emulatePrepare !== null && constant('PDO::ATTR_EMULATE_PREPARES')) |
||||
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, $this->emulatePrepare); |
||||
if ($this->charset !== null) |
||||
{ |
||||
$driver = strtolower($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)); |
||||
if (in_array($driver, array('pgsql', 'mysql', 'mysqli'))) |
||||
$pdo->exec('SET NAMES ' . $pdo->quote($this->charset)); |
||||
} |
||||
if ($this->initSQLs !== null) |
||||
{ |
||||
foreach ($this->initSQLs as $sql) |
||||
$pdo->exec($sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the PDO instance. |
||||
* @return PDO the PDO instance, null if the connection is not established yet |
||||
*/ |
||||
public function getPdoInstance() |
||||
{ |
||||
return $this->_pdo; |
||||
} |
||||
|
||||
/** |
||||
* Creates a command for execution. |
||||
* @param mixed $query the DB query to be executed. This can be either a string representing a SQL statement, |
||||
* or an array representing different fragments of a SQL statement. Please refer to {@link CDbCommand::__construct} |
||||
* for more details about how to pass an array as the query. If this parameter is not given, |
||||
* you will have to call query builder methods of {@link CDbCommand} to build the DB query. |
||||
* @return CDbCommand the DB command |
||||
*/ |
||||
public function createCommand($query = null) |
||||
{ |
||||
$this->setActive(true); |
||||
return new CDbCommand($this, $query); |
||||
} |
||||
|
||||
/** |
||||
* Returns the currently active transaction. |
||||
* @return CDbTransaction the currently active transaction. Null if no active transaction. |
||||
*/ |
||||
public function getCurrentTransaction() |
||||
{ |
||||
if ($this->_transaction !== null) |
||||
{ |
||||
if ($this->_transaction->getActive()) |
||||
return $this->_transaction; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Starts a transaction. |
||||
* @return CDbTransaction the transaction initiated |
||||
*/ |
||||
public function beginTransaction() |
||||
{ |
||||
Yii::trace('Starting transaction', 'system.db.Connection'); |
||||
$this->setActive(true); |
||||
$this->_pdo->beginTransaction(); |
||||
return $this->_transaction = new CDbTransaction($this); |
||||
} |
||||
|
||||
/** |
||||
* Returns the database schema for the current connection |
||||
* @return CDbSchema the database schema for the current connection |
||||
*/ |
||||
public function getSchema() |
||||
{ |
||||
if ($this->_schema !== null) |
||||
return $this->_schema; |
||||
else |
||||
{ |
||||
$driver = $this->getDriverName(); |
||||
if (isset($this->driverMap[$driver])) |
||||
return $this->_schema = Yii::createComponent($this->driverMap[$driver], $this); |
||||
else |
||||
throw new CDbException(Yii::t('yii', 'Connection does not support reading schema for {driver} database.', |
||||
array('{driver}' => $driver))); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the SQL command builder for the current DB connection. |
||||
* @return CDbCommandBuilder the command builder |
||||
* @since 1.0.4 |
||||
*/ |
||||
public function getCommandBuilder() |
||||
{ |
||||
return $this->getSchema()->getCommandBuilder(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the ID of the last inserted row or sequence value. |
||||
* @param string $sequenceName name of the sequence object (required by some DBMS) |
||||
* @return string the row ID of the last row inserted, or the last value retrieved from the sequence object |
||||
* @see http://www.php.net/manual/en/function.PDO-lastInsertId.php |
||||
*/ |
||||
public function getLastInsertID($sequenceName = '') |
||||
{ |
||||
$this->setActive(true); |
||||
return $this->_pdo->lastInsertId($sequenceName); |
||||
} |
||||
|
||||
/** |
||||
* Quotes a string value for use in a query. |
||||
* @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_int($str) || is_float($str)) |
||||
return $str; |
||||
|
||||
$this->setActive(true); |
||||
if (($value = $this->_pdo->quote($str)) !== false) |
||||
return $value; |
||||
else // the driver doesn't support quote (e.g. oci) |
||||
return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'"; |
||||
} |
||||
|
||||
/** |
||||
* 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 |
||||
*/ |
||||
public function quoteTableName($name) |
||||
{ |
||||
return $this->getSchema()->quoteTableName($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 |
||||
*/ |
||||
public function quoteColumnName($name) |
||||
{ |
||||
return $this->getSchema()->quoteColumnName($name); |
||||
} |
||||
|
||||
/** |
||||
* Determines the PDO type for the specified PHP type. |
||||
* @param string $type The PHP type (obtained by gettype() call). |
||||
* @return integer the corresponding PDO type |
||||
*/ |
||||
public function getPdoType($type) |
||||
{ |
||||
static $map = array |
||||
( |
||||
'boolean' => PDO::PARAM_BOOL, |
||||
'integer' => PDO::PARAM_INT, |
||||
'string' => PDO::PARAM_STR, |
||||
'NULL' => PDO::PARAM_NULL, |
||||
); |
||||
return isset($map[$type]) ? $map[$type] : PDO::PARAM_STR; |
||||
} |
||||
|
||||
/** |
||||
* Returns the case of the column names |
||||
* @return mixed the case of the column names |
||||
* @see http://www.php.net/manual/en/pdo.setattribute.php |
||||
*/ |
||||
public function getColumnCase() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_CASE); |
||||
} |
||||
|
||||
/** |
||||
* Sets the case of the column names. |
||||
* @param mixed $value the case of the column names |
||||
* @see http://www.php.net/manual/en/pdo.setattribute.php |
||||
*/ |
||||
public function setColumnCase($value) |
||||
{ |
||||
$this->setAttribute(PDO::ATTR_CASE, $value); |
||||
} |
||||
|
||||
/** |
||||
* Returns how the null and empty strings are converted. |
||||
* @return mixed how the null and empty strings are converted |
||||
* @see http://www.php.net/manual/en/pdo.setattribute.php |
||||
*/ |
||||
public function getNullConversion() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_ORACLE_NULLS); |
||||
} |
||||
|
||||
/** |
||||
* Sets how the null and empty strings are converted. |
||||
* @param mixed $value how the null and empty strings are converted |
||||
* @see http://www.php.net/manual/en/pdo.setattribute.php |
||||
*/ |
||||
public function setNullConversion($value) |
||||
{ |
||||
$this->setAttribute(PDO::ATTR_ORACLE_NULLS, $value); |
||||
} |
||||
|
||||
/** |
||||
* Returns whether creating or updating a DB record will be automatically committed. |
||||
* Some DBMS (such as sqlite) may not support this feature. |
||||
* @return boolean whether creating or updating a DB record will be automatically committed. |
||||
*/ |
||||
public function getAutoCommit() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_AUTOCOMMIT); |
||||
} |
||||
|
||||
/** |
||||
* Sets whether creating or updating a DB record will be automatically committed. |
||||
* Some DBMS (such as sqlite) may not support this feature. |
||||
* @param boolean $value whether creating or updating a DB record will be automatically committed. |
||||
*/ |
||||
public function setAutoCommit($value) |
||||
{ |
||||
$this->setAttribute(PDO::ATTR_AUTOCOMMIT, $value); |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the connection is persistent or not. |
||||
* Some DBMS (such as sqlite) may not support this feature. |
||||
* @return boolean whether the connection is persistent or not |
||||
*/ |
||||
public function getPersistent() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_PERSISTENT); |
||||
} |
||||
|
||||
/** |
||||
* Sets whether the connection is persistent or not. |
||||
* Some DBMS (such as sqlite) may not support this feature. |
||||
* @param boolean $value whether the connection is persistent or not |
||||
*/ |
||||
public function setPersistent($value) |
||||
{ |
||||
return $this->setAttribute(PDO::ATTR_PERSISTENT, $value); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the DB driver |
||||
* @return string name of the DB driver |
||||
*/ |
||||
public function getDriverName() |
||||
{ |
||||
if (($pos = strpos($this->connectionString, ':')) !== false) |
||||
return strtolower(substr($this->connectionString, 0, $pos)); |
||||
// return $this->getAttribute(PDO::ATTR_DRIVER_NAME); |
||||
} |
||||
|
||||
/** |
||||
* Returns the version information of the DB driver. |
||||
* @return string the version information of the DB driver |
||||
*/ |
||||
public function getClientVersion() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_CLIENT_VERSION); |
||||
} |
||||
|
||||
/** |
||||
* Returns the status of the connection. |
||||
* Some DBMS (such as sqlite) may not support this feature. |
||||
* @return string the status of the connection |
||||
*/ |
||||
public function getConnectionStatus() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_CONNECTION_STATUS); |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the connection performs data prefetching. |
||||
* @return boolean whether the connection performs data prefetching |
||||
*/ |
||||
public function getPrefetch() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_PREFETCH); |
||||
} |
||||
|
||||
/** |
||||
* Returns the information of DBMS server. |
||||
* @return string the information of DBMS server |
||||
*/ |
||||
public function getServerInfo() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_SERVER_INFO); |
||||
} |
||||
|
||||
/** |
||||
* Returns the version information of DBMS server. |
||||
* @return string the version information of DBMS server |
||||
*/ |
||||
public function getServerVersion() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_SERVER_VERSION); |
||||
} |
||||
|
||||
/** |
||||
* Returns the timeout settings for the connection. |
||||
* @return integer timeout settings for the connection |
||||
*/ |
||||
public function getTimeout() |
||||
{ |
||||
return $this->getAttribute(PDO::ATTR_TIMEOUT); |
||||
} |
||||
|
||||
/** |
||||
* Obtains a specific DB connection attribute information. |
||||
* @param integer $name the attribute to be queried |
||||
* @return mixed the corresponding attribute information |
||||
* @see http://www.php.net/manual/en/function.PDO-getAttribute.php |
||||
*/ |
||||
public function getAttribute($name) |
||||
{ |
||||
$this->setActive(true); |
||||
return $this->_pdo->getAttribute($name); |
||||
} |
||||
|
||||
/** |
||||
* Sets an attribute on the database connection. |
||||
* @param integer $name the attribute to be set |
||||
* @param mixed $value the attribute value |
||||
* @see http://www.php.net/manual/en/function.PDO-setAttribute.php |
||||
*/ |
||||
public function setAttribute($name, $value) |
||||
{ |
||||
if ($this->_pdo instanceof PDO) |
||||
$this->_pdo->setAttribute($name, $value); |
||||
else |
||||
$this->_attributes[$name] = $value; |
||||
} |
||||
|
||||
/** |
||||
* Returns the attributes that are previously explicitly set for the DB connection. |
||||
* @return array attributes (name=>value) that are previously explicitly set for the DB connection. |
||||
* @see setAttributes |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function getAttributes() |
||||
{ |
||||
return $this->_attributes; |
||||
} |
||||
|
||||
/** |
||||
* Sets a set of attributes on the database connection. |
||||
* @param array $values attributes (name=>value) to be set. |
||||
* @see setAttribute |
||||
* @since 1.1.7 |
||||
*/ |
||||
public function setAttributes($values) |
||||
{ |
||||
foreach ($values as $name => $value) |
||||
$this->_attributes[$name] = $value; |
||||
} |
||||
|
||||
/** |
||||
* Returns the statistical results of SQL executions. |
||||
* The results returned include the number of SQL statements executed and |
||||
* the total time spent. |
||||
* In order to use this method, {@link enableProfiling} has to be set true. |
||||
* @return array the first element indicates the number of SQL statements executed, |
||||
* and the second element the total time spent in SQL execution. |
||||
* @since 1.0.6 |
||||
*/ |
||||
public function getStats() |
||||
{ |
||||
$logger = Yii::getLogger(); |
||||
$timings = $logger->getProfilingResults(null, 'system.db.CDbCommand.query'); |
||||
$count = count($timings); |
||||
$time = array_sum($timings); |
||||
$timings = $logger->getProfilingResults(null, 'system.db.CDbCommand.execute'); |
||||
$count += count($timings); |
||||
$time += array_sum($timings); |
||||
return array($count, $time); |
||||
} |
||||
} |
@ -0,0 +1,241 @@
|
||||
<?php |
||||
/** |
||||
* CDbDataReader 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* CDbDataReader represents a forward-only stream of rows from a query result set. |
||||
* |
||||
* To read the current row of data, call {@link read}. The method {@link readAll} |
||||
* returns all the rows in a single array. |
||||
* |
||||
* One can also retrieve the rows of data in CDbDataReader by using foreach: |
||||
* <pre> |
||||
* foreach($reader as $row) |
||||
* // $row represents a row of data |
||||
* </pre> |
||||
* Since CDbDataReader is a forward-only stream, you can only traverse it once. |
||||
* |
||||
* It is possible to use a specific mode of data fetching by setting |
||||
* {@link setFetchMode FetchMode}. See {@link http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php} |
||||
* for more details. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @version $Id: CDbDataReader.php 3204 2011-05-05 21:36:32Z alexander.makarow $ |
||||
* @package system.db |
||||
* @since 1.0 |
||||
*/ |
||||
class CDbDataReader extends CComponent implements Iterator, Countable |
||||
{ |
||||
private $_statement; |
||||
private $_closed = false; |
||||
private $_row; |
||||
private $_index = -1; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* @param CDbCommand $command the command generating the query result |
||||
*/ |
||||
public function __construct(CDbCommand $command) |
||||
{ |
||||
$this->_statement = $command->getPdoStatement(); |
||||
$this->_statement->setFetchMode(PDO::FETCH_ASSOC); |
||||
} |
||||
|
||||
/** |
||||
* Binds a column to a PHP variable. |
||||
* When rows of data are being fetched, the corresponding column value |
||||
* will be set in the variable. Note, the fetch mode must include PDO::FETCH_BOUND. |
||||
* @param mixed $column Number of the column (1-indexed) or name of the column |
||||
* in the result set. If using the column name, be aware that the name |
||||
* should match the case of the column, as returned by the driver. |
||||
* @param mixed $value Name of the PHP variable to which the column will be bound. |
||||
* @param integer $dataType Data type of the parameter |
||||
* @see http://www.php.net/manual/en/function.PDOStatement-bindColumn.php |
||||
*/ |
||||
public function bindColumn($column, &$value, $dataType = null) |
||||
{ |
||||
if ($dataType === null) |
||||
$this->_statement->bindColumn($column, $value); |
||||
else |
||||
$this->_statement->bindColumn($column, $value, $dataType); |
||||
} |
||||
|
||||
/** |
||||
* Set the default fetch mode for this statement |
||||
* @param mixed $mode fetch mode |
||||
* @see http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php |
||||
*/ |
||||
public function setFetchMode($mode) |
||||
{ |
||||
$params = func_get_args(); |
||||
call_user_func_array(array($this->_statement, 'setFetchMode'), $params); |
||||
} |
||||
|
||||
/** |
||||
* Advances the reader to the next row in a result set. |
||||
* @return array|false the current row, false if no more row available |
||||
*/ |
||||
public function read() |
||||
{ |
||||
return $this->_statement->fetch(); |
||||
} |
||||
|
||||
/** |
||||
* Returns a single column from the next row of a result set. |
||||
* @param integer $columnIndex zero-based column index |
||||
* @return mixed|false the column of the current row, false if no more row available |
||||
*/ |
||||
public function readColumn($columnIndex) |
||||
{ |
||||
return $this->_statement->fetchColumn($columnIndex); |
||||
} |
||||
|
||||
/** |
||||
* Returns an object populated with the next row of data. |
||||
* @param string $className class name of the object to be created and populated |
||||
* @param array $fields Elements of this array are passed to the constructor |
||||
* @return mixed|false the populated object, false if no more row of data available |
||||
*/ |
||||
public function readObject($className, $fields) |
||||
{ |
||||
return $this->_statement->fetchObject($className, $fields); |
||||
} |
||||
|
||||
/** |
||||
* Reads the whole result set into an array. |
||||
* @return array the result set (each array element represents a row of data). |
||||
* An empty array will be returned if the result contains no row. |
||||
*/ |
||||
public function readAll() |
||||
{ |
||||
return $this->_statement->fetchAll(); |
||||
} |
||||
|
||||
/** |
||||
* Advances the reader to the next result when reading the results of a batch of statements. |
||||
* This method is only useful when there are multiple result sets |
||||
* returned by the query. Not all DBMS support this feature. |
||||
* @return boolean Returns true on success or false on failure. |
||||
*/ |
||||
public function nextResult() |
||||
{ |
||||
if (($result = $this->_statement->nextRowset()) !== false) |
||||
$this->_index = -1; |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Closes the reader. |
||||
* This frees up the resources allocated for executing this SQL statement. |
||||
* Read attemps after this method call are unpredictable. |
||||
*/ |
||||
public function close() |
||||
{ |
||||
$this->_statement->closeCursor(); |
||||
$this->_closed = true; |
||||
} |
||||
|
||||
/** |
||||
* whether the reader is closed or not. |
||||
* @return boolean whether the reader is closed or not. |
||||
*/ |
||||
public function getIsClosed() |
||||
{ |
||||
return $this->_closed; |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of rows in the result set. |
||||
* Note, most DBMS may not give a meaningful count. |
||||
* In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows. |
||||
* @return integer number of rows contained in the result. |
||||
*/ |
||||
public function getRowCount() |
||||
{ |
||||
return $this->_statement->rowCount(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of rows in the result set. |
||||
* This method is required by the Countable interface. |
||||
* Note, most DBMS may not give a meaningful count. |
||||
* In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows. |
||||
* @return integer number of rows contained in the result. |
||||
*/ |
||||
public function count() |
||||
{ |
||||
return $this->getRowCount(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of columns in the result set. |
||||
* Note, even there's no row in the reader, this still gives correct column number. |
||||
* @return integer the number of columns in the result set. |
||||
*/ |
||||
public function getColumnCount() |
||||
{ |
||||
return $this->_statement->columnCount(); |
||||
} |
||||
|
||||
/** |
||||
* Resets the iterator to the initial state. |
||||
* This method is required by the interface Iterator. |
||||
* @throws CException if this method is invoked twice |
||||
*/ |
||||
public function rewind() |
||||
{ |
||||
if ($this->_index < 0) |
||||
{ |
||||
$this->_row = $this->_statement->fetch(); |
||||
$this->_index = 0; |
||||
} |
||||
else |
||||
throw new CDbException(Yii::t('yii', 'CDbDataReader cannot rewind. It is a forward-only reader.')); |
||||
} |
||||
|
||||
/** |
||||
* Returns the index of the current row. |
||||
* This method is required by the interface Iterator. |
||||
* @return integer the index of the current row. |
||||
*/ |
||||
public function key() |
||||
{ |
||||
return $this->_index; |
||||
} |
||||
|
||||
/** |
||||
* Returns the current row. |
||||
* This method is required by the interface Iterator. |
||||
* @return mixed the current row. |
||||
*/ |
||||
public function current() |
||||
{ |
||||
return $this->_row; |
||||
} |
||||
|
||||
/** |
||||
* Moves the internal pointer to the next row. |
||||
* This method is required by the interface Iterator. |
||||
*/ |
||||
public function next() |
||||
{ |
||||
$this->_row = $this->_statement->fetch(); |
||||
$this->_index++; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether there is a row of data at current position. |
||||
* This method is required by the interface Iterator. |
||||
* @return boolean whether there is a row of data at current position. |
||||
*/ |
||||
public function valid() |
||||
{ |
||||
return $this->_row !== false; |
||||
} |
||||
} |
@ -0,0 +1,108 @@
|
||||
<?php |
||||
/** |
||||
* CDbTransaction 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/ |
||||
*/ |
||||
|
||||
/** |
||||
* CDbTransaction represents a DB transaction. |
||||
* |
||||
* It is usually created by calling {@link CDbConnection::beginTransaction}. |
||||
* |
||||
* The following code is a common scenario of using transactions: |
||||
* <pre> |
||||
* $transaction=$connection->beginTransaction(); |
||||
* try |
||||
* { |
||||
* $connection->createCommand($sql1)->execute(); |
||||
* $connection->createCommand($sql2)->execute(); |
||||
* //.... other SQL executions |
||||
* $transaction->commit(); |
||||
* } |
||||
* catch(Exception $e) |
||||
* { |
||||
* $transaction->rollBack(); |
||||
* } |
||||
* </pre> |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @version $Id: CDbTransaction.php 3069 2011-03-14 00:28:38Z qiang.xue $ |
||||
* @package system.db |
||||
* @since 1.0 |
||||
*/ |
||||
class CDbTransaction extends CComponent |
||||
{ |
||||
private $_connection = null; |
||||
private $_active; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* @param CDbConnection $connection the connection associated with this transaction |
||||
* @see CDbConnection::beginTransaction |
||||
*/ |
||||
public function __construct(CDbConnection $connection) |
||||
{ |
||||
$this->_connection = $connection; |
||||
$this->_active = true; |
||||
} |
||||
|
||||
/** |
||||
* Commits a transaction. |
||||
* @throws CException if the transaction or the DB connection is not active. |
||||
*/ |
||||
public function commit() |
||||
{ |
||||
if ($this->_active && $this->_connection->getActive()) |
||||
{ |
||||
Yii::trace('Committing transaction', 'system.db.CDbTransaction'); |
||||
$this->_connection->getPdoInstance()->commit(); |
||||
$this->_active = false; |
||||
} |
||||
else |
||||
throw new CDbException(Yii::t('yii', 'CDbTransaction is inactive and cannot perform commit or roll back operations.')); |
||||
} |
||||
|
||||
/** |
||||
* Rolls back a transaction. |
||||
* @throws CException if the transaction or the DB connection is not active. |
||||
*/ |
||||
public function rollback() |
||||
{ |
||||
if ($this->_active && $this->_connection->getActive()) |
||||
{ |
||||
Yii::trace('Rolling back transaction', 'system.db.CDbTransaction'); |
||||
$this->_connection->getPdoInstance()->rollBack(); |
||||
$this->_active = false; |
||||
} |
||||
else |
||||
throw new CDbException(Yii::t('yii', 'CDbTransaction is inactive and cannot perform commit or roll back operations.')); |
||||
} |
||||
|
||||
/** |
||||
* @return CDbConnection the DB connection for this transaction |
||||
*/ |
||||
public function getConnection() |
||||
{ |
||||
return $this->_connection; |
||||
} |
||||
|
||||
/** |
||||
* @return boolean whether this transaction is active |
||||
*/ |
||||
public function getActive() |
||||
{ |
||||
return $this->_active; |
||||
} |
||||
|
||||
/** |
||||
* @param boolean $value whether this transaction is active |
||||
*/ |
||||
protected function setActive($value) |
||||
{ |
||||
$this->_active = $value; |
||||
} |
||||
} |
Loading…
Reference in new issue