Commit 6f6e739f by Qiang Xue

...

parent d991f42c
...@@ -416,27 +416,31 @@ class YiiBase ...@@ -416,27 +416,31 @@ class YiiBase
* *
* ~~~ * ~~~
* \Yii::beginProfile('block1'); * \Yii::beginProfile('block1');
* \Yii::beginProfile('block2'); * // some code to be profiled
* \Yii::endProfile('block2'); * \Yii::beginProfile('block2');
* // some other code to be profiled
* \Yii::endProfile('block2');
* \Yii::endProfile('block1'); * \Yii::endProfile('block1');
* ~~~ * ~~~
* @param string $category the category of this profile block * @param string $token token for the code block
* @param string $category the category of this log message
* @see endProfile * @see endProfile
*/ */
public static function beginProfile($category) public static function beginProfile($token, $category)
{ {
self::getLogger()->beginProfile($category); self::getLogger()->beginProfile($token, $category);
} }
/** /**
* Marks the end of a code block for profiling. * Marks the end of a code block for profiling.
* This has to be matched with a previous call to [[beginProfile]] with the same category name. * This has to be matched with a previous call to [[beginProfile]] with the same category name.
* @param string $category the category of this profile block * @param string $token token for the code block
* @param string $category the category of this log message
* @see beginProfile * @see beginProfile
*/ */
public static function endProfile($category) public static function endProfile($token, $category)
{ {
self::getLogger()->endProfile($category); self::getLogger()->endProfile($token, $category);
} }
/** /**
......
...@@ -196,14 +196,6 @@ class Connection extends \yii\base\ApplicationComponent ...@@ -196,14 +196,6 @@ class Connection extends \yii\base\ApplicationComponent
*/ */
public $emulatePrepare; public $emulatePrepare;
/** /**
* @var boolean whether to log the values that are bound to a prepare SQL statement.
* Defaults to false. During development, you may consider setting this property to true
* so that parameter values bound to SQL statements are logged for debugging purpose.
* You should be aware that logging parameter values could be expensive and have significant
* impact on the performance of your application.
*/
public $enableParamLogging = false;
/**
* @var boolean whether to enable profiling for the SQL statements being executed. * @var boolean whether to enable profiling for the SQL statements being executed.
* Defaults to false. This should be mainly enabled and used during development * Defaults to false. This should be mainly enabled and used during development
* to find out the bottleneck of SQL executions. * to find out the bottleneck of SQL executions.
...@@ -436,6 +428,8 @@ class Connection extends \yii\base\ApplicationComponent ...@@ -436,6 +428,8 @@ class Connection extends \yii\base\ApplicationComponent
{ {
if ($this->_transaction !== null && $this->_transaction->active) { if ($this->_transaction !== null && $this->_transaction->active) {
return $this->_transaction; return $this->_transaction;
} else {
return null;
} }
} }
...@@ -536,6 +530,24 @@ class Connection extends \yii\base\ApplicationComponent ...@@ -536,6 +530,24 @@ class Connection extends \yii\base\ApplicationComponent
} }
/** /**
* Prefixes table names in a SQL statement with [[tablePrefix]].
* By calling this method, tokens like '{{TableName}}' in the given SQL statement will
* be replaced with 'prefixTableName', where 'prefix' refers to [[tablePrefix]].
* Note that if [[tablePrefix]] is null, this method will do nothing.
* @param string $sql the SQL statement whose table names need to be prefixed with [[tablePrefix]].
* @return string the expanded SQL statement
* @see tablePrefix
*/
public function expandTablePrefix($sql)
{
if ($this->tablePrefix !== null && strpos($sql, '{{') !== false) {
return preg_replace('/{{(.*?)}}/', $this->tablePrefix . '\1', $sql);
} else {
return $sql;
}
}
/**
* Determines the PDO type for the give PHP data type. * Determines the PDO type for the give PHP data type.
* @param string $type The PHP type (obtained by `gettype()` call). * @param string $type The PHP type (obtained by `gettype()` call).
* @return integer the corresponding PDO type * @return integer the corresponding PDO type
......
...@@ -38,8 +38,13 @@ class QueryBuilder extends \yii\base\Object ...@@ -38,8 +38,13 @@ class QueryBuilder extends \yii\base\Object
'boolean' => 'tinyint(1)', 'boolean' => 'tinyint(1)',
'money' => 'decimal(19,4)', 'money' => 'decimal(19,4)',
); );
/**
* @var Connection the database connection.
*/
public $connection; public $connection;
/**
* @var Schema the database schema
*/
public $schema; public $schema;
public function __construct($schema) public function __construct($schema)
...@@ -61,11 +66,7 @@ class QueryBuilder extends \yii\base\Object ...@@ -61,11 +66,7 @@ class QueryBuilder extends \yii\base\Object
$this->buildOrderBy($query), $this->buildOrderBy($query),
$this->buildLimit($query), $this->buildLimit($query),
); );
$sql = implode("\n", array_filter($clauses)); return $this->connection->expandTablePrefix(implode("\n", array_filter($clauses)));
if ($this->connection->tablePrefix !== null && strpos($sql, '{') !== false) {
$sql = preg_replace('/{{(.*?)}}/', $this->connection->tablePrefix . '\1', $sql);
}
return $sql;
} }
/** /**
...@@ -74,7 +75,6 @@ class QueryBuilder extends \yii\base\Object ...@@ -74,7 +75,6 @@ class QueryBuilder extends \yii\base\Object
* @param string $table the table that new rows will be inserted into. * @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name=>value) to be inserted into the table. * @param array $columns the column data (name=>value) to be inserted into the table.
* @return integer number of rows affected by the execution. * @return integer number of rows affected by the execution.
* @since 1.1.6
*/ */
public function insert($table, $columns, &$params = array()) public function insert($table, $columns, &$params = array())
{ {
......
...@@ -50,7 +50,7 @@ class EmailTarget extends Target ...@@ -50,7 +50,7 @@ class EmailTarget extends Target
$body .= $this->formatMessage($message); $body .= $this->formatMessage($message);
} }
$body = wordwrap($body, 70); $body = wordwrap($body, 70);
$subject = $this->subject === null ? Yii::t('yii', 'Application Log') : $this->subject; $subject = $this->subject === null ? \Yii::t('yii', 'Application Log') : $this->subject;
foreach ($this->emails as $email) { foreach ($this->emails as $email) {
$this->sendEmail($subject, $body, $email, $this->sentFrom, $this->headers); $this->sendEmail($subject, $body, $email, $this->sentFrom, $this->headers);
} }
...@@ -71,6 +71,6 @@ class EmailTarget extends Target ...@@ -71,6 +71,6 @@ class EmailTarget extends Target
if ($sentFrom !== null) { if ($sentFrom !== null) {
$headers[] = "From: {$sentFrom}"; $headers[] = "From: {$sentFrom}";
} }
mail($email, $subject, $body, implode("\r\n", $headers)); mail($sentTo, $subject, $body, implode("\r\n", $headers));
} }
} }
\ No newline at end of file
...@@ -96,8 +96,7 @@ class FileTarget extends Target ...@@ -96,8 +96,7 @@ class FileTarget extends Target
// suppress errors because it's possible multiple processes enter into this section // suppress errors because it's possible multiple processes enter into this section
if ($i === $this->maxLogFiles) { if ($i === $this->maxLogFiles) {
@unlink($rotateFile); @unlink($rotateFile);
} } else {
else {
@rename($rotateFile, $file . '.' . ($i + 1)); @rename($rotateFile, $file . '.' . ($i + 1));
} }
} }
......
...@@ -22,11 +22,12 @@ namespace yii\logging; ...@@ -22,11 +22,12 @@ namespace yii\logging;
*/ */
class Logger extends \yii\base\Component class Logger extends \yii\base\Component
{ {
const LEVEL_TRACE = 'trace'; const LEVEL_ERROR = 1;
const LEVEL_WARNING = 'warning'; const LEVEL_WARNING = 2;
const LEVEL_ERROR = 'error'; const LEVEL_INFO = 3;
const LEVEL_INFO = 'info'; const LEVEL_TRACE = 4;
const LEVEL_PROFILE = 'profile'; const LEVEL_PROFILE_BEGIN = 5;
const LEVEL_PROFILE_END = 6;
/** /**
* @var integer how many messages should be logged before they are flushed from memory and sent to targets. * @var integer how many messages should be logged before they are flushed from memory and sent to targets.
...@@ -111,23 +112,25 @@ class Logger extends \yii\base\Component ...@@ -111,23 +112,25 @@ class Logger extends \yii\base\Component
* Marks the beginning of a code block for profiling. * Marks the beginning of a code block for profiling.
* This has to be matched with a call to [[endProfile]] with the same category name. * This has to be matched with a call to [[endProfile]] with the same category name.
* The begin- and end- calls must also be properly nested. For example, * The begin- and end- calls must also be properly nested. For example,
* @param string $category the category of this profile block * @param string $token token for the code block
* @param string $category the category of this log message
* @see endProfile * @see endProfile
*/ */
public function beginProfile($category) public function beginProfile($token, $category)
{ {
$this->log('begin', self::LEVEL_PROFILE, $category); $this->log($token, self::LEVEL_PROFILE_BEGIN, $category);
} }
/** /**
* Marks the end of a code block for profiling. * Marks the end of a code block for profiling.
* This has to be matched with a previous call to [[beginProfile]] with the same category name. * This has to be matched with a previous call to [[beginProfile]] with the same category name.
* @param string $category the category of this profile block * @param string $token token for the code block
* @param string $category the category of this log message
* @see beginProfile * @see beginProfile
*/ */
public function endProfile($category) public function endProfile($token, $category)
{ {
$this->log('end', self::LEVEL_PROFILE, $category); $this->log($token, self::LEVEL_PROFILE_END, $category);
} }
/** /**
...@@ -141,11 +144,11 @@ class Logger extends \yii\base\Component ...@@ -141,11 +144,11 @@ class Logger extends \yii\base\Component
*/ */
public function log($message, $level, $category) public function log($message, $level, $category)
{ {
if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level !== self::LEVEL_PROFILE) { if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level <= self::LEVEL_TRACE) {
$traces = debug_backtrace(); $traces = debug_backtrace();
$count = 0; $count = 0;
foreach ($traces as $trace) { foreach ($traces as $trace) {
if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII_DIR) !== 0) { if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII_PATH) !== 0) {
$message .= "\nin " . $trace['file'] . ' (' . $trace['line'] . ')'; $message .= "\nin " . $trace['file'] . ' (' . $trace['line'] . ')';
if (++$count >= YII_TRACE_LEVEL) { if (++$count >= YII_TRACE_LEVEL) {
break; break;
...@@ -206,7 +209,7 @@ class Logger extends \yii\base\Component ...@@ -206,7 +209,7 @@ class Logger extends \yii\base\Component
* such as 'yii\db\dao\Connection'. * such as 'yii\db\dao\Connection'.
* @param array $excludeCategories list of categories that you are interested in. * @param array $excludeCategories list of categories that you are interested in.
* @return array the profiling results. Each array element has the following structure: * @return array the profiling results. Each array element has the following structure:
* `array($category, $time)`. * `array($token, $category, $time)`.
*/ */
public function getProfiling($categories = array(), $excludeCategories = array()) public function getProfiling($categories = array(), $excludeCategories = array())
{ {
...@@ -219,7 +222,7 @@ class Logger extends \yii\base\Component ...@@ -219,7 +222,7 @@ class Logger extends \yii\base\Component
$matched = empty($categories); $matched = empty($categories);
foreach ($categories as $category) { foreach ($categories as $category) {
$prefix = rtrim($category, '*'); $prefix = rtrim($category, '*');
if (strpos($timing[0], $prefix) === 0 && ($timing[0] === $category || $prefix !== $category)) { if (strpos($timing[1], $prefix) === 0 && ($timing[1] === $category || $prefix !== $category)) {
$matched = true; $matched = true;
break; break;
} }
...@@ -229,7 +232,7 @@ class Logger extends \yii\base\Component ...@@ -229,7 +232,7 @@ class Logger extends \yii\base\Component
foreach ($excludeCategories as $category) { foreach ($excludeCategories as $category) {
$prefix = rtrim($category, '*'); $prefix = rtrim($category, '*');
foreach ($timings as $i => $timing) { foreach ($timings as $i => $timing) {
if (strpos($timing[0], $prefix) === 0 && ($timing[0] === $category || $prefix !== $category)) { if (strpos($timing[1], $prefix) === 0 && ($timing[1] === $category || $prefix !== $category)) {
$matched = false; $matched = false;
break; break;
} }
...@@ -250,20 +253,17 @@ class Logger extends \yii\base\Component ...@@ -250,20 +253,17 @@ class Logger extends \yii\base\Component
$stack = array(); $stack = array();
foreach ($this->messages as $log) { foreach ($this->messages as $log) {
if ($log[1] !== self::LEVEL_PROFILE) { if ($log[1] < self::LEVEL_PROFILE_BEGIN) {
continue; continue;
} }
list($message, $level, $category, $timestamp) = $log; list($token, $level, $category, $timestamp) = $log;
if ($message === 'begin') { if ($level === self::LEVEL_PROFILE_BEGIN) {
$stack[] = $log; $stack[] = $log;
} } else {
else { // $message === 'end' if (($last = array_pop($stack)) !== null && $last[0] === $token) {
if (($last = array_pop($stack)) !== null && $last[2] === $category) { $timings[] = array($token, $category, $timestamp - $last[3]);
$delta = $timestamp - $last[3]; } else {
$timings[] = array($category, $delta); throw new \yii\base\Exception("Unmatched profiling block: $token");
}
else {
throw new \yii\base\Exception('Found a mismatching profiling block: ' . $category);
} }
} }
} }
...@@ -271,7 +271,7 @@ class Logger extends \yii\base\Component ...@@ -271,7 +271,7 @@ class Logger extends \yii\base\Component
$now = microtime(true); $now = microtime(true);
while (($last = array_pop($stack)) !== null) { while (($last = array_pop($stack)) !== null) {
$delta = $now - $last[3]; $delta = $now - $last[3];
$timings[] = array($last[2], $delta); $timings[] = array($last[0], $last[2], $delta);
} }
return $timings; return $timings;
......
...@@ -96,33 +96,33 @@ class CProfileLogRoute extends CWebLogRoute ...@@ -96,33 +96,33 @@ class CProfileLogRoute extends CWebLogRoute
$n = 0; $n = 0;
foreach ($logs as $log) foreach ($logs as $log)
{ {
if ($log[1] !== CLogger::LEVEL_PROFILE) if ($log[1] !== CLogger::LEVEL_PROFILE) {
continue; continue;
}
$message = $log[0]; $message = $log[0];
if (!strncasecmp($message, 'begin:', 6)) if (!strncasecmp($message, 'begin:', 6)) {
{
$log[0] = substr($message, 6); $log[0] = substr($message, 6);
$log[4] = $n; $log[4] = $n;
$stack[] = $log; $stack[] = $log;
$n++; $n++;
} } elseif (!strncasecmp($message, 'end:', 4)) {
elseif (!strncasecmp($message, 'end:', 4))
{
$token = substr($message, 4); $token = substr($message, 4);
if (($last = array_pop($stack)) !== null && $last[0] === $token) if (($last = array_pop($stack)) !== null && $last[0] === $token) {
{
$delta = $log[3] - $last[3]; $delta = $log[3] - $last[3];
$results[$last[4]] = array($token, $delta, count($stack)); $results[$last[4]] = array($token, $delta, count($stack));
} }
else else
{
throw new CException(Yii::t('yii', 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.', throw new CException(Yii::t('yii', 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
array('{token}' => $token))); array('{token}' => $token)));
}
} }
} }
// remaining entries should be closed here // remaining entries should be closed here
$now = microtime(true); $now = microtime(true);
while (($last = array_pop($stack)) !== null) while (($last = array_pop($stack)) !== null) {
$results[$last[4]] = array($last[0], $now - $last[3], count($stack)); $results[$last[4]] = array($last[0], $now - $last[3], count($stack));
}
ksort($results); ksort($results);
$this->render('profile-callstack', $results); $this->render('profile-callstack', $results);
} }
......
...@@ -127,7 +127,7 @@ class Router extends \yii\base\ApplicationComponent ...@@ -127,7 +127,7 @@ class Router extends \yii\base\ApplicationComponent
{ {
$messages = \Yii::getLogger()->messages; $messages = \Yii::getLogger()->messages;
$export = !isset($event->params['export']) || $event->params['export']; $export = !isset($event->params['export']) || $event->params['export'];
$final = !isset($event-params['flush']) || !$event->params['flush']; $final = !isset($event->params['flush']) || !$event->params['flush'];
foreach ($this->_targets as $target) { foreach ($this->_targets as $target) {
if ($target->enabled) { if ($target->enabled) {
$target->processMessages($messages, $export, $final); $target->processMessages($messages, $export, $final);
......
...@@ -116,7 +116,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable ...@@ -116,7 +116,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
/** /**
* Prepares the [[messages]] for exporting. * Prepares the [[messages]] for exporting.
* This method will modify each message by prependding extra information * This method will modify each message by prepending extra information
* if [[prefixSession]] and/or [[prefixUser]] are set true. * if [[prefixSession]] and/or [[prefixUser]] are set true.
* It will also add an additional message showing context information if * It will also add an additional message showing context information if
* [[logUser]] and/or [[logVars]] are set. * [[logUser]] and/or [[logVars]] are set.
......
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