Changelog
- [!]—backward incompatible change
- [+]—new feature
- [f]—bugfix
- [r]—refactoring
- [t]—test suite improvement
- [d]—docs improvement
2.8.7 (March 19, 2025)
- [f] SQLite backend doesn't require PostgreSQL driver any more (see #210).
- [t] Split images for SQLite and PostreSQL tests.
2.8.6 (January 25, 2025)
- [f] Fix closure support for
getDbproc parameter ofnewPool
2.8.5 (December 25, 2024)
- [+] Add
selectandselectAllprocs that don't require object instances and accept types instead (see #176).
2.8.4 (December 24, 2024)
- [f] Fix connection pool creation for Nim 2.2.0 (see #206).
- [d] Update the docs in the code for the improved docgen in Nim 2.2.0.
2.8.3 (July 5, 2024)
- [f] Make creating indices idempotent (see #203).
2.8.2 (January 30, 2024)
- [+] PostgreSQL: Add the ability to set custom schema name for models (see #202).
2.8.1 (August 11, 2023)
- [f] version bump lowdb to fix failed import of db_connector on nim 2.0.0
2.8.0 (April 5, 2023)
- [+] Bulk update is now performed in a single query which speeds up execution 1000 times (see #188).
- [+] Enum Support (see #166).
2.7.0 (February 27, 2023)
- [+] Norm is not Nim 2.0 compatible (see #182).
- [f] DB interactions are now GC-safe (see #167).
- [r] ndb dependency has been replaced with lowdb.
- [r] Improve exception tracking accuracy.
- [t] Tons of improvements with regard to GitHub Actions and nimble tasks to run the test suite.
2.6.2 (February 9, 2023)
- [+] Add
LIMIT 1to the single object variant ofselectproc to make selection faster. - [f] Add
PRAGMA foreign_keys=onto sqlite connections upon creation, for both the pool and when usinggetDb.
2.6.1 (December 12, 2022)
- [+] Add the ability to create indexes for tables (see #180).
2.6.0 (October 18, 2022)
- [+] App connection pool (see #50).
2.5.2 (September 14, 2022)
- [+] Added
rawSelectproc, which allows you execute raw SQL and have the output be parsed into a custom object-type. - [+]
insertwithobj.id != 0andforce=truenow uses the id provided. For PostgreSQL, this means adding conflictPolicy withON CONFLICT DO...clause. - [r] Logging: refactored
logmodule to not trigger warnings whennormDebugis not defined. - [r] Slightly changed how objects are being parsed, leading to a small performance increase.
2.5.1 (July 20, 2022)
- [+] Added
uniqueGrouppragma to provide UNIQUE constraint on multiple columns (see #136). - [+] Add
readOnlyalias forropragma (see #128). - [f] Fixed further points where compile-time assertions created unused variables.
- [f] Fixed
selectOneToManyandselectManyToManythat were introduced in 2.5.1 being unable to deal with FK fields that were Optionals or directly ids. - [t] Enable deepCopy for tests to prepare for the
--mm:arc|orcswitch in Nim 2.0.
2.5.0 (July 8, 2022)
- [+] Added
selectOneToManyproc overload that is able to query multiple many-to-one relationships at once (see #142). - [+] Added
selectManyToManyproc overload that is able to query multiple many-to-many relationships at once (see #142). - [d] Added small hint that placeholders in postgres is done via
$1,S2... etc. - [d] Added links to norman, example app, the API index and these nimibook docs.
2.4.1 (Jun 23, 2022)
- [r] Replaced pointless variable assignments at compile time with
static discard. - [r] Improved error message you receive when using
selectManyToManywith an invalid joinModel.
2.4.0 (March 7, 2022)
- [+] Added
selectOneToManyproc to query many-to-one relationships (see #127) - [+] Added
selectManyToManyproc to query many-to-many relationships (see #127)
2.3.7 (February 22, 2022)
- [f] Fix tests for self-ref foreign keys.
- [t] Run tests of PRs.
2.3.6 (February 22, 2022)
- [f] Fix generic models for Nim <= 1.6.4. The same fix has been merged in
std/macros, in the devel branch of the compiler but will not be backported to 1.6 (see #132). - [f] Fix self-referencing optional foreign key, handled manually through
fkpragmas (see #137 ).
2.3.5 (January 17, 2022)
- [+] Add
sumproc to calculate column value sum.
2.3.4 (January 16, 2022)
- [+] Add the ability to define read-only models (see #125).
- [+] Add
existsproc to check if a row exists (see #115). - [r] Remove
nimibookfrom dependencies to speed up package builds.
2.3.3 (December 26, 2021)
- [+] SQLite: Add
conflictPolicyparam toinsertprocs. It determines how insertion conflicts should be handled:cpRaise(default) means raise anDbError,cpIgnoremeans keep the old row and ignore the new one, andcpReplacemeans replace the old row (see #120).
2.3.2 (November 19, 2021)
- [+] Add
norm.model.fColfunc variant that works with typedescs. NowfColfunc variants are symmetrical tocol. - [+] Add
tableNamepragma to specify custom table name for model (see #117). - [f] Add missing exceptions to
selectprocs (see #116).
2.3.1 (September 29, 2021)
- [r][d] Add
{.raises.}annotations toselectprocs to make it more explicit that they raise aNotFoundErrorif the requested row is not in the DB.
2.3.0 (April 8, 2021)
- [!][+] Objects with
id!= 0 are now not inserted multiple times by default. To force insertion, use explicitforce == trueparam. - [+] Add
countprocs to count rows without fetching them. - [t] Remove unused import from
sqlite/trows.nim.
2.2.5 (March 23, 2021)
- [+] Add
onDeletepragma that lets addON DELETEconstraints to foreign keys. - [r] Improve formatting of import statements: use
std/notation.
2.2.4 (March 21, 2021)
- [+]
NotFoundErrorexception is raised instead ofKeyErrorif a record is not found. - [f] Fix issue with objects with
none Modelfields failing to be used as containers to select records into (see #103). - [f] Allow objects to be inserted multiple times. The
idis updated with each insertion (see #104). - [t] Added tests for record not found case.
- [t] Added tests for
none Modelcontainer fields.
2.2.3 (February 20, 2021)
- [+]
idis nowint64instead ofintto produce a DB type in Postgres that doesn't depend on the processor architecture of a particular computer running the code. - [+] Add granular convertors for
int16,int32, andint64in Postgres. - [+] Add granular convertors for
float32andfloat64in Postgres. - [+] Add type
StringOfCap[static n]that is converted toVARCHAR(n)in Postgres. - [+] Add type
PaddedStringOfCap[static n]that is converted toCHAR(n)in Postgres. - [t] Remove redundant environment variable usage from
tdbtypestests.
2.2.2 (November 19, 2020)
- [f] Fix
ProveInitwarning.
2.2.1 (November 10, 2020)
-
[+] Added
fkpragma that allows to manually declare aSomeIntegerfield ofModelas a foreign key.Pragma value must be a
Model. The foreign key will reference the referenced model'sidfield. -
[t] Reorganized tests into folders.
-
[t] Switch from vanilla
nimble testto testament. -
[t] Added missing tests for
NULLforeign keys in Postgres. -
[t] Cleaned up redundant imports and consts.
2.2.0 (October 26, 2020)
- [!][f][t] The way
JOINstatements are generated has been changed competely. The previous algorithm was just wrong, it didn't work with models that that multiple FKs to the same model or when the same model was referenced from the root model and any of itsModelfields or theirModelfields.
Long story short, the old algorithm would rely on table names with no regard for whether the table is a foreign key. That means that, if you had the same table referenced with two different fields, the JOIN statement would make no difference between them, which led to invalid selections (see `#82).
The new algorithm adds alias for each joined table. The alias is named after the model field that points to the table. Compare tests/tmodel.nim before and after the change:
# Old way:
test "Join groups":
let
toy = newToy(123.45)
pet = newPet("cat", toy)
person = newPerson("Alice", pet)
check person. joinGroups == @[
(""""Pet"""", """"Person".pet""", """"Pet".id"""),
(""""Toy"""", """"Pet".favToy""", """"Toy".id""")
]
# produces the following `JOIN` statement:
# `JOIN "Pet" ON "Person".pet = "Pet".id JOIN "Toy" ON "Pet".favToy = "Toy".id`
# New way:
test "Join groups":
let
toy = newToy(123.45)
pet = newPet("cat", toy)
person = newPerson("Alice", pet)
check person.joinGroups == @[
(""""Pet"""", """"pet"""", """"Person".pet""", """"pet".id"""),
(""""Toy"""", """"pet_favToy"""", """"pet".favToy""", """"pet_favToy".id""")
]
# produces the following `JOIN` statement:
# `JOIN "Pet" AS "pet" ON "Person".pet = "pet".id JOIN "Toy" AS "pet_favToy" ON "pet".favToy = "pet_favToy".id`
With the change in the algorithm, the way select conditions must be composed has changed. Here's an example from the tests to illustrate this change (tests/tpostgresrows.nim):
# Old way:
test "Get rows, nested models":
var
inpPersons = @[
newPerson("Alice", newPet("cat", newToy(123.45))),
newPerson("Bob", newPet("dog", newToy(456.78))),
newPerson("Charlie", newPet("frog", newToy(99.99))),
]
outPersons = @[newPerson()]
for inpPerson in inpPersons.mitems:
dbConn.insert(inpPerson)
# We're querying by `"Toy".price` as if it weren't `favToy` field of `pet` field of `Person` model:
dbConn.select(outPersons, """"Toy".price > $1""", 100.00)
check outPersons === inpPersons[0..^2]
# New way:
test "Get rows, nested models":
var
inpPersons = @[
newPerson("Alice", newPet("cat", newToy(123.45))),
newPerson("Bob", newPet("dog", newToy(456.78))),
newPerson("Charlie", newPet("frog", newToy(99.99))),
]
outPersons = @[newPerson()]
for inpPerson in inpPersons.mitems:
dbConn.insert(inpPerson)
# Querying by `"pet_favToy".price` to indicate that we want to match specifically by `Person.pet.favToy`:
dbConn.select(outPersons, """"pet_favToy".price > $1""", 100.00)
check outPersons === inpPersons[0..^2]
-
[f][t] Fix #79.
NULLforeign keys are not omitted in selects anymore if the container objects issome Model. -
[+] Add
selectAllprocs to select all rows without condition (see #85). -
[r] Require Nim version >= 1.4.0.
-
[r] Update Nim version to 1.4.0 in Dockerfile.
-
[+] Hide logging behind
normDebugcompilation flag to improve runtime performance. -
[+] Add
uniquepragma to addUNIQUEconstaints to fields.
2.1.5 (September 8, 2020)
- [+] Export private
dbValue, andtoprocs in public modules.
2.1.4 (August 14, 2020)
- [+] Add
dropDbprocs.
2.1.3 (August 13, 2020)
- [f] Fix relation triangle with more deeply nested relations.
2.1.2 (August 12, 2020)
- [f] Fix
selectfor models that relate to two models that are related with each other as well.
2.1.1 (July 10, 2020)
- [r] Add missing docstrings for
getDbandwithDb.
2.1.0 (July 10, 2020)
- [+] Add
getDbandwithDbsugars to get DB configuration from environment variablesDB_HOST,DB_USER,DB_PASS, andDB_NAME.
2.0.1 (June 24, 2020)
- [f] Replace func with proc in dbtypes since
tocan have side effects.
2.0.0 (June 22, 2020)
Rewritten from scratch. Backward compatibility has been completely broken.
Most noticeable changes are:
- DB procs work only with model instances and never with model types.
- DB procs mutate objects in-place. To create new instances, use
dup. - Models are ref types instead of value types.
- Model objects are defined by being inherited from
Modeland not by being defined underdbblock. - DB procs now take database connection as the first argument.
- Foreign keys are created automatically.
- N+1 problem has been solved.
- Most pragmas are gone, resulting in less customizability but simpler API.
- Adding custom converters now means adding procs and not putting expressions in pragmas, which was very fragile.
1.1.3 (May 11, 2020)
- [f] Fix #69:
tablepragma is now respected as it should despite being deprecated.
1.1.2 (March 13, 2020)
- [f] Fix #63: foreign key boilerplate code is now correctly injected into exported type definitions.
1.1.1 (March 13, 2020)
-
[+] Add
insertIdproc that takes an immutable object and inserts it as a record to the DB. The inserted record ID is returned. The objectidfield is not updated. -
[+] Automatically generate foreign key boilerplate for models defined under the same
typesection. See examples in tests/tpostgres.nim and tests/tsqlite.nim.
1.1.0 (January 27, 2020)
-
[!] Deprecate
notNullpragma.NOT NULLis the default for all types exceptOption.To set
NOT NULLconstraint for custom DB types, add it directly todbType, e.g.{.dbType: "INTEGER NOT NULL".}. -
[!] Rename pragma
tabletodbTable. -
[!] Deprecate
defaultpragma. Default values are added to tables by default. -
[!][+] Rewrite PostgreSQL backend to use ndb_, which adds
NULLsupport viaOptiontype similarly to SQLite backend. -
[+] Add
transactionmacro to run multiple commands in a transaction androllbackproc to safely interrupt a transaction. -
[+] Add
createTableanddropTable. -
[+] SQLite: Add means to write migrations:
addColumn,dropUnusedColumns,renameColumnFrom, andrenameTableFrom. -
[+] PostgreSQL: Add means to write migrations:
addColumn,dropColumns,dropUnusedColumns,renameColumnFrom, andrenameTableFrom. -
[+] Add support for
int64field type. -
[+] Add
getAlltemplate 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] Fix "unreachable statement" compile error for certain SQLite use cases.
1.0.17 (September 12, 2019)
- [f] Fixed table schema generation for
PositiveandNaturaltypes: they used to be stored asTEXT, now they are stored asINTEGER. Also, fixed #28.
1.0.16 (September 11, 2019)
- [f] Added missing
strutilsexport to eliminateError: undeclared identifier: '%'and fix #27. - [r]
genTableSchemanow returnsSqlQueryinstead ofstringto be in line with the othergen*procs.
1.0.15 (September 06, 2019)
- [+] Add
dbTypesmacro to mark existing type sections to be usable in DB schema generation. - [+] Add
dbFromTypesmacro to define DB schema from existing types. This is an alternative to defining the entire schema underdbmacro. - [f] PostgreSQL:
times.Datetimeare now explicitly stored in UTC timezone. - [r] Move row-object conversion and SQL query generation into backend-specific submodules:
sqlite/rowutils.nim,sqlite/sqlgen.nim,postgres/rowutils.nim,postgres/sqlgen.nim. - [r] Move procs to inject
idfield in type definitions into a separate moduletypedefutils.nim.
1.0.14 (August 21, 2019)
- [+] PostgreSQL: Support
booltype. - [+] SQLite, PostgreSQL: Support
times.DateTimetype.
1.0.13 (August 16, 2019)
- [f] SQLite:
TEXTtype fields would be created forbooltype object fields, whereasINTEGERshould have been used.
1.0.12 (August 15, 2019)
- [!]
formatItexpression must evaluate toDbValue, implicit conversion has been removed. - [+] SQLite: Added boolean type conversion. Nim bools are stored as 1 and 0 in SQLite. SQLite's 0's are converted to
false, any other number—totrue.
1.0.11 (June 15, 2019)
- [!] SQLite: Switch to ndb_.
- [!] SQLite: Non-
Optionnon-custom types areNOT NULLby default. - [+] SQLite: Support inserting and retrieving
NULLvalues withOptiontypes. - [+] SQLite, PostgreSQL: Add
withCustomDbto run DB procs on a non-default DB (i.e. not the one defined indbdeclaration). - [r] Replace
typewithtypedescandtypeofwhere it is not a type definition.
1.0.10 (June 6, 2019)
- [r] Rename
getUpdateQuerytogenUpdateQuery. - [f] Fix compatibility with nim 0.20.0.
1.0.9 (May 9, 2019)
- [!] Change signatures for
getManyandgetOne: instead ofwhereandorderByargs there's a singlecondarg. - [+] Add
paramsarg togetManyandgetoneto allow safe value insertion in SQL queries. - [+] Add
getOne(cond: string, params: varargs[string, `$`])procs to query a single record by condition.
1.0.8 (April 30, 2019)
- [+] SQLite: Add
onUpdateandonDeletepragmas. - [+] SQLite: Add
uniquepragma. - [f] SQLite: Add support for multiple foreign keys.
- [f] SQLite: Enable foreign keys for all connections.
- [t] Add tests for multiple foreign keys.
1.0.7 (March 21, 2019)
- [+] Add
orderByargument togetManyprocs.
1.0.6 (March 21, 2019)
- [+] Log all generated SQL statements as debug level logs.
1.0.5 (March 18, 2019)
- [+] Do not require
chroniclespackage.
1.0.4 (March 3, 2019)
- [+] Add
wherelookup togetManyprocs.
1.0.3 (March 2, 2019)
- [r] objutils: Rename
[]field accessor todotto avoid collisions withtablesmodule.
1.0.2 (March 1, 2019)
- [!] Procs defined in
dbmacro are now passed as is to the resulting code and are not forced insidewithdbtemplate. - [+] Allow to override column names for fields with
dbColpragma.
1.0.1 (February 28, 2019)
- [+] Respect custom field parsers and formatters.
- [+] rowutils: respect
ropragma intoRowproc. - [+] objutils: respect
ropragma infieldnamesproc. - [t] Type conversion: fix issue with incorrect conversion of field named
name.
1.0.0 (February 27, 2019)
- 🎉 initial release.