Connection.php 18.8 KB
Newer Older
w  
Qiang Xue committed
1 2 3
<?php
/**
 * @link http://www.yiiframework.com/
Qiang Xue committed
4
 * @copyright Copyright (c) 2008 Yii Software LLC
w  
Qiang Xue committed
5 6 7
 * @license http://www.yiiframework.com/license/
 */

Qiang Xue committed
8
namespace yii\db;
w  
Qiang Xue committed
9

10
use yii\base\Component;
Qiang Xue committed
11 12
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
13
use yii\caching\Cache;
w  
Qiang Xue committed
14

w  
Qiang Xue committed
15
/**
w  
Qiang Xue committed
16
 * Connection represents a connection to a database via [PDO](http://www.php.net/manual/en/ref.pdo.php).
w  
Qiang Xue committed
17
 *
w  
Qiang Xue committed
18 19 20
 * 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
21
 *
w  
Qiang Xue committed
22
 * To establish a DB connection, set [[dsn]], [[username]] and [[password]], and then
23
 * call [[open()]] to be true.
w  
Qiang Xue committed
24 25
 *
 * The following example shows how to create a Connection instance and establish
w  
Qiang Xue committed
26
 * the DB connection:
w  
Qiang Xue committed
27
 *
w  
Qiang Xue committed
28
 * ~~~
Qiang Xue committed
29
 * $connection = new \yii\db\Connection(array(
Qiang Xue committed
30 31 32
 *     'dsn' => $dsn,
 *     'username' => $username,
 *     'password' => $password,
Qiang Xue committed
33
 * ));
34
 * $connection->open();
w  
Qiang Xue committed
35 36
 * ~~~
 *
Qiang Xue committed
37
 * After the DB connection is established, one can execute SQL statements like the following:
w  
Qiang Xue committed
38 39 40
 *
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post');
Qiang Xue committed
41 42 43
 * $posts = $command->queryAll();
 * $command = $connection->createCommand('UPDATE tbl_post SET status=1');
 * $command->execute();
w  
Qiang Xue committed
44 45
 * ~~~
 *
Qiang Xue committed
46 47 48
 * 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
49
 *
w  
Qiang Xue committed
50 51 52 53 54
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post WHERE id=:id');
 * $command->bindValue(':id', $_GET['id']);
 * $post = $command->query();
 * ~~~
w  
Qiang Xue committed
55
 *
Qiang Xue committed
56 57 58 59
 * 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
60
 *
w  
Qiang Xue committed
61 62 63
 * ~~~
 * $transaction = $connection->beginTransaction();
 * try {
64 65 66 67
 *     $connection->createCommand($sql1)->execute();
 *     $connection->createCommand($sql2)->execute();
 *     // ... executing other SQL statements ...
 *     $transaction->commit();
Qiang Xue committed
68
 * } catch(Exception $e) {
69
 *     $transaction->rollBack();
w  
Qiang Xue committed
70
 * }
w  
Qiang Xue committed
71
 * ~~~
w  
Qiang Xue committed
72
 *
73
 * Connection is often used as an application component and configured in the application
Qiang Xue committed
74
 * configuration like the following:
w  
Qiang Xue committed
75 76
 *
 * ~~~
w  
Qiang Xue committed
77
 * array(
Qiang Xue committed
78 79
 *	 'components' => array(
 *		 'db' => array(
Qiang Xue committed
80
 *			 'class' => '\yii\db\Connection',
Qiang Xue committed
81 82 83 84 85 86
 *			 'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
 *			 'username' => 'root',
 *			 'password' => '',
 *			 'charset' => 'utf8',
 *		 ),
 *	 ),
w  
Qiang Xue committed
87
 * )
w  
Qiang Xue committed
88
 * ~~~
w  
Qiang Xue committed
89
 *
90
 * @property boolean $isActive Whether the DB connection is established. This property is read-only.
Qiang Xue committed
91 92
 * @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
93 94 95
 * @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
96
 * @property array $querySummary The statistical results of SQL queries.
Qiang Xue committed
97
 *
w  
Qiang Xue committed
98 99 100
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
101
class Connection extends Component
w  
Qiang Xue committed
102
{
103 104 105 106 107
	/**
	 * @event Event an event that is triggered after a DB connection is established
	 */
	const EVENT_AFTER_OPEN = 'afterOpen';

w  
Qiang Xue committed
108
	/**
w  
Qiang Xue committed
109 110 111
	 * @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
112
	 * @see charset
w  
Qiang Xue committed
113 114 115 116 117 118 119 120 121 122
	 */
	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
123
	/**
Qiang Xue committed
124
	 * @var array PDO attributes (name=>value) that should be set when calling [[open()]]
w  
Qiang Xue committed
125 126 127 128 129 130 131
	 * 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.
132
	 * This property is mainly managed by [[open()]] and [[close()]] methods.
w  
Qiang Xue committed
133 134 135 136
	 * When a DB connection is active, this property will represent a PDO instance;
	 * otherwise, it will be null.
	 */
	public $pdo;
137 138 139
	/**
	 * @var boolean whether to enable schema caching.
	 * Note that in order to enable truly schema caching, a valid cache component as specified
140
	 * by [[schemaCache]] must be enabled and [[enableSchemaCache]] must be set true.
141 142
	 * @see schemaCacheDuration
	 * @see schemaCacheExclude
143
	 * @see schemaCache
144 145
	 */
	public $enableSchemaCache = false;
w  
Qiang Xue committed
146 147
	/**
	 * @var integer number of seconds that table metadata can remain valid in cache.
w  
Qiang Xue committed
148
	 * Use 0 to indicate that the cached data will never expire.
149
	 * @see enableSchemaCache
w  
Qiang Xue committed
150
	 */
151
	public $schemaCacheDuration = 3600;
w  
Qiang Xue committed
152 153
	/**
	 * @var array list of tables whose metadata should NOT be cached. Defaults to empty array.
Qiang Xue committed
154
	 * The table names may contain schema prefix, if any. Do not quote the table names.
155
	 * @see enableSchemaCache
w  
Qiang Xue committed
156
	 */
157
	public $schemaCacheExclude = array();
w  
Qiang Xue committed
158
	/**
159 160
	 * @var Cache|string the cache object or the ID of the cache application component that
	 * is used to cache the table metadata.
161
	 * @see enableSchemaCache
w  
Qiang Xue committed
162
	 */
163
	public $schemaCache = 'cache';
w  
Qiang Xue committed
164
	/**
165
	 * @var boolean whether to enable query caching.
w  
Qiang Xue committed
166
	 * Note that in order to enable query caching, a valid cache component as specified
167
	 * by [[queryCache]] must be enabled and [[enableQueryCache]] must be set true.
w  
Qiang Xue committed
168
	 *
169 170 171
	 * Methods [[beginCache()]] and [[endCache()]] can be used as shortcuts to turn on
	 * and off query caching on the fly.
	 * @see queryCacheDuration
172
	 * @see queryCache
173 174 175
	 * @see queryCacheDependency
	 * @see beginCache()
	 * @see endCache()
w  
Qiang Xue committed
176
	 */
177
	public $enableQueryCache = false;
w  
Qiang Xue committed
178
	/**
179
	 * @var integer number of seconds that query results can remain valid in cache.
180
	 * Defaults to 3600, meaning 3600 seconds, or one hour.
181 182
	 * Use 0 to indicate that the cached data will never expire.
	 * @see enableQueryCache
w  
Qiang Xue committed
183
	 */
184
	public $queryCacheDuration = 3600;
w  
Qiang Xue committed
185
	/**
186 187 188
	 * @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
189
	 */
190
	public $queryCacheDependency;
w  
Qiang Xue committed
191
	/**
192 193
	 * @var Cache|string the cache object or the ID of the cache application component
	 * that is used for query caching.
194
	 * @see enableQueryCache
w  
Qiang Xue committed
195
	 */
196
	public $queryCache = 'cache';
w  
Qiang Xue committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210
	/**
	 * @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
211 212
	 * 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
213 214 215
	 */
	public $emulatePrepare;
	/**
w  
Qiang Xue committed
216
	 * @var boolean whether to enable profiling for the SQL statements being executed.
w  
Qiang Xue committed
217 218
	 * Defaults to false. This should be mainly enabled and used during development
	 * to find out the bottleneck of SQL executions.
w  
Qiang Xue committed
219
	 * @see getStats
w  
Qiang Xue committed
220 221 222
	 */
	public $enableProfiling = false;
	/**
223 224 225 226 227 228
	 * @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
229 230
	 */
	public $tablePrefix;
231 232 233 234 235 236 237 238 239
	/**
	 * @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
240
	/**
Qiang Xue committed
241
	 * @var array mapping between PDO driver names and [[Schema]] classes.
w  
Qiang Xue committed
242
	 * The keys of the array are PDO driver names while the values the corresponding
Qiang Xue committed
243
	 * schema class name or configuration. Please refer to [[\Yii::createObject()]] for
w  
Qiang Xue committed
244 245
	 * details on how to specify a configuration.
	 *
Qiang Xue committed
246
	 * This property is mainly used by [[getSchema()]] when fetching the database schema information.
Qiang Xue committed
247
	 * You normally do not need to set this property unless you want to use your own
Qiang Xue committed
248 249 250 251 252 253 254 255 256 257 258 259
	 * [[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
260
	);
Qiang Xue committed
261 262 263
	/**
	 * @var Transaction the currently active transaction
	 */
w  
Qiang Xue committed
264
	private $_transaction;
Qiang Xue committed
265
	/**
Qiang Xue committed
266
	 * @var Schema the database schema
Qiang Xue committed
267
	 */
Qiang Xue committed
268
	private $_schema;
w  
Qiang Xue committed
269 270

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

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

	/**
290 291 292
	 * 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
293
	 * @param integer $duration the number of seconds that query results may remain valid in cache.
294
	 * If not set, it will use the value of [[queryCacheDuration]]. See [[queryCacheDuration]] for more details.
Qiang Xue committed
295
	 * @param \yii\caching\Dependency $dependency the dependency for the cached query result.
296 297 298 299 300 301 302 303 304 305 306 307 308
	 * 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
309
	 */
310
	public function endCache()
w  
Qiang Xue committed
311
	{
312
		$this->enableQueryCache = false;
w  
Qiang Xue committed
313 314 315
	}

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

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

	/**
	 * Creates the PDO instance.
w  
Qiang Xue committed
355
	 * This method is called by [[open]] to establish a DB connection.
Qiang Xue committed
356 357
	 * 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
358
	 * @return \PDO the pdo instance
w  
Qiang Xue committed
359 360 361
	 */
	protected function createPdoInstance()
	{
w  
Qiang Xue committed
362 363 364 365
		$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
366
				$pdoClass = 'yii\db\mssql\PDO';
w  
Qiang Xue committed
367
			}
w  
Qiang Xue committed
368
		}
w  
Qiang Xue committed
369
		return new $pdoClass($this->dsn, $this->username, $this->password, $this->attributes);
w  
Qiang Xue committed
370 371 372
	}

	/**
w  
Qiang Xue committed
373 374
	 * Initializes the DB connection.
	 * This method is invoked right after the DB connection is established.
Qiang Xue committed
375 376
	 * 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
377
	 * It then triggers an [[EVENT_AFTER_OPEN]] event.
w  
Qiang Xue committed
378
	 */
w  
Qiang Xue committed
379
	protected function initConnection()
w  
Qiang Xue committed
380
	{
w  
Qiang Xue committed
381 382 383
		$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
384
		}
Qiang Xue committed
385 386
		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
387
		}
388
		$this->trigger(self::EVENT_AFTER_OPEN);
w  
Qiang Xue committed
389 390 391 392
	}

	/**
	 * Creates a command for execution.
Qiang Xue committed
393 394
	 * @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
395
	 * @return Command the DB command
w  
Qiang Xue committed
396
	 */
Qiang Xue committed
397
	public function createCommand($sql = null, $params = array())
w  
Qiang Xue committed
398
	{
w  
Qiang Xue committed
399
		$this->open();
400
		$command = new Command(array(
Qiang Xue committed
401
			'db' => $this,
402 403
			'sql' => $sql,
		));
Qiang Xue committed
404
		return $command->bindValues($params);
w  
Qiang Xue committed
405 406 407 408
	}

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

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

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

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

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

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

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

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

	/**
	 * Quotes a column name for use in a query.
509 510 511
	 * 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
512 513 514
	 * @param string $name column name
	 * @return string the properly quoted column name
	 */
515
	public function quoteColumnName($name)
Qiang Xue committed
516
	{
Qiang Xue committed
517
		return $this->getSchema()->quoteColumnName($name);
Qiang Xue committed
518 519
	}

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

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