Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clickhouse-query-ext"
version = "1.0.0"
version = "1.0.1"
edition = "2024"
authors = ["Querya Community"]
description = "High-performance ClickHouse driver for Querya Desktop"
Expand Down
167 changes: 42 additions & 125 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,148 +1,65 @@
# 🚀 clickhouse-query-ext (Querya ClickHouse Database Extension)
# clickhouse-query-ext

[![Rust CI](https://github.com/QueryaHub/clickhouse-query-ext/actions/workflows/rust.yml/badge.svg)](https://github.com/QueryaHub/clickhouse-query-ext/actions/workflows/rust.yml)
[![Rust Edition](https://img.shields.io/badge/Edition-2024-brightgreen.svg)](https://doc.rust-lang.org/edition-guide/rust-2024/)
[![Protocol](https://img.shields.io/badge/Protocol-JSON--RPC%202.0%20over%20NDJSON%20%2F%20stdio-blue.svg)](#architecture)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**`clickhouse-query-ext`** — это высокопроизводительный, отказоустойчивый асинхронный драйвер и расширение СУБД [ClickHouse](https://clickhouse.com/) для платформы **Querya Desktop (Analyst Edition)**.
Драйвер построен на **Rust (Edition 2024)** и работает как изолированный подпроцесс (Zero-Trust Sandbox), взаимодействуя с хостом Querya через протокол **JSON-RPC 2.0 (NDJSON over `stdin` / `stdout`)**.

---

## 📐 Архитектурная схема расширения

```mermaid
graph LR
subgraph Querya [Querya Desktop Host]
UI[💻 Generative SDUI]
Bridge[🔌 Bridge Process Manager]
end

subgraph RustSandbox [clickhouse-query-ext (Rust Subprocess)]
Reader[📥 LineStream stdin] --> Router[🔄 JSON-RPC 2.0 Router]
Router --> Sys[⚙️ system.* Handshake / Ping / Secrets]
Router --> Conn[🔌 db.connect / disconnect]
Router --> Query[📊 db.query / execute / cancel]
Router --> Sdui[🎨 SDUI Tree & Form Schemas]

Sys --> Pool[🔒 ConnectionSecretsPool zeroize]
Query --> Safe[🛡️ Safe Mode AST Filter & Limits]
Sdui --> Parser[🌳 SYSTEM.* Introspection]

Router --> Writer[📤 NDJSON stdout Mutex]
Writer --> Bridge
end

Query -->|HTTP/HTTPS ClickHouse Client| CH[(🌐 ClickHouse Server)]
```
Расширение базы данных [ClickHouse](https://clickhouse.com/) для [Querya Desktop](https://github.com/QueryaHub). Устанавливается как `.qext`-пакет и добавляет ClickHouse в список подключений: форма настройки, дерево схемы, просмотр таблиц и SQL-редактор.

---
## Возможности

## ✨ Ключевые возможности и этапы реализации
- Подключение к ClickHouse по HTTP/HTTPS
- Дерево объектов: базы, таблицы, представления, колонки, партиции
- Выполнение SQL-запросов и просмотр результатов
- Аналитический режим (Safe Mode): ограничение опасных операций и лимиты на сессию
- Контекстные действия для таблиц и партиций (статистика, DDL, optimize и др.)

Все 6 этапов технического задания полностью реализованы, проверены и покрыты автоматическими тестами:
## Требования

### 1️⃣ Каркас, асинхронный I/O и NDJSON-транспорт ([Stage 1/6])
- Чтение потока `stdin` через асинхронный `tokio_util::codec::LinesCodec` без блокировки главного потока.
- Запись ответов в `stdout` через потокобезопасный `Mutex<Stdout>` с автоматической очисткой символов перевода строки (`\n`, `\r\n`), гарантирующая 100% валидный **NDJSON (Newline Delimited JSON)**.
- Разделение быстрых методов (`system.*` — задержка `< 5ms`) и тяжёлых SQL-выборок (выполняются в пуле задач `tokio::spawn`).
- Querya Desktop 2.0+
- Для сборки из исходников: Rust stable (1.85+)

### 2️⃣ Жизненный цикл, управление секретами и логирование ([Stage 2/6])
- **`system.handshake`**: обмен версиями и регистрация возможностей драйвера (`db.connect`, `db.query`, `db.getSchemaTree`, `sdui.contextActions` и др.).
- **`system.ping`**: Watchdog-таймер мгновенного ответа для предотвращения зависаний (`result: "pong"`).
- **`system.injectCredentials`**: передача паролей и JWT в изолированный `ConnectionSecretsPool`.
- **Защита памяти (`zeroize` & `secrecy`)**: пароли и токены хранятся в защищённой памяти и зануляются при удалении соединения или аварийном завершении (`clear_all`).
- **Санитазированный логгер ([src/utils/logger.rs](src/utils/logger.rs))**: все логи направляются исключительно в `stderr` с автоматическим маскированием паролей и HTTP-заголовков авторизации.
## Сборка

### 3️⃣ Исполнение SQL, конвертация типов и Safe Mode ([Stage 3/6])
- **`db.query` / `db.execute` / `db.cancelQuery`**: выполнение SQL-запросов через HTTP API ClickHouse с поддержкой стримингового парсинга формата `FORMAT JSONCompactEachRowWithNamesAndTypes`.
- **Конвертер типов ([src/mapper/types.rs](src/mapper/types.rs))**: полная поддержка `Int64/UInt64/Int128/UInt256`, `Decimal(P, S)`, `DateTime64`, `Array(T)`, `Tuple(...)`, `Map(K, V)`, `Nullable(T)` и `LowCardinality(T)`. Большие числа автоматически сериализуются в строки (`"18446744073709551615"`), предотвращая потерю точности в JS.
- **🛡️ Аналитический Safe Mode (Read-Only)**:
- Пре-фильтрация AST на стороне Rust (мгновенная блокировка `DROP DATABASE`, `TRUNCATE TABLE`, `ALTER ... DROP COLUMN` до отправки на сервер).
- Установка сессионных квот на сервере ClickHouse (`readonly=1`, `max_execution_time=300`, `max_memory_usage=10000000000`).
```bash
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo build --release
./scripts/package_qext.sh
```

### 4️⃣ Интроспекция схемы и ленивое дерево ([Stage 4/6])
- **`db.getSchemaTree` & `db.expandTreeNode`**: иерархическая навигация по объектам СУБД с поддержкой ленивой дозагрузки.
- Отображение баз данных (`SYSTEM.databases`), таблиц и представлений (`SYSTEM.tables`), словарей (`SYSTEM.dictionaries` с метриками `HitRate`), колонок (`SYSTEM.columns`) и партиций (`SYSTEM.parts` с расчётом количества строк и сжатого размера на диске).
Артефакты:

### 5️⃣ Генератор SDUI-форм и контекстные действия ([Stage 5/6])
- **`db.getConnectionFormSchema`**: генерация формы настройки подключения (`assets/connection_form.json`).
- **`sdui.contextActions` ([src/sdui/actions.rs](src/sdui/actions.rs))**: контекстное меню для аналитиков без написания DDL:
- **Для таблиц (`table`)**: выборка *Top 100 Rows*, *Column Statistics* (быстрый профайлер), *Optimize Table (FINAL)*, *Deduplicate*, *Show DDL*.
- **Для партиций (`partition`)**: *Drop Partition*, *Freeze Partition* (создание бэкапа/hardlink), *Detach Partition*.
- **Для баз данных (`database`, `view`)**: мониторинг активных мутаций (`SYSTEM.mutations`) и процессов (`SYSTEM.processes`).
| Файл | Назначение |
|------|------------|
| `target/release/clickhouse-query-ext` | Бинарник драйвера |
| `dist/clickhouse-query-ext-1.0.1.qext` | Пакет для установки в Querya Desktop |
| `dist/clickhouse-query-ext-1.0.1.qext.sha256` | Контрольная сумма |

### 6️⃣ Отказоустойчивость, автовосстановление и Panic Hook ([Stage 6/6])
- **`std::panic::set_hook`**: перехват любых паник Rust, вывод диагностического отчета в `stderr`, зануление всех секретов в памяти (`zeroize`) и завершение с кодом **`101`** для корректного запуска экспоненциального backoff-перезапуска (`SandboxAutoRecovery`).
- Проверка и восстановление структуры scratch-директорий (`ensure_scratch_directories`) при каждом запуске драйвера.
Установка: **Querya Desktop → Extensions → Install from file** → выбрать `.qext`.

---
## Кросс-компиляция

## 🛠️ Сборка и тестирование
```bash
./scripts/build_cross.sh x86_64-unknown-linux-gnu
./scripts/package_qext.sh --target x86_64-unknown-linux-gnu
```

### Требования
- **Rust toolchain:** `stable` (edition 2024, Rust 1.85+)
- **OS:** Linux / macOS / Windows
Поддерживаемые цели: `x86_64-unknown-linux-gnu`, `aarch64-apple-darwin`, `x86_64-pc-windows-msvc`.

### Команды сборки и проверки
## Релиз

Тег `v*` запускает GitHub Actions: сборка для всех платформ и публикация `.qext` в Releases.

```bash
# Проверка форматирования
cargo fmt --all -- --check
git tag v1.0.1
git push origin v1.0.1
```

# Запуск строгого линтера
cargo clippy --all-targets --all-features -- -D warnings
## Документация

# Запуск полного комплекта unit- и интеграционных тестов (48+ тестов)
cargo test --verbose --all
Подробная спецификация RPC, SDUI и аналитических функций — в каталоге [`docs/`](docs/).

# Сборка релизного бинарного файла драйвера
cargo build --release
```
## Лицензия

После успешной сборки исполняемый файл будет доступен по пути `target/release/clickhouse-query-ext`.

---

## 📋 Спецификация JSON-RPC методов

| Метод | Описание | Назначение |
| :--- | :--- | :--- |
| `system.handshake` | Обмен версиями и `capabilities` | Инициализация сессии Querya Host ↔ Rust |
| `system.ping` | Watchdog heartbeat | Быстрая проверка жизнеспособности (`< 5ms`) |
| `system.injectCredentials` | Передача пароля/JWT | Безопасное сохранение в In-Memory Pool |
| `system.shutdown` | Завершение работы | Очистка памяти и выход с кодом `0` |
| `db.connect` | Создание HTTP-клиента | Инициализация TLS и проверка соединения |
| `db.disconnect` | Закрытие сессии | Удаление клиента из глобального пула |
| `db.query` | Выборка строк (`SELECT`) | Возврат `RowCompact` с маппингом типов |
| `db.execute` | Выполнение DDL/DML | Возврат количества затронутых строк (`affectedRows`) |
| `db.cancelQuery` | Отмена запроса (`KILL QUERY`) | Остановка долгих вычислений по `query_id` |
| `db.getSchemaTree` | Список баз данных | Корневой уровень SDUI-дерева |
| `db.expandTreeNode` | Разворачивание узла | Подгрузка таблиц, вьюх, колонок и партиций |
| `db.getConnectionFormSchema`| Форма подключения | Отдача JSON-схемы настроек СУБД |
| `sdui.contextActions` | Контекстное меню | Генерация аналитических команд для UI |

---

## 👥 Структура репозитория

```text
clickhouse-query-ext/
├── assets/
│ ├── connection_form.json # JSON-схема формы подключения
│ └── icon.svg # Иконка расширения
├── docs/
│ ├── 01_TZ_RUST_ARCHITECTURE.md
│ └── 02_CLICKHOUSE_ANALYST_FEATURES.md
├── src/
│ ├── main.rs # Точка входа, инициализация Sandbox и асинхронный цикл
│ ├── error.rs # Доменные ошибки DriverError и маппинг в коды JSON-RPC (-3260x)
│ ├── transport/ # Асинхронный NDJSON-транспорт (stdio.rs, framing.rs)
│ ├── rpc/ # Роутер и обработчики JSON-RPC 2.0
│ ├── driver/ # HTTP/TLS клиент, пул соединений, настройки сессий
│ ├── mapper/ # Парсер типов ClickHouse и Row Format
│ ├── sdui/ # Generative SDUI: дерево, формы и контекстные действия
│ └── utils/ # Panic hook, recovery, zeroize секреты, санитазированный логгер
└── manifest.json # Манифест расширения для Querya Desktop
```
MIT
8 changes: 8 additions & 0 deletions assets/connection_form.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
"required": true,
"defaultValue": "default"
},
{
"key": "database",
"label": "База данных по умолчанию",
"type": "text",
"required": false,
"defaultValue": "default",
"helperText": "Имя базы ClickHouse для подключения и дерева схемы"
},
{
"key": "password",
"label": "Пароль",
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "queryahub.clickhouse-driver",
"name": "ClickHouse Database Driver (Analyst Edition)",
"version": "1.0.0",
"version": "1.0.1",
"publisher": "Querya Community",
"description": "Изолированный нативный Rust-драйвер для аналитической СУБД ClickHouse с полной поддержкой MergeTree, словарей, партиций и SDUI-интроспекции.",
"type": "database_driver",
Expand Down
4 changes: 4 additions & 0 deletions scripts/package_qext.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ cp "${BIN_PATH}" "${STAGING_DIR}/bin/${DEST_BIN_NAME}"
if [ "${DEST_BIN_NAME}" != "${BIN_NAME}" ] && [ ! -f "${STAGING_DIR}/bin/${BIN_NAME}" ]; then
cp "${BIN_PATH}" "${STAGING_DIR}/bin/${BIN_NAME}"
fi
chmod +x "${STAGING_DIR}/bin/${DEST_BIN_NAME}"
if [ -f "${STAGING_DIR}/bin/${BIN_NAME}" ]; then
chmod +x "${STAGING_DIR}/bin/${BIN_NAME}"
fi

# 3. Create .qext (.zip) archive using python zipfile module or zip CLI
ARCHIVE_NAME="clickhouse-query-ext-${VERSION}-${TARGET}.qext"
Expand Down
Loading
Loading