Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for AR case insensitive relation #17595

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion framework/db/ActiveRelationTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ private function normalizeModelKey($value)
$value = $value->__toString();
}

return $value;
return strtolower($value);
}

/**
Expand Down
29 changes: 29 additions & 0 deletions tests/data/ar/Product.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php


namespace yiiunit\data\ar;


/**
* Class Product
* @package yiiunit\data\ar
*
* @property string $sku
* @property string $title
* @property ProductAttribute[] $productAttributes
*/
class Product extends ActiveRecord
{
public static function tableName()
{
return 'product';
}

/**
* @return ProductAttribute[]|\yii\db\ActiveQuery
*/
public function getProductAttributes()
{
return $this->hasMany(ProductAttribute::className(), ['product_sku' => 'sku']);
}
}
31 changes: 31 additions & 0 deletions tests/data/ar/ProductAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php


namespace yiiunit\data\ar;


/**
* Class Product
* @package yiiunit\data\ar
*
* @property int $id
* @property string $product_sku
* @property string $value
* @property Product $product
*/
class ProductAttribute extends ActiveRecord
{
public static function tableName()
{
return 'product_attribute';
}

/**
* @return Product|\yii\db\ActiveQuery
*/
public function getProduct()
{
return $this->hasOne(Product::className(), ['sku' => 'product_sku'])->inverseOf('productAttributes');
}

}
19 changes: 19 additions & 0 deletions tests/data/mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ DROP TABLE IF EXISTS `T_constraints_2` CASCADE;
DROP TABLE IF EXISTS `T_constraints_1` CASCADE;
DROP TABLE IF EXISTS `T_upsert` CASCADE;
DROP TABLE IF EXISTS `T_upsert_1`;
DROP TABLE IF EXISTS `product`;
DROP TABLE IF EXISTS `product_attribute`;

CREATE TABLE `constraints`
(
Expand Down Expand Up @@ -402,3 +404,20 @@ CREATE TABLE `T_upsert_1` (
`a` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `product` (
sku varchar(45) NOT NULL PRIMARY KEY,
title varchar(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;

CREATE TABLE `product_attribute` (
id INTEGER NOT NULL PRIMARY KEY,
product_sku varchar(45),
value varchar(128)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;

INSERT INTO `product` (sku, title) VALUES ('ARTi01', 'Yii1');
INSERT INTO `product` (sku, title) VALUES ('ARTI02', 'Yii2');
INSERT INTO `product_attribute` (id, product_sku, value) VALUES (1, 'ARTI01', 'UPPERCASE');
INSERT INTO `product_attribute` (id, product_sku, value) VALUES (2, 'ARTI01', 'UPPERCASE2');
INSERT INTO `product_attribute` (id, product_sku, value) VALUES (3, 'ARTi01', 'EXACT');
19 changes: 19 additions & 0 deletions tests/data/sqlite.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ DROP TABLE IF EXISTS "T_constraints_2";
DROP TABLE IF EXISTS "T_constraints_1";
DROP TABLE IF EXISTS "T_upsert";
DROP TABLE IF EXISTS "T_upsert_1";
DROP TABLE IF EXISTS "product";
DROP TABLE IF EXISTS "product_attribute";

CREATE TABLE "profile" (
id INTEGER NOT NULL,
Expand Down Expand Up @@ -360,3 +362,20 @@ CREATE TABLE "T_upsert_1"
(
"a" INTEGER NOT NULL PRIMARY KEY
);

CREATE TABLE "product" (
sku varchar(45) NOT NULL,
title varchar(128) NOT NULL,
PRIMARY KEY (sku)
);

CREATE TABLE "product_attribute" (
id INTEGER NOT NULL PRIMARY KEY,
product_sku varchar(45),
value varchar(128)
);
INSERT INTO "product" (sku, title) VALUES ('ARTi01', 'Yii1');
INSERT INTO "product" (sku, title) VALUES ('ARTI02', 'Yii2');
INSERT INTO "product_attribute" (id, product_sku, value) VALUES (1, 'ARTI01', 'UPPERCASE');
INSERT INTO "product_attribute" (id, product_sku, value) VALUES (2, 'ARTI01', 'UPPERCASE2');
INSERT INTO "product_attribute" (id, product_sku, value) VALUES (3, 'ARTi01', 'EXACT');
35 changes: 35 additions & 0 deletions tests/framework/db/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
use yiiunit\data\ar\OrderItemWithNullFK;
use yiiunit\data\ar\OrderWithConstructor;
use yiiunit\data\ar\OrderWithNullFK;
use yiiunit\data\ar\Product;
use yiiunit\data\ar\ProductAttribute;
use yiiunit\data\ar\Profile;
use yiiunit\data\ar\ProfileWithConstructor;
use yiiunit\data\ar\Type;
Expand Down Expand Up @@ -200,6 +202,39 @@ public function testFindLazyViaTable()
$this->assertInternalType('array', $order);
}

/**
* related to https://github.com/yiisoft/active-record/issues/22#issuecomment-443460996
*/
public function testCaseInsensitiveKeysPopulation()
{
if (!in_array($this->driverName, ['mysql'])) {
$this->markTestSkipped('This test only for databases that make case insensitive search by key like MySQL or postgres with citext');
}

$productAttributes = ProductAttribute::find()->where(['product_sku' => 'ARTi01'])->all();
$this->assertCount(3, $productAttributes); // there are here ARTi01 and ARTI01 records

// explicitly change to caseSensitive collation utf8_bin
$this->getConnection()->createCommand("ALTER TABLE " . Product::tableName() . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin")
->execute();
$this->getConnection()->createCommand("ALTER TABLE " . ProductAttribute::tableName() . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin")
->execute();

$product = Product::find()->where(['sku' => 'ARTi01'])->with('productAttributes')->one(); // join for ARTi01
$this->assertNotNull($product);
$this->assertNotCount(3, $product->productAttributes); // joined one record of 3

// revert to caseInsensitive collation utf8_general_ci
$this->getConnection()->createCommand("ALTER TABLE " . Product::tableName() . " CHARACTER SET utf8 COLLATE utf8_general_ci")
->execute();
$this->getConnection()->createCommand("ALTER TABLE " . ProductAttribute::tableName() . " CHARACTER SET utf8 COLLATE utf8_general_ci")
->execute();

$product = Product::find()->where(['sku' => 'ARTi01'])->with('productAttributes')->one(); // join for ARTi01
$this->assertCount(3, $product->productAttributes);

}

public function testFindEagerViaTable()
{
$orders = Order::find()->with('books')->orderBy('id')->all();
Expand Down