sanchezzzhak / kak-clickhouse

Yii2 ext. ClickHouse
69 stars 43 forks source link

Strict field types #50

Open Aresenka opened 4 years ago

Aresenka commented 4 years ago

Реализую выдачу из ClickHouse в GridView с фильтрацией. Соответственно, использую SearchModel, расширяющую модель соответствующей таблицы. В этой SearchModel есть следующий абстрактный код: $query = Stat::find()->where(['user_string_id' => Yii::$app->user->identity->user_custom_id), 'user_int_id' => Yii::$app->user->identity->user_id,]);

Если в таком случае user_custom_id будет строкой, идентичной числу, в модель будет передано число и в запросе значение экранироваться не будет, не смотря на указание для этого поля в rules (['user_string_id','string']), что вызовет ошибку движка ClickHouse

DB::Exception: Illegal types of arguments (String, UInt8) of function equals.

Если возможно, приведение к типам, указанным в rules, было бы весьма полезным.

sanchezzzhak commented 4 years ago

Привет Правила в модели используются только при записях, так-как родной AR не заботится о конвертации все делает PDO

Для поиска вам нужно самим соблюдать тип. (Возможно можно будет сделать проверку типа на основе схемы если используем ActiveQuery и если запрос без связей, над подумать, идея интересная и думаю реализуема)

Мы у себя решаем с поиском вопрос вот так: Для поиска создаем поисковую модель так проще создавать фильтры, под запросы пользователей (а хотелок бывает много)

Поля которые мы ищем мы задаем вот так:

$query = $stat = Stat::find();
$filterArray = [
   'название колонки' => $this->user_id
];
$query = $this->andFilterWhereCaseInt($query, $filterArray);

сам доп. метод

 public function andFilterWhereCaseInt(Query $query, array $params): Query
 {
        foreach ($params as $key => $value) {
            if (!empty($value) && !is_array($value)) {
                $query->andFilterWhere([$key => (int) $value]);
            } else if (is_array($value) && count($value)) {
                    $condition = 'IN';
                    $query->andFilterWhere([
                        $condition,
                        $key, array_map(function ($data) {
                            return (int)$data;
                        }, $value)
                    ]);
                }
            }
        }
        return $query;
}
Aresenka commented 4 years ago

В моём случае изначально было достаточно обернуть передаваемое значение в strval(), что, конечно, просто костыль. В итоге в целом отказался от AQ, так как, насколько я понимаю, QueryBuilder не полностью поддерживает синтаксис запросов ClickHouse (в моём случае всё упёрлось в необходимость использования ANY LEFT JOIN () USING)

sanchezzzhak commented 4 years ago

JOIN не подерживаются в AQ.