diff --git a/clients/nim/README.md b/clients/nim/README.md index 720ef10..b88e08e 100644 --- a/clients/nim/README.md +++ b/clients/nim/README.md @@ -15,7 +15,7 @@ Official Nim client for **BaraDB** — a multimodal database engine. Add to your `.nimble` file: ```nim -requires "baradb >= 1.0.0" +requires "baradb >= 1.1.0" ``` Or clone locally: diff --git a/clients/python/README.md b/clients/python/README.md index 300db89..5c21582 100644 --- a/clients/python/README.md +++ b/clients/python/README.md @@ -1,15 +1,16 @@ -# BaraDB Python Client +# BaraDB Python Async Client -Official Python client for **BaraDB** — a multimodal database engine written in Nim. +Official async Python client for **BaraDB** — a multimodal database engine written in Nim. ## Features +- **Async/await** — fully non-blocking, concurrent query support - **Binary wire protocol** — fast, compact TCP communication -- **Sync & blocking API** — simple to use in scripts and apps +- **Request queueing** — sequential processing with concurrent execution - **Query builder** — fluent SQL construction - **Parameterized queries** — safe from SQL injection - **Vector & JSON support** — first-class multimodal types -- **Context managers** — `with` statement support +- **Context managers** — async `async with` statement support ## Installation @@ -20,7 +21,7 @@ pip install baradb Or from source: ```bash -git clone https://github.com/barabadb/baradadb.git +git clone https://github.com/katehonz/barabaDB.git cd clients/python pip install -e ".[dev]" ``` @@ -28,71 +29,92 @@ pip install -e ".[dev]" ## Quick Start ```python +import asyncio from baradb import Client -client = Client("localhost", 9472) -client.connect() +async def main(): + client = Client("localhost", 9472) + await client.connect() -result = client.query("SELECT name, age FROM users WHERE age > 18") -for row in result: - print(row["name"], row["age"]) + result = await client.query("SELECT name, age FROM users WHERE age > 18") + for row in result: + print(row["name"], row["age"]) -client.close() + await client.close() + +asyncio.run(main()) ``` ### Context Manager ```python +import asyncio from baradb import Client -with Client("localhost", 9472) as client: - result = client.query("SELECT 1") - print(result.row_count) +async def main(): + async with Client("localhost", 9472) as client: + result = await client.query("SELECT 1") + print(result.row_count) + +asyncio.run(main()) ``` ### Parameterized Queries ```python +import asyncio from baradb import Client, WireValue -with Client("localhost", 9472) as client: - result = client.query_params( - "SELECT * FROM users WHERE age > $1 AND country = $2", - [WireValue.int64(18), WireValue.string("BG")], - ) - for row in result: - print(row) +async def main(): + async with Client("localhost", 9472) as client: + result = await client.query_params( + "SELECT * FROM users WHERE age > $1 AND country = $2", + [WireValue.int64(18), WireValue.string("BG")], + ) + for row in result: + print(row) + +asyncio.run(main()) ``` ### Query Builder ```python +import asyncio from baradb import Client, QueryBuilder -with Client("localhost", 9472) as client: - qb = ( - QueryBuilder(client) - .select("name", "email") - .from_("users") - .where("active = true") - .order_by("name") - .limit(10) - ) - result = qb.exec() - for row in result: - print(row) +async def main(): + async with Client("localhost", 9472) as client: + qb = ( + QueryBuilder(client) + .select("name", "email") + .from_("users") + .where("active = true") + .order_by("name") + .limit(10) + ) + result = await qb.exec() + for row in result: + print(row) + +asyncio.run(main()) ``` ### Vector Search ```python +import asyncio from baradb import Client, WireValue -with Client("localhost", 9472) as client: - result = client.query_params( - "SELECT id, name FROM products ORDER BY embedding <-> $1 LIMIT 5", - [WireValue.vector([0.1, 0.2, 0.3])], - ) +async def main(): + async with Client("localhost", 9472) as client: + result = await client.query_params( + "SELECT id, name FROM products ORDER BY embedding <-> $1 LIMIT 5", + [WireValue.vector([0.1, 0.2, 0.3])], + ) + print(result.rows) + +asyncio.run(main()) ``` ## Running Tests @@ -107,7 +129,7 @@ Integration tests (requires server on `localhost:9472`): ```bash # Start server -docker run -d -p 9472:9472 baradb:latest +docker run -d -p 9472:9472 barabadb:latest # Run all tests pytest @@ -124,18 +146,18 @@ pytest | `database` | `default` | Default database | | `username` | `admin` | Username | | `password` | `""` | Password | -| `timeout` | `30` | Socket timeout in seconds | +| `timeout` | `30.0` | Socket timeout in seconds | -### Methods +### Methods (all async) -- `connect()` — open TCP connection -- `close()` — close connection -- `query(sql) -> QueryResult` — execute SELECT-like query -- `query_params(sql, params) -> QueryResult` — parameterized query -- `execute(sql) -> int` — execute DDL/DML, returns affected rows -- `auth(token)` — JWT authentication -- `ping() -> bool` — health check +- `await client.connect()` — open TCP connection +- `await client.close()` — close connection +- `await client.query(sql) -> QueryResult` — execute SELECT-like query +- `await client.query_params(sql, params) -> QueryResult` — parameterized query +- `await client.execute(sql) -> int` — execute DDL/DML, returns affected rows +- `await client.auth(token)` — JWT authentication +- `await client.ping() -> bool` — health check ## License -Apache-2.0 +Apache-2.0 \ No newline at end of file diff --git a/clients/python/baradb/__init__.py b/clients/python/baradb/__init__.py index 80e94c0..c045231 100644 --- a/clients/python/baradb/__init__.py +++ b/clients/python/baradb/__init__.py @@ -1,20 +1,34 @@ """ -BaraDB Python Client +BaraDB Python Async Client -Official Python client for BaraDB — Multimodal Database Engine. +Official async Python client for BaraDB — Multimodal Database Engine. Communicates via the BaraDB Wire Protocol (binary, big-endian, TCP). Install: pip install baradb Quick Start: + import asyncio from baradb import Client - client = Client("localhost", 9472) - client.connect() - result = client.query("SELECT name FROM users WHERE age > 18") - for row in result: - print(row["name"]) - client.close() + + async def main(): + client = Client("localhost", 9472) + await client.connect() + result = await client.query("SELECT name FROM users WHERE age > 18") + for row in result: + print(row["name"]) + await client.close() + + asyncio.run(main()) + +Parameterized Queries: + result = await client.query_params( + "SELECT * FROM users WHERE age > $1", + [WireValue.int64(18)] + ) + +Authentication: + await client.auth("jwt-token-here") """ from .core import ( @@ -27,7 +41,7 @@ from .core import ( ResultFormat, ) -__version__ = "1.0.0" +__version__ = "1.1.0" __all__ = [ "Client", "QueryBuilder", @@ -36,4 +50,4 @@ __all__ = [ "MsgKind", "FieldKind", "ResultFormat", -] +] \ No newline at end of file diff --git a/clients/python/baradb/core.py b/clients/python/baradb/core.py index 8ff7a7a..5ac8d2f 100644 --- a/clients/python/baradb/core.py +++ b/clients/python/baradb/core.py @@ -1,33 +1,38 @@ """ -BaraDB Python Client +BaraDB Python Async Client -Binary protocol client for BaraDB database. -Communicates via the BaraDB Wire Protocol (binary, big-endian). +Official async Python client for BaraDB — Multimodal Database Engine. +Communicates via the BaraDB Wire Protocol (binary, big-endian, TCP). Install: pip install baradb Quick Start: + import asyncio from baradb import Client - client = Client("localhost", 9472) - client.connect() - result = client.query("SELECT name FROM users WHERE age > 18") - for row in result: - print(row["name"]) - client.close() + + async def main(): + client = Client("localhost", 9472) + await client.connect() + result = await client.query("SELECT name FROM users WHERE age > 18") + for row in result: + print(row["name"]) + await client.close() + + asyncio.run(main()) Parameterized Queries: - result = client.query_params("SELECT * FROM users WHERE age > $1", [WireValue.int64(18)]) + result = await client.query_params( + "SELECT * FROM users WHERE age > $1", + [WireValue.int64(18)] + ) Authentication: - client = Client("localhost", 9472, username="admin", password="secret") - client.connect() - client.auth("jwt-token-here") + await client.auth("jwt-token-here") """ -import socket +import asyncio import struct -import json from typing import Any, Optional, Sequence @@ -49,7 +54,6 @@ class FieldKind: class MsgKind: - # Client messages CLIENT_HANDSHAKE = 0x01 QUERY = 0x02 QUERY_PARAMS = 0x03 @@ -59,7 +63,6 @@ class MsgKind: CLOSE = 0x07 PING = 0x08 AUTH = 0x09 - # Server messages SERVER_HANDSHAKE = 0x80 READY = 0x81 DATA = 0x82 @@ -88,7 +91,7 @@ class WireValue: return WireValue(FieldKind.NULL) @staticmethod - def bool_val(val: bool): + def bool(val: bool): return WireValue(FieldKind.BOOL, val) @staticmethod @@ -120,15 +123,15 @@ class WireValue: return WireValue(FieldKind.STRING, val) @staticmethod - def bytes_val(val: bytes): + def bytes(val: bytes): return WireValue(FieldKind.BYTES, val) @staticmethod - def array_val(val: list): + def array(val: list): return WireValue(FieldKind.ARRAY, val) @staticmethod - def object_val(val: dict): + def object(val: dict): return WireValue(FieldKind.OBJECT, val) @staticmethod @@ -136,7 +139,7 @@ class WireValue: return WireValue(FieldKind.VECTOR, val) @staticmethod - def json_val(val: str): + def json(val: str): return WireValue(FieldKind.JSON, val) def serialize(self) -> bytes: @@ -202,72 +205,92 @@ class QueryResult: class Client: - """BaraDB database client.""" + """Async BaraDB database client.""" def __init__(self, host: str = "localhost", port: int = 9472, database: str = "default", username: str = "admin", - password: str = "", timeout: int = 30): + password: str = "", timeout: float = 30.0): self.host = host self.port = port self.database = database self.username = username self.password = password self.timeout = timeout - self._sock: Optional[socket.socket] = None + self._reader: Optional[asyncio.StreamReader] = None + self._writer: Optional[asyncio.StreamWriter] = None self._connected = False self._request_id = 0 + self._buffer = bytearray() + self._pending_resolve = None + self._request_queue: list = [] + self._request_lock = False - def connect(self) -> None: + async def connect(self) -> None: """Connect to the BaraDB server.""" - self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._sock.settimeout(self.timeout) - self._sock.connect((self.host, self.port)) + self._reader, self._writer = await asyncio.wait_for( + asyncio.open_connection(self.host, self.port), + timeout=self.timeout + ) self._connected = True - def close(self) -> None: - if self._sock: + async def close(self) -> None: + """Close the connection to the server.""" + if self._writer and self._connected: try: msg = self._build_message(MsgKind.CLOSE, b"") - self._sock.send(msg) + self._writer.write(msg) + await self._writer.drain() except Exception: pass - self._sock.close() + if self._writer: + self._writer.close() + await self._writer.wait_closed() + self._writer = None + self._reader = None self._connected = False def is_connected(self) -> bool: + """Check if client is connected.""" return self._connected def _next_id(self) -> int: self._request_id += 1 return self._request_id - def _recv_exact(self, size: int) -> bytes: + async def _recv_exact(self, size: int) -> bytes: """Receive exactly `size` bytes from the socket.""" - data = b"" - while len(data) < size: - chunk = self._sock.recv(size - len(data)) - if not chunk: - raise ConnectionError("Connection closed by server") - data += chunk + while len(self._buffer) < size: + try: + chunk = await asyncio.wait_for( + self._reader.read(size - len(self._buffer)), + timeout=self.timeout + ) + if not chunk: + raise ConnectionError("Connection closed by server") + self._buffer.extend(chunk) + except asyncio.TimeoutError: + raise TimeoutError("Receive timeout") + data = bytes(self._buffer[:size]) + del self._buffer[:size] return data - def _read_response_header(self) -> tuple[int, int, int]: + async def _read_header(self) -> tuple[int, int, int]: """Read a 12-byte message header. Returns (kind, length, request_id).""" - header = self._recv_exact(12) + header = await self._recv_exact(12) kind, length, req_id = struct.unpack(">III", header) return kind, length, req_id - def _read_error(self, length: int) -> Exception: + async def _read_error(self, length: int) -> Exception: """Read and parse an ERROR payload.""" - data = self._recv_exact(length) + data = await self._recv_exact(length) code = struct.unpack(">I", data[:4])[0] msg_len = struct.unpack(">I", data[4:8])[0] error_msg = data[8:8 + msg_len].decode("utf-8") return Exception(f"BaraDB error {code}: {error_msg}") - def _read_data_response(self, length: int) -> QueryResult: + async def _read_data_response(self, length: int) -> QueryResult: """Read and parse a DATA payload, then follow up with COMPLETE.""" - data = self._recv_exact(length) + data = await self._recv_exact(length) pos = [0] col_count = struct.unpack(">I", data[pos[0]:pos[0]+4])[0] @@ -299,95 +322,138 @@ class Client: result.rows = rows result.row_count = row_count - comp_kind, comp_len, _ = self._read_response_header() + comp_kind, comp_len, _ = await self._read_header() if comp_kind == MsgKind.COMPLETE: - comp_data = self._recv_exact(comp_len) + comp_data = await self._recv_exact(comp_len) result.affected_rows = struct.unpack(">I", comp_data[:4])[0] elif comp_kind == MsgKind.ERROR: - raise self._read_error(comp_len) + raise await self._read_error(comp_len) return result - def auth(self, token: str) -> None: + async def auth(self, token: str) -> None: """Authenticate with the server using a JWT token.""" + if not self._connected: + raise Exception("Not connected") encoded = token.encode("utf-8") payload = struct.pack(">I", len(encoded)) + encoded msg = self._build_message(MsgKind.AUTH, payload) - self._sock.send(msg) + self._writer.write(msg) + await self._writer.drain() - kind, length, _ = self._read_response_header() + kind, length, _ = await self._read_header() if kind == MsgKind.AUTH_OK: return elif kind == MsgKind.ERROR: - raise self._read_error(length) + raise await self._read_error(length) else: raise Exception(f"Unexpected auth response: 0x{kind:02x}") - def ping(self) -> bool: + async def ping(self) -> bool: """Ping the server. Returns True if pong received.""" + if not self._connected: + raise Exception("Not connected") msg = self._build_message(MsgKind.PING, b"") - self._sock.send(msg) + self._writer.write(msg) + await self._writer.drain() - kind, length, _ = self._read_response_header() + kind, length, _ = await self._read_header() if kind == MsgKind.PONG: return True elif kind == MsgKind.ERROR: - raise self._read_error(length) + raise await self._read_error(length) return False - def query(self, sql: str) -> QueryResult: + async def _process_queue(self) -> None: + """Process queued requests sequentially.""" + if self._request_lock or len(self._request_queue) == 0: + return + self._request_lock = True + task_data = self._request_queue.pop(0) + try: + result = await task_data["task"]() + task_data["resolve"](result) + except Exception as err: + task_data["reject"](err) + finally: + self._request_lock = False + asyncio.create_task(self._process_queue()) + + def _enqueue(self, task) -> None: + """Add a task to the request queue.""" + future = asyncio.Future() + self._request_queue.append({"task": task, "resolve": future.set_result, "reject": future.set_exception}) + asyncio.create_task(self._process_queue()) + return future + + async def query(self, sql: str) -> QueryResult: """Execute a BaraQL query.""" - payload = self._encode_string(sql) - payload += bytes([ResultFormat.BINARY]) + if not self._connected: + raise Exception("Not connected") - msg = self._build_message(MsgKind.QUERY, payload) - self._sock.send(msg) + async def _do_query(): + payload = self._encode_string(sql) + payload += bytes([ResultFormat.BINARY]) - kind, length, _ = self._read_response_header() + msg = self._build_message(MsgKind.QUERY, payload) + self._writer.write(msg) + await self._writer.drain() - if kind == MsgKind.ERROR: - raise self._read_error(length) + kind, length, _ = await self._read_header() - if kind == MsgKind.DATA: - return self._read_data_response(length) + if kind == MsgKind.ERROR: + raise await self._read_error(length) - if kind == MsgKind.COMPLETE: - data = self._recv_exact(length) - result = QueryResult() - result.affected_rows = struct.unpack(">I", data[:4])[0] - return result + if kind == MsgKind.DATA: + return await self._read_data_response(length) - return QueryResult() + if kind == MsgKind.COMPLETE: + data = await self._recv_exact(length) + result = QueryResult() + result.affected_rows = struct.unpack(">I", data[:4])[0] + return result - def query_params(self, sql: str, params: Sequence[WireValue]) -> QueryResult: + return QueryResult() + + return await self._enqueue(_do_query) + + async def query_params(self, sql: str, params: Sequence[WireValue]) -> QueryResult: """Execute a parameterized BaraQL query.""" - payload = self._encode_string(sql) - payload += bytes([ResultFormat.BINARY]) - payload += struct.pack(">I", len(params)) - for p in params: - payload += p.serialize() + if not self._connected: + raise Exception("Not connected") - msg = self._build_message(MsgKind.QUERY_PARAMS, payload) - self._sock.send(msg) + async def _do_query_params(): + payload = self._encode_string(sql) + payload += bytes([ResultFormat.BINARY]) + payload += struct.pack(">I", len(params)) + for p in params: + payload += p.serialize() - kind, length, _ = self._read_response_header() + msg = self._build_message(MsgKind.QUERY_PARAMS, payload) + self._writer.write(msg) + await self._writer.drain() - if kind == MsgKind.ERROR: - raise self._read_error(length) + kind, length, _ = await self._read_header() - if kind == MsgKind.DATA: - return self._read_data_response(length) + if kind == MsgKind.ERROR: + raise await self._read_error(length) - if kind == MsgKind.COMPLETE: - data = self._recv_exact(length) - result = QueryResult() - result.affected_rows = struct.unpack(">I", data[:4])[0] - return result + if kind == MsgKind.DATA: + return await self._read_data_response(length) - return QueryResult() + if kind == MsgKind.COMPLETE: + data = await self._recv_exact(length) + result = QueryResult() + result.affected_rows = struct.unpack(">I", data[:4])[0] + return result - def execute(self, sql: str) -> int: - result = self.query(sql) + return QueryResult() + + return await self._enqueue(_do_query_params) + + async def execute(self, sql: str) -> int: + """Execute a query and return affected rows count.""" + result = await self.query(sql) return result.affected_rows def _build_message(self, kind: int, payload: bytes) -> bytes: @@ -477,12 +543,12 @@ class Client: return self._read_string(data, pos) return None - def __enter__(self): - self.connect() + async def __aenter__(self): + await self.connect() return self - def __exit__(self, *args): - self.close() + async def __aexit__(self, *args): + await self.close() class QueryBuilder: @@ -559,5 +625,5 @@ class QueryBuilder: sql += " OFFSET " + str(self._offset) return sql - def exec(self) -> QueryResult: - return self.client.query(self.build()) + async def exec(self) -> QueryResult: + return await self.client.query(self.build()) \ No newline at end of file diff --git a/clients/rust/Cargo.toml b/clients/rust/Cargo.toml index e4a3324..3d4611c 100644 --- a/clients/rust/Cargo.toml +++ b/clients/rust/Cargo.toml @@ -3,9 +3,9 @@ name = "baradb" version = "1.1.0" edition = "2021" authors = ["BaraDB Team "] -description = "Official Rust client for BaraDB — binary protocol client" +description = "Official async Rust client for BaraDB — binary protocol client" license = "Apache-2.0" -repository = "https://github.com/barabadb/baradadb" +repository = "https://github.com/katehonz/barabaDB" documentation = "https://docs.baradb.dev" readme = "README.md" keywords = ["database", "baradb", "multimodal", "client", "wire-protocol"] @@ -13,9 +13,10 @@ categories = ["database", "network-programming"] rust-version = "1.70" [dependencies] +tokio = { version = "1.35", features = ["full"] } [dev-dependencies] [[example]] name = "basic" -path = "examples/basic.rs" +path = "examples/basic.rs" \ No newline at end of file diff --git a/clients/rust/README.md b/clients/rust/README.md index 2c49930..d8f310f 100644 --- a/clients/rust/README.md +++ b/clients/rust/README.md @@ -1,13 +1,13 @@ -# BaraDB Rust Client +# BaraDB Async Rust Client -Official Rust client for **BaraDB** — a multimodal database engine written in Nim. +Official async Rust client for **BaraDB** — a multimodal database engine written in Nim. ## Features -- **Binary wire protocol** — fast TCP communication using only `std` -- **Zero dependencies** — no external crates required -- **Sync API** — blocking I/O suitable for most applications +- **Async/await** — fully non-blocking with Tokio runtime +- **Binary wire protocol** — fast TCP communication - **Query builder** — fluent SQL construction +- **Parameterized queries** — safe from SQL injection - **Vector & JSON support** — first-class multimodal types ## Installation @@ -16,13 +16,14 @@ Add to your `Cargo.toml`: ```toml [dependencies] -baradb = "1.0" +baradb = "1.1" +tokio = { version = "1.35", features = ["full"] } ``` Or from source: ```bash -git clone https://github.com/barabadb/baradadb.git +git clone https://github.com/katehonz/barabaDB.git cd clients/rust cargo build ``` @@ -32,13 +33,14 @@ cargo build ```rust use baradb::Client; -fn main() -> Result<(), Box> { - let mut client = Client::connect("localhost", 9472)?; - let result = client.query("SELECT name, age FROM users WHERE age > 18")?; +#[tokio::main] +async fn main() -> Result<(), Box> { + let mut client = Client::connect("localhost", 9472).await?; + let result = client.query("SELECT name, age FROM users WHERE age > 18").await?; for row in result.rows() { println!("{:?}", row); } - client.close(); + client.close().await; Ok(()) } ``` @@ -48,16 +50,17 @@ fn main() -> Result<(), Box> { ```rust use baradb::{Client, WireValue}; -fn main() -> Result<(), Box> { - let mut client = Client::connect("localhost", 9472)?; +#[tokio::main] +async fn main() -> Result<(), Box> { + let mut client = Client::connect("localhost", 9472).await?; let result = client.query_params( "SELECT * FROM users WHERE age > $1 AND country = $2", &[WireValue::Int64(18), WireValue::String("BG".to_string())], - )?; + ).await?; for row in result.rows() { println!("{:?}", row); } - client.close(); + client.close().await; Ok(()) } ``` @@ -65,21 +68,23 @@ fn main() -> Result<(), Box> { ### Query Builder ```rust -use baradb::Client; +use baradb::{Client, QueryBuilder}; -fn main() -> Result<(), Box> { - let mut client = Client::connect("localhost", 9472)?; - let result = baradb::QueryBuilder::new(&mut client) +#[tokio::main] +async fn main() -> Result<(), Box> { + let mut client = Client::connect("localhost", 9472).await?; + let result = QueryBuilder::new(&mut client) .select(&["name", "email"]) .from("users") .where_clause("active = true") .order_by("name", "ASC") .limit(10) - .exec()?; + .exec() + .await?; for row in result.rows() { println!("{:?}", row); } - client.close(); + client.close().await; Ok(()) } ``` @@ -89,13 +94,14 @@ fn main() -> Result<(), Box> { ```rust use baradb::{Client, WireValue}; -fn main() -> Result<(), Box> { - let mut client = Client::connect("localhost", 9472)?; +#[tokio::main] +async fn main() -> Result<(), Box> { + let mut client = Client::connect("localhost", 9472).await?; let result = client.query_params( "SELECT id, name FROM products ORDER BY embedding <-> $1 LIMIT 5", &[WireValue::Vector(vec![0.1, 0.2, 0.3])], - )?; - client.close(); + ).await?; + client.close().await; Ok(()) } ``` @@ -112,7 +118,7 @@ Integration tests (requires server on `localhost:9472`): ```bash # Start server -docker run -d -p 9472:9472 baradb:latest +docker run -d -p 9472:9472 barabadb:latest # Run all tests cargo test @@ -120,19 +126,19 @@ cargo test ## API Reference -### `Client::connect(host, port)` +### `Client::connect(host, port) -> Result` -Creates a new client connected to the given host and port. +Creates a new async client connected to the given host and port. -### Methods +### Methods (all async) -- `query(sql) -> Result` — execute SELECT-like query -- `query_params(sql, params) -> Result` — parameterized query -- `execute(sql) -> Result` — execute DDL/DML, returns affected rows -- `auth(token) -> Result<()>` — JWT authentication -- `ping() -> Result` — health check -- `close()` — close connection +- `await client.query(sql) -> Result` — execute SELECT-like query +- `await client.query_params(sql, params) -> Result` — parameterized query +- `await client.execute(sql) -> Result` — execute DDL/DML, returns affected rows +- `await client.auth(token) -> Result<()>` — JWT authentication +- `await client.ping() -> Result` — health check +- `await client.close()` — close connection ## License -Apache-2.0 +Apache-2.0 \ No newline at end of file diff --git a/clients/rust/examples/basic.rs b/clients/rust/examples/basic.rs index b03d1b8..11909b3 100644 --- a/clients/rust/examples/basic.rs +++ b/clients/rust/examples/basic.rs @@ -3,34 +3,65 @@ use baradb::{Client, QueryBuilder, WireValue}; -fn example_connection() -> Result<(), Box> { +#[tokio::main] +async fn main() { + println!("BaraDB Rust Client Examples"); + println!("Make sure BaraDB is running on localhost:9472"); + println!(); + + if let Err(e) = example_connection().await { + eprintln!("ERROR: {}", e); + } + + if let Err(e) = example_simple_query().await { + eprintln!("ERROR: {}", e); + } + + if let Err(e) = example_parameterized_query().await { + eprintln!("ERROR: {}", e); + } + + if let Err(e) = example_query_builder().await { + eprintln!("ERROR: {}", e); + } + + if let Err(e) = example_vector().await { + eprintln!("ERROR: {}", e); + } + + if let Err(e) = example_ddl_dml().await { + eprintln!("ERROR: {}", e); + } +} + +async fn example_connection() -> Result<(), Box> { println!("=== Connection ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; + let mut client = Client::connect("127.0.0.1", 9472).await?; println!("Connected: {}", client.is_connected()); - println!("Ping: {}", client.ping()?); - client.close(); + println!("Ping: {}", client.ping().await?); + client.close().await; println!("Connected after close: {}", client.is_connected()); println!(); Ok(()) } -fn example_simple_query() -> Result<(), Box> { +async fn example_simple_query() -> Result<(), Box> { println!("=== Simple Query ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; - let result = client.query("SELECT 42 as answer, 'BaraDB' as db")?; + let mut client = Client::connect("127.0.0.1", 9472).await?; + let result = client.query("SELECT 42 as answer, 'BaraDB' as db").await?; println!("Columns: {:?}", result.columns()); println!("Row count: {}", result.row_count()); for row in result.rows() { println!(" {:?}", row); } - client.close(); + client.close().await; println!(); Ok(()) } -fn example_parameterized_query() -> Result<(), Box> { +async fn example_parameterized_query() -> Result<(), Box> { println!("=== Parameterized Query ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; + let mut client = Client::connect("127.0.0.1", 9472).await?; let result = client.query_params( "SELECT $1 as num, $2 as txt, $3 as flag", &[ @@ -38,18 +69,18 @@ fn example_parameterized_query() -> Result<(), Box> { WireValue::String("hello world".to_string()), WireValue::Bool(true), ], - )?; + ).await?; for row in result.rows() { println!(" {:?}", row); } - client.close(); + client.close().await; println!(); Ok(()) } -fn example_query_builder() -> Result<(), Box> { +async fn example_query_builder() -> Result<(), Box> { println!("=== Query Builder ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; + let mut client = Client::connect("127.0.0.1", 9472).await?; let sql = QueryBuilder::new(&mut client) .select(&["id", "name"]) .from("users") @@ -58,70 +89,49 @@ fn example_query_builder() -> Result<(), Box> { .limit(5) .build(); println!("Generated SQL: {}", sql); - client.close(); + client.close().await; println!(); Ok(()) } -fn example_vector() -> Result<(), Box> { +async fn example_vector() -> Result<(), Box> { println!("=== Vector Value ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; + let mut client = Client::connect("127.0.0.1", 9472).await?; let result = client.query_params( "SELECT $1 as embedding", &[WireValue::Vector(vec![0.1, 0.2, 0.3, 0.4])], - )?; + ).await?; for row in result.rows() { println!(" {:?}", row); } - client.close(); + client.close().await; println!(); Ok(()) } -fn example_ddl_dml() -> Result<(), Box> { +async fn example_ddl_dml() -> Result<(), Box> { println!("=== DDL & DML ==="); - let mut client = Client::connect("127.0.0.1", 9472)?; + let mut client = Client::connect("127.0.0.1", 9472).await?; - let _ = client.execute("DROP TABLE IF EXISTS demo_products"); + let _ = client.execute("DROP TABLE IF EXISTS demo_products").await; client.execute( "CREATE TABLE demo_products (id INT PRIMARY KEY, name STRING, price FLOAT)", - )?; + ).await?; let affected = client.execute( "INSERT INTO demo_products (id, name, price) VALUES (1, 'Widget', 9.99)", - )?; + ).await?; println!("Insert affected rows: {}", affected); - let result = client.query("SELECT * FROM demo_products")?; + let result = client.query("SELECT * FROM demo_products").await?; println!("Select returned {} row(s)", result.row_count()); for row in result.rows() { println!(" {:?}", row); } - client.execute("DROP TABLE demo_products")?; + client.execute("DROP TABLE demo_products").await?; println!("Table dropped"); - client.close(); + client.close().await; println!(); Ok(()) -} - -fn main() { - println!("BaraDB Rust Client Examples"); - println!("Make sure BaraDB is running on localhost:9472"); - println!(); - - let examples: Vec Result<(), Box>> = vec![ - example_connection, - example_simple_query, - example_parameterized_query, - example_query_builder, - example_vector, - example_ddl_dml, - ]; - - for example in examples { - if let Err(e) = example() { - eprintln!("ERROR: {}", e); - } - } -} +} \ No newline at end of file diff --git a/clients/rust/src/lib.rs b/clients/rust/src/lib.rs index 3cf8cef..36e7c93 100644 --- a/clients/rust/src/lib.rs +++ b/clients/rust/src/lib.rs @@ -1,36 +1,42 @@ -//! BaraDB Rust Client +//! BaraDB Async Rust Client //! -//! Binary protocol client for BaraDB database. -//! Zero external dependencies — uses only `std`. +//! Async binary protocol client for BaraDB database. +//! Uses Tokio for async I/O operations. //! //! # Example //! ```no_run //! use baradb::{Client, WireValue}; //! -//! let mut client = Client::connect("localhost", 9472).unwrap(); -//! let result = client.query("SELECT name FROM users WHERE age > 18").unwrap(); -//! for row in result.rows() { -//! if let Some(WireValue::String(name)) = row.get("name") { -//! println!("{}", name); +//! #[tokio::main] +//! async fn main() { +//! let mut client = Client::connect("localhost", 9472).await.unwrap(); +//! let result = client.query("SELECT name FROM users WHERE age > 18").await.unwrap(); +//! for row in result.rows() { +//! if let Some(WireValue::String(name)) = row.get("name") { +//! println!("{}", name); +//! } //! } +//! client.close().await; //! } -//! client.close(); //! ``` //! //! # Parameterized Queries //! ```no_run //! use baradb::{Client, WireValue}; //! -//! let mut client = Client::connect("localhost", 9472).unwrap(); -//! let result = client.query_params( -//! "SELECT * FROM users WHERE age > $1", -//! &[WireValue::Int64(18)], -//! ).unwrap(); +//! #[tokio::main] +//! async fn main() { +//! let mut client = Client::connect("localhost", 9472).await.unwrap(); +//! let result = client.query_params( +//! "SELECT * FROM users WHERE age > $1", +//! &[WireValue::Int64(18)], +//! ).await.unwrap(); +//! } //! ``` use std::collections::HashMap; -use std::io::{Read, Write}; -use std::net::TcpStream; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; // Client message kinds const MK_CLIENT_HANDSHAKE: u32 = 0x01; @@ -221,43 +227,41 @@ impl QueryResult { } } -/// BaraDB client +/// BaraDB async client pub struct Client { - config: Config, stream: TcpStream, connected: bool, request_id: u32, + read_buf: Vec, } impl Client { - pub fn connect(host: &str, port: u16) -> Result> { - let config = Config { - host: host.to_string(), - port, - ..Default::default() - }; - Self::connect_with_config(config) - } - - pub fn connect_with_config(config: Config) -> Result> { - let addr = format!("{}:{}", config.host, config.port); - let stream = TcpStream::connect(&addr)?; - stream.set_nodelay(true)?; + /// Connect to a BaraDB server + pub async fn connect(host: &str, port: u16) -> Result> { + let addr = format!("{}:{}", host, port); + let stream = TcpStream::connect(&addr).await?; Ok(Client { - config, stream, connected: true, request_id: 0, + read_buf: Vec::new(), }) } - pub fn close(&mut self) { + /// Connect with custom configuration + pub async fn connect_with_config(config: Config) -> Result> { + Self::connect(&config.host, config.port).await + } + + /// Close the connection + pub async fn close(&mut self) { if self.connected { - let _ = self.send_close(); + let _ = self.send_close().await; } self.connected = false; } + /// Check if connected pub fn is_connected(&self) -> bool { self.connected } @@ -267,27 +271,39 @@ impl Client { self.request_id } - fn send_close(&mut self) -> Result<(), Box> { + async fn send_close(&mut self) -> Result<(), Box> { let msg = build_message(MK_CLOSE, self.next_id(), &[]); - self.stream.write_all(&msg)?; + self.stream.write_all(&msg).await?; Ok(()) } - fn read_header(&mut self) -> Result<(u32, u32, u32), Box> { - let mut header = [0u8; 12]; - self.stream.read_exact(&mut header)?; + async fn read_exact(&mut self, mut n: usize) -> Result, Box> { + let mut buf = vec![0u8; n]; + let mut pos = 0; + while pos < n { + let read = self.stream.read(&mut buf[pos..]).await?; + if read == 0 { + return Err("Connection closed".into()); + } + pos += read; + } + Ok(buf) + } + + async fn read_header(&mut self) -> Result<(u32, u32, u32), Box> { + let header = self.read_exact(12).await?; let kind = u32::from_be_bytes([header[0], header[1], header[2], header[3]]); let length = u32::from_be_bytes([header[4], header[5], header[6], header[7]]); let req_id = u32::from_be_bytes([header[8], header[9], header[10], header[11]]); Ok((kind, length, req_id)) } - fn read_payload(&mut self, length: u32) -> Result, Box> { - let mut payload = vec![0u8; length as usize]; + async fn read_payload(&mut self, length: u32) -> Result, Box> { if length > 0 { - self.stream.read_exact(&mut payload)?; + self.read_exact(length as usize).await + } else { + Ok(vec![]) } - Ok(payload) } fn read_error_message(payload: &[u8]) -> String { @@ -302,26 +318,26 @@ impl Client { "Query error".to_string() } - fn read_data_response(&mut self, payload: &[u8]) -> Result> { + async fn read_data_response(&mut self, payload: &[u8]) -> Result> { let mut pos = 0usize; - let col_count = read_u32(payload, &mut pos) as usize; + let col_count = read_u32(payload, &mut pos); - let mut columns = Vec::with_capacity(col_count); + let mut columns = Vec::with_capacity(col_count as usize); for _ in 0..col_count { columns.push(read_string(payload, &mut pos)); } - let mut col_types = Vec::with_capacity(col_count); + let mut col_types = Vec::with_capacity(col_count as usize); for _ in 0..col_count { col_types.push(payload[pos]); pos += 1; } - let row_count = read_u32(payload, &mut pos) as usize; - let mut rows = Vec::with_capacity(row_count); + let row_count = read_u32(payload, &mut pos); + let mut rows = Vec::with_capacity(row_count as usize); for _ in 0..row_count { let mut row = HashMap::new(); - for c in 0..col_count { + for c in 0..col_count as usize { let val = read_wire_value(payload, &mut pos); row.insert(columns[c].clone(), val); } @@ -329,9 +345,9 @@ impl Client { } let mut affected = 0usize; - let (comp_kind, comp_len, _) = self.read_header()?; + let (comp_kind, comp_len, _) = self.read_header().await?; if comp_kind == MK_COMPLETE { - let comp_payload = self.read_payload(comp_len)?; + let comp_payload = self.read_payload(comp_len).await?; if comp_payload.len() >= 4 { affected = u32::from_be_bytes([comp_payload[0], comp_payload[1], comp_payload[2], comp_payload[3]]) as usize; } @@ -340,44 +356,47 @@ impl Client { Ok(QueryResult { columns, column_types: col_types, rows, affected_rows: affected }) } - pub fn auth(&mut self, token: &str) -> Result<(), Box> { + /// Authenticate with JWT token + pub async fn auth(&mut self, token: &str) -> Result<(), Box> { if !self.connected { return Err("Not connected".into()); } let payload = encode_string(token); let msg = build_message(MK_AUTH, self.next_id(), &payload); - self.stream.write_all(&msg)?; + self.stream.write_all(&msg).await?; - let (kind, length, _) = self.read_header()?; + let (kind, length, _) = self.read_header().await?; match kind { MK_AUTH_OK => Ok(()), MK_ERROR => { - let p = self.read_payload(length)?; + let p = self.read_payload(length).await?; Err(Self::read_error_message(&p).into()) } _ => Err(format!("Unexpected auth response: 0x{:02x}", kind).into()), } } - pub fn ping(&mut self) -> Result> { + /// Ping the server + pub async fn ping(&mut self) -> Result> { if !self.connected { return Err("Not connected".into()); } let msg = build_message(MK_PING, self.next_id(), &[]); - self.stream.write_all(&msg)?; + self.stream.write_all(&msg).await?; - let (kind, length, _) = self.read_header()?; + let (kind, length, _) = self.read_header().await?; match kind { MK_PONG => Ok(true), MK_ERROR => { - let p = self.read_payload(length)?; + let p = self.read_payload(length).await?; Err(Self::read_error_message(&p).into()) } _ => Ok(false), } } - pub fn query(&mut self, sql: &str) -> Result> { + /// Execute a query + pub async fn query(&mut self, sql: &str) -> Result> { if !self.connected { return Err("Not connected".into()); } @@ -386,14 +405,14 @@ impl Client { payload.push(0x00); // ResultFormat::BINARY let msg = build_message(MK_QUERY, self.next_id(), &payload); - self.stream.write_all(&msg)?; + self.stream.write_all(&msg).await?; - let (kind, length, _) = self.read_header()?; - let resp_payload = self.read_payload(length)?; + let (kind, length, _) = self.read_header().await?; + let resp_payload = self.read_payload(length).await?; match kind { MK_READY => Ok(QueryResult { columns: vec![], column_types: vec![], rows: vec![], affected_rows: 0 }), - MK_DATA => self.read_data_response(&resp_payload), + MK_DATA => self.read_data_response(&resp_payload).await, MK_COMPLETE => { let affected = if resp_payload.len() >= 4 { u32::from_be_bytes([resp_payload[0], resp_payload[1], resp_payload[2], resp_payload[3]]) as usize @@ -405,7 +424,8 @@ impl Client { } } - pub fn query_params(&mut self, sql: &str, params: &[WireValue]) -> Result> { + /// Execute a parameterized query + pub async fn query_params(&mut self, sql: &str, params: &[WireValue]) -> Result> { if !self.connected { return Err("Not connected".into()); } @@ -418,14 +438,14 @@ impl Client { } let msg = build_message(MK_QUERY_PARAMS, self.next_id(), &payload); - self.stream.write_all(&msg)?; + self.stream.write_all(&msg).await?; - let (kind, length, _) = self.read_header()?; - let resp_payload = self.read_payload(length)?; + let (kind, length, _) = self.read_header().await?; + let resp_payload = self.read_payload(length).await?; match kind { MK_READY => Ok(QueryResult { columns: vec![], column_types: vec![], rows: vec![], affected_rows: 0 }), - MK_DATA => self.read_data_response(&resp_payload), + MK_DATA => self.read_data_response(&resp_payload).await, MK_COMPLETE => { let affected = if resp_payload.len() >= 4 { u32::from_be_bytes([resp_payload[0], resp_payload[1], resp_payload[2], resp_payload[3]]) as usize @@ -437,12 +457,14 @@ impl Client { } } - pub fn execute(&mut self, sql: &str) -> Result> { - let result = self.query(sql)?; + /// Execute and return affected rows + pub async fn execute(&mut self, sql: &str) -> Result> { + let result = self.query(sql).await?; Ok(result.affected_rows()) } } +/// Query builder for fluent SQL construction pub struct QueryBuilder<'a> { client: &'a mut Client, select_cols: Vec, @@ -457,6 +479,7 @@ pub struct QueryBuilder<'a> { } impl<'a> QueryBuilder<'a> { + /// Create a new query builder pub fn new(client: &'a mut Client) -> Self { QueryBuilder { client, @@ -472,56 +495,67 @@ impl<'a> QueryBuilder<'a> { } } + /// Add columns to SELECT pub fn select(mut self, cols: &[&str]) -> Self { self.select_cols.extend(cols.iter().map(|s| s.to_string())); self } + /// Set the FROM table pub fn from(mut self, table: &str) -> Self { self.from_table = table.to_string(); self } + /// Add a WHERE clause pub fn where_clause(mut self, clause: &str) -> Self { self.where_clauses.push(clause.to_string()); self } + /// Add a JOIN clause pub fn join(mut self, table: &str, on: &str) -> Self { self.joins.push(format!("JOIN {} ON {}", table, on)); self } + /// Add a LEFT JOIN clause pub fn left_join(mut self, table: &str, on: &str) -> Self { self.joins.push(format!("LEFT JOIN {} ON {}", table, on)); self } + /// Add GROUP BY columns pub fn group_by(mut self, cols: &[&str]) -> Self { self.group_by.extend(cols.iter().map(|s| s.to_string())); self } + /// Add HAVING clause pub fn having(mut self, clause: &str) -> Self { self.having = clause.to_string(); self } + /// Add ORDER BY column pub fn order_by(mut self, col: &str, dir: &str) -> Self { self.order_by.push(format!("{} {}", col, dir)); self } + /// Set LIMIT pub fn limit(mut self, n: usize) -> Self { self.limit = n; self } + /// Set OFFSET pub fn offset(mut self, n: usize) -> Self { self.offset = n; self } + /// Build the SQL string pub fn build(&self) -> String { let mut sql = String::from("SELECT "); if self.select_cols.is_empty() { @@ -555,9 +589,10 @@ impl<'a> QueryBuilder<'a> { sql } - pub fn exec(self) -> Result> { + /// Execute the query + pub async fn exec(self) -> Result> { let sql = self.build(); - self.client.query(&sql) + self.client.query(&sql).await } } @@ -675,4 +710,4 @@ fn read_wire_value(data: &[u8], pos: &mut usize) -> WireValue { FK_JSON => WireValue::Json(read_string(data, pos)), _ => WireValue::Null, } -} +} \ No newline at end of file diff --git a/docs/ar/baraql.md b/docs/ar/baraql.md index a521b6e..8c10a06 100644 --- a/docs/ar/baraql.md +++ b/docs/ar/baraql.md @@ -97,5 +97,172 @@ RETURN friend.name; ```sql BEGIN; INSERT users { name := 'Alice', age := 30 }; +INSERT orders { user_id := last_insert_id(), total := 100 }; COMMIT; -``` \ No newline at end of file + +-- مع نقطة حفظ +BEGIN; +INSERT users { name := 'Bob', age := 25 }; +SAVEPOINT sp1; +INSERT orders { user_id := last_insert_id(), total := 200 }; +-- خطأ، التراجع إلى نقطة الحفظ +ROLLBACK TO sp1; +COMMIT; +``` + +## البحث النصي الكامل + +```sql +-- بحث أساسي +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('database programming'); + +-- مع درجة الصلة +SELECT title, relevance() +FROM articles +WHERE MATCH(title, body) AGAINST('Nim language') +ORDER BY relevance() DESC; + +-- الوضع المنطقي +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('+Nim -Python' IN BOOLEAN MODE); + +-- البحث الضبابي +SELECT * FROM articles +WHERE MATCH(title) AGAINST('programing' WITH FUZZINESS 2); +``` + +## الدوال المحددة من المستخدم + +```sql +-- تسجيل UDF +CREATE FUNCTION greet(name str) -> str { + RETURN 'Hello, ' || name || '!'; +}; + +-- استخدامها +SELECT greet(name) FROM users; + +-- الدوال المدمجة +SELECT abs(-5), sqrt(16), lower('HELLO'), len('test'); +``` + +## تلميحات الاستعلام + +```sql +-- فرض استخدام الفهرس +SELECT /*+ USE_INDEX(idx_users_age) */ * FROM users WHERE age > 18; + +-- فرض البحث المتجهي التقريبي +SELECT /*+ APPROXIMATE */ * FROM vectors +ORDER BY cosine_distance(embedding, [...]) +LIMIT 10; + +-- التنفيذ المتوازي +SELECT /*+ PARALLEL(4) */ * FROM large_table; +``` + +## دوال النوافذ + +```sql +-- دوال الترتيب +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- دوال القيمة +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- دوال التوزيع +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### مواصفات الإطار + +```sql +-- إطار ROWS +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- إطار RANGE +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## ERP متعدد المستأجرين + +يدعم BaraDB تشغيل عدة شركات (مستأجرين) في مثيل قاعدة بيانات واحد، باستخدام **أمان مستوى الصف (RLS)** مع **متغيرات الجلسة**. + +### متغيرات الجلسة + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### المستخدم / الدور الحالي + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### عزل المستأجر عبر RLS + +```sql +-- تمكين RLS على جدول +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- إنشاء سياسة تصفية حسب المستأجر +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- كل جلسة ترى فقط بياناتها +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- صفوف company-a فقط +``` + +### لماذا متعدد المستأجرين؟ + +- **مثيل واحد، مستأجرون كثيرون** — لا حاجة لتشغيل 100 قاعدة بيانات منفصلة +- **مستندات JSONB** — تخزين مخطط مرن، سهل إضافة حقول لكل مستأجر +- **RLS يضمن العزل** — قاعدة البيانات تفرض حدود المستأجر، وليس فقط التطبيق + +## الكلمات المفتاحية المدعومة + +| الفئة | الكلمات المفتاحية | +|----------|----------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Transaction | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Graph | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Vector | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (تطابق BM25) | +| Recovery | RECOVER TO TIMESTAMP | +| Functions | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Session | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Functions | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | \ No newline at end of file diff --git a/docs/ar/installation.md b/docs/ar/installation.md index dc37792..b9bb7e0 100644 --- a/docs/ar/installation.md +++ b/docs/ar/installation.md @@ -22,38 +22,284 @@ ### لينكس ```bash +# المثبت الرسمي curl https://nim-lang.org/choosenim/init.sh -sSf | sh + +# Ubuntu/Debian +sudo apt-get update +sudo apt-get install nim + +# Fedora +sudo dnf install nim + +# Arch Linux +sudo pacman -S nim ``` ### macOS ```bash +# Homebrew brew install nim + +# MacPorts +sudo port install nim ``` ### ويندوز ```powershell +# باستخدام choosenim +curl.exe -A "MSYS2_$(uname -m)" -L https://nim-lang.org/choosenim/init.ps1 | powershell - + +# باستخدام winget winget install nim + +# باستخدام scoop +scoop install nim ``` +### التحقق من التثبيت + +```bash +nim --version +# المتوقع: Nim Compiler Version 2.2.0 أو أحدث +``` + +## تثبيت OpenSSL + +### لينكس + +```bash +# Ubuntu/Debian +sudo apt-get install libssl-dev + +# Fedora +sudo dnf install openssl-devel + +# Arch Linux +sudo pacman -S openssl +``` + +### macOS + +OpenSSL مضمن مع النظام. إذا لزم الأمر: + +```bash +brew install openssl +``` + +### ويندوز + +OpenSSL مضمن مع توزيع Nim ويندوز. للبناء اليدوي، قم بالتنزيل من [slproweb.com](https://slproweb.com/products/Win32OpenSSL.html). + ## بناء BaraDB +### استنساخ المستودع + ```bash git clone https://github.com/katehonz/barabaDB.git cd barabaDB +``` + +### تثبيت التبعيات + +```bash nimble install -d -y +``` + +### خيارات البناء + +#### بناء التصحيح + +```bash +nim c -d:ssl -o:build/baradadb src/baradadb.nim +``` + +#### بناء الإصدار (موصى به) + +```bash nim c -d:ssl -d:release --opt:speed -o:build/baradadb src/baradadb.nim ``` +#### استخدام مهام Nimble + +```bash +# بناء التصحيح +nimble build_debug + +# بناء الإصدار +nimble build_release +``` + +#### تقليل حجم الملف الثنائي + +```bash +nim c -d:ssl -d:release --opt:size -o:build/baradadb src/baradadb.nim +strip build/baradadb +``` + +### التحقق من البناء + +```bash +./build/baradadb --version +# المتوقع: BaraDB v1.1.0 — Multimodal Database Engine +``` + +## تشغيل الاختبارات + +### جميع الاختبارات + +```bash +nim c -d:ssl -r tests/test_all.nim +``` + +### مجموعات اختبارات محددة + +```bash +# اختبارات التخزين +nim c -d:ssl -r tests/test_storage.nim + +# اختبارات محرك الاستعلام +nim c -d:ssl -r tests/test_query.nim + +# اختبارات البروتوكول +nim c -d:ssl -r tests/test_protocol.nim +``` + +### المعايير + +```bash +nim c -d:ssl -d:release -r benchmarks/bench_all.nim +``` + +## خيارات التثبيت + +### التثبيت على مستوى النظام + +```bash +# بناء إصدار RELEASE +nimble build_release + +# التثبيت في /usr/local/bin +sudo cp build/baradadb /usr/local/bin/ +sudo chmod +x /usr/local/bin/baradadb + +# إنشاء دليل البيانات +sudo mkdir -p /var/lib/baradb +sudo chmod 755 /var/lib/baradb +``` + +### الملف الثنائي المبنى مسبقًا + +قم بتنزيل أحدث إصدار لمنصتك: + +```bash +# لينكس x86_64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64 +chmod +x baradadb-linux-amd64 +mv baradadb-linux-amd64 /usr/local/bin/baradadb + +# لينكس ARM64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-arm64 +chmod +x baradadb-linux-arm64 +mv baradadb-linux-arm64 /usr/local/bin/baradadb + +# macOS +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-darwin-amd64 +chmod +x baradadb-darwin-amd64 +mv baradadb-darwin-amd64 /usr/local/bin/baradadb +``` + +### Docker + +```bash +# سحب الصورة الرسمية +docker pull barabadb/barabadb:latest + +# التشغيل +docker run -d \ + -p 9472:9472 \ + -p 9470:9470 \ + -p 9471:9471 \ + -v baradb_data:/data \ + barabadb/barabadb +``` + +### Docker Compose + +```bash +docker-compose up -d +``` + +### الاستخدام المدمج (مشاريع Nim) + +أضف إلى ملف `.nimble` الخاص بك: + +```nim +requires "barabadb >= 1.1.0" +``` + +استخدم في الكود: + +```nim +import barabadb/storage/lsm + +var db = newLSMTree("./data") +db.put("key", cast[seq[byte]]("value")) +let (found, val) = db.get("key") +db.close() +``` + ## التشغيل الأول ```bash +# بدء الخادم ./build/baradadb + +# المخرجات المتوقعة: +# BaraDB v1.1.0 — Multimodal Database Engine +# BaraDB TCP listening on 127.0.0.1:9472 + +# الاختبار عبر HTTP API curl http://localhost:9470/health + +# الصدفة التفاعلية ./build/baradadb --shell ``` +## حل مشكلات التثبيت + +### "cannot open file: hunos" + +```bash +nimble install -d -y +``` + +### "BaraDB requires SSL support" + +قم دائمًا بالبناء باستخدام `-d:ssl`: + +```bash +nim c -d:ssl -o:build/baradadb src/baradadb.nim +``` + +### البناء البطيء + +استخدم البناء المتوازي: + +```bash +nim c -d:ssl -d:release --parallelBuild:4 -o:build/baradadb src/baradadb.nim +``` + +### حجم الملف الثنائي الكبير + +استخدم تحسين الحجم: + +```bash +nim c -d:ssl -d:release --opt:size --passL:-s -o:build/baradadb src/baradadb.nim +``` + ## الخطوات التالية - [دليل البداية السريعة](quickstart.md) diff --git a/docs/bg/api-binary.md b/docs/bg/api-binary.md new file mode 100644 index 0000000..2f7cb6d --- /dev/null +++ b/docs/bg/api-binary.md @@ -0,0 +1,107 @@ +# API за Бинарен Протокол + +Ниско-нивов wire протокол за високопроизводителни клиентски връзки. + +## Формат на Съобщенията + +Всички съобщения използват big-endian byte order: + +``` +┌─────────────┬─────────────┬─────────────┬─────────────────────┐ +│ Kind │ Length │ RequestId │ Payload │ +│ (4 bytes) │ (4 bytes) │ (4 bytes) │ │ +│ uint32 BE │ uint32 BE │ uint32 BE │ (Length bytes) │ +└─────────────┴─────────────┴─────────────┴─────────────────────┘ +``` + +## Типове Съобщения + +### Query (0x01) + +```nim +let msg = makeQueryMessage(requestId, "SELECT * FROM users") +``` + +### QueryParams (0x02) + +```nim +let msg = makeQueryParamsMessage(requestId, "SELECT * FROM users WHERE name = ?", params) +``` + +### Auth (0x07) + +```nim +let msg = makeAuthMessage(requestId, token) +``` + +### Ping (0x09) + +```nim +let msg = makePingMessage(requestId) +``` + +### Close (0x0A) + +```nim +let msg = makeCloseMessage(requestId) +``` + +## Отговорни Съобщения + +### Ready (0x05) + +```nim +let msg = makeReadyMessage(requestId) +``` + +### Error (0x06) + +```nim +let msg = makeErrorMessage(requestId, code, message) +``` + +### Data (0x81) + +```nim +# Съдържа резултатите от заявката с колони и редове +``` + +### Complete (0x82) + +```nim +# Потвърждава завършване на заявката +``` + +### Auth_OK (0x83) + +```nim +# Потвърждава успешна автентикация +``` + +### Pong (0x84) + +```nim +# Keepalive отговор +``` + +## Кодове за Грешки + +| Код | Име | Описание | +|------|-----|----------| +| 0x00 | OK | Успех | +| 0x01 | ERROR | Обща грешка | +| 0x02 | AUTH_REQUIRED | Изисква се автентикация | +| 0x03 | INVALID_QUERY | Синтактична грешка в заявката | +| 0x04 | NOT_FOUND | Ресурсът не е намерен | + +## Сериализация + +```nim +import barabadb/protocol/wire + +# Сериализиране на стойност +let bytes = serializeValue(Value(kind: vkString, strVal: "test")) + +# Десериализиране на стойност +let value = deserializeValue(bytes) +``` diff --git a/docs/bg/api-http.md b/docs/bg/api-http.md new file mode 100644 index 0000000..49c146f --- /dev/null +++ b/docs/bg/api-http.md @@ -0,0 +1,111 @@ +# HTTP/REST API + +JSON-базиран REST API за уеб приложения. + +## Базов URL + +``` +http://localhost:9470 +``` + +## Endpoints + +### GET /health + +Health проверка: + +```bash +curl http://localhost:9470/health +``` + +### GET /ready + +Readiness проверка: + +```bash +curl http://localhost:9470/ready +``` + +### POST /query + +Изпълнение на BaraQL заявка: + +```bash +curl -X POST http://localhost:9470/api/query \ + -H "Content-Type: application/json" \ + -d '{"query": "SELECT * FROM users WHERE age > 18"}' +``` + +Отговор: +```json +{ + "columns": ["name", "age"], + "rows": [["Alice", 30], ["Bob", 25]], + "row_count": 2, + "duration_ms": 12 +} +``` + +### POST /batch + +Групови заявки: + +```bash +curl -X POST http://localhost:9470/api/batch \ + -H "Content-Type: application/json" \ + -d '{"queries": ["INSERT users { name := \"Alice\" }", "INSERT users { name := \"Bob\" }"]}' +``` + +### GET /schema + +Преглед на схемата: + +```bash +curl http://localhost:9470/api/schema +``` + +### GET /metrics + +Prometheus метрики: + +```bash +curl http://localhost:9470/metrics +``` + +### POST /explain + +Обяснение на план за изпълнение: + +```bash +curl -X POST http://localhost:9470/api/explain \ + -H "Content-Type: application/json" \ + -d '{"query": "SELECT * FROM users WHERE age > 18"}' +``` + +### POST /backup + +Създаване на backup: + +```bash +curl -X POST http://localhost:9470/api/backup \ + -H "Content-Type: application/json" \ + -d '{"destination": "/backup/snapshot.db"}' +``` + +## Грешки + +```json +{ + "error": { + "code": "INVALID_QUERY", + "message": "Грешка в синтаксиса" + } +} +``` + +## Автентикация + +```bash +curl -H "Authorization: Bearer " \ + http://localhost:9470/api/users +``` diff --git a/docs/bg/api-websocket.md b/docs/bg/api-websocket.md new file mode 100644 index 0000000..a70ae06 --- /dev/null +++ b/docs/bg/api-websocket.md @@ -0,0 +1,127 @@ +# WebSocket API + +Full-duplex стрийминг за данни в реално време и push известия. + +## Свързване + +``` +ws://localhost:9471 +``` + +## Клиентски Пример + +```javascript +const ws = new WebSocket('ws://localhost:9471'); + +ws.onopen = () => { + console.log('Свързан'); + ws.send(JSON.stringify({ + type: 'query', + query: 'SELECT * FROM users' + })); +}; + +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log('Получено:', data); +}; +``` + +## Формат на Съобщенията + +```json +{ + "type": "query", + "id": "1", + "query": "SELECT * FROM users" +} +``` + +## Типове Съобщения + +### Заявка (query) + +```json +{ + "type": "query", + "id": "1", + "query": "SELECT * FROM users" +} +``` + +### Резултат (result) + +```json +{ + "type": "result", + "id": "1", + "columns": ["id", "name"], + "rows": [["1", "Alice"], ["2", "Bob"]] +} +``` + +### Грешка (error) + +```json +{ + "type": "error", + "id": "1", + "code": "INVALID_QUERY", + "message": "Синтактична грешка" +} +``` + +### Абониране (subscribe) + +Абониране за промени в таблица: + +```json +{ + "type": "subscribe", + "id": "sub1", + "table": "users" +} +``` + +### Известие (notification) + +Push известие от сървъра: + +```json +{ + "type": "notification", + "table": "users", + "operation": "insert", + "data": {"id": 3, "name": "Charlie"} +} +``` + +### Ping/Pong (keepalive) + +```json +{"type": "ping", "id": "ping1"} +``` + +Отговор: +```json +{"type": "pong", "id": "ping1"} +``` + +## JavaScript Клиент + +```javascript +class BaraDBClient { + constructor(url) { + this.ws = new WebSocket(url); + this.pending = new Map(); + } + + query(sql) { + return new Promise((resolve, reject) => { + const id = crypto.randomUUID(); + this.pending.set(id, { resolve, reject }); + this.ws.send(JSON.stringify({ type: 'query', id, query: sql })); + }); + } +} +``` diff --git a/docs/bg/architecture.md b/docs/bg/architecture.md index 3cf9dea..86a9100 100644 --- a/docs/bg/architecture.md +++ b/docs/bg/architecture.md @@ -2,150 +2,125 @@ ## Преглед -BaraDB е **мултимодална база данни** написана на Nim, която комбинира документно (KV), графично, векторно, колонно и пълнотекстово търсене в един двигател с обединен език за заявки наречен **BaraQL**. +BaraDB е **мултимодален database engine**, написан на Nim, който комбинира документно (KV), графово, векторно, колонково и пълнотекстово съхранение в един engine с унифициран език за заявки наречен **BaraQL**. -## Слоеста Архитектура +## Слоеве на Архитектурата ``` ┌─────────────────────────────────────────────────────────┐ -│ 1. СЛОЙ ЗА КЛИЕНТИ │ -│ Binary Protocol │ HTTP/REST │ WebSocket │ Embedded │ +│ 1. КЛИЕНТСКИ СЛОЙ │ +│ Бинарен Протокол │ HTTP/REST │ WebSocket │ Embedded │ ├─────────────────────────────────────────────────────────┤ -│ 2. ЗАЯВКИ СЛОЙ (BaraQL) │ +│ 2. QUERY СЛОЙ (BaraQL) │ │ Lexer → Parser → AST → IR → Optimizer → Codegen │ ├─────────────────────────────────────────────────────────┤ -│ 3. ИЗПЪЛНИТЕЛЕН ДВИГАТЕЛ │ -│ Document │ Graph │ Vector │ Columnar │ FTS │ +│ 3. ИЗПЪЛНИТЕЛЕН ENGINE │ +│ Документен │ Графов │ Векторен │ Колонков │ FTS │ ├─────────────────────────────────────────────────────────┤ -│ 4. СЪХРАНЕНИЕ │ +│ 4. СЪХРАНЕНИЕ │ │ LSM-Tree │ B-Tree │ WAL │ Bloom │ Compaction │ Cache │ ├─────────────────────────────────────────────────────────┤ -│ 5. РАЗПРЕДЕЛЕНО │ -│ Raft Consensus │ Sharding │ Replication │ Gossip │ +│ 5. РАЗПРЕДЕЛЕНИ │ +│ Raft Консенсус │ Шардиране │ Репликация │ Gossip │ └─────────────────────────────────────────────────────────┘ ``` ## Слой 1: Клиентски Слой -Множество протоколи за комуникация: +Множество комуникационни протоколи: -- **Binary Protocol** (`protocol/wire.nim`): Ефективен big-endian бинарен протокол с 16 типа съобщения -- **HTTP/REST** (`core/httpserver.nim`): JSON REST API с мулти-трединг -- **WebSocket** (`core/websocket.nim`): Пълен дуплекс стрийминг +- **Бинарен Протокол** (`protocol/wire.nim`): Ефективен big-endian бинарен протокол с 16 типа съобщения +- **HTTP/REST** (`core/httpserver.nim`): JSON-базиран REST API с multi-threading +- **WebSocket** (`core/websocket.nim`): Full-duplex стрийминг - **Embedded** (`storage/lsm.nim`): Директен in-process достъп -### Управление на Връзките +### Управление на Връзки -- **Connection Pool** (`protocol/pool.nim`): Мин/макс лимити на връзки -- **Rate Limiting** (`protocol/ratelimit.nim`): Token-bucket лимитиране -- **Authentication** (`protocol/auth.nim`): JWT с HMAC-SHA256 -- **TLS/SSL** (`protocol/ssl.nim`): TLS 1.3 с авто-генерирани сертификати +- **Connection Pool** (`protocol/pool.nim`): Min/max лимити на връзки с idle timeout +- **Rate Limiting** (`protocol/ratelimit.nim`): Token-bucket глобални и per-client лимити +- **Автентикация** (`protocol/auth.nim`): JWT с HMAC-SHA256 и достъп на база роли +- **TLS/SSL** (`protocol/ssl.nim`): TLS 1.3 с автоматично генерирани сертификати -## Слой 2: Заявки (BaraQL) +## Слой 2: Query Слой (BaraQL) -Pipeline-а на BaraQL: +BaraQL конвейрът: 1. **Lexer** (`query/lexer.nim`): Токенизира входа в 80+ типа токени -2. **Parser** (`query/parser.nim`): Рекурсивен descent парсър произвеждащ AST +2. **Parser** (`query/parser.nim`): Recursive descent parser генериращ AST 3. **AST** (`query/ast.nim`): 300+ реда покриващи 25+ вида възли -4. **IR** (`query/ir.nim`): Междинно представяне за планове за изпълнение -5. **Optimizer** (`query/adaptive.nim`): Адаптивен крос-модален оптимизатор -6. **Codegen** (`query/codegen.nim`): Транслира IR към операции върху съхранение +4. **IR** (`query/ir.nim`): Intermediate representation за планове за изпълнение +5. **Optimizer** (`query/adaptive.nim`): Adaptive cross-modal оптимизация на заявки +6. **Codegen** (`query/codegen.nim`): Превежда IR към storage операции 7. **Executor** (`query/executor.nim`): Изпълнява планове с паралелизация -### Крос-Модално Планиране +## Слой 3: Изпълнителен Engine -Оптимизаторът определя реда на изпълнение между двигателите: +### Документен/KV Engine +- **LSM-Tree** (`storage/lsm.nim`): Write-оптимизирано съхранение с MemTable, WAL, SSTables +- **B-Tree Индекс** (`storage/btree.nim`): Подреден индекс за range сканиране с COW -``` -1. Оценка на селективност за всеки предикат -2. Най-селективният предикат се изпълнява първи -3. Bloom филтри за KV търсения -4. Паралелизация на независими клонове -``` +### Vector Engine (`vector/`) +- **HNSW Индекс** (`vector/engine.nim`): Hierarchical Navigable Small World граф +- **IVF-PQ Индекс** (`vector/engine.nim`): Inverted File Index с Product Quantization +- **SIMD Операции** (`vector/simd.nim`): AVX2-оптимизирани изчисления на разстояние +- **Квантуване** (`vector/quant.nim`): Скаларно, продуктово и бинарно квантуване -## Слой 3: Изпълнителен Двигател - -### Document/KV Двигател -- **LSM-Tree** (`storage/lsm.nim`): Оптимизиран за запис с MemTable, WAL, SSTables -- **B-Tree Index** (`storage/btree.nim`): Подреден индекс за диапазони с COW - -### Vector Engine -- **HNSW** (`vector/engine.nim`): Иерархичен навигируем малък свят -- **IVF-PQ** (`vector/engine.nim`): Инвертиран файл с продуктово квантуване -- **SIMD** (`vector/simd.nim`): AVX2-оптимизирани изчисления на разстояния -- **Quantization** (`vector/quant.nim`): Скаларно, продуктово и бинарно квантуване - -### Graph Engine -- **Списък със съседи** (`graph/engine.nim`): Насочен граф с тегла +### Graph Engine (`graph/`) +- **Adjacency List** (`graph/engine.nim`): Насочен граф с тегла на ребрата - **Алгоритми** (`graph/engine.nim`): BFS, DFS, Dijkstra, PageRank - **Community Detection** (`graph/community.nim`): Louvain алгоритъм -- **Pattern Matching** (`graph/community.nim`): Subgraph isomorphism -- **Cypher Parser** (`graph/cypher.nim`): Cypher-подобни заявки +- **Pattern Matching** (`graph/community.nim`): Subgraph изоморфизъм +- **Cypher Parser** (`graph/cypher.nim`): Cypher-подобни графови заявки -### FTS -- **Инвертиран индекс** (`fts/engine.nim`): Термин-документ индекс -- **Ранжиране** (`fts/engine.nim`): BM25 и TF-IDF -- **Fuzzy Search** (`fts/engine.nim`): Levenshtein разстояние -- **Многоезичен** (`fts/multilang.nim`): Токенизация за EN, BG, DE, FR, RU +### Full-Text Search (`fts/`) +- **Inverted Index** (`fts/engine.nim`): Термин-документен индекс +- **Ранжиране** (`fts/engine.nim`): BM25 и TF-IDF оценяване +- **Fuzzy Търсене** (`fts/engine.nim`): Съвпадение с Levenshtein разстояние +- **Многоезичност** (`fts/multilang.nim`): Токенизатори за EN, BG, DE, FR, RU -### Columnar Engine -- **Колонно съхранение** (`core/columnar.nim`): Аналитични заявки -- **Компресия**: RLE и dictionary encoding -- **SIMD агрегати**: Ускорени агрегатни функции +### Columnar Engine (`core/columnar.nim`) +- Колонково съхранение за аналитични заявки +- RLE и dictionary encoding +- SIMD-ускорени агрегати ## Слой 4: Съхранение - **LSM-Tree** (`storage/lsm.nim`): MemTable, WAL, SSTable, Bloom Filter, Compaction -- **Page Cache** (`storage/compaction.nim`): LRU кеш -- **Memory-mapped I/O** (`storage/mmap.nim`): mmap-базиран достъп -- **Recovery** (`storage/recovery.nim`): WAL replay и възстановяване +- **Page Cache** (`storage/compaction.nim`): LRU кеш с проследяване на hit rate +- **Memory-mapped I/O** (`storage/mmap.nim`): mmap-базиран достъп до файлове +- **Recovery** (`storage/recovery.nim`): WAL replay и crash recovery -### Път на Запис +## Слой 5: Разпределение -``` -Client → Protocol → Auth → Parser → AST → IR → Codegen - → StorageOp → MVCC Txn → WAL Write → MemTable → Commit -``` +- **Raft Консенсус** (`core/raft.nim`): Leader election, log репликация +- **Шардиране** (`core/sharding.nim`): Hash, range и consistent hashing +- **Репликация** (`core/replication.nim`): Sync, async, semi-sync режими +- **Gossip Протокол** (`core/gossip.nim`): SWIM-подобно управление на членство +- **Разпределени Транзакции** (`core/disttxn.nim`): Two-phase commit -### Път на Четене - -``` -Client → Protocol → Auth → Parser → AST → IR → Codegen - → StorageOp → MVCC Snapshot → MemTable → SSTable → Result -``` - -## Слой 5: Разпределено - -- **Raft Consensus** (`core/raft.nim`): Лидерско избиране, репликация на логове -- **Sharding** (`core/sharding.nim`): Hash, range и консистентно хеширане -- **Replication** (`core/replication.nim`): Sync, async, semi-sync режими -- **Gossip Protocol** (`core/gossip.nim`): SWIM-подобно управление на членство -- **Distributed Transactions** (`core/disttxn.nim`): Two-phase commit - -## Ключови Дизайн Решения +## Ключови Дизайнерски Решения 1. **Чист Nim**: Без Cython, Python или Rust зависимости -2. **Обединено Съхранение**: Един двигател за KV, граф, вектор, FTS и колонно -3. **Вграден Режим**: Работи като библиотека или сървър -4. **Бинарен Протокол**: Ефективен wire протокол +2. **Унифицирано Съхранение**: Един engine обработва KV, graph, vector, FTS и columnar +3. **Embedded Режим**: Може да работи като библиотека или сървър +4. **Бинарен Протокол**: Персонализиран ефективен wire протокол 5. **MVCC**: Multi-version concurrency control -6. **Schema-First**: Строго типизирана система с наследяване -7. **Крос-Модал**: Един език за заявки през всички модели данни -8. **Формално Верифициран**: Разпределените алгоритми са специфицирани в TLA+ и проверени с TLC +6. **Schema-First**: Силно типизирана система от схеми с наследяване +7. **Cross-Modal**: Един език за заявки за всички модели на данни +8. **Формално Верифициран**: Основните разпределени алгоритми са специфицирани в TLA+ и проверени с TLC ## Статистика на Модулите | Категория | Модули | Редове Код | Предназначение | |-----------|--------|------------|----------------| -| Core | 16 | ~4,200 | Сървър, протоколи, транзакции, разпределено | +| Core | 16 | ~4,200 | Сървър, протоколи, транзакции, разпределени | | Storage | 7 | ~3,100 | LSM, B-Tree, WAL, bloom, compaction, mmap | -| Query | 7 | ~2,800 | Lexer, parser, AST, IR, оптимизатор, codegen, executor | +| Query | 7 | ~2,800 | Lexer, parser, AST, IR, optimizer, codegen, executor | | Vector | 3 | ~1,200 | HNSW, IVF-PQ, квантуване, SIMD | -| Graph | 3 | ~1,000 | Списък със съседи, алгоритми, community detection | -| FTS | 2 | ~900 | Инвертиран индекс, BM25, fuzzy, многоезичен | +| Graph | 3 | ~1,000 | Adjacency list, алгоритми, community detection | +| FTS | 2 | ~900 | Inverted index, BM25, fuzzy, многоезичност | | Protocol | 7 | ~2,400 | Wire, HTTP, WebSocket, pool, auth, rate limit, SSL | | Schema | 1 | ~600 | Типове, връзки, наследяване, миграции | -| Client | 2 | ~800 | Nim binary client, file helpers | -| CLI | 1 | ~400 | Интерактивна BaraQL конзола | +| Client | 2 | ~800 | Nim бинарен клиент, файлови помощници | +| CLI | 1 | ~400 | Интерактивна BaraQL обвивка | | **Общо** | **49** | **~14,100** | | diff --git a/docs/bg/backup.md b/docs/bg/backup.md new file mode 100644 index 0000000..78333b3 --- /dev/null +++ b/docs/bg/backup.md @@ -0,0 +1,198 @@ +# Backup и Възстановяване + +## Online Snapshots + +BaraDB поддържа online snapshots без спиране на сървъра. Snapshot-ът заснема консистентен изглед към момент във времето чрез MVCC. + +### Създаване на Snapshot + +```nim +import barabadb/core/backup + +var bm = newBackupManager() +bm.createSnapshot("/backup/baradb_2025-01-15") +``` + +### Чрез CLI + +```bash +./build/baradadb --snapshot --output=/backup/snapshot.db +``` + +### Чрез HTTP API + +```bash +curl -X POST http://localhost:9470/api/backup \ + -H "Content-Type: application/json" \ + -d '{"destination": "/backup/snapshot.db"}' +``` + +### Автоматизирани Backups + +Използвайте cron за планирани backups: + +```bash +# Ежедневен snapshot в 2 сутринта +0 2 * * * /usr/local/bin/baradadb --snapshot --output=/backup/baradb_$(date +\%Y\%m\%d).db + +# Запазване на последните 7 дни +find /backup -name "baradb_*.db" -mtime +7 -delete +``` + +## Point-in-Time Recovery (PITR) + +BaraDB използва Write-Ahead Log (WAL) за възстановяване до момент във времето. + +### WAL Архивиране + +Включете непрекъснато WAL архивиране: + +```bash +BARADB_WAL_ARCHIVE_DIR=/backup/wal \ +BARADB_WAL_ARCHIVE_INTERVAL_MS=60000 \ +./build/baradadb +``` + +### Възстановяване от Checkpoint + WAL + +```bash +# Възстановяване от snapshot +./build/baradadb --recover \ + --checkpoint=/backup/snapshot.db \ + --wal-dir=/backup/wal + +# Възстановяване до конкретен LSN +./build/baradadb --recover \ + --checkpoint=/backup/snapshot.db \ + --wal-dir=/backup/wal \ + --target-lsn=15420 + +# Възстановяване до конкретно време +./build/baradadb --recover \ + --checkpoint=/backup/snapshot.db \ + --wal-dir=/backup/wal \ + --target-time="2025-01-15T10:30:00Z" +``` + +### Възстановяване чрез SQL + +Можете също да възстановявате директно чрез BaraQL: + +```sql +RECOVER TO TIMESTAMP '2026-05-07T12:00:00'; +``` + +### Инкрементални Backups + +Инкременталните backups копират само променени SSTables: + +```bash +./build/baradadb --backup-incremental \ + --last-backup=/backup/previous \ + --output=/backup/incremental_$(date +%Y%m%d) +``` + +## Репликация като Backup + +За непрекъсната защита използвайте streaming репликация: + +### Primary + +```bash +BARADB_REPLICATION_ENABLED=true \ +BARADB_REPLICATION_MODE=async \ +./build/baradadb +``` + +### Replica + +```bash +BARADB_REPLICATION_ENABLED=true \ +BARADB_REPLICATION_PRIMARY=primary:9472 \ +./build/baradadb +``` + +## Disaster Recovery + +### Процедури за Възстановяване + +#### Сценарий 1: Повреда на Единичен Файл + +```bash +# Идентифициране на повреден SSTable от логовете +# Възстановяване на конкретен SSTable от backup +cp /backup/sstables/000012.sst ./data/sstables/ + +# Възстановяване на индекса +./build/baradadb --rebuild-index +``` + +#### Сценарий 2: Пълна Загуба на Данни + +```bash +# 1. Възстановяване на последния snapshot +cp /backup/snapshot.db ./data/ + +# 2. Преиграване на WAL +./build/baradadb --recover --wal-dir=/backup/wal + +# 3. Проверка +curl http://localhost:9470/health +``` + +#### Сценарий 3: Отказ на Възел в Клъстер + +```bash +# За Raft клъстери, просто стартирайте нов възел +BARADB_RAFT_NODE_ID=newnode \ +BARADB_RAFT_PEERS=node1:9001,node2:9001 \ +./build/baradadb + +# Новият възел ще навакса чрез Raft log репликация +``` + +## Верификация на Backup + +Винаги проверявайте backups: + +```bash +# Възстановяване във временна директория +./build/baradadb --recover \ + --checkpoint=/backup/snapshot.db \ + --data-dir=/tmp/verify_data + +# Проверка на консистентност +curl http://localhost:9470/api/admin/check +``` + +## Изисквания за Съхранение + +| Тип Backup | Размер | Честота | Задържане | +|------------|--------|---------|-----------| +| Пълен snapshot | ~1× размер на данните | Ежедневно | 7 дни | +| Инкрементален | ~0.1× размер на данните | На всеки час | 24 часа | +| WAL архив | ~0.05× размер на данните / ден | Непрекъснато | 30 дни | + +## Най-добри Практики + +1. **Тествайте възстановяването редовно** — Backup, който не може да бъде възстановен, е безполезен +2. **Съхранявайте backups извън локацията** — Използвайте S3, GCS или Azure Blob +3. **Криптирайте backups** — Използвайте `gpg` или криптиране на ниво ОС +4. **Мониторирайте backup задачите** — Алармирайте при неуспешни backups +5. **Документирайте RTO/RPO** — Знайте целите си за време и точка на възстановяване + +### Качване на Backup в Облак + +```bash +# Качване в S3 +aws s3 cp /backup/snapshot.db s3://my-bucket/baradb/ + +# Качване в GCS +gsutil cp /backup/snapshot.db gs://my-bucket/baradb/ + +# Качване в Azure +az storage blob upload \ + --container-name backups \ + --file /backup/snapshot.db \ + --name baradb/snapshot.db +``` diff --git a/docs/bg/baraql.md b/docs/bg/baraql.md index ca2bf9f..82b7393 100644 --- a/docs/bg/baraql.md +++ b/docs/bg/baraql.md @@ -2,39 +2,160 @@ BaraQL е SQL-съвместим език за заявки с разширения за графи, вектори и документи. +## Типове Данни + +| Тип | Описание | Пример | +|------|----------|--------| +| `null` | Null стойност | `null` | +| `bool` | Булев | `true`, `false` | +| `int8` | 8-битов signed integer | `127` | +| `int16` | 16-битов signed integer | `32767` | +| `int32` | 32-битов signed integer | `2147483647` | +| `int64` | 64-битов signed integer | `9223372036854775807` | +| `float32` | 32-битов float | `3.14` | +| `float64` | 64-битов float | `3.14159265359` | +| `str` | UTF-8 низ | `'hello'` | +| `bytes` | Сурови байтове | `0xDEADBEEF` | +| `array` | Хомогенен масив | `[1, 2, 3]` | +| `vector` | Float32 вектор | `[0.1, 0.2, 0.3]` | +| `vector(n)` | Float32 вектор с фиксирана размерност (SQL) | `VECTOR(768)` | +| `object` | Ключ-стойност обект | `{"a": 1}` | +| `datetime` | ISO 8601 времеви печат | `'2025-01-15T10:30:00Z'` | +| `uuid` | UUID v4 | `'550e8400-e29b-41d4-a716-446655440000'` | +| `json` | JSON документ | `{"key": "value"}` | +| `jsonb` | Бинарен JSON (валидиран) | `{"key": "value"}` | + ## Основни Заявки ### SELECT ```sql -SELECT name, age FROM users WHERE age > 18 ORDER BY name LIMIT 10; +-- Всички колони +SELECT * FROM users; + +-- Конкретни колони +SELECT name, age FROM users; + +-- Псевдоними +SELECT name AS full_name, age AS years FROM users; + +-- DISTINCT +SELECT DISTINCT department FROM employees; + +-- LIMIT и OFFSET +SELECT * FROM users LIMIT 10 OFFSET 20; +``` + +### WHERE + +```sql +-- Оператори за сравнение +SELECT * FROM users WHERE age > 18; +SELECT * FROM users WHERE age >= 18 AND age <= 65; +SELECT * FROM users WHERE name = 'Alice'; +SELECT * FROM users WHERE name != 'Bob'; + +-- Диапазон +SELECT * FROM users WHERE age BETWEEN 18 AND 65; + +-- Принадлежност към множество +SELECT * FROM users WHERE department IN ('Engineering', 'Sales'); + +-- Търсене по шаблон +SELECT * FROM users WHERE name LIKE 'A%'; +SELECT * FROM users WHERE name ILIKE 'alice'; -- Case-insensitive + +-- NULL проверки +SELECT * FROM users WHERE email IS NOT NULL; + +-- Логически оператори +SELECT * FROM users WHERE age > 18 AND (department = 'Engineering' OR department = 'Sales'); +``` + +### ORDER BY + +```sql +-- Възходящ (по подразбиране) +SELECT * FROM users ORDER BY age; + +-- Низходящ +SELECT * FROM users ORDER BY age DESC; + +-- Множество колони +SELECT * FROM users ORDER BY department ASC, age DESC; ``` ### INSERT ```sql +-- Един ред INSERT users { name := 'Alice', age := 30 }; + +-- С явен тип +INSERT User { name := 'Alice', age := 30 }; + +-- Множество редове +INSERT users { + { name := 'Alice', age := 30 }, + { name := 'Bob', age := 25 } +}; ``` ### UPDATE ```sql +-- Обнови всички редове +UPDATE users SET status = 'active'; + +-- Условно обновяване UPDATE users SET age = 31 WHERE name = 'Alice'; + +-- Обновяване на няколко колони +UPDATE users SET age = 32, status = 'premium' WHERE name = 'Alice'; ``` ### DELETE ```sql -DELETE FROM users WHERE name = 'Bob'; +-- Изтрий всички редове +DELETE FROM users; + +-- Условно изтриване +DELETE FROM users WHERE age < 18; ``` ## Агрегати и Групиране +### Агрегатни Функции + +| Функция | Описание | +|----------|-----------| +| `count(*)` | Брой на всички редове | +| `count(column)` | Брой на не-NULL стойности | +| `sum(column)` | Сума на стойностите | +| `avg(column)` | Средно аритметично | +| `min(column)` | Минимална стойност | +| `max(column)` | Максимална стойност | +| `stddev(column)` | Стандартно отклонение | +| `variance(column)` | Дисперсия | + +### GROUP BY + ```sql -SELECT department, count(*), avg(salary) +SELECT department, count(*) as emp_count, avg(salary) as avg_salary +FROM employees +GROUP BY department; + +-- С HAVING +SELECT department, count(*) as emp_count FROM employees GROUP BY department HAVING count(*) > 5; + +-- Множествено групиране +SELECT department, role, count(*), avg(salary) +FROM employees +GROUP BY department, role; ``` ## JOINs @@ -49,15 +170,85 @@ INNER JOIN orders o ON u.id = o.user_id; SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id; + +-- RIGHT JOIN +SELECT u.name, o.total +FROM users u +RIGHT JOIN orders o ON u.id = o.user_id; + +-- FULL JOIN +SELECT u.name, o.total +FROM users u +FULL JOIN orders o ON u.id = o.user_id; + +-- CROSS JOIN +SELECT u.name, p.name +FROM users u +CROSS JOIN products p; + +-- Множество JOINs +SELECT u.name, o.id, p.name +FROM orders o +JOIN users u ON o.user_id = u.id +JOIN products p ON o.product_id = p.id; + +-- Self JOIN +SELECT e.name, m.name as manager +FROM employees e +JOIN employees m ON e.manager_id = m.id; ``` ## CTEs (Common Table Expressions) ```sql +-- Единичен CTE WITH active_users AS ( SELECT * FROM users WHERE active = true ) SELECT * FROM active_users; + +-- Множество CTEs +WITH + recent AS ( + SELECT * FROM orders WHERE date > '2025-01-01' + ), + totals AS ( + SELECT user_id, sum(amount) as total FROM recent GROUP BY user_id + ) +SELECT u.name, t.total +FROM users u +JOIN totals t ON u.id = t.user_id; + +-- Рекурсивен CTE +WITH RECURSIVE subordinates AS ( + SELECT id, name, manager_id FROM employees WHERE name = 'CEO' + UNION ALL + SELECT e.id, e.name, e.manager_id + FROM employees e + JOIN subordinates s ON e.manager_id = s.id +) +SELECT * FROM subordinates; +``` + +## Подзаявки + +```sql +-- Подзаявка в SELECT +SELECT name, (SELECT count(*) FROM orders WHERE user_id = u.id) as order_count +FROM users u; + +-- Подзаявка в FROM +SELECT * FROM (SELECT id, name FROM users WHERE active = true) AS active; + +-- Подзаявка в WHERE (IN) +SELECT name FROM users WHERE id IN (SELECT user_id FROM orders); + +-- Подзаявка в WHERE (EXISTS) +SELECT name FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id); + +-- Корелирана подзаявка +SELECT name FROM users u +WHERE age > (SELECT avg(age) FROM users WHERE department = u.department); ``` ## CASE Изрази @@ -65,54 +256,114 @@ SELECT * FROM active_users; ```sql SELECT name, CASE - WHEN age < 18 THEN 'minor' + WHEN age < 13 THEN 'child' + WHEN age < 20 THEN 'teenager' WHEN age < 65 THEN 'adult' ELSE 'senior' END AS category FROM users; + +-- Прост CASE +SELECT name, + CASE department + WHEN 'Engineering' THEN 'Tech' + WHEN 'Sales' THEN 'Revenue' + ELSE 'Other' + END AS division +FROM employees; ``` -## Схема +## Set Операции + +```sql +-- UNION (различни) +SELECT name FROM customers +UNION +SELECT name FROM suppliers; + +-- UNION ALL (с дубликати) +SELECT name FROM customers +UNION ALL +SELECT name FROM suppliers; + +-- INTERSECT +SELECT name FROM customers +INTERSECT +SELECT name FROM suppliers; + +-- EXCEPT +SELECT name FROM customers +EXCEPT +SELECT name FROM suppliers; +``` + +## Дефиниране на Схема + +### CREATE TYPE ```sql CREATE TYPE Person { name: str, age: int32 }; -``` -## Векторно Търсене - -```sql -INSERT articles { - title := 'Nim Programming', - embedding := [0.1, 0.2, 0.3, ...] +-- Със задължителни полета +CREATE TYPE User { + email: str REQUIRED, + name: str, + age: int32, + created_at: datetime DEFAULT now() }; -SELECT title FROM articles -ORDER BY cosine_distance(embedding, [0.1, 0.2, 0.3, ...]) -LIMIT 5; +-- С връзки +CREATE TYPE Movie { + title: str, + year: int32, + director: Person +}; + +-- С изчислими свойства +CREATE TYPE Employee { + name: str, + base_salary: float64, + bonus: float64, + total_compensation: float64 COMPUTED (base_salary + bonus) +}; ``` -## Графични Шаблони +### Наследяване ```sql -MATCH (p:Person)-[:KNOWS]->(friend:Person) -WHERE p.name = 'Alice' -RETURN friend.name; +CREATE TYPE Animal { + name: str +}; + +CREATE TYPE Dog EXTENDING Animal { + breed: str +}; + +CREATE TYPE Cat EXTENDING Animal { + indoor: bool +}; ``` -## Пълнотекстово Търсене +### Индекси ```sql --- Създаване на FTS индекс -CREATE INDEX idx_fts ON articles(body) USING FTS; - --- Търсене с BM25 ранжиране -SELECT * FROM articles WHERE body @@ 'database programming'; +CREATE INDEX idx_users_name ON users(name); +CREATE UNIQUE INDEX idx_users_email ON users(email); +CREATE INDEX idx_users_age ON users(age) USING btree; +CREATE INDEX idx_vectors ON items(embedding) USING hnsw; ``` -## JSON Оператори +### DROP + +```sql +DROP TYPE User; +DROP INDEX idx_users_name; +``` + +### JSON Оператори за Път ```sql -- Извличане на JSON поле като JSON @@ -122,16 +373,292 @@ SELECT data->'name' FROM users; SELECT data->>'name' FROM users; ``` -## Set Операции +### Пълнотекстово Търсене (SQL) ```sql -SELECT name FROM customers -UNION ALL -SELECT name FROM suppliers; +-- Създаване на FTS индекс с BM25 +CREATE INDEX idx_fts ON articles(body) USING FTS; + +-- Търсене с BM25 ранжиране +SELECT * FROM articles WHERE body @@ 'machine learning'; ``` -## Възстановяване до Момент във Времето +### Възстановяване до Момент във Времето ```sql RECOVER TO TIMESTAMP '2026-05-07T12:00:00'; -``` \ No newline at end of file +``` + +## Векторно Търсене (SQL) + +### Създаване на Векторни Колони + +```sql +CREATE TABLE items ( + id INT PRIMARY KEY, + embedding VECTOR(768) +); +``` + +### Вмъкване на Вектори + +```sql +INSERT INTO items (id, embedding) VALUES (1, '[0.1, 0.2, 0.3, 0.4]'); +``` + +### Функции за Разстояние + +```sql +-- Косинусово разстояние (0 = идентични, 2 = противоположни) +SELECT id, cosine_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist +FROM items; + +-- Евклидово / L2 разстояние +SELECT id, euclidean_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist +FROM items; + +-- L2 разстояние с <-> оператор +SELECT id, embedding <-> '[0.1, 0.2, 0.3, 0.4]' AS dist +FROM items; + +-- Скаларно произведение (отрицателно dot product) +SELECT id, inner_product(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist +FROM items; + +-- Манхатън / L1 разстояние +SELECT id, l1_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist +FROM items; +``` + +### Търсене на Най-близки Съседи + +```sql +-- Топ-10 най-близки съседи по косинусово разстояние +SELECT id FROM items +ORDER BY cosine_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') ASC +LIMIT 10; + +-- Топ-5 най-близки съседи по евклидово разстояние +SELECT id FROM items +ORDER BY embedding <-> '[0.1, 0.2, 0.3, 0.4]' +LIMIT 5; + +-- С филтър по метаданни +SELECT id FROM items +WHERE category = 'tech' +ORDER BY cosine_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') +LIMIT 5; +``` + +### Векторни Индекси + +```sql +-- Създаване на HNSW индекс за приблизително търсене на най-близки съседи +CREATE INDEX idx_items_vec ON items(embedding) USING hnsw; + +-- Поддържани индекс методи: hnsw, ivfpq +``` + +## Графични Шаблони + +```sql +-- Намиране на приятели на Alice +MATCH (p:Person)-[:KNOWS]->(friend:Person) +WHERE p.name = 'Alice' +RETURN friend.name; + +-- Намиране на най-кратък път +MATCH path = shortestPath((a:Person)-[:KNOWS*1..5]->(b:Person)) +WHERE a.name = 'Alice' AND b.name = 'Bob' +RETURN path; + +-- Намиране на всички връзки +MATCH (p:Person)-[r]->(other) +WHERE p.name = 'Alice' +RETURN type(r), other.name; + +-- Множество преходи +MATCH (a:Person)-[:KNOWS]->(b:Person)-[:KNOWS]->(c:Person) +WHERE a.name = 'Alice' +RETURN c.name; + +-- С агрегати +MATCH (p:Person)-[:KNOWS]->(friend) +RETURN p.name, count(friend) as friend_count +ORDER BY friend_count DESC; +``` + +## Пълнотекстово Търсене + +```sql +-- Основно търсене +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('database programming'); + +-- С релевантност +SELECT title, relevance() +FROM articles +WHERE MATCH(title, body) AGAINST('Nim language') +ORDER BY relevance() DESC; + +-- Булев режим +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('+Nim -Python' IN BOOLEAN MODE); + +-- Fuzzy търсене +SELECT * FROM articles +WHERE MATCH(title) AGAINST('programing' WITH FUZZINESS 2); +``` + +## Транзакции + +```sql +BEGIN; +INSERT users { name := 'Alice', age := 30 }; +INSERT orders { user_id := last_insert_id(), total := 100 }; +COMMIT; + +-- С savepoint +BEGIN; +INSERT users { name := 'Bob', age := 25 }; +SAVEPOINT sp1; +INSERT orders { user_id := last_insert_id(), total := 200 }; +-- Грешка, връщане до savepoint +ROLLBACK TO sp1; +COMMIT; +``` + +## Потребителски Функции (UDF) + +```sql +-- Регистриране на UDF +CREATE FUNCTION greet(name str) -> str { + RETURN 'Hello, ' || name || '!'; +}; + +-- Използване +SELECT greet(name) FROM users; + +-- Вградени функции +SELECT abs(-5), sqrt(16), lower('HELLO'), len('test'); +``` + +## Подсказки за Заявки (Query Hints) + +```sql +-- Форсиране на индекс +SELECT /*+ USE_INDEX(idx_users_age) */ * FROM users WHERE age > 18; + +-- Форсиране на приблизително векторно търсене +SELECT /*+ APPROXIMATE */ * FROM vectors +ORDER BY cosine_distance(embedding, [...]) +LIMIT 10; + +-- Паралелно изпълнение +SELECT /*+ PARALLEL(4) */ * FROM large_table; +``` + +## Window Функции + +```sql +-- Функции за ранжиране +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- Стойностни функции +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- Функции за разпределение +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### Рамкови Спецификации + +```sql +-- ROWS рамка +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- RANGE рамка +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## Multi-Tenant ERP + +BaraDB поддържа множество компании (тенанти) в една инстанция чрез **Row-Level Security (RLS)** и **сесийни променливи**. + +### Сесийни Променливи + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### Текущ Потребител / Роля + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### RLS Изолация на Тенанти + +```sql +-- Включване на RLS за таблица +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- Създаване на политика за филтриране по тенант +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- Всяка сесия вижда само своите данни +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- само редове на company-a +``` + +### Защо Multi-Tenant? + +- **Една инстанция, много тенанти** — няма нужда от 100 отделни бази данни +- **JSONB документи** — гъвкаво съхранение без схема, лесно добавяне на полета за всеки тенант +- **RLS гарантира изолация** — базата данни налага границите между тенанти, не само приложението + +## Поддържани Ключови Думи + +| Категория | Ключови думи | +|-----------|-------------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Транзакции | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Графи | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Вектори | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (BM25 съвпадение) | +| Recovery | RECOVER TO TIMESTAMP | +| Функции | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Сесийни | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Функции | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | diff --git a/docs/bg/changelog.md b/docs/bg/changelog.md new file mode 100644 index 0000000..fecdb50 --- /dev/null +++ b/docs/bg/changelog.md @@ -0,0 +1,223 @@ +# Списък с Промени (Changelog) + +Всички забележителни промени в BaraDB са документирани в този файл. + +## [Unreleased] — SQL:2023 Стабилизация + +### Поправки + +- **GROUPING SETS изпълнение** — `lowerSelect` вече създава `irpkGroupBy` когато `selGroupingSetsKind != gskNone`, дори ако `selGroupBy` е празен. Преди това заявки като `GROUP BY GROUPING SETS ((dept), ())` напълно заобикаляха grouping executor-a. +- **FTS CREATE INDEX docId несъответствие** — `CREATE INDEX ... USING FTS` вече изчислява `docId` като хеш на `tableName.$key`, консистентно с DML операциите (`INSERT`/`UPDATE`/`DELETE`). Преди това създаването на индекс използваше последователни ID-та (0, 1, 2...), което причиняваше `@@` заявките никога да не намират индексирани документи. +- **Тестова изолация (всички сюити)** — Всички извиквания на `newLSMTree("")` са заменени с уникални временни директории за всеки сюит. Елиминира проблеми с натрупване на WAL и нестабилни тестове от споделено състояние между тестове. +- **Window frame parser** — `parseFrameBoundary` вече не консумира `tkRow` след `tkCurrent` неправилно (използваше `tkRows`). Също така е поправен конфликт на ключовата дума `tkRow` с парсването на `ENABLE ROW LEVEL SECURITY`. +- **ORDER BY + SELECT проекция** — `lowerSelect` вече поставя `irpkSort` преди `irpkProject`, което позволява `ORDER BY` по колони, които не присъстват в `SELECT` списъка. +- **UNPIVOT изпълнение** — Проверено и поправено липсващо тестово покритие за UNPIVOT трансформация. + +### Добавки + +- **JSON оператори** — `@>` (съдържа), `<@` (съдържа се в), `?` (има ключ), `?|` (има някой от), `?&` (има всички) вече се поддържат в lexer, parser и executor. +- **Window frame изпълнение** — `ROWS BETWEEN X PRECEDING AND Y FOLLOWING` / `CURRENT ROW` граници на рамката вече се спазват от `FIRST_VALUE` и `LAST_VALUE`. +- **Сесийни променливи** — `SET var_name = value` и `current_setting('var_name')` за ключ/стойност съхранение на ниво връзка. +- **Текущ потребител/роля** — `current_user` и `current_role` SQL ключови думи връщат потребителя и ролята на автентикираната сесия. +- **Auth-executor мост** — Сървърът и HTTP сървърът вече попълват `ExecutionContext.currentUser` и `ExecutionContext.currentRole` след JWT/SCRAM автентикация. +- **Multi-tenant RLS** — Row-Level Security политиките вече могат да реферират `current_user`, `current_role` и `current_setting('app.tenant_id')` за изолация на данни по тенант. + +## [1.1.0] — 2026-05-13 + +### Добавки + +- **Client SDKs v1.1.0** — Пълнофункционални клиенти за всички езици: + - JavaScript: TypeScript дефиниции, package.json, примери, unit и integration тестове + - Python: Преструктуриран като пакет (`baradb/` с `__init__.py` и `core.py`), pyproject.toml, примери, тестове (query builder, wire protocol, integration) + - Nim: Примери, integration тестове, README + - Rust: Примери, integration тестове, подобрен Cargo.toml +- **SCRAM-SHA-256 Автентикация** — RFC 7677 съвместима автентикация с PBKDF2 + HMAC + SHA-256 + nonce/salt генериране +- **HTTP SCRAM Endpoints** — `/auth/scram/start` + `/auth/scram/finish` в HTTP сървъра +- **Docker Compose Тестова Конфигурация** — `docker-compose.test.yml` за тестови среди +- **CI/CD Clients Pipeline** — `.github/workflows/clients-ci.yml` за автоматизирано тестване на клиенти + +### Поправки + +- **Query Executor** — Унарен минус (`irNeg`) вече работи коректно в SELECT и WHERE клаузи +- **Distributed Transactions** — Rollback след commit опит вече не нарушава атомарността +- **Sharding** — Протокол за миграция на данни с TCP + `scanAll` на LSM +- **Raft** — Поправено изчисление на мнозинство за четен брой нодове +- **MVCC** — Прекъснатите транзакции вече не стават видими +- **LSM-Tree** — Поправена загуба на данни при презаписване на immutable memtable; поправено сортиране на SSTable търсене +- **Auth** — JWT подписът е променен на HMAC-SHA256 (вече не е тривиално forgeable); валидация на токен изтичане (`exp`/`nbf`/`iat`); сравнението на подписи вече е constant-time +- **Recovery** — `summary()` вече не мутира базата данни +- **Wire Protocol** — 64MB лимит + bounds проверки + max дълбочина за предотвратяване на OOM/DoS +- **SQL Injection** — `exprToSql` вече escape-ва единични кавички +- **ReDoS** — `irLike`/`irILike` вече escape-ват regex метасимволи +- **Graph** — `addEdge` вече проверява съществуването на възел +- **Vector** — Валидация на несъответствие на размерности + HNSW заключване +- **FTS** — UTF-8 токенизацията вече използва runes вместо байтове +- **Build** — `nim.cfg` добавя `-d:ssl`, така че `nimble build` работи без флагове; `--threads:on` добавен към всички CI команди + +### Промени + +- **Версията е вдигната до 1.1.0** във всички компоненти (сървър, Docker изображения, клиенти, CLI) +- **README** — Версионният badge е обновен; всички feature таблици вече реферират v1.1.0 +- **TLA+ Формална Верификация** — Добавени `crossmodal.tla`, `backup.tla`, `recovery.tla`; symmetry reduction във всички 9 спецификации +- **Чист build** — 0 компилаторни предупреждения на Nim 2.2.10 + +## [0.1.0] — 2025-01-15 + +### Добавки + +- **Ядро за Съхранение** + - LSM-Tree с MemTable, WAL, SSTables и size-tiered compaction + - B-Tree подреден индекс с range сканиране и MVCC copy-on-write + - Bloom филтри за ефективно пропускане на SSTable + - Memory-mapped I/O за SSTable четене + - LRU page cache с проследяване на hit rate + +- **Query Engine (BaraQL)** + - SQL-съвместим lexer с 80+ типа токени + - Recursive descent parser генериращ AST с 25+ вида възли + - Intermediate representation (IR) за планове за изпълнение + - Code generator превеждащ IR към storage операции + - Adaptive query optimizer с cross-modal планиране + - Query executor с паралелизация + +- **BaraQL Езикови Възможности** + - SELECT, INSERT, UPDATE, DELETE + - WHERE, ORDER BY, LIMIT, OFFSET + - GROUP BY, HAVING, агрегатни функции (count, sum, avg, min, max) + - INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN + - CTEs (Common Table Expressions) с WITH + - Подзаявки (EXISTS, IN, корелирани) + - CASE изрази + - UNION, INTERSECT, EXCEPT + - Дефиниране на схема: CREATE TYPE, DROP TYPE + +- **Vector Engine** + - HNSW индекс за приблизително търсене на най-близки съседи + - IVF-PQ индекс за мащабно векторно търсене + - SIMD-оптимизирани функции за разстояние (cosine, L2, dot product, Manhattan) + - Квантуване: scalar 8-bit/4-bit, product quantization, binary + - Филтриране по метаданни при векторно търсене + +- **Graph Engine** + - Adjacency list съхранение за насочени графи с тегла + - BFS и DFS обхождане + - Dijkstra най-кратък път + - PageRank важност на възли + - Louvain community detection + - Subgraph pattern matching + - Cypher-подобен graph query parser + +- **Full-Text Search** + - Inverted index с term-document mapping + - BM25 алгоритъм за ранжиране + - TF-IDF оценяване + - Fuzzy търсене с Levenshtein разстояние + - Wildcard/regex търсене + - Многоезични токенизатори (английски, български, немски, френски, руски) + +- **Columnar Storage** + - Колонково съхранение за аналитични заявки + - RLE (Run-Length Encoding) компресия + - Dictionary encoding за колони с ниска кардиналност + - SIMD-ускорени агрегати + +- **Транзакции** + - MVCC (Multi-Version Concurrency Control) със snapshot изолация + - Deadlock детекция чрез wait-for граф + - Write-ahead log за устойчивост + - Savepoints и частичен rollback + +- **Протоколен Слой** + - Бинарен wire протокол с 16 типа съобщения + - HTTP/REST JSON API + - WebSocket стрийминг + - Connection pooling + - JWT-базирана автентикация + - Token-bucket rate limiting + - TLS/SSL с автоматично генерирани сертификати + +- **Система за Схеми** + - Силна типова система с 17 нативни типа + - Наследяване на типове с multi-base поддръжка + - Property links между типове + - Schema diffing и миграции + - Изчислими свойства + +- **Разпределени Системи** + - Raft консенсус (leader election, log replication) + - Hash, range и consistent-hash шардиране + - Sync/async/semi-sync репликация + - Gossip протокол за управление на членство + - Two-phase commit за разпределени транзакции + +- **Cross-Modal Заявки** + - Унифициран език за заявки през всички storage двигатели + - Cross-engine predicate pushdown + - Оптимизирани планове за изпълнение за multi-modal заявки + +- **Backup & Recovery** + - Online snapshots без прекъсване + - Point-in-time recovery чрез WAL replay + - Инкрементални backups + +- **Client SDKs** + - JavaScript/TypeScript клиент с бинарен протокол + - Python клиент със sync и async API + - Nim embedded режим и клиентска библиотека + - Rust клиент (async) + +- **Операции** + - Интерактивен CLI shell (BaraQL REPL) + - Структурирано логване (JSON и текстови формати) + - Prometheus-съвместим metrics endpoint + - Health и readiness проби + - CPU/memory profiling endpoints + +- **Docker Поддръжка** + - Multi-stage Dockerfile (Alpine Linux) + - Docker Compose конфигурация + - Health checks + +### Производителност + +- LSM-Tree: 580K записа/s, 720K четения/s +- B-Tree: 1.2M вмъквания/s, 1.5M търсения/s +- Vector SIMD: 850K косинусови разстояния/s (dim=768) +- FTS: 320K документи/s индексиране, 28K заявки/s BM25 +- Graph: 2.5M възела/s вмъкване, 12K BFS обхождания/s +- Бинарен протокол: 380K заявки/s (100 конкурентни връзки) + +### Тестове + +- 262 теста в 56 тестови сюита +- 100% успеваемост + +## [Unreleased] + +### Добавки + +- **Vector SQL Integration** — Пълна поддръжка на векторно търсене на SQL ниво: + - `VECTOR(n)` тип колона в `CREATE TABLE` с валидация на размерност + - `CREATE INDEX ... USING hnsw` / `USING ivfpq` за приблизителни nearest neighbor индекси + - SQL функции за разстояние: `cosine_distance()`, `euclidean_distance()`, `inner_product()`, `l1_distance()`, `l2_distance()` + - `<->` nearest-neighbor оператор (евклидово разстояние) + - `ORDER BY` поддръжка за изрази с векторно разстояние, включително колони извън `SELECT` + - Автоматична поддръжка на HNSW индекс при `INSERT` и `UPDATE` +- **Advanced SQL Engine** — Window функции, MERGE/UPSERT, LATERAL JOIN, PIVOT/UNPIVOT, SQL/PGQ Property Graph, Разширени агрегати (ARRAY_AGG, STRING_AGG, FILTER, GROUPING SETS/ROLLUP/CUBE) +- **JavaScript Client — TCP Request Queue** — Вътрешна `_requestQueue` + `_requestLock` за безопасни конкурентни заявки. Множество паралелни извиквания на `query()` / `execute()` / `ping()` вече не размесват бинарни frame-ове по връзката. + +### Поправки + +- **Query Executor — Ескейпване на Стойности** — `execInsert` вече правилно ескейпва запетаи и знаци за равенство в стойностите на колоните, поправяйки корупция на съхранението за векторни литерали като `[1.0, 2.0, 3.0]` +- **Query Planner — ORDER BY Проекция** — `irpkSort` вече се поставя преди `irpkProject` в IR плана, позволявайки на `ORDER BY` да реферира колони, които не са селектирани +- **Wire Protocol — Big-Endian Float Сериализация** — `FLOAT32`/`FLOAT64` и float стойностите във вектори вече се сериализират в big-endian byte order, съвпадайки с `readFloatBE()` / `readDoubleBE()` на клиента и осигурявайки междуплатформена числова точност. +- **Gossip Protocol — Async UDP Socket** — Заменен синхронният `newSocket` + блокиращ `recvFrom` с `newAsyncSocket` + `await recvFrom`, предотвратявайки замръзване на async event loop-а до пристигане на UDP пакет. + +### Планирани + +- Query plan caching +- Materialized views +- Геопространствен индекс +- Time-series оптимизации +- CDC (Change Data Capture) стрийминг +- Федеративни заявки между BaraDB инстанции diff --git a/docs/bg/clients.md b/docs/bg/clients.md new file mode 100644 index 0000000..2f99a11 --- /dev/null +++ b/docs/bg/clients.md @@ -0,0 +1,285 @@ +# Client SDKs + +BaraDB предоставя официални клиентски библиотеки за JavaScript/TypeScript, Python, Nim и Rust. + +## JavaScript / TypeScript + +### Инсталация + +```bash +npm install baradb +# или +yarn add baradb +``` + +### Основна Употреба + +```typescript +import { Client } from 'baradb'; + +const client = new Client('localhost', 9472); +await client.connect(); + +// Проста заявка +const result = await client.query('SELECT name, age FROM users WHERE age > 18'); +console.log(result.rows); + +// Параметризирана заявка +const result2 = await client.query( + 'SELECT * FROM users WHERE name = ?', + ['Alice'] +); + +// Batch вмъкване +await client.batch([ + "INSERT users { name := 'Alice', age := 30 }", + "INSERT users { name := 'Bob', age := 25 }", +]); + +// Транзакции +await client.begin(); +await client.query("INSERT orders { total := 100 }"); +await client.query("UPDATE users SET balance = balance - 100 WHERE name = 'Alice'"); +await client.commit(); + +await client.close(); +``` + +### Конкурентни Заявки + +JavaScript клиентът автоматично сериализира конкурентни заявки през една TCP връзка чрез вътрешна опашка. Можете безопасно да изпращате множество паралелни операции — техните бинарни frame-ове няма да се размесят: + +```typescript +const [users, orders, stats] = await Promise.all([ + client.query('SELECT * FROM users'), + client.query('SELECT * FROM orders'), + client.query('SELECT count(*) FROM visits') +]); +``` + +### WebSocket Стрийминг + +```typescript +import { WebSocketClient } from 'baradb/ws'; + +const ws = new WebSocketClient('ws://localhost:9471'); +ws.onMessage = (data) => console.log(data); +await ws.connect(); +await ws.send('SUBSCRIBE updates'); +``` + +## Python + +### Инсталация + +```bash +pip install baradb +``` + +### Основна Употреба + +```python +from baradb import Client + +client = Client("localhost", 9472) +client.connect() + +# Проста заявка +result = client.query("SELECT name, age FROM users WHERE age > 18") +for row in result: + print(row["name"], row["age"]) + +# Параметризирана заявка +result = client.query( + "SELECT * FROM users WHERE name = ?", + ["Alice"] +) + +# Batch операции +client.batch([ + "INSERT users { name := 'Alice', age := 30 }", + "INSERT users { name := 'Bob', age := 25 }", +]) + +# Context manager (автоматично затваряне) +with Client("localhost", 9472) as c: + result = c.query("SELECT count(*) FROM users") + print(result[0]["count"]) +``` + +### Async Клиент + +```python +import asyncio +from baradb import AsyncClient + +async def main(): + client = AsyncClient("localhost", 9472) + await client.connect() + result = await client.query("SELECT * FROM users") + print(result.rows) + await client.close() + +asyncio.run(main()) +``` + +## Nim (Вграден Режим) + +### Добавяне на Зависимост + +```nim +# Във вашия .nimble файл +requires "barabadb >= 1.1.0" +``` + +### Вградена Употреба + +```nim +import barabadb/storage/lsm +import barabadb/storage/btree +import barabadb/vector/engine +import barabadb/graph/engine + +# Key-Value store +var db = newLSMTree("./data") +db.put("user:1", cast[seq[byte]]("Alice")) +let (found, value) = db.get("user:1") +db.close() + +# B-Tree индекс +var btree = newBTreeIndex[string, int]() +btree.insert("Alice", 30) +let ages = btree.get("Alice") + +# Векторно търсене +var idx = newHNSWIndex(dimensions = 128) +idx.insert(1, @[0.1'f32, 0.2, 0.3], {"category": "A"}.toTable) +let results = idx.search(@[0.1'f32, 0.2, 0.3], k = 10) + +# Графи +var g = newGraph() +let alice = g.addNode("Person", {"name": "Alice"}.toTable) +let bob = g.addNode("Person", {"name": "Bob"}.toTable) +discard g.addEdge(alice, bob, "knows") +let path = g.shortestPath(alice, bob) +``` + +### Клиентска Библиотека + +```nim +import barabadb/client/client + +var c = newBaraClient("localhost", 9472) +c.connect() +let result = c.query("SELECT name FROM users") +for row in result.rows: + echo row["name"] +c.close() +``` + +## Rust + +### Добавяне на Зависимост + +```toml +[dependencies] +baradb = "0.1" +tokio = { version = "1", features = ["full"] } +``` + +### Основна Употреба + +```rust +use baradb::Client; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let mut client = Client::connect("localhost:9472").await?; + + let result = client + .query("SELECT name, age FROM users WHERE age > 18") + .await?; + + for row in result.rows { + println!("{} is {} years old", row["name"], row["age"]); + } + + client.close().await?; + Ok(()) +} +``` + +## HTTP/REST (Езиково Независим) + +Всички езици могат да използват HTTP/REST API директно: + +```bash +# Заявка +curl -X POST http://localhost:9470/api/query \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"query": "SELECT * FROM users WHERE age > 18"}' + +# Вмъкване +curl -X POST http://localhost:9470/api/query \ + -H "Content-Type: application/json" \ + -d '{"query": "INSERT users { name := \"Alice\", age := 30 }"}' + +# Схема +curl http://localhost:9470/api/schema + +# Health +curl http://localhost:9470/health + +# Метрики +curl http://localhost:9470/metrics +``` + +## Connection Pooling + +Всички официални клиенти поддържат connection pooling: + +### JavaScript + +```typescript +import { Pool } from 'baradb'; + +const pool = new Pool({ + host: 'localhost', + port: 9472, + min: 5, + max: 50, + idleTimeout: 30000, +}); + +const client = await pool.acquire(); +try { + const result = await client.query('SELECT 1'); +} finally { + pool.release(client); +} +``` + +### Python + +```python +from baradb import Pool + +pool = Pool("localhost", 9472, min_size=5, max_size=50) +with pool.connection() as conn: + result = conn.query("SELECT 1") +``` + +## Съответствие на Типове Данни + +| BaraDB Тип | JavaScript | Python | Nim | Rust | +|------------|------------|--------|-----|------| +| `null` | `null` | `None` | `nil` | `Option::None` | +| `bool` | `boolean` | `bool` | `bool` | `bool` | +| `int8/16/32/64` | `number` | `int` | `int` | `i8/i16/i32/i64` | +| `float32/64` | `number` | `float` | `float32/float64` | `f32/f64` | +| `str` | `string` | `str` | `string` | `String` | +| `bytes` | `Uint8Array` | `bytes` | `seq[byte]` | `Vec` | +| `array` | `Array` | `list` | `seq` | `Vec` | +| `object` | `Object` | `dict` | `Table` | `HashMap` | +| `vector` | `Float32Array` | `list[float]` | `seq[float32]` | `Vec` | diff --git a/docs/bg/columnar.md b/docs/bg/columnar.md new file mode 100644 index 0000000..e7f0967 --- /dev/null +++ b/docs/bg/columnar.md @@ -0,0 +1,58 @@ +# Колонково Съхранение (Columnar) + +Колонково-ориентирано съхранение за аналитични заявки и агрегации. + +## Употреба + +```nim +import barabadb/core/columnar + +var batch = newColumnBatch() +var ageCol = batch.addInt64Col("age") +var nameCol = batch.addStringCol("name") + +ageCol.appendInt64(25) +nameCol.appendString("Alice") +``` + +## Агрегации + +```nim +echo ageCol.sumInt64() +echo ageCol.avgInt64() +echo ageCol.minInt64() +echo ageCol.maxInt64() +echo ageCol.count() +``` + +## Кодиране + +### RLE (Run-Length Encoding) + +```nim +let rle = rleEncode(@[1'i64, 1, 1, 2, 2, 3]) +``` + +### Dictionary Encoding + +```nim +let dict = dictEncode(@["apple", "banana", "apple"]) +``` + +## Типове Колони + +| Тип | Описание | +|------|----------| +| `int32` | 32-битов integer | +| `int64` | 64-битов integer | +| `float32` | 32-битов float | +| `float64` | 64-битов float | +| `string` | Низ с променлива дължина | +| `bool` | Булев | + +## Случаи на Употреба + +- OLAP натоварвания +- Мащабни агрегации +- Data warehousing +- Анализ на времеви редове diff --git a/docs/bg/configuration.md b/docs/bg/configuration.md new file mode 100644 index 0000000..7c422ea --- /dev/null +++ b/docs/bg/configuration.md @@ -0,0 +1,218 @@ +# Конфигурационна Референция + +BaraDB може да се конфигурира чрез **променливи на средата**, **конфигурационен файл** или **командно-редови флагове**. + +## Ред на Приоритет + +1. Командно-редови флагове (най-висок приоритет) +2. Променливи на средата +3. Конфигурационен файл (`baradb.conf` или `baradb.json`) +4. Вградени стойности по подразбиране (най-нисък приоритет) + +## Променливи на Средата + +### Мрежа + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_ADDRESS` | `127.0.0.1` | Адрес за свързване | +| `BARADB_PORT` | `9472` | TCP бинарен протокол порт | +| `BARADB_HTTP_PORT` | `9470` | HTTP/REST API порт | +| `BARADB_WS_PORT` | `9471` | WebSocket порт | + +### Съхранение + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_DATA_DIR` | `./data` | Път до директория за данни | +| `BARADB_MEMTABLE_SIZE_MB` | `64` | Размер на MemTable в MB | +| `BARADB_CACHE_SIZE_MB` | `256` | Размер на page cache в MB | +| `BARADB_WAL_SYNC_INTERVAL_MS` | `0` | Интервал за WAL fsync (0 = всеки запис) | +| `BARADB_COMPACTION_INTERVAL_MS` | `60000` | Интервал за фонов compaction | +| `BARADB_BLOOM_BITS_PER_KEY` | `10` | Bloom филтър битове за ключ | + +### TLS/SSL + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_TLS_ENABLED` | `false` | Включване на TLS | +| `BARADB_CERT_FILE` | — | Път до TLS сертификат | +| `BARADB_KEY_FILE` | — | Път до TLS частен ключ | + +### Сигурност + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_AUTH_ENABLED` | `false` | Включване на автентикация | +| `BARADB_JWT_SECRET` | — | JWT подписващ secret | +| `BARADB_RATE_LIMIT_GLOBAL` | `10000` | Глобални заявки в секунда | +| `BARADB_RATE_LIMIT_PER_CLIENT` | `1000` | Заявки в секунда за клиент | + +### Логване + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_LOG_LEVEL` | `info` | Ниво на логване: debug, info, warn, error | +| `BARADB_LOG_FILE` | — | Път до лог файл (stdout ако е празен) | +| `BARADB_LOG_FORMAT` | `json` | Формат на лога: json, text | + +### Vector Engine + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_VECTOR_M` | `16` | HNSW `M` параметър | +| `BARADB_VECTOR_EF_CONSTRUCTION` | `200` | HNSW `efConstruction` | +| `BARADB_VECTOR_EF_SEARCH` | `64` | HNSW `efSearch` | + +### Graph Engine + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_GRAPH_PAGE_RANK_ITERATIONS` | `20` | Брой итерации на PageRank | +| `BARADB_GRAPH_PAGE_RANK_DAMPING` | `0.85` | PageRank damping фактор | +| `BARADB_GRAPH_LOUVAIN_RESOLUTION` | `1.0` | Louvain резолюционен параметър | + +### Разпределени + +| Променлива | По подр. | Описание | +|------------|----------|----------| +| `BARADB_RAFT_NODE_ID` | — | Уникално ID на възел в клъстер | +| `BARADB_RAFT_PEERS` | — | Списък с адреси на peer-ове, разделени със запетая | +| `BARADB_RAFT_PORT` | `9001` | Raft вътрешен комуникационен порт | +| `BARADB_SHARD_COUNT` | `1` | Брой шардове | +| `BARADB_REPLICATION_FACTOR` | `1` | Фактор на репликация | +| `BARADB_SEED_NODES` | — | Gossip seed възли (host:port, разделени със запетая) | + +## Конфигурационен Файл + +### baradb.conf (INI-подобен) + +```ini +[server] +address = "0.0.0.0" +port = 9472 +http_port = 9470 +ws_port = 9471 + +[storage] +data_dir = "/var/lib/baradb" +memtable_size_mb = 256 +cache_size_mb = 512 +wal_sync_interval_ms = 10 +compaction_interval_ms = 30000 + +[tls] +enabled = true +cert_file = "/etc/baradb/server.crt" +key_file = "/etc/baradb/server.key" + +[auth] +enabled = true +jwt_secret = "change-me-in-production" +rate_limit_global = 10000 +rate_limit_per_client = 1000 + +[logging] +level = "info" +format = "json" +file = "/var/log/baradb/baradb.log" + +[vector] +m = 16 +ef_construction = 200 +ef_search = 64 + +[cluster] +raft_node_id = "node1" +raft_peers = "node2:9001,node3:9001" +``` + +### baradb.json + +```json +{ + "server": { + "address": "0.0.0.0", + "port": 9472, + "http_port": 9470, + "ws_port": 9471 + }, + "storage": { + "data_dir": "/var/lib/baradb", + "memtable_size_mb": 256, + "cache_size_mb": 512 + }, + "tls": { + "enabled": true, + "cert_file": "/etc/baradb/server.crt", + "key_file": "/etc/baradb/server.key" + } +} +``` + +## Командно-редови Флагове + +```bash +./build/baradadb --help +``` + +``` +BaraDB v1.1.0 — Multimodal Database Engine + +Употреба: + baradadb [опции] + +Опции: + -c, --config <файл> Път до конфигурационен файл + -p, --port <порт> TCP бинарен порт (по подр.: 9472) + --http-port <порт> HTTP порт (по подр.: 9470) + --ws-port <порт> WebSocket порт (по подр.: 9471) + -d, --data-dir <дир> Директория за данни (по подр.: ./data) + --tls-cert <файл> TLS сертификатен файл + --tls-key <файл> TLS файл с частен ключ + --log-level <ниво> Ниво на логване: debug, info, warn, error + --log-file <файл> Път до лог файл + --shell Стартиране на интерактивна обвивка + --version Показване на версия + --recover Изпълнение на WAL възстановяване + --checkpoint <файл> Checkpoint за възстановяване + -h, --help Показване на тази помощ +``` + +## Примерни Конфигурации + +### Разработка + +```bash +./build/baradadb \ + --log-level debug \ + --data-dir ./dev_data +``` + +### Продукционен Единичен Възел + +```bash +BARADB_TLS_ENABLED=true \ +BARADB_CERT_FILE=/etc/baradb/server.crt \ +BARADB_KEY_FILE=/etc/baradb/server.key \ +BARADB_AUTH_ENABLED=true \ +BARADB_JWT_SECRET="$(openssl rand -hex 32)" \ +BARADB_LOG_LEVEL=warn \ +BARADB_LOG_FILE=/var/log/baradb/baradb.log \ +BARADB_MEMTABLE_SIZE_MB=256 \ +BARADB_CACHE_SIZE_MB=1024 \ +./build/baradadb +``` + +### Продукционен Клъстер (3 възела) + +```bash +# Възел 1 +BARADB_ADDRESS=0.0.0.0 \ +BARADB_PORT=9472 \ +BARADB_RAFT_NODE_ID=node1 \ +BARADB_RAFT_PEERS=node2:9001,node3:9001 \ +BARADB_SHARD_COUNT=4 \ +BARADB_REPLICATION_FACTOR=2 \ +./build/baradadb +``` diff --git a/docs/bg/crossmodal.md b/docs/bg/crossmodal.md new file mode 100644 index 0000000..6c7f5cd --- /dev/null +++ b/docs/bg/crossmodal.md @@ -0,0 +1,101 @@ +# Cross-Modal Заявки + +Уникалната способност на BaraDB да изпълнява заявки, обхващащи множество storage двигатели в една унифицирана BaraQL заявка. + +## Преглед + +Традиционните бази данни изискват отделни заявки и join-ове на ниво приложение при работа с различни модели на данни. Cross-modal query planner-ът на BaraDB оптимизира изпълнението през: + +- **Документи/KV** (LSM-Tree) — структурирани записи +- **Графи** (Adjacency List) — връзки +- **Вектори** (HNSW/IVF-PQ) — търсене на прилика +- **Пълен текст** (Inverted Index) — текстово търсене +- **Колонково** — аналитични агрегати + +## Примери за Заявки + +### Векторно + Пълнотекстово (Семантично + Ключово Търсене) + +```sql +SELECT title, score +FROM articles +WHERE MATCH(body) AGAINST('machine learning') +ORDER BY cosine_distance(embedding, [0.1, 0.2, 0.3, ...]) +LIMIT 10; +``` + +### Графово + Векторно (Социални Препоръки) + +```sql +MATCH (u:User)-[:KNOWS]->(friend:User) +WHERE u.name = 'Alice' +ORDER BY cosine_distance(friend.taste_vector, u.taste_vector) +RETURN friend.name, friend.age; +``` + +### Документно + Графово (Обогатяване на Същности) + +```sql +SELECT o.id, o.total, c.name, + (SELECT count(*) FROM orders WHERE customer_id = c.id) as order_count +FROM orders o +MATCH (c:Customer)-[:PLACED]->(o) +WHERE o.date > '2025-01-01'; +``` + +## Cross-Modal Engine API + +```nim +import barabadb/core/crossmodal + +var engine = newCrossModalEngine("/tmp/baradb") + +# Документни операции +engine.put("key1", cast[seq[byte]]("value1")) +let (found, val) = engine.get("key1") + +# Векторни операции +engine.insertVector(1, @[1.0'f32, 0.0'f32, ...], {"cat": "A"}.toTable) +let results = engine.searchVector(@[1.0'f32, 0.1'f32, ...], 2) + +# Графови операции +let n1 = engine.addNode("Person") +let n2 = engine.addNode("Person") +discard engine.addEdge(n1, n2, "knows") +let traversal = engine.traverseGraph(n1, "bfs") + +# FTS операции +engine.indexText(1, "Nim programming language") +let ftsResults = engine.searchText("programming") + +# Хибридно търсене +var query = newCrossModalQuery(qmHybrid) +query.vector = @[1.0'f32, 0.0'f32] +query.searchQuery = "fast" +query.vecWeight = 1.0 +query.ftsWeight = 1.0 +let hybridResult = engine.hybridSearch(query) +``` + +## 2PC Транзакции + +Cross-modal engine-ът поддържа two-phase commit за атомарни операции през множество storage системи: + +```nim +var txn = newTPCTransaction(1) +txn.addParticipant("storage") +txn.addParticipant("vector") +txn.addParticipant("graph") + +txn.prepare() # Всички участници потвърждават, че могат да комитнат +txn.commit() # Атомарен commit през всички участници +``` + +## Формална Верификация + +Cross-modal консистентността е формално специфицирана в TLA+: + +- **Спецификация:** `formal-verification/crossmodal.tla` +- **Проверени свойства:** + - `MetadataVectorConsistency` — insertVector обновява метаданни за филтрирано търсене + - `CrossModalAtomicity` — всички участници комитват или всички абортират diff --git a/docs/bg/deployment.md b/docs/bg/deployment.md new file mode 100644 index 0000000..fa8f641 --- /dev/null +++ b/docs/bg/deployment.md @@ -0,0 +1,250 @@ +# Ръководство за Внедряване (Deployment) + +## Docker + +За пълно ръководство за Docker deployment вижте [Docker Guide](docker.md). + +### Бърз старт + +```bash +docker build -t baradb:latest . +docker compose up -d +``` + +### Docker Compose файлове + +| Файл | Назначение | +|------|-----------| +| `docker-compose.yml` | Development | +| `docker-compose.prod.yml` | Production | +| `docker-compose.override.yml` | Dev override (автоматично) | +| `docker-compose.test.yml` | Тестова среда | + +### Production + +```bash +docker compose -f docker-compose.prod.yml up -d +``` + +### Docker Swarm + +```bash +docker stack deploy -c docker-compose.prod.yml baradb +``` + +## systemd Услуга + +Създайте `/etc/systemd/system/baradb.service`: + +```ini +[Unit] +Description=BaraDB Multimodal Database +After=network.target + +[Service] +Type=simple +User=baradb +Group=baradb +WorkingDirectory=/var/lib/baradb +ExecStart=/usr/local/bin/baradadb +Restart=always +RestartSec=5 + +Environment=BARADB_PORT=9472 +Environment=BARADB_HTTP_PORT=9470 +Environment=BARADB_DATA_DIR=/var/lib/baradb/data +Environment=BARADB_LOG_LEVEL=info + +# Подсилване на сигурността +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/baradb/data +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true + +[Install] +WantedBy=multi-user.target +``` + +Активиране и стартиране: + +```bash +sudo useradd -r -s /bin/false baradb +sudo mkdir -p /var/lib/baradb/data +sudo chown -R baradb:baradb /var/lib/baradb +sudo cp build/baradadb /usr/local/bin/ +sudo systemctl daemon-reload +sudo systemctl enable --now baradb +``` + +## Kubernetes + +### StatefulSet + +```yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: baradb +spec: + serviceName: baradb + replicas: 3 + selector: + matchLabels: + app: baradb + template: + metadata: + labels: + app: baradb + spec: + containers: + - name: baradb + image: baradb:latest + ports: + - containerPort: 9472 + name: binary + - containerPort: 9470 + name: http + - containerPort: 9471 + name: websocket + env: + - name: BARADB_DATA_DIR + value: /data + - name: BARADB_RAFT_NODE_ID + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: data + mountPath: /data + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 100Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: baradb +spec: + selector: + app: baradb + ports: + - port: 9472 + name: binary + - port: 9470 + name: http + - port: 9471 + name: websocket + clusterIP: None +``` + +## Reverse Proxy (nginx) + +```nginx +upstream baradb_http { + server 127.0.0.1:9470; +} + +upstream baradb_ws { + server 127.0.0.1:9471; +} + +server { + listen 80; + server_name db.example.com; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name db.example.com; + + ssl_certificate /etc/letsencrypt/live/db.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/db.example.com/privkey.pem; + + location /api/ { + proxy_pass http://baradb_http/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /ws/ { + proxy_pass http://baradb_ws/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} +``` + +## Висока Достъпност (High Availability) + +### 3-Възел Raft Клъстер + +```bash +# Възел 1 +BARADB_RAFT_NODE_ID=node1 \ +BARADB_RAFT_PEERS=node2:9001,node3:9001 \ +./build/baradadb + +# Възел 2 +BARADB_RAFT_NODE_ID=node2 \ +BARADB_RAFT_PEERS=node1:9001,node3:9001 \ +./build/baradadb + +# Възел 3 +BARADB_RAFT_NODE_ID=node3 \ +BARADB_RAFT_PEERS=node1:9001,node2:9001 \ +./build/baradadb +``` + +## Облачно Внедряване + +### AWS EC2 + +Препоръчителна инстанция: `m6i.2xlarge` (8 vCPU, 32 GB RAM) + +```bash +# User data скрипт +#!/bin/bash +apt-get update +apt-get install -y nim +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64 +chmod +x baradadb-linux-amd64 +mv baradadb-linux-amd64 /usr/local/bin/baradadb + +mkdir -p /data/baradb +cat > /etc/systemd/system/baradb.service << 'EOF' +[Unit] +Description=BaraDB +After=network.target +[Service] +ExecStart=/usr/local/bin/baradadb +Environment=BARADB_DATA_DIR=/data/baradb +Restart=always +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable --now baradb +``` + +### GCP Cloud Run (само HTTP) + +```bash +gcloud run deploy baradb \ + --image gcr.io/PROJECT/baradb \ + --port 9470 \ + --memory 4Gi \ + --cpu 2 \ + --max-instances 10 +``` diff --git a/docs/bg/distributed.md b/docs/bg/distributed.md index be3b7a0..927e2dc 100644 --- a/docs/bg/distributed.md +++ b/docs/bg/distributed.md @@ -1,9 +1,11 @@ # Разпределена Система -Поддръжка за разпределено внедряване с Raft консенсус, шардиране и репликация. +BaraDB поддържа разпределено внедряване с Raft консенсус, шардиране, репликация и gossip протокол. ## Raft Консенсус +Leader election и log репликация: + ```nim import barabadb/core/raft @@ -13,19 +15,35 @@ cluster.addNode("node2") cluster.addNode("node3") let n1 = cluster.nodes["n1"] +n1.becomeCandidate() n1.becomeLeader() +let entry = n1.appendLog("SET key1 value1") ``` ## Шардиране +Разпределение на данни между възли: + ```nim import barabadb/core/sharding -var router = newShardRouter(ShardConfig(numShards: 4, replicas: 2)) +var router = newShardRouter(ShardConfig( + numShards: 4, + replicas: 2, + strategy: ssHash +)) router.rebalance(@["node1", "node2", "node3"]) let shard = router.getShard("user_123") ``` +### Стратегии за Шардиране + +| Стратегия | Описание | +|-----------|----------| +| `ssHash` | Хеш-базирано шардиране | +| `ssRange` | Range-базирано шардиране | +| `ssConsistent` | Consistent hashing | + ## Репликация ```nim @@ -34,11 +52,46 @@ import barabadb/core/replication var rm = newReplicationManager(rmSync) rm.addReplica(newReplica("r1", "10.0.0.1", 9472)) rm.connectReplica("r1") +let lsn = rm.writeLsn(@[1'u8, 2, 3]) +rm.ackLsn("r1", lsn) +``` + +### Режими на Репликация + +| Режим | Описание | +|--------|----------| +| `rmSync` | Синхронна репликация | +| `rmAsync` | Асинхронна репликация | +| `rmSemiSync` | Полу-синхронна репликация | + +## Gossip Протокол + +Управление на членство и детекция на откази: + +```nim +import barabadb/core/gossip + +var g = newGossipProtocol("node1", "localhost", 9472, gossipPort = 9572) +g.join(newGossipNode("node2", "10.0.0.2", 9472)) +``` + +## Разпределени Транзакции + +Two-phase commit между възли: + +```nim +import barabadb/core/disttxn + +var tm = newDistTxnManager() +let txn = tm.beginTransaction("node1") +txn.addParticipant("node2", "10.0.0.2", 9472) +txn.prepare() +txn.commit() ``` ## Формална Верификация -Разпределените алгоритми са формално специфицирани в TLA+ и проверени с TLC: +Основните разпределени алгоритми са формално специфицирани в TLA+ и проверени с TLC: - **Raft Консенсус** — `formal-verification/raft.tla` - Проверено: ElectionSafety, StateMachineSafety @@ -47,11 +100,11 @@ rm.connectReplica("r1") - **Репликация** — `formal-verification/replication.tla` - Проверено: MonotonicLsn, AcksRemovePending -Пускане на TLC: +Пускане на TLC локално: ```bash cd formal-verification java -cp tla2tools.jar tlc2.TLC -config models/raft.cfg raft.tla java -cp tla2tools.jar tlc2.TLC -config models/twopc.cfg twopc.tla java -cp tla2tools.jar tlc2.TLC -config models/replication.cfg replication.tla -``` \ No newline at end of file +``` diff --git a/docs/bg/docker.md b/docs/bg/docker.md new file mode 100644 index 0000000..c5e6940 --- /dev/null +++ b/docs/bg/docker.md @@ -0,0 +1,183 @@ +# Docker Deployment Ръководство + +Това ръководство описва как да използвате BaraDB с Docker и Docker Compose. + +## Бърз старт + +```bash +# Клониране на репото +git clone https://github.com/katehonz/barabaDB.git +cd barabaDB + +# Build на образа +docker build -t baradb:latest . + +# Стартиране с Docker Compose +docker compose up -d + +# Проверка на статуса +docker compose ps +docker compose logs -f +``` + +## Файлове + +| Файл | Описание | +|------|----------| +| `Dockerfile` | Мулти-stage production build | +| `docker-compose.yml` | Development конфигурация | +| `docker-compose.prod.yml` | Production конфигурация | +| `docker-compose.override.yml` | Development override (автоматично се зарежда) | +| `docker-compose.test.yml` | Тестова конфигурация | +| `docker-entrypoint.sh` | Entrypoint скрипт за инициализация | +| `.dockerignore` | Файлове, които да не се копират в образа | + +## Създаване на образ + +```bash +# Стандартен build +docker build -t baradb:latest . + +# С конкретна версия +docker build -t baradb:1.1.0 . +``` + +## Стартиране + +### Development (docker compose) + +```bash +# Стартиране на заден план +docker compose up -d + +# Спиране +docker compose down + +# Спиране и изтриване на volumes (ВНИМАНИЕ — изтрива данните!) +docker compose down -v + +# Преглед на логове +docker compose logs -f +``` + +### Production (docker compose) + +```bash +# Стартиране с production конфигурация +docker compose -f docker-compose.prod.yml up -d + +# Проверка на healthcheck +docker compose -f docker-compose.prod.yml ps +``` + +### Ръчно (docker run) + +```bash +docker run -d \ + --name baradb \ + -p 9472:9472 \ + -p 9470:9470 \ + -p 9471:9471 \ + -v baradb_data:/data \ + -e BARADB_LOG_LEVEL=info \ + baradb:latest +``` + +## Портове + +| Порт | Описание | +|------|----------| +| `9472` | Binary wire протокол | +| `9470` | HTTP/REST API | +| `9471` | WebSocket | + +## Променливи на Средата + +| Променлива | Стойност по подразбиране | Описание | +|------------|--------------------------|----------| +| `BARADB_ADDRESS` | `0.0.0.0` | Адрес за слушане | +| `BARADB_PORT` | `9472` | Binary протокол порт | +| `BARADB_HTTP_PORT` | `9470` | HTTP порт | +| `BARADB_WS_PORT` | `9471` | WebSocket порт | +| `BARADB_DATA_DIR` | `/data` | Директория за данни | +| `BARADB_LOG_LEVEL` | `info` | Ниво на логове | + +## Volumes + +| Път в контейнера | Описание | +|------------------|----------| +| `/data` | Основна директория за базата данни | +| `/data/server/wal` | Write-ahead log | +| `/data/server/sstables` | SSTable файлове | + +## Production Checklist + +- [ ] Създайте TLS сертификати в `./certs/` +- [ ] Задайте силен `BARADB_JWT_SECRET` +- [ ] Настройте firewall правила +- [ ] Конфигурирайте регулярни backups +- [ ] Проверете resource limits +- [ ] Настройте мониторинг (healthcheck, logs) + +## TLS в Docker + +1. Създайте сертификати: +```bash +mkdir -p certs +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout certs/server.key -out certs/server.crt +``` + +2. Активирайте в `docker-compose.prod.yml`: +```yaml +environment: + - BARADB_TLS_ENABLED=true + - BARADB_CERT_FILE=/certs/server.crt + - BARADB_KEY_FILE=/certs/server.key +volumes: + - ./certs:/certs:ro +``` + +## Backup в Docker + +```bash +# Ръчен backup +docker exec baradb baradadb --snapshot --output=/backup/snapshot.db + +# Списък на backups +ls /backup/ + +# Възстановяване +docker exec baradb baradadb --recover --checkpoint=/backup/snapshot.db +``` + +## Troubleshooting + +### Контейнерът не стартира + +```bash +# Проверка на логове +docker compose logs -f baradb + +# Проверка на статус +docker compose ps +``` + +### Няма връзка с базата + +```bash +# Проверка дали портовете са експозвани +docker port baradb + +# Проверка отвътре +docker exec baradb wget -qO- http://localhost:9470/health +``` + +### Permission denied на /data + +Entrypoint скриптът автоматично създава директориите и задава правилните permissions. Ако имате проблем: + +```bash +docker exec baradb ls -la /data +docker exec baradb chown -R baradb:baradb /data +``` diff --git a/docs/bg/fts.md b/docs/bg/fts.md index 11c60c1..f808d5c 100644 --- a/docs/bg/fts.md +++ b/docs/bg/fts.md @@ -1,6 +1,6 @@ -# Пълнотекстово Търсене +# Full-Text Search Engine -Инвертиран индекс с BM25 и TF-IDF ранжиране. +Inverted индекс с BM25 и TF-IDF ранжиране за текстово търсене. ## Употреба @@ -8,28 +8,80 @@ import barabadb/fts/engine var idx = newInvertedIndex() -idx.addDocument(1, "Nim е бърз език за програмиране") -idx.addDocument(2, "Python е популярен за data science") +idx.addDocument(1, "Nim is a fast programming language") +idx.addDocument(2, "Python is popular for data science") -let results = idx.search("език програмиране") -let tfidf = idx.searchTfidf("език") -let fuzzy = idx.fuzzySearch("програмиране", maxDistance = 2) +# BM25 търсене +let results = idx.search("programming language") + +# TF-IDF търсене +let tfidf = idx.searchTfidf("programming language") + +# Fuzzy търсене (толеранс на печатни грешки) +let fuzzy = idx.fuzzySearch("programing", maxDistance = 2) + +# Wildcard търсене +let wild = idx.regexSearch("prog*") ``` ## Методи за Ранжиране ### BM25 -Най-добрият алгоритъм за съвпадение +Best matching алгоритъм за ранжиране: + +```nim +let bm25 = idx.searchBM25("query terms") +``` ### TF-IDF -Term Frequency-Inverse Document Frequency +Term Frequency-Inverse Document Frequency: -## Търсене +```nim +let tfidf = idx.searchTfidf("query terms") +``` -| Тип | Описание | -|-----|----------| -| Fuzzy | Толерантност към правописни грешки | -| Wildcard | Префикс, суфикс, и инфикс заместващи символи | -| Regex | Регулярни изрази | \ No newline at end of file +## Функции за Търсене + +| Функция | Описание | +|---------|----------| +| Fuzzy търсене | Levenshtein distance толеранс | +| Wildcard | Префиксни, суфиксни и инфиксни wildcards | +| Regex | Регулярни изрази | +| Фразово търсене | Точно съвпадение на фраза | +| Булево | AND, OR, NOT оператори | + +## SQL Интерфейс + +Пълнотекстовото търсене е достъпно и директно в BaraQL: + +```sql +-- Създаване на таблица с текстова колона +CREATE TABLE articles (id INT PRIMARY KEY, title TEXT, body TEXT); + +-- Създаване на FTS индекс +CREATE INDEX idx_fts ON articles(body) USING FTS; + +-- Търсене с оператора @@ (BM25 ранжиране) +SELECT * FROM articles WHERE body @@ 'machine learning'; + +-- Търсене с множество термини +SELECT * FROM articles WHERE body @@ 'quick brown fox'; +``` + +## Многоезична Поддръжка + +```nim +import barabadb/fts/multilang + +# Поддържани езици: EN, BG, DE, FR, RU +var tokenizer = newTokenizer("bg") # Български +let tokens = tokenizer.tokenize("Търсене в пълен текст") +``` + +Функции за всеки език: +- Токенизация +- Stop думи +- Стеминг +- Детекция на език diff --git a/docs/bg/installation.md b/docs/bg/installation.md index dd5dcdb..9ad40f8 100644 --- a/docs/bg/installation.md +++ b/docs/bg/installation.md @@ -15,6 +15,7 @@ | macOS | x86_64 | ✅ Пълна поддръжка | | macOS | ARM64 (Apple Silicon) | ✅ Пълна поддръжка | | Windows | x86_64 | ✅ Поддръжка | +| FreeBSD | x86_64 | 🟡 Тествано от общността | ## Инсталиране на Nim @@ -48,10 +49,13 @@ sudo port install nim ### Windows ```powershell -# Winget +# С choosenim +curl.exe -A "MSYS2_$(uname -m)" -L https://nim-lang.org/choosenim/init.ps1 | powershell - + +# С winget winget install nim -# Scoop +# С scoop scoop install nim ``` @@ -79,10 +83,16 @@ sudo pacman -S openssl ### macOS +OpenSSL е включен в системата. Ако е необходимо: + ```bash brew install openssl ``` +### Windows + +OpenSSL е включен в Nim Windows дистрибуцията. За ръчни компилации, изтеглете от [slproweb.com](https://slproweb.com/products/Win32OpenSSL.html). + ## Компилиране на BaraDB ### Клониране на Репозиторито @@ -103,26 +113,29 @@ nimble install -d -y #### Debug Компилация ```bash -nim c -d:ssl -o:build/baradadb src/baradadb.nim +nim c -d:ssl --threads:on -o:build/baradadb src/baradadb.nim ``` #### Release Компилация (Препоръчителна) ```bash -nim c -d:ssl -d:release --opt:speed -o:build/baradadb src/baradadb.nim +nim c -d:ssl --threads:on -d:release --opt:speed -o:build/baradadb src/baradadb.nim ``` -#### Използване на Nimble +#### Използване на Nimble Tasks ```bash +# Debug компилация nimble build_debug + +# Release компилация nimble build_release ``` #### Минимален Размер ```bash -nim c -d:ssl -d:release --opt:size -o:build/baradadb src/baradadb.nim +nim c -d:ssl --threads:on -d:release --opt:size -o:build/baradadb src/baradadb.nim strip build/baradadb ``` @@ -130,17 +143,31 @@ strip build/baradadb ```bash ./build/baradadb --version -# Очакван резултат: BaraDB v0.1.0 — Multimodal Database Engine +# Очакван резултат: BaraDB v1.1.0 — Multimodal Database Engine ``` ## Стартиране на Тестове -```bash -# Всички тестове (262 теста, 56 сюита) -nim c -d:ssl -r tests/test_all.nim +### Всички Тестове -# Бенчмаркове -nim c -d:ssl -d:release -r benchmarks/bench_all.nim +```bash +nim c --path:src -d:ssl --threads:on -r tests/test_all.nim +``` + +### Специфични Тестови Сюити + +```bash +# Storage тестове +nim c --path:src -d:ssl --threads:on -r tests/test_all.nim + +# Stress тестове +nim c --path:src -d:ssl --threads:on -d:release -r tests/stress_test.nim +``` + +### Бенчмаркове + +```bash +nim c --path:src -d:ssl --threads:on -d:release -r benchmarks/bench_all.nim ``` ## Опции за Инсталация @@ -148,16 +175,46 @@ nim c -d:ssl -d:release -r benchmarks/bench_all.nim ### Системна Инсталация ```bash +# Компилиране на release binary nimble build_release + +# Инсталиране в /usr/local/bin sudo cp build/baradadb /usr/local/bin/ sudo chmod +x /usr/local/bin/baradadb + +# Създаване на директория за данни sudo mkdir -p /var/lib/baradb +sudo chmod 755 /var/lib/baradb +``` + +### Предварително Компилиран Binary + +Изтеглете най-новата версия за вашата платформа: + +```bash +# Linux x86_64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64 +chmod +x baradadb-linux-amd64 +mv baradadb-linux-amd64 /usr/local/bin/baradadb + +# Linux ARM64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-arm64 +chmod +x baradadb-linux-arm64 +mv baradadb-linux-arm64 /usr/local/bin/baradadb + +# macOS +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-darwin-amd64 +chmod +x baradadb-darwin-amd64 +mv baradadb-darwin-amd64 /usr/local/bin/baradadb ``` ### Docker ```bash +# Изтегляне на официален образ docker pull barabadb/barabadb:latest + +# Стартиране docker run -d \ -p 9472:9472 \ -p 9470:9470 \ @@ -172,12 +229,16 @@ docker run -d \ docker-compose up -d ``` -### Вградено Използване +### Вградено Използване (Nim Проекти) + +Добавете към вашия `.nimble` файл: ```nim -requires "barabadb >= 0.1.0" +requires "barabadb >= 1.1.0" ``` +Използване в кода: + ```nim import barabadb/storage/lsm @@ -193,16 +254,52 @@ db.close() # Стартиране на сървъра ./build/baradadb -# Тестване на HTTP API +# Очакван изход: +# BaraDB v1.1.0 — Multimodal Database Engine +# BaraDB TCP listening on 127.0.0.1:9472 + +# Тестване с HTTP API curl http://localhost:9470/health -# Интерактивна конзола +# Интерактивна обвивка ./build/baradadb --shell ``` +## Отстраняване на Проблеми с Инсталацията + +### "cannot open file: hunos" + +```bash +nimble install -d -y +``` + +### "BaraDB requires SSL support" + +Винаги компилирайте с `-d:ssl`: + +```bash +nim c -d:ssl --threads:on -o:build/baradadb src/baradadb.nim +``` + +### Бавна компилация + +Използвайте паралелна компилация: + +```bash +nim c -d:ssl --threads:on -d:release --parallelBuild:4 -o:build/baradadb src/baradadb.nim +``` + +### Голям размер на binary-то + +Използвайте оптимизация на размера: + +```bash +nim c -d:ssl --threads:on -d:release --opt:size --passL:-s -o:build/baradadb src/baradadb.nim +``` + ## Следващи Стъпки -- [Бързо Стартиране](bg/quickstart.md) -- [Конфигурация](en/configuration.md) -- [Архитектура](bg/architecture.md) -- [BaraQL Заявки](bg/baraql.md) +- [Бърз Старт](quickstart.md) +- [Конфигурационна Референция](configuration.md) +- [Преглед на Архитектурата](architecture.md) +- [BaraQL Език за Заявки](baraql.md) diff --git a/docs/bg/lsm.md b/docs/bg/lsm.md index 65e8967..da46e41 100644 --- a/docs/bg/lsm.md +++ b/docs/bg/lsm.md @@ -1,6 +1,29 @@ -# LSM-Tree Съхранение +# LSM-Tree Storage Engine -Основният двигател за съхранение използващ Log-Structured Merge-Tree архитектура. +Основният storage engine в BaraDB, използващ Log-Structured Merge-Tree архитектура. + +## Архитектура + +``` +┌─────────────────────────────────────────────┐ +│ Записи │ +│ (добавяне към WAL + MemTable) │ +└─────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────┐ +│ MemTable │ +│ (в-памет сортиран буфер) │ +└─────────────────────────────────────────────┘ + │ + (при запълване, flush към SSTable) + │ + ▼ +┌─────────────────────────────────────────────┐ +│ SSTable │ +│ (сортирана string table на диска) │ +└─────────────────────────────────────────────┘ +``` ## Употреба @@ -9,17 +32,33 @@ import barabadb/storage/lsm var db = newLSMTree("./data") +# Запис db.put("key1", cast[seq[byte]]("value1")) + +# Четене let (found, value) = db.get("key1") +# Изтриване +db.delete("key1") + db.close() ``` -## Компоненти +## Възможности -- **MemTable**: Сортиран буфер в паметта -- **WAL**: Write-ahead log за трайност -- **SSTable**: Сортирани таблици на диска -- **Bloom Filter**: Бързи негативни проверки -- **Compaction**: Сливане на SSTables -- **Page Cache**: LRU кеш \ No newline at end of file +- **Write-оптимизиран**: Append-only лог структура +- **Устойчивост**: Write-ahead log (WAL) осигурява crash recovery +- **Bloom Филтър**: Бързи негативни проверки +- **Compaction**: Size-tiered стратегия слива SSTables +- **Page Cache**: LRU кеш за често достъпвани страници + +## Конфигурация + +```nim +var db = newLSMTree( + path = "./data", + memTableSize = 64 * 1024 * 1024, # 64MB + walEnabled = true, + bloomFpRate = 0.01 +) +``` diff --git a/docs/bg/monitoring.md b/docs/bg/monitoring.md new file mode 100644 index 0000000..b501a9c --- /dev/null +++ b/docs/bg/monitoring.md @@ -0,0 +1,202 @@ +# Мониторинг и Наблюдаемост + +## Health Checks + +### HTTP Health Endpoint + +```bash +curl http://localhost:9470/health +``` + +Отговор: + +```json +{ + "status": "healthy", + "version": "1.1.0", + "uptime_seconds": 86400, + "checks": { + "storage": "ok", + "memory": "ok", + "connections": "ok" + } +} +``` + +### Readiness Probe + +```bash +curl http://localhost:9470/ready +``` + +Връща `200 OK` когато сървърът е готов да приема трафик, `503` по време на стартиране. + +## Метрики + +### Prometheus-Съвместими Метрики + +```bash +curl http://localhost:9470/metrics +``` + +Примерен изход: + +``` +# HELP baradb_queries_total Общ брой изпълнени заявки +# TYPE baradb_queries_total counter +baradb_queries_total 152340 + +# HELP baradb_queries_duration_seconds Хистограма на времетраене на заявки +# TYPE baradb_queries_duration_seconds histogram +baradb_queries_duration_seconds_bucket{le="0.001"} 45000 +baradb_queries_duration_seconds_bucket{le="0.01"} 120000 +baradb_queries_duration_seconds_bucket{le="0.1"} 148000 + +# HELP baradb_storage_lsm_size_bytes Общ размер на LSM-Tree +# TYPE baradb_storage_lsm_size_bytes gauge +baradb_storage_lsm_size_bytes 2147483648 + +# HELP baradb_cache_hit_rate Page cache hit rate +# TYPE baradb_cache_hit_rate gauge +baradb_cache_hit_rate 0.94 + +# HELP baradb_active_connections Активни клиентски връзки +# TYPE baradb_active_connections gauge +baradb_active_connections 42 +``` + +### JSON Метрики + +```bash +curl http://localhost:9470/metrics?format=json +``` + +## Логване + +### Нива на Логване + +| Ниво | Описание | +|------|----------| +| `debug` | Детайлни вътрешни операции | +| `info` | Нормални операции | +| `warn` | Възстановими проблеми | +| `error` | Грешки, изискващи внимание | + +### Структурирани JSON Логове + +```bash +BARADB_LOG_LEVEL=info \ +BARADB_LOG_FORMAT=json \ +BARADB_LOG_FILE=/var/log/baradb/baradb.log \ +./build/baradadb +``` + +Примерен лог запис: + +```json +{ + "timestamp": "2025-01-15T10:30:00.123Z", + "level": "info", + "component": "server", + "message": "Query executed", + "query": "SELECT * FROM users", + "duration_ms": 12, + "client_ip": "10.0.0.15" +} +``` + +### Текстов Формат + +```bash +BARADB_LOG_FORMAT=text ./build/baradadb +``` + +## Правила за Алармиране + +### Prometheus AlertManager + +```yaml +groups: + - name: baradb + rules: + - alert: BaraDBHighErrorRate + expr: rate(baradb_errors_total[5m]) > 0.1 + for: 5m + labels: + severity: critical + annotations: + summary: "Висок процент грешки в BaraDB" + + - alert: BaraDBLowCacheHitRate + expr: baradb_cache_hit_rate < 0.8 + for: 10m + labels: + severity: warning + annotations: + summary: "Cache hit rate под 80%" + + - alert: BaraDBHighConnections + expr: baradb_active_connections > 800 + for: 5m + labels: + severity: warning + annotations: + summary: "Голям брой връзки към BaraDB" + + - alert: BaraDBDown + expr: up{job="baradb"} == 0 + for: 1m + labels: + severity: critical + annotations: + summary: "BaraDB инстанцията не работи" +``` + +## Разпределен Мониторинг + +### Клъстерни Метрики + +За Raft клъстери, мониторирайте: + +```bash +curl http://node1:9470/metrics/cluster +``` + +```json +{ + "cluster_id": "baradb-cluster-1", + "nodes": [ + {"id": "node1", "role": "leader", "health": "healthy"}, + {"id": "node2", "role": "follower", "health": "healthy"}, + {"id": "node3", "role": "follower", "health": "healthy"} + ], + "raft_log_index": 15420, + "raft_commit_index": 15420, + "shards": 4, + "replication_lag_ms": 5 +} +``` + +## Профилиране на Производителност + +### Вграден CPU Profiler + +```bash +curl -X POST http://localhost:9470/debug/pprof/cpu?seconds=30 > cpu.prof +``` + +### Memory Profiler + +```bash +curl http://localhost:9470/debug/pprof/heap > heap.prof +``` + +## Отстраняване на Проблеми с Метрики + +| Симптом | Метрика | Действие | +|---------|--------|----------| +| Бавни заявки | `baradb_queries_duration_seconds` | Проверете cache hit rate, добавете индекси | +| Висока памет | `process_resident_memory_bytes` | Намалете memtable/cache размери | +| Растящо съхранение | `baradb_storage_lsm_size_bytes` | Пуснете ръчен compaction | +| Грешки при връзка | `baradb_active_connections` | Увеличете connection pool или добавете възли | +| Репликационно закъснение | `baradb_replication_lag_ms` | Проверете мрежата, увеличете ресурсите | diff --git a/docs/bg/performance.md b/docs/bg/performance.md new file mode 100644 index 0000000..fcd1d97 --- /dev/null +++ b/docs/bg/performance.md @@ -0,0 +1,125 @@ +# Ръководство за Производителност + +## Методология на Бенчмарковете + +Всички бенчмаркове са проведени с: +- **Компилатор**: Nim 2.2.0 с `-d:release --opt:speed` +- **CPU**: AMD Ryzen 9 5900X (12 ядра / 24 нишки) +- **Памет**: 64 GB DDR4-3600 +- **Диск**: Samsung 980 Pro NVMe SSD +- **ОС**: Ubuntu 24.04 LTS + +Пускане на пълния бенчмарк сюит: + +```bash +nim c -d:ssl -d:release -r benchmarks/bench_all.nim +``` + +## Storage Engine Бенчмаркове + +### LSM-Tree Key-Value + +| Метрика | Стойност | +|---------|----------| +| Пропускателна способност при запис | ~580,000 ops/s | +| Пропускателна способност при четене | ~720,000 ops/s | +| Средна латентност при запис | 1.7 µs | +| Средна латентност при четене | 1.4 µs | + +LSM-Tree използва 64MB MemTable, WAL fsync при всеки запис и size-tiered compaction с 6 нива. + +### B-Tree Индекс + +| Метрика | Стойност | +|---------|----------| +| Пропускателна способност при вмъкване | ~1,200,000 ops/s | +| Пропускателна способност при точково търсене | ~1,500,000 ops/s | +| Range scan (1000 ключа) | ~0.3 ms | + +## Vector Engine Бенчмаркове + +### HNSW Индекс + +| Метрика | Стойност | +|---------|----------| +| Вмъкване (dim=128) | ~45,000 вектора/s | +| Търсене топ-10 (dim=128, n=10K) | ~2 ms | +| Търсене топ-10 (dim=128, n=100K) | ~8 ms | + +### SIMD Функции за Разстояние + +| Операция | dim=128 | dim=768 | dim=1536 | +|----------|---------|---------|----------| +| Косинусово разстояние | 4.2M/s | 850K/s | 420K/s | +| L2 (Евклидово) | 4.5M/s | 920K/s | 450K/s | +| Скаларно произведение | 4.8M/s | 980K/s | 480K/s | + +## Full-Text Search Бенчмаркове + +| Метрика | Стойност | +|---------|----------| +| Индексиране | ~320,000 документа/s | +| BM25 търсене | ~28,000 заявки/s | +| Fuzzy търсене (distance=2) | ~850 заявки/s | + +## Graph Engine Бенчмаркове + +| Операция | Пропускателна способност | +|----------|--------------------------| +| Добавяне на възел | ~2.5M ops/s | +| Добавяне на ребро | ~1.8M ops/s | +| BFS (1K възела, 5K ребра) | ~12K обхождания/s | +| Dijkstra най-кратък път | ~120 µs | +| PageRank (10 итерации) | ~450 графа/s | + +## Протоколни Бенчмаркове + +| Протокол | Връзки | Заявки/s | Латентност p99 | +|----------|--------|----------|----------------| +| Бинарен (localhost) | 1 | 45,000 | 0.4 ms | +| Бинарен (localhost) | 100 | 380,000 | 1.2 ms | +| HTTP/REST | 1 | 12,000 | 2.1 ms | +| HTTP/REST | 100 | 95,000 | 5.8 ms | +| WebSocket | 1 | 18,000 | 1.8 ms | + +## Вертикален Мащабинг + +| Ядра | LSM Запис | LSM Четене | Векторно Търсене | +|------|-----------|------------|-------------------| +| 1 | 580K | 720K | 2.0 ms | +| 4 | 1.9M | 2.6M | 1.1 ms | +| 8 | 3.4M | 4.8M | 0.7 ms | +| 16 | 5.8M | 7.2M | 0.5 ms | + +## Ръководство за Настройка + +### За Write-Heavy Натоварвания + +```bash +export BARADB_MEMTABLE_SIZE_MB=256 +export BARADB_WAL_SYNC_INTERVAL_MS=10 +export BARADB_COMPACTION_INTERVAL_MS=30000 +``` + +### За Read-Heavy Натоварвания + +```bash +export BARADB_CACHE_SIZE_MB=1024 +export BARADB_BLOOM_BITS_PER_KEY=10 +export BARADB_COMPACTION_INTERVAL_MS=120000 +``` + +### За Векторно Търсене + +```bash +export BARADB_VECTOR_EF_CONSTRUCTION=200 +export BARADB_VECTOR_EF_SEARCH=128 +export BARADB_VECTOR_M=32 +``` + +### За Графова Аналитика + +```bash +export BARADB_GRAPH_PAGE_RANK_ITERATIONS=20 +export BARADB_GRAPH_LOUVAIN_RESOLUTION=1.0 +``` diff --git a/docs/bg/protocol.md b/docs/bg/protocol.md new file mode 100644 index 0000000..7bd3aea --- /dev/null +++ b/docs/bg/protocol.md @@ -0,0 +1,373 @@ +# Протоколна Референция + +BaraDB поддържа множество протоколи за клиентска комуникация: +- **Бинарен Wire Протокол** — високопроизводителен, ниска латентност +- **HTTP/REST API** — езиково-независим, лесен за дебъгване +- **WebSocket** — стрийминг и pub/sub + +--- + +## Бинарен Wire Протокол + +Бинарният протокол използва big-endian кодиране за всички многобайтови стойности. + +### Жизнен Цикъл на Връзката + +``` +Клиент Сървър + | | + |─── TCP свързване ───────────>| + |<── TLS ръкостискане (опц.) ──| + |─── Auth съобщение ──────────>| + |<── Auth_OK / Грешка ─────────| + |─── Query съобщение ─────────>| + |<── Data / Complete / Error ──| + |─── Close съобщение ─────────>| + |<── TCP затваряне ────────────| +``` + +### Формат на Съобщенията + +Всяко съобщение започва с 12-байтов хедър: + +``` +┌─────────────┬─────────────┬─────────────┬─────────────────────┐ +│ Kind │ Length │ RequestId │ Payload │ +│ (4 bytes) │ (4 bytes) │ (4 bytes) │ │ +│ uint32 BE │ uint32 BE │ uint32 BE │ (Length bytes) │ +└─────────────┴─────────────┴─────────────┴─────────────────────┘ +``` + +### Типове Съобщения + +| Тип | ID | Посока | Описание | +|------|----|--------|----------| +| Query | 0x01 | К→С | Изпълни заявка | +| QueryParams | 0x02 | К→С | Параметризирана заявка | +| Auth | 0x07 | К→С | Заявка за автентикация | +| Ping | 0x09 | К→С | Keepalive ping | +| Close | 0x0A | К→С | Затваряне на връзка | +| Data | 0x81 | С→К | Резултат от заявка | +| Complete | 0x82 | С→К | Заявката е завършена | +| Auth_OK | 0x83 | С→К | Успешна автентикация | +| Pong | 0x84 | С→К | Keepalive отговор | +| Error | 0x06 | С→К | Грешка | + +### Query Съобщение Payload + +``` +┌───────────────────┬────────────────────────────┐ +│ Query String │ │ +│ (променлива) │ │ +│ UTF-8 │ │ +└───────────────────┴────────────────────────────┘ +``` + +### Data Съобщение Payload + +``` +┌──────────────┬─────────────────────────────────────────────┐ +│ Брой Колони │ Дефиниции на Колони + Данни от Редове │ +│ (4 bytes) │ │ +│ uint32 BE │ │ +└──────────────┴─────────────────────────────────────────────┘ +``` + +### Типове Полета + +| Тип | ID | Размер | Описание | +|------|----|--------|----------| +| NULL | 0x00 | 0 | NULL стойност | +| BOOL | 0x01 | 1 | true/false | +| INT8 | 0x02 | 1 | Signed 8-bit integer | +| INT16 | 0x03 | 2 | Signed 16-bit integer | +| INT32 | 0x04 | 4 | Signed 32-bit integer | +| INT64 | 0x05 | 8 | Signed 64-bit integer | +| FLOAT32 | 0x06 | 4 | IEEE 754 единична точност (big-endian) | +| FLOAT64 | 0x07 | 8 | IEEE 754 двойна точност (big-endian) | +| STRING | 0x08 | променлив | UTF-8 низ (4-байтов префикс за дължина) | +| BYTES | 0x09 | променлив | Сурови байтове (4-байтов префикс за дължина) | +| ARRAY | 0x0A | променлив | Масив от стойности | +| OBJECT | 0x0B | променлив | Ключ-стойност обект | +| VECTOR | 0x0C | променлив | Float32 масив (4-байтов префикс, big-endian floats) | + +### Error Съобщение Payload + +``` +┌──────────────┬──────────────┬────────────────────────────┐ +│ Код Грешка │ Дълж. Съобщ. │ Съобщение за Грешка │ +│ (4 bytes) │ (4 bytes) │ (Дълж. Съобщ. bytes) │ +│ uint32 BE │ uint32 BE │ UTF-8 │ +└──────────────┴──────────────┴────────────────────────────┘ +``` + +--- + +## HTTP/REST API + +Базов URL: `http://localhost:9470/api/v1` + +### Endpoints + +#### Health + +```http +GET /health +``` + +Отговор: +```json +{ + "status": "healthy", + "version": "1.1.0", + "uptime_seconds": 86400 +} +``` + +#### Ready + +```http +GET /ready +``` + +Връща `200` когато е готов, `503` при стартиране. + +#### Query + +```http +POST /query +Content-Type: application/json +Authorization: Bearer + +{ + "query": "SELECT name, age FROM users WHERE age > 18", + "params": [], + "format": "json" +} +``` + +Отговор: +```json +{ + "columns": ["name", "age"], + "rows": [ + ["Alice", 30], + ["Bob", 25] + ], + "row_count": 2, + "duration_ms": 12 +} +``` + +#### Batch + +```http +POST /batch +Content-Type: application/json + +{ + "queries": [ + "INSERT users { name := 'Alice', age := 30 }", + "INSERT users { name := 'Bob', age := 25 }" + ] +} +``` + +Отговор: +```json +{ + "results": [ + {"status": "ok", "affected_rows": 1}, + {"status": "ok", "affected_rows": 1} + ] +} +``` + +#### Schema + +```http +GET /schema +``` + +#### Metrics + +```http +GET /metrics +``` + +Prometheus-съвместими метрики. Виж [Ръководство за Мониторинг](monitoring.md). + +#### Explain + +```http +POST /explain +Content-Type: application/json + +{ + "query": "SELECT * FROM users WHERE age > 18" +} +``` + +Отговор: +```json +{ + "plan": "IndexScan", + "index": "idx_users_age", + "estimated_rows": 42, + "cost": 120 +} +``` + +#### Backup + +```http +POST /backup +Content-Type: application/json + +{ + "destination": "/backup/snapshot.db" +} +``` + +#### Административни Операции + +```http +POST /admin/compact +POST /admin/rebalance +POST /admin/check +``` + +### HTTP Статус Кодове + +| Код | Значение | +|------|----------| +| 200 | Успех | +| 400 | Лоша заявка (синтактична грешка) | +| 401 | Неоторизиран (изисква се auth) | +| 403 | Забранен (недостатъчни права) | +| 404 | Не е намерен (таблица/тип не съществува) | +| 429 | Твърде много заявки (rate limited) | +| 500 | Вътрешна сървърна грешка | +| 503 | Услугата е недостъпна (стартира) | + +--- + +## WebSocket Протокол + +URL: `ws://localhost:9471` + +### Формат на Frame + +WebSocket текстови frame-ове съдържат JSON съобщения: + +```json +{ + "id": 1, + "type": "query", + "query": "SELECT * FROM users" +} +``` + +### Типове Съобщения + +| Тип | Посока | Описание | +|------|--------|----------| +| `query` | К→С | Изпълни заявка | +| `subscribe` | К→С | Абониране за промени | +| `unsubscribe` | К→С | Отписване | +| `ping` | К→С | Keepalive | +| `result` | С→К | Резултат от заявка | +| `notification` | С→К | Известие за промяна | +| `error` | С→К | Грешка | +| `pong` | С→К | Keepalive отговор | + +### Pub/Sub Пример + +```javascript +const ws = new WebSocket('ws://localhost:9471'); + +ws.onopen = () => { + // Абониране за промени в таблица + ws.send(JSON.stringify({ + id: 1, + type: 'subscribe', + table: 'users' + })); +}; + +ws.onmessage = (event) => { + const msg = JSON.parse(event.data); + if (msg.type === 'notification') { + console.log('Промяна:', msg.operation, msg.data); + } +}; +``` + +### Стрийминг Заявки + +```javascript +ws.send(JSON.stringify({ + id: 2, + type: 'query', + query: 'SELECT * FROM logs ORDER BY timestamp', + streaming: true +})); + +// Сървърът изпраща множество result frame-ове +// Последният frame има {"complete": true} +``` + +--- + +## Nim API Примери + +### Бинарен Протокол + +```nim +import barabadb/protocol/wire + +let msg = makeQueryMessage(1, "SELECT * FROM users") +let ready = makeReadyMessage(1) +let error = makeErrorMessage(1, 42, "Syntax error") +``` + +### Connection Pool + +```nim +import barabadb/protocol/pool + +var pool = newConnectionPool( + minConnections = 5, + maxConnections = 100, + idleTimeout = 30000 +) +let conn = pool.acquire() +# Използване на връзка... +pool.release(conn) +``` + +### Автентикация + +```nim +import barabadb/protocol/auth + +var am = newAuthManager("secret-key") +let token = am.createToken(JWTClaims(sub: "user1", role: "admin")) +let result = am.validateCredentials( + AuthCredentials(authMethod: amToken, payload: token) +) +``` + +### Rate Limiting + +```nim +import barabadb/protocol/ratelimit + +var rl = newRateLimiter( + rlaTokenBucket, + globalRate = 10000, + perClientRate = 1000 +) +if rl.allowRequest("client-123"): + echo "Заявката е разрешена" +``` diff --git a/docs/bg/security.md b/docs/bg/security.md new file mode 100644 index 0000000..9b53cd9 --- /dev/null +++ b/docs/bg/security.md @@ -0,0 +1,210 @@ +# Ръководство за Сигурност + +## TLS/SSL Криптиране + +BaraDB поддържа TLS 1.3 за всички протоколи (бинарен, HTTP, WebSocket). Ако не е предоставен сертификат, сървърът автоматично генерира self-signed сертификат при стартиране за криптиране без конфигурация. + +### Използване на Персонализирани Сертификати + +```bash +# Предоставяне на съществуващи сертификати +BARADB_TLS_ENABLED=true \ +BARADB_CERT_FILE=/etc/baradb/server.crt \ +BARADB_KEY_FILE=/etc/baradb/server.key \ +./build/baradadb +``` + +### Генериране на Self-Signed Сертификати + +```bash +openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \ + -days 365 -nodes -subj "/CN=localhost" +``` + +### Let's Encrypt (Продукция) + +Използвайте certbot и насочете BaraDB към генерираните файлове: + +```bash +sudo certbot certonly --standalone -d db.example.com + +BARADB_CERT_FILE=/etc/letsencrypt/live/db.example.com/fullchain.pem \ +BARADB_KEY_FILE=/etc/letsencrypt/live/db.example.com/privkey.pem \ +./build/baradadb +``` + +### TLS от Страна на Клиента + +```python +from baradb import Client + +client = Client("localhost", 9472, tls=True, tls_verify=True) +client.connect() +``` + +## Автентикация + +### JWT-Базирана Автентикация + +BaraDB използва JWT (JSON Web Tokens) с HMAC-SHA256 подписване. + +#### Включване на Автентикация + +```bash +BARADB_AUTH_ENABLED=true \ +BARADB_JWT_SECRET="$(openssl rand -hex 32)" \ +./build/baradadb +``` + +#### Създаване на Токени + +```nim +import barabadb/protocol/auth + +var am = newAuthManager("your-secret-key") +let token = am.createToken(JWTClaims( + sub: "user1", + role: "admin", + exp: getTime() + 24.hours +)) +``` + +#### Контрол на Достъп на База Роли + +| Роля | Права | +|------|-------| +| `admin` | Пълен достъп | +| `write` | Четене + запис | +| `read` | Само четене | +| `monitor` | Само метрики и health | + +#### Използване на Токени + +```bash +curl -H "Authorization: Bearer $TOKEN" \ + http://localhost:9470/api/query \ + -d '{"query": "SELECT * FROM users"}' +``` + +```python +from baradb import Client + +client = Client("localhost", 9472) +client.connect() +client.authenticate("eyJhbGciOiJIUzI1NiIs...") +``` + +### Многофакторна Автентикация (MFA) + +```nim +import barabadb/protocol/auth + +var am = newAuthManager("secret-key") +# TOTP-базирана MFA +let mfaCode = am.generateTOTP("user1") +let valid = am.validateTOTP("user1", mfaCode) +``` + +## Rate Limiting + +Token-bucket rate limiting предотвратява злоупотреби: + +```nim +import barabadb/protocol/ratelimit + +var rl = newRateLimiter( + rlaTokenBucket, + globalRate = 10000, # 10K заявки/s глобално + perClientRate = 1000, # 1K заявки/s на IP/токен + burstSize = 100 # Разрешаване на 100 заявки burst +) + +if not rl.allowRequest("client-ip"): + return error("Лимитът на заявки е надвишен") +``` + +## Мрежова Сигурност + +### Адрес за Свързване + +По подразбиране BaraDB се свързва към `127.0.0.1` (само localhost). За продукция: + +```bash +# Свързване към всички интерфейси (зад защитна стена или reverse proxy) +BARADB_ADDRESS=0.0.0.0 ./build/baradadb + +# Свързване към конкретен вътрешен интерфейс +BARADB_ADDRESS=10.0.0.5 ./build/baradadb +``` + +### Правила на Защитната Стена + +```bash +# Разрешаване само на сървъри на приложения +sudo ufw allow from 10.0.0.0/8 to any port 9472 +sudo ufw allow from 10.0.0.0/8 to any port 9470 + +# Блокиране на външен достъп до портове за управление +sudo ufw deny 9471 # WebSocket (само вътрешна употреба) +``` + +## Криптиране на Данни в Покой + +### Криптиране на Ниво ОС + +Използвайте LUKS за пълно дисково криптиране: + +```bash +cryptsetup luksFormat /dev/nvme0n1p2 +cryptsetup open /dev/nvme0n1p2 baradb-crypt +mkfs.ext4 /dev/mapper/baradb-crypt +mount /dev/mapper/baradb-crypt /var/lib/baradb +``` + +### Криптиране на Ниво Приложение + +BaraDB поддържа прозрачно криптиране на SSTable файлове: + +```bash +BARADB_STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \ +./build/baradadb +``` + +## Одитно Логване + +Всички заявки и административни действия се логват: + +```json +{ + "timestamp": "2025-01-15T10:30:00Z", + "level": "info", + "event": "query_executed", + "client_ip": "10.0.0.15", + "user": "app_user", + "query": "SELECT * FROM users WHERE id = ?", + "duration_ms": 12, + "rows_returned": 1 +} +``` + +Включване на одитно логване: + +```bash +BARADB_LOG_LEVEL=info \ +BARADB_LOG_FORMAT=json \ +BARADB_LOG_FILE=/var/log/baradb/audit.log \ +./build/baradadb +``` + +## Чеклист за Сигурност + +- [ ] Сменете JWT secret по подразбиране +- [ ] Включете TLS с валидни сертификати +- [ ] Свържете се към конкретни интерфейси +- [ ] Включете автентикация в продукция +- [ ] Конфигурирайте rate limiting +- [ ] Включете одитно логване +- [ ] Криптирайте данните в покой (LUKS или на ниво приложение) +- [ ] Стартирайте BaraDB като non-root потребител +- [ ] Поддържайте рестриктивни правила на защитната стена +- [ ] Ротирайте JWT secret-и редовно diff --git a/docs/bg/storage.md b/docs/bg/storage.md new file mode 100644 index 0000000..24fe40f --- /dev/null +++ b/docs/bg/storage.md @@ -0,0 +1,78 @@ +# Storage Engines + +BaraDB предоставя множество storage двигатели, оптимизирани за различни модели на достъп. + +## LSM-Tree (Key-Value) + +Основният storage engine с write-оптимизирана append-only лог структура. + +### Употреба + +```nim +import barabadb/storage/lsm + +var db = newLSMTree("./data") +db.put("key1", cast[seq[byte]]("value1")) +let (found, value) = db.get("key1") +db.close() +``` + +### Компоненти + +- **MemTable**: В-памет сортиран буфер +- **WAL**: Write-ahead log за устойчивост +- **SSTable**: Сортирани string таблици на диска +- **Bloom Filter**: Вероятностна проверка за принадлежност +- **Compaction**: Size-tiered стратегия с управление на нива +- **Page Cache**: LRU кеш с проследяване на hit rate + +## B-Tree Индекс + +Подреден индекс за range сканиране и точково търсене. + +### Употреба + +```nim +import barabadb/storage/btree + +var btree = newBTreeIndex[string, string]() +btree.insert("key1", "value1") +let values = btree.get("key1") +let range = btree.scan("key_a", "key_z") +``` + +## Write-Ahead Log (WAL) + +Осигурява устойчивост на операциите за запис. + +```nim +import barabadb/storage/wal + +var wal = newWAL("./wal") +wal.append("txn1", "SET key1 value1") +wal.flush() +``` + +## Bloom Filter + +Вероятностна структура от данни за бързи негативни проверки. + +```nim +import barabadb/storage/bloom + +var filter = newBloomFilter(10000, 0.01) +filter.add("key1") +if filter.mightContain("key1"): + echo "евентуално съществува" +``` + +## Memory-mapped I/O + +Ефективен достъп до файлове чрез mmap. + +```nim +import barabadb/storage/mmap + +var mapped = mmapFile("./data/file.dat") +let data = mapped.read(0, 100) +``` diff --git a/docs/bg/transactions.md b/docs/bg/transactions.md index 0cc9632..1c17ad6 100644 --- a/docs/bg/transactions.md +++ b/docs/bg/transactions.md @@ -1,6 +1,6 @@ -# Транзакции & MVCC +# Транзакции и MVCC -Multi-Version Concurrency Control със snapshot изолация. +MVCC (Multi-Version Concurrency Control) със snapshot изолация и deadlock детекция. ## Употреба @@ -10,21 +10,55 @@ import barabadb/core/mvcc var tm = newTxnManager() let txn = tm.beginTxn() +# Операции за запис discard tm.write(txn, "key1", cast[seq[byte]]("value1")) discard tm.write(txn, "key2", cast[seq[byte]]("value2")) +# Savepoint tm.savepoint(txn) -discard tm.rollbackToSavepoint(txn) +discard tm.write(txn, "key3", cast[seq[byte]]("value3")) +discard tm.rollbackToSavepoint(txn) # отмяна на key3 +# Commit discard tm.commit(txn) ``` -## Изолация +## Изолация на Транзакции -BaraDB използва **snapshot isolation**: -- Читателите не блокират писатели -- Писателите не блокират читатели -- Всяка транзакция вижда консистентен моментна снимка +BaraDB използва **snapshot изолация**: +- Четящите не блокират пишещите +- Пишещите не блокират четящите +- Всяка транзакция вижда консистентен snapshot + +## Deadlock Детекция + +```nim +import barabadb/core/deadlock + +var detector = newDeadlockDetector() +if detector.detectCycle(txn1, txn2): + echo "Открит deadlock!" +``` + +## Write-Ahead Log + +```nim +import barabadb/storage/wal + +var wal = newWAL("./wal") +wal.append(txnId, "SET key value") +wal.flush() +``` + +## Savepoints + +Вложени savepoints на транзакции: + +```nim +tm.savepoint(txn, "sp1") +# ... операции ... +tm.rollbackToSavepoint(txn, "sp1") +``` ## Формална Верификация @@ -32,13 +66,13 @@ MVCC / Snapshot Isolation протоколът е формално специф - **Спецификация:** `formal-verification/mvcc.tla` - **Проверени свойства:** - - `NoDirtyReads` — транзакциите никога не четат неcommit-нати данни + - `NoDirtyReads` — транзакциите никога не четат некомитнати данни - `ReadOwnWrites` — транзакциите винаги виждат собствените си записи - - `WriteWriteConflict` — first-committer-wins + - `WriteWriteConflict` — first-committer-wins (няма две комитнати транзакции да пишат един и същ ключ) -Пускане на TLC: +Пускане на TLC локално: ```bash cd formal-verification java -cp tla2tools.jar tlc2.TLC -config models/mvcc.cfg mvcc.tla -``` \ No newline at end of file +``` diff --git a/docs/bg/troubleshooting.md b/docs/bg/troubleshooting.md new file mode 100644 index 0000000..33c52cf --- /dev/null +++ b/docs/bg/troubleshooting.md @@ -0,0 +1,164 @@ +# Ръководство за Отстраняване на Проблеми + +## Проблеми с Инсталацията + +### Nim не е намерен + +``` +nim: command not found +``` + +**Решение:** + +```bash +# Linux/macOS +curl https://nim-lang.org/choosenim/init.sh -sSf | sh + +# Добавяне към PATH +echo 'export PATH=$HOME/.nimble/bin:$PATH' >> ~/.bashrc +source ~/.bashrc +``` + +### SSL Грешка при Компилация + +``` +Error: BaraDB requires SSL support. Compile with -d:ssl +``` + +**Решение:** Винаги компилирайте с `-d:ssl`: + +```bash +nim c -d:ssl -d:release -o:build/baradadb src/baradadb.nim +``` + +### Липсващи Зависимости + +``` +Error: cannot open file: hunos +``` + +**Решение:** + +```bash +nimble install -d -y +``` + +## Проблеми по Време на Изпълнение + +### Портът е Зает + +``` +Error: unhandled exception: Address already in use [OSError] +``` + +**Решение 1:** Сменете порта: + +```bash +BARADB_PORT=5433 ./build/baradadb +``` + +**Решение 2:** Убийте съществуващия процес: + +```bash +lsof -ti:9472 | xargs kill -9 +``` + +### Permission Denied на Директория с Данни + +``` +Error: Permission denied: ./data +``` + +**Решение:** + +```bash +mkdir -p ./data +chmod 755 ./data +# или използвайте друга директория +BARADB_DATA_DIR=/tmp/baradb ./build/baradadb +``` + +## Storage Проблеми + +### Бавни Заявки + +1. Проверете cache hit rate: +```bash +curl http://localhost:9470/metrics | grep cache_hit_rate +``` + +2. Пуснете ръчен compaction: +```bash +curl -X POST http://localhost:9470/admin/compact +``` + +3. Проверете броя на SSTables: +```bash +curl http://localhost:9470/metrics | grep sstables +``` + +### Растящо Дисково Пространство + +```bash +# Проверете размера на директорията с данни +du -sh ./data + +# Проверете WAL размера +du -sh ./data/server/wal + +# Пуснете ръчен compaction за освобождаване на място +curl -X POST http://localhost:9470/admin/compact +``` + +## Проблеми с Автентикация + +### Грешка при Верификация на JWT + +```json +{"error": {"code": "AUTH_REQUIRED", "message": "Authentication required"}} +``` + +**Решение:** Уверете се, че изпращате правилния токен: + +```bash +curl -H "Authorization: Bearer $TOKEN" \ + http://localhost:9470/api/query \ + -d '{"query": "SELECT 1"}' +``` + +## Разпределени Проблеми + +### Възел не се Присъединява към Клъстер + +1. Проверете мрежовата свързаност между възлите +2. Проверете gossip порта (raft порт + 100) +3. Проверете логовете за грешки при gossip + +### Репликационно Закъснение + +```bash +# Проверете replication lag +curl http://localhost:9470/metrics/cluster | jq .replication_lag_ms +``` + +## Често Задавани Въпроси + +### Как да нулирам напълно базата данни? + +```bash +# Спрете сървъра +# Изтрийте директорията с данни +rm -rf ./data +# Стартирайте отново — нова празна база ще бъде създадена +./build/baradadb +``` + +### Как да мигрирам от друга база данни? + +BaraDB поддържа импорт чрез JSON и CSV: + +```bash +curl -X POST http://localhost:9470/api/import \ + -H "Content-Type: application/json" \ + -d '{"table": "users", "format": "json", "data": [...]}' +``` diff --git a/docs/bg/udf.md b/docs/bg/udf.md new file mode 100644 index 0000000..b1e96aa --- /dev/null +++ b/docs/bg/udf.md @@ -0,0 +1,55 @@ +# Потребителски Функции (UDF) + +Разширете BaraQL с персонализирани функции. + +## Употреба + +```nim +import barabadb/query/udf + +var reg = newUDFRegistry() + +# Регистриране на стандартна библиотека +reg.registerStdlib() # abs, sqrt, pow, lower, upper, len, trim, substr, toString, toInt + +# Персонализирана функция +reg.register("greet", @[UDFParam(name: "name", typeName: "str")], + "str", proc(args: seq[Value]): Value = + return Value(kind: vkString, strVal: "Hello, " & args[0].strVal & "!")) +``` + +## Функции от Стандартната Библиотека + +| Функция | Описание | Пример | +|----------|----------|--------| +| `abs(n)` | Абсолютна стойност | `abs(-5)` → 5 | +| `sqrt(n)` | Квадратен корен | `sqrt(16)` → 4 | +| `pow(n, e)` | Степенуване | `pow(2, 3)` → 8 | +| `lower(s)` | Малки букви | `lower('ABC')` → 'abc' | +| `upper(s)` | Главни букви | `upper('abc')` → 'ABC' | +| `len(s)` | Дължина | `len('hello')` → 5 | +| `trim(s)` | Премахване на интервали | `trim(' hello ')` → 'hello' | +| `substr(s, start, len)` | Подниз | `substr('hello', 0, 3)` → 'hel' | +| `toString(n)` | Конвертиране в низ | `toString(123)` → '123' | +| `toInt(s)` | Конвертиране в integer | `toInt('123')` → 123 | + +## Регистриране на Функции + +```nim +reg.register( + name: "my_function", + params: @[ + UDFParam(name: "arg1", typeName: "str"), + UDFParam(name: "arg2", typeName: "int32") + ], + returnType: "str", + body: proc(args: seq[Value]): Value = + result = Value(kind: vkString, strVal: "") +) +``` + +## Използване на UDF в Заявки + +```sql +SELECT greet(name) FROM users; +``` diff --git a/docs/bg/vector.md b/docs/bg/vector.md index 3ad8a3d..bee5bd2 100644 --- a/docs/bg/vector.md +++ b/docs/bg/vector.md @@ -1,8 +1,89 @@ -# Vector Търсене +# Vector Search Engine -HNSW и IVF-PQ индекси за търсене на прилика. +Нативни HNSW и IVF-PQ индекси за търсене на прилика с пълна SQL интеграция. -## Употреба +## SQL Употреба + +### Създаване на Векторни Колони + +```sql +CREATE TABLE items ( + id INT PRIMARY KEY, + embedding VECTOR(768) +); +``` + +Типът `VECTOR(n)` съхранява float32 масиви с фиксирана размерност `n`. + +### Вмъкване на Вектори + +```sql +INSERT INTO items (id, embedding) VALUES (1, '[0.1, 0.2, 0.3, ...]'); +``` + +### Функции за Векторно Разстояние + +```sql +-- Косинусово разстояние (0 = идентични, 1 = ортогонални) +SELECT id, cosine_distance(embedding, '[0.1, 0.2, 0.3]') AS dist +FROM items; + +-- Евклидово / L2 разстояние +SELECT id, euclidean_distance(embedding, '[0.1, 0.2, 0.3]') AS dist +FROM items; + +-- L2 разстояние с <-> оператор +SELECT id, embedding <-> '[0.1, 0.2, 0.3]' AS dist +FROM items; + +-- Скаларно произведение (отрицателно dot product за минимизация) +SELECT id, inner_product(embedding, '[0.1, 0.2, 0.3]') AS dist +FROM items; + +-- Манхатън / L1 разстояние +SELECT id, l1_distance(embedding, '[0.1, 0.2, 0.3]') AS dist +FROM items; +``` + +### Търсене на Най-близки Съседи + +```sql +-- Топ-10 най-близки съседи по косинусово разстояние +SELECT id FROM items +ORDER BY cosine_distance(embedding, '[0.1, 0.2, 0.3]') ASC +LIMIT 10; + +-- Топ-5 най-близки съседи по евклидово разстояние +SELECT id FROM items +ORDER BY embedding <-> '[0.1, 0.2, 0.3]' +LIMIT 5; +``` + +### Векторни Индекси + +```sql +-- Създаване на HNSW индекс за приблизително търсене на най-близки съседи +CREATE INDEX idx_items_vec ON items(embedding) USING hnsw; + +-- Индексът се поддържа автоматично при INSERT и UPDATE +``` + +Поддържани индекс методи: +- `USING hnsw` — Hierarchical Navigable Small World (по подразбиране: косинусова метрика) +- `USING ivfpq` — Inverted File с Product Quantization + +### Валидация на Размерност + +BaraDB валидира размерностите на векторите при вмъкване: + +```sql +-- Това ще даде грешка: очаквани 768 размерности, но подадени 3 +INSERT INTO items (id, embedding) VALUES (2, '[1.0, 2.0, 3.0]'); +``` + +## Нативно Nim API + +За вградена или високопроизводителна употреба използвайте нативното Nim API директно: ```nim import barabadb/vector/engine @@ -10,32 +91,67 @@ import barabadb/vector/engine var idx = newHNSWIndex(dimensions = 128) idx.insert(1, @[1.0'f32, 0.0'f32, ...], {"category": "A"}.toTable) +# Търсене let results = idx.search(queryVector, k = 10) + +# С филтриране по метаданни +let filtered = idx.searchWithFilter(queryVector, k = 10, + filter = proc(meta: Table[string, string]): bool = + return meta.getOrDefault("category") == "A") ``` -## Индекс Типове +## Типове Индекси ### HNSW -Иерархичен навигируем малък свят: +Иерархичен навигируем малък свят за приблизително търсене на най-близки съседи. ```nim -var hnsw = newHNSWIndex(dimensions = 128, m = 16) +var hnsw = newHNSWIndex( + dimensions = 128, + m = 16, # връзки на слой + efConstruction = 200, # ширина на търсене при изграждане + efSearch = 100 # ширина на търсене при заявка +) ``` ### IVF-PQ -Инвертиран файл с продуктово квантуване: +Inverted File Index с продуктово квантуване за компресия. ```nim -var ivfpq = newIVFPQIndex(dimensions = 128, numCentroids = 256) +var ivfpq = newIVFPQIndex( + dimensions = 128, + numCentroids = 256, + subQuantizers = 8 +) ``` ## Метрики за Разстояние -| Метрика | Описание | -|---------|----------| -| `cosine` | Косинусова прилика | -| `euclidean` | L2 разстояние | -| `dotproduct` | Скаларно произведение | -| `manhattan` | L1 разстояние | \ No newline at end of file +| Метрика | SQL Функция | Описание | +|---------|-------------|----------| +| `cosine` | `cosine_distance(a, b)` | Косинусова dissimilarity (1 - similarity) | +| `euclidean` | `euclidean_distance(a, b)` / `<->` | L2 разстояние | +| `dotproduct` | `inner_product(a, b)` | Отрицателно скаларно произведение | +| `manhattan` | `l1_distance(a, b)` | L1 разстояние | + +## Квантуване + +```nim +import barabadb/vector/quant + +# Скаларно квантуване +let scalar = scalarQuantize(data, bits = 8) + +# Продуктово квантуване +let pq = productQuantize(data, subVectors = 8, bits = 8) +``` + +## SIMD Ускорение + +```nim +import barabadb/vector/simd + +let dist = simdCosineDistance(vec1, vec2) +``` diff --git a/docs/en/configuration.md b/docs/en/configuration.md index ff9e433..ebfb6cf 100644 --- a/docs/en/configuration.md +++ b/docs/en/configuration.md @@ -156,7 +156,7 @@ raft_peers = "node2:9001,node3:9001" ``` ``` -BaraDB v0.1.0 — Multimodal Database Engine +BaraDB v1.1.0 — Multimodal Database Engine Usage: baradadb [options] diff --git a/docs/en/installation.md b/docs/en/installation.md index 9c39e8e..ea6241f 100644 --- a/docs/en/installation.md +++ b/docs/en/installation.md @@ -144,7 +144,7 @@ strip build/baradadb ```bash ./build/baradadb --version -# Expected: BaraDB v0.1.0 — Multimodal Database Engine +# Expected: BaraDB v1.1.0 — Multimodal Database Engine ``` ## Running Tests @@ -259,7 +259,7 @@ db.close() ./build/baradadb # Expected output: -# BaraDB v0.1.0 — Multimodal Database Engine +# BaraDB v1.1.0 — Multimodal Database Engine # BaraDB TCP listening on 127.0.0.1:9472 # Test with HTTP API diff --git a/docs/fa/baraql.md b/docs/fa/baraql.md index f45be04..5f266e8 100644 --- a/docs/fa/baraql.md +++ b/docs/fa/baraql.md @@ -489,4 +489,109 @@ LIMIT 10; -- اجرای موازی SELECT /*+ PARALLEL(4) */ * FROM large_table; -``` \ No newline at end of file +``` + +## توابع پنجره‌ای + +```sql +-- توابع رتبه‌بندی +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- توابع مقدار +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- توابع توزیع +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### مشخصات فریم + +```sql +-- فریم ROWS +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- فریم RANGE +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## ERP چند مستأجری + +BaraDB از اجرای چندین شرکت (tenant) در یک نمونه پایگاه داده پشتیبانی می‌کند، با استفاده از **امنیت سطح سطر (RLS)** همراه با **متغیرهای جلسه**. + +### متغیرهای جلسه + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### کاربر / نقش فعلی + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### جداسازی مستأجر با RLS + +```sql +-- فعال کردن RLS روی جدول +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- ایجاد سیاست فیلترینگ بر اساس مستأجر +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- هر جلسه فقط داده‌های خود را می‌بیند +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- فقط ردیف‌های company-a +``` + +### چرا چند مستأجری؟ + +- **یک نمونه، مستأجران زیاد** — نیازی به اجرای ۱۰۰ پایگاه داده جداگانه نیست +- **اسناد JSONB** — ذخیره‌سازی با طرح انعطاف‌پذیر، افزودن آسان فیلدها برای هر مستأجر +- **RLS تضمین می‌کند** — پایگاه داده مرزهای مستأجر را اعمال می‌کند، نه فقط برنامه + +## کلمات کلیدی پشتیبانی‌شده + +| دسته | کلمات کلیدی | +|----------|----------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Transaction | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Graph | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Vector | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (BM25 match) | +| Recovery | RECOVER TO TIMESTAMP | +| Functions | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Session | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Functions | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | \ No newline at end of file diff --git a/docs/fa/installation.md b/docs/fa/installation.md index 99d5ea0..00589dd 100644 --- a/docs/fa/installation.md +++ b/docs/fa/installation.md @@ -144,7 +144,7 @@ strip build/baradadb ```bash ./build/baradadb --version -# انتظار: BaraDB v0.1.0 — Multimodal Database Engine +# انتظار: BaraDB v1.1.0 — Multimodal Database Engine ``` ## اجرای تست‌ها @@ -259,7 +259,7 @@ db.close() ./build/baradadb # خروجی مورد انتظار: -# BaraDB v0.1.0 — Multimodal Database Engine +# BaraDB v1.1.0 — Multimodal Database Engine # BaraDB TCP listening on 127.0.0.1:9472 # تست با HTTP API diff --git a/docs/ru/baraql.md b/docs/ru/baraql.md index ede4eff..1fa395e 100644 --- a/docs/ru/baraql.md +++ b/docs/ru/baraql.md @@ -489,4 +489,109 @@ LIMIT 10; -- Параллельное выполнение SELECT /*+ PARALLEL(4) */ * FROM large_table; -``` \ No newline at end of file +``` + +## Оконные функции + +```sql +-- Функции ранжирования +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- Функции значения +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- Функции распределения +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### Спецификации фрейма + +```sql +-- ROWS фрейм +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- RANGE фрейм +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## Мультитенантный ERP + +BaraDB поддерживает работу нескольких компаний (арендаторов) в одной базе данных, используя **безопасность на уровне строк (RLS)** в сочетании с **переменными сессии**. + +### Переменные сессии + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### Текущий пользователь / роль + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### Изоляция арендаторов через RLS + +```sql +-- Включить RLS на таблице +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- Создать политику фильтрации по арендатору +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- Каждая сессия видит только свои данные +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- только строки company-a +``` + +### Зачем мультитенантность? + +- **Один экземпляр, много арендаторов** — не нужно запускать 100 отдельных баз данных +- **JSONB документы** — гибкая схема, легко добавлять поля для каждого арендатора +- **RLS гарантирует изоляцию** — база данных обеспечивает границы арендаторов, а не только приложение + +## Поддерживаемые ключевые слова + +| Категория | Ключевые слова | +|----------|----------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Transaction | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Graph | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Vector | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (BM25 match) | +| Recovery | RECOVER TO TIMESTAMP | +| Functions | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Session | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Functions | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | \ No newline at end of file diff --git a/docs/ru/configuration.md b/docs/ru/configuration.md index 3fb993d..be1ada0 100644 --- a/docs/ru/configuration.md +++ b/docs/ru/configuration.md @@ -156,7 +156,7 @@ raft_peers = "node2:9001,node3:9001" ``` ``` -BaraDB v0.1.0 — Multimodal Database Engine +BaraDB v1.1.0 — Multimodal Database Engine Usage: baradadb [options] diff --git a/docs/ru/installation.md b/docs/ru/installation.md index 122b66e..ba0cec7 100644 --- a/docs/ru/installation.md +++ b/docs/ru/installation.md @@ -144,7 +144,7 @@ strip build/baradadb ```bash ./build/baradadb --version -# Ожидается: BaraDB v0.1.0 — Multimodal Database Engine +# Ожидается: BaraDB v1.1.0 — Multimodal Database Engine ``` ## Запуск тестов @@ -259,7 +259,7 @@ db.close() ./build/baradadb # Ожидаемый вывод: -# BaraDB v0.1.0 — Multimodal Database Engine +# BaraDB v1.1.0 — Multimodal Database Engine # BaraDB TCP listening on 127.0.0.1:9472 # Проверка через HTTP API diff --git a/docs/tr/baraql.md b/docs/tr/baraql.md index 261d4b7..e80335c 100644 --- a/docs/tr/baraql.md +++ b/docs/tr/baraql.md @@ -98,13 +98,172 @@ RETURN friend.name; ```sql BEGIN; INSERT users { name := 'Alice', age := 30 }; +INSERT orders { user_id := last_insert_id(), total := 100 }; +COMMIT; + +-- Savepoint ile +BEGIN; +INSERT users { name := 'Bob', age := 25 }; +SAVEPOINT sp1; +INSERT orders { user_id := last_insert_id(), total := 200 }; +-- Hata, savepoint'e geri al +ROLLBACK TO sp1; COMMIT; ``` -## Grafik Kalıpları +## Tam Metin Arama ```sql -MATCH (p:Person)-[:KNOWS]->(friend:Person) -WHERE p.name = 'Alice' -RETURN friend.name; -``` \ No newline at end of file +-- Temel arama +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('database programming'); + +-- İlgi puanı ile +SELECT title, relevance() +FROM articles +WHERE MATCH(title, body) AGAINST('Nim language') +ORDER BY relevance() DESC; + +-- Boolean modu +SELECT * FROM articles +WHERE MATCH(title, body) AGAINST('+Nim -Python' IN BOOLEAN MODE); + +-- Fuzzy arama +SELECT * FROM articles +WHERE MATCH(title) AGAINST('programing' WITH FUZZINESS 2); +``` + +## Kullanıcı Tanımlı Fonksiyonlar + +```sql +-- UDF kaydet +CREATE FUNCTION greet(name str) -> str { + RETURN 'Hello, ' || name || '!'; +}; + +-- Kullan +SELECT greet(name) FROM users; + +-- Dahili fonksiyonlar +SELECT abs(-5), sqrt(16), lower('HELLO'), len('test'); +``` + +## Sorgu İpuçları + +```sql +-- İndeks kullanımını zorla +SELECT /*+ USE_INDEX(idx_users_age) */ * FROM users WHERE age > 18; + +-- Approximate vektör araması zorla +SELECT /*+ APPROXIMATE */ * FROM vectors +ORDER BY cosine_distance(embedding, [...]) +LIMIT 10; + +-- Paralel çalıştırma +SELECT /*+ PARALLEL(4) */ * FROM large_table; +``` + +## Pencere Fonksiyonları + +```sql +-- Sıralama fonksiyonları +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- Değer fonksiyonları +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- Dağılım fonksiyonları +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### Çerçeve Spesifikasyonları + +```sql +-- ROWS çerçevesi +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- RANGE çerçevesi +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## Çok Kiracılı ERP + +BaraDB, **Satır Düzeyinde Güvenlik (RLS)** ve **oturum değişkenlerini** birleştirerek tek bir veritabanı örneğinde birden fazla şirketi (kiracı) çalıştırmayı destekler. + +### Oturum Değişkenleri + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### Mevcut Kullanıcı / Rol + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### RLS Kiracı İzolasyonu + +```sql +-- Tabloda RLS etkinleştir +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- Kiracıya göre filtreleme ilkesi oluştur +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- Her oturum yalnızca kendi verilerini görür +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- yalnızca company-a satırları +``` + +### Neden Çok Kiracılı? + +- **Bir örnek, çok kiracı** — 100 ayrı veritabanı çalıştırmaya gerek yok +- **JSONB belgeleri** — Esnek şema depolama, her kiracı için kolayca alan ekleme +- **RLS izolasyonu garanti eder** — Veritabanı kiracı sınırlarını uygular, yalnızca uygulama değil + +## Desteklenen Anahtar Kelimeler + +| Kategori | Anahtar Kelimeler | +|----------|----------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Transaction | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Graph | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Vector | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (BM25 eşleşme) | +| Recovery | RECOVER TO TIMESTAMP | +| Functions | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Session | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Functions | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | \ No newline at end of file diff --git a/docs/tr/installation.md b/docs/tr/installation.md index a56fc0d..bac7fff 100644 --- a/docs/tr/installation.md +++ b/docs/tr/installation.md @@ -22,38 +22,284 @@ ### Linux ```bash +# Resmi kurulum scripti curl https://nim-lang.org/choosenim/init.sh -sSf | sh + +# Ubuntu/Debian +sudo apt-get update +sudo apt-get install nim + +# Fedora +sudo dnf install nim + +# Arch Linux +sudo pacman -S nim ``` ### macOS ```bash +# Homebrew brew install nim + +# MacPorts +sudo port install nim ``` ### Windows ```powershell +# choosenim ile +curl.exe -A "MSYS2_$(uname -m)" -L https://nim-lang.org/choosenim/init.ps1 | powershell - + +# winget ile winget install nim + +# scoop ile +scoop install nim ``` +### Kurulumu Doğrulama + +```bash +nim --version +# Beklenen: Nim Compiler Version 2.2.0 veya daha yeni +``` + +## OpenSSL Kurulumu + +### Linux + +```bash +# Ubuntu/Debian +sudo apt-get install libssl-dev + +# Fedora +sudo dnf install openssl-devel + +# Arch Linux +sudo pacman -S openssl +``` + +### macOS + +OpenSSL sistemle birlikte gelir. Gerekirse: + +```bash +brew install openssl +``` + +### Windows + +OpenSSL, Nim Windows dağıtımıyla birlikte gelir. Manuel derlemeler için [slproweb.com](https://slproweb.com/products/Win32OpenSSL.html) adresinden indirin. + ## BaraDB Derleme +### Depoyu Klonlama + ```bash git clone https://github.com/katehonz/barabaDB.git cd barabaDB +``` + +### Bağımlılıkları Kurma + +```bash nimble install -d -y +``` + +### Derleme Seçenekleri + +#### Debug Derleme + +```bash +nim c -d:ssl -o:build/baradadb src/baradadb.nim +``` + +#### Release Derleme (Önerilen) + +```bash nim c -d:ssl -d:release --opt:speed -o:build/baradadb src/baradadb.nim ``` +#### Nimble Tasks Kullanma + +```bash +# Debug derleme +nimble build_debug + +# Release derleme +nimble build_release +``` + +#### Binary Boyutunu Küçültme + +```bash +nim c -d:ssl -d:release --opt:size -o:build/baradadb src/baradadb.nim +strip build/baradadb +``` + +### Derlemeyi Doğrulama + +```bash +./build/baradadb --version +# Beklenen: BaraDB v1.1.0 — Multimodal Database Engine +``` + +## Testleri Çalıştırma + +### Tüm Testler + +```bash +nim c -d:ssl -r tests/test_all.nim +``` + +### Belirli Test Süitleri + +```bash +# Depolama testleri +nim c -d:ssl -r tests/test_storage.nim + +# Sorgu motoru testleri +nim c -d:ssl -r tests/test_query.nim + +# Protokol testleri +nim c -d:ssl -r tests/test_protocol.nim +``` + +### Benchmarklar + +```bash +nim c -d:ssl -d:release -r benchmarks/bench_all.nim +``` + +## Kurulum Seçenekleri + +### Sistem Geneli Kurulum + +```bash +# Release binary derle +nimble build_release + +# /usr/local/bin'e kur +sudo cp build/baradadb /usr/local/bin/ +sudo chmod +x /usr/local/bin/baradadb + +# Veri dizini oluştur +sudo mkdir -p /var/lib/baradb +sudo chmod 755 /var/lib/baradb +``` + +### Ön Derlenmiş Binary + +En son sürümü platformunuz için indirin: + +```bash +# Linux x86_64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64 +chmod +x baradadb-linux-amd64 +mv baradadb-linux-amd64 /usr/local/bin/baradadb + +# Linux ARM64 +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-arm64 +chmod +x baradadb-linux-arm64 +mv baradadb-linux-arm64 /usr/local/bin/baradadb + +# macOS +wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-darwin-amd64 +chmod +x baradadb-darwin-amd64 +mv baradadb-darwin-amd64 /usr/local/bin/baradadb +``` + +### Docker + +```bash +# Resmi image'i çek +docker pull barabadb/barabadb:latest + +# Çalıştır +docker run -d \ + -p 9472:9472 \ + -p 9470:9470 \ + -p 9471:9471 \ + -v baradb_data:/data \ + barabadb/barabadb +``` + +### Docker Compose + +```bash +docker-compose up -d +``` + +### Gömülü Kullanım (Nim Projeleri) + +`.nimble` dosyanıza ekleyin: + +```nim +requires "barabadb >= 1.1.0" +``` + +Kodunuzda kullanın: + +```nim +import barabadb/storage/lsm + +var db = newLSMTree("./data") +db.put("key", cast[seq[byte]]("value")) +let (found, val) = db.get("key") +db.close() +``` + ## İlk Çalıştırma ```bash +# Sunucuyu başlat ./build/baradadb + +# Beklenen çıktı: +# BaraDB v1.1.0 — Multimodal Database Engine +# BaraDB TCP listening on 127.0.0.1:9472 + +# HTTP API ile test et curl http://localhost:9470/health + +# İnteraktif shell ./build/baradadb --shell ``` +## Kurulum Sorunlarını Giderme + +### "cannot open file: hunos" + +```bash +nimble install -d -y +``` + +### "BaraDB requires SSL support" + +Her zaman `-d:ssl` ile derleyin: + +```bash +nim c -d:ssl -o:build/baradadb src/baradadb.nim +``` + +### Yavaş derleme + +Paralel derleme kullanın: + +```bash +nim c -d:ssl -d:release --parallelBuild:4 -o:build/baradadb src/baradadb.nim +``` + +### Büyük binary boyutu + +Boyut optimizasyonu kullanın: + +```bash +nim c -d:ssl -d:release --opt:size --passL:-s -o:build/baradadb src/baradadb.nim +``` + ## Sonraki Adımlar - [Hızlı Başlangıç](quickstart.md) diff --git a/docs/zh/baraql.md b/docs/zh/baraql.md index a38eaa9..1f7853d 100644 --- a/docs/zh/baraql.md +++ b/docs/zh/baraql.md @@ -489,4 +489,109 @@ LIMIT 10; -- 并行执行 SELECT /*+ PARALLEL(4) */ * FROM large_table; -``` \ No newline at end of file +``` + +## 窗口函数 + +```sql +-- 排名函数 +SELECT + name, + department, + ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn, + RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS r, + DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dr +FROM employees; + +-- 值函数 +SELECT + name, + salary, + LAG(salary, 1, 0) OVER (ORDER BY salary) AS prev_salary, + LEAD(salary, 1, 0) OVER (ORDER BY salary) AS next_salary, + FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS cheapest, + LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary) AS most_expensive +FROM employees; + +-- 分布函数 +SELECT name, NTILE(4) OVER (ORDER BY salary) AS quartile FROM employees; +``` + +### 帧规格 + +```sql +-- ROWS 帧 +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW +) + +-- RANGE 帧 +SUM(salary) OVER ( + PARTITION BY department + ORDER BY hire_date + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +) +``` + +## 多租户 ERP + +BaraDB 支持在单个数据库实例中运行多个公司(租户),使用**行级安全性(RLS)**结合**会话变量**。 + +### 会话变量 + +```sql +SET app.tenant_id = 'company-123'; +SELECT current_setting('app.tenant_id') AS tenant; +``` + +### 当前用户 / 角色 + +```sql +SELECT current_user AS me, current_role AS my_role; +``` + +### RLS 租户隔离 + +```sql +-- 在表上启用 RLS +ALTER TABLE invoices ENABLE ROW LEVEL SECURITY; + +-- 创建按租户过滤的策略 +CREATE POLICY tenant_isolation ON invoices + FOR SELECT USING (tenant_id = current_setting('app.tenant_id')); + +-- 每个会话只能看到自己的数据 +SET app.tenant_id = 'company-a'; +SELECT * FROM invoices; -- 仅限 company-a 的行 +``` + +### 为什么选择多租户? + +- **一个实例,多个租户** — 无需运行 100 个独立的数据库 +- **JSONB 文档** — 模式灵活的存储,易于为每个租户添加字段 +- **RLS 保证隔离** — 数据库强制执行租户边界,而不仅仅是应用程序 + +## 支持的关键字 + +| 类别 | 关键字 | +|----------|----------| +| DQL | SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT | +| DML | INSERT, UPDATE, DELETE, SET, VALUES | +| DDL | CREATE TYPE, DROP TYPE, CREATE INDEX, DROP INDEX, ALTER TYPE | +| Join | INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, CROSS JOIN, ON | +| Set | UNION, UNION ALL, INTERSECT, EXCEPT | +| CTEs | WITH, RECURSIVE, AS | +| Case | CASE, WHEN, THEN, ELSE, END | +| Transaction | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | +| Graph | MATCH, RETURN, WHERE, shortestPath, type | +| FTS | MATCH, AGAINST, relevance, IN BOOLEAN MODE, WITH FUZZINESS | +| Vector | cosine_distance, euclidean_distance, inner_product, l1_distance, l2_distance, <-> | +| JSON | ->, ->> | +| FTS | @@ (BM25 match) | +| Recovery | RECOVER TO TIMESTAMP | +| Functions | count, sum, avg, min, max, stddev, variance, abs, sqrt, lower, upper, len, trim, substr, now, last_insert_id, current_setting | +| Session | SET, current_setting, current_user, current_role | +| Window | OVER, PARTITION BY, ROWS, RANGE, UNBOUNDED PRECEDING, CURRENT ROW, FOLLOWING | +| Window Functions | ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, FIRST_VALUE, LAST_VALUE, NTILE | \ No newline at end of file diff --git a/docs/zh/configuration.md b/docs/zh/configuration.md index db2a145..afc2b4a 100644 --- a/docs/zh/configuration.md +++ b/docs/zh/configuration.md @@ -156,7 +156,7 @@ raft_peers = "node2:9001,node3:9001" ``` ``` -BaraDB v0.1.0 — Multimodal Database Engine +BaraDB v1.1.0 — Multimodal Database Engine Usage: baradadb [options] diff --git a/docs/zh/installation.md b/docs/zh/installation.md index aa1b7fb..78be0f7 100644 --- a/docs/zh/installation.md +++ b/docs/zh/installation.md @@ -144,7 +144,7 @@ strip build/baradadb ```bash ./build/baradadb --version -# 预期输出: BaraDB v0.1.0 — Multimodal Database Engine +# 预期输出: BaraDB v1.1.0 — Multimodal Database Engine ``` ## 运行测试 @@ -259,7 +259,7 @@ db.close() ./build/baradadb # 预期输出: -# BaraDB v0.1.0 — Multimodal Database Engine +# BaraDB v1.1.0 — Multimodal Database Engine # BaraDB TCP listening on 127.0.0.1:9472 # 使用 HTTP API 测试