mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-03 13:58:55 +08:00
Merge branch 'master' into unique-validator-fix
This commit is contained in:
@ -909,12 +909,12 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
|
||||
* ```php
|
||||
* public function beforeSave($insert)
|
||||
* {
|
||||
* if (parent::beforeSave($insert)) {
|
||||
* // ...custom code here...
|
||||
* return true;
|
||||
* } else {
|
||||
* if (!parent::beforeSave($insert)) {
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* // ...custom code here...
|
||||
* return true;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
@ -964,12 +964,12 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
|
||||
* ```php
|
||||
* public function beforeDelete()
|
||||
* {
|
||||
* if (parent::beforeDelete()) {
|
||||
* // ...custom code here...
|
||||
* return true;
|
||||
* } else {
|
||||
* if (!parent::beforeDelete()) {
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* // ...custom code here...
|
||||
return true;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
|
||||
@ -537,7 +537,7 @@ class Command extends Component
|
||||
{
|
||||
$sql = $this->db->getQueryBuilder()->createTable($table, $columns, $options);
|
||||
|
||||
return $this->setSql($sql);
|
||||
return $this->setSql($sql)->requireTableSchemaRefresh($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -680,7 +680,7 @@ class Command extends Component
|
||||
{
|
||||
$sql = $this->db->getQueryBuilder()->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update);
|
||||
|
||||
return $this->setSql($sql);
|
||||
return $this->setSql($sql)->requireTableSchemaRefresh($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -693,7 +693,7 @@ class Command extends Component
|
||||
{
|
||||
$sql = $this->db->getQueryBuilder()->dropForeignKey($name, $table);
|
||||
|
||||
return $this->setSql($sql);
|
||||
return $this->setSql($sql)->requireTableSchemaRefresh($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -771,7 +771,7 @@ class Command extends Component
|
||||
{
|
||||
$sql = $this->db->getQueryBuilder()->addCommentOnColumn($table, $column, $comment);
|
||||
|
||||
return $this->setSql($sql);
|
||||
return $this->setSql($sql)->requireTableSchemaRefresh($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -801,7 +801,7 @@ class Command extends Component
|
||||
{
|
||||
$sql = $this->db->getQueryBuilder()->dropCommentFromColumn($table, $column);
|
||||
|
||||
return $this->setSql($sql);
|
||||
return $this->setSql($sql)->requireTableSchemaRefresh($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -828,10 +828,7 @@ class Command extends Component
|
||||
public function execute()
|
||||
{
|
||||
$sql = $this->getSql();
|
||||
|
||||
$rawSql = $this->getRawSql();
|
||||
|
||||
Yii::info($rawSql, __METHOD__);
|
||||
list($profile, $rawSql) = $this->logQuery(__METHOD__);
|
||||
|
||||
if ($sql == '') {
|
||||
return 0;
|
||||
@ -839,21 +836,40 @@ class Command extends Component
|
||||
|
||||
$this->prepare(false);
|
||||
|
||||
$token = $rawSql;
|
||||
try {
|
||||
Yii::beginProfile($token, __METHOD__);
|
||||
$profile and Yii::beginProfile($rawSql, __METHOD__);
|
||||
|
||||
$this->pdoStatement->execute();
|
||||
$n = $this->pdoStatement->rowCount();
|
||||
|
||||
Yii::endProfile($token, __METHOD__);
|
||||
$profile and Yii::endProfile($rawSql, __METHOD__);
|
||||
|
||||
$this->refreshTableSchema();
|
||||
|
||||
return $n;
|
||||
} catch (\Exception $e) {
|
||||
Yii::endProfile($token, __METHOD__);
|
||||
throw $this->db->getSchema()->convertException($e, $rawSql);
|
||||
$profile and Yii::endProfile($rawSql, __METHOD__);
|
||||
throw $this->db->getSchema()->convertException($e, $rawSql ?: $this->getRawSql());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the current database query if query logging is enabled and returns
|
||||
* the profiling token if profiling is enabled.
|
||||
* @param string $category the log category.
|
||||
* @return array array of two elements, the first is boolean of whether profiling is enabled or not.
|
||||
* The second is the rawSql if it has been created.
|
||||
*/
|
||||
private function logQuery($category)
|
||||
{
|
||||
if ($this->db->enableLogging) {
|
||||
$rawSql = $this->getRawSql();
|
||||
Yii::info($rawSql, $category);
|
||||
}
|
||||
if (!$this->db->enableProfiling) {
|
||||
return [false, isset($rawSql) ? $rawSql : null];
|
||||
} else {
|
||||
return [true, isset($rawSql) ? $rawSql : $this->getRawSql()];
|
||||
}
|
||||
}
|
||||
|
||||
@ -868,9 +884,7 @@ class Command extends Component
|
||||
*/
|
||||
protected function queryInternal($method, $fetchMode = null)
|
||||
{
|
||||
$rawSql = $this->getRawSql();
|
||||
|
||||
Yii::info($rawSql, 'yii\db\Command::query');
|
||||
list($profile, $rawSql) = $this->logQuery('yii\db\Command::query');
|
||||
|
||||
if ($method !== '') {
|
||||
$info = $this->db->getQueryCacheInfo($this->queryCacheDuration, $this->queryCacheDependency);
|
||||
@ -883,7 +897,7 @@ class Command extends Component
|
||||
$fetchMode,
|
||||
$this->db->dsn,
|
||||
$this->db->username,
|
||||
$rawSql,
|
||||
$rawSql ?: $rawSql = $this->getRawSql(),
|
||||
];
|
||||
$result = $cache->get($cacheKey);
|
||||
if (is_array($result) && isset($result[0])) {
|
||||
@ -895,9 +909,8 @@ class Command extends Component
|
||||
|
||||
$this->prepare(true);
|
||||
|
||||
$token = $rawSql;
|
||||
try {
|
||||
Yii::beginProfile($token, 'yii\db\Command::query');
|
||||
$profile and Yii::beginProfile($rawSql, 'yii\db\Command::query');
|
||||
|
||||
$this->pdoStatement->execute();
|
||||
|
||||
@ -911,10 +924,10 @@ class Command extends Component
|
||||
$this->pdoStatement->closeCursor();
|
||||
}
|
||||
|
||||
Yii::endProfile($token, 'yii\db\Command::query');
|
||||
$profile and Yii::endProfile($rawSql, 'yii\db\Command::query');
|
||||
} catch (\Exception $e) {
|
||||
Yii::endProfile($token, 'yii\db\Command::query');
|
||||
throw $this->db->getSchema()->convertException($e, $rawSql);
|
||||
$profile and Yii::endProfile($rawSql, 'yii\db\Command::query');
|
||||
throw $this->db->getSchema()->convertException($e, $rawSql ?: $this->getRawSql());
|
||||
}
|
||||
|
||||
if (isset($cache, $cacheKey, $info)) {
|
||||
|
||||
@ -373,7 +373,22 @@ class Connection extends Component
|
||||
* @see masters
|
||||
*/
|
||||
public $shuffleMasters = true;
|
||||
|
||||
/**
|
||||
* @var bool whether to enable logging of database queries. Defaults to true.
|
||||
* You may want to disable this option in a production environment to gain performance
|
||||
* if you do not need the information being logged.
|
||||
* @since 2.0.12
|
||||
* @see enableProfiling
|
||||
*/
|
||||
public $enableLogging = true;
|
||||
/**
|
||||
* @var bool whether to enable profiling of database queries. Defaults to true.
|
||||
* You may want to disable this option in a production environment to gain performance
|
||||
* if you do not need the information being logged.
|
||||
* @since 2.0.12
|
||||
* @see enableLogging
|
||||
*/
|
||||
public $enableProfiling = true;
|
||||
/**
|
||||
* @var Transaction the currently active transaction
|
||||
*/
|
||||
@ -1065,4 +1080,18 @@ class Connection extends Component
|
||||
$this->close();
|
||||
return array_keys((array) $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the connection after cloning.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
parent::__clone();
|
||||
|
||||
$this->_master = false;
|
||||
$this->_slave = false;
|
||||
$this->pdo = null;
|
||||
$this->_schema = null;
|
||||
$this->_transaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,9 +276,8 @@ class QueryBuilder extends \yii\db\QueryBuilder
|
||||
if (!$modelClass) {
|
||||
return null;
|
||||
}
|
||||
/* @var $model \yii\db\ActiveRecord */
|
||||
$model = new $modelClass;
|
||||
$schema = $model->getTableSchema();
|
||||
/* @var $modelClass \yii\db\ActiveRecord */
|
||||
$schema = $modelClass::getTableSchema();
|
||||
return array_keys($schema->columns);
|
||||
}
|
||||
|
||||
|
||||
@ -331,4 +331,59 @@ EOD;
|
||||
}
|
||||
return parent::buildLikeCondition($operator, $operands, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function buildInCondition($operator, $operands, &$params)
|
||||
{
|
||||
$splitCondition = $this->splitInCondition($operator, $operands, $params);
|
||||
if ($splitCondition !== null) {
|
||||
return $splitCondition;
|
||||
}
|
||||
|
||||
return parent::buildInCondition($operator, $operands, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Oracle DBMS does not support more than 1000 parameters in `IN` condition.
|
||||
* This method splits long `IN` condition into series of smaller ones.
|
||||
*
|
||||
* @param string $operator
|
||||
* @param array $operands
|
||||
* @param array $params
|
||||
* @return null|string null when split is not required. Otherwise - built SQL condition.
|
||||
* @throws Exception
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function splitInCondition($operator, $operands, &$params)
|
||||
{
|
||||
if (!isset($operands[0], $operands[1])) {
|
||||
throw new Exception("Operator '$operator' requires two operands.");
|
||||
}
|
||||
|
||||
list($column, $values) = $operands;
|
||||
|
||||
if ($values instanceof \Traversable) {
|
||||
$values = iterator_to_array($values);
|
||||
}
|
||||
|
||||
if (!is_array($values)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$maxParameters = 1000;
|
||||
$count = count($values);
|
||||
if ($count <= $maxParameters) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$condition = [($operator === 'IN') ? 'OR' : 'AND'];
|
||||
for ($i = 0; $i < $count; $i += $maxParameters) {
|
||||
$condition[] = [$operator, $column, array_slice($values, $i, $maxParameters)];
|
||||
}
|
||||
|
||||
return $this->buildCondition(['AND', $condition], $params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user