Database
Jazzy includes a powerful, fluent Query Builder that allows you to interact with your database without writing raw SQL. It allows you to switch underlying databases with minimal code changes (currently optimized for SQLite).
Connecting
In your app.nim or database.nim module:
import jazzy
connectDB("app.db")Retrieving Data
Fetching All Rows
let users = DB.table("users").get()# Returns a JsonNode (JArray) of objectsFetching a Single Row
let user = DB.table("users").where("id", 1).first()# Returns a JsonNode (JObject) or JNull if not foundSelecting Specific Columns
By default, get() returns all columns (SELECT *). You can specify which columns you want:
let user = DB.table("users").select("name", "email").first()# Only "name" and "email" keys will exist in the result JsonNodeWhere Clauses
Fluid chaining makes complex queries easy.
DB.table("posts").where("published", 1)Comparison Operators:
DB.table("users").where("age", ">=", 18)DB.table("products").where("price", "<", 100)DB.table("status", "!=", "deleted")Chaining (AND logic):
Multiple calls are treated as AND conditions.
DB.table("users") .where("active", 1) .where("role", "admin") .get()# SELECT * FROM users WHERE active = 1 AND role = 'admin'Ordering and Sorting
You can sort your results using orderBy.
# Sort users by age in descending orderlet users = DB.table("users").orderBy("age", "DESC").get()
# Default direction is ASC (ascending)let recentPosts = DB.table("posts").orderBy("created_at").get()Counting Records
let totalUsers = DB.table("users").count()let activeUsers = DB.table("users").where("active", 1).count()Pagination (Limit & Offset)
Limit the number of results returned or skip a certain number of records.
# Get the top 10 recent postslet posts = DB.table("posts").limit(10).get()
# Pagination: Skip 20 posts and get the next 10let page3 = DB.table("posts").limit(10).offset(20).get()Modifying Data
Inserts
To insert data, pass a JsonNode (%*). Returns the ID of the newly inserted row.
let newUserId = DB.table("users").insert(%*{ "username": "caner", "email": "jcanermastan@gmail.com"})Note: If your table has
created_atorupdated_atcolumns, Jazzy will automatically populate them with the current UTC timestamp.
Updates
Updates affect all rows matching the where clause.
# Deactivate user #5DB.table("users") .where("id", 5) .update(%*{"active": 0})Note: If your table has an
updated_atcolumn, Jazzy will automatically update its value.
Deletes
Deletes all rows matching the where clause.
DB.table("users").where("id", 5).delete()Warning: Calling
delete()without awhereclause will wipe the table!
Soft Deletes
When a table supports Soft Deletes, records are not actually removed from the database. Instead, a deleted_at timestamp is set.
Supporting Soft Deletes
In your schema definition:
createTable("posts") .increments("id") .string("title") .softDeletes() # Adds deleted_at column .execute()Querying with Soft Deletes
By default, soft-deleted records are excluded from all queries.
# Only returns active (non-deleted) postslet posts = DB.table("posts").get()
# Include deleted recordslet allPosts = DB.table("posts").withTrashed().get()
# Only retrieve deleted recordslet trash = DB.table("posts").onlyTrashed().get()Restoring & Forcing
# Restore a deleted recordDB.table("posts").where("id", 1).restore()
# Permanently delete a recordDB.table("posts").where("id", 1).forceDelete()Raw SQL
For complex queries (JOINs, subqueries) that the Query Builder doesn’t yet support, you can use the raw() and rawExec() methods.
Fetching Data (raw)
The raw() method is used for data-returning queries (like SELECT or PRAGMA). It returns a JSON array of rows.
let res = DB.raw("SELECT name, age FROM users WHERE id = ?", 1)Executing Statements (rawExec)
The rawExec() method is used for statements that modify data (INSERT, UPDATE, DELETE). It returns the number of affected rows.
let affected = DB.rawExec("UPDATE users SET age = ? WHERE name = ?", 30, "Alice")