diff --git a/allographer.nimble b/allographer.nimble index be3d0ee3..37817360 100644 --- a/allographer.nimble +++ b/allographer.nimble @@ -1,6 +1,6 @@ # Package -version = "0.14.0" +version = "0.15.0" author = "Hidenobu Itsumura @dumblepytech1 as 'medy'" description = "A Nim query builder library inspired by Laravel/PHP and Orator/Python" license = "MIT" diff --git a/src/allographer/connection.nim b/src/allographer/connection.nim index 595d3df5..90fbbc1b 100644 --- a/src/allographer/connection.nim +++ b/src/allographer/connection.nim @@ -11,7 +11,7 @@ const when DRIVER == "sqlite": import db_sqlite export db_sqlite - import sqlite3 except close + # import sqlite3 except close when DRIVER == "postgres": import ./async/asyncpg diff --git a/src/allographer/query_builder/exec.nim b/src/allographer/query_builder/exec.nim index 330979a8..869acc1e 100644 --- a/src/allographer/query_builder/exec.nim +++ b/src/allographer/query_builder/exec.nim @@ -123,7 +123,7 @@ proc getAllRowsPlain*(sqlString:string, args:varargs[string]):seq[seq[string]] = proc getAllRowsPlain*(db:DbConn, sqlString:string, args:varargs[string]):seq[seq[string]] = return db.getAllRows(sql sqlString, args) -proc getRow(sqlString:string, args:varargs[string]):JsonNode = +proc getRow(sqlString:string, args:varargs[string]):Option[JsonNode] = let db = db() defer: db.close() @@ -138,12 +138,12 @@ proc getRow(sqlString:string, args:varargs[string]):JsonNode = if rows.len == 0: echoErrorMsg(sqlString & $args) - return newJNull() + return none(JsonNode) let columns = getColumns(db_columns) - return toJson(rows, columns)[0] + return toJson(rows, columns)[0].some -proc getRow(db:DbConn, sqlString:string, args:varargs[string]): JsonNode = +proc getRow(db:DbConn, sqlString:string, args:varargs[string]):Option[JsonNode] = ## used in transaction var db_columns: DbColumns var rows = newSeq[seq[string]]() @@ -156,10 +156,10 @@ proc getRow(db:DbConn, sqlString:string, args:varargs[string]): JsonNode = if rows.len == 0: echoErrorMsg(sqlString & $args) - return newJNull() + return none(JsonNode) let columns = getColumns(db_columns) - return toJson(rows, columns)[0] + return toJson(rows, columns)[0].some proc getRowPlain(sqlString:string, args:varargs[string]):seq[string] = let db = db() @@ -410,7 +410,7 @@ proc getRaw*(this: RDB, typ: typedesc): seq[typ.type] = getCurrentExceptionMsg().echoErrorMsg() return newSeq[typ.type](0) -proc first*(this: RDB): JsonNode = +proc first*(this: RDB):Option[JsonNode] = defer: this.cleanUp() this.sqlString = this.selectFirstBuilder().sqlString try: @@ -422,7 +422,7 @@ proc first*(this: RDB): JsonNode = except Exception: echoErrorMsg(this.sqlString & $this.placeHolder) getCurrentExceptionMsg().echoErrorMsg() - return newJNull() + return none(JsonNode) proc first*(this: RDB, typ: typedesc):Option[typ.type] = defer: this.cleanUp() @@ -430,9 +430,9 @@ proc first*(this: RDB, typ: typedesc):Option[typ.type] = try: logger(this.sqlString, this.placeHolder) if this.db.isNil: - return getRow(this.sqlString, this.placeHolder).orm(typ).some() + return getRow(this.sqlString, this.placeHolder).get.orm(typ).some else: - return getRow(this.db, this.sqlString, this.placeHolder).orm(typ).some() + return getRow(this.db, this.sqlString, this.placeHolder).get.orm(typ).some except Exception: echoErrorMsg(this.sqlString & $this.placeHolder) getCurrentExceptionMsg().echoErrorMsg() @@ -452,7 +452,7 @@ proc firstPlain*(this: RDB): seq[string] = getCurrentExceptionMsg().echoErrorMsg() return newSeq[string](0) -proc find*(this: RDB, id: int, key="id"): JsonNode = +proc find*(this: RDB, id: int, key="id"):Option[JsonNode] = defer: this.cleanUp() this.placeHolder.add($id) this.sqlString = this.selectFindBuilder(id, key).sqlString @@ -465,7 +465,7 @@ proc find*(this: RDB, id: int, key="id"): JsonNode = except Exception: echoErrorMsg(this.sqlString & $this.placeHolder) getCurrentExceptionMsg().echoErrorMsg() - return newJNull() + return none(JsonNode) proc find*(this: RDB, id: int, typ:typedesc, key="id"):Option[typ.type] = defer: this.cleanUp() @@ -474,9 +474,9 @@ proc find*(this: RDB, id: int, typ:typedesc, key="id"):Option[typ.type] = try: logger(this.sqlString, this.placeHolder) if this.db.isNil: - return getRow(this.sqlString, this.placeHolder).orm(typ).some() + return getRow(this.sqlString, this.placeHolder).get.orm(typ).some else: - return getRow(this.db, this.sqlString, this.placeHolder).orm(typ).some() + return getRow(this.db, this.sqlString, this.placeHolder).get.orm(typ).some except Exception: echoErrorMsg(this.sqlString & $this.placeHolder) getCurrentExceptionMsg().echoErrorMsg() @@ -696,61 +696,76 @@ proc exec*(this: RDB) = proc count*(this:RDB): int = this.sqlString = this.countBuilder().sqlString logger(this.sqlString, this.placeHolder) - var response = getRow(this.sqlString, this.placeHolder) - let DRIVER = getDriver() - case DRIVER - of "sqlite": - return response["aggregate"].getStr().parseInt() - of "mysql": - return response["aggregate"].getInt() - of "postgres": - return response["aggregate"].getInt() - -proc max*(this:RDB, column:string): string = + let response = getRow(this.sqlString, this.placeHolder) + if response.isSome: + let DRIVER = getDriver() + case DRIVER + of "sqlite": + return response.get["aggregate"].getStr().parseInt() + of "mysql": + return response.get["aggregate"].getInt() + of "postgres": + return response.get["aggregate"].getInt() + else: + return 0 + +proc max*(this:RDB, column:string):Option[string] = this.sqlString = this.maxBuilder(column).sqlString logger(this.sqlString, this.placeHolder) - var response = getRow(this.sqlString, this.placeHolder) - case response["aggregate"].kind - of JInt: - return $(response["aggregate"].getInt()) - of JFloat: - return $(response["aggregate"].getFloat()) + let response = getRow(this.sqlString, this.placeHolder) + if response.isSome: + case response.get["aggregate"].kind + of JInt: + return some($(response.get["aggregate"].getInt)) + of JFloat: + return some($(response.get["aggregate"].getFloat)) + else: + return some(response.get["aggregate"].getStr) else: - return response["aggregate"].getStr() + return none(string) -proc min*(this:RDB, column:string): string = +proc min*(this:RDB, column:string):Option[string] = this.sqlString = this.minBuilder(column).sqlString logger(this.sqlString, this.placeHolder) - var response = getRow(this.sqlString, this.placeHolder) - case response["aggregate"].kind - of JInt: - return $(response["aggregate"].getInt()) - of JFloat: - return $(response["aggregate"].getFloat()) + let response = getRow(this.sqlString, this.placeHolder) + if response.isSome: + case response.get["aggregate"].kind + of JInt: + return some($(response.get["aggregate"].getInt)) + of JFloat: + return some($(response.get["aggregate"].getFloat)) + else: + return some(response.get["aggregate"].getStr) else: - return response["aggregate"].getStr() + return none(string) -proc avg*(this:RDB, column:string): float = +proc avg*(this:RDB, column:string): Option[float] = this.sqlString = this.avgBuilder(column).sqlString logger(this.sqlString, this.placeHolder) - var response = getRow(this.sqlString, this.placeHolder) - let DRIVER = getDriver() - case DRIVER - of "sqlite": - return response["aggregate"].getStr().parseFloat() + let response = getRow(this.sqlString, this.placeHolder) + if response.isSome: + let DRIVER = getDriver() + case DRIVER + of "sqlite": + return response.get["aggregate"].getStr().parseFloat.some + else: + return response.get["aggregate"].getFloat.some else: - return response["aggregate"].getFloat() + return none(float) -proc sum*(this:RDB, column:string): float = +proc sum*(this:RDB, column:string): Option[float] = this.sqlString = this.sumBuilder(column).sqlString logger(this.sqlString, this.placeHolder) - var response = getRow(this.sqlString, this.placeHolder) - let DRIVER = getDriver() - case DRIVER - of "sqlite": - return response["aggregate"].getStr().parseFloat() + let response = getRow(this.sqlString, this.placeHolder) + if response.isSome: + let DRIVER = getDriver() + case DRIVER + of "sqlite": + return response.get["aggregate"].getStr.parseFloat.some + else: + return response.get["aggregate"].getFloat.some else: - return response["aggregate"].getFloat() + return none(float) # ==================== Paginate ==================== @@ -788,7 +803,10 @@ proc getFirstItem(this:RDB, keyArg:string, order:Order=Asc):int = sqlString = &"{sqlString} ORDER BY {keyArg} DESC LIMIT 1" let row = getRow(sqlString, this.placeHolder) let key = if keyArg.contains("."): keyArg.split(".")[1] else: keyArg - return row[key].getInt + if row.isSome: + return row.get[key].getInt + else: + return 0 proc getLastItem(this:RDB, keyArg:string, order:Order=Asc):int = @@ -799,7 +817,10 @@ proc getLastItem(this:RDB, keyArg:string, order:Order=Asc):int = sqlString = &"{sqlString} ORDER BY {keyArg} ASC LIMIT 1" let row = getRow(sqlString, this.placeHolder) let key = if keyArg.contains("."): keyArg.split(".")[1] else: keyArg - return row[key].getInt + if row.isSome: + return row.get[key].getInt + else: + return 0 proc fastPaginate*(this:RDB, display:int, key="id", order:Order=Asc):JsonNode = @@ -810,20 +831,29 @@ proc fastPaginate*(this:RDB, display:int, key="id", order:Order=Asc):JsonNode = this.sqlString = &"{this.sqlString} ORDER BY {key} DESC LIMIT {display + 1}" logger(this.sqlString, this.placeHolder) var currentPage = getAllRows(this.sqlString, this.placeHolder) - let newKey = if key.contains("."): key.split(".")[1] else: key - let nextId = currentPage[currentPage.len-1][newKey].getInt() - var hasNextId = true - if currentPage.len > display: - discard currentPage.pop() + if currentPage.len > 0: + let newKey = if key.contains("."): key.split(".")[1] else: key + let nextId = currentPage[currentPage.len-1][newKey].getInt() + var hasNextId = true + if currentPage.len > display: + discard currentPage.pop() + else: + hasNextId = false + return %*{ + "previousId": 0, + "hasPreviousId": false, + "currentPage": currentPage, + "nextId": nextId, + "hasNextId": hasNextId + } else: - hasNextId = false - return %*{ - "previousId": 0, - "hasPreviousId": false, - "currentPage": currentPage, - "nextId": nextId, - "hasNextId": hasNextId - } + %*{ + "previousId": 0, + "hasPreviousId": false, + "currentPage": currentPage, + "nextId": 0, + "hasNextId": false + } proc fastPaginateNext*(this:RDB, display:int, id:int, key="id", @@ -856,29 +886,38 @@ SELECT * FROM ( this.placeHolder &= this.placeHolder logger(this.sqlString, this.placeHolder) var currentPage = getAllRows(this.sqlString, this.placeHolder) - let newKey = if key.contains("."): key.split(".")[1] else: key - # previous - var previousId = currentPage[0][newKey].getInt() - var hasPreviousId = true - if previousId != firstItem: - currentPage.delete(0) - else: - hasPreviousId = false - # next - var nextId = currentPage[currentPage.len-1][newKey].getInt() - var hasNextId = true - if currentPage.len > display: - discard currentPage.pop() + if currentPage.len > 0: + let newKey = if key.contains("."): key.split(".")[1] else: key + # previous + var previousId = currentPage[0][newKey].getInt() + var hasPreviousId = true + if previousId != firstItem: + currentPage.delete(0) + else: + hasPreviousId = false + # next + var nextId = currentPage[currentPage.len-1][newKey].getInt() + var hasNextId = true + if currentPage.len > display: + discard currentPage.pop() + else: + hasNextId = false + + return %*{ + "previousId": previousId, + "hasPreviousId": hasPreviousId, + "currentPage": currentPage, + "nextId": nextId, + "hasNextId": hasNextId + } else: - hasNextId = false - - return %*{ - "previousId": previousId, - "hasPreviousId": hasPreviousId, - "currentPage": currentPage, - "nextId": nextId, - "hasNextId": hasNextId - } + return %*{ + "previousId": 0, + "hasPreviousId": false, + "currentPage": currentPage, + "nextId": 0, + "hasNextId": false + } proc fastPaginateBack*(this:RDB, display:int, id:int, key="id", @@ -911,28 +950,37 @@ SELECT * FROM ( this.placeHolder &= this.placeHolder logger(this.sqlString, this.placeHolder) var currentPage = getAllRows(this.sqlString, this.placeHolder) - let newKey = if key.contains("."): key.split(".")[1] else: key - # next - let nextId = currentPage[0][newKey].getInt() - var hasNextId = true - if nextId != lastItem: - currentPage.delete(0) - else: - hasNextId = false - # previous - let previousId = currentPage[currentPage.len-1][newKey].getInt - var hasPreviousId = true - if currentPage.len > display: - discard currentPage.pop() - else: - hasPreviousId = false + if currentPage.len > 0: + let newKey = if key.contains("."): key.split(".")[1] else: key + # next + let nextId = currentPage[0][newKey].getInt() + var hasNextId = true + if nextId != lastItem: + currentPage.delete(0) + else: + hasNextId = false + # previous + let previousId = currentPage[currentPage.len-1][newKey].getInt + var hasPreviousId = true + if currentPage.len > display: + discard currentPage.pop() + else: + hasPreviousId = false - currentPage.reverse() + currentPage.reverse() - return %*{ - "previousId": previousId, - "hasPreviousId": hasPreviousId, - "currentPage": currentPage, - "nextId": nextId, - "hasNextId": hasNextId - } + return %*{ + "previousId": previousId, + "hasPreviousId": hasPreviousId, + "currentPage": currentPage, + "nextId": nextId, + "hasNextId": hasNextId + } + else: + return %*{ + "previousId": 0, + "hasPreviousId": false, + "currentPage": currentPage, + "nextId": 0, + "hasNextId": false + } diff --git a/src/allographer/query_builder/transaction.nim b/src/allographer/query_builder/transaction.nim index 31cd1a98..8e42b40c 100644 --- a/src/allographer/query_builder/transaction.nim +++ b/src/allographer/query_builder/transaction.nim @@ -1,5 +1,4 @@ import macros, strutils, strformat -import ../connection, base macro transaction*(bodyInput: untyped):untyped = diff --git a/src/allographer/schema_builder/alter.nim b/src/allographer/schema_builder/alter.nim index 10f0e0a5..329ef56c 100644 --- a/src/allographer/schema_builder/alter.nim +++ b/src/allographer/schema_builder/alter.nim @@ -1,10 +1,8 @@ -import json, strformat import ./table, ./column import ./alters/sqlite_alter, ./alters/mysql_alter, ./alters/postgres_alter -import ../utils import ../connection diff --git a/src/allographer/schema_builder/alters/mysql_alter.nim b/src/allographer/schema_builder/alters/mysql_alter.nim index db1e9c42..dcdc6bff 100644 --- a/src/allographer/schema_builder/alters/mysql_alter.nim +++ b/src/allographer/schema_builder/alters/mysql_alter.nim @@ -1,4 +1,4 @@ -import strformat, re, strutils +import strformat import ../table import ../column import ../migrates/mysql_migrate diff --git a/src/allographer/schema_builder/alters/sqlite_alter.nim b/src/allographer/schema_builder/alters/sqlite_alter.nim index b3f64048..e8710f3b 100644 --- a/src/allographer/schema_builder/alters/sqlite_alter.nim +++ b/src/allographer/schema_builder/alters/sqlite_alter.nim @@ -1,4 +1,4 @@ -import strformat, re, strutils +import strformat, re import ../table import ../column import ../migrates/sqlite_migrate diff --git a/tests/test_alter_table.nim b/tests/test_alter_table.nim index abf41019..0fd5b647 100644 --- a/tests/test_alter_table.nim +++ b/tests/test_alter_table.nim @@ -1,5 +1,5 @@ import unittest -import json, strformat +import json, strformat, options import ../src/allographer/schema_builder import ../src/allographer/query_builder @@ -44,7 +44,7 @@ rdb().table("table_drop").insert(table_drop_data) suite "alter table": test "add_column": - check rdb().table("table_alter").select("add_column").first() == newJNull() + check rdb().table("table_alter").select("add_column").first.isSome == false alter( table("table_alter", [ @@ -58,7 +58,7 @@ suite "alter table": .table("table_alter") .select("add_column") .orderBy("id", Asc) - .first()["add_column"] + .first.get["add_column"] .getStr == "test" test "changed_column": @@ -71,7 +71,7 @@ suite "alter table": .table("table_alter") .select("changed_column") .orderBy("id", Asc) - .first()["changed_column"] + .first.get["changed_column"] .getStr == "change1" alter( @@ -85,14 +85,14 @@ suite "alter table": .table("table_alter") .select("changed_column_success") .orderBy("id", Asc) - .first()["changed_column_success"] + .first.get["changed_column_success"] .getStr == "change1" check rdb() .table("table_alter") .select("changed_int_success") .orderBy("id", Asc) - .first()["changed_int_success"] + .first.get["changed_int_success"] .getInt == 1 test "delete_column": @@ -100,7 +100,7 @@ suite "alter table": .table("table_alter") .select("delete_column") .orderBy("id", Asc) - .first()["delete_column"].getStr == "delete1" + .first.get["delete_column"].getStr == "delete1" alter( table("table_alter", [ @@ -112,13 +112,13 @@ suite "alter table": .table("table_alter") .select("delete_column") .orderBy("id", Asc) - .first() == newJNull() + .first.isSome == false test "rename": check rdb() .table("table_rename") .orderBy("id", Asc) - .first()["id"] + .first.get["id"] .getInt == 1 alter(rename("table_rename", "table_rename_success")) @@ -126,14 +126,14 @@ suite "alter table": check rdb() .table("table_rename_success") .orderBy("id", Asc) - .first()["id"] + .first.get["id"] .getInt == 1 test "drop table": check rdb() .table("table_drop") .orderBy("id", Asc) - .first()["id"] + .first.get["id"] .getInt == 1 alter(drop("table_drop")) @@ -141,4 +141,4 @@ suite "alter table": check rdb() .table("table_drop") .orderBy("id", Asc) - .first() == newJNull() + .first.isSome == false diff --git a/tests/test_query.nim b/tests/test_query.nim index b1011d54..150b6048 100644 --- a/tests/test_query.nim +++ b/tests/test_query.nim @@ -1,4 +1,4 @@ -import unittest, json, strformat +import unittest, json, strformat, options import ../src/allographer/schema_builder import ../src/allographer/query_builder @@ -50,7 +50,7 @@ suite "select": check t[0] == @["1", "user1", "user1@gmail.com", "", "1"] test "first()": - var t = rdb().table("users").where("name", "=", "user1").first() + var t = rdb().table("users").where("name", "=", "user1").first.get check t == %*{"id": 1, "name": "user1", "email": "user1@gmail.com", "address":newJNull(), "auth_id": 1} test "firstPlain()": @@ -58,7 +58,7 @@ suite "select": check t == @["1", "user1", "user1@gmail.com", "", "1"] test "find()": - var t = rdb().table("users").find(1) + var t = rdb().table("users").find(1).get check t == %*{"id": 1, "name": "user1", "email": "user1@gmail.com", "address":newJNull(), "auth_id": 1} test "findPlain()": @@ -96,12 +96,12 @@ suite "select": test "update()": rdb().table("users").where("id", "=", 2).update(%*{"name": "John"}) - var t = rdb().table("users").find(2) + var t = rdb().table("users").find(2).get check t["name"].getStr() == "John" test "insertID()": var id = rdb().table("users").insertID(%*{"name": "John"}) - var t = rdb().table("users").find(id) + var t = rdb().table("users").find(id).get check t["name"].getStr() == "John" test "insertsID()": @@ -109,9 +109,9 @@ suite "select": %*{"name": "John"}, %*{"email": "Paul@gmail.com"}, ]) - var t = rdb().table("users").find(ids[0]) + var t = rdb().table("users").find(ids[0]).get check t["name"].getStr() == "John" - t = rdb().table("users").find(ids[1]) + t = rdb().table("users").find(ids[1]).get check t["email"].getStr() == "Paul@gmail.com" test "distinct": @@ -229,14 +229,14 @@ suite "select": check t[0]["auth_id"] == newJNull() test "result is null": - check newJNull() == rdb().table("users").find(50) + check rdb().table("users").find(50).isSome == false check newSeq[JsonNode](0) == rdb().table("users").where("id", "=", 50).get() test "delete": echo rdb().table("users").get() rdb().table("users").delete(1) - check rdb().table("users").find(1) == newJNull() + check rdb().table("users").find(1).isSome == false test "delete with where": rdb().table("users").where("name", "=", "user2").delete() - check rdb().table("users").find(2) == newJNull() + check rdb().table("users").find(2).isSome == false diff --git a/tests/test_query_aggregates.nim b/tests/test_query_aggregates.nim index 336f2509..6b95dcb2 100644 --- a/tests/test_query_aggregates.nim +++ b/tests/test_query_aggregates.nim @@ -1,4 +1,4 @@ -import unittest, json, strformat +import unittest, json, strformat, options import ../src/allographer/query_builder import ../src/allographer/schema_builder @@ -31,27 +31,27 @@ suite "aggregates": check t == 10 test "max()": - var t = rdb().table("users").max("name") + var t = rdb().table("users").max("name").get echo t check t == "user9" - var t2 = rdb().table("users").max("id") + var t2 = rdb().table("users").max("id").get echo t2 check t2 == "10" test "min()": - var t = rdb().table("users").min("name") + var t = rdb().table("users").min("name").get echo t check t == "user1" - var t2 = rdb().table("users").min("id") + var t2 = rdb().table("users").min("id").get echo t2 check t2 == "1" test "avg()": - var t = rdb().table("users").avg("id") + var t = rdb().table("users").avg("id").get echo t check t == 5.5 test "sum()": - var t = rdb().table("users").sum("id") + var t = rdb().table("users").sum("id").get echo t - check t == 55.0 \ No newline at end of file + check t == 55.0 diff --git a/tests/test_query_return_type.nim b/tests/test_query_return_type.nim index 3f714790..ee93ec4a 100644 --- a/tests/test_query_return_type.nim +++ b/tests/test_query_return_type.nim @@ -41,11 +41,11 @@ proc checkTest(t:Typ, r:Typ) = check t.bool == r.bool proc checkTestOptions(t:Typ, r:Option[Typ]) = - check t.id == r.get().id - check t.name == r.get().name - check t.birth_date == r.get().birth_date - check t.null == r.get().null - check t.bool == r.get().bool + check t.id == r.get.id + check t.name == r.get.name + check t.birth_date == r.get.birth_date + check t.null == r.get.null + check t.bool == r.get.bool suite "return with type": test "get": diff --git a/tests/test_transaction.nim b/tests/test_transaction.nim index f1069425..5cb8cf61 100644 --- a/tests/test_transaction.nim +++ b/tests/test_transaction.nim @@ -1,4 +1,4 @@ -import unittest, json, strformat +import unittest, json, strformat, options import ../src/allographer/schema_builder import ../src/allographer/query_builder @@ -47,10 +47,10 @@ suite "transaction": test "in transaction": transaction: - var user= rdb().table("users").select("id").where("name", "=", "user3").first() + var user= rdb().table("users").select("id").where("name", "=", "user3").first.get var id = user["id"].getInt() echo id - user = rdb().table("users").select("name", "email").find(id) + user = rdb().table("users").select("name", "email").find(id).get echo user test "rollback success":