The Nim [Row][nim-row] implementation only supports positional
identification of columns. In other words, there is nothing to tell us
which column is in which position. Because of this, we always create SQL
statements which explicitly name the columns we wish to receive so that
we know the order of columns and can rebuild models appropriately.
`createRule` wasn't doing this but naively using `RETURNING *`. This
still works as long as the field ordering in the Nim model class match
the default column ordering returned by the database, but confuses
columns otherwise. This fixes that by specifying explicitly the column
ordering as we do in other places.
[nim-row]: https://nim-lang.org/docs/db_postgres.html#Row
The previous implementation expected to work with a context object that
contained a field `conn` that represented a valid database connection.
However, this required the caller to manage the connection's lifecycle
(close, renew, etc.). Now we expect to receive a context object that
provides a `withConn` procedure or template that accepts a statement
block and provides a `conn` variable to that code block. For example:
createRecord(db: DbContext): Record =
# withConn must be defined for DbContext
db.withConn:
# conn must be injected into the statement block context
conn.exec(sql("INSERT INTO..."))
In addition, this change provides a connection pooling mechanism
(`DbConnPool`) as a default implementation for this hypothetical
DbContext. There is also a new function `initPool` that will create an
DbConnPool instance.
Callers of this library can modify their DbContext objects to extend
DbConnPool or simply be a type alias of DbConnPool.