More complex queries

Norm allows you to sort, limit use subqueries for complex where clauses and more. To understand how, it helps to keep in mind that norm essentially generates SQL SELECT queries after the following pattern: SELECT <fields of model> FROM <table-name specified by model> WHERE <condition>

This means that whatever pieces of SQL come after the WHERE keyword are thing you can freely specify if need be.

Limiting the number of queried models

To limit the number of queried models, simply use SQL's Limit keyword.

Lets query our Customer table from earlier and query multiple entries, but only take the first entry.

var
  userFoo = newUser("foo@foo.foo")
  alice = newCustomer(some "Alice", userFoo)
  bob = newCustomer(some "Bob", userFoo)
with dbConn:
  insert userFoo
  insert alice
  insert bob

var customersFoo = @[newCustomer()]
dbConn.select(customersFoo, "User.email = ? LIMIT 1", "foo@foo.foo")

assert customersFoo.len() == 1

echo()
INSERT INTO "User" (email) VALUES(?) <- @['foo@foo.foo']
Object ID is not 0, skipping insertion. Type: User, ID: 1
INSERT INTO "Customer" (name, user) VALUES(?, ?) <- @['Alice', 1]
Object ID is not 0, skipping insertion. Type: User, ID: 1
INSERT INTO "Customer" (name, user) VALUES(?, ?) <- @['Bob', 1]
SELECT "Customer".name, "Customer".user, "user".email, "user".id, "Customer".id FROM "Customer" LEFT JOIN "User" AS "user" ON "Customer".user = "user".id WHERE User.email = ? LIMIT 1 <- ['foo@foo.foo']

customersFoo has only 1 entry, despite alice and bob both having the email address "foo@foo.foo", thanks to the LIMIT SQL keyword.

Sorting model output

We can of course use ORDER BY just as we did LIMIT before:

var sortedCustomersFoo = @[newCustomer()]
dbConn.select(sortedCustomersFoo, "User.email = ? ORDER BY name DESC", "foo@foo.foo")

assert sortedCustomersFoo[0].name.get() == "Bob"
assert sortedCustomersFoo[1].name.get() == "Alice"

echo()
SELECT "Customer".name, "Customer".user, "user".email, "user".id, "Customer".id FROM "Customer" LEFT JOIN "User" AS "user" ON "Customer".user = "user".id WHERE User.email = ? ORDER BY name DESC <- ['foo@foo.foo']

Using Subqueries

Similarly as to ORDER BY, you can also use subqueries within the WHERE block:

var subqueryCustomersFoo = @[newCustomer()]
const condition = """
    Customer.id IN (SELECT Cust.id FROM Customer AS Cust WHERE Cust.id % 2 == 0)
  """
dbConn.select(subqueryCustomersFoo, condition)
assert subqueryCustomersFoo.len() == 1
assert subqueryCustomersFoo[0].id == 2

echo()
SELECT "Customer".name, "Customer".user, "user".email, "user".id, "Customer".id FROM "Customer" LEFT JOIN "User" AS "user" ON "Customer".user = "user".id WHERE     Customer.id IN (SELECT Cust.id FROM Customer AS Cust WHERE Cust.id % 2 == 0)
   <- []