You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
6.8 KiB
248 lines
6.8 KiB
<?php |
|
/** |
|
* Connection class file |
|
* |
|
* @link http://www.yiiframework.com/ |
|
* @copyright Copyright © 2008 Yii Software LLC |
|
* @license http://www.yiiframework.com/license/ |
|
*/ |
|
|
|
namespace yii\db\redis; |
|
|
|
use \yii\base\Component; |
|
use yii\base\NotSupportedException; |
|
use yii\base\InvalidConfigException; |
|
use \yii\db\Exception; |
|
|
|
/** |
|
* |
|
* |
|
* |
|
* |
|
* @since 2.0 |
|
*/ |
|
class Connection extends Component |
|
{ |
|
/** |
|
* @event Event an event that is triggered after a DB connection is established |
|
*/ |
|
const EVENT_AFTER_OPEN = 'afterOpen'; |
|
|
|
/** |
|
* @var string the Data Source Name, or DSN, contains the information required to connect to the database. |
|
* DSN format: redis://[auth@][server][:port][/db] |
|
* @see charset |
|
*/ |
|
public $dsn; |
|
/** |
|
* @var string the username for establishing DB connection. Defaults to empty string. |
|
*/ |
|
public $username = ''; |
|
/** |
|
* @var string the password for establishing DB connection. Defaults to empty string. |
|
*/ |
|
public $password = ''; |
|
|
|
/** |
|
* @var \Jamm\Memory\RedisServer |
|
*/ |
|
public $redis; |
|
|
|
/** |
|
* @var boolean whether to enable profiling for the SQL statements being executed. |
|
* Defaults to false. This should be mainly enabled and used during development |
|
* to find out the bottleneck of SQL executions. |
|
* @see getStats |
|
*/ |
|
public $enableProfiling = false; |
|
/** |
|
* @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 |
|
*/ |
|
public $keyPrefix; |
|
/** |
|
* @var Transaction the currently active transaction |
|
*/ |
|
private $_transaction; |
|
|
|
/** |
|
* Closes the connection when this component is being serialized. |
|
* @return array |
|
*/ |
|
public function __sleep() |
|
{ |
|
$this->close(); |
|
return array_keys(get_object_vars($this)); |
|
} |
|
|
|
/** |
|
* Returns a value indicating whether the DB connection is established. |
|
* @return boolean whether the DB connection is established |
|
*/ |
|
public function getIsActive() |
|
{ |
|
return $this->redis !== null; |
|
} |
|
|
|
/** |
|
* Establishes a DB connection. |
|
* It does nothing if a DB connection has already been established. |
|
* @throws Exception if connection fails |
|
*/ |
|
public function open() |
|
{ |
|
if ($this->redis === null) { |
|
if (empty($this->dsn)) { |
|
throw new InvalidConfigException('Connection.dsn cannot be empty.'); |
|
} |
|
// TODO parse DSN |
|
$host = 'localhost'; |
|
$port = 6379; |
|
try { |
|
\Yii::trace('Opening DB connection: ' . $this->dsn, __CLASS__); |
|
// TODO connection to redis seems to be very easy, consider writing own connect |
|
$this->redis = new \Jamm\Memory\RedisServer($host, $port); |
|
$this->initConnection(); |
|
} |
|
catch (\PDOException $e) { |
|
\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); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Closes the currently active DB connection. |
|
* It does nothing if the connection is already closed. |
|
*/ |
|
public function close() |
|
{ |
|
if ($this->redis !== null) { |
|
\Yii::trace('Closing DB connection: ' . $this->dsn, __CLASS__); |
|
$this->redis = null; |
|
$this->_transaction = null; |
|
} |
|
} |
|
|
|
/** |
|
* Initializes the DB connection. |
|
* This method is invoked right after the DB connection is established. |
|
* 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 [[EVENT_AFTER_OPEN]] event. |
|
*/ |
|
protected function initConnection() |
|
{ |
|
$this->trigger(self::EVENT_AFTER_OPEN); |
|
} |
|
|
|
|
|
/** |
|
* Creates a command for execution. |
|
* @param string $query the SQL statement to be executed |
|
* @param array $params the parameters to be bound to the SQL statement |
|
* @return Command the DB command |
|
*/ |
|
public function createCommand($query = null, $params = array()) |
|
{ |
|
$this->open(); |
|
$command = new Command(array( |
|
'db' => $this, |
|
'query' => $query, |
|
)); |
|
return $command->addValues($params); |
|
} |
|
|
|
/** |
|
* Returns the currently active transaction. |
|
* @return Transaction the currently active transaction. Null if no active transaction. |
|
*/ |
|
public function getTransaction() |
|
{ |
|
return $this->_transaction && $this->_transaction->isActive ? $this->_transaction : null; |
|
} |
|
|
|
/** |
|
* Starts a transaction. |
|
* @return Transaction the transaction initiated |
|
*/ |
|
public function beginTransaction() |
|
{ |
|
$this->open(); |
|
$this->_transaction = new Transaction(array( |
|
'db' => $this, |
|
)); |
|
$this->_transaction->begin(); |
|
return $this->_transaction; |
|
} |
|
|
|
/** |
|
* Returns the schema information for the database opened by this connection. |
|
* @return Schema the schema information for the database opened by this connection. |
|
* @throws NotSupportedException if there is no support for the current driver type |
|
*/ |
|
public function getSchema() |
|
{ |
|
$driver = $this->getDriverName(); |
|
throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS."); |
|
} |
|
|
|
/** |
|
* Returns the query builder for the current DB connection. |
|
* @return QueryBuilder the query builder for the current DB connection. |
|
*/ |
|
public function getQueryBuilder() |
|
{ |
|
return $this->getSchema()->getQueryBuilder(); |
|
} |
|
|
|
/** |
|
* Obtains the schema information for the named table. |
|
* @param string $name table name. |
|
* @param boolean $refresh whether to reload the table schema even if it is found in the cache. |
|
* @return TableSchema table schema information. Null if the named table does not exist. |
|
*/ |
|
public function getTableSchema($name, $refresh = false) |
|
{ |
|
return $this->getSchema()->getTableSchema($name, $refresh); |
|
} |
|
|
|
/** |
|
* Returns the name of the DB driver for the current [[dsn]]. |
|
* @return string name of the DB driver |
|
*/ |
|
public function getDriverName() |
|
{ |
|
if (($pos = strpos($this->dsn, ':')) !== false) { |
|
return strtolower(substr($this->dsn, 0, $pos)); |
|
} else { |
|
return 'redis'; |
|
} |
|
} |
|
|
|
/** |
|
* Returns the statistical results of SQL queries. |
|
* The results returned include the number of SQL statements executed and |
|
* the total time spent. |
|
* In order to use this method, [[enableProfiling]] has to be set true. |
|
* @return array the first element indicates the number of SQL statements executed, |
|
* and the second element the total time spent in SQL execution. |
|
* @see \yii\logging\Logger::getProfiling() |
|
*/ |
|
public function getQuerySummary() |
|
{ |
|
$logger = \Yii::getLogger(); |
|
$timings = $logger->getProfiling(array('yii\db\Command::query', 'yii\db\Command::execute')); |
|
$count = count($timings); |
|
$time = 0; |
|
foreach ($timings as $timing) { |
|
$time += $timing[1]; |
|
} |
|
return array($count, $time); |
|
} |
|
}
|
|
|