sanchezzzhak / kak-clickhouse

Yii2 ext. ClickHouse
69 stars 43 forks source link

Некорректная работа с UInt64 в batchInsert #38

Closed reynholm closed 5 years ago

reynholm commented 5 years ago

Проблема схожая с #33 и #22 но касается batchInsert(): Yii пытается привратить число в строку и так и записать в CH.

Code: 53, e.displayText() = DB::Exception: Type mismatch in IN or VALUES section. Expected: UInt64. Got: String, e.what() = DB::Exception

Возможное решение - переопределить Schema::getColumnPhpType($column) (на bigint возвращать integer независимо от signed/unsigned типа при условии что PHP_INT_SIZE === 8):

protected function getColumnPhpType($column) {
        static $typeMap = [
            // abstract type => php type
            self::TYPE_TINYINT => 'integer',
            self::TYPE_SMALLINT => 'integer',
            self::TYPE_INTEGER => 'integer',
            self::TYPE_BIGINT => 'integer',
            self::TYPE_BOOLEAN => 'boolean',
            self::TYPE_FLOAT => 'double',
            self::TYPE_DOUBLE => 'double',
            self::TYPE_BINARY => 'resource',
            self::TYPE_JSON => 'array',
        ];
        if (isset($typeMap[$column->type])) {
            if ($column->type === 'bigint') {
                return PHP_INT_SIZE === 8 ? 'integer' : 'string';
            }
            if ($column->type === 'integer') {
                return PHP_INT_SIZE === 4 && $column->unsigned ? 'string' : 'integer';
            }

            return $typeMap[$column->type];
        }

        return 'string';
    }
sanchezzzhak commented 5 years ago

Привет, нужна схема и данные, которые невозможно вставить.

reynholm commented 5 years ago

Привет, нужна схема и данные, которые невозможно вставить.

Приветствую.

Для тестов простейшая табличка из одного поля:

CREATE TABLE IF NOT EXISTS ym_visits (
    visit_id UInt64
)
ENGINE = MergeTree()
ORDER BY (visit_id);

Ну и код для проверки:

        $ch_client = \Yii::$app->clickhouse;

        $data = [
            [12345678987654321],
            [12345678987654321],
            [12345678987654321]
        ];
        try
        {
            $ch_client
                ->createCommand(null)
                ->batchInsert(
                    'test_table',
                    [
                        'visit_id'
                    ],
                    $data
                )
                ->execute();
        }
        catch(\Exception $e)
        {
            dump($e->getMessage());
            dump($e->getTraceAsString());
        }

Значения в дате можно как интом, так и строками, результат одинаков.

sanchezzzhak commented 5 years ago

Привет, зафиксил.

reynholm commented 5 years ago

Приветствую, потрясающая оперативность. Проверил, работает, спасибо!