Explore the basics of integrating Haskell with databases using Persistent and Esqueleto. This quiz covers schema definitions, query construction, migration handling, and key features to help you confidently work with relational databases in Haskell applications.
Which of the following best represents how you define a database entity in Persistent using Haskell syntax?
Explanation: Persistent uses a quasi-quoted syntax where you list entities and their fields along with types in a distinct block. The other options suggest patterns or functions that do not exist in Persistent's standard setup: there’s no persistentEntity function or entityGenerator; defineEntity is also not used this way. Only the quasi-quoted block method aligns with Persistent’s entity definitions.
In Persistent, what does the selectList function typically return when called in a database action?
Explanation: The selectList function returns a list of database entities, each wrapped in the Entity type, which includes the key and the field values. It does not return SQL strings, a Maybe value, or perform IO file actions directly. The other choices either refer to incorrect return types or functionalities not provided by selectList.
How would you perform an SQL inner join between two tables using Esqueleto’s EDSL in Haskell?
Explanation: Esqueleto’s EDSL offers the innerJoin function, where you specify the join and its condition much like SQL's INNER JOIN. The other options misrepresent Esqueleto’s syntax or functions—selectAll and joinTables do not exist, and listing tables in FROM without conditions does not specify a join in Esqueleto.
What is the main purpose of running runMigration or equivalent in a Persistent-based Haskell application?
Explanation: runMigration is used to update the actual database schema so that it matches the entities as defined in Haskell. It does not delete all tables, create in-memory-only relationships, or clear connection pools. The mechanism ensures database and code are synchronized, which is vital for data integrity.
Why is it necessary to implement the PersistField typeclass for certain custom Haskell types in Persistent?
Explanation: Persistent needs to know how to convert custom Haskell types to and from database values, and this is done by implementing the PersistField typeclass. This does not affect query speed, generate test data, or impact use of raw SQL. The other options either misstate the purpose or relate to unrelated features.
What is the result type when you execute an Esqueleto query using the select function?
Explanation: Esqueleto’s select returns a list where each element matches the query's result fields, frequently as tuples if multiple entities or fields are selected. It does not produce maps, single Maybe values, or raw SQL strings. Only a list of the selected values represents the actual output.
How would you specify a uniqueness constraint for an email field in a Persistent entity definition?
Explanation: In Persistent, you add a line like UniqueEmail email in the entity's quasi-quoted block to create a uniqueness constraint on the email field. There is no unique=True annotation, and functions like enforceUnique or enforceConstraint are not part of Persistent's schema definition process. The accepted method is the Unique line.
A new database row is inserted via Persistent without specifying a primary key. How does Persistent handle the key in this case?
Explanation: For auto-incrementing keys, Persistent lets the database generate the primary key upon insertion. It does not throw an error, use a random Int, or prompt the user for input. Automatic key handling is managed according to the database schema settings.
Which construct is used in Esqueleto to add a WHERE clause that filters users by age greater than 18?
Explanation: Esqueleto uses the where_ function to express the WHERE part of a query with the desired condition, such as checking if age is greater than 18. The functions filter_ and filterField do not exist, and writing whereClause as a string is not how Esqueleto's EDSL operates.
When retrieving an Entity value from a Persistent query, how do you access the entity’s field values in Haskell?
Explanation: You pattern match on the Entity to extract the underlying record, then use standard Haskell field accessor functions. There is no getField function or tuple-based indexing, and referencing database column names as strings is not a Haskell pattern. Pattern matching provides type-safe access.