Tables

Create Tables

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 Option fields, norm/model provides 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:

dbConn.createTables(newCustomer())
echo()
CREATE TABLE IF NOT EXISTS "User"(email TEXT NOT NULL, id INTEGER NOT NULL PRIMARY KEY)
CREATE TABLE IF NOT EXISTS "Customer"(name TEXT, user INTEGER NOT NULL, id INTEGER NOT NULL PRIMARY KEY, FOREIGN KEY(user) REFERENCES "User"(id))

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 NOT NULL.

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 createTable.

Caveats

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.

Note that 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.