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,10 @@
|
||||
import std/os
|
||||
import std/strutils
|
||||
import ../../src/allographer/connection
|
||||
|
||||
let
|
||||
mysqlUrl = getEnv("MY_URL")
|
||||
maxConnections = getEnv("DB_MAX_CONNECTION").parseInt
|
||||
timeout = getEnv("DB_TIMEOUT").parseInt
|
||||
|
||||
let mysql* = dbOpen(MySQL, databaseUrl = asDatabaseUrl(mysqlUrl), maxConnections, timeout, shouldDisplayLog=true)
|
||||
@@ -0,0 +1,108 @@
|
||||
discard """
|
||||
cmd: "nim c -d:reset $file"
|
||||
"""
|
||||
|
||||
# nim c -d:reset -r tests/mysql/test_create_schema.nim
|
||||
|
||||
import std/unittest
|
||||
import std/asyncdispatch
|
||||
import std/os
|
||||
import std/strutils
|
||||
import std/json
|
||||
import ../../src/allographer/schema_builder
|
||||
import ./connections
|
||||
import ../clear_tables
|
||||
|
||||
|
||||
let rdb = mysql
|
||||
let schemaFilePath = getCurrentDir() / "schema.nim"
|
||||
clearTables(rdb).waitFor()
|
||||
|
||||
suite "Schema output after migration":
|
||||
setup:
|
||||
# schema.nim ファイルの削除
|
||||
if fileExists(schemaFilePath):
|
||||
removeFile(schemaFilePath)
|
||||
|
||||
rdb.create(
|
||||
table("int_relation", [
|
||||
Column.increments("id")
|
||||
]),
|
||||
table("str_relation", [
|
||||
Column.uuid("uuid")
|
||||
]),
|
||||
table("test_schema_output", [
|
||||
Column.increments("id"),
|
||||
Column.integer("integer"),
|
||||
Column.smallInteger("smallInteger"),
|
||||
Column.mediumInteger("mediumInteger"),
|
||||
Column.bigInteger("bigInteger"),
|
||||
Column.decimal("decimal", 10, 3),
|
||||
Column.double("double", 10, 3),
|
||||
Column.float("float"),
|
||||
Column.uuid("uuid"),
|
||||
Column.char("char", 255),
|
||||
Column.string("string"),
|
||||
Column.text("text"),
|
||||
Column.mediumText("mediumText"),
|
||||
Column.longText("longText"),
|
||||
Column.date("date"),
|
||||
Column.datetime("datetime"),
|
||||
Column.time("time"),
|
||||
Column.timestamp("timestamp"),
|
||||
Column.timestamps(),
|
||||
Column.softDelete(),
|
||||
Column.binary("binary"),
|
||||
Column.boolean("boolean"),
|
||||
Column.enumField("enumField", ["A", "B", "C"]),
|
||||
Column.json("json"),
|
||||
Column.foreign("int_relation_id").reference("id").onTable("int_relation").onDelete(SET_NULL),
|
||||
Column.strForeign("str_relation_id").reference("uuid").onTable("str_relation").onDelete(SET_NULL)
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
test "should generate schema.nim file":
|
||||
# スキーマ生成
|
||||
rdb.createSchema(schemaFilePath).waitFor()
|
||||
|
||||
# schema.nim ファイルの存在確認
|
||||
check fileExists(schemaFilePath)
|
||||
|
||||
# ファイル内容の検証
|
||||
let schemaContent = readFile(schemaFilePath)
|
||||
echo "schemaContent: ", schemaContent
|
||||
check schemaContent.contains("type TestSchemaOutputTable* = object")
|
||||
check schemaContent.contains("## test_schema_output")
|
||||
check schemaContent.contains("integer*: int")
|
||||
check schemaContent.contains("smallInteger*: int")
|
||||
check schemaContent.contains("mediumInteger*: int")
|
||||
check schemaContent.contains("bigInteger*: int")
|
||||
check schemaContent.contains("decimal*: float")
|
||||
check schemaContent.contains("double*: float")
|
||||
check schemaContent.contains("float*: float")
|
||||
check schemaContent.contains("uuid*: string")
|
||||
check schemaContent.contains("char*: string")
|
||||
check schemaContent.contains("string*: string")
|
||||
check schemaContent.contains("text*: string")
|
||||
check schemaContent.contains("mediumText*: string")
|
||||
check schemaContent.contains("longText*: string")
|
||||
check schemaContent.contains("date*: string")
|
||||
check schemaContent.contains("datetime*: string")
|
||||
check schemaContent.contains("time*: string")
|
||||
check schemaContent.contains("timestamp*: string")
|
||||
check schemaContent.contains("created_at*: string")
|
||||
check schemaContent.contains("updated_at*: string")
|
||||
check schemaContent.contains("deleted_at*: string")
|
||||
check schemaContent.contains("binary*: string")
|
||||
check schemaContent.contains("boolean*: bool")
|
||||
check schemaContent.contains("enumField*: string")
|
||||
check schemaContent.contains("json*: JsonNode")
|
||||
check schemaContent.contains("int_relation_id*: int")
|
||||
check schemaContent.contains("str_relation_id*: string")
|
||||
|
||||
|
||||
clearTables(rdb).waitFor()
|
||||
# schema.nim ファイルの削除
|
||||
if fileExists(schemaFilePath):
|
||||
removeFile(schemaFilePath)
|
||||
@@ -0,0 +1,45 @@
|
||||
discard """
|
||||
cmd: "nim c $file"
|
||||
"""
|
||||
|
||||
# nim c -r tests/v2/mariadb/test_open.nim
|
||||
|
||||
import std/unittest
|
||||
import ../../src/allographer/connection
|
||||
import ../../src/allographer/query_builder
|
||||
|
||||
|
||||
suite("MySQL connection"):
|
||||
test("connection"):
|
||||
let database = "database"
|
||||
let user = "user"
|
||||
let password = "pass"
|
||||
let host = "mariadb"
|
||||
let port = 3306
|
||||
|
||||
let rdb = dbOpen(MySQL, database, user, password, host, port)
|
||||
check(rdb.isConnected())
|
||||
|
||||
|
||||
test("connection with URL"):
|
||||
let url = "mysql://user:pass@mariadb:3306/database"
|
||||
let rdb = dbOpen(MySQL, url)
|
||||
check(rdb.isConnected())
|
||||
|
||||
|
||||
test("connection with DatabaseUrl"):
|
||||
let url = asDatabaseUrl("mysql://user:pass@mariadb:3306/database")
|
||||
let rdb = dbOpen(MySQL, databaseUrl = url)
|
||||
check(rdb.isConnected())
|
||||
|
||||
|
||||
test("url is not start with mysql://"):
|
||||
let url = "aaa://user:pass@mariadb:3306/database"
|
||||
expect(ValueError):
|
||||
discard dbOpen(MySQL, url)
|
||||
|
||||
|
||||
test("cannot reach to database"):
|
||||
let url = "mysql://john:password@host:0001/database"
|
||||
expect(DbError):
|
||||
discard dbOpen(MySQL, url)
|
||||
@@ -0,0 +1,149 @@
|
||||
discard """
|
||||
cmd: "nim c -d:reset -d:ssl -r $file"
|
||||
"""
|
||||
|
||||
import std/unittest
|
||||
import std/asyncdispatch
|
||||
import std/json
|
||||
import std/options
|
||||
import std/strformat
|
||||
import ../../src/allographer/schema_builder
|
||||
import ../../src/allographer/query_builder
|
||||
import ./connections
|
||||
|
||||
|
||||
let rdb = mysql
|
||||
|
||||
|
||||
proc setup(rdb: MysqlConnections) =
|
||||
rdb.create([
|
||||
table("auth", [
|
||||
Column.increments("id"),
|
||||
Column.string("auth")
|
||||
]),
|
||||
table("user", [
|
||||
Column.increments("id"),
|
||||
Column.string("name").nullable(),
|
||||
Column.string("email").nullable(),
|
||||
Column.string("address").nullable(),
|
||||
Column.date("submit_on").nullable(),
|
||||
Column.datetime("submit_at").nullable(),
|
||||
Column.foreign("auth_id").reference("id").onTable("auth").onDelete(SET_NULL).nullable()
|
||||
])
|
||||
])
|
||||
|
||||
seeder(rdb, "auth"):
|
||||
rdb.table("auth").insert(@[
|
||||
%*{"auth": "admin"},
|
||||
%*{"auth": "user"}
|
||||
]).waitFor
|
||||
|
||||
seeder(rdb, "user"):
|
||||
var users: seq[JsonNode]
|
||||
for i in 1..10:
|
||||
let authId = if i mod 2 == 0: 2 else: 1
|
||||
let month = if i > 9: $i else: &"0{i}"
|
||||
users.add(
|
||||
%*{
|
||||
"name": &"user{i}",
|
||||
"email": &"user{i}@example.com",
|
||||
"auth_id": authId,
|
||||
"submit_on": &"2020-{month}-01",
|
||||
"submit_at": &"2020-{month}-01 00:00:00",
|
||||
}
|
||||
)
|
||||
|
||||
rdb.table("user").insert(users).waitFor
|
||||
|
||||
|
||||
setup(rdb)
|
||||
|
||||
|
||||
suite($rdb & " prepared statement"):
|
||||
test("aged connection refresh"):
|
||||
rdb.pools.maxConnectionLifetime = 1
|
||||
rdb.pools.maxConnectionIdleTime = 1
|
||||
for conn in rdb.pools.conns.mitems:
|
||||
conn.createdAt = 0
|
||||
conn.lastUsedAt = 0
|
||||
|
||||
let sql = """SELECT `id`, `name`, `email`, `address` FROM `user` WHERE `id` = ?"""
|
||||
let stmt = rdb.prepare(sql)
|
||||
defer:
|
||||
waitFor stmt.close()
|
||||
|
||||
let rowOpt = stmt.first(@["1"]).waitFor
|
||||
check rowOpt.isSome
|
||||
|
||||
var refreshed = false
|
||||
for conn in rdb.pools.conns:
|
||||
if conn.createdAt > 0:
|
||||
refreshed = true
|
||||
break
|
||||
check refreshed
|
||||
|
||||
test("select"):
|
||||
let stmt = rdb.prepare("""SELECT `id`, `name`, `email`, `address` FROM `user` WHERE `id` = ?""")
|
||||
defer:
|
||||
waitFor stmt.close()
|
||||
|
||||
let args = newJArray()
|
||||
args.add(newJInt(1))
|
||||
|
||||
let rows = stmt.get(args).waitFor
|
||||
check rows.len == 1
|
||||
check rows[0] == %*{"id": 1, "name": "user1", "email": "user1@example.com", "address": newJNull()}
|
||||
let rowOpt = stmt.first(args).waitFor
|
||||
let row = options.get(rowOpt)
|
||||
check row["name"].getStr == "user1"
|
||||
check stmt.getPlain(args).waitFor[0][1] == "user1"
|
||||
check stmt.firstPlain(args).waitFor[1] == "user1"
|
||||
|
||||
|
||||
test("logical close and clear cache"):
|
||||
let sql = """SELECT `id`, `name`, `email`, `address` FROM `user` WHERE `id` = ?"""
|
||||
let stmt = rdb.prepare(sql)
|
||||
discard waitFor stmt.first(@["1"])
|
||||
waitFor stmt.close()
|
||||
|
||||
let stmt2 = rdb.prepare(sql)
|
||||
defer:
|
||||
waitFor stmt2.close()
|
||||
|
||||
let rowOpt = stmt2.first(@["1"]).waitFor
|
||||
check rowOpt.isSome
|
||||
|
||||
waitFor rdb.clearStmtCache()
|
||||
let stmt3 = rdb.prepare(sql)
|
||||
defer:
|
||||
waitFor stmt3.close()
|
||||
check stmt3.first(@["1"]).waitFor.isSome
|
||||
|
||||
|
||||
test("with prepared connection context"):
|
||||
let selectStmt = rdb.prepare("""SELECT `id`, `name` FROM `user` WHERE `id` = ?""")
|
||||
let updateStmt = rdb.prepare("""UPDATE `user` SET `address` = ? WHERE `id` = ?""")
|
||||
defer:
|
||||
waitFor selectStmt.close()
|
||||
waitFor updateStmt.close()
|
||||
|
||||
waitFor rdb.withConn(
|
||||
proc(ctx: MysqlPreparedContext): Future[void] {.async.} =
|
||||
discard await selectStmt.first(ctx, @["1"])
|
||||
await updateStmt.exec(ctx, @["ctx-address", "1"])
|
||||
)
|
||||
|
||||
let rowOpt = rdb.table("user").find(1).waitFor
|
||||
let row = options.get(rowOpt)
|
||||
check row["address"].getStr == "ctx-address"
|
||||
|
||||
|
||||
test("update null"):
|
||||
let stmt = rdb.prepare("""UPDATE `user` SET `address` = ? WHERE `id` = ?""")
|
||||
defer:
|
||||
waitFor stmt.close()
|
||||
|
||||
waitFor stmt.exec(@["NULL", "1"])
|
||||
let rowOpt = rdb.table("user").find(1).waitFor
|
||||
let row = options.get(rowOpt)
|
||||
check row["address"].kind == JNull
|
||||
@@ -0,0 +1,565 @@
|
||||
discard """
|
||||
cmd: "nim c -d:reset -d:ssl -r $file"
|
||||
"""
|
||||
|
||||
# nim c -d:reset -d:ssl -r tests/mysql/test_query.nim
|
||||
|
||||
import std/unittest
|
||||
import std/asyncdispatch
|
||||
import std/httpclient
|
||||
import std/json
|
||||
import std/options
|
||||
import std/streams
|
||||
import std/strformat
|
||||
import ../../src/allographer/schema_builder
|
||||
import ../../src/allographer/query_builder
|
||||
import ./connections
|
||||
import ../clear_tables
|
||||
|
||||
|
||||
let rdb = mysql
|
||||
|
||||
proc setup(rdb:MysqlConnections) =
|
||||
rdb.create([
|
||||
table("auth",[
|
||||
Column.increments("id"),
|
||||
Column.string("auth")
|
||||
]),
|
||||
table("user",[
|
||||
Column.increments("id"),
|
||||
Column.string("name").nullable(),
|
||||
Column.string("email").nullable(),
|
||||
Column.string("address").nullable(),
|
||||
Column.date("submit_on").nullable(),
|
||||
Column.datetime("submit_at").nullable(),
|
||||
Column.foreign("auth_id").reference("id").onTable("auth").onDelete(SET_NULL).nullable()
|
||||
])
|
||||
])
|
||||
|
||||
# seeder
|
||||
seeder(rdb, "auth"):
|
||||
rdb.table("auth").insert(@[
|
||||
%*{"auth": "admin"},
|
||||
%*{"auth": "user"}
|
||||
])
|
||||
.waitFor
|
||||
|
||||
seeder(rdb, "user"):
|
||||
var users: seq[JsonNode]
|
||||
for i in 1..10:
|
||||
let authId = if i mod 2 == 0: 2 else: 1
|
||||
let month = if i > 9: $i else: &"0{i}"
|
||||
users.add(
|
||||
%*{
|
||||
"name": &"user{i}",
|
||||
"email": &"user{i}@example.com",
|
||||
"auth_id": authId,
|
||||
"submit_on": &"2020-{month}-01",
|
||||
"submit_at": &"2020-{month}-01 00:00:00",
|
||||
}
|
||||
)
|
||||
|
||||
rdb.table("user").insert(users).waitFor
|
||||
|
||||
|
||||
setup(rdb)
|
||||
|
||||
suite($rdb & " get"):
|
||||
test("get"):
|
||||
let t = rdb.table("user").get().waitFor
|
||||
let expect = %*{"id":1,"name":"user1","email":"user1@example.com","address":newJNull(),"submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00","auth_id":1}
|
||||
echo t[0]
|
||||
echo expect
|
||||
check t[0] == expect
|
||||
|
||||
|
||||
test("getPlain"):
|
||||
let t = rdb.table("user").getPlain().waitFor
|
||||
check t[0] == @["1", "user1", "user1@example.com", "", "2020-01-01", "2020-01-01 00:00:00", "1"]
|
||||
|
||||
|
||||
test("first"):
|
||||
var t = rdb.table("user").where("name", "=", "user1").first().waitFor().get
|
||||
check t == %*{"id": 1, "name": "user1", "email": "user1@example.com", "address":newJNull(), "submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00", "auth_id": 1}
|
||||
|
||||
|
||||
test("firstPlain"):
|
||||
var t = rdb.table("user").firstPlain().waitFor
|
||||
check t == @["1", "user1", "user1@example.com", "", "2020-01-01", "2020-01-01 00:00:00", "1"]
|
||||
|
||||
|
||||
test("find"):
|
||||
var t = rdb.table("user").find(1).waitFor.get
|
||||
check t == %*{"id": 1, "name": "user1", "email": "user1@example.com", "address":newJNull(), "submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00", "auth_id": 1}
|
||||
|
||||
|
||||
test("findString"):
|
||||
var t = rdb.table("user").find("1").waitFor.get
|
||||
check t == %*{"id": 1, "name": "user1", "email": "user1@example.com", "address":newJNull(), "submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00", "auth_id": 1}
|
||||
|
||||
|
||||
test("findPlain"):
|
||||
var t = rdb.table("user").findPlain(1).waitFor
|
||||
check t == @["1", "user1", "user1@example.com", "", "2020-01-01", "2020-01-01 00:00:00", "1"]
|
||||
|
||||
|
||||
test("columns"):
|
||||
let columns = rdb.table("user").columns().waitFor
|
||||
check columns == @["id", "name", "email", "address", "submit_on", "submit_at", "auth_id"]
|
||||
|
||||
|
||||
test("select"):
|
||||
var t = rdb.select("name", "email").table("user").get().waitFor
|
||||
check t[0] == %*{"name": "user1", "email": "user1@example.com"}
|
||||
|
||||
|
||||
test("selectAs"):
|
||||
var t = rdb.select("name as user_name", "email").table("user").get().waitFor
|
||||
check t[0] == %*{"user_name": "user1", "email": "user1@example.com"}
|
||||
|
||||
|
||||
test("selectLike"):
|
||||
var t = rdb.select("email").table("user").where("email", "LIKE", "%10%").get().waitFor
|
||||
check t == @[%*{"email":"user10@example.com"}]
|
||||
t = rdb.select("email").table("user").where("email", "LIKE", "user10%").get().waitFor
|
||||
check t == @[%*{"email":"user10@example.com"}]
|
||||
t = rdb.select("email").table("user").where("email", "LIKE", "%10@example.com%").get().waitFor
|
||||
check t == @[%*{"email":"user10@example.com"}]
|
||||
|
||||
|
||||
test("select count"):
|
||||
var t = rdb.select("COUNT(id) as count").table("user").get().waitFor
|
||||
check t[0]["count"].getInt() == 10
|
||||
|
||||
|
||||
test("select max"):
|
||||
var t = rdb.select("MAX(id) as max").table("user").get().waitFor
|
||||
check t[0]["max"].getInt() == 10
|
||||
|
||||
|
||||
test("where"):
|
||||
var t = rdb.table("user").where("auth_id", "=", "1").get().waitFor
|
||||
check t == @[
|
||||
%*{"id":1,"name":"user1","email":"user1@example.com","address":newJNull(),"submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00","auth_id":1},
|
||||
%*{"id":3,"name":"user3","email":"user3@example.com","address":newJNull(),"submit_on":"2020-03-01","submit_at":"2020-03-01 00:00:00","auth_id":1},
|
||||
%*{"id":5,"name":"user5","email":"user5@example.com","address":newJNull(),"submit_on":"2020-05-01","submit_at":"2020-05-01 00:00:00","auth_id":1},
|
||||
%*{"id":7,"name":"user7","email":"user7@example.com","address":newJNull(),"submit_on":"2020-07-01","submit_at":"2020-07-01 00:00:00","auth_id":1},
|
||||
%*{"id":9,"name":"user9","email":"user9@example.com","address":newJNull(),"submit_on":"2020-09-01","submit_at":"2020-09-01 00:00:00","auth_id":1}
|
||||
]
|
||||
|
||||
|
||||
test("orWhere"):
|
||||
var t = rdb.table("user").where("auth_id", "=", "1").orWhere("name", "=", "user2").get().waitFor
|
||||
check t == @[
|
||||
%*{"id":1,"name":"user1","email":"user1@example.com","address":newJNull(),"submit_on":"2020-01-01","submit_at":"2020-01-01 00:00:00","auth_id":1},
|
||||
%*{"id":2,"name":"user2","email":"user2@example.com","address":newJNull(),"submit_on":"2020-02-01","submit_at":"2020-02-01 00:00:00","auth_id":2},
|
||||
%*{"id":3,"name":"user3","email":"user3@example.com","address":newJNull(),"submit_on":"2020-03-01","submit_at":"2020-03-01 00:00:00","auth_id":1},
|
||||
%*{"id":5,"name":"user5","email":"user5@example.com","address":newJNull(),"submit_on":"2020-05-01","submit_at":"2020-05-01 00:00:00","auth_id":1},
|
||||
%*{"id":7,"name":"user7","email":"user7@example.com","address":newJNull(),"submit_on":"2020-07-01","submit_at":"2020-07-01 00:00:00","auth_id":1},
|
||||
%*{"id":9,"name":"user9","email":"user9@example.com","address":newJNull(),"submit_on":"2020-09-01","submit_at":"2020-09-01 00:00:00","auth_id":1}
|
||||
]
|
||||
|
||||
|
||||
test("whereBetween"):
|
||||
var t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.where("auth_id", "=", 1)
|
||||
.whereBetween("id", [6, 9])
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["name"].getStr() == "user7"
|
||||
|
||||
|
||||
test("whereBetweenString"):
|
||||
var t = rdb
|
||||
.table("user")
|
||||
.whereBetween("submit_at", ["2020-01-01 00:00:00", "2020-01-31 00:00:00"])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr == "user1"
|
||||
|
||||
t = rdb
|
||||
.table("user")
|
||||
.whereBetween("submit_on", ["2020-01-01", "2020-01-31"])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr == "user1"
|
||||
|
||||
|
||||
test("whereNotBetween"):
|
||||
var t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.where("auth_id", "=", 1)
|
||||
.whereNotBetween("id", [1, 4])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr() == "user5"
|
||||
|
||||
|
||||
test("whereNotBetweenString"):
|
||||
var t = rdb
|
||||
.table("user")
|
||||
.whereNotBetween("submit_at", ["2020-2-1 00:00:00", "2020-12-31 00:00:00"])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr == "user1"
|
||||
|
||||
t = rdb
|
||||
.table("user")
|
||||
.whereNotBetween("submit_on", ["2020-2-1", "2020-12-31"])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr == "user1"
|
||||
|
||||
|
||||
test("whereIn"):
|
||||
var t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.whereBetween("id", [4, 10])
|
||||
.whereIn("id", @[5, 6, 7])
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["name"].getStr() == "user5"
|
||||
|
||||
t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.whereBetween("id", [4, 10])
|
||||
.whereIn("name", @["user5", "user6", "user7"])
|
||||
.get()
|
||||
.waitFor
|
||||
check t[0]["name"].getStr() == "user5"
|
||||
|
||||
|
||||
test("whereNotIn"):
|
||||
var t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.whereBetween("id", [4, 10])
|
||||
.whereNotIn("id", @[5, 6, 7])
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t == @[
|
||||
%*{"id":4, "name": "user4"},
|
||||
%*{"id":8, "name": "user8"},
|
||||
%*{"id":9, "name": "user9"},
|
||||
%*{"id":10, "name": "user10"},
|
||||
]
|
||||
|
||||
t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.whereBetween("id", [4, 10])
|
||||
.whereNotIn("name", @["user5", "user6", "user7"])
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t == @[
|
||||
%*{"id":4, "name": "user4"},
|
||||
%*{"id":8, "name": "user8"},
|
||||
%*{"id":9, "name": "user9"},
|
||||
%*{"id":10, "name": "user10"},
|
||||
]
|
||||
|
||||
|
||||
test("whereNull"):
|
||||
setUp(rdb)
|
||||
rdb.table("user").insert(%*{"email": "user11@example.com"}).waitFor
|
||||
var t = rdb
|
||||
.select("id", "name", "email")
|
||||
.table("user")
|
||||
.whereNull("name")
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["id"].getInt() == 11
|
||||
|
||||
|
||||
test("groupBy"):
|
||||
var t = rdb
|
||||
.table("user")
|
||||
.where("auth_id", "=", 1)
|
||||
.groupBy("auth_id")
|
||||
.max("id")
|
||||
.waitFor()
|
||||
.get()
|
||||
echo t
|
||||
check t == "9"
|
||||
|
||||
|
||||
test("having"):
|
||||
var t = rdb
|
||||
.select("id", "name")
|
||||
.table("user")
|
||||
.groupBy("auth_id")
|
||||
.groupBy("id")
|
||||
.having("auth_id", "=", 1)
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["id"].getInt() == 1
|
||||
|
||||
|
||||
test("orderBy"):
|
||||
var t = rdb.table("user")
|
||||
.where("auth_id", "is not", nil)
|
||||
.orderBy("auth_id", Asc)
|
||||
.orderBy("id", Desc)
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["id"].getInt() == 9
|
||||
|
||||
|
||||
test("join"):
|
||||
var t = rdb
|
||||
.select("user.id", "user.name")
|
||||
.table("user")
|
||||
.join("auth", "auth.id", "=", "user.auth_id")
|
||||
.where("auth.id", "=", "2")
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["name"].getStr() == "user2"
|
||||
|
||||
|
||||
test("leftJoin"):
|
||||
rdb.table("user").insert(%*{
|
||||
"name": "user11"
|
||||
})
|
||||
.waitFor
|
||||
var t = rdb
|
||||
.select("user.id", "user.name", "user.auth_id")
|
||||
.table("user")
|
||||
.leftJoin("auth", "auth.id", "=", "user.auth_id")
|
||||
.orderBy("user.id", Desc)
|
||||
.get()
|
||||
.waitFor
|
||||
echo t
|
||||
check t[0]["name"].getStr() == "user11"
|
||||
check t[0]["auth_id"] == newJNull()
|
||||
|
||||
|
||||
test("resultIsNull"):
|
||||
check rdb.table("user").find(50).waitFor().isSome == false
|
||||
check newSeq[JsonNode](0) == rdb.table("user").where("id", "=", 50).get().waitFor
|
||||
|
||||
|
||||
suite($rdb & " insert"):
|
||||
setup:
|
||||
setup(rdb)
|
||||
|
||||
test("insert row"):
|
||||
rdb.table("user").insert(%*{"name": "Alice"}).waitFor
|
||||
let t = rdb.table("user").orderBy("id", Desc).first().waitFor().get()
|
||||
check t["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
test("insert rows"):
|
||||
rdb.table("user").insert(@[
|
||||
%*{"name": "Alice"},
|
||||
%*{"name": "Bob"},
|
||||
]).waitFor
|
||||
let t = rdb.table("user").orderBy("id", Desc).limit(2).get().waitFor()
|
||||
check t[0]["name"].getStr() == "Bob"
|
||||
check t[1]["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
test("insertId row"):
|
||||
var id = rdb.table("user").insertId(%*{"name": "Alice"}).waitFor
|
||||
echo id
|
||||
let t = rdb.table("user").find(id).waitFor().get()
|
||||
check t["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
test("insertId rows"):
|
||||
let ids = rdb.table("user").insertId(@[
|
||||
%*{"name": "Alice"},
|
||||
%*{"name": "Bob"},
|
||||
]).waitFor
|
||||
|
||||
var t = rdb.table("user").find(ids[0]).waitFor().get()
|
||||
check t["name"].getStr == "Alice"
|
||||
|
||||
t = rdb.table("user").find(ids[1]).waitFor().get()
|
||||
check t["name"].getStr == "Bob"
|
||||
|
||||
|
||||
test("insertNil"):
|
||||
var id = rdb.table("user").insertId(%*{
|
||||
"name": "Alice",
|
||||
"email": nil,
|
||||
"address": ""
|
||||
})
|
||||
.waitFor
|
||||
var res = rdb.table("user").find(id).waitFor
|
||||
echo res.get
|
||||
check res.get["email"] == newJNull()
|
||||
|
||||
res = rdb.table("user").where("email", "is", nil).first().waitFor
|
||||
echo res.get
|
||||
check res.get["email"] == newJNull()
|
||||
|
||||
|
||||
|
||||
test("insert [T]"):
|
||||
type User = object
|
||||
name:string
|
||||
|
||||
let user = User(name: "Alice")
|
||||
rdb.table("user").insert(user).waitFor
|
||||
|
||||
let row = rdb.table("user").orderBy("id", Desc).first().waitFor().get()
|
||||
check row["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
test("insert seq[T]"):
|
||||
type User = object
|
||||
name:string
|
||||
|
||||
let users = @[
|
||||
User(name: "Alice"),
|
||||
User(name: "Bob"),
|
||||
]
|
||||
|
||||
rdb.table("user").insert(users).waitFor
|
||||
let t = rdb.table("user").orderBy("id", Desc).limit(2).get().waitFor()
|
||||
check t[0]["name"].getStr() == "Bob"
|
||||
check t[1]["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
suite($rdb & " update"):
|
||||
setup:
|
||||
setup(rdb)
|
||||
|
||||
test("update"):
|
||||
rdb.table("user").where("id", "=", 1).update(%*{"name": "Alice"}).waitFor
|
||||
var t = rdb.table("user").find(1).waitFor().get()
|
||||
check t["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
test("update [T]"):
|
||||
type User = object
|
||||
name:string
|
||||
|
||||
let user = User(name: "Alice")
|
||||
rdb.table("user").where("id", "=", 1).update(user).waitFor
|
||||
var t = rdb.table("user").find(1).waitFor().get()
|
||||
check t["name"].getStr() == "Alice"
|
||||
|
||||
|
||||
suite($rdb & " delete"):
|
||||
setup(rdb)
|
||||
|
||||
test("delete"):
|
||||
rdb.table("user").delete(1).waitFor
|
||||
check rdb.table("user").find(1).waitFor.isSome == false
|
||||
|
||||
|
||||
test("delete where"):
|
||||
rdb.table("user").where("name", "=", "user1").delete().waitFor
|
||||
check rdb.table("user").find(1).waitFor.isSome == false
|
||||
|
||||
|
||||
suite($rdb & " rawQuery"):
|
||||
setup(rdb)
|
||||
|
||||
test("get"):
|
||||
echo rdb.table("user").get().waitFor
|
||||
let sql = &"SELECT * FROM `user` WHERE `id` = ?"
|
||||
let res = rdb.raw(sql, %*[1]).get().waitFor
|
||||
echo res
|
||||
check res[0]["name"].getStr == "user1"
|
||||
|
||||
|
||||
test("getPlain"):
|
||||
let sql = &"SELECT * FROM `user` WHERE `id` = ?"
|
||||
let res = rdb.raw(sql, %*[1]).getPlain().waitFor
|
||||
echo res
|
||||
check res[0][1] == "user1"
|
||||
|
||||
|
||||
test("first"):
|
||||
echo rdb.table("user").get().waitFor
|
||||
let sql = &"SELECT * FROM `user` WHERE `id` = ?"
|
||||
let res = rdb.raw(sql, %*[1]).first().waitFor().get()
|
||||
echo res
|
||||
check res["name"].getStr == "user1"
|
||||
|
||||
|
||||
test("firstPlain"):
|
||||
echo rdb.table("user").get().waitFor
|
||||
let sql = &"SELECT name FROM `user` WHERE `id` = ?"
|
||||
let res = rdb.raw(sql, %*[1]).firstPlain().waitFor()
|
||||
echo res
|
||||
check res[0] == "user1"
|
||||
|
||||
|
||||
test("exec"):
|
||||
var sql = "UPDATE `user` SET `name` = ? WHERE `id` = ?"
|
||||
rdb.raw(sql, %*["updated user1", 1]).exec().waitFor
|
||||
sql = &"SELECT * FROM `user` WHERE `id` = ?"
|
||||
let res = rdb.raw(sql, %[1]).get().waitFor
|
||||
echo res
|
||||
check res[0]["name"].getStr == "updated user1"
|
||||
|
||||
|
||||
setup(rdb)
|
||||
suite($rdb & " aggregates"):
|
||||
test("count"):
|
||||
var t = rdb.table("user").count().waitFor
|
||||
check t == 10
|
||||
|
||||
test("max"):
|
||||
var t = rdb.table("user").max("name").waitFor.get
|
||||
check t == "user9"
|
||||
var t2 = rdb.table("user").max("id").waitFor.get
|
||||
check t2 == "10"
|
||||
|
||||
test("min"):
|
||||
var t = rdb.table("user").min("name").waitFor.get
|
||||
check t == "user1"
|
||||
var t2 = rdb.table("user").min("id").waitFor.get
|
||||
check t2 == "1"
|
||||
|
||||
test("avg"):
|
||||
var t = rdb.table("user").avg("id").waitFor.get
|
||||
check t == 5.5
|
||||
|
||||
test("sum"):
|
||||
var t = rdb.table("user").sum("id").waitFor.get
|
||||
check t == 55.0
|
||||
|
||||
|
||||
suite($rdb & " insert binary"):
|
||||
test("should success"):
|
||||
rdb.create(
|
||||
table("test", [
|
||||
Column.increments("id"),
|
||||
Column.binary("pic"),
|
||||
])
|
||||
)
|
||||
|
||||
let client = newAsyncHttpClient()
|
||||
let response = client.getContent("https://nim-lang.org/assets/img/twitter_banner.png").waitFor()
|
||||
let imageStream = newStringStream(response)
|
||||
let binaryImage = imageStream.readAll()
|
||||
|
||||
let id = rdb.table("test").insertId(%*{"pic": binaryImage}).waitFor()
|
||||
|
||||
var res = rdb.table("test").find(id).waitFor().get()
|
||||
check res["pic"].getStr().len > 0
|
||||
|
||||
rdb.table("test").where("id","=", id).update(%*{"pic": binaryImage}).waitFor()
|
||||
|
||||
res = rdb.table("test").find(id).waitFor().get()
|
||||
check res["pic"].getStr().len > 0
|
||||
|
||||
|
||||
clearTables(rdb).waitFor()
|
||||
@@ -0,0 +1,617 @@
|
||||
discard """
|
||||
cmd: "nim c -d:reset $file"
|
||||
"""
|
||||
|
||||
import std/unittest
|
||||
import std/asyncdispatch
|
||||
import std/json
|
||||
import std/options
|
||||
import ../../src/allographer/schema_builder
|
||||
import ../../src/allographer/query_builder
|
||||
import ./connections
|
||||
import ../clear_tables
|
||||
|
||||
|
||||
let rdb = mysql
|
||||
|
||||
suite("MySQL create table"):
|
||||
test("create table"):
|
||||
rdb.create(
|
||||
table("IntRelation", [
|
||||
Column.increments("id")
|
||||
]),
|
||||
table("StrRelation", [
|
||||
Column.uuid("uuid")
|
||||
]),
|
||||
# text, binary, json column can't use default value and index
|
||||
table("TypeIndex", [
|
||||
Column.increments("id"),
|
||||
Column.integer("integer").unsigned().index().default(1),
|
||||
Column.smallInteger("smallInteger").unsigned().index().default(1),
|
||||
Column.mediumInteger("mediumInteger").unsigned().index().default(1),
|
||||
Column.bigInteger("bigInteger").unsigned().index().default(1),
|
||||
Column.decimal("decimal", 10, 3).unsigned().index().default(1.1),
|
||||
Column.double("double", 10, 3).unsigned().index().default(1.1),
|
||||
Column.float("float").unsigned().index().default(1.1),
|
||||
Column.uuid("uuid").index().default("A"),
|
||||
Column.char("char", 255).index().default("A"),
|
||||
Column.string("string").index().default("A"),
|
||||
Column.text("text"),
|
||||
Column.mediumText("mediumText"),
|
||||
Column.longText("longText"),
|
||||
Column.date("date").index().default(),
|
||||
Column.datetime("datetime").index().default(),
|
||||
Column.time("time").index().default(),
|
||||
Column.timestamp("timestamp").index().default(),
|
||||
Column.timestamps(),
|
||||
Column.softDelete(),
|
||||
Column.binary("binary"),
|
||||
Column.boolean("boolean").index().default(true),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).index().default("A"),
|
||||
Column.json("json"),
|
||||
Column.foreign("int_relation_id").reference("id").onTable("IntRelation").onDelete(SET_NULL),
|
||||
Column.strForeign("str_relation_id").reference("uuid").onTable("StrRelation").onDelete(SET_NULL)
|
||||
]),
|
||||
# text, binary, json column can't use default value, index and unique
|
||||
table("TypeUnique", [
|
||||
Column.increments("id"),
|
||||
Column.integer("integer").unsigned().unique().index().default(1),
|
||||
Column.smallInteger("smallInteger").unsigned().unique().index().default(1),
|
||||
Column.mediumInteger("mediumInteger").unsigned().unique().index().default(1),
|
||||
Column.bigInteger("bigInteger").unsigned().unique().index().default(1),
|
||||
Column.decimal("decimal", 10, 3).unsigned().unique().index().default(1.1),
|
||||
Column.double("double", 10, 3).unsigned().unique().index().default(1.1),
|
||||
Column.float("float").unsigned().unique().index().default(1.1),
|
||||
Column.uuid("uuid").unique().index().default("A"),
|
||||
Column.char("char", 255).unique().index().default("A"),
|
||||
Column.string("string").unique().index().default("A"),
|
||||
Column.text("text"),
|
||||
Column.mediumText("mediumText"),
|
||||
Column.longText("longText"),
|
||||
Column.date("date").unique().index().default(),
|
||||
Column.datetime("datetime").unique().index().default(),
|
||||
Column.time("time").unique().index().default(),
|
||||
Column.timestamp("timestamp").unique().index().default(),
|
||||
Column.timestamps(),
|
||||
Column.softDelete(),
|
||||
Column.binary("binary"),
|
||||
Column.boolean("boolean").unique().index().default(true),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).unique().index().default("A"),
|
||||
Column.json("json"),
|
||||
Column.foreign("int_relation_id").reference("id").onTable("IntRelation").onDelete(SET_NULL),
|
||||
Column.strForeign("str_relation_id").reference("uuid").onTable("StrRelation").onDelete(SET_NULL)
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
test("change columns"):
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.integer("integer").unsigned().index().default(1).change(),
|
||||
Column.smallInteger("smallInteger").unsigned().index().default(1).change(),
|
||||
Column.mediumInteger("mediumInteger").unsigned().index().default(1).change(),
|
||||
Column.bigInteger("bigInteger").unsigned().index().default(1).change(),
|
||||
Column.decimal("decimal", 10, 3).unsigned().index().default(1.1).change(),
|
||||
Column.double("double", 10, 3).unsigned().index().default(1.1).change(),
|
||||
Column.float("float").unsigned().index().default(1.1).change(),
|
||||
Column.uuid("uuid").index().default("A").change(),
|
||||
Column.char("char", 255).index().default("A").change(),
|
||||
Column.string("string").index().default("A").change(),
|
||||
Column.text("text").change(),
|
||||
Column.mediumText("mediumText").change(),
|
||||
Column.longText("longText").change(),
|
||||
Column.date("date").index().default().change(),
|
||||
Column.datetime("datetime").index().default().change(),
|
||||
Column.time("time").index().default().change(),
|
||||
Column.timestamp("timestamp").index().default().change(),
|
||||
Column.binary("binary").change(),
|
||||
Column.boolean("boolean").index().default(true).change(),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).index().default("A").change(),
|
||||
Column.json("json").change(),
|
||||
]),
|
||||
table("TypeUnique", [
|
||||
Column.integer("integer").unsigned().unique().index().default(1).change(),
|
||||
Column.smallInteger("smallInteger").unsigned().unique().index().default(1).change(),
|
||||
Column.mediumInteger("mediumInteger").unsigned().unique().index().default(1).change(),
|
||||
Column.bigInteger("bigInteger").unsigned().unique().index().default(1).change(),
|
||||
Column.decimal("decimal", 10, 3).unsigned().unique().index().default(1.1).change(),
|
||||
Column.double("double", 10, 3).unsigned().unique().index().default(1.1).change(),
|
||||
Column.float("float").unsigned().unique().index().default(1.1).change(),
|
||||
Column.uuid("uuid").unique().index().default("A").change(),
|
||||
Column.char("char", 255).unique().index().default("A").change(),
|
||||
Column.string("string").unique().index().default("A").change(),
|
||||
Column.text("text").change(),
|
||||
Column.mediumText("mediumText").change(),
|
||||
Column.longText("longText").change(),
|
||||
Column.date("date").unique().index().default().change(),
|
||||
Column.datetime("datetime").unique().index().default().change(),
|
||||
Column.time("time").unique().index().default().change(),
|
||||
Column.timestamp("timestamp").unique().index().default().change(),
|
||||
Column.binary("binary").change(),
|
||||
Column.boolean("boolean").unique().index().default(true).change(),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).unique().index().default("A").change(),
|
||||
Column.json("json").change(),
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
suite("error in text, blob, json column for default, index and unique"):
|
||||
suite("create table"):
|
||||
test("text"):
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").default("A"),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").index(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").unique(),
|
||||
])
|
||||
)
|
||||
|
||||
test("mediumText"):
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").default("A"),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").index(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").unique(),
|
||||
])
|
||||
)
|
||||
|
||||
test("longText"):
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").default("A"),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").index(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").unique(),
|
||||
])
|
||||
)
|
||||
|
||||
test("binary"):
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").default("A"),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").index(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").unique(),
|
||||
])
|
||||
)
|
||||
|
||||
test("json"):
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").default(%*{"key": "value"}),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").index(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").unique(),
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
suite("add column"):
|
||||
test("text"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").default("A").add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").index().add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").unique().add(),
|
||||
])
|
||||
)
|
||||
|
||||
test("mediumText"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").default("A").add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").index().add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").unique().add(),
|
||||
])
|
||||
)
|
||||
|
||||
test("longText"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").default("A").add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").index().add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").unique().add(),
|
||||
])
|
||||
)
|
||||
|
||||
test("binary"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").default("A").add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").index().add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").unique().add(),
|
||||
])
|
||||
)
|
||||
|
||||
test("json"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").default(%*{"key": "value"}).add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").index().add(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").unique().add(),
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
suite("change column"):
|
||||
test("text"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").default("A").change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").index().change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.text("text").unique().change(),
|
||||
])
|
||||
)
|
||||
|
||||
test("mediumText"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").default("A").change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").index().change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.mediumText("mediumText").unique().change(),
|
||||
])
|
||||
)
|
||||
|
||||
test("longText"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").default("A").change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").index().change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.longText("longText").unique().change(),
|
||||
])
|
||||
)
|
||||
|
||||
test("binary"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").default("A").change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").index().change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.binary("binary").unique().change(),
|
||||
])
|
||||
)
|
||||
|
||||
test("json"):
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").default(%*{"key": "value"}).change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").index().change(),
|
||||
])
|
||||
)
|
||||
expect DbError:
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.json("json").unique().change(),
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
suite("MySQL alter table"):
|
||||
setup:
|
||||
rdb.create(
|
||||
table("IntRelation", [
|
||||
Column.increments("id"),
|
||||
]),
|
||||
table("StrRelation", [
|
||||
Column.uuid("uuid"),
|
||||
]),
|
||||
table("TypeUnique", [
|
||||
Column.integer("num"),
|
||||
Column.string("str"),
|
||||
]),
|
||||
table("TypeIndex", [
|
||||
Column.integer("num"),
|
||||
Column.string("str"),
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
test("add columns"):
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.increments("id").add(),
|
||||
Column.integer("integer").unsigned().index().default(1).add(),
|
||||
Column.smallInteger("smallInteger").unsigned().index().default(1).add(),
|
||||
Column.mediumInteger("mediumInteger").unsigned().index().default(1).add(),
|
||||
Column.bigInteger("bigInteger").unsigned().index().default(1).add(),
|
||||
Column.decimal("decimal", 10, 3).unsigned().index().default(1.1).add(),
|
||||
Column.double("double", 10, 3).unsigned().index().default(1.1).add(),
|
||||
Column.float("float").unsigned().index().default(1.1).add(),
|
||||
Column.uuid("uuid").index().default("A").add(),
|
||||
Column.char("char", 255).index().default("A").add(),
|
||||
Column.string("string").index().default("A").add(),
|
||||
Column.text("text").add(),
|
||||
Column.mediumText("mediumText").add(),
|
||||
Column.longText("longText").add(),
|
||||
Column.date("date").index().default().add(),
|
||||
Column.datetime("datetime").index().default(),
|
||||
Column.time("time").index().default().add(),
|
||||
Column.timestamp("timestamp").index().default().add(),
|
||||
Column.timestamps().add(),
|
||||
Column.softDelete().add(),
|
||||
Column.binary("binary").add(),
|
||||
Column.boolean("boolean").index().default(true).add(),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).index().default("A").add(),
|
||||
Column.json("json").add(),
|
||||
Column.foreign("int_relation_id").reference("id").onTable("IntRelation").onDelete(SET_NULL).add(),
|
||||
Column.strForeign("str_relation_id").reference("uuid").onTable("StrRelation").onDelete(SET_NULL).add()
|
||||
]),
|
||||
table("TypeUnique", [
|
||||
Column.increments("id").add(),
|
||||
Column.integer("integer").unsigned().unique().index().default(1).add(),
|
||||
Column.smallInteger("smallInteger").unsigned().unique().index().default(1).add(),
|
||||
Column.mediumInteger("mediumInteger").unsigned().unique().index().default(1).add(),
|
||||
Column.bigInteger("bigInteger").unsigned().unique().index().default(1).add(),
|
||||
Column.decimal("decimal", 10, 3).unsigned().unique().index().default(1.1).add(),
|
||||
Column.double("double", 10, 3).unsigned().unique().index().default(1.1).add(),
|
||||
Column.float("float").unsigned().unique().index().default(1.1).add(),
|
||||
Column.uuid("uuid").unique().index().default("A").add(),
|
||||
Column.char("char", 255).unique().index().default("A").add(),
|
||||
Column.string("string").unique().index().default("A").add(),
|
||||
Column.text("text").add(),
|
||||
Column.mediumText("mediumText").add(),
|
||||
Column.longText("longText").add(),
|
||||
Column.date("date").unique().index().default().add(),
|
||||
Column.datetime("datetime").unique().index().default().add(),
|
||||
Column.time("time").unique().index().default().add(),
|
||||
Column.timestamp("timestamp").unique().index().default().add(),
|
||||
Column.timestamps().add(),
|
||||
Column.softDelete().add(),
|
||||
Column.binary("binary").add(),
|
||||
Column.boolean("boolean").unique().index().default(true).add(),
|
||||
Column.enumField("enumField", ["A", "B", "C"]).unique().index().default("A").add(),
|
||||
Column.json("json").add()
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
test("rename column"):
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.renameColumn("num", "num2"),
|
||||
Column.renameColumn("str", "str2"),
|
||||
])
|
||||
)
|
||||
|
||||
let columns = rdb.table("TypeIndex").columns().waitFor
|
||||
check not columns.contains("num")
|
||||
check columns.contains("num2")
|
||||
check not columns.contains("str")
|
||||
check columns.contains("str2")
|
||||
|
||||
|
||||
test("drop column"):
|
||||
rdb.alter(
|
||||
table("TypeIndex", [
|
||||
Column.dropColumn("str")
|
||||
])
|
||||
)
|
||||
|
||||
let columns = rdb.table("TypeIndex").columns().waitFor
|
||||
check not columns.contains("str")
|
||||
|
||||
|
||||
test("rename table"):
|
||||
rdb.drop(
|
||||
table("TypeIndex_renamed")
|
||||
)
|
||||
rdb.table("TypeIndex").insert(%*{"num":1, "str": "a"}).waitFor
|
||||
|
||||
rdb.alter(
|
||||
table("TypeIndex").renameTo("TypeIndex_renamed")
|
||||
)
|
||||
|
||||
var res:Option[JsonNode]
|
||||
try:
|
||||
res = rdb.table("TypeIndex").first().waitFor
|
||||
check not res.isSome
|
||||
except CatchableError:
|
||||
check true
|
||||
|
||||
res = rdb.table("TypeIndex_renamed").first().waitFor
|
||||
check res.isSome
|
||||
|
||||
|
||||
test("drop table"):
|
||||
rdb.create(
|
||||
table("TypeIndex", [
|
||||
Column.integer("num")
|
||||
])
|
||||
)
|
||||
|
||||
rdb.drop(
|
||||
table("TypeIndex")
|
||||
)
|
||||
|
||||
var res:Option[JsonNode]
|
||||
try:
|
||||
res = rdb.table("TypeIndex").first().waitFor
|
||||
check not res.isSome
|
||||
except CatchableError:
|
||||
check true
|
||||
|
||||
|
||||
suite($rdb & " primary"):
|
||||
test("primary key"):
|
||||
rdb.create(
|
||||
table("relation", [
|
||||
Column.increments("id"),
|
||||
]),
|
||||
table("TypeIndex", @[
|
||||
Column.integer("index1"),
|
||||
Column.integer("index2"),
|
||||
Column.string("string"),
|
||||
Column.foreign("relation_id").reference("id").onTable("relation").onDelete(SET_NULL)
|
||||
],
|
||||
primary = @["index1", "index2"]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
suite("Comment"):
|
||||
test("column comment"):
|
||||
rdb.create(
|
||||
table("Comment", [
|
||||
Column.integer("index1").comment("index1 comment"),
|
||||
Column.string("string").comment("string comment")
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
clearTables(rdb).waitFor()
|
||||
@@ -0,0 +1,128 @@
|
||||
discard """
|
||||
cmd: "nim c --mm:orc -d:reset -r $file"
|
||||
"""
|
||||
|
||||
import std/unittest
|
||||
import std/json
|
||||
import std/strformat
|
||||
import std/strutils
|
||||
import std/options
|
||||
import std/asyncdispatch
|
||||
import ../../src/allographer/schema_builder
|
||||
import ../../src/allographer/query_builder
|
||||
import ./connections
|
||||
import ../clear_tables
|
||||
|
||||
|
||||
let rdb = mysql
|
||||
|
||||
proc setUp(rdb:MysqlConnections) =
|
||||
rdb.create([
|
||||
table("auth",[
|
||||
Column.increments("id"),
|
||||
Column.string("auth")
|
||||
]),
|
||||
table("user",[
|
||||
Column.increments("id"),
|
||||
Column.string("name").nullable(),
|
||||
Column.string("email").nullable(),
|
||||
Column.string("address").nullable(),
|
||||
Column.foreign("auth_id").reference("id").onTable("auth").onDelete(SET_NULL)
|
||||
])
|
||||
])
|
||||
|
||||
# seeder
|
||||
seeder(rdb, "auth"):
|
||||
rdb.table("auth").insert(@[
|
||||
%*{"auth": "admin"},
|
||||
%*{"auth": "user"}
|
||||
])
|
||||
.waitFor()
|
||||
|
||||
seeder(rdb, "user"):
|
||||
var users: seq[JsonNode]
|
||||
for i in 1..10:
|
||||
let authId = if i mod 2 == 0: 2 else: 1
|
||||
users.add(
|
||||
%*{
|
||||
"name": &"user{i}",
|
||||
"email": &"user{i}@example.com",
|
||||
"auth_id": authId
|
||||
}
|
||||
)
|
||||
|
||||
rdb.table("user").insert(users).waitFor()
|
||||
|
||||
|
||||
suite("raw code transaction"):
|
||||
setup:
|
||||
setUp(rdb)
|
||||
|
||||
test("commit"):
|
||||
(proc() {.async.} =
|
||||
var user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
|
||||
block:
|
||||
rdb.begin().await
|
||||
try:
|
||||
rdb.table("user").where("id", "=", 1).update(%*{"name": "updated"}).await
|
||||
rdb.commit().await
|
||||
except CatchableError:
|
||||
rdb.rollback().await
|
||||
|
||||
user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "updated"
|
||||
)().waitFor
|
||||
|
||||
|
||||
test("rollback"):
|
||||
(proc() {.async.} =
|
||||
var user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
|
||||
block:
|
||||
rdb.begin().await
|
||||
try:
|
||||
rdb.table("user").where("id", "=", 1).update(%*{"name": "updated"}).await
|
||||
raise newException(CatchableError, "")
|
||||
except:
|
||||
rdb.rollback().await
|
||||
|
||||
user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
)().waitFor
|
||||
|
||||
|
||||
suite("transaction template"):
|
||||
setup:
|
||||
setUp(rdb)
|
||||
|
||||
test("commit"):
|
||||
(proc(){.async.} =
|
||||
var user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
|
||||
transaction(rdb):
|
||||
rdb.table("user").where("id", "=", 1).update(%*{"name": "updated"}).await
|
||||
|
||||
user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "updated"
|
||||
)().waitFor()
|
||||
|
||||
|
||||
test("rollback"):
|
||||
(proc(){.async.} =
|
||||
var user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
|
||||
transaction(rdb):
|
||||
rdb.table("user").where("id", "=", 1).update(%*{"name": "updated"}).await
|
||||
raise newException(DbError, "")
|
||||
|
||||
user1 = rdb.table("user").find(1).await.get()
|
||||
check user1["name"].getStr() == "user1"
|
||||
)().waitFor()
|
||||
|
||||
|
||||
clearTables(rdb).waitFor()
|
||||
Reference in New Issue
Block a user