feat(clients): add nim-allographer client with BaraDB driver support
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
- 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
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
Example: Prepared Statement for SurrealDB
|
||||
===
|
||||
> [!WARNING]
|
||||
> SurrealDB の prepared statement は server-side prepare ではなく、client-side template reuse と `/sql` の multi-statement 実行で再現しています。
|
||||
|
||||
[back](../../README.md)
|
||||
|
||||
## index
|
||||
<!--ts-->
|
||||
* [Example: Prepared Statement for SurrealDB](#example-prepared-statement-for-surrealdb)
|
||||
* [index](#index)
|
||||
* [About](#about)
|
||||
* [Create Connection](#create-connection)
|
||||
* [prepare](#prepare)
|
||||
* [withConn](#withconn)
|
||||
* [Cache Control](#cache-control)
|
||||
<!--te-->
|
||||
|
||||
---
|
||||
|
||||
## About
|
||||
[SurrealDB official docs](https://surrealdb.com/docs)
|
||||
|
||||
Prepared statement の公開 API は他 driver に寄せていますが、SurrealDB では内部的に次の形へ展開します。
|
||||
|
||||
```sql
|
||||
LET $a = "user:alice";
|
||||
SELECT * FROM "user" WHERE "id" = $a;
|
||||
```
|
||||
|
||||
`?` は `$a`, `$b`, ... に変換され、引数は `LET` で前置されます。これにより、1 リクエストで安全に再利用できるテンプレートとして扱えます。
|
||||
|
||||
## Create Connection
|
||||
|
||||
```nim
|
||||
import std/asyncdispatch
|
||||
import allographer/connection
|
||||
|
||||
let surreal = dbOpen(SurrealDB, "test", "test", "user", "pass", "http://surreal", 8000, 5, 30, false, false).await
|
||||
```
|
||||
|
||||
## prepare
|
||||
|
||||
```nim
|
||||
import std/asyncdispatch
|
||||
import std/json
|
||||
import allographer/query_builder
|
||||
|
||||
let stmt = surreal.prepare("""SELECT * FROM "user" WHERE "id" = ?""")
|
||||
let rows = await stmt.get(@["user:alice"])
|
||||
let row = await stmt.first(@["user:alice"])
|
||||
await stmt.exec(@["user:alice"])
|
||||
await stmt.close()
|
||||
```
|
||||
|
||||
`close()` は logical close です。SurrealDB 側に物理 prepared handle はないため、キャッシュの整理は `flushStmt()` / `clearStmtCache()` で行います。
|
||||
|
||||
## withConn
|
||||
|
||||
```nim
|
||||
await surreal.withConn(
|
||||
proc(ctx: SurrealPreparedContext): Future[void] {.async.} =
|
||||
discard await stmt.first(ctx, @["user:alice"])
|
||||
await stmt.exec(ctx, @["user:alice"])
|
||||
)
|
||||
```
|
||||
|
||||
`withConn()` は同じ connection index を使い回したいときの API です。将来の session 前提最適化や transaction helper とも相性がよい形にしてあります。
|
||||
|
||||
## Cache Control
|
||||
|
||||
```nim
|
||||
await surreal.flushStmt(stmt)
|
||||
await surreal.clearStmtCache()
|
||||
```
|
||||
|
||||
`flushStmt(stmt)` はその prepared statement を閉じて、対応するテンプレートをキャッシュから外します。`clearStmtCache()` はキャッシュ全体を空にします。
|
||||
@@ -0,0 +1,547 @@
|
||||
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](../../README.md)
|
||||
|
||||
## index
|
||||
<!--ts-->
|
||||
* [Example: Query Builder for SurrealDB](#example-query-builder-for-surrealdb)
|
||||
* [index](#index)
|
||||
* [About SurrealDB](#about-surrealdb)
|
||||
* [Create Connection](#create-connection)
|
||||
* [SurrealId type](#surrealid-type)
|
||||
* [SELECT](#select)
|
||||
* [get](#get)
|
||||
* [first](#first)
|
||||
* [find](#find)
|
||||
* [columns](#columns)
|
||||
* [where](#where)
|
||||
* [fetch](#fetch)
|
||||
* [INSERT](#insert)
|
||||
* [insert single row](#insert-single-row)
|
||||
* [insert rows](#insert-rows)
|
||||
* [insertId](#insertid)
|
||||
* [UPDATE](#update)
|
||||
* [DELETE](#delete)
|
||||
* [delete all](#delete-all)
|
||||
* [delete row](#delete-row)
|
||||
* [Raw Query](#raw-query)
|
||||
* [Prepared Statement](#prepared-statement)
|
||||
* [Aggregates](#aggregates)
|
||||
* [count](#count)
|
||||
* [max](#max)
|
||||
* [min](#min)
|
||||
|
||||
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
|
||||
<!-- Added by: root, at: Mon Jul 17 07:46:29 UTC 2023 -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
---
|
||||
|
||||
## About SurrealDB
|
||||
[SurrealDB official docs](https://surrealdb.com/docs)
|
||||
[SurrealDB Github](https://github.com/surrealdb/surrealdb)
|
||||
|
||||
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](#index)
|
||||
|
||||
```nim
|
||||
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](https://itsumura-h.github.io/nim-allographer/query_builder/surreal/surreal_types.html#SurrealId)
|
||||
[SurrealDB Official document](https://surrealdb.com/docs/surrealql/datamodel/ids)
|
||||
|
||||
```nim
|
||||
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](#index)
|
||||
|
||||
https://surrealdb.com/docs/surrealql/statements/select
|
||||
|
||||
When it returns following table
|
||||
|
||||
```sql
|
||||
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
|
||||
|
||||
```nim
|
||||
import allographer/query_builder
|
||||
|
||||
echo surreal.table("user").get().await
|
||||
```
|
||||
|
||||
```nim
|
||||
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]`
|
||||
|
||||
```nim
|
||||
let res = surreal.table("type").first().await
|
||||
if res.isSome():
|
||||
echo firstRes.get()
|
||||
```
|
||||
|
||||
```nim
|
||||
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
|
||||
|
||||
```nim
|
||||
let id = SurrealId.new("type:64t0w6gpnye7tdf083ch")
|
||||
let res = surreal.table("type").find(id).await
|
||||
if res.isSome():
|
||||
echo res.get()
|
||||
```
|
||||
|
||||
```nim
|
||||
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.
|
||||
```nim
|
||||
let columns = surreal.table("users").columns().await
|
||||
columns == @["email", "name", "id"]
|
||||
```
|
||||
|
||||
|
||||
### where
|
||||
user
|
||||
|id|name|email|
|
||||
|---|---|---|
|
||||
|user:2jrkvgwpdr02p71sfu1f|alice|alice@example.com|
|
||||
|
||||
```nim
|
||||
let res = surreal.table("user").where("name", "=", "alice").first().await
|
||||
if res.isSome():
|
||||
echo res.get()
|
||||
```
|
||||
|
||||
```nim
|
||||
{
|
||||
"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|
|
||||
|
||||
```nim
|
||||
let alice = surreal.table("user").where("auth.name", "=", "admin").fetch("auth").first().await
|
||||
if alice.isSome():
|
||||
echo alice.get()
|
||||
```
|
||||
|
||||
```nim
|
||||
{
|
||||
"auth": {
|
||||
"id": "auth:ayp1w74u5oo8m4w2neyi",
|
||||
"name": "admin"
|
||||
},
|
||||
"email": "alice@example.com",
|
||||
"id": "user:5d7pgwag7i7uymigdako",
|
||||
"name": "alice"
|
||||
}
|
||||
```
|
||||
|
||||
## INSERT
|
||||
[to index](#index)
|
||||
|
||||
https://surrealdb.com/docs/surrealql/statements/insert
|
||||
|
||||
### insert single row
|
||||
```nim
|
||||
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
|
||||
```nim
|
||||
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
|
||||
```nim
|
||||
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()
|
||||
```
|
||||
|
||||
```nim
|
||||
type:9nxye3dons0juyelv5if
|
||||
```
|
||||
|
||||
## UPDATE
|
||||
[to index](#index)
|
||||
|
||||
https://surrealdb.com/docs/surrealql/statements/update
|
||||
|
||||
```nim
|
||||
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()
|
||||
```
|
||||
|
||||
```nim
|
||||
{
|
||||
"bool":true,
|
||||
"datetime":"2023-06-06T02:34:25Z",
|
||||
"float":3.14,
|
||||
"id":"type:hp0aqct78btlcyr1ho06",
|
||||
"int":1,
|
||||
"string":"bob"
|
||||
}
|
||||
```
|
||||
|
||||
## DELETE
|
||||
[to index](#index)
|
||||
|
||||
https://surrealdb.com/docs/surrealql/statements/delete
|
||||
|
||||
## delete all
|
||||
```nim
|
||||
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
|
||||
```
|
||||
|
||||
```nim
|
||||
@[]
|
||||
```
|
||||
|
||||
## delete row
|
||||
```nim
|
||||
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
|
||||
```
|
||||
|
||||
```nim
|
||||
@[
|
||||
{
|
||||
"bool":false,
|
||||
"datetime":"2023-06-07T03:39:14Z",
|
||||
"float":"1.11",
|
||||
"id":"type:y93d6ig6iyrvcez0lc9k",
|
||||
"int":2,
|
||||
"string":"bob"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Raw Query
|
||||
[to index](#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.
|
||||
|
||||
```nim
|
||||
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](#INDEX)
|
||||
|
||||
SurrealDB の prepared statement は [`documents/surrealdb/prepared_statement.md`](./prepared_statement.md) にまとめています。`prepare()`, `get()`, `first()`, `exec()`, `close()`, `flushStmt(stmt)`, `clearStmtCache()`, `withConn()` が利用できます。
|
||||
|
||||
```nim
|
||||
let stmt = surreal.prepare("""SELECT * FROM "type" WHERE "id" = ?""")
|
||||
let row = await stmt.first(@["type:9nxye3dons0juyelv5if"])
|
||||
await stmt.close()
|
||||
```
|
||||
|
||||
## Aggregates
|
||||
[to index](#INDEX)
|
||||
|
||||
### count
|
||||
```nim
|
||||
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
|
||||
```
|
||||
|
||||
```sh
|
||||
>> 3
|
||||
```
|
||||
|
||||
### max
|
||||
```nim
|
||||
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
|
||||
```nim
|
||||
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
|
||||
```
|
||||
@@ -0,0 +1,147 @@
|
||||
Example: Schema 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](../../README.md)
|
||||
|
||||
## index
|
||||
<!--ts-->
|
||||
* [Example: Schema Builder for SurrealDB](#example-schema-builder-for-surrealdb)
|
||||
* [index](#index)
|
||||
* [About SurrealDB](#about-surrealdb)
|
||||
* [Create table](#create-table)
|
||||
* [Alter Table](#alter-table)
|
||||
* [add column](#add-column)
|
||||
* [drop column](#drop-column)
|
||||
* [drop table](#drop-table)
|
||||
|
||||
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
|
||||
<!-- Added by: root, at: Mon Jul 17 07:46:33 UTC 2023 -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
---
|
||||
|
||||
## About SurrealDB
|
||||
[SurrealDB official docs](https://surrealdb.com/docs)
|
||||
[SurrealDB Github](https://github.com/surrealdb/surrealdb)
|
||||
|
||||
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 table
|
||||
You can create `SCHEMAFULL` table for SurrealDB.
|
||||
|
||||
[DEFINE TABLE](https://surrealdb.com/docs/surrealql/statements/define/table)
|
||||
[DEFINE FIELD](https://surrealdb.com/docs/surrealql/statements/define/field)
|
||||
|
||||
```nim
|
||||
import std/asyncdispatch
|
||||
import allographer/connection
|
||||
import allographer/schema_builder
|
||||
|
||||
let surreal = dbOpen(SurrealDb, "test", "test", "user", "pass", "http://surreal", 8000, 5, 30, false, false).await
|
||||
|
||||
surreal.create(
|
||||
table("auth", [
|
||||
Column.increments("index"),
|
||||
Column.uuid("uuid"),
|
||||
Column.string("name"),
|
||||
Column.timestamps()
|
||||
]),
|
||||
table("user", [
|
||||
Column.increments("index"),
|
||||
Column.string("name"),
|
||||
Column.foreign("auth").reference("id").onTable("auth").onDelete(SET_NULL)
|
||||
])
|
||||
)
|
||||
```
|
||||
|
||||
These query run.
|
||||
|
||||
```sql
|
||||
DEFINE TABLE `auth` SCHEMAFULL;
|
||||
INSERT INTO `_autoincrement_sequences` {table: "auth", column: "index", max_index: 0};
|
||||
DEFINE EVENT `autoincrement_auth_index` ON TABLE `auth` WHEN $event = "CREATE" THEN {
|
||||
LET $val = (SELECT `max_index` FROM `_autoincrement_sequences` WHERE `table` = "auth" AND `column` = "index" LIMIT 1)[0].max_index + 1;
|
||||
UPDATE `auth` MERGE {index: $val} WHERE id = $after.id;
|
||||
UPDATE `_autoincrement_sequences` MERGE {max_index: $val} WHERE `table` = "auth" AND `column` = "index";
|
||||
};
|
||||
DEFINE FIELD `index` ON TABLE `auth` TYPE int;
|
||||
DEFINE INDEX `auth_index_unique` ON TABLE `auth` COLUMNS `index` UNIQUE;
|
||||
DEFINE FIELD `uuid` ON TABLE `auth` TYPE string VALUE $value OR rand::uuid() ASSERT $value != NONE;
|
||||
DEFINE INDEX `auth_uuid_unique` ON TABLE `auth` COLUMNS `uuid` UNIQUE;
|
||||
DEFINE FIELD `name` ON TABLE `auth` TYPE string ASSERT string::len($value) < 255 AND $value != NONE VALUE $value OR '';
|
||||
DEFINE FIELD `created_at` ON TABLE `auth` TYPE datetime VALUE $value OR time::now();
|
||||
DEFINE INDEX `auth_created_at_index` ON TABLE `auth` COLUMNS `created_at`;
|
||||
DEFINE FIELD `updated_at` ON TABLE `auth` TYPE datetime VALUE time::now();
|
||||
DEFINE INDEX `auth_updated_at_index` ON TABLE `auth` COLUMNS `updated_at`;
|
||||
|
||||
DEFINE TABLE `user` SCHEMAFULL;
|
||||
INSERT INTO `_autoincrement_sequences` {table: "user", column: "index", max_index: 0};
|
||||
DEFINE EVENT `autoincrement_user_index` ON TABLE `user` WHEN $event = "CREATE" THEN {
|
||||
LET $val = (SELECT `max_index` FROM `_autoincrement_sequences` WHERE `table` = "user" AND `column` = "index" LIMIT 1)[0].max_index + 1;
|
||||
UPDATE `user` MERGE {index: $val} WHERE id = $after.id;
|
||||
UPDATE `_autoincrement_sequences` MERGE {max_index: $val} WHERE `table` = "user" AND `column` = "index";
|
||||
};
|
||||
DEFINE FIELD `index` ON TABLE `user` TYPE int;
|
||||
DEFINE INDEX `user_index_unique` ON TABLE `user` COLUMNS `index` UNIQUE;
|
||||
DEFINE FIELD `name` ON TABLE `user` TYPE string ASSERT string::len($value) < 255 AND $value != NONE VALUE $value OR '';
|
||||
DEFINE FIELD `auth` ON TABLE `user` TYPE record (`auth`) ASSERT $value != NONE;
|
||||
```
|
||||
|
||||
|
||||
## Alter Table
|
||||
### add column
|
||||
```nim
|
||||
surreal.alter(
|
||||
table("auth", [
|
||||
Column.increments("index").add(),
|
||||
Column.string("name").add(),
|
||||
]),
|
||||
table("user", [
|
||||
Column.string("email").unique().default("").add(),
|
||||
Column.foreign("auth").reference("id").onTable("auth").onDelete(SET_NULL).add()
|
||||
])
|
||||
)
|
||||
```
|
||||
|
||||
```sql
|
||||
INSERT INTO `_autoincrement_sequences` {table: "auth", column: "index", max_index: 0};
|
||||
DEFINE EVENT `autoincrement_auth_index` ON TABLE `auth` WHEN $event = "CREATE" THEN {
|
||||
LET $val = (SELECT `max_index` FROM `_autoincrement_sequences` WHERE `table` = "auth" AND `column` = "index" LIMIT 1)[0].max_index + 1;
|
||||
UPDATE `auth` MERGE {index: $val} WHERE id = $after.id;
|
||||
UPDATE `_autoincrement_sequences` MERGE {max_index: $val} WHERE `table` = "auth" AND `column` = "index";
|
||||
}
|
||||
DEFINE FIELD `index` ON TABLE `auth` TYPE int
|
||||
DEFINE INDEX `auth_index_unique` ON TABLE `auth` COLUMNS `index` UNIQUE
|
||||
DEFINE FIELD `name` ON TABLE `auth` TYPE string ASSERT string::len($value) < 255 AND $value != NONE VALUE $value OR ''
|
||||
DEFINE FIELD `email` ON TABLE `user` TYPE string ASSERT string::len($value) < 255 AND $value != NONE VALUE $value OR ''
|
||||
DEFINE INDEX `user_email_unique` ON TABLE `user` COLUMNS `email` UNIQUE
|
||||
DEFINE FIELD `auth` ON TABLE `user` TYPE record (`auth`) ASSERT $value != NONE
|
||||
```
|
||||
|
||||
### drop column
|
||||
```nim
|
||||
surreal.alter(
|
||||
table("user", [
|
||||
Column.dropColumn("name")
|
||||
])
|
||||
)
|
||||
```
|
||||
|
||||
```sql
|
||||
REMOVE FIELD `name` ON TABLE `user`
|
||||
```
|
||||
|
||||
### drop table
|
||||
```nim
|
||||
surreal.drop(
|
||||
table("user")
|
||||
)
|
||||
```
|
||||
|
||||
```sql
|
||||
REMOVE TABLE `user`
|
||||
```
|
||||
Reference in New Issue
Block a user