discard """ cmd: "nim c -d:reset $file" """ # nim c -r -d:reset tests/surrealdb/test_query.nim import std/unittest import std/asyncdispatch import std/json import std/options import std/strformat import std/times import ../../src/allographer/schema_builder import ../../src/allographer/query_builder import ./connections import ../clear_tables let rdb = surreal proc isNullish(node: JsonNode, key: string): bool = not node.hasKey(key) or node[key].kind == JNull # ============================================================================= # test # ============================================================================= proc setup(rdb:SurrealConnections) = # rdb.raw("REMOVE TABLE auth; REMOVE TABLE user").exec().waitFor # rdb.raw("DEFINE TABLE auth SCHEMAFULL; DEFINE TABLE user SCHEMAFULL").exec().waitFor rdb.create([ table("auth",[ Column.increments("index"), Column.string("name") ]), table("user",[ Column.increments("index"), Column.string("name").nullable(), Column.string("email").nullable(), Column.string("address").nullable(), Column.date("submit_on"), Column.datetime("submit_at"), Column.foreign("auth").reference("id").onTable("auth").onDelete(SET_NULL).nullable() ]) ]) # seeder var adminId, userId:SurrealId seeder(rdb, "auth"): adminId = rdb.table("auth").insertId(%*{"name":"admin"}).waitFor() userId = rdb.table("auth").insertId(%*{"name":"user"}).waitFor() seeder(rdb, "user"): var users: seq[JsonNode] for i in 1..10: let authId = if i mod 2 == 0: userId else: adminId let month = if i > 9: $i else: &"0{i}" users.add( %*{ "name": &"user{i}", "email": &"user{i}@example.com", "address": newJNull(), "auth": authId, "submit_on": &"2020-{month}-01", "submit_at": &"2020-{month}-01T00:00:00Z", } ) rdb.table("user").insert(users).waitFor() setup(rdb) suite($rdb & " get"): test("get"): let t = rdb.table("user").orderBy("name", Asc).get().waitFor() echo t[0] check t[0]["index"].getInt() == 1 check t[0]["name"].getStr() == "user1" check t[0]["email"].getStr() == "user1@example.com" check isNullish(t[0], "address") check t[0]["submit_on"].getStr().parse("yyyy-MM-dd'T'hh:mm:ss'Z'").format("yyyy-MM-dd") == "2020-01-01" check t[0]["submit_at"].getStr() == "2020-01-01T00:00:00Z" test("first"): var t = rdb.table("user").where("name", "=", "user1").orderBy("name", Asc).first().waitFor().get() check t["index"].getInt() == 1 check t["name"].getStr() == "user1" check t["email"].getStr() == "user1@example.com" check isNullish(t, "address") check t["submit_on"].getStr().parse("yyyy-MM-dd'T'hh:mm:ss'Z'").format("yyyy-MM-dd") == "2020-01-01" check t["submit_at"].getStr() == "2020-01-01T00:00:00Z" test("find"): var t = rdb.table("user").where("name", "=", "user1").orderBy("name", Asc).first().waitFor().get() let id = SurrealId.new(t["id"].getStr()) t = rdb.table("user").find(id).waitFor().get() check t["index"].getInt() == 1 check t["name"].getStr() == "user1" check t["email"].getStr() == "user1@example.com" check isNullish(t, "address") check t["submit_on"].getStr().parse("yyyy-MM-dd'T'hh:mm:ss'Z'").format("yyyy-MM-dd") == "2020-01-01" check t["submit_at"].getStr() == "2020-01-01T00:00:00Z" test("columns"): let columns = rdb.table("user").columns().waitFor() check columns == @["address", "auth", "email", "index", "name", "submit_at", "submit_on"] test("select"): var t = rdb.select("name", "email").table("user").orderBy("name", Asc).get().waitFor() check t[0] == %*{"name": "user1", "email": "user1@example.com"} test("selectAs"): var t = rdb.select("name as user_name", "email").table("user").orderBy("user_name", Asc).get().waitFor() check t[0] == %*{"user_name": "user1", "email": "user1@example.com"} test("selectLike"): let users = rdb.table("user").where("email", "CONTAINS", "10").get().waitFor() check users[0]["email"].getStr() == "user10@example.com" var user10 = rdb.raw("SELECT * FROM user WHERE string::starts_with(email, \"user10\")").first().waitFor() check user10.get()["email"].getStr() == "user10@example.com" user10 = rdb.raw("SELECT * FROM user WHERE string::ends_with(email, \"10@example.com\")").first().waitFor() check user10.get()["email"].getStr() == "user10@example.com" test("select count"): var t = rdb.raw("SELECT count(`id`) as `count` FROM `user` GROUP ALL").get().waitFor echo t check t[0]["count"].getInt() == 10 test("select max"): var t = rdb.raw("SELECT math::max(`index`) as `max` FROM `user` GROUP ALL").get().waitFor echo t check t[0]["max"].getInt() == 10 test("where string"): let admin = rdb.table("auth").where("name", "=", "admin").first().waitFor().get() let adminId = SurrealId.new(admin["id"].getStr()) var t = rdb.table("user").where("auth", "=", adminId.rawId()).orderBy("index", Asc).get().waitFor() const ids = [1,3,5,7,9] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("where int"): var t = rdb.table("user").where("index", "=", 1).orderBy("index", Asc).first().waitFor().get() check t["index"].getInt() == 1 check t["name"].getStr() == "user1" check t["email"].getStr() == "user1@example.com" check isNullish(t, "address") check t["submit_on"].getStr() == "2020-01-01T00:00:00Z" test("orWhere"): let admin = rdb.table("auth").where("name", "=", "admin").first().waitFor().get() let adminId = SurrealId.new(admin["id"].getStr()) var t = rdb.table("user").where("auth", "=", adminId).orWhere("name", "=", "user2").orderBy("index", Asc).get().waitFor() const ids = [1,2,3,5,7,9] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("whereBetween"): var t = rdb .table("user") .whereBetween("index", [6, 9]) .orderBy("index", Asc) .get() .waitFor() const ids = [6,7,8,9] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("whereNotBetween"): var t = rdb .table("user") .whereNotBetween("index", [2, 6]) .orderBy("index", Asc) .get() .waitFor() const ids = [1,7,8,9] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("whereIn"): var t = rdb .table("user") .whereIn("index", @[5, 6, 7]) .orderBy("index", Asc) .get() .waitFor() const ids = [5,6,7] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("whereNotIn"): var t = rdb .table("user") .whereNotIn("index", @[4, 5, 6, 7, 10]) .orderBy("index", Asc) .get() .waitFor() const ids = [1,2,3,8,9] for i, row in t: check row["index"].getInt() == ids[i] check row["name"].getStr() == &"user{ids[i]}" check row["email"].getStr() == &"user{ids[i]}@example.com" check isNullish(row, "address") check row["submit_on"].getStr() == &"2020-0{ids[i]}-01T00:00:00Z" test("whereNull"): rdb.table("user").insert(%*{"email": "user11@example.com"}).waitFor() var t = rdb .table("user") .whereNull("name") .first() .waitFor() check t.get()["index"].getInt() == 11 setUp(rdb) # TODO: not work # test("groupBy"): # var t = rdb # .select("auth.name") # .table("user") # .groupBy("auth.name") # .get() # .waitFor() # echo t test("orderBy"): var res = rdb.table("user").orderBy("name", Asc).get().waitFor() check res[0]["name"].getStr() == "user1" res = rdb.table("user").orderBy("name", Desc).get().waitFor() check res[0]["name"].getStr() == "user9" res = rdb.table("user").orderBy("index", Numeric, Asc).get().waitFor() check res[0]["name"].getStr() == "user1" res = rdb.table("user").orderBy("index", Numeric, Desc).get().waitFor() check res[0]["name"].getStr() == "user10" res = rdb.table("user").orderBy("name", Collate, Asc).get().waitFor() check res[0]["name"].getStr() == "user1" res = rdb.table("user").orderBy("name", Collate, Desc).get().waitFor() check res[0]["name"].getStr() == "user9" test("fetch"): var res = rdb.table("user").where("name", "=", "user1").fetch("auth").first().waitFor().get() check res["auth"]["name"].getStr() == "admin" res = rdb.table("user").where("name", "=", "user2").fetch("auth").first().waitFor().get() check res["auth"]["name"].getStr() == "user" test("resultIsNull"): check rdb.table("user").where("id", "=", 50).first().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("index", 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("index", 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 check not res.get.hasKey("email") or res.get["email"].kind == JNull res = rdb.table("user").whereNull("email").first().waitFor check not res.get.hasKey("email") or res.get["email"].kind == JNull 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("index", 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("index", 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"): var user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) rdb.table("user").where("id", "=", user1Id).update(%*{"name": "Alice"}).waitFor() user1 = rdb.table("user").find(user1Id).waitFor().get() check user1["name"].getStr() == "Alice" test("update [T]"): type User = object name:string let user = User(name: "Alice") var user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) rdb.table("user").where("id", "=", user1Id).update(user).waitFor() user1 = rdb.table("user").find(user1Id).waitFor().get() check user1["name"].getStr() == "Alice" test("update merge"): var user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) rdb.update(user1Id, %*{"name": "updated"}).waitFor() user1 = rdb.table("user").find(user1Id).waitFor().get() check user1["name"].getStr() == "updated" test("update merge [T]"): type User = object name:string var user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) let user = User(name: "updated") rdb.update(user1Id, user).waitFor() user1 = rdb.table("user").find(user1Id).waitFor().get() check user1["name"].getStr() == "updated" suite($rdb & " delete"): setup: setup(rdb) test("delete"): let user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) rdb.table("user").where("name", "=", "user1").delete().waitFor() check rdb.table("user").find(user1Id).waitFor().isSome() == false test("delete id"): let user1 = rdb.table("user").where("index", "=", 1).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) rdb.table("user").delete(user1Id).waitFor check rdb.table("user").find(user1Id).waitFor().isSome() == false suite($rdb & " rawQuery"): setup(rdb) test("get"): let sql = &"SELECT * FROM `user` WHERE `index` = ?" let res = rdb.raw(sql, %*[1]).get().waitFor check res[0]["name"].getStr == "user1" test("first"): let sql = &"SELECT * FROM `user` WHERE `index` = ?" let res = rdb.raw(sql, %*[1]).first().waitFor().get() check res["name"].getStr() == "user1" test("exec"): var sql = "SELECT * FROM `user` WHERE `index` = ?" let user1 = rdb.raw(sql, %*[1]).first().waitFor().get() let user1Id = SurrealId.new(user1["id"].getStr()) sql = "UPDATE `user` SET `name` = ? WHERE `id` = ?" rdb.raw(sql, %*["updated", user1Id.rawId()]).exec().waitFor sql = &"SELECT * FROM `user` WHERE `id` = ?" let res = rdb.raw(sql, %[user1Id.rawId()]).get().waitFor check res[0]["name"].getStr == "updated" 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", Collate).waitFor() check t == "user9" var t2 = rdb.table("user").max("index", Numeric).waitFor() check t2 == "10" test("min"): var t = rdb.table("user").min("name", Collate).waitFor() check t == "user1" var t2 = rdb.table("user").min("index", Numeric).waitFor() check t2 == "1" test("avg"): let t = rdb.table("user").avg("index").waitFor() check t == 5.5 test("sum"): let t = rdb.table("user").sum("index").waitFor() check t == 55.0 clearTables(rdb).waitFor()