Connection.php 18.7 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

Qiang Xue committed
12
use yii\base\BadConfigException;
w  
Qiang Xue committed
13

w  
Qiang Xue committed
14
/**
w  
Qiang Xue committed
15
 * Connection represents a connection to a database via [PDO](http://www.php.net/manual/en/ref.pdo.php).
w  
Qiang Xue committed
16
 *
w  
Qiang Xue committed
17 18 19
 * 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
20
 *
w  
Qiang Xue committed
21
 * To establish a DB connection, set [[dsn]], [[username]] and [[password]], and then
22
 * call [[open()]] to be true.
w  
Qiang Xue committed
23 24
 *
 * The following example shows how to create a Connection instance and establish
w  
Qiang Xue committed
25
 * the DB connection:
w  
Qiang Xue committed
26
 *
w  
Qiang Xue committed
27
 * ~~~
Qiang Xue committed
28
 * $connection = new \yii\db\Connection(array(
Qiang Xue committed
29 30 31
 *     'dsn' => $dsn,
 *     'username' => $username,
 *     'password' => $password,
Qiang Xue committed
32
 * ));
33
 * $connection->open();
w  
Qiang Xue committed
34 35
 * ~~~
 *
Qiang Xue committed
36
 * After the DB connection is established, one can execute SQL statements like the following:
w  
Qiang Xue committed
37 38 39
 *
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post');
Qiang Xue committed
40 41 42
 * $posts = $command->queryAll();
 * $command = $connection->createCommand('UPDATE tbl_post SET status=1');
 * $command->execute();
w  
Qiang Xue committed
43 44
 * ~~~
 *
Qiang Xue committed
45 46 47
 * 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
48
 *
w  
Qiang Xue committed
49 50 51 52 53
 * ~~~
 * $command = $connection->createCommand('SELECT * FROM tbl_post WHERE id=:id');
 * $command->bindValue(':id', $_GET['id']);
 * $post = $command->query();
 * ~~~
w  
Qiang Xue committed
54
 *
Qiang Xue committed
55 56 57 58
 * 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
59
 *
w  
Qiang Xue committed
60 61 62
 * ~~~
 * $transaction = $connection->beginTransaction();
 * try {
63 64 65 66
 *     $connection->createCommand($sql1)->execute();
 *     $connection->createCommand($sql2)->execute();
 *     // ... executing other SQL statements ...
 *     $transaction->commit();
Qiang Xue committed
67
 * } catch(Exception $e) {
68
 *     $transaction->rollBack();
w  
Qiang Xue committed
69
 * }
w  
Qiang Xue committed
70
 * ~~~
w  
Qiang Xue committed
71
 *
Qiang Xue committed
72 73
 * Connection is often used as an [[\yii\base\ApplicationComponent|application component]] and configured in the application
 * configuration like the following:
w  
Qiang Xue committed
74 75
 *
 * ~~~
w  
Qiang Xue committed
76
 * array(
Qiang Xue committed
77 78
 *	 'components' => array(
 *		 'db' => array(
Qiang Xue committed
79
 *			 'class' => '\yii\db\Connection',
Qiang Xue committed
80 81 82 83 84 85
 *			 'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
 *			 'username' => 'root',
 *			 'password' => '',
 *			 'charset' => 'utf8',
 *		 ),
 *	 ),
w  
Qiang Xue committed
86
 * )
w  
Qiang Xue committed
87
 * ~~~
w  
Qiang Xue committed
88
 *
89
 * @property boolean $isActive Whether the DB connection is established. This property is read-only.
Qiang Xue committed
90 91
 * @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
92 93 94
 * @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
95
 * @property array $querySummary The statistical results of SQL queries.
Qiang Xue committed
96
 *
97 98
 * @event Event afterOpen this event is triggered after a DB connection is established
 *
w  
Qiang Xue committed
99 100 101 102 103 104
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Connection extends \yii\base\ApplicationComponent
{
	/**
w  
Qiang Xue committed
105 106 107
	 * @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
108
	 * @see charset
w  
Qiang Xue committed
109 110 111 112 113 114 115 116 117 118
	 */
	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
119
	/**
Qiang Xue committed
120
	 * @var array PDO attributes (name=>value) that should be set when calling [[open()]]
w  
Qiang Xue committed
121 122 123 124 125 126 127
	 * 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.
128
	 * This property is mainly managed by [[open()]] and [[close()]] methods.
w  
Qiang Xue committed
129 130 131 132
	 * When a DB connection is active, this property will represent a PDO instance;
	 * otherwise, it will be null.
	 */
	public $pdo;
133 134 135
	/**
	 * @var boolean whether to enable schema caching.
	 * Note that in order to enable truly schema caching, a valid cache component as specified
136
	 * by [[schemaCacheID]] must be enabled and [[enableSchemaCache]] must be set true.
137 138 139 140 141
	 * @see schemaCacheDuration
	 * @see schemaCacheExclude
	 * @see schemaCacheID
	 */
	public $enableSchemaCache = false;
