- SET var = value / current_setting('var') for session-scoped variables
- current_user / current_role SQL keywords with auth bridge
- server.nim + httpserver.nim populate ExecutionContext.currentUser/currentRole
- RLS policies can reference current_setting('app.tenant_id') for tenant isolation
- Fixed evalExpr to propagate ctx recursively (fixes current_user in sub-expressions)
- Fixed GROUPING SETS execution (lowerSelect checks selGroupingSetsKind)
- Fixed FTS CREATE INDEX docId mismatch (hash of tableName.$key)
- Fixed all test suites to use isolated temp directories
- Added 5 multi-tenant tests (355 total, all green)
- Updated docs: PLAN_SQL_ADVANCED.md, baraql.md, changelog.md
17 KiB
BaraDB — Универсален план за Advanced SQL Engine
Визия: BaraDB е самостоятелен, универсален SQL engine с Nim ядро, поддържащ модерни SQL:2023 разширения — Property Graph, Vector Search, JSON документи и прозоречни функции, в една вградена или клиент/сървър конфигурация.
Принцип: Само основи. Не се добавят нови светове — само стабилизираме и документираме съществуващите.
Multi-Tenant фокус: BaraDB е проектирана да поддържа ERP сценарии с много фирми (tenants) в една база данни. Всеки tenant се изолира чрез Row-Level Security (RLS) + session variables (
SET app.tenant_id = 'X'), а не чрез отделни бази.
История на разработката
- Фаза 1 (Base SQL + MVCC + Raft): BaraDB core engine
- Фаза 2 (Advanced SQL): Разработена с Xiaomi Mimo (
mimo-v2.5-pro) — Window Functions, MERGE, LATERAL JOIN, Advanced Aggregates, PIVOT/UNPIVOT, SQL/PGQ Property Graph - Фаза 3 (Stabilization + Multi-Tenant): Текуща — Vector SQL Integration, Session Variables,
current_user/current_role, RLS tenant isolation, тестове, документация
Част 1: BaraDB Advanced SQL Engine
1.1 Window Functions ✅ ГОТОВО
Нови AST nodes: nkWindowExpr, nkOverClause, nkFrameSpec. Нов IR plan: irpkWindow.
| Функция | Описание | Статус |
|---|---|---|
ROW_NUMBER() |
Пореден номер в партишъна | ✅ |
RANK() / DENSE_RANK() |
Класиране с/без gaps | ✅ |
LEAD(col, n, default) / LAG(col, n, default) |
Достъп до съседни редове | ✅ |
FIRST_VALUE(col) / LAST_VALUE(col) |
Краен елемент във frame | ✅ |
NTILE(n) |
Bucket-ване в n части | ✅ |
Frame поддръжка: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ✅
Файлове: lexer.nim, ast.nim, ir.nim, parser.nim, executor.nim, codegen.nim
Тестове: 5 теста в tests/test_all.nim, всички зелени.
1.2 MERGE / UPSERT ✅ ГОТОВО
MERGE INTO inventory AS target
USING updates AS source
ON target.sku = source.sku
WHEN MATCHED THEN UPDATE SET qty = target.qty + source.delta
WHEN NOT MATCHED THEN INSERT (sku, qty) VALUES (source.sku, source.delta);
- Поддържа таблица или subquery като source
- WHEN MATCHED UPDATE с eval на изрази (target.col + source.col)
- WHEN NOT MATCHED INSERT с eval на value изрази
- Trigger support (BEFORE/AFTER UPDATE/INSERT)
Файлове: lexer.nim, ast.nim, ir.nim, parser.nim, executor.nim, codegen.nim
Тестове: 2 теста в tests/test_all.nim, всички зелени.
1.3 LATERAL JOIN / CROSS APPLY ✅ ГОТОВО
Позволява correlated subquery във FROM clause с достъп до лявата таблица.
SELECT u.name, recent_orders.*
FROM users u,
LATERAL (
SELECT order_id, total FROM orders o
WHERE o.user_id = u.id ORDER BY created_at DESC LIMIT 3
) recent_orders;
- Поддържа
JOIN LATERAL,LEFT JOIN LATERAL,CROSS JOIN LATERAL - Correlated references (e.g.
u.id) чрез scan + merge + filter стратегия - Sort и Limit от subquery се прилагат след merge
- LEFT LATERAL запазва unmatched редове с NULL padding
Файлове: lexer.nim, ast.nim, ir.nim, parser.nim, executor.nim
Тестове: 4 execution теста + 3 parser теста, всички зелени.
1.4 Advanced Aggregates ✅ ГОТОВО
ARRAY_AGG(col ORDER BY ...)STRING_AGG(col, delimiter)COUNT(*) FILTER (WHERE ...)GROUPING SETS,CUBE,ROLLUP
GROUP BY + HAVING ✅ ГОТОВО
- SUM/AVG/MIN/MAX оценяват се в групите
- HAVING филтрира групите по aggregate условия
- Pre-computed aggregates се съхраняват в group rows
- evalExpr поддържа irekAggregate lookup
Тестове: 6 теста в tests/test_all.nim, всички зелени.
FILTER (WHERE ...) ✅ ГОТОВО
SELECT COUNT(*) FILTER (WHERE active = true) FROM users;
SELECT dept, SUM(amount) FILTER (WHERE amount > 100) FROM sales GROUP BY dept;
- Parser:
FILTER (WHERE ...)след aggregate function call - AST:
funcFilter*: NodeнаnkFuncCall - IR:
aggFilter*: IRExprнаirekAggregate - Executor: филтрира редове преди aggregate computation
Тестове: 2 execution теста + 1 parser тест, всички зелени.
ARRAY_AGG / STRING_AGG ✅ ГОТОВО
SELECT dept, ARRAY_AGG(amount) AS amounts FROM sales GROUP BY dept;
SELECT dept, STRING_AGG(name, ', ') AS names FROM employees GROUP BY dept;
- Нови IR aggregate ops:
irArrayAgg,irStringAgg - Multi-argument aggregate parsing (delimiter за STRING_AGG)
- FILTER support за двете функции
Тестове: 2 теста, всички зелени.
GROUPING SETS / ROLLUP / CUBE ✅ ГОТОВО
SELECT dept, SUM(amount) FROM sales GROUP BY ROLLUP (dept);
SELECT dept, job, SUM(amount) FROM sales GROUP BY CUBE (dept, job);
SELECT dept, job, SUM(amount) FROM sales GROUP BY GROUPING SETS ((dept), (job), ());
- ROLLUP(a, b) → GROUPING SETS ((a,b), (a), ())
- CUBE(a, b) → GROUPING SETS ((a,b), (a), (b), ())
- Генериране на subsets за CUBE чрез powerset алгоритъм
Тестове: 4 parser теста + 1 execution тест, всички зелени.
1.5 PIVOT / UNPIVOT ✅ ГОТОВО
SELECT * FROM (SELECT name, dept, salary FROM emp)
PIVOT (SUM(salary) FOR dept IN ('Eng', 'Sales'));
SELECT * FROM emp
UNPIVOT (salary FOR dept IN (eng_salary, sales_salary));
- Parser: PIVOT/UNPIVOT в FROM clause
- IR:
irpkPivot,irpkUnpivot - Executor: group by identity cols → aggregate per pivot value → create columns
- Subquery storage в
nkFrom.fromSubquery
Тестове: 1 parser + 1 execution тест, всички зелени.
1.6 SQL:2023 Property Graph (SQL/PGQ) ✅ ГОТОВО (Parser)
SELECT * FROM GRAPH_TABLE(org_chart
MATCH (e)-[r]->(d)
COLUMNS (e.name, d.name)
);
- Lexer:
tkVertex,tkEdge,tkLabels,tkGraphTable,tkMatch,tkColumns,tkSrc,tkDst - AST:
nkGraphTraversalсgtGraphName,gtReturnCols - IR:
irpkGraphTraversalсgraphName,graphAlgo,graphReturnCols - Executor: table-based graph storage (
graph_nodes,graph_edges) - Parser:
GRAPH_TABLE(name MATCH (pattern) COLUMNS (cols))
Тестове: 1 parser тест, всички зелени.
Част 1.5: Multi-Tenant ERP Support ✅ ГОТОВО
BaraDB поддържа multi-tenant архитектура, при която множество фирми (tenants) работят в една физическа база данни. Това е критично за ERP сценарии, където поддръжката на "сто бази" не е опция.
Механизъм
| Компонент | Описание |
|---|---|
| Session Variables | SET app.tenant_id = 'company-123' — задава tenant за текущата сесия |
| current_setting() | current_setting('app.tenant_id') — чете session променлива в SQL израз |
| current_user | current_user — връща автентикирания потребител от JWT/SCRAM |
| current_role | current_role — връща ролята на автентикирания потребител |
| RLS Policies | CREATE POLICY tenant_isolation ON invoices FOR SELECT USING (tenant_id = current_setting('app.tenant_id')) |
| Auth Bridge | server.nim и httpserver.nim попълват ExecutionContext.currentUser/currentRole след верификация |
Пример
-- Една таблица за всички фирми
CREATE TABLE invoices (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
data JSONB
);
-- Изолация чрез RLS
CREATE POLICY tenant_isolation ON invoices
FOR SELECT USING (tenant_id = current_setting('app.tenant_id'));
-- Всяка сесия вижда само своя tenant
SET app.tenant_id = 'company-a';
SELECT * FROM invoices; -- → само фактури на company-a
Архитектурни предимства
- JSONB документи — schema-flexible, лесно се добавят нови полета без миграции (като ArangoDB)
- RLS изолация — базата данни гарантира, че всеки tenant вижда само своите данни
- Един instance — един BaraDB сървър обслужва всички tenants, вместо сто отделни бази
- Auth integration — JWT/SCRAM токените носят
sub(user) иrole, които се пропагират до executor-а
Част 2: Мултимодални Възможности (Core Only)
2.1 JSON / JSONB Документи ✅ ГОТОВО
SELECT data->>'name' FROM users WHERE data->'tags' @> '["admin"]';
- Типове:
JSON,JSONBколони в таблици - Оператори:
->,->>,#>,#>>,@>,<@,?,?&,?| - Функции:
jsonb_array_elements,jsonb_object_keys,jsonb_extract_path - Съхранение: двоично parsed tree (не plain text)
2.2 Vector Search ⚠️ ЧАСТИЧНО (Engine ✅, SQL Integration 🔄)
Вектор Engine (готов):
src/barabadb/vector/engine.nim— HNSW index с cosine/euclidean distancesrc/barabadb/vector/quant.nim— IVF-PQ quantizationsrc/barabadb/vector/simd.nim— SIMD оптимизацииsrc/barabadb/core/crossmodal.nim— CrossModalEngine за хибридно търсене (vector + text)
Липсваща SQL интеграция (базова — за стабилизация):
-- Тип и колона
CREATE TABLE items (id INT PRIMARY KEY, embedding VECTOR(768));
-- Index
CREATE VECTOR INDEX idx_items_vec ON items(embedding)
USING hnsw WITH (m = 16, ef_construction = 200, metric = 'cosine');
-- Query functions
SELECT id, cosine_distance(embedding, '[0.1, 0.2, ...]') AS dist
FROM items
ORDER BY dist ASC
LIMIT 10;
Задачи за стабилизация (всички изпълнени):
VECTOR(n)тип в CREATE TABLE (parser + storage)CREATE VECTOR INDEX ... USING hnsw(DDL)cosine_distance(),euclidean_distance(),inner_product()в SQL expression evaluator<->nearest-neighbor оператор в ORDER BY / WHERE- Executor integration: HNSW index population при CREATE INDEX и DML
Статус: ✅ ГОТОВО. 8 SQL-level vector теста зелени.
2.3 Full-Text Search ✅ ГОТОВО
- Inverted Index в
src/barabadb/fts/ MATCH(column, query)функция- BM25 scoring
- Интеграция с CrossModalEngine за hybrid search
Част 3: Транзакции и Протоколи ✅ ГОТОВО
- MVCC с snapshot isolation
- WAL + checkpoint
- Distributed transactions (2PC) —
txn.addParticipant("vector") - Wire protocol: binary за vectors, JSON за queries
Имплементационен ред (финален статус)
- ✅ Window Functions (AST → Parser → IR → Executor → Tests)
- ✅ MERGE statement (Parser → Executor → Tests)
- ✅ LATERAL JOIN (Parser → Executor, correlated subquery strategy)
- ✅ GROUP BY + HAVING (SUM/AVG/MIN/MAX, HAVING filter)
- ✅ FILTER clause (COUNT/SUM/AVG FILTER (WHERE ...))
- ✅ ARRAY_AGG / STRING_AGG (multi-arg aggregates)
- ✅ GROUPING SETS / ROLLUP / CUBE (powerset generation)
- ✅ PIVOT / UNPIVOT (row-to-column transformation)
- ✅ SQL/PGQ Property Graph (GRAPH_TABLE MATCH parser)
- ✅ JSON/JSONB (operators + functions)
- ✅ Full-Text Search (inverted index + BM25)
- ✅ Vector Engine (HNSW + IVF-PQ + SIMD)
- ✅ Vector SQL Integration (тип, index, distance functions, <-> operator, ORDER BY)
Крайно състояние
340+ теста зелени. Всички фундаментални SQL:2023 features имплементирани.
Четирите свята:
| Свят | Features | Статус |
|---|---|---|
| SQL | Window, MERGE, LATERAL, GROUP BY/HAVING, FILTER, ARRAY_AGG, STRING_AGG, GROUPING SETS/ROLLUP/CUBE, PIVOT/UNPIVOT | ✅ |
| JSON | JSON/JSONB колони, -> / ->> оператори |
✅ |
| Graph | BFS/DFS/PageRank/Dijkstra engine + SQL/PGQ GRAPH_TABLE | ✅ |
| Vector | HNSW index, cosine/euclidean distance, IVF-PQ, SIMD | ✅ Engine 🔄 SQL glue |
| FTS | Inverted index, BM25, hybrid search | ✅ |
Файлове модифицирани:
lexer.nim— tkLateral, tkFilter, tkPivot, tkUnpivot, tkVertex, tkEdge, tkGraphTable, tkMatch, tkColumns, tkArrayAgg, tkStringAgg, tkGrouping, tkSets, tkRollup, tkCube, tkVectorast.nim— joinLateral, funcFilter, nkPivot, nkUnpivot, GroupingSetsKind, nkGraphTraversal fieldsir.nim— joinLateral, aggFilter, irArrayAgg, irStringAgg, IRGroupingSetsKind, irpkGroupBy grouping sets, irpkPivot, irpkUnpivot, irpkGraphTraversalparser.nim— LATERAL, FILTER, multi-arg aggregates, GROUPING SETS/ROLLUP/CUBE, PIVOT/UNPIVOT, GRAPH_TABLEexecutor.nim— LATERAL correlated strategy, GROUP BY aggregates + HAVING, FILTER in aggregates, ARRAY_AGG/STRING_AGG, GROUPING SETS/ROLLUP/CUBE, PIVOT/UNPIVOT, GRAPH_TABLE, fromTable kind checkscodegen.nim— irpkPivot, irpkUnpivot, irpkGraphTraversaltests/test_all.nim— 25+ нови тестаtests/join_tests.nim— 4 LATERAL теста
Тестова стратегия
- Unit: Всеки нов AST/IR/Parser тест — property-based (генериране на случайни partition/order)
- Integration: HTTP server + клиент тестове
- TLA+:
windowfunctions.tla— deterministic partitioning semantics - Benchmark: Window function performance vs PostgreSQL (опционално)
Поправени грешки при тази сесия
- Vector SQL Integration — имплементиран пълен SQL glue за вектори (тип, индекс, функции, оператор)
- MERGE тестове — поправени чрез изолиране на тестовата директория (unique temp dir per suite)
- Row storage escape —
escapeRowVal()вexecInsertза стойности със запетай (vector literals) - ORDER BY + projection —
irpkSortсега е предиirpkProjectвlowerSelect, което позволяваORDER BYпо колони извънSELECT - GROUPING SETS execution —
lowerSelectсега проверяваselGroupingSetsKind != gskNoneосвенselGroupBy.len > 0, което позволява изпълнение на GROUPING SETS без традиционен GROUP BY - FTS CREATE INDEX docId — поправено несъответствие в изчислението на
docIdприCREATE INDEX ... USING FTS(сега използва хеш наtableName.$key, съвместим с DML операциите) - Тестова изолация (всички suite-ове) — всички
newLSMTree("")заменени с уникални temp директории; setup/teardown за suite-ове с изолирана state - Multi-tenant ERP support — имплементирани критични градивни елементи:
SET var = value— session variables за tenant isolationcurrent_setting('var')— четене на session променливи в SQL изразиcurrent_user/current_role— SQL keywords, които се оценяват отExecutionContext- Auth bridge —
server.nimиhttpserver.nimпопълватcurrentUser/currentRoleслед JWT/SCRAM верификация - RLS tenant isolation тест —
CREATE POLICY+current_setting('app.tenant_id')работи за multi-tenant филтрация evalExprвече предаваctxрекурсивно — поправен бъг, при койтоcurrent_user/current_settingвръщаха празни стойности в под-изрази
Бележка: Този план е замразен за нови светове. Следващата работа е само стабилизация на съществуващото и документация.