kak-clickhouse icon indicating copy to clipboard operation
kak-clickhouse copied to clipboard

Strict field types

Open Aresenka opened this issue 5 years ago • 3 comments

Реализую выдачу из 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, было бы весьма полезным.

Aresenka avatar Feb 27 '20 18:02 Aresenka

Привет Правила в модели используются только при записях, так-как родной 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;
}

sanchezzzhak avatar Feb 28 '20 15:02 sanchezzzhak

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

Aresenka avatar Feb 28 '20 15:02 Aresenka

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

sanchezzzhak avatar Feb 28 '20 16:02 sanchezzzhak