Connection.php 18.8 KB
Newer Older
w  
Qiang Xue committed
1 2 3 4 5
<?php
/**
 * Connection class file
 *
 * @link http://www.yiiframework.com/
Qiang Xue committed
6
 * @copyright Copyright &copy; 2008 Yii Software LLC
w  
Qiang Xue committed
7 8 9
 * @license http://www.yiiframework.com/license/
 */

Qiang Xue committed
10
namespace yii\db;
w  
Qiang Xue committed
11

12
use yii\base\Component;
Qiang Xue committed
13 14
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
w  
Qiang Xue committed
15

w  
Qiang Xue committed
16
/**
w  
Qiang Xue committed
17
 * Connection represents a connection to a database via [PDO](http://www.php.net/manual/en/ref.pdo.php).
w  
Qiang Xue committed
18
 *
w  
Qiang Xue committed
19 20 21
 * Connection works together with [[Command]], [[DataReader]] and [[Transaction]]
 * to provide data access to various DBMS in a common set of APIs. They are a thin wrapper
 * of the [[PDO PHP extension]](http://www.php.net/manual/en/ref.pdo.php).
w  
Qiang Xue committed
22
 *
w  
Qiang Xue committed
23
 * To establish a DB connection, set [[dsn]], [[username]] and [[password]], and then
24
 * call [[open()]] to be true.
w  
Qiang Xue committed
25 26
 *
 * The following example shows how to create a Connection instance and establish
w  
Qiang Xue committed
27
 * the DB connection:
w  
Qiang Xue committed
28
 *
w  
Qiang Xue committed
29
 * ~~~
Qiang Xue committed
30
 * $connection = new \yii\db\Connection(array(
Qiang Xue committed
31 32 33
 *     'dsn' => $dsn,
 *     'username' => $username,
 *     'password' => $password,
Qiang Xue committed
34
 * ));
35
 * $connection->open();
w  
Qiang Xue committed
36 37
 * ~~~
 *
Qiang Xue committed
38
 * After the DB connection is established, one can execute SQL statements like the following:
w  
Qiang Xue committed
39 40 41
 *
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post');
Qiang Xue committed
42 43 44
 * $posts = $command->queryAll();
 * $command = $connection->createCommand('UPDATE tbl_post SET status=1');
 * $command->execute();
w  
Qiang Xue committed
45 46
 * ~~~
 *
Qiang Xue committed
47 48 49
 * One can also do prepared SQL execution and bind parameters to the prepared SQL.
 * When the parameters are coming from user input, you should use this approach
 * to prevent SQL injection attacks. The following is an example:
w  
Qiang Xue committed
50
 *
w  
Qiang Xue committed
51 52 53 54 55
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post WHERE id=:id');
 * $command->bindValue(':id', $_GET['id']);
 * $post = $command->query();
 * ~~~
w  
Qiang Xue committed
56
 *
Qiang Xue committed
57 58 59 60
 * For more information about how to perform various DB queries, please refer to [[Command]].
 *
 * If the underlying DBMS supports transactions, you can perform transactional SQL queries
 * like the following:
w  
Qiang Xue committed
61
 *
w  
Qiang Xue committed
62 63 64
 * ~~~
 * $transaction = $connection->beginTransaction();
 * try {
65 66 67 68
 *     $connection->createCommand($sql1)->execute();
 *     $connection->createCommand($sql2)->execute();
 *     // ... executing other SQL statements ...
 *     $transaction->commit();
Qiang Xue committed
69
 * } catch(Exception $e) {
70
 *     $transaction->rollBack();
w  
Qiang Xue committed
71
 * }
w  
Qiang Xue committed
72
 * ~~~
w  
Qiang Xue committed
73
 *
74
 * Connection is often used as an application component and configured in the application
Qiang Xue committed
75
 * configuration like the following:
w  
Qiang Xue committed
76 77
 *
 * ~~~
w  
Qiang Xue committed
78
 * array(
Qiang Xue committed
79 80
 *	 'components' => array(
 *		 'db' => array(
Qiang Xue committed
81
 *			 'class' => '\yii\db\Connection',
Qiang Xue committed
82 83 84 85 86 87
 *			 'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
 *			 'username' => 'root',
 *			 'password' => '',
 *			 'charset' => 'utf8',
 *		 ),
 *	 ),
w  
Qiang Xue committed
88
 * )
w  
Qiang Xue committed
89
 * ~~~
w  
Qiang Xue committed
90
 *
91
 * @property boolean $isActive Whether the DB connection is established. This property is read-only.
Qiang Xue committed
92 93
 * @property Transaction $transaction The currently active transaction. Null if no active transaction.
 * @property Schema $schema The database schema information for the current connection.
Qiang Xue committed
94 95 96
 * @property QueryBuilder $queryBuilder The query builder.
 * @property string $lastInsertID The row ID of the last row inserted, or the last value retrieved from the sequence object.
 * @property string $driverName Name of the DB driver currently being used.
Qiang Xue committed
97
 * @property array $querySummary The statistical results of SQL queries.
Qiang Xue committed
98
 *
w  
Qiang Xue committed
99 100 101
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
102
class Connection extends Component
w  
Qiang Xue committed
103
{
104 105 106 107 108
	/**
	 * @event Event an event that is triggered after a DB connection is established
	 */
	const EVENT_AFTER_OPEN = 'afterOpen';

