Files
Baradb/clients/nim-allographer/documents/surrealdb/query_builder.md
T
dimgigov 6bfc5b3a3c
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
feat(clients): add nim-allographer client with BaraDB driver support
- Pure Nim wire protocol client (async + sync, no C FFI)
- Query Builder: fluent API, SQL generator, execution, transactions
- Schema Builder: create/alter/drop tables, column operations
- Connection pool with aging and timeout handling
- ORM integration via compile-time DB_BARADB switch
- Tests: test_open, test_query
- Documentation: README.md, PLAN_BARADB.md
2026-05-21 15:49:11 +03:00

12 KiB

Example: Query Builder for SurrealDB

Warning

SurrealDB support is planned for v3. The current implementation is for reference only and may not work as expected in v2.

back

index


About SurrealDB

SurrealDB official docs
SurrealDB Github

SurrealDB is a next-generation database built on Rust that can handle all type of data structures-relational, document, and graph-and can run in-memory, on a single node, or in a distributed environment.
It's response is JSON and allographer return as JsonNode.

Create Connection

to index

import allographer/connection

let maxConnections = 95
let timeout = 30
let surreal = dbOpen(SurrealDb, "test", "test", "user", "pass", "http://surreal", 8000, maxConnections, timeout, true, true).await()

SurrealId type

The SurrealId type is used to handle SurrealDB Record IDs. It has the table name and id data.
insertId returns SurrealId response and can be used as an argument to the where and find clauses.

Nim API document
SurrealDB Official document

let aliceId = surreal.table("user").insertId(%*{"name": "alice"}).await
let aliceOpt = surreal.table("user").where("name", "=", "alice").first().await
let alice = aliceOpt.get()
check aliceId.rawId() == alice["id"].getStr()
check aliceId.table == alice["id"].getStr().split(":")[0]
check $aliceId == alice["id"].getStr().split(":")[1]

let alice2 = SurrealId.new(aliceId.rawId())
check alice2.rawId() == alice["id"].getStr()
check alice2.table == alice["id"].getStr().split(":")[0]
check $alice2 == alice["id"].getStr().split(":")[1]

let alice3 = SurrealId.new(aliceId.table, $aliceId)
check alice3.rawId() == alice["id"].getStr()
check alice3.table == alice["id"].getStr().split(":")[0]
check $alice3 == alice["id"].getStr().split(":")[1]

SELECT

to index

https://surrealdb.com/docs/surrealql/statements/select

When it returns following table

INSERT INTO `type` [
  {"bool":true,"string":"alice","int":1,"float":3.14,"datetime":"2023-06-05T11:58:42+00:00"},
  {"bool":false,"string":"bob","int":2,"float":1.11,"datetime":"2023-06-06T11:58:42+00:00"}
]
bool string int float datetime
true alice 1 3.14 2023-06-05T11:58:42+00:00
false bob 2 1.11 2023-06-06T11:58:42+00:00

get

Retrieving all row from a table

import allographer/query_builder

echo surreal.table("user").get().await
DEBUG SELECT * FROM `type`

@[
  {
    "bool":true,
    "datetime":"2023-06-05T12:05:07Z",
    "float":3.14,
    "id":"type:9nxye3dons0juyelv5if",
    "int":1,
    "string":"alice"
    },
  {
    "bool":false,
    "datetime":"2023-06-06T12:05:07Z"
    ,"float":1.11,
    "id":"type:tw9iqdycdz9h1egtjkwb",
    "int":2,
    "string":"bob"
  }
]

first

Retrieving a single row from a table. This returns Option[JsonNode]

let res = surreal.table("type").first().await
if res.isSome():
  echo firstRes.get()
DEBUG SELECT * FROM `type` LIMIT 1

{
  "bool":true,
  "datetime":"2023-06-05T12:08:47Z",
  "float":3.14,
  "id":"type:64t0w6gpnye7tdf083ch",
  "int":1,
  "string":"alice"
}

find

Retrieve a single row by id. This returns Option[JsonNode]
Id should be SurrealId type.
https://itsumura-h.github.io/nim-allographer/query_builder/surreal/surreal_types.html#SurrealId

