Skip to content

Instantly share code, notes, and snippets.

@moigagoo
Last active November 4, 2019 13:05
Show Gist options
  • Save moigagoo/23d48dc277192b5b6559c3d8ab0f9190 to your computer and use it in GitHub Desktop.
Save moigagoo/23d48dc277192b5b6559c3d8ab0f9190 to your computer and use it in GitHub Desktop.
diff --git a/changelog.md b/changelog.md
index 5dfd2f5..91cf0c9 100755
--- a/changelog.md
+++ b/changelog.md
@@ -14,6 +14,7 @@
- [+] Add `createTable` and `dropTable`.
- [+] SQLite: Add means to write migrations: `addColumn`, `dropUnusedColumns`, `renameColumnFrom`, and `renameTableFrom`.
- [+] PostgreSQL: Add means to writemigrations: `addColumn`, `dropColumns`, `dropUnusedColumns`, `renameColumnFrom`, and `renameTableFrom`.
+- [+] Add `getAll` template to get all records without limit or offset.
- [r] Rewrite table schema generation so that schemas are generated from typed nodes rather than untyped modes.
- [f] Fixed "unreachable statement" compile error for certain SQLite use cases.
diff --git a/src/norm/postgres.nim b/src/norm/postgres.nim
index ea19314..2c394b9 100755
--- a/src/norm/postgres.nim
+++ b/src/norm/postgres.nim
@@ -252,32 +252,26 @@ template genWithDb(connection, user, password, database: string, dbTypeNames: op
result.setLen limit
result.getMany(limit, offset, cond, params)
- proc getAll(objs: var seq[object], cond = "TRUE", params: varargs[DbValue, dbValue]) {.used.} =
- ##[ Read all records from DB into an existing open array of objects.
- This is a dangerous operation as you don't control the amount of data received.
+ template getAll(T: typedesc, cond = "TRUE", params: varargs[DbValue, dbValue]): seq[T] {.used.} =
+ ##[ Read all records from DB into a sequence of objects, create the sequence on the fly.
Filter using ``cond`` condition.
+
+ Warning! This is a dangerous operation since you don't control the amount of data received. Consider using ``getMany`` for more deterministic data retrieval.
]##
- let getAllQuery = genGetAllQuery(objs[0], cond)
+ let getAllQuery = genGetAllQuery(T, cond)
debug getAllQuery, " <- ", params.join(", ")
let rows = dbConn.getAllRows(getAllQuery, params)
- objs.setLen rows.len
+ var objs: seq[T]
+ objs.setLen len(rows)
rows.to(objs)
- proc getAll(T: typedesc, cond = "TRUE", params: varargs[DbValue, dbValue]): seq[T] {.used.} =
- ##[ Read all records from DB into a sequence of objects, create the sequence on the fly.
- This is a dangerous operation as you don't control the amount of data received.
-
- Filter using ``cond`` condition.
- ]##
-
- result.setLen 1
- result.getAll(cond, params)
+ objs
template update(obj: object, force = false) {.used.} =
##[ Update DB record with object field values.
diff --git a/src/norm/postgres/sqlgen.nim b/src/norm/postgres/sqlgen.nim
index b988700..2366c89 100644
--- a/src/norm/postgres/sqlgen.nim
+++ b/src/norm/postgres/sqlgen.nim
@@ -232,12 +232,10 @@ proc genGetManyQuery*(obj: object, condition: string, paramCount = 0): SqlQuery
$(paramCount+2)
]
-proc genGetAllQuery*(obj: object, condition: string): SqlQuery =
+template genGetAllQuery*(T: typedesc, condition: string): SqlQuery =
## Generate ``SELECT`` query to fetch all records for an object.
- sql "SELECT $# FROM $# WHERE $#" % [obj.getColumns(force=true).join(", "),
- type(obj).getTable(), condition]
-
+ sql "SELECT $# FROM $# WHERE $#" % [T.getColumns(force=true).join(", "), T.getTable(), condition]
proc genUpdateQuery*(obj: object, force: bool): SqlQuery =
## Generate ``UPDATE`` query for an object.
diff --git a/src/norm/sqlite.nim b/src/norm/sqlite.nim
index a48a3ea..fcfd633 100755
--- a/src/norm/sqlite.nim
+++ b/src/norm/sqlite.nim
@@ -252,32 +252,26 @@ template genWithDb(connection, user, password, database: string, dbTypeNames: op
result.setLen limit
result.getMany(limit, offset, cond, params)
- proc getAll(objs: var seq[object], cond = "1", params: varargs[DbValue, dbValue]) {.used.} =
- ##[ Read all records from DB into an existing open array of objects.
- This is a dangerous operation as you don't control the amount of data received.
+ template getAll(T: typedesc, cond = "1", params: varargs[DbValue, dbValue]): seq[T] {.used.} =
+ ##[ Read all records from DB into a sequence of objects, create the sequence on the fly.
Filter using ``cond`` condition.
+
+ Warning! This is a dangerous operation since you don't control the amount of data received. Consider using ``getMany`` for more deterministic data retrieval.
]##
- let getAllQuery = genGetAllQuery(objs[0], cond)
+ let getAllQuery = genGetAllQuery(T, cond)
debug getAllQuery, " <- ", params.join(", ")
let rows = dbConn.getAllRows(getAllQuery, params)
- objs.setLen rows.len
+ var objs: seq[T]
+ objs.setLen len(rows)
rows.to(objs)
- proc getAll(T: typedesc, cond = "1", params: varargs[DbValue, dbValue]): seq[T] {.used.} =
- ##[ Read all records from DB into a sequence of objects, create the sequence on the fly.
- This is a dangerous operation as you don't control the amount of data received.
-
- Filter using ``cond`` condition.
- ]##
-
- result.setLen 1
- result.getAll(cond, params)
+ objs
template update(obj: object, force = false) {.used.} =
##[ Update DB record with object field values.
diff --git a/src/norm/sqlite/sqlgen.nim b/src/norm/sqlite/sqlgen.nim
index 8c0719d..e756ab8 100644
--- a/src/norm/sqlite/sqlgen.nim
+++ b/src/norm/sqlite/sqlgen.nim
@@ -217,11 +217,10 @@ proc genGetManyQuery*(obj: object, condition: string): SqlQuery =
sql "SELECT $# FROM $# WHERE $# LIMIT ? OFFSET ?" % [obj.getColumns(force=true).join(", "),
type(obj).getTable(), condition]
-proc genGetAllQuery*(obj: object, condition: string): SqlQuery =
+template genGetAllQuery*(T: typedesc, condition: string): SqlQuery =
## Generate ``SELECT`` query to fetch all records for an object.
- sql "SELECT $# FROM $# WHERE $#" % [obj.getColumns(force=true).join(", "),
- type(obj).getTable(), condition]
+ sql "SELECT $# FROM $# WHERE $#" % [T.getColumns(force=true).join(", "), T.getTable(), condition]
proc genUpdateQuery*(obj: object, force: bool): SqlQuery =
## Generate ``UPDATE`` query for an object.
diff --git a/tests/tpostgres.nim b/tests/tpostgres.nim
index f921e21..5c6272f 100644
--- a/tests/tpostgres.nim
+++ b/tests/tpostgres.nim
@@ -173,6 +173,18 @@ suite "Creating and dropping tables, CRUD":
expect KeyError:
let notExistingBook {.used.} = Book.getOne("title = $1", "Does not exist")
+ withDb:
+ let
+ allBooks = Book.getAll()
+ someBooks = Book.getAll(cond="title IN ($1, $2) ORDER BY title DESC",
+ params=[?"Book 1", ?"Book 5"])
+
+ check len(allBooks) == 9
+
+ check len(someBooks) == 2
+ check someBooks[0].title == "Book 5"
+ check someBooks[1].authorEmail == "test-1@example.com"
+
test "Update records":
withDb:
var
diff --git a/tests/tsqlite.nim b/tests/tsqlite.nim
index 19cac8b..ccfd92a 100644
--- a/tests/tsqlite.nim
+++ b/tests/tsqlite.nim
@@ -191,6 +191,18 @@ suite "Creating and dropping tables, CRUD":
expect KeyError:
let notExistingBook {.used.} = Book.getOne("title=?", "Does not exist")
+ withDb:
+ let
+ allBooks = Book.getAll()
+ someBooks = Book.getAll(cond="title IN (?, ?) ORDER BY title DESC",
+ params=[?"Book 1", ?"Book 5"])
+
+ check len(allBooks) == 9
+
+ check len(someBooks) == 2
+ check someBooks[0].title == "Book 5"
+ check someBooks[1].authorEmail == "test-1@example.com"
+
test "Update records":
withDb:
var
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment