feat(clients): add nim-allographer client with BaraDB driver support
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled

- Pure Nim wire protocol client (async + sync, no C FFI)
- Query Builder: fluent API, SQL generator, execution, transactions
- Schema Builder: create/alter/drop tables, column operations
- Connection pool with aging and timeout handling
- ORM integration via compile-time DB_BARADB switch
- Tests: test_open, test_query
- Documentation: README.md, PLAN_BARADB.md
This commit is contained in:
2026-05-21 15:49:11 +03:00
parent 2d310a33a1
commit 6bfc5b3a3c
654 changed files with 109419 additions and 0 deletions
+353
View File
@@ -0,0 +1,353 @@
# План за интеграция на BaraDB в nim-allographer
## Цел
**BaraDB** е пълноценен драйвер в `nim-allographer`. Използва се чист Nim клиент (`BaraClient` / `SyncClient`) без C зависимости. Compile-time switch: `DB_BARADB`.
---
## Актуално състояние (2026-05-21)
### Статус по фази
| Фаза | Състояние | Бележки |
|------|-----------|---------|
| 1. Инфраструктура и типове | **ГОТОВО** | `env.nim`, `connection.nim`, `query_builder.nim`, `schema_builder.nim` — всичко е интегрирано |
| 2. Query Builder — SQL генерация | **ГОТОВО** | `baradb_generator.nim` (397 реда), `baradb_builder.nim` (237 реда) — всички CRUD + агрегати |
| 3. Query Builder — execution | **ГОТОВО** (с бележки) | `baradb_exec.nim` (716 реда) — всички операции работят, но `insertId` използва `SELECT MAX` вместо `RETURNING` |
| 4. Schema Builder | **СКЕЛЕТ** | Flow-ът е налице, но column type mapping е 24 реда вместо 466 (PostgreSQL) |
| 5. Тестове и документация | **МИНИМАЛНО** | Само `test_open.nim` и `test_query.nim` |
---
## Какво е ГОТОВО (не пипай)
### Wire Protocol клиент — `query_builder/libs/baradb/baradb_client.nim` (706 реда)
- Pure Nim, async + sync, без C FFI
- Binary serialization (big-endian) на всички `WireValue` типове (13 типа: fkNull..fkJson)
- `mkQuery`, `mkQueryParams`, `mkAuth`, `mkPing` съобщения
- `readQueryResponse` — парсва `mkData`, `mkComplete`, `mkError`, `mkReady`
- Вграден `QueryBuilder` (fluent) за standalone употреба
### Connection Pool — `baradb_open.nim` + `baradb_exec.nim`
- `dbOpen(Baradb, database, user, pass, host, port, maxConnections, timeout)`
- `getFreeConn()` — async с deque-based waiters и timeout
- `returnConn()` — освобождава и буди чакащи
- Connection aging: `maxConnectionLifetime`, `maxConnectionIdleTime`
- `refreshConn()`, `hasConnExpired()`, `openBaradbConn()`
### Query Builder — `baradb_query.nim` (386 реда)
- Всички fluent методи: `select`, `table`, `distinct`, `join`, `leftJoin`
- `where` / `orWhere` (string|int|float, bool, nil overloads)
- `whereBetween`, `whereNotBetween`, `whereIn`, `whereNotIn`, `whereNull`
- `groupBy`, `having`, `orderBy`, `limit`, `offset`
- `raw(sql, args)` — суров SQL с параметри
### SQL Generator — `baradb_generator.nim` (397 реда)
- Всички SQL конструкции: SELECT, INSERT, UPDATE, DELETE, агрегати
- Quoting с backtick `` ` `` (MySQL/SQLite стил, **не** PostgreSQL `"`)
- Placeholder: `?` (не `$1`)
### Execution — `baradb_exec.nim` (716 реда)
- `get()`, `first()`, `find()``seq[JsonNode]` / `Option[JsonNode]`
- `getPlain()`, `firstPlain()`, `findPlain()``seq[seq[string]]`
- `insert(JsonNode)`, `insert(seq[JsonNode])`, `insertId(...)`
- `update(JsonNode)`, `delete()`, `delete(id)`
- `count()`, `min()`, `max()`, `avg()`, `sum()`
- `begin()`, `commit()`, `rollback()` + `transaction` макро
- Raw query варианти за всички операции
- `seeder` шаблони
### ORM — споделен модул
- `orm()` template работи с BaraDB
### Schema Code Generation — `usecases/baradb/create_schema.nim`
- Четене от `information_schema` и генериране на Nim типове
---
## Какво трябва да се ДОИЗПИПА
### 1. Prepared Statements — САМО типове, НЯМА имплементация
**Текущо състояние:** Типовете са дефинирани в `baradb_types.nim`:
- `BaradbPreparedEntry``sql`, `nArgs`, `refCount`, `lastUsedAt`
- `BaradbPreparedContext``owner`, `connI`
- `BaradbPreparedStatement``owner`, `entry`, `sql`, `nArgs`, `isClosed`
- `preparedCache` е инициализиран в `baradb_open.nim`
**Липсващо:**
- `prepare()` proc — да създава `BaradbPreparedStatement`
- `ensureStmt()` — да кешира и преизползва statement-и
- `get*()` / `exec*()` procs върху `BaradbPreparedStatement`
- `withConn()` proc за context-based изпълнение
- `flushStmt()` / `clearStmtCache()`
**Wire protocol поддръжка:** `baradb_client.nim` вече има `mkQueryParams` — параметризираните заявки са вградени на ниво протокол. Трябва само да се свърже от allographer слоя.
**Проблем:** В момента `baradb_exec.nim` използва **client-side string interpolation** (`formatSql` + `escapeSqlValue`) вместо server-side параметри. Това е по-малко сигурно и по-малко ефективно.
**Референция:** PostgreSQL драйверът има ~300 реда prepared statement код (`postgres_exec.nim``ensureStmt`, `preparedQuery`, `preparedExec`, `deallocate`, `flush`, `clearCache`, context API).
**План:**
```
Файл: baradb_exec.nim
- [ ] prepare(sql: string): BaradbPreparedStatement
- [ ] ensureStmt(conn, sql, nArgs): BaradbPreparedEntry — кеширане в preparedCache
- [ ] preparedGet(stmt, args): seq[JsonNode] — използва mkQueryParams
- [ ] preparedExec(stmt, args): void
- [ ] withConn(pool, callback): auto — context-based
- [ ] flushStmt(stmt): void — deallocate
- [ ] clearStmtCache(): void
```
---
### 2. RETURNING id за INSERT — използва SELECT MAX (race condition)
**Текущо състояние в `baradb_exec.nim`:**
```nim
discard await self.pools.conns[connI].client.exec(sql)
let idSql = &"SELECT MAX(\"{key}\") FROM \"{table}\""
let qr = await self.pools.conns[connI].client.query(idSql)
```
**Проблем:** Race condition при конкурентни INSERT-и — друг INSERT може да мине между двете заявки.
**Варианти:**
1. **`INSERT ... RETURNING id`** — ако BaraDB го поддържа (за предпочитане, атомарно)
2. **`last_insert_rowid()`** — ако BaraDB има такава функция (както SQLite)
3. **`SELECT LAST_INSERT_ID()`** — MySQL-стил
4. **CTE с `INSERT ... RETURNING`**`WITH inserted AS (INSERT ...) SELECT id FROM inserted`
**План:**
```
Файл: baradb_exec.nim — insertId proc
- [ ] Проверка дали BaraDB поддържа RETURNING
- [ ] Ако да: INSERT ... RETURNING "id" (като PostgreSQL)
- [ ] Ако не: използване на заявката за последно вмъкнат ID от wire protocol-а
- [ ] Премахване на SELECT MAX workaround
```
---
### 3. Schema Builder — Column Type Mapping е СКЕЛЕТ
**Текущо състояние в `queries/baradb/sub/create_column_query.nim` (24 реда):**
```nim
query.add(&"`{column.name}` {column.typ}")
# Само: NOT NULL, UNIQUE, DEFAULT
```
**Проблем:** Изкарва raw `RdbTypeKind` enum стойности (`rdbIncrements`, `rdbString`) вместо SQL типове (`SERIAL`, `VARCHAR(256)`).
**Референция:** PostgreSQL `sub/create_column_query.nim`**466 реда**, обработва всички `RdbTypeKind`:
- `rdbIncrements``SERIAL PRIMARY KEY`
- `rdbBigIncrements``BIGSERIAL PRIMARY KEY`
- `rdbInteger``INTEGER`
- `rdbBigInteger``BIGINT`
- `rdbBoolean``BOOLEAN`
- `rdbString(n)``VARCHAR(n)` (default 255)
- `rdbText``TEXT`
- `rdbFloat``DOUBLE PRECISION`
- `rdbDecimal(p,s)``DECIMAL(p,s)`
- `rdbDate``DATE`
- `rdbDateTime` / `rdbTimestamp``TIMESTAMP`
- `rdbTimestampz``TIMESTAMPTZ`
- `rdbTime``TIME`
- `rdbBinary``BYTEA`
- `rdbUuid``UUID`
- `rdbJson` / `rdbJsonb``JSON` / `JSONB`
- `rdbEnum``VARCHAR(255)` + CHECK constraint
- Foreign keys: `REFERENCES "table"("column") ON DELETE/UPDATE CASCADE/SET NULL/...`
- Indexes, comments, unsigned
**План:**
```
Файл: queries/baradb/sub/create_column_query.nim
- [ ] Пълен mapping на RdbTypeKind → SQL тип (по PostgreSQL референцията)
- [ ] Auto-increment: SERIAL / BIGSERIAL PRIMARY KEY
- [ ] String/Text: VARCHAR(n), TEXT с default 255
- [ ] Числови: INTEGER, BIGINT, SMALLINT, DOUBLE PRECISION, DECIMAL(p,s)
- [ ] Дати: DATE, TIME, TIMESTAMP, TIMESTAMPTZ
- [ ] Бинарни: BYTEA
- [ ] Специални: UUID, JSON, JSONB, BOOLEAN, ENUM
- [ ] Foreign key constraints: REFERENCES ... ON DELETE/UPDATE
- [ ] Index генерация
- [ ] Column comments
Файл: queries/baradb/create_table.nim
- [ ] Да използва create_column_query вместо raw {column.typ}
Файлове: rename_column.nim, rename_table.nim
- [ ] Fix: `changeTo` → `previousName` (ако е bug)
Файл: create_migration_table.nim
- [ ] Консистентност: backtick quoting вместо double-quote
Файл: schema_utils.nim
- [ ] shouldRun() — checksum-based skip (вместо винаги true)
```
---
### 4. SQL Quoting Inconsistency
**Проблем:** `baradb_generator.nim` използва backtick `` ` ``, но `create_migration_table.nim` използва double-quote `"`. Трябва да е консистентно.
**Въпрос:** Какво използва BaraDB сървърът? Ако поддържа и двете — изберем едно. Ако само едно — коригираме навсякъде.
---
### 5. Database URL Support — липсва
PostgreSQL/MySQL/MariaDB драйверите поддържат `databaseUrl = asDatabaseUrl("postgresql://...")`. BaraDB `dbOpen` приема само позиционни параметри.
```
Файл: baradb_open.nim
- [ ] Парсване на `baradb://user:pass@host:port/db` URL
- [ ] Интеграция с `libs/database_url.nim`
```
---
### 6. Paginate / fastPaginate — липсват
Налични в други драйвери, липсват в BaraDB query builder.
```
Файл: baradb_exec.nim
- [ ] paginate(page, perPage): seq[JsonNode] + metadata
- [ ] fastPaginate(key, perPage): cursor-based
```
---
### 7. whereNull Bug
**Проблем:** `baradb_generator.nim:205` — `whereNullSql` референцира `row["symbol"]`, но `baradb_query.nim` `whereNull` не задава `"symbol"` ключ. Ще даде runtime crash.
```
Файл: baradb_query.nim — whereNull proc
- [ ] Добавяне на "symbol": "IS" или "IS NOT" в JSON а
```
---
## Тестове — какво липсва
| Тестов файл | Съществува за | Липсва за BaraDB |
|-------------|--------------|------------------|
| `test_open.nim` | postgres, sqlite, mysql, mariadb, surreal, **baradb** | — |
| `test_query.nim` | postgres, sqlite, mysql, mariadb, surreal, **baradb** | — |
| `test_prepared_statement.nim` | postgres, sqlite, mysql, mariadb, surreal | **baradb** |
| `test_schema.nim` | postgres, sqlite, mysql, mariadb, surreal | **baradb** |
| `test_create_schema.nim` | postgres, sqlite, mysql, mariadb, surreal | **baradb** |
| `test_pool_wait.nim` | postgres | **baradb** |
| `test_transaction.nim` | postgres, sqlite, mysql, mariadb, surreal | **baradb** |
---
## Приоритети
| # | Подобрение | Сложност | Ефект | Приоритет |
|---|-----------|----------|-------|-----------|
| 1 | Schema Builder column mapping | Средна | Без него migrations не работят | **ВИСОК** |
| 2 | INSERT RETURNING id | Ниска | Премахва race condition | **ВИСОК** |
| 3 | Prepared Statements | Висока | Security + performance | **СРЕДЕН** |
| 4 | Database URL support | Ниска | UX удобство | **НИСЪК** |
| 5 | Paginate / fastPaginate | Ниска | Feature parity | **НИСЪК** |
| 6 | whereNull fix | Ниска | Bug fix | **ВИСОК** |
| 7 | SQL quoting консистентност | Ниска | Потенциален runtime error | **СРЕДЕН** |
| 8 | Schema utils checksum | Ниска | Migration skip optimization | **НИСЪК** |
---
## Архитектура — файлова карта
```
src/allographer/
├── env.nim # DB_BARADB compile switch ✅
├── connection.nim # Import/export Baradb типове ✅
├── query_builder.nim # Import/export baradb модули ✅
├── schema_builder.nim # Import/export baradb schema ✅
├── query_builder/
│ ├── libs/baradb/
│ │ └── baradb_client.nim # Wire protocol (706 реда) ✅
│ │
│ └── models/baradb/
│ ├── baradb_types.nim # Типове (90 реда) ✅
│ ├── baradb_open.nim # dbOpen + pool (52 реда) ✅
│ ├── baradb_query.nim # Fluent API (386 реда) ✅
│ ├── baradb_exec.nim # Execution (716 реда) ✅⚠️
│ ├── baradb_transaction.nim # Transaction макро (42 реда) ✅
│ └── query/
│ ├── baradb_builder.nim # SQL builder (237 реда) ✅
│ └── baradb_generator.nim # SQL generator (397 реда) ✅
├── schema_builder/
│ ├── queries/baradb/
│ │ ├── baradb_query_type.nim # Типове (14 реда) ✅
│ │ ├── create_table.nim # CREATE TABLE (16 реда) ⚠️ skeletal
│ │ ├── add_column.nim # ADD COLUMN (8 реда) ⚠️ minimal
│ │ ├── change_column.nim # ALTER COLUMN (8 реда) ⚠️ minimal
│ │ ├── drop_column.nim # DROP COLUMN (8 реда) ✅
│ │ ├── drop_table.nim # DROP TABLE (7 реда) ✅
│ │ ├── rename_column.nim # RENAME COLUMN (8 реда) ⚠️ possible bug
│ │ ├── rename_table.nim # RENAME TABLE (7 реда) ⚠️ possible bug
│ │ ├── reset_table.nim # DELETE FROM (7 реда) ✅
│ │ ├── create_migration_table.nim (12 реда) ⚠️ quoting inconsistency
│ │ ├── schema_utils.nim # shouldRun (12 реда) ⚠️ always true
│ │ └── sub/
│ │ ├── create_column_query.nim # (24 реда) ❌ skeletal
│ │ ├── add_column_query.nim # (8 реда) ⚠️ minimal
│ │ └── change_column_query.nim # (6 реда) ⚠️ minimal
│ │
│ └── usecases/baradb/
│ ├── create.nim # Table creation flow (24 реда) ✅
│ ├── alter.nim # Alter flow (45 реда) ✅
│ ├── drop.nim # Drop flow (18 реда) ✅
│ ├── create_schema.nim # Code gen from DB (60 реда) ✅
│ └── create_query_def.nim # Factory (10 реда) ✅
tests/baradb/
├── config.nims # DB_BARADB=true ✅
├── connections.nim # Connection setup ✅
├── test_open.nim # Basic connection test ✅
├── test_query.nim # Integration tests ✅
├── test_prepared_statement.nim # ❌ липсва
├── test_schema.nim # ❌ липсва
├── test_create_schema.nim # ❌ липсва
├── test_pool_wait.nim # ❌ липсва
└── test_transaction.nim # ❌ липсва
```
**Легенда:** ✅ готово | ⚠️ partial/needs work | ❌ липсва | ✅⚠️ работи но с workaround
---
## Краткосрочен план (следващи стъпки)
### Седмица 1: Schema Builder + Bug fixes
1. `sub/create_column_query.nim` — пълен RdbTypeKind → SQL mapping (по PostgreSQL референция)
2. `create_table.nim` — да използва column query вместо raw тип
3. Fix `whereNull` bug в `baradb_query.nim`
4. Fix quoting inconsistency в `create_migration_table.nim`
5. Fix `rename_column.nim` / `rename_table.nim` ако `changeTo` не съществува
### Седмица 2: INSERT RETURNING + Prepared Statements (част 1)
1. `insertId` — проучване дали BaraDB поддържа RETURNING, имплементация
2. `prepare()` / `ensureStmt()` — prepared statement кеш
3. `preparedGet()` / `preparedExec()` — изпълнение през `mkQueryParams`
### Седмица 3: Тестове + Prepared Statements (част 2)
1. `test_schema.nim` — schema builder тестове
2. `test_prepared_statement.nim` — prepared statement тестове
3. `test_transaction.nim` — transaction тестове
4. `test_pool_wait.nim` — pool timeout тестове
### Седмица 4: Polish
1. Database URL support
2. Paginate / fastPaginate
3. Schema utils checksum
4. Документация в `documents/`