let id = SurrealId.new("type:64t0w6gpnye7tdf083ch")
let res = surreal.table("type").find(id).await
if res.isSome():
  echo res.get()
DEBUG SELECT * FROM `type` WHERE `id` = ? LIMIT 1 ["type:64t0w6gpnye7tdf083ch"]

{
  "bool":true,
  "datetime":"2023-06-05T12:08:47Z",
  "float":3.14,
  "id":"type:64t0w6gpnye7tdf083ch",
  "int":1,
  "string":"alice"
}

columns

Retrieve columns from table.

let columns = surreal.table("users").columns().await
columns == @["email", "name", "id"]

where

user

id name email
user:2jrkvgwpdr02p71sfu1f alice alice@example.com
let res = surreal.table("user").where("name", "=", "alice").first().await
if res.isSome():
  echo res.get()
{
  "email": "alice@example.com",
  "id": "user:iss5w0fp4x3o08t2br3s",
  "name": "alice"
}

fetch

Fetch and replace records with the remote record data.
It is used for retrieve relational tables.

auth

id name
auth:pl93k823yinrm8hzip22 admin
auth:e3is4h0txnn6cpmcuoca editor

user

id name email auth
user:2jrkvgwpdr02p71sfu1f alice alice@example.com auth:pl93k823yinrm8hzip22
let alice = surreal.table("user").where("auth.name", "=", "admin").fetch("auth").first().await
if alice.isSome():
  echo alice.get()
{
  "auth": {
    "id": "auth:ayp1w74u5oo8m4w2neyi",
    "name": "admin"
  },
  "email": "alice@example.com",
  "id": "user:5d7pgwag7i7uymigdako",
  "name": "alice"
}

INSERT

to index

https://surrealdb.com/docs/surrealql/statements/insert

insert single row

surreal.table("type").insert(%*{
  "bool":true,
  "string": "alice",
  "int": 1,
  "float": 3.14,
  "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
})
.await

insert rows

surreal.table("type").insert(%*[
  {
    "bool":true,
    "string": "alice",
    "int": 1,
    "float": 3.14,
    "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
  },
  {
    "bool":false,
    "string": "bob",
    "int": 2,
    "float": 1.11,
    "datetime": (now() + initDuration(days=1)).format("yyyy-MM-dd'T'HH:mm:sszzz")
  }
])
.await

insertId

let id:SurrealId = surreal.table("type").insertId(%*{
  "bool":true,
  "string": "alice",
  "int": 1,
  "float": 3.14,
  "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
})
.await

echo id.rawId()
type:9nxye3dons0juyelv5if

UPDATE

to index

https://surrealdb.com/docs/surrealql/statements/update

let id = surreal.table("type").insertId(%*{
  "bool":true,
  "string": "alice",
  "int": 1,
  "float": 3.14,
  "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
})
.await

surreal.table("type").where("id", "=", id).update(%*{"string": "bob"}).await
let res = surreal.table("type").find(id).await
if res.isSome():
  echo res.get()
{
  "bool":true,
  "datetime":"2023-06-06T02:34:25Z",
  "float":3.14,
  "id":"type:hp0aqct78btlcyr1ho06",
  "int":1,
  "string":"bob"
}

DELETE

to index

https://surrealdb.com/docs/surrealql/statements/delete

delete all

let id = surreal.table("type").insertId(%*{
  "bool":true,
  "string": "alice",
  "int": 1,
  "float": 3.14,
  "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
})
.await

surreal.table("type").delete().await
echo surreal.table("type").get().await
@[]

delete row

surreal.table("type").insert(%*[
  {
    "bool":true,
    "string": "alice",
    "int": 1,
    "float": 3.14,
    "datetime": now().format("yyyy-MM-dd'T'HH:mm:sszzz")
  },
  {
    "bool":false,
    "string": "bob",
    "int": 2,
    "float": 1.11,
    "datetime": (now() + initDuration(days=1)).format("yyyy-MM-dd'T'HH:mm:sszzz")
  }
])
.await

let row = surreal.table("type").where("string", "=", "alice").first().await.get()
let rowId = SurrealId.new(row["id"].getStr())

