Skip to content

Commit 640532d

Browse files
committed
Merge pull request #11403 from yiisoft/fix-11176
This superseeds #11238, #11135, #11176. fixes #11088
2 parents bf9fb0e + 8d8cd1a commit 640532d

File tree

12 files changed

+173
-56
lines changed

12 files changed

+173
-56
lines changed

framework/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ Yii Framework 2 Change Log
139139
- Bug #10751: Fixed `yii\validators\UrlValidator` pattern to improve matching (silverfire)
140140
- Bug #10760: `yii\widgets\DetailView::normalizeAttributes()` fixed for arrayable models (boehsermoe)
141141
- Bug #10825: Fixed `yii\validators\EachValidator` does not respect `skipOnEmpty` rule parameter (klimov-paul)
142+
- Bug #11088: Fixed bug with column name not being quoted correctly, when a quoted table name or a table name in prefix syntax was used (cebe, edgardmessias, Ni-san)
142143
- Bug: Fixed generation of canonical URLs for `ViewAction` pages (samdark)
143144
- Bug: Fixed `mb_*` functions calls to use `UTF-8` or `Yii::$app->charset` (silverfire)
144145
- Enh #2377: Allow specifying a table alias when joining relations via `joinWith()` (cebe, nainoon)

framework/db/Schema.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ public function quoteTableName($name)
522522
*/
523523
public function quoteColumnName($name)
524524
{
525-
if (strpos($name, '(') !== false || strpos($name, '[[') !== false || strpos($name, '{{') !== false) {
525+
if (strpos($name, '(') !== false || strpos($name, '[[') !== false) {
526526
return $name;
527527
}
528528
if (($pos = strrpos($name, '.')) !== false) {
@@ -531,7 +531,9 @@ public function quoteColumnName($name)
531531
} else {
532532
$prefix = '';
533533
}
534-
534+
if (strpos($name, '{{') !== false) {
535+
return $name;
536+
}
535537
return $prefix . $this->quoteSimpleColumnName($name);
536538
}
537539

tests/data/ar/Order.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
*/
1313
class Order extends ActiveRecord
1414
{
15+
public static $tableName;
16+
1517
public static function tableName()
1618
{
17-
return 'order';
19+
return static::$tableName ?: 'order';
1820
}
1921

2022
public function getCustomer()

tests/data/ar/OrderItem.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
*/
1313
class OrderItem extends ActiveRecord
1414
{
15+
public static $tableName;
16+
1517
public static function tableName()
1618
{
17-
return 'order_item';
19+
return static::$tableName ?: 'order_item';
1820
}
1921

2022
public function getOrder()

tests/framework/db/ActiveRecordTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,41 @@ public function testJoinWithSameTable()
815815
$this->assertEquals(0, count($orders[0]->itemsIndexed));
816816
}
817817

818+
public function tableNameProvider()
819+
{
820+
return [
821+
['order', 'order_item'],
822+
['order', '{{%order_item}}'],
823+
['{{%order}}', 'order_item'],
824+
['{{%order}}', '{{%order_item}}'],
825+
];
826+
}
827+
828+
/**
829+
* Test whether conditions are quoted correctly in conditions where joinWith is used.
830+
* @see https://github.com/yiisoft/yii2/issues/11088
831+
* @dataProvider tableNameProvider
832+
*/
833+
public function testRelationWhereParams($orderTableName, $orderItemTableName)
834+
{
835+
Order::$tableName = $orderTableName;
836+
OrderItem::$tableName = $orderItemTableName;
837+
838+
/** @var $order Order */
839+
$order = Order::findOne(1);
840+
$itemsSQL = $order->getOrderitems()->createCommand()->rawSql;
841+
$expectedSQL = $this->replaceQuotes("SELECT * FROM [[order_item]] WHERE [[order_id]]=1");
842+
$this->assertEquals($expectedSQL, $itemsSQL);
843+
844+
$order = Order::findOne(1);
845+
$itemsSQL = $order->getOrderItems()->joinWith('item')->createCommand()->rawSql;
846+
$expectedSQL = $this->replaceQuotes("SELECT [[order_item]].* FROM [[order_item]] LEFT JOIN [[item]] ON [[order_item]].[[item_id]] = [[item]].[[id]] WHERE [[order_item]].[[order_id]]=1");
847+
$this->assertEquals($expectedSQL, $itemsSQL);
848+
849+
Order::$tableName = null;
850+
OrderItem::$tableName = null;
851+
}
852+
818853
public function testAlias()
819854
{
820855
$query = Order::find();

tests/framework/db/ConnectionTest.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,25 +70,49 @@ public function testQuoteValue()
7070

7171
public function testQuoteTableName()
7272
{
73-
$connection = $this->getConnection(false);
73+
$connection = $this->getConnection(false, false);
7474
$this->assertEquals('`table`', $connection->quoteTableName('table'));
7575
$this->assertEquals('`table`', $connection->quoteTableName('`table`'));
7676
$this->assertEquals('`schema`.`table`', $connection->quoteTableName('schema.table'));
7777
$this->assertEquals('`schema`.`table`', $connection->quoteTableName('schema.`table`'));
78+
$this->assertEquals('`schema`.`table`', $connection->quoteTableName('`schema`.`table`'));
7879
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
7980
$this->assertEquals('(table)', $connection->quoteTableName('(table)'));
8081
}
8182

8283
public function testQuoteColumnName()
8384
{
84-
$connection = $this->getConnection(false);
85+
$connection = $this->getConnection(false, false);
8586
$this->assertEquals('`column`', $connection->quoteColumnName('column'));
8687
$this->assertEquals('`column`', $connection->quoteColumnName('`column`'));
87-
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('table.column'));
88-
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('table.`column`'));
8988
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]'));
9089
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}'));
9190
$this->assertEquals('(column)', $connection->quoteColumnName('(column)'));
91+
92+
$this->assertEquals('`column`', $connection->quoteSql('[[column]]'));
93+
$this->assertEquals('`column`', $connection->quoteSql('{{column}}'));
94+
}
95+
96+
public function testQuoteFullColumnName()
97+
{
98+
$connection = $this->getConnection(false, false);
99+
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('table.column'));
100+
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('table.`column`'));
101+
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('`table`.column'));
102+
$this->assertEquals('`table`.`column`', $connection->quoteColumnName('`table`.`column`'));
103+
104+
$this->assertEquals('[[table.column]]', $connection->quoteColumnName('[[table.column]]'));
105+
$this->assertEquals('{{table}}.`column`', $connection->quoteColumnName('{{table}}.column'));
106+
$this->assertEquals('{{table}}.`column`', $connection->quoteColumnName('{{table}}.`column`'));
107+
$this->assertEquals('{{table}}.[[column]]', $connection->quoteColumnName('{{table}}.[[column]]'));
108+
$this->assertEquals('{{%table}}.`column`', $connection->quoteColumnName('{{%table}}.column'));
109+
$this->assertEquals('{{%table}}.`column`', $connection->quoteColumnName('{{%table}}.`column`'));
110+
111+
$this->assertEquals('`table`.`column`', $connection->quoteSql('[[table.column]]'));
112+
$this->assertEquals('`table`.`column`', $connection->quoteSql('{{table}}.[[column]]'));
113+
$this->assertEquals('`table`.`column`', $connection->quoteSql('{{table}}.`column`'));
114+
$this->assertEquals('`table`.`column`', $connection->quoteSql('{{%table}}.[[column]]'));
115+
$this->assertEquals('`table`.`column`', $connection->quoteSql('{{%table}}.`column`'));
92116
}
93117

