yiisoft / yii2

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

Raise visibility of \yii\db\ActiveRelationTrait::filterByModels #3705

Closed mcd-php closed 10 years ago

mcd-php commented 10 years ago

Need to override, had to patch to protected for non-relational DB with limited IN() capability.

Is where any solid reason behind making so many methods private and so non-overridable ? Maybe, need more relaxed visibility policy ?

samdark commented 10 years ago

What's your use case for it?

cebe commented 10 years ago

as far as I see you can fix this in the QueryBuilder by implementing IN condition in a different way.

mcd-php commented 10 years ago

WHERE (col1,col2) IN ((v11,v12),(v21,v22)) breaks Apache Cassandra, replaced by WHERE col1 IN (v11,v21) AND col2 IN (v12,v22) and hope what \yii\db\ActiveRelationTrait::buildBuckets will sort out possible relation algebra breakage and resulting extra rows.

cebe commented 10 years ago

your two conditions are not equal so the transformation is not correct.

cebe commented 10 years ago

as already said, you can implement the QueryBuilder::buildCompositeInCondition to create a condition that works for cassandra. Should be something like (col1 = v11 AND col2 = v21) OR (col1 = v12 AND col2 = v22). You do not need to touch query internals for this.

mcd-php commented 10 years ago

Thank you ! Just implemented - Cassandra rejects it.

Questions:

mcd-php commented 9 years ago

Now I patched it again and wrote trait that asks more data than needed, just by primary keys, in hope what buckets will filter off the extra. In future, i maybe will filter off the extra in all() and one(), applying non-PK 'where' by something like array LINQ.

Question: how would you work around crippled IN() without raising visibility, by asking for more than needed and then filtering off the result set, both in relations and in direct query ?

namespace app\components\cassandra;

use \Yii;

trait ActiveRelationPartialLinkTrait {

    protected function filterByModels($models) {
        $linkSaved = $this->link;
        $modelClassName = $this->modelClass;
        $primaryKeyNames = \Yii::$app->db
            ->getSchema()
            ->getTableSchema($modelClassName::tableName())
            ->primaryKey;

        $this->link = array_intersect_key(
            $this->link,
            array_fill_keys($primaryKeyNames,1)
        );

        parent::filterByModels($models);

        $this->link = $linkSaved;
    }
}
namespace app\components\cassandra;

class ActiveQuery extends \yii\db\ActiveQuery {

    use AllowFilteringTrait; // Just ignore it for this case
    use ActiveRelationPartialLinkTrait;

}