w  
Qiang Xue committed
109
	/**
w  
Qiang Xue committed
110 111 112
	 * @var string the Data Source Name, or DSN, contains the information required to connect to the database.
	 * Please refer to the [PHP manual](http://www.php.net/manual/en/function.PDO-construct.php) on
	 * the format of the DSN string.
Qiang Xue committed
113
	 * @see charset
w  
Qiang Xue committed
114 115 116 117 118 119 120 121 122 123
	 */
	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 = '';
w  
Qiang Xue committed
124
	/**
Qiang Xue committed
125
	 * @var array PDO attributes (name=>value) that should be set when calling [[open()]]
w  
Qiang Xue committed
126 127 128 129 130 131 132
	 * to establish a DB connection. Please refer to the
	 * [PHP manual](http://www.php.net/manual/en/function.PDO-setAttribute.php) for
	 * details about available attributes.
	 */
	public $attributes;
	/**
	 * @var \PDO the PHP PDO instance associated with this DB connection.
133
	 * This property is mainly managed by [[open()]] and [[close()]] methods.
w  
Qiang Xue committed
134 135 136 137
	 * When a DB connection is active, this property will represent a PDO instance;
	 * otherwise, it will be null.
	 */
	public $pdo;
138 139 140
	/**
	 * @var boolean whether to enable schema caching.
	 * Note that in order to enable truly schema caching, a valid cache component as specified
141
	 * by [[schemaCacheID]] must be enabled and [[enableSchemaCache]] must be set true.
142 143 144 145 146
	 * @see schemaCacheDuration
	 * @see schemaCacheExclude
	 * @see schemaCacheID
	 */
	public $enableSchemaCache = false;
w  
Qiang Xue committed
147 148
	/**
	 * @var integer number of seconds that table metadata can remain valid in cache.
w  
Qiang Xue committed
149
	 * Use 0 to indicate that the cached data will never expire.
150
	 * @see enableSchemaCache
w  
Qiang Xue committed
151
	 */
152
	public $schemaCacheDuration = 3600;
w  
Qiang Xue committed
153 154
	/**
	 * @var array list of tables whose metadata should NOT be cached. Defaults to empty array.
Qiang Xue committed
155
	 * The table names may contain schema prefix, if any. Do not quote the table names.
156
	 * @see enableSchemaCache
w  
Qiang Xue committed
157
	 */
158
	public $schemaCacheExclude = array();
w  
Qiang Xue committed
159 160
	/**
	 * @var string the ID of the cache application component that is used to cache the table metadata.
w  
Qiang Xue committed
161
	 * Defaults to 'cache'.
162
	 * @see enableSchemaCache
w  
Qiang Xue committed
163 164 165
	 */
	public $schemaCacheID = 'cache';
	/**
166
	 * @var boolean whether to enable query caching.
w  
Qiang Xue committed
167
	 * Note that in order to enable query caching, a valid cache component as specified
168
	 * by [[queryCacheID]] must be enabled and [[enableQueryCache]] must be set true.
w  
Qiang Xue committed
169
	 *
170 171 172
	 * Methods [[beginCache()]] and [[endCache()]] can be used as shortcuts to turn on
	 * and off query caching on the fly.
	 * @see queryCacheDuration
w  
Qiang Xue committed
173
	 * @see queryCacheID
174 175 176
	 * @see queryCacheDependency
	 * @see beginCache()
	 * @see endCache()
w  
Qiang Xue committed
177
	 */
178
	public $enableQueryCache = false;
w  
Qiang Xue committed
179
	/**
180 181 182 183
	 * @var integer number of seconds that query results can remain valid in cache.
	 * Defaults to 3600, meaning one hour.
	 * Use 0 to indicate that the cached data will never expire.
	 * @see enableQueryCache
w  
Qiang Xue committed
184
	 */
185
	public $queryCacheDuration = 3600;
w  
Qiang Xue committed
186
	/**
187 188 189
	 * @var \yii\caching\Dependency the dependency that will be used when saving query results into cache.
	 * Defaults to null, meaning no dependency.
	 * @see enableQueryCache
w  
Qiang Xue committed
190
	 */
191
	public $queryCacheDependency;
w  
Qiang Xue committed
192 193
	/**
	 * @var string the ID of the cache application component that is used for query caching.
w  
Qiang Xue committed
194
	 * Defaults to 'cache'.
195
	 * @see enableQueryCache
w  
Qiang Xue committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	 */
	public $queryCacheID = 'cache';
	/**
	 * @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
Qiang Xue committed
212 213
	 * the buggy native prepare support.
	 * The default value is null, which means the PDO ATTR_EMULATE_PREPARES value will not be changed.
w  
Qiang Xue committed
214 215 216
	 */
	public $emulatePrepare;
	/**
w  
Qiang Xue committed
217
	 * @var boolean whether to enable profiling for the SQL statements being executed.
w  
Qiang Xue committed
218 219
	 * Defaults to false. This should be mainly enabled and used during development
	 * to find out the bottleneck of SQL executions.
w  
Qiang Xue committed
220
	 * @see getStats
w  
Qiang Xue committed
221 222 223
	 */
	public $enableProfiling = false;
	/**
224 225 226 227 228 229
	 * @var string the common prefix or suffix for table names. If a table name is given
	 * as `{{%TableName}}`, then the percentage character `%` will be replaced with this
	 * property value. For example, `{{%post}}` becomes `{{tbl_post}}` if this property is
	 * set as `"tbl_"`. Note that this property is only effective when [[enableAutoQuoting]]
	 * is true.
	 * @see enableAutoQuoting
w  
Qiang Xue committed
230 231
	 */
	public $tablePrefix;
232 233 234 235 236 237 238 239 240
	/**
	 * @var boolean whether to enable automatic quoting of table names and column names.
	 * Defaults to true. When this property is true, any token enclosed within double curly brackets
	 * (e.g. `{{post}}`) in a SQL statement will be treated as a table name and will be quoted
	 * accordingly when the SQL statement is executed; and any token enclosed within double square
	 * brackets (e.g. `[[name]]`) will be treated as a column name and quoted accordingly.
	 * @see tablePrefix
	 */
	public $enableAutoQuoting = true;