surreal.table("type").where("id", "=", rowId).delete().await
echo surreal.table("type").get().await
@[
  {
    "bool":false,
    "datetime":"2023-06-07T03:39:14Z",
    "float":"1.11",
    "id":"type:y93d6ig6iyrvcez0lc9k",
    "int":2,
    "string":"bob"
  }
]

Raw Query

to index

raw() returns RawQuerySurrealDb type.
You can use get(), first(), exec() and info() for raw query.
get() returns all rows of result.
first() returns first row of result.
exec() executes query and not return any variables.
info() executes query and returns all data of response.

let define = """
REMOVE TABLE type;
DEFINE TABLE type SCHEMAFULL;
DEFINE FIELD index ON TABLE type TYPE int;
DEFINE INDEX types_index ON TABLE type COLUMNS index UNIQUE;
DEFINE FIELD bool ON TABLE type TYPE bool;
DEFINE FIELD datetime ON TABLE type TYPE datetime;
DEFINE FIELD float ON TABLE type TYPE float;
DEFINE FIELD int ON TABLE type TYPE int;
DEFINE FIELD string ON TABLE type TYPE string;
"""
surreal.raw(define).exec().await()

echo surreal.raw("INFO FOR TABLE type").info().await

>> [
  {
    "time":"32.762515ms",
    "status":"OK",
    "result":{
      "ev":{},
      "fd":{
        "bool":"DEFINE FIELD bool ON type TYPE bool",
        "datetime":"DEFINE FIELD datetime ON type TYPE datetime",
        "float":"DEFINE FIELD float ON type TYPE float",
        "index":"DEFINE FIELD index ON type TYPE int",
        "int":"DEFINE FIELD int ON type TYPE int",
        "string":"DEFINE FIELD string ON type TYPE string"
      },
      "ft":{},
      "ix":{
        "types_index":"DEFINE INDEX types_index ON type FIELDS index UNIQUE"
      }
    }
  }
]

var rows = surreal.raw("SELECT * FROM type").get().await
let max = rows.len + 1

surreal.raw(
  """
    CREATE type CONTENT {
      index: ?,
      bool: true,
      datetime: ?,
      float: 1.11,
      int: 1,
      string: "aaa"
    }
  """,
  $max, now().format("yyyy-MM-dd'T'HH:mm:sszzz")
)
.exec()
.await

rows = surreal.raw("SELECT * FROM type").get().await
echo rows

>> @[
  {
    "bool":true,
    "datetime":"2023-06-06T04:01:32Z",
    "float":1.11,
    "id":"type:f1qxioacts8cydbmchpy",
    "index":1,
    "int":1,
    "string":"aaa"
  }
]

Prepared Statement

to index

SurrealDB の prepared statement は documents/surrealdb/prepared_statement.md にまとめています。prepare(), get(), first(), exec(), close(), flushStmt(stmt), clearStmtCache(), withConn() が利用できます。

let stmt = surreal.prepare("""SELECT * FROM "type" WHERE "id" = ?""")
let row = await stmt.first(@["type:9nxye3dons0juyelv5if"])
await stmt.close()

Aggregates

to index

count

surreal.table("user").insert(%*[
  {"name": "alice", "email": "alice@example.com"},
  {"name": "bob", "email": "bob@example.com"},
  {"name": "charlie", "email": "charlie@example.com"},
])
.await

let count = surreal.table("user").count().await
echo count
>> 3

max

surreal.table("user").insert(%*[
  {"name": "alice", "email": "alice@example.com", "index": 1},
  {"name": "bob", "email": "bob@example.com", "index": 2},
  {"name": "charlie", "email": "charlie@example.com", "index": 3},
])
.await

let max = surreal.table("user").max("index").await
echo max
>> 3

min

surreal.table("user").insert(%*[
  {"name": "alice", "email": "alice@example.com", "index": 1},
  {"name": "bob", "email": "bob@example.com", "index": 2},
  {"name": "charlie", "email": "charlie@example.com", "index": 3},
])
.await

let min = surreal.table("user").min("index").await
echo min
>> 1