yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.23k stars 6.91k forks source link

Query using a subquery with sql #19771

Open Mikk36 opened 1 year ago

Mikk36 commented 1 year ago

What steps will reproduce the problem?

$testQuery = Entity::findBySql("select entity.id from entity where entity.parent_id is null and entity.status = 10");
$test = Entity::find()->andWhere(['id' => $testQuery])->count();

What is the expected result?

SELECT COUNT(*) FROM `entity` WHERE `id` IN (select entity.id from entity where entity.parent_id is null and entity.status = 10)

What do you get instead?

SELECT COUNT(*) FROM `entity` WHERE `id` IN (SELECT * FROM `entity`)

This seems to come from https://github.com/yiisoft/yii2/blob/f388ca71b08b89e940f1ffbe4afa19ae9d5e115f/framework/db/QueryBuilder.php#L227 not taking into account the possibility of Query already having sql in place. It should do a similar check to this: https://github.com/yiisoft/yii2/blob/f388ca71b08b89e940f1ffbe4afa19ae9d5e115f/framework/db/ActiveQuery.php#L351

Additional info

Q A
Yii version 2.0.46
PHP version 7.0.33
Operating system Docker php:7.0-fpm image
notaidea commented 1 year ago

$testQuery = new \yii\db\Expression("select entity.id from entity where entity.parent_id is null and entity.status = 10"); $test = Entity::find()->andWhere("id in ({$testQuery})")->count();

// or $testQuery = Entity::findBySql("select entity.id from entity where entity.parent_id is null and entity.status = 10"); $expression = new \yii\db\Expression($testQuery->sql); $test = Entity::find()->andWhere("id in ({$expression})")->count();

// or $testQuery = Entity::findBySql("select entity.id from entity where entity.parent_id is null and entity.status = 10"); $test = Entity::find()->andWhere(["in" , "id", $testQuery->all()])->count();

Mikk36 commented 1 year ago

// or $testQuery = Entity::findBySql("select entity.id from entity where entity.parent_id is null and entity.status = 10"); $expression = new \yii\db\Expression($testQuery->sql); $test = Entity::find()->andWhere("id in ({$expression})")->count();

This is ok as long as You know that that specific query is crafted from raw SQL, however is very annoying to keep track of when this sort of query is an ActiveRecord class method for finding some other related models.