w  
Qiang Xue committed
241
	/**
Qiang Xue committed
242
	 * @var array mapping between PDO driver names and [[Schema]] classes.
w  
Qiang Xue committed
243
	 * The keys of the array are PDO driver names while the values the corresponding
Qiang Xue committed
244
	 * schema class name or configuration. Please refer to [[\Yii::createObject()]] for
w  
Qiang Xue committed
245 246
	 * details on how to specify a configuration.
	 *
Qiang Xue committed
247
	 * This property is mainly used by [[getSchema()]] when fetching the database schema information.
Qiang Xue committed
248
	 * You normally do not need to set this property unless you want to use your own
Qiang Xue committed
249 250 251 252 253 254 255 256 257 258 259 260
	 * [[Schema]] class to support DBMS that is not supported by Yii.
	 */
	public $schemaMap = array(
		'pgsql' => 'yii\db\pgsql\Schema', // PostgreSQL
		'mysqli' => 'yii\db\mysql\Schema', // MySQL
		'mysql' => 'yii\db\mysql\Schema', // MySQL
		'sqlite' => 'yii\db\sqlite\Schema', // sqlite 3
		'sqlite2' => 'yii\db\sqlite\Schema', // sqlite 2
		'mssql' => 'yi\db\dao\mssql\Schema', // Mssql driver on windows hosts
		'dblib' => 'yii\db\mssql\Schema', // dblib drivers on linux (and maybe others os) hosts
		'sqlsrv' => 'yii\db\mssql\Schema', // Mssql
		'oci' => 'yii\db\oci\Schema', // Oracle driver
w  
Qiang Xue committed
261
	);
Qiang Xue committed
262 263 264
	/**
	 * @var Transaction the currently active transaction
	 */
w  
Qiang Xue committed
265
	private $_transaction;
Qiang Xue committed
266
	/**
Qiang Xue committed
267
	 * @var Schema the database schema
Qiang Xue committed
268
	 */
Qiang Xue committed
269
	private $_schema;
w  
Qiang Xue committed
270 271

	/**
w  
Qiang Xue committed
272
	 * Closes the connection when this component is being serialized.
w  
Qiang Xue committed
273 274 275 276 277 278 279 280 281
	 * @return array
	 */
	public function __sleep()
	{
		$this->close();
		return array_keys(get_object_vars($this));
	}

	/**
w  
Qiang Xue committed
282
	 * Returns a value indicating whether the DB connection is established.
w  
Qiang Xue committed
283 284
	 * @return boolean whether the DB connection is established
	 */
285
	public function getIsActive()
w  
Qiang Xue committed
286
	{
w  
Qiang Xue committed
287
		return $this->pdo !== null;
w  
Qiang Xue committed
288 289 290
	}

	/**
291 292 293
	 * Turns on query caching.
	 * This method is provided as a shortcut to setting two properties that are related
	 * with query caching: [[queryCacheDuration]] and [[queryCacheDependency]].
w  
Qiang Xue committed
294
	 * @param integer $duration the number of seconds that query results may remain valid in cache.
295
	 * See [[queryCacheDuration]] for more details.
Qiang Xue committed
296
	 * @param \yii\caching\Dependency $dependency the dependency for the cached query result.
297 298 299 300 301 302 303 304 305 306 307 308 309
	 * See [[queryCacheDependency]] for more details.
	 */
	public function beginCache($duration = null, $dependency = null)
	{
		$this->enableQueryCache = true;
		if ($duration !== null) {
			$this->queryCacheDuration = $duration;
		}
		$this->queryCacheDependency = $dependency;
	}

	/**
	 * Turns off query caching.
w  
Qiang Xue committed
310
	 */
311
	public function endCache()
w  
Qiang Xue committed
312
	{
313
		$this->enableQueryCache = false;
w  
Qiang Xue committed
314 315 316
	}

	/**
w  
Qiang Xue committed
317 318 319
	 * Establishes a DB connection.
	 * It does nothing if a DB connection has already been established.
	 * @throws Exception if connection fails
w  
Qiang Xue committed
320
	 */
w  
Qiang Xue committed
321
	public function open()