94118
public function testTransaction()

tests/framework/db/DatabaseTestCase.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,26 @@ public function prepareDatabase($config, $fixture, $open = true)
8989
}
9090
return $db;
9191
}
92+
93+
/**
94+
* adjust dbms specific escaping
95+
* @param $sql
96+
* @return mixed
97+
*/
98+
protected function replaceQuotes($sql)
99+
{
100+
switch ($this->driverName) {
101+
case 'mysql':
102+
case 'sqlite':
103+
return str_replace(['[[', ']]'], '`', $sql);
104+
case 'cubrid':
105+
case 'pgsql':
106+
case 'oci':
107+
return str_replace(['[[', ']]'], '"', $sql);
108+
case 'sqlsrv':
109+
return str_replace(['[[', ']]'], ['[', ']'], $sql);
110+
default:
111+
return $sql;
112+
}
113+
}
92114
}

tests/framework/db/QueryBuilderTest.php

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,28 +50,6 @@ protected function getQueryBuilder()
5050
throw new \Exception('Test is not implemented for ' . $this->driverName);
5151
}
5252

53-
/**
54-
* adjust dbms specific escaping
55-
* @param $sql
56-
* @return mixed
57-
*/
58-
protected function replaceQuotes($sql)
59-
{
60-
switch ($this->driverName) {
61-
case 'mysql':
62-
case 'sqlite':
63-
return str_replace(['[[', ']]'], '`', $sql);
64-
case 'cubrid':
65-
case 'pgsql':
66-
case 'oci':
67-
return str_replace(['[[', ']]'], '"', $sql);
68-
case 'sqlsrv':
69-
return str_replace(['[[', ']]'], ['[', ']'], $sql);
70-
default:
71-
return $sql;
72-
}
73-
}
74-
7553
/**
7654
* this is not used as a dataprovider for testGetColumnType to speed up the test
7755
* when used as dataprovider every single line will cause a reconnect with the database which is not needed here

tests/framework/db/cubrid/CubridConnectionTest.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function testQuoteTableName()
2626
$this->assertEquals('"table"', $connection->quoteTableName('"table"'));
2727
$this->assertEquals('"schema"."table"', $connection->quoteTableName('schema.table'));
2828
$this->assertEquals('"schema"."table"', $connection->quoteTableName('schema."table"'));
29+
$this->assertEquals('"schema"."table"', $connection->quoteTableName('"schema"."table"'));
2930
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
3031
$this->assertEquals('(table)', $connection->quoteTableName('(table)'));
3132
}
@@ -35,10 +36,33 @@ public function testQuoteColumnName()
3536
$connection = $this->getConnection(false);
3637
$this->assertEquals('"column"', $connection->quoteColumnName('column'));
3738
$this->assertEquals('"column"', $connection->quoteColumnName('"column"'));
38-
$this->assertEquals('"table"."column"', $connection->quoteColumnName('table.column'));
39-
$this->assertEquals('"table"."column"', $connection->quoteColumnName('table."column"'));
4039
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]'));
4140
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}'));
4241
$this->assertEquals('(column)', $connection->quoteColumnName('(column)'));
42+
43+
$this->assertEquals('"column"', $connection->quoteSql('[[column]]'));
44+
$this->assertEquals('"column"', $connection->quoteSql('{{column}}'));
45+
}
46+
47+
public function testQuoteFullColumnName()
48+
{
49+
$connection = $this->getConnection(false, false);
50+
$this->assertEquals('"table"."column"', $connection->quoteColumnName('table.column'));
51+
$this->assertEquals('"table"."column"', $connection->quoteColumnName('table."column"'));
52+
$this->assertEquals('"table"."column"', $connection->quoteColumnName('"table".column'));
53+
$this->assertEquals('"table"."column"', $connection->quoteColumnName('"table"."column"'));
54+
55+
$this->assertEquals('[[table.column]]', $connection->quoteColumnName('[[table.column]]'));
56+
$this->assertEquals('{{table}}."column"', $connection->quoteColumnName('{{table}}.column'));
57+
$this->assertEquals('{{table}}."column"', $connection->quoteColumnName('{{table}}."column"'));
58+
$this->assertEquals('{{table}}.[[column]]', $connection->quoteColumnName('{{table}}.[[column]]'));
59+
$this->assertEquals('{{%table}}."column"', $connection->quoteColumnName('{{%table}}.column'));
60+
$this->assertEquals('{{%table}}."column"', $connection->quoteColumnName('{{%table}}."column"'));
61+
62+
$this->assertEquals('"table"."column"', $connection->quoteSql('[[table.column]]'));
63+
$this->assertEquals('"table"."column"', $connection->quoteSql('{{table}}.[[column]]'));
64+
$this->assertEquals('"table"."column"', $connection->quoteSql('{{table}}."column"'));
65+
$this->assertEquals('"table"."column"', $connection->quoteSql('{{%table}}.[[column]]'));
66+
$this->assertEquals('"table"."column"', $connection->quoteSql('{{%table}}."column"'));
4367
}
4468
}

tests/framework/db/mssql/MssqlConnectionTest.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function testQuoteTableName()
2727
$this->assertEquals('[table]', $connection->quoteTableName('[table]'));
2828
$this->assertEquals('[schema].[table]', $connection->quoteTableName('schema.table'));
2929
$this->assertEquals('[schema].[table]', $connection->quoteTableName('schema.[table]'));
30+
$this->assertEquals('[schema].[table]', $connection->quoteTableName('[schema].[table]'));
3031
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
3132
$this->assertEquals('(table)', $connection->quoteTableName('(table)'));
3233
}
@@ -36,10 +37,33 @@ public function testQuoteColumnName()
3637
$connection = $this->getConnection(false);
3738
$this->assertEquals('[column]', $connection->quoteColumnName('column'));
3839
$this->assertEquals('[column]', $connection->quoteColumnName('[column]'));
39-
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.column'));
40-
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.[column]'));
4140
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]'));
4241
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}'));
4342
$this->assertEquals('(column)', $connection->quoteColumnName('(column)'));
43+
44+
$this->assertEquals('[column]', $connection->quoteSql('[[column]]'));
45+
$this->assertEquals('[column]', $connection->quoteSql('{{column}}'));
46+
}
47+
48+
public function testQuoteFullColumnName()
49+
{
50+
$connection = $this->getConnection(false, false);
51+
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.column'));
52+
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.[column]'));
53+
$this->assertEquals('[table].[column]', $connection->quoteColumnName('[table].column'));
54+
$this->assertEquals('[table].[column]', $connection->quoteColumnName('[table].[column]'));
55+
56+
$this->assertEquals('[[table.column]]', $connection->quoteColumnName('[[table.column]]'));
57+
$this->assertEquals('{{table}}.[column]', $connection->quoteColumnName('{{table}}.column'));
58+
$this->assertEquals('{{table}}.[column]', $connection->quoteColumnName('{{table}}.[column]'));
59+
$this->assertEquals('{{table}}.[[column]]', $connection->quoteColumnName('{{table}}.[[column]]'));
60+
$this->assertEquals('{{%table}}.[column]', $connection->quoteColumnName('{{%table}}.column'));
61+
$this->assertEquals('{{%table}}.[column]', $connection->quoteColumnName('{{%table}}.[column]'));
62+
63+
$this->assertEquals('[table].[column]', $connection->quoteSql('[[table.column]]'));
64+
$this->assertEquals('[table].[column]', $connection->quoteSql('{{table}}.[[column]]'));
65+
$this->assertEquals('[table].[column]', $connection->quoteSql('{{table}}.[column]'));
66+
$this->assertEquals('[table].[column]', $connection->quoteSql('{{%table}}.[[column]]'));
67+
$this->assertEquals('[table].[column]', $connection->quoteSql('{{%table}}.[column]'));
4468
}
4569
}

0 commit comments

Comments
 (0)