Let's create some tables and examine the queries generated by Norm.
In the inim session, enter this code:
import std / [options, logging] import norm / [model, sqlite] addHandler newConsoleLogger(fmtStr = "")
logging allows you to see the generated queries,
options is necessary to support
Model type to inherit your models from, and
norm/sqlite is the SQLite backend, which implements the actual SQL generation and conversion between Nim objects and SQL rows.
Then, define the types:
type User* = ref object of Model email*: string Customer* = ref object of Model name*: Option[string] user*: User
These are your models. It's a good habit to define init procs for your types, so let's do so:
func newUser*(email = ""): User = User(email: email) func newCustomer*(name = none string; user = newUser()): Customer = Customer(name: name, user: user)
Now, we are ready to open a connection to the database:
let dbConn* = open(":memory:", "", "", "")
And here is the actual table creation:
createTables proc takes a model instance and generates a table schema for it. For each of the instance's fields, a column is generated. If a field is itself a
Model, a foreign key is added.
Option fields are nullable, non-
Option ones are
Note that a single
createTables call generated two table schemas. That's because model
Customer refers to
User, and therefore its table can't be created without the table for
User existing beforehand. Norm makes sure all dependency tables are created before creating the one that
createTables was actually called with. That's why the proc is called
createTables and not
Make sure to instantiate models with
Model fields so that these fields are not
nil. Otherwise, Norm won't be able to create a table schema for them.
id column is created despite not being present in
User definition. That's because it's a special read-only field maintained automatically by Norm. It represents row id in the database. Do not define id field or manually update its value.