w  
Qiang Xue committed
322
	{
w  
Qiang Xue committed
323 324
		if ($this->pdo === null) {
			if (empty($this->dsn)) {
Qiang Xue committed
325
				throw new InvalidConfigException('Connection.dsn cannot be empty.');
w  
Qiang Xue committed
326 327
			}
			try {
Qiang Xue committed
328
				\Yii::trace('Opening DB connection: ' . $this->dsn, __CLASS__);
w  
Qiang Xue committed
329
				$this->pdo = $this->createPdoInstance();
Qiang Xue committed
330
				$this->initConnection();
w  
Qiang Xue committed
331
			}
w  
Qiang Xue committed
332
			catch (\PDOException $e) {
Qiang Xue committed
333 334 335
				\Yii::error("Failed to open DB connection ({$this->dsn}): " . $e->getMessage(), __CLASS__);
				$message = YII_DEBUG ? 'Failed to open DB connection: ' . $e->getMessage() : 'Failed to open DB connection.';
				throw new Exception($message, (int)$e->getCode(), $e->errorInfo);
w  
Qiang Xue committed
336 337 338 339 340 341 342 343
			}
		}
	}

	/**
	 * Closes the currently active DB connection.
	 * It does nothing if the connection is already closed.
	 */
w  
Qiang Xue committed
344
	public function close()
w  
Qiang Xue committed
345
	{
w  
Qiang Xue committed
346
		if ($this->pdo !== null) {
Qiang Xue committed
347
			\Yii::trace('Closing DB connection: ' . $this->dsn, __CLASS__);
w  
Qiang Xue committed
348
			$this->pdo = null;
Qiang Xue committed
349
			$this->_schema = null;
Qiang Xue committed
350
			$this->_transaction = null;
w  
Qiang Xue committed
351
		}
w  
Qiang Xue committed
352 353 354 355
	}

	/**
	 * Creates the PDO instance.
w  
Qiang Xue committed
356
	 * This method is called by [[open]] to establish a DB connection.
Qiang Xue committed
357 358
	 * The default implementation will create a PHP PDO instance.
	 * You may override this method if the default PDO needs to be adapted for certain DBMS.
w  
Qiang Xue committed
359
	 * @return \PDO the pdo instance
w  
Qiang Xue committed
360 361 362
	 */
	protected function createPdoInstance()
	{
w  
Qiang Xue committed
363 364 365 366
		$pdoClass = '\PDO';
		if (($pos = strpos($this->dsn, ':')) !== false) {
			$driver = strtolower(substr($this->dsn, 0, $pos));
			if ($driver === 'mssql' || $driver === 'dblib' || $driver === 'sqlsrv') {
Qiang Xue committed
367
				$pdoClass = 'yii\db\mssql\PDO';
w  
Qiang Xue committed
368
			}
w  
Qiang Xue committed
369
		}
w  
Qiang Xue committed
370
		return new $pdoClass($this->dsn, $this->username, $this->password, $this->attributes);
w  
Qiang Xue committed
371 372 373
	}

	/**
w  
Qiang Xue committed
374 375
	 * Initializes the DB connection.
	 * This method is invoked right after the DB connection is established.
Qiang Xue committed
376 377
	 * The default implementation turns on `PDO::ATTR_EMULATE_PREPARES`
	 * if [[emulatePrepare]] is true, and sets the database [[charset]] if it is not empty.
Qiang Xue committed
378
	 * It then triggers an [[EVENT_AFTER_OPEN]] event.
w  
Qiang Xue committed
379
	 */
w  
Qiang Xue committed
380
	protected function initConnection()
w  
Qiang Xue committed
381
	{
w  
Qiang Xue committed
382 383 384
		$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
		if ($this->emulatePrepare !== null && constant('\PDO::ATTR_EMULATE_PREPARES')) {
			$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, $this->emulatePrepare);
w  
Qiang Xue committed
385
		}
Qiang Xue committed
386 387
		if ($this->charset !== null && in_array($this->getDriverName(), array('pgsql', 'mysql', 'mysqli'))) {
			$this->pdo->exec('SET NAMES ' . $this->pdo->quote($this->charset));
w  
Qiang Xue committed
388
		}
389
		$this->trigger(self::EVENT_AFTER_OPEN);
w  
Qiang Xue committed
390 391 392 393
	}

	/**
	 * Creates a command for execution.
Qiang Xue committed
394 395
	 * @param string $sql the SQL statement to be executed
	 * @param array $params the parameters to be bound to the SQL statement
w  
Qiang Xue committed
396
	 * @return Command the DB command
w  
Qiang Xue committed
397
	 */
Qiang Xue committed
398
	public function createCommand($sql = null, $params = array())
w  
Qiang Xue committed
399
	{
w  
Qiang Xue committed
400
		$this->open();
401
		$command = new Command(array(
Qiang Xue committed
402
			'db' => $this,
403 404
			'sql' => $sql,
		));
Qiang Xue committed
405
		return $command->bindValues($params);
w  
Qiang Xue committed
406 407 408 409
	}

	/**
	 * Returns the currently active transaction.
w  
Qiang Xue committed
410
	 * @return Transaction the currently active transaction. Null if no active transaction.
w  
Qiang Xue committed
411
	 */
Qiang Xue committed
412
	public function getTransaction()
w  
Qiang Xue committed
413
	{
Qiang Xue committed
414
		return $this->_transaction && $this->_transaction->isActive ? $this->_transaction : null;
w  
Qiang Xue committed
415 416 417 418
	}

	/**
	 * Starts a transaction.
Qiang Xue committed
419
	 * @return Transaction the transaction initiated
w  
Qiang Xue committed
420 421 422
	 */
	public function beginTransaction()
	{
w  
Qiang Xue committed
423
		$this->open();
424
		$this->_transaction = new Transaction(array(
Qiang Xue committed
425
			'db' => $this,
426 427 428
		));
		$this->_transaction->begin();
		return $this->_transaction;
w  
Qiang Xue committed
429 430 431
	}

	/**
Qiang Xue committed
432 433
	 * Returns the schema information for the database opened by this connection.
	 * @return Schema the schema information for the database opened by this connection.
Qiang Xue committed
434
	 * @throws NotSupportedException if there is no support for the current driver type
w  
Qiang Xue committed
435
	 */
Qiang Xue committed
436
	public function getSchema()
w  
Qiang Xue committed
437
	{
Qiang Xue committed
438 439
		if ($this->_schema !== null) {
			return $this->_schema;
Qiang Xue committed
440
		} else {
w  
Qiang Xue committed
441
			$driver = $this->getDriverName();
Qiang Xue committed
442 443
			if (isset($this->schemaMap[$driver])) {
				$this->_schema = \Yii::createObject($this->schemaMap[$driver]);
Qiang Xue committed
444
				$this->_schema->db = $this;
Qiang Xue committed
445
				return $this->_schema;
Qiang Xue committed
446
			} else {
Qiang Xue committed
447
				throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS.");
w  
Qiang Xue committed
448
			}
w  
Qiang Xue committed
449 450 451
		}
	}

Qiang Xue committed
452 453 454 455
	/**
	 * Returns the query builder for the current DB connection.
	 * @return QueryBuilder the query builder for the current DB connection.
	 */
w  
Qiang Xue committed
456 457
	public function getQueryBuilder()
	{
Qiang Xue committed
458
		return $this->getSchema()->getQueryBuilder();
w  
Qiang Xue committed
459 460
	}

Qiang Xue committed
461
	/**
Qiang Xue committed
462 463
	 * Obtains the schema information for the named table.
	 * @param string $name table name.
Qiang Xue committed
464
	 * @param boolean $refresh whether to reload the table schema even if it is found in the cache.
Qiang Xue committed
465
	 * @return TableSchema table schema information. Null if the named table does not exist.
Qiang Xue committed
466 467 468
	 */
	public function getTableSchema($name, $refresh = false)
	{
Qiang Xue committed
469
		return $this->getSchema()->getTableSchema($name, $refresh);
Qiang Xue committed
470 471
	}

w  
Qiang Xue committed
472 473 474 475 476 477 478 479
	/**
	 * 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 = '')
	{
Qiang Xue committed
480
		return $this->getSchema()->getLastInsertID($sequenceName);
w  
Qiang Xue committed
481 482 483 484
	}

	/**
	 * Quotes a string value for use in a query.
Qiang Xue committed
485
	 * Note that if the parameter is not a string, it will be returned without change.
w  
Qiang Xue committed
486 487 488 489 490 491
	 * @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)
	{
Qiang Xue committed
492
		return $this->getSchema()->quoteValue($str);
w  
Qiang Xue committed
493 494 495 496 497
	}

	/**
	 * Quotes a table name for use in a query.
	 * If the table name contains schema prefix, the prefix will also be properly quoted.
498 499
	 * If the table name is already quoted or contains special characters including '(', '[[' and '{{',
	 * then this method will do nothing.
w  
Qiang Xue committed
500 501 502
	 * @param string $name table name
	 * @return string the properly quoted table name
	 */
503
	public function quoteTableName($name)
w  
Qiang Xue committed
504
	{
Qiang Xue committed
505
		return $this->getSchema()->quoteTableName($name);
w  
Qiang Xue committed
506 507 508 509
	}

	/**
	 * Quotes a column name for use in a query.
510 511 512
	 * If the column name contains prefix, the prefix will also be properly quoted.
	 * If the column name is already quoted or contains special characters including '(', '[[' and '{{',
	 * then this method will do nothing.
w  
Qiang Xue committed
513 514 515
	 * @param string $name column name
	 * @return string the properly quoted column name
	 */
516
	public function quoteColumnName($name)
Qiang Xue committed
517
	{
Qiang Xue committed
518
		return $this->getSchema()->quoteColumnName($name);
Qiang Xue committed
519 520
	}

w  
Qiang Xue committed
521
	/**
w  
Qiang Xue committed
522
	 * Returns the name of the DB driver for the current [[dsn]].
w  
Qiang Xue committed
523 524 525 526
	 * @return string name of the DB driver
	 */
	public function getDriverName()
	{
w  
Qiang Xue committed
527 528
		if (($pos = strpos($this->dsn, ':')) !== false) {
			return strtolower(substr($this->dsn, 0, $pos));
Qiang Xue committed
529
		} else {
Qiang Xue committed
530
			return strtolower($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME));
w  
Qiang Xue committed
531
		}
w  
Qiang Xue committed
532 533 534
	}

	/**
Qiang Xue committed
535
	 * Returns the statistical results of SQL queries.
w  
Qiang Xue committed
536 537
	 * The results returned include the number of SQL statements executed and
	 * the total time spent.
w  
Qiang Xue committed
538
	 * In order to use this method, [[enableProfiling]] has to be set true.
w  
Qiang Xue committed
539 540
	 * @return array the first element indicates the number of SQL statements executed,
	 * and the second element the total time spent in SQL execution.
Qiang Xue committed
541
	 * @see \yii\logging\Logger::getProfiling()
w  
Qiang Xue committed
542
	 */
Qiang Xue committed
543
	public function getQuerySummary()
w  
Qiang Xue committed
544
	{
w  
Qiang Xue committed
545
		$logger = \Yii::getLogger();
Qiang Xue committed
546
		$timings = $logger->getProfiling(array('yii\db\Command::query', 'yii\db\Command::execute'));
w  
Qiang Xue committed
547
		$count = count($timings);
w  
Qiang Xue committed
548 549 550 551
		$time = 0;
		foreach ($timings as $timing) {
			$time += $timing[1];
		}
w  
Qiang Xue committed
552 553 554
		return array($count, $time);
	}
}