Introduction
The QueryBuilder module allows you to compose database queries in a type-safe way. Below you can find a short reference to all the commonly-used functions.Retrieving Records
Querying Records
You can retrieve all records of a table usingquery:
SELECT * FROM users query and put a list of User structures.
Fetching a Single Record
When you have the id of a record, you can also usefetch to get it from the database:
SELECT * FROM users WHERE id = ... LIMIT 1.
fetch knows a single entity will be returned for the id, so instead of a list of users, a single user will be returned. In case the entity is not found, an exception is thrown. Use fetchOrNothing to get Nothing instead of an exception when no result is found.
Fetching a List of IDs
When have you a list of ids of a single record type, you can also justfetch them:
SELECT * FROM users WHERE id IN (...). The results in users have type [User].
Fetching a Maybe ID
Sometimes you have an optional id field, like e.g. when having a database schema like this:assigned_user_id can be null. In our action we want to fetch user when it’s not null, and return Nothing otherwise:
Maybe value.
Running Queries
You can run a query usingfetch, fetchOneOrNothing or fetchOne:
Many Rows: fetch
To run a query which will return many rows use fetch:
Maybe Single Row: fetchOneOrNothing
To run a query which will maybe return a single row use fetchOneOrNothing:
Single Row: fetchOne
To run a query which will return a single row and throw an error if no record is found use fetchOne:
Where Conditions
To specifyWHERE conditions, you can use filterWhere:
filterWhereNot to negate a condition:
filterWhere called filterWhereCaseInsensitive:
filterWhereSql:
Several other filter-functions for generating
WHERE clauses exist, such as filterWhereIn and filterWhereNotIn which take lists of items. Read more about these in the API docs on QueryBuilderLimiting and Offset
Fetching n Records (LIMIT)
Uselimit to query only up to n records from a table:
SELECT * FROM users ORDER BY firstname LIMIT 10 query and will return the first 10 users ordered by their firstname.
When you are only interested in the first result you can also use fetchOne as a shortcut for |> limit 1:
Skipping n Records (OFFSET)
Useoffset to skip n records from a table:
limit to implement paging.
Order By
You can just useorderBy #field:
orderBys work as expected:
Counting Records
You can usefetchCount instead of fetch to get the count of records matching the query:
Distinct Records
Usedistinct to fetch distinct records:
distinctOn #tableField to fetch distinct records based on the #tableField value:
Raw SQL Queries
The IHP query builder is designed to be able to easily express many basic sql queries. When your application is growing you will typically hit a point where a complex SQL query cannot be easily expressed with the IHP query builder. In that case it’s recommended to use handwritten SQL to access your data.For compile-time type-checked SQL queries, see the Typed SQL Guide. Typed SQL automatically infers Haskell types from your SQL at compile time, eliminating the need for manual
FromRow instances.sqlQuery to run a raw SQL query:
Dynamic Query Building
If you would like to have your query dynamically built with an argument you could:Fetching Single Columns
If you need to fetch only a single column, for example only the ID of a record, you need to help the compiler and type hint the result, with anOnly prefix. Here’s an example of fetching only the IDs of a project table, and converting them to Id Project:
Scalar Results
ThesqlQuery function always returns a list of rows as the result. When the result of your query is a single value (such as an integer or string) use sqlQueryScalar:
Dealing With Complex Query Results
Let’s say you’re querying posts and a count of comments on each post:id, title and comments_count but a Post record consists of id, title, body.
The solution here is to write our own data type and mapping code:
Query Shortcuts
findBy #field value
Just a shortcut for filterWhere (#field, value) |> fetchOne
findMaybeBy #field value
Just a shortcut for filterWhere (#field, value) |> fetchOneOrNothing
findManyBy #field value
Just a shortcut for filterWhere (#field, value) |> fetch
Create
Creating a Single Record
To insert a record into the database, callnewRecord to get an empty record value:
newRecord function does not insert the record, it just returns a new empty data structure we can fill with values and then insert into the database.
We can use set to fill in attributes:
createRecord to insert the above record into the users table:
Creating Many Records
You can usecreateMany to insert multiple records with a single INSERT statement:
Update
The functionupdateRecord runs an UPDATE query for a specific record:
lastname of user cf633b17-c409-4df5-a2fc-8c3b3d6c2ea7 to Tester and run an UPDATE query to persist that:
UPDATE query will only update columns that have been changed using |> set #someField someValue on the record.
Delete
Deleting a Single Record
UsedeleteRecord to run a simple DELETE query:
Deleting Many Records
UsedeleteRecords to run a DELETE query for multiple records:
Deleting All Records
UsedeleteAll to run a DELETE query for all rows in a table: