feat: migrate system + cross-DB engine + IMPORT/EXPORT syntax -- 22 files, client+server+docs
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
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
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
# BaraDB Migration System — Ръководство
|
||||
|
||||
## Общ преглед
|
||||
|
||||
BaraDB има вградена миграционна система чрез BaraQL. Миграциите се управляват
|
||||
изцяло от сървъра — checksums, locking, rollback, status tracking. Клиентът
|
||||
(nim-allographer) изпраща BaraQL команди и не поддържа собствена миграционна
|
||||
таблица.
|
||||
|
||||
## BaraQL миграционен синтаксис
|
||||
|
||||
```sql
|
||||
-- Създаване на миграция с UP и DOWN скриптове
|
||||
CREATE MIGRATION add_users_table {
|
||||
UP: CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) UNIQUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
DOWN: DROP TABLE IF EXISTS users;
|
||||
}
|
||||
|
||||
-- Прилагане на конкретна миграция
|
||||
APPLY MIGRATION add_users_table
|
||||
|
||||
-- Прилагане на всички неприложени миграции
|
||||
MIGRATION UP
|
||||
|
||||
-- Прилагане на следващите N миграции
|
||||
MIGRATION UP 3
|
||||
|
||||
-- Отмяна на последната миграция (rollback)
|
||||
MIGRATION DOWN
|
||||
|
||||
-- Отмяна на последните N миграции
|
||||
MIGRATION DOWN 2
|
||||
|
||||
-- Преглед на статуса на всички миграции
|
||||
MIGRATION STATUS
|
||||
|
||||
-- Dry run — проверка без изпълнение
|
||||
MIGRATION DRY RUN add_users_table
|
||||
```
|
||||
|
||||
## Nim API (nim-allographer)
|
||||
|
||||
### Свързване
|
||||
|
||||
```nim
|
||||
import allographer/connection
|
||||
import allographer/query_builder
|
||||
|
||||
# Стандартно свързване
|
||||
let rdb = dbOpen(Baradb, "mydb", "admin", "", "127.0.0.1", 9472)
|
||||
|
||||
# Или чрез URL
|
||||
let rdb = dbOpen(Baradb, asDatabaseUrl("baradb://admin@127.0.0.1:9472/mydb"))
|
||||
```
|
||||
|
||||
### Управление на миграции
|
||||
|
||||
```nim
|
||||
import allographer/query_builder/models/baradb/baradb_exec
|
||||
|
||||
# Създаване на миграция
|
||||
let upSql = """
|
||||
CREATE TABLE products (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
price DECIMAL(10,2)
|
||||
)
|
||||
"""
|
||||
let downSql = "DROP TABLE IF EXISTS products"
|
||||
let qr = waitFor rdb.createMigration("add_products", upSql, downSql)
|
||||
|
||||
# Прилагане на миграция
|
||||
let qr = waitFor rdb.applyMigration("add_products")
|
||||
|
||||
# Прилагане на всички неприложени
|
||||
let qr = waitFor rdb.migrateUp()
|
||||
|
||||
# Rollback
|
||||
let qr = waitFor rdb.migrateDown(1)
|
||||
|
||||
# Проверка на статус
|
||||
let status = waitFor rdb.migrationStatus()
|
||||
for row in status:
|
||||
echo row["name"].getStr, " → ", row["status"].getStr
|
||||
|
||||
# Проверка дали миграция е приложена
|
||||
if waitFor rdb.isMigrationApplied("add_products"):
|
||||
echo "Migration already applied"
|
||||
|
||||
# Dry run
|
||||
let qr = waitFor rdb.migrationDryRun("add_products")
|
||||
echo $qr
|
||||
```
|
||||
|
||||
### Schema Builder (автоматични миграции)
|
||||
|
||||
```nim
|
||||
import allographer/schema_builder
|
||||
import allographer/query_builder
|
||||
|
||||
let rdb = dbOpen(Baradb, "mydb", "admin", "", "127.0.0.1", 9472)
|
||||
|
||||
# Дефиниране на таблица
|
||||
let usersTable = table("users", [
|
||||
Column.increments("id"),
|
||||
Column.string("name"),
|
||||
Column.string("email").unique(),
|
||||
Column.integer("age").nullable(),
|
||||
Column.timestamps()
|
||||
])
|
||||
|
||||
# Създаване (автоматично генерира CREATE MIGRATION)
|
||||
rdb.create(usersTable)
|
||||
|
||||
# Промяна
|
||||
let alteredTable = table("users", [
|
||||
Column.string("phone").nullable().add() # добавяне на колона
|
||||
])
|
||||
rdb.alter(alteredTable)
|
||||
|
||||
# Изтриване
|
||||
rdb.drop(usersTable)
|
||||
```
|
||||
|
||||
### Prepared Statements
|
||||
|
||||
```nim
|
||||
import allographer/query_builder/models/baradb/baradb_exec
|
||||
|
||||
# Подготовка на statement (кешира се)
|
||||
let stmt = waitFor rdb.prepare(
|
||||
"SELECT * FROM users WHERE age > ? AND status = ?", nArgs = 2
|
||||
)
|
||||
|
||||
# Изпълнение с параметри
|
||||
let youngAdmins = waitFor stmt.preparedGet(@[
|
||||
WireValue(kind: fkInt32, int32Val: 18),
|
||||
WireValue(kind: fkString, strVal: "active")
|
||||
])
|
||||
|
||||
# Execute (INSERT/UPDATE/DELETE)
|
||||
let affected = waitFor stmt.preparedExec(@[
|
||||
WireValue(kind: fkInt32, int32Val: 21),
|
||||
WireValue(kind: fkString, strVal: "pending")
|
||||
])
|
||||
|
||||
# Освобождаване
|
||||
stmt.flushStmt()
|
||||
|
||||
# Изчистване на целия кеш
|
||||
rdb.clearStmtCache()
|
||||
```
|
||||
|
||||
### Pagination
|
||||
|
||||
```nim
|
||||
# Offset-based
|
||||
let page1 = waitFor rdb.table("users")
|
||||
.orderBy("id", Asc)
|
||||
.paginate(page = 1, perPage = 20)
|
||||
echo page1.rows.len # 20
|
||||
echo page1.total # 150
|
||||
echo page1.hasMore # true
|
||||
|
||||
# Cursor-based (по-бързо за големи таблици)
|
||||
let batch = waitFor rdb.table("users")
|
||||
.fastPaginate("id", perPage = 100, afterId = "42")
|
||||
echo batch.hasMore
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cross-DB Migration Engine
|
||||
|
||||
Мигриране на данни от PostgreSQL, MySQL, MariaDB, SQLite или SurrealDB към BaraDB.
|
||||
|
||||
### Поддържани source бази
|
||||
|
||||
| База | Статус | Schema extraction |
|
||||
|------|--------|-------------------|
|
||||
| PostgreSQL | ✅ | `information_schema` |
|
||||
| MySQL | ✅ | `information_schema` |
|
||||
| MariaDB | ✅ | `information_schema` |
|
||||
| SQLite | ✅ | `sqlite_master` + `PRAGMA` |
|
||||
| SurrealDB | ✅ | `INFO FOR DB` / `INFO FOR TABLE` |
|
||||
|
||||
### API
|
||||
|
||||
```nim
|
||||
import allographer/migrate_data
|
||||
|
||||
# Свързване към source и target
|
||||
let pg = dbOpen(PostgreSQL, "sourcedb", "user", "pass", "localhost", 5432)
|
||||
let bdb = dbOpen(Baradb, "targetdb", "admin", "", "127.0.0.1", 9472)
|
||||
|
||||
# Мигриране на всички таблици
|
||||
let report = waitFor migrate(pg, bdb, batchSize = 5000)
|
||||
echo report
|
||||
# Migration: PostgreSQL → BaraDB
|
||||
# Tables: 12/12
|
||||
# Rows: 45230
|
||||
# Time: 3.2s
|
||||
|
||||
# Мигриране само на конкретни таблици
|
||||
let report = waitFor migrate(pg, bdb, tables = @["users", "orders", "products"])
|
||||
```
|
||||
|
||||
### Как работи
|
||||
|
||||
1. **Schema extraction** — чете структурата на таблиците от source базата
|
||||
2. **Type mapping** — мапва типовете към BaraDB еквиваленти:
|
||||
- `SERIAL` → `SERIAL`
|
||||
- `VARCHAR(n)` → `VARCHAR(n)`
|
||||
- `TEXT` → `TEXT`
|
||||
- `JSONB` → `JSON`
|
||||
- `BOOLEAN` → `BOOLEAN`
|
||||
- и още 50+ типа
|
||||
3. **DDL генерация** — създава `CREATE MIGRATION` с UP/DOWN скриптове
|
||||
4. **Data transfer** — чете данни на batch-ове и ги вмъква в BaraDB
|
||||
5. **Progress tracking** — връща `MigrationReport` с детайли
|
||||
|
||||
---
|
||||
|
||||
## IMPORT FROM / EXPORT TO (BaraQL)
|
||||
|
||||
```sql
|
||||
-- Импорт от CSV
|
||||
IMPORT FROM '/data/users.csv' INTO users
|
||||
FORMAT CSV
|
||||
DELIMITER ','
|
||||
HEADER true
|
||||
BATCH 1000
|
||||
|
||||
-- Импорт от JSON
|
||||
IMPORT FROM '/data/users.json' INTO users
|
||||
FORMAT JSON
|
||||
|
||||
-- Импорт от NDJSON (newline-delimited JSON)
|
||||
IMPORT FROM '/data/users.ndjson' INTO users
|
||||
FORMAT NDJSON
|
||||
|
||||
-- Експорт към CSV
|
||||
EXPORT TO '/backup/users.csv' FROM users
|
||||
FORMAT CSV
|
||||
DELIMITER ','
|
||||
HEADER true
|
||||
|
||||
-- Експорт към JSON
|
||||
EXPORT TO '/backup/users.json' FROM users
|
||||
FORMAT JSON
|
||||
```
|
||||
|
||||
### Поддържани формати
|
||||
|
||||
| Формат | Import | Export | Опции |
|
||||
|--------|--------|--------|-------|
|
||||
| CSV | ✅ | ✅ | DELIMITER, HEADER, BATCH |
|
||||
| JSON | ✅ | ✅ | — |
|
||||
| NDJSON | ✅ | ✅ | — |
|
||||
|
||||
---
|
||||
|
||||
## Често задавани въпроси
|
||||
|
||||
### Мога ли да мигрирам от SQLite директно към BaraDB?
|
||||
|
||||
Да. Свържете се към SQLite файла и използвайте `migrate()`:
|
||||
|
||||
```nim
|
||||
let sqlite = dbOpen(SQLite3, "mydb.sqlite")
|
||||
let bdb = dbOpen(Baradb, "mydb", "admin", "", "127.0.0.1", 9472)
|
||||
let report = waitFor migrate(sqlite, bdb)
|
||||
```
|
||||
|
||||
### Какво става ако миграцията се прекъсне?
|
||||
|
||||
BaraDB сървърът поддържа transaction safety. Всяка миграция се изпълнява в
|
||||
рамките на една транзакция. При грешка:
|
||||
- DDL промените се отменят автоматично
|
||||
- `MIGRATION STATUS` показва кои миграции са applied и кои не
|
||||
- Може да продължите от последната успешна миграция
|
||||
|
||||
### Как да проверя какви миграции са приложени?
|
||||
|
||||
```nim
|
||||
let status = waitFor rdb.migrationStatus()
|
||||
for row in status:
|
||||
echo &"{row[\"name\"]} → {row[\"status\"]} ({row[\"applied_at\"]})"
|
||||
```
|
||||
|
||||
Или чрез BaraQL:
|
||||
```sql
|
||||
MIGRATION STATUS
|
||||
```
|
||||
|
||||
### Поддържат ли се foreign key зависимости при cross-DB миграция?
|
||||
|
||||
Да. `migrate_data.nim` запазва foreign key дефинициите в генерирания DDL.
|
||||
Препоръчва се таблиците без foreign key зависимости да се мигрират първи.
|
||||
|
||||
### Как се прави backup преди миграция?
|
||||
|
||||
```sql
|
||||
-- Експортирайте данните преди миграция
|
||||
EXPORT TO '/backup/before_migration.csv' FROM users FORMAT CSV
|
||||
|
||||
-- Или използвайте backup manager-а
|
||||
-- (backup restore list verify cleanup)
|
||||
```
|
||||
Reference in New Issue
Block a user