diff --git a/changelog.md b/changelog.md index 8de7469c..8086de22 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,11 @@ - [d]—docs improvement +## 2.8.5 (December 25, 2024) + +- [+] Add `select` and `selectAll` procs that don't require object instances and accept types instead (see [#176](https://github.com/moigagoo/norm/pull/176)). + + ## 2.8.4 (December 24, 2024) - [f] Fix connection pool creation for Nim 2.2.0 (see [#206](https://github.com/moigagoo/norm/pull/206)). diff --git a/src/norm/postgres.nim b/src/norm/postgres.nim index 8f8cb132..ad0f8cd2 100644 --- a/src/norm/postgres.nim +++ b/src/norm/postgres.nim @@ -289,6 +289,15 @@ proc select*[T: Model](dbConn; objs: var seq[T], cond: string, params: varargs[D for i, row in rows: objs[i].fromRow(row) +proc select*[T: Model](dbConn; typ: typedesc[T], cond: string, params: varargs[DbValue, dbValue]): seq[T] {.raises: {ValueError, DbError, LoggingError}.} = + ##[ Populate a sequence of `Model`_ instances from DB. + + ``typ`` is a `Model`_ subtype to contain the values. + ]## + + result.add(new T) + select(dbConn, result, cond, params) + proc selectAll*[T: Model](dbConn; objs: var seq[T]) = ##[ Populate a sequence of `Model`_ instances from DB, fetching all rows in the matching table. @@ -299,6 +308,17 @@ proc selectAll*[T: Model](dbConn; objs: var seq[T]) = dbConn.select(objs, "TRUE") +proc selectAll*[T: Model](dbConn; typ: typedesc[T]): seq[T] = + ##[ Populate a sequence of `Model`_ instances from DB, fetching all rows in the matching table. + + ``typ`` is a `Model`_ subtype to contain the values. + + **Warning:** this is a dangerous operation because you don't control how many rows will be fetched. + ]## + + result.add(new T) + selectAll(dbConn, result) + proc rawSelect*[T: ref object](dbConn; qry: string, obj: var T, params: varargs[DbValue, dbValue]) {.raises: {ValueError, DbError, LoggingError}.} = ##[ Populate a ref object instance ``obj`` and its ref object fields from DB. diff --git a/src/norm/sqlite.nim b/src/norm/sqlite.nim index a7299c76..002f469a 100644 --- a/src/norm/sqlite.nim +++ b/src/norm/sqlite.nim @@ -260,6 +260,15 @@ proc select*[T: Model](dbConn; objs: var seq[T], cond: string, params: varargs[D for i, row in rows: objs[i].fromRow(row) +proc select*[T: Model](dbConn; typ: typedesc[T], cond: string, params: varargs[DbValue, dbValue]): seq[T] {.raises: {ValueError, DbError, LoggingError}.} = + ##[ Populate a sequence of `Model`_ instances from DB. + + ``typ`` is a `Model`_ subtype to contain the values. + ]## + + result.add(new T) + select(dbConn, result, cond, params) + proc selectAll*[T: Model](dbConn; objs: var seq[T]) = ##[ Populate a sequence of `Model`_ instances from DB, fetching all rows in the matching table. @@ -270,6 +279,17 @@ proc selectAll*[T: Model](dbConn; objs: var seq[T]) = dbConn.select(objs, "1") +proc selectAll*[T: Model](dbConn; typ: typedesc[T]): seq[T] = + ##[ Populate a sequence of `Model`_ instances from DB, fetching all rows in the matching table. + + ``typ`` is a `Model`_ subtype to contain the values. + + **Warning:** this is a dangerous operation because you don't control how many rows will be fetched. + ]## + + result.add(new T) + selectAll(dbConn, result) + proc rawSelect*[T: ref object](dbConn; qry: string, obj: var T, params: varargs[DbValue, dbValue]) {.raises: {ValueError, DbError, LoggingError}.} = ##[ Populate a ref object instance ``obj`` and its ref object fields from DB. diff --git a/tests/postgres/trows.nim b/tests/postgres/trows.nim index e4dc124b..74bc89a5 100644 --- a/tests/postgres/trows.nim +++ b/tests/postgres/trows.nim @@ -172,13 +172,21 @@ suite "Row CRUD": inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] outToys = @[newToy()] - for inpToy in inpToys.mitems: - dbConn.insert(inpToy) + dbConn.insert(inpToys) dbConn.selectAll(outToys) check outToys === inpToys + test "Get all rows, implicit object instantiation": + var inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] + + dbConn.insert(inpToys) + + let outToys = dbConn.selectAll(Toy) + + check outToys === inpToys + test "Get rows, no intermediate objects": let inpToys = @[ @@ -191,6 +199,16 @@ suite "Row CRUD": check outToys === inpToys[..1] + test "Get rows, implicit object instantiation": + var + inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] + + dbConn.insert(inpToys) + + let outToys = dbConn.select(Toy, "price > $1", 100.00) + + check outToys === inpToys[0..1] + test "Get rows, nested models": var inpPersons = @[ @@ -284,4 +302,4 @@ suite "Row CRUD": dbConn.insert(cat) expect DBError: - dbConn.delete(toy) \ No newline at end of file + dbConn.delete(toy) diff --git a/tests/sqlite/trows.nim b/tests/sqlite/trows.nim index c2830475..92f33815 100644 --- a/tests/sqlite/trows.nim +++ b/tests/sqlite/trows.nim @@ -163,13 +163,21 @@ suite "Row CRUD": inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] outToys = @[newToy()] - for inpToy in inpToys.mitems: - dbConn.insert(inpToy) + dbConn.insert(inpToys) dbConn.selectAll(outToys) check outToys === inpToys + test "Get all rows, implicit object instantiation": + var inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] + + dbConn.insert(inpToys) + + let outToys = dbConn.selectAll(Toy) + + check outToys === inpToys + test "Get rows, no intermediate objects": let inpToys = @[ @@ -182,6 +190,16 @@ suite "Row CRUD": check outToys === inpToys[0..1] + test "Get rows, implicit object instantiation": + var + inpToys = @[newToy(123.45), newToy(456.78), newToy(99.99)] + + dbConn.insert(inpToys) + + let outToys = dbConn.select(Toy, "price > ?", 100.00) + + check outToys === inpToys[0..1] + test "Get rows, nested models": var inpPersons = @[ @@ -275,4 +293,4 @@ suite "Row CRUD": dbConn.insert(cat) expect DBError: - dbConn.delete(toy) \ No newline at end of file + dbConn.delete(toy)