Перейти к основному содержанию
Перейти к основному содержанию

chDB для Rust

chDB-rust предоставляет экспериментальные привязки FFI (Foreign Function Interface) для chDB, позволяющие выполнять запросы к ClickHouse непосредственно в ваших Rust-приложениях без каких-либо внешних зависимостей.

Установка

Установка libchdb

Установите библиотеку chDB:

curl -sL https://lib.chdb.io | bash

Использование

chDB для Rust предоставляет как статический, так и состояние-сохраняющий режимы выполнения запросов.

Статический режим

Для простых запросов без сохранения состояния:

use chdb_rust::{execute, arg::Arg, format::OutputFormat};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Выполнить простой запрос
    let result = execute(
        "SELECT version()",
        Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)])
    )?;
    println!("Версия ClickHouse: {}", result.data_utf8()?);
    
    // Запрос к CSV‑файлу
    let result = execute(
        "SELECT * FROM file('data.csv', 'CSV')",
        Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)])
    )?;
    println!("Данные из CSV: {}", result.data_utf8()?);
    
    Ok(())
}

Использование с сохранением состояния (сеансы)

Для запросов, которым требуется постоянное состояние, например для работы с базами данных и таблицами:

use chdb_rust::{
    session::SessionBuilder,
    arg::Arg,
    format::OutputFormat,
    log_level::LogLevel
};
use tempdir::TempDir;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Создайте временный каталог для хранения данных базы
    let tmp = TempDir::new("chdb-rust")?;
    
    // Создайте сеанс с заданной конфигурацией
    let session = SessionBuilder::new()
        .with_data_path(tmp.path())
        .with_arg(Arg::LogLevel(LogLevel::Debug))
        .with_auto_cleanup(true)  // Автоочистка при уничтожении объекта
        .build()?;

    // Создайте базу данных и таблицу
    session.execute(
        "CREATE DATABASE demo; USE demo", 
        Some(&[Arg::MultiQuery])
    )?;

    session.execute(
        "CREATE TABLE logs (id UInt64, msg String) ENGINE = MergeTree() ORDER BY id",
        None,
    )?;

    // Вставьте данные
    session.execute(
        "INSERT INTO logs (id, msg) VALUES (1, 'Привет'), (2, 'Мир')",
        None,
    )?;

    // Выполните запрос
    let result = session.execute(
        "SELECT * FROM logs ORDER BY id",
        Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]),
    )?;

    println!("Результаты запроса:\n{}", result.data_utf8()?);
    
    // Выведите статистику запроса
    println!("Прочитано строк: {}", result.rows_read());
    println!("Прочитано байт: {}", result.bytes_read());
    println!("Время выполнения запроса: {:?}", result.elapsed());

    Ok(())
}

Сборка и тестирование

Сборка проекта

cargo build

Запуск тестов

cargo test

Зависимости для разработки

В проекте используются следующие зависимости для разработки:

  • bindgen (v0.70.1) - генерация FFI-биндингов из заголовков C
  • tempdir (v0.3.7) - работа с временными каталогами в тестах
  • thiserror (v1) - утилиты для обработки ошибок

Обработка ошибок

chDB Rust предоставляет всестороннюю обработку ошибок с помощью перечисления Error:

use chdb_rust::{execute, error::Error};

match execute("SELECT 1", None) {
    Ok(result) => {
        println!("Успешно: {}", result.data_utf8()?);
    },
    Err(Error::QueryError(msg)) => {
        eprintln!("Ошибка запроса: {}", msg);
    },
    Err(Error::NoResult) => {
        eprintln!("Результат не получен");
    },
    Err(Error::NonUtf8Sequence(e)) => {
        eprintln!("Недопустимая последовательность UTF-8: {}", e);
    },
    Err(e) => {
        eprintln!("Другая ошибка: {}", e);
    }
}

Репозиторий на GitHub

Репозиторий проекта на GitHub доступен по адресу chdb-io/chdb-rust.