feat: standalone Nim client package (baradb) with nimble + 16 tests

Standalone Nim client ():
- Self-contained: no dependency on BaraDB server code
- Inlined wire protocol with full serialization (int32/64, float64, string, bytes, array, object)
- Async client (connect/close/query/exec/ping)
- Sync wrapper (newSyncClient)
- Fluent QueryBuilder (select/from/where/join/groupBy/having/orderBy/limit)
- Nimble package file for ecosystem (nimble install baradb)
- 16 passing tests covering: QueryBuilder (6), Config (3), Wire protocol (5), Client (2)

Also has Python + JS clients with identical API
This commit is contained in:
2026-05-06 02:31:52 +03:00
parent da7e3afb44
commit c6de13ef7a
3 changed files with 514 additions and 0 deletions
+129
View File
@@ -0,0 +1,129 @@
## BaraDB Nim Client — Tests
import std/unittest
import std/strutils
import baradb/client
suite "QueryBuilder":
test "Simple SELECT":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name", "age").from("users").build()
check sql == "SELECT name, age FROM users"
test "SELECT with WHERE":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name").from("users").where("age > 18").build()
check sql == "SELECT name FROM users WHERE age > 18"
test "SELECT with JOIN":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("u.name", "o.total").from("users u")
.join("orders o", "u.id = o.user_id").build()
check "JOIN" in sql
check "ON" in sql
test "SELECT with GROUP BY and HAVING":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("dept", "count(*)").from("employees")
.groupBy("dept").having("count(*) > 5").build()
check "GROUP BY" in sql
check "HAVING" in sql
test "SELECT with ORDER BY and LIMIT":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("name").from("users")
.orderBy("name", "DESC").limit(10).offset(5).build()
check "ORDER BY name DESC" in sql
check "LIMIT 10" in sql
check "OFFSET 5" in sql
test "Full complex query":
let client = newClient()
let qb = newQueryBuilder(client)
let sql = qb.select("u.name", "count(*) as cnt")
.from("users u")
.leftJoin("orders o", "u.id = o.user_id")
.where("u.age > 18")
.groupBy("u.name")
.having("cnt > 3")
.orderBy("cnt", "DESC")
.limit(50)
.build()
check sql.startsWith("SELECT")
check "LEFT JOIN" in sql
check "WHERE" in sql
check "GROUP BY" in sql
check "HAVING" in sql
check "ORDER BY" in sql
check "LIMIT 50" in sql
suite "Client Config":
test "Default config":
let config = defaultConfig()
check config.host == "127.0.0.1"
check config.port == 5432
check config.database == "default"
test "Custom config":
let config = ClientConfig(host: "db.example.com", port: 9999,
database: "production", username: "app")
check config.host == "db.example.com"
check config.port == 9999
test "Client creation":
let client = newClient()
check not client.isConnected
suite "Wire Protocol":
test "Build query message":
let msg = makeQueryMessage(1, "SELECT 1")
check msg.len > 0
# First 4 bytes: mkQuery (0x02) in big-endian uint32
check msg[3] == 2'u8
test "Wire value serialization":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkString, strVal: "hello")
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkString
check decoded.strVal == "hello"
test "Null value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkNull)
buf.serializeValue(val)
check buf.len == 1
check buf[0] == 0x00'u8
test "Int64 value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkInt64, int64Val: 123456789)
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkInt64
check decoded.int64Val == 123456789
test "Array value roundtrip":
var buf: seq[byte] = @[]
let val = WireValue(kind: fkArray, arrayVal: @[
WireValue(kind: fkString, strVal: "a"),
WireValue(kind: fkString, strVal: "b"),
])
buf.serializeValue(val)
var pos = 0
let decoded = buf.deserializeValue(pos)
check decoded.kind == fkArray
check decoded.arrayVal.len == 2
check decoded.arrayVal[0].strVal == "a"
suite "Client async":
test "Client nextId":
let client = newClient()
check not client.isConnected