1: <?php
2: /**
3: * CDbConnection class file
4: *
5: * @author Qiang Xue <qiang.xue@gmail.com>
6: * @link http://www.yiiframework.com/
7: * @copyright 2008-2013 Yii Software LLC
8: * @license http://www.yiiframework.com/license/
9: */
10:
11: /**
12: * CDbConnection represents a connection to a database.
13: *
14: * CDbConnection works together with {@link CDbCommand}, {@link CDbDataReader}
15: * and {@link CDbTransaction} to provide data access to various DBMS
16: * in a common set of APIs. They are a thin wrapper of the {@link http://www.php.net/manual/en/ref.pdo.php PDO}
17: * PHP extension.
18: *
19: * To establish a connection, set {@link setActive active} to true after
20: * specifying {@link connectionString}, {@link username} and {@link password}.
21: *
22: * The following example shows how to create a CDbConnection instance and establish
23: * the actual connection:
24: * <pre>
25: * $connection=new CDbConnection($dsn,$username,$password);
26: * $connection->active=true;
27: * </pre>
28: *
29: * After the DB connection is established, one can execute an SQL statement like the following:
30: * <pre>
31: * $command=$connection->createCommand($sqlStatement);
32: * $command->execute(); // a non-query SQL statement execution
33: * // or execute an SQL query and fetch the result set
34: * $reader=$command->query();
35: *
36: * // each $row is an array representing a row of data
37: * foreach($reader as $row) ...
38: * </pre>
39: *
40: * One can do prepared SQL execution and bind parameters to the prepared SQL:
41: * <pre>
42: * $command=$connection->createCommand($sqlStatement);
43: * $command->bindParam($name1,$value1);
44: * $command->bindParam($name2,$value2);
45: * $command->execute();
46: * </pre>
47: *
48: * To use transaction, do like the following:
49: * <pre>
50: * $transaction=$connection->beginTransaction();
51: * try
52: * {
53: * $connection->createCommand($sql1)->execute();
54: * $connection->createCommand($sql2)->execute();
55: * //.... other SQL executions
56: * $transaction->commit();
57: * }
58: * catch(Exception $e)
59: * {
60: * $transaction->rollback();
61: * }
62: * </pre>
63: *
64: * CDbConnection also provides a set of methods to support setting and querying
65: * of certain DBMS attributes, such as {@link getNullConversion nullConversion}.
66: *
67: * Since CDbConnection implements the interface IApplicationComponent, it can
68: * be used as an application component and be configured in application configuration,
69: * like the following,
70: * <pre>
71: * array(
72: * 'components'=>array(
73: * 'db'=>array(
74: * 'class'=>'CDbConnection',
75: * 'connectionString'=>'sqlite:path/to/dbfile',
76: * ),
77: * ),
78: * )
79: * </pre>
80: *
81: * Use the {@link driverName} property if you want to force the DB connection to use a particular driver
82: * by the given name, disregarding of what was set in the {@link connectionString} property. This might
83: * be useful when working with ODBC connections. Sample code:
84: *
85: * <pre>
86: * 'db'=>array(
87: * 'class'=>'CDbConnection',
88: * 'driverName'=>'mysql',
89: * 'connectionString'=>'odbc:Driver={MySQL};Server=127.0.0.1;Database=test',
90: * 'username'=>'',
91: * 'password'=>'',
92: * ),
93: * </pre>
94: *
95: * @property boolean $active Whether the DB connection is established.
96: * @property PDO $pdoInstance The PDO instance, null if the connection is not established yet.
97: * @property CDbTransaction $currentTransaction The currently active transaction. Null if no active transaction.
98: * @property CDbSchema $schema The database schema for the current connection.
99: * @property CDbCommandBuilder $commandBuilder The command builder.
100: * @property string $lastInsertID The row ID of the last row inserted, or the last value retrieved from the sequence object.
101: * @property mixed $columnCase The case of the column names.
102: * @property mixed $nullConversion How the null and empty strings are converted.
103: * @property boolean $autoCommit Whether creating or updating a DB record will be automatically committed.
104: * @property boolean $persistent Whether the connection is persistent or not.
105: * @property string $driverName Name of the DB driver. This property is read-write since 1.1.16.
106: * Before 1.1.15 it was read-only.
107: * @property string $clientVersion The version information of the DB driver.
108: * @property string $connectionStatus The status of the connection.
109: * @property boolean $prefetch Whether the connection performs data prefetching.
110: * @property string $serverInfo The information of DBMS server.
111: * @property string $serverVersion The version information of DBMS server.
112: * @property integer $timeout Timeout settings for the connection.
113: * @property array $attributes Attributes (name=>value) that are previously explicitly set for the DB connection.
114: * @property array $stats The first element indicates the number of SQL statements executed,
115: * and the second element the total time spent in SQL execution.
116: *
117: * @author Qiang Xue <qiang.xue@gmail.com>
118: * @package system.db
119: * @since 1.0
120: */
121: class CDbConnection extends CApplicationComponent
122: {
123: /**
124: * @var string The Data Source Name, or DSN, contains the information required to connect to the database.
125: * @see http://www.php.net/manual/en/function.PDO-construct.php
126: *
127: * Note that if you're using GBK or BIG5 then it's highly recommended to
128: * update to PHP 5.3.6+ and to specify charset via DSN like
129: * 'mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;'.
130: */
131: public $connectionString;
132: /**
133: * @var string the username for establishing DB connection. Defaults to empty string.
134: */
135: public $username='';
136: /**
137: * @var string the password for establishing DB connection. Defaults to empty string.
138: */
139: public $password='';
140: /**
141: * @var integer number of seconds that table metadata can remain valid in cache.
142: * Use 0 or negative value to indicate not caching schema.
143: * If greater than 0 and the primary cache is enabled, the table metadata will be cached.
144: * @see schemaCachingExclude
145: */
146: public $schemaCachingDuration=0;
147: /**
148: * @var array list of tables whose metadata should NOT be cached. Defaults to empty array.
149: * @see schemaCachingDuration
150: */
151: public $schemaCachingExclude=array();
152: /**
153: * @var string the ID of the cache application component that is used to cache the table metadata.
154: * Defaults to 'cache' which refers to the primary cache application component.
155: * Set this property to false if you want to disable caching table metadata.
156: */
157: public $schemaCacheID='cache';
158: /**
159: * @var integer number of seconds that query results can remain valid in cache.
160: * Use 0 or negative value to indicate not caching query results (the default behavior).
161: *
162: * In order to enable query caching, this property must be a positive
163: * integer and {@link queryCacheID} must point to a valid cache component ID.
164: *
165: * The method {@link cache()} is provided as a convenient way of setting this property
166: * and {@link queryCachingDependency} on the fly.
167: *
168: * @see cache
169: * @see queryCachingDependency
170: * @see queryCacheID
171: * @since 1.1.7
172: */
173: public $queryCachingDuration=0;
174: /**
175: * @var CCacheDependency|ICacheDependency the dependency that will be used when saving query results into cache.
176: * @see queryCachingDuration
177: * @since 1.1.7
178: */
179: public $queryCachingDependency;
180: /**
181: * @var integer the number of SQL statements that need to be cached next.
182: * If this is 0, then even if query caching is enabled, no query will be cached.
183: * Note that each time after executing a SQL statement (whether executed on DB server or fetched from
184: * query cache), this property will be reduced by 1 until 0.
185: * @since 1.1.7
186: */
187: public $queryCachingCount=0;
188: /**
189: * @var string the ID of the cache application component that is used for query caching.
190: * Defaults to 'cache' which refers to the primary cache application component.
191: * Set this property to false if you want to disable query caching.
192: * @since 1.1.7
193: */
194: public $queryCacheID='cache';
195: /**
196: * @var boolean whether the database connection should be automatically established
197: * the component is being initialized. Defaults to true. Note, this property is only
198: * effective when the CDbConnection object is used as an application component.
199: */
200: public $autoConnect=true;
201: /**
202: * @var string the charset used for database connection. The property is only used
203: * for MySQL, MariaDB and PostgreSQL databases. Defaults to null, meaning using default charset
204: * as specified by the database.
205: *
206: * Note that if you're using GBK or BIG5 then it's highly recommended to
207: * update to PHP 5.3.6+ and to specify charset via DSN like
208: * 'mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;'.
209: */
210: public $charset;
211: /**
212: * @var boolean whether to turn on prepare emulation. Defaults to false, meaning PDO
213: * will use the native prepare support if available. For some databases (such as MySQL),
214: * this may need to be set true so that PDO can emulate the prepare support to bypass
215: * the buggy native prepare support. Note, this property is only effective for PHP 5.1.3 or above.
216: * The default value is null, which will not change the ATTR_EMULATE_PREPARES value of PDO.
217: */
218: public $emulatePrepare;
219: /**
220: * @var boolean whether to log the values that are bound to a prepare SQL statement.
221: * Defaults to false. During development, you may consider setting this property to true
222: * so that parameter values bound to SQL statements are logged for debugging purpose.
223: * You should be aware that logging parameter values could be expensive and have significant
224: * impact on the performance of your application.
225: */
226: public $enableParamLogging=false;
227: /**
228: * @var boolean whether to enable profiling the SQL statements being executed.
229: * Defaults to false. This should be mainly enabled and used during development
230: * to find out the bottleneck of SQL executions.
231: */
232: public $enableProfiling=false;
233: /**
234: * @var string the default prefix for table names. Defaults to null, meaning no table prefix.
235: * By setting this property, any token like '{{tableName}}' in {@link CDbCommand::text} will
236: * be replaced by 'prefixTableName', where 'prefix' refers to this property value.
237: * @since 1.1.0
238: */
239: public $tablePrefix;
240: /**
241: * @var array list of SQL statements that should be executed right after the DB connection is established.
242: * @since 1.1.1
243: */
244: public $initSQLs;
245: /**
246: * @var array mapping between PDO driver and schema class name.
247: * A schema class can be specified using path alias.
248: * @since 1.1.6
249: */
250: public $driverMap=array(
251: 'cubrid'=>'CCubridSchema', // CUBRID
252: 'pgsql'=>'CPgsqlSchema', // PostgreSQL
253: 'mysqli'=>'CMysqlSchema', // MySQL
254: 'mysql'=>'CMysqlSchema', // MySQL,MariaDB
255: 'sqlite'=>'CSqliteSchema', // sqlite 3
256: 'sqlite2'=>'CSqliteSchema', // sqlite 2
257: 'mssql'=>'CMssqlSchema', // Mssql driver on windows hosts
258: 'dblib'=>'CMssqlSchema', // dblib drivers on linux (and maybe others os) hosts
259: 'sqlsrv'=>'CMssqlSchema', // Mssql
260: 'oci'=>'COciSchema', // Oracle driver
261: );
262:
263: /**
264: * @var string Custom PDO wrapper class.
265: * @since 1.1.8
266: */
267: public $pdoClass = 'PDO';
268:
269: private $_driverName;
270: private $_attributes=array();
271: private $_active=false;
272: private $_pdo;
273: private $_transaction;
274: private $_schema;
275:
276:
277: /**
278: * Constructor.
279: * Note, the DB connection is not established when this connection
280: * instance is created. Set {@link setActive active} property to true
281: * to establish the connection.
282: * @param string $dsn The Data Source Name, or DSN, contains the information required to connect to the database.
283: * @param string $username The user name for the DSN string.
284: * @param string $password The password for the DSN string.
285: * @see http://www.php.net/manual/en/function.PDO-construct.php
286: */
287: public function __construct($dsn='',$username='',$password='')
288: {
289: $this->connectionString=$dsn;
290: $this->username=$username;
291: $this->password=$password;
292: }
293:
294: /**
295: * Close the connection when serializing.
296: * @return array
297: */
298: public function __sleep()
299: {
300: $this->close();
301: return array_keys(get_object_vars($this));
302: }
303:
304: /**
305: * Returns a list of available PDO drivers.
306: * @return array list of available PDO drivers
307: * @see http://www.php.net/manual/en/function.PDO-getAvailableDrivers.php
308: */
309: public static function getAvailableDrivers()
310: {
311: return PDO::getAvailableDrivers();
312: }
313:
314: /**
315: * Initializes the component.
316: * This method is required by {@link IApplicationComponent} and is invoked by application
317: * when the CDbConnection is used as an application component.
318: * If you override this method, make sure to call the parent implementation
319: * so that the component can be marked as initialized.
320: */
321: public function init()
322: {
323: parent::init();
324: if($this->autoConnect)
325: $this->setActive(true);
326: }
327:
328: /**
329: * Returns whether the DB connection is established.
330: * @return boolean whether the DB connection is established
331: */
332: public function getActive()
333: {
334: return $this->_active;
335: }
336:
337: /**
338: * Open or close the DB connection.
339: * @param boolean $value whether to open or close DB connection
340: * @throws CException if connection fails
341: */
342: public function setActive($value)
343: {
344: if($value!=$this->_active)
345: {
346: if($value)
347: $this->open();
348: else
349: $this->close();
350: }
351: }
352:
353: /**
354: * Sets the parameters about query caching.
355: * This method can be used to enable or disable query caching.
356: * By setting the $duration parameter to be 0, the query caching will be disabled.
357: * Otherwise, query results of the new SQL statements executed next will be saved in cache
358: * and remain valid for the specified duration.
359: * If the same query is executed again, the result may be fetched from cache directly
360: * without actually executing the SQL statement.
361: * @param integer $duration the number of seconds that query results may remain valid in cache.
362: * If this is 0, the caching will be disabled.
363: * @param CCacheDependency|ICacheDependency $dependency the dependency that will be used when saving
364: * the query results into cache.
365: * @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1,
366: * meaning that the next SQL query will be cached.
367: * @return static the connection instance itself.
368: * @since 1.1.7
369: */
370: public function cache($duration, $dependency=null, $queryCount=1)
371: {
372: $this->queryCachingDuration=$duration;
373: $this->queryCachingDependency=$dependency;
374: $this->queryCachingCount=$queryCount;
375: return $this;
376: }
377:
378: /**
379: * Opens DB connection if it is currently not
380: * @throws CException if connection fails
381: */
382: protected function open()
383: {
384: if($this->_pdo===null)
385: {
386: if(empty($this->connectionString))
387: throw new CDbException('CDbConnection.connectionString cannot be empty.');
388: try
389: {
390: Yii::trace('Opening DB connection','system.db.CDbConnection');
391: $this->_pdo=$this->createPdoInstance();
392: $this->initConnection($this->_pdo);
393: $this->_active=true;
394: }
395: catch(PDOException $e)
396: {
397: if(YII_DEBUG)
398: {
399: throw new CDbException('CDbConnection failed to open the DB connection: '.
400: $e->getMessage(),(int)$e->getCode(),$e->errorInfo);
401: }
402: else
403: {
404: Yii::log($e->getMessage(),CLogger::LEVEL_ERROR,'exception.CDbException');
405: throw new CDbException('CDbConnection failed to open the DB connection.',(int)$e->getCode(),$e->errorInfo);
406: }
407: }
408: }
409: }
410:
411: /**
412: * Closes the currently active DB connection.
413: * It does nothing if the connection is already closed.
414: */
415: protected function close()
416: {
417: Yii::trace('Closing DB connection','system.db.CDbConnection');
418: $this->_pdo=null;
419: $this->_active=false;
420: $this->_schema=null;
421: }
422:
423: /**
424: * Creates the PDO instance.
425: * When some functionalities are missing in the pdo driver, we may use
426: * an adapter class to provide them.
427: * @throws CDbException when failed to open DB connection
428: * @return PDO the pdo instance
429: */
430: protected function createPdoInstance()
431: {
432: $pdoClass=$this->pdoClass;
433: if(($driver=$this->getDriverName())!==null)
434: {
435: if($driver==='mssql' || $driver==='dblib')
436: $pdoClass='CMssqlPdoAdapter';
437: elseif($driver==='sqlsrv')
438: $pdoClass='CMssqlSqlsrvPdoAdapter';
439: }
440:
441: if(!class_exists($pdoClass))
442: throw new CDbException(Yii::t('yii','CDbConnection is unable to find PDO class "{className}". Make sure PDO is installed correctly.',
443: array('{className}'=>$pdoClass)));
444:
445: @$instance=new $pdoClass($this->connectionString,$this->username,$this->password,$this->_attributes);
446:
447: if(!$instance)
448: throw new CDbException(Yii::t('yii','CDbConnection failed to open the DB connection.'));
449:
450: return $instance;
451: }
452:
453: /**
454: * Initializes the open db connection.
455: * This method is invoked right after the db connection is established.
456: * The default implementation is to set the charset for MySQL, MariaDB and PostgreSQL database connections.
457: * @param PDO $pdo the PDO instance
458: */
459: protected function initConnection($pdo)
460: {
461: $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
462: if($this->emulatePrepare!==null && constant('PDO::ATTR_EMULATE_PREPARES'))
463: $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,$this->emulatePrepare);
464: if($this->charset!==null)
465: {
466: $driver=strtolower($pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
467: if(in_array($driver,array('pgsql','mysql','mysqli')))
468: $pdo->exec('SET NAMES '.$pdo->quote($this->charset));
469: }
470: if($this->initSQLs!==null)
471: {
472: foreach($this->initSQLs as $sql)
473: $pdo->exec($sql);
474: }
475: }
476:
477: /**
478: * Returns the PDO instance.
479: * @return PDO the PDO instance, null if the connection is not established yet
480: */
481: public function getPdoInstance()
482: {
483: return $this->_pdo;
484: }
485:
486: /**
487: * Creates a command for execution.
488: * @param mixed $query the DB query to be executed. This can be either a string representing a SQL statement,
489: * or an array representing different fragments of a SQL statement. Please refer to {@link CDbCommand::__construct}
490: * for more details about how to pass an array as the query. If this parameter is not given,
491: * you will have to call query builder methods of {@link CDbCommand} to build the DB query.
492: * @return CDbCommand the DB command
493: */
494: public function createCommand($query=null)
495: {
496: $this->setActive(true);
497: return new CDbCommand($this,$query);
498: }
499:
500: /**
501: * Returns the currently active transaction.
502: * @return CDbTransaction the currently active transaction. Null if no active transaction.
503: */
504: public function getCurrentTransaction()
505: {
506: if($this->_transaction!==null)
507: {
508: if($this->_transaction->getActive())
509: return $this->_transaction;
510: }
511: return null;
512: }
513:
514: /**
515: * Starts a transaction.
516: * @return CDbTransaction the transaction initiated
517: */
518: public function beginTransaction()
519: {
520: Yii::trace('Starting transaction','system.db.CDbConnection');
521: $this->setActive(true);
522: $this->_pdo->beginTransaction();
523: return $this->_transaction=new CDbTransaction($this);
524: }
525:
526: /**
527: * Returns the database schema for the current connection
528: * @throws CDbException if CDbConnection does not support reading schema for specified database driver
529: * @return CDbSchema the database schema for the current connection
530: */
531: public function getSchema()
532: {
533: if($this->_schema!==null)
534: return $this->_schema;
535: else
536: {
537: $driver=$this->getDriverName();
538: if(isset($this->driverMap[$driver]))
539: return $this->_schema=Yii::createComponent($this->driverMap[$driver], $this);
540: else
541: throw new CDbException(Yii::t('yii','CDbConnection does not support reading schema for {driver} database.',
542: array('{driver}'=>$driver)));
543: }
544: }
545:
546: /**
547: * Returns the SQL command builder for the current DB connection.
548: * @return CDbCommandBuilder the command builder
549: */
550: public function getCommandBuilder()
551: {
552: return $this->getSchema()->getCommandBuilder();
553: }
554:
555: /**
556: * Returns the ID of the last inserted row or sequence value.
557: * @param string $sequenceName name of the sequence object (required by some DBMS)
558: * @return string the row ID of the last row inserted, or the last value retrieved from the sequence object
559: * @see http://www.php.net/manual/en/function.PDO-lastInsertId.php
560: */
561: public function getLastInsertID($sequenceName='')
562: {
563: $this->setActive(true);
564: return $this->_pdo->lastInsertId($sequenceName);
565: }
566:
567: /**
568: * Quotes a string value for use in a query.
569: * @param string $str string to be quoted
570: * @return string the properly quoted string
571: * @see http://www.php.net/manual/en/function.PDO-quote.php
572: */
573: public function quoteValue($str)
574: {
575: if(is_int($str) || is_float($str))
576: return $str;
577:
578: $this->setActive(true);
579: if(($value=$this->_pdo->quote($str))!==false)
580: return $value;
581: else // the driver doesn't support quote (e.g. oci)
582: return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'";
583: }
584:
585: /**
586: * Quotes a table name for use in a query.
587: * If the table name contains schema prefix, the prefix will also be properly quoted.
588: * @param string $name table name
589: * @return string the properly quoted table name
590: */
591: public function quoteTableName($name)
592: {
593: return $this->getSchema()->quoteTableName($name);
594: }
595:
596: /**
597: * Quotes a column name for use in a query.
598: * If the column name contains prefix, the prefix will also be properly quoted.
599: * @param string $name column name
600: * @return string the properly quoted column name
601: */
602: public function quoteColumnName($name)
603: {
604: return $this->getSchema()->quoteColumnName($name);
605: }
606:
607: /**
608: * Determines the PDO type for the specified PHP type.
609: * @param string $type The PHP type (obtained by gettype() call).
610: * @return integer the corresponding PDO type
611: */
612: public function getPdoType($type)
613: {
614: static $map=array
615: (
616: 'boolean'=>PDO::PARAM_BOOL,
617: 'integer'=>PDO::PARAM_INT,
618: 'string'=>PDO::PARAM_STR,
619: 'resource'=>PDO::PARAM_LOB,
620: 'NULL'=>PDO::PARAM_NULL,
621: );
622: return isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
623: }
624:
625: /**
626: * Returns the case of the column names
627: * @return mixed the case of the column names
628: * @see http://www.php.net/manual/en/pdo.setattribute.php
629: */
630: public function getColumnCase()
631: {
632: return $this->getAttribute(PDO::ATTR_CASE);
633: }
634:
635: /**
636: * Sets the case of the column names.
637: * @param mixed $value the case of the column names
638: * @see http://www.php.net/manual/en/pdo.setattribute.php
639: */
640: public function setColumnCase($value)
641: {
642: $this->setAttribute(PDO::ATTR_CASE,$value);
643: }
644:
645: /**
646: * Returns how the null and empty strings are converted.
647: * @return mixed how the null and empty strings are converted
648: * @see http://www.php.net/manual/en/pdo.setattribute.php
649: */
650: public function getNullConversion()
651: {
652: return $this->getAttribute(PDO::ATTR_ORACLE_NULLS);
653: }
654:
655: /**
656: * Sets how the null and empty strings are converted.
657: * @param mixed $value how the null and empty strings are converted
658: * @see http://www.php.net/manual/en/pdo.setattribute.php
659: */
660: public function setNullConversion($value)
661: {
662: $this->setAttribute(PDO::ATTR_ORACLE_NULLS,$value);
663: }
664:
665: /**
666: * Returns whether creating or updating a DB record will be automatically committed.
667: * Some DBMS (such as sqlite) may not support this feature.
668: * @return boolean whether creating or updating a DB record will be automatically committed.
669: */
670: public function getAutoCommit()
671: {
672: return $this->getAttribute(PDO::ATTR_AUTOCOMMIT);
673: }
674:
675: /**
676: * Sets whether creating or updating a DB record will be automatically committed.
677: * Some DBMS (such as sqlite) may not support this feature.
678: * @param boolean $value whether creating or updating a DB record will be automatically committed.
679: */
680: public function setAutoCommit($value)
681: {
682: $this->setAttribute(PDO::ATTR_AUTOCOMMIT,$value);
683: }
684:
685: /**
686: * Returns whether the connection is persistent or not.
687: * Some DBMS (such as sqlite) may not support this feature.
688: * @return boolean whether the connection is persistent or not
689: */
690: public function getPersistent()
691: {
692: return $this->getAttribute(PDO::ATTR_PERSISTENT);
693: }
694:
695: /**
696: * Sets whether the connection is persistent or not.
697: * Some DBMS (such as sqlite) may not support this feature.
698: * @param boolean $value whether the connection is persistent or not
699: */
700: public function setPersistent($value)
701: {
702: return $this->setAttribute(PDO::ATTR_PERSISTENT,$value);
703: }
704:
705: /**
706: * Returns the name of the DB driver.
707: * @return string name of the DB driver.
708: */
709: public function getDriverName()
710: {
711: if($this->_driverName!==null)
712: return $this->_driverName;
713: elseif(($pos=strpos($this->connectionString,':'))!==false)
714: return $this->_driverName=strtolower(substr($this->connectionString,0,$pos));
715: //return $this->getAttribute(PDO::ATTR_DRIVER_NAME);
716: }
717:
718: /**
719: * Changes the name of the DB driver. Overrides value extracted from the {@link connectionString},
720: * which is behavior by default.
721: * @param string $driverName to be set. Valid values are the keys from the {@link driverMap} property.
722: * @see getDriverName
723: * @see driverName
724: * @since 1.1.16
725: */
726: public function setDriverName($driverName)
727: {
728: $this->_driverName=strtolower($driverName);
729: }
730:
731: /**
732: * Returns the version information of the DB driver.
733: * @return string the version information of the DB driver
734: */
735: public function getClientVersion()
736: {
737: return $this->getAttribute(PDO::ATTR_CLIENT_VERSION);
738: }
739:
740: /**
741: * Returns the status of the connection.
742: * Some DBMS (such as sqlite) may not support this feature.
743: * @return string the status of the connection
744: */
745: public function getConnectionStatus()
746: {
747: return $this->getAttribute(PDO::ATTR_CONNECTION_STATUS);
748: }
749:
750: /**
751: * Returns whether the connection performs data prefetching.
752: * @return boolean whether the connection performs data prefetching
753: */
754: public function getPrefetch()
755: {
756: return $this->getAttribute(PDO::ATTR_PREFETCH);
757: }
758:
759: /**
760: * Returns the information of DBMS server.
761: * @return string the information of DBMS server
762: */
763: public function getServerInfo()
764: {
765: return $this->getAttribute(PDO::ATTR_SERVER_INFO);
766: }
767:
768: /**
769: * Returns the version information of DBMS server.
770: * @return string the version information of DBMS server
771: */
772: public function getServerVersion()
773: {
774: return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
775: }
776:
777: /**
778: * Returns the timeout settings for the connection.
779: * @return integer timeout settings for the connection
780: */
781: public function getTimeout()
782: {
783: return $this->getAttribute(PDO::ATTR_TIMEOUT);
784: }
785:
786: /**
787: * Obtains a specific DB connection attribute information.
788: * @param integer $name the attribute to be queried
789: * @return mixed the corresponding attribute information
790: * @see http://www.php.net/manual/en/function.PDO-getAttribute.php
791: */
792: public function getAttribute($name)
793: {
794: $this->setActive(true);
795: return $this->_pdo->getAttribute($name);
796: }
797:
798: /**
799: * Sets an attribute on the database connection.
800: * @param integer $name the attribute to be set
801: * @param mixed $value the attribute value
802: * @see http://www.php.net/manual/en/function.PDO-setAttribute.php
803: */
804: public function setAttribute($name,$value)
805: {
806: if($this->_pdo instanceof PDO)
807: $this->_pdo->setAttribute($name,$value);
808: else
809: $this->_attributes[$name]=$value;
810: }
811:
812: /**
813: * Returns the attributes that are previously explicitly set for the DB connection.
814: * @return array attributes (name=>value) that are previously explicitly set for the DB connection.
815: * @see setAttributes
816: * @since 1.1.7
817: */
818: public function getAttributes()
819: {
820: return $this->_attributes;
821: }
822:
823: /**
824: * Sets a set of attributes on the database connection.
825: * @param array $values attributes (name=>value) to be set.
826: * @see setAttribute
827: * @since 1.1.7
828: */
829: public function setAttributes($values)
830: {
831: foreach($values as $name=>$value)
832: $this->_attributes[$name]=$value;
833: }
834:
835: /**
836: * Returns the statistical results of SQL executions.
837: * The results returned include the number of SQL statements executed and
838: * the total time spent.
839: * In order to use this method, {@link enableProfiling} has to be set true.
840: * @return array the first element indicates the number of SQL statements executed,
841: * and the second element the total time spent in SQL execution.
842: */
843: public function getStats()
844: {
845: $logger=Yii::getLogger();
846: $timings=$logger->getProfilingResults(null,'system.db.CDbCommand.query');
847: $count=count($timings);
848: $time=array_sum($timings);
849: $timings=$logger->getProfilingResults(null,'system.db.CDbCommand.execute');
850: $count+=count($timings);
851: $time+=array_sum($timings);
852: return array($count,$time);
853: }
854: }
855: