Commit 9b62fb67 by Qiang Xue

DB cleanup.

parent 1cbfcb19
<?php
/**
* BadCallException class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BadCallException represents an exception caused by calling a method in a wrong way.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class BadCallException extends \Exception
{
}
......@@ -45,7 +45,7 @@ use yii\util\StringHelper;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class ActiveRecord extends Model
class ActiveRecord extends Model
{
/**
* @var array attribute values indexed by attribute names
......
......@@ -21,7 +21,7 @@ namespace yii\db;
* For example,
*
* ~~~
* $users = \Yii::$application->db->createCommand('SELECT * FROM tbl_user')->queryAll();
* $users = $connection->createCommand('SELECT * FROM tbl_user')->queryAll();
* ~~~
*
* Command supports SQL statement preparation and parameter binding.
......@@ -30,6 +30,18 @@ namespace yii\db;
* When binding a parameter, the SQL statement is automatically prepared.
* You may also call [[prepare()]] explicitly to prepare a SQL statement.
*
* Command also supports building SQL statements by providing methods such as [[insert()]],
* [[update()]], etc. For example,
*
* ~~~
* $connection->createCommand()->insert('tbl_user', array(
* 'name' => 'Sam',
* 'age' => 30,
* ))->execute();
* ~~~
*
* To build SELECT SQL statements, please use [[QueryBuilder]] instead.
*
* @property string $sql the SQL statement to be executed
*
* @author Qiang Xue <qiang.xue@gmail.com>
......@@ -42,7 +54,7 @@ class Command extends \yii\base\Component
*/
public $connection;
/**
* @var \PDOStatement the PDOStatement object that this command contains
* @var \PDOStatement the PDOStatement object that this command is associated with
*/
public $pdoStatement;
/**
......@@ -78,7 +90,23 @@ class Command extends \yii\base\Component
{
if ($sql !== $this->_sql) {
if ($this->connection->enableAutoQuoting && $sql != '') {
$sql = preg_replace_callback('/(\\{\\{(.*?)\\}\\}|\\[\\[(.*?)\\]\\])/', function($matches) {
$sql = $this->expandSql($sql);
}
$this->cancel();
$this->_sql = $sql;
$this->_params = array();
}
return $this;
}
/**
* Expands a SQL statement by quoting table and column names and replacing table prefixes.
* @param string $sql the SQL to be expanded
* @return string the expanded SQL
*/
protected function expandSql($sql)
{
return preg_replace_callback('/(\\{\\{(.*?)\\}\\}|\\[\\[(.*?)\\]\\])/', function($matches) {
if (isset($matches[3])) {
return $this->connection->quoteColumnName($matches[3]);
} else {
......@@ -87,12 +115,6 @@ class Command extends \yii\base\Component
}
}, $sql);
}
$this->_sql = $sql;
$this->_params = array();
$this->cancel();
}
return $this;
}
/**
* Prepares the SQL statement to be executed.
......@@ -142,7 +164,7 @@ class Command extends \yii\base\Component
{
$this->prepare();
if ($dataType === null) {
$this->pdoStatement->bindParam($name, $value, $this->getPdoType(gettype($value)));
$this->pdoStatement->bindParam($name, $value, $this->getPdoType($value));
} elseif ($length === null) {
$this->pdoStatement->bindParam($name, $value, $dataType);
} elseif ($driverOptions === null) {
......@@ -169,7 +191,7 @@ class Command extends \yii\base\Component
{
$this->prepare();
if ($dataType === null) {
$this->pdoStatement->bindValue($name, $value, $this->getPdoType(gettype($value)));
$this->pdoStatement->bindValue($name, $value, $this->getPdoType($value));
} else {
$this->pdoStatement->bindValue($name, $value, $dataType);
}
......@@ -197,7 +219,7 @@ class Command extends \yii\base\Component
$type = $value[1];
$value = $value[0];
} else {
$type = $this->getPdoType(gettype($value));
$type = $this->getPdoType($value);
}
$this->pdoStatement->bindValue($name, $value, $type);
$this->_params[$name] = $value;
......@@ -207,12 +229,12 @@ class Command extends \yii\base\Component
}
/**
* Determines the PDO type for the give PHP data type.
* @param string $type The PHP type (obtained by `gettype()` call).
* @return integer the corresponding PDO type
* Determines the PDO type for the give PHP data value.
* @param mixed $data the data whose PDO type is to be determined
* @return integer the PDO type
* @see http://www.php.net/manual/en/pdo.constants.php
*/
private function getPdoType($type)
private function getPdoType($data)
{
static $typeMap = array(
'boolean' => \PDO::PARAM_BOOL,
......@@ -220,6 +242,7 @@ class Command extends \yii\base\Component
'string' => \PDO::PARAM_STR,
'NULL' => \PDO::PARAM_NULL,
);
$type = gettype($data);
return isset($typeMap[$type]) ? $typeMap[$type] : \PDO::PARAM_STR;
}
......@@ -267,7 +290,9 @@ class Command extends \yii\base\Component
\Yii::endProfile(__METHOD__ . "($sql)", __CLASS__);
}
$message = $e->getMessage();
\Yii::error("$message\nFailed to execute SQL: {$sql}{$paramLog}", __CLASS__);
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null;
throw new Exception($message, (int)$e->getCode(), $errorInfo);
}
......@@ -364,6 +389,7 @@ class Command extends \yii\base\Component
* @param mixed $fetchMode the result fetch mode. Please refer to [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php)
* for valid fetch modes. If this parameter is null, the value set in [[fetchMode]] will be used.
* @return mixed the method execution result
* @throws Exception if the query causes any problem
*/
private function queryInternal($method, $params, $fetchMode = null)
{
......@@ -439,7 +465,7 @@ class Command extends \yii\base\Component
* For example,
*
* ~~~
* $db->createCommand()->insert('tbl_user', array(
* $connection->createCommand()->insert('tbl_user', array(
* 'name' => 'Sam',
* 'age' => 30,
* ))->execute();
......@@ -465,7 +491,7 @@ class Command extends \yii\base\Component
* For example,
*
* ~~~
* $db->createCommand()->update('tbl_user', array(
* $connection->createCommand()->update('tbl_user', array(
* 'status' => 1,
* ), 'age > 30')->execute();
* ~~~
......@@ -492,7 +518,7 @@ class Command extends \yii\base\Component
* For example,
*
* ~~~
* $db->createCommand()->delete('tbl_user', 'status = 0')->execute();
* $connection->createCommand()->delete('tbl_user', 'status = 0')->execute();
* ~~~
*
* The method will properly escape the table and column names.
......
......@@ -92,8 +92,7 @@ use yii\base\BadConfigException;
* @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.
* @property string $clientVersion The version information of the DB driver.
* @property array $stats The statistical results of SQL executions.
* @property array $querySummary The statistical results of SQL queries.
*
* @event Event afterOpen this event is triggered after a DB connection is established
*
......@@ -118,7 +117,7 @@ class Connection extends \yii\base\ApplicationComponent
*/
public $password = '';
/**
* @var array PDO attributes (name=>value) that should be set when calling [[open]]
* @var array PDO attributes (name=>value) that should be set when calling [[open()]]
* 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.
......@@ -275,16 +274,6 @@ class Connection extends \yii\base\ApplicationComponent
}
/**
* Returns a list of available PDO drivers.
* @return array list of available PDO drivers
* @see http://www.php.net/manual/en/function.PDO-getAvailableDrivers.php
*/
public static function getAvailableDrivers()
{
return \PDO::getAvailableDrivers();
}
/**
* Returns a value indicating whether the DB connection is established.
* @return boolean whether the DB connection is established
*/
......@@ -533,36 +522,12 @@ class Connection extends \yii\base\ApplicationComponent
if (($pos = strpos($this->dsn, ':')) !== false) {
return strtolower(substr($this->dsn, 0, $pos));
} else {
return strtolower($this->getAttribute(\PDO::ATTR_DRIVER_NAME));
return strtolower($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME));
}
}
/**
* Obtains a specific DB connection attribute information.
* @param integer $name the attribute to be queried
* @return mixed the corresponding attribute information
* @see http://www.php.net/manual/en/function.PDO-getAttribute.php
*/
public function getAttribute($name)
{
$this->open();
return $this->pdo->getAttribute($name);
}
/**
* Sets an attribute on the database connection.
* @param integer $name the attribute to be set
* @param mixed $value the attribute value
* @see http://www.php.net/manual/en/function.PDO-setAttribute.php
*/
public function setAttribute($name, $value)
{
$this->open();
$this->pdo->setAttribute($name, $value);
}
/**
* Returns the statistical results of SQL executions.
* 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.
......@@ -570,7 +535,7 @@ class Connection extends \yii\base\ApplicationComponent
* and the second element the total time spent in SQL execution.
* @see \yii\logging\Logger::getProfiling()
*/
public function getExecutionSummary()
public function getQuerySummary()
{
$logger = \Yii::getLogger();
$timings = $logger->getProfiling(array('yii\db\Command::query', 'yii\db\Command::execute'));
......
......@@ -9,23 +9,33 @@
namespace yii\db;
use yii\db\Exception;
use yii\base\BadCallException;
/**
* DataReader represents a forward-only stream of rows from a query result set.
*
* To read the current row of data, call [[read]]. The method [[readAll]]
* returns all the rows in a single array.
*
* One can also retrieve the rows of data in DataReader by using `foreach`:
* To read the current row of data, call [[read()]]. The method [[readAll()]]
* returns all the rows in a single array. Rows of data can also be read by
* iterating through the reader. For example,
*
* ~~~
* $reader = $command->query('SELECT * FROM tbl_post');
*
* while ($row = $reader->read()) {
* $rows[] = $row;
* }
*
* // equivalent to:
* foreach($reader as $row) {
* // $row represents a row of data
* $rows[] = $row;
* }
*
* // equivalent to:
* $rows = $reader->readAll();
* ~~~
*
* Since DataReader is a forward-only stream, you can only traverse it once.
* Note that since DataReader is a forward-only stream, you can only traverse it once.
* Doing it the second time will throw an exception.
*
* It is possible to use a specific mode of data fetching by setting
* [[fetchMode]]. See the [PHP manual](http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php)
......@@ -202,7 +212,7 @@ class DataReader extends \yii\base\Object implements \Iterator, \Countable
/**
* Resets the iterator to the initial state.
* This method is required by the interface Iterator.
* @throws Exception if this method is invoked twice
* @throws BadCallException if this method is invoked twice
*/
public function rewind()
{
......@@ -210,7 +220,7 @@ class DataReader extends \yii\base\Object implements \Iterator, \Countable
$this->_row = $this->_statement->fetch();
$this->_index = 0;
} else {
throw new Exception('DataReader cannot rewind. It is a forward-only reader.');
throw new BadCallException('DataReader cannot rewind. It is a forward-only reader.');
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment