Browse Source

Fix #18821: Allow `yii\db\ExpressionInterface` as column in `yii\db\conditions\InBuilder`

tags/2.0.45
ntesic 3 years ago committed by GitHub
parent
commit
730f0e56b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/CHANGELOG.md
  2. 20
      framework/db/conditions/InConditionBuilder.php
  3. 7
      framework/db/mssql/conditions/InConditionBuilder.php
  4. 7
      framework/db/sqlite/conditions/InConditionBuilder.php
  5. 4
      tests/framework/db/QueryBuilderTest.php

1
framework/CHANGELOG.md

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.45 under development
------------------------
- Enh #18821: Allow `yii\db\ExpressionInterface` as column in `yii\db\conditions\InBuilder` (ntesic)
- Bug #19182: RBAC Migration failed when use oracle with oci8 (Murolike)
- Bug #19138: Allow digits in language code (ntesic)
- Bug #19148: Fix undefined array key errors in `yii\db\ActiveRelationTrait` (stevekr)

20
framework/db/conditions/InConditionBuilder.php

@ -66,6 +66,10 @@ class InConditionBuilder implements ExpressionBuilderInterface
$column = $column->current();
}
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
if (is_array($values)) {
$rawValues = $values;
} elseif ($values instanceof \Traversable) {
@ -124,6 +128,10 @@ class InConditionBuilder implements ExpressionBuilderInterface
$column = $column->current();
}
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
foreach ($values as $i => $value) {
if (is_array($value) || $value instanceof \ArrayAccess) {
$value = isset($value[$column]) ? $value[$column] : null;
@ -155,6 +163,9 @@ class InConditionBuilder implements ExpressionBuilderInterface
if (is_array($columns)) {
foreach ($columns as $i => $col) {
if ($col instanceof ExpressionInterface) {
$col = $col->expression;
}
if (strpos($col, '(') === false) {
$columns[$i] = $this->queryBuilder->db->quoteColumnName($col);
}
@ -163,6 +174,9 @@ class InConditionBuilder implements ExpressionBuilderInterface
return '(' . implode(', ', $columns) . ") $operator $sql";
}
if ($columns instanceof ExpressionInterface) {
$columns = $columns->expression;
}
if (strpos($columns, '(') === false) {
$columns = $this->queryBuilder->db->quoteColumnName($columns);
}
@ -185,6 +199,9 @@ class InConditionBuilder implements ExpressionBuilderInterface
foreach ($values as $value) {
$vs = [];
foreach ($columns as $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
if (isset($value[$column])) {
$vs[] = $this->queryBuilder->bindParam($value[$column], $params);
} else {
@ -200,6 +217,9 @@ class InConditionBuilder implements ExpressionBuilderInterface
$sqlColumns = [];
foreach ($columns as $i => $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
$sqlColumns[] = strpos($column, '(') === false ? $this->queryBuilder->db->quoteColumnName($column) : $column;
}

7
framework/db/mssql/conditions/InConditionBuilder.php

@ -8,6 +8,7 @@
namespace yii\db\mssql\conditions;
use yii\base\NotSupportedException;
use yii\db\ExpressionInterface;
/**
* {@inheritdoc}
@ -37,12 +38,18 @@ class InConditionBuilder extends \yii\db\conditions\InConditionBuilder
{
$quotedColumns = [];
foreach ($columns as $i => $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
$quotedColumns[$i] = strpos($column, '(') === false ? $this->queryBuilder->db->quoteColumnName($column) : $column;
}
$vss = [];
foreach ($values as $value) {
$vs = [];
foreach ($columns as $i => $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
if (isset($value[$column])) {
$phName = $this->queryBuilder->bindParam($value[$column], $params);
$vs[] = $quotedColumns[$i] . ($operator === 'IN' ? ' = ' : ' != ') . $phName;

7
framework/db/sqlite/conditions/InConditionBuilder.php

@ -8,6 +8,7 @@
namespace yii\db\sqlite\conditions;
use yii\base\NotSupportedException;
use yii\db\ExpressionInterface;
/**
* {@inheritdoc}
@ -37,12 +38,18 @@ class InConditionBuilder extends \yii\db\conditions\InConditionBuilder
{
$quotedColumns = [];
foreach ($columns as $i => $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
$quotedColumns[$i] = strpos($column, '(') === false ? $this->queryBuilder->db->quoteColumnName($column) : $column;
}
$vss = [];
foreach ($values as $value) {
$vs = [];
foreach ($columns as $i => $column) {
if ($column instanceof ExpressionInterface) {
$column = $column->expression;
}
if (isset($value[$column])) {
$phName = $this->queryBuilder->bindParam($value[$column], $params);
$vs[] = $quotedColumns[$i] . ($operator === 'IN' ? ' = ' : ' != ') . $phName;

4
tests/framework/db/QueryBuilderTest.php

@ -1184,6 +1184,7 @@ abstract class QueryBuilderTest extends DatabaseTestCase
//in using array object containing only null value
[['in', 'id', new TraversableObject([null])], '[[id]] IS NULL', []],
[['not in', 'id', new TraversableObject([null])], '[[id]] IS NOT NULL', []],
[['not in', new Expression('id'), new TraversableObject([null])], '[[id]] IS NOT NULL', []],
'composite in using array objects' => [
['in', new TraversableObject(['id', 'name']), new TraversableObject([
@ -1196,6 +1197,7 @@ abstract class QueryBuilderTest extends DatabaseTestCase
// in object conditions
[new InCondition('id', 'in', 1), '[[id]]=:qp0', [':qp0' => 1]],
[new InCondition(new Expression('id'), 'in', 1), '[[id]]=:qp0', [':qp0' => 1]],
[new InCondition('id', 'in', [1]), '[[id]]=:qp0', [':qp0' => 1]],
[new InCondition('id', 'not in', 1), '[[id]]<>:qp0', [':qp0' => 1]],
[new InCondition('id', 'not in', [1]), '[[id]]<>:qp0', [':qp0' => 1]],
@ -1237,6 +1239,7 @@ abstract class QueryBuilderTest extends DatabaseTestCase
case 'sqlite':
$conditions = array_merge($conditions, [
[['in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '(([[id]] = :qp0 AND [[name]] = :qp1) OR ([[id]] = :qp2 AND [[name]] = :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
[['in', [new Expression('id'), 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '(([[id]] = :qp0 AND [[name]] = :qp1) OR ([[id]] = :qp2 AND [[name]] = :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
[['not in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '(([[id]] != :qp0 OR [[name]] != :qp1) AND ([[id]] != :qp2 OR [[name]] != :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
//[ ['in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], 'EXISTS (SELECT 1 FROM (SELECT [[id]], [[name]] FROM [[users]] WHERE [[active]]=:qp0) AS a WHERE a.[[id]] = [[id AND a.]]name[[ = ]]name`)', [':qp0' => 1] ],
//[ ['not in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], 'NOT EXISTS (SELECT 1 FROM (SELECT [[id]], [[name]] FROM [[users]] WHERE [[active]]=:qp0) AS a WHERE a.[[id]] = [[id]] AND a.[[name = ]]name`)', [':qp0' => 1] ],
@ -1246,6 +1249,7 @@ abstract class QueryBuilderTest extends DatabaseTestCase
$conditions = array_merge($conditions, [
[['in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '([[id]], [[name]]) IN ((:qp0, :qp1), (:qp2, :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
[['not in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '([[id]], [[name]]) NOT IN ((:qp0, :qp1), (:qp2, :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
[['not in', [new Expression('id'), 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '([[id]], [[name]]) NOT IN ((:qp0, :qp1), (:qp2, :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar']],
[['in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], '([[id]], [[name]]) IN (SELECT [[id]], [[name]] FROM [[users]] WHERE [[active]]=:qp0)', [':qp0' => 1]],
[['not in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], '([[id]], [[name]]) NOT IN (SELECT [[id]], [[name]] FROM [[users]] WHERE [[active]]=:qp0)', [':qp0' => 1]],
]);

Loading…
Cancel
Save