w  
Qiang Xue committed
142 143
	/**
	 * @var integer number of seconds that table metadata can remain valid in cache.
w  
Qiang Xue committed
144
	 * Use 0 to indicate that the cached data will never expire.
145
	 * @see enableSchemaCache
w  
Qiang Xue committed
146
	 */
147
	public $schemaCacheDuration = 3600;
w  
Qiang Xue committed
148 149
	/**
	 * @var array list of tables whose metadata should NOT be cached. Defaults to empty array.
Qiang Xue committed
150
	 * The table names may contain schema prefix, if any. Do not quote the table names.
151
	 * @see enableSchemaCache
w  
Qiang Xue committed
152
	 */
153
	public $schemaCacheExclude = array();
w  
Qiang Xue committed
154 155
	/**
	 * @var string the ID of the cache application component that is used to cache the table metadata.
w  
Qiang Xue committed
156
	 * Defaults to 'cache'.
157
	 * @see enableSchemaCache
w  
Qiang Xue committed
158 159 160
	 */
	public $schemaCacheID = 'cache';
	/**
161
	 * @var boolean whether to enable query caching.
w  
Qiang Xue committed
162
	 * Note that in order to enable query caching, a valid cache component as specified
163
	 * by [[queryCacheID]] must be enabled and [[enableQueryCache]] must be set true.
w  
Qiang Xue committed
164
	 *
165 166 167
	 * 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
168
	 * @see queryCacheID
169 170 171
	 * @see queryCacheDependency
	 * @see beginCache()
	 * @see endCache()
w  
Qiang Xue committed
172
	 */
173
	public $enableQueryCache = false;
w  
Qiang Xue committed
174
	/**
175 176 177 178
	 * @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
179
	 */
180
	public $queryCacheDuration = 3600;
w  
Qiang Xue committed
181
	/**
182 183 184
	 * @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
185
	 */
186
	public $queryCacheDependency;
w  
Qiang Xue committed
187 188
	/**
	 * @var string the ID of the cache application component that is used for query caching.
w  
Qiang Xue committed
189
	 * Defaults to 'cache'.
190
	 * @see enableQueryCache
w  
Qiang Xue committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	 */
	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
207 208
	 * 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
209 210 211
	 */
	public $emulatePrepare;
	/**
w  
Qiang Xue committed
212
	 * @var boolean whether to enable profiling for the SQL statements being executed.
w  
Qiang Xue committed
213 214
	 * Defaults to false. This should be mainly enabled and used during development
	 * to find out the bottleneck of SQL executions.
w  
Qiang Xue committed
215
	 * @see getStats
w  
Qiang Xue committed
216 217 218
	 */
	public $enableProfiling = false;
	/**
219 220 221 222 223 224
	 * @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
225 226
	 */
	public $tablePrefix;
227 228 229 230 231 232 233 234 235
	/**
	 * @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
236
	/**
Qiang Xue committed
237
	 * @var array mapping between PDO driver names and [[Schema]] classes.
w  
Qiang Xue committed
238
	 * The keys of the array are PDO driver names while the values the corresponding
Qiang Xue committed
239
	 * schema class name or configuration. Please refer to [[\Yii::createObject()]] for
w  
Qiang Xue committed
240 241
	 * details on how to specify a configuration.
	 *
Qiang Xue committed
242
	 * This property is mainly used by [[getSchema()]] when fetching the database schema information.
Qiang Xue committed
243
	 * You normally do not need to set this property unless you want to use your own
Qiang Xue committed
244 245 246 247 248 249 250 251 252 253 254 255
	 * [[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
256
	);
Qiang Xue committed
257 258 259
	/**
	 * @var Transaction the currently active transaction
	 */
w  
Qiang Xue committed
260
	private $_transaction;
Qiang Xue committed
261
	/**
Qiang Xue committed
262
	 * @var Schema the database schema
Qiang Xue committed
263
	 */
Qiang Xue committed
264
	private $_schema;
w  
Qiang Xue committed
265 266

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

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

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

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

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

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

	/**
w  
Qiang Xue committed
369 370
	 * Initializes the DB connection.
	 * This method is invoked right after the DB connection is established.
Qiang Xue committed
371 372 373
	 * The default implementation turns on `PDO::ATTR_EMULATE_PREPARES`
	 * if [[emulatePrepare]] is true, and sets the database [[charset]] if it is not empty.
	 * It then triggers an [[afterOpen]] event.
w  
Qiang Xue committed
374
	 */
w  
Qiang Xue committed
375
	protected function initConnection()
w  
Qiang Xue committed
376
	{
w  
Qiang Xue committed
377 378 379
		$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
380
		}
Qiang Xue committed
381 382
		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
383
		}
384
		$this->trigger('afterOpen');
w  
Qiang Xue committed
385 386 387 388
	}

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

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

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

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

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

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

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

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

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

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

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

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