Q package:esqueleto

Type-safe EDSL for SQL queries on persistent backends. esqueleto is a bare bones, type-safe EDSL for SQL queries that works with unmodified persistent SQL backends. Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked esqueleto queries that fail at runtime. persistent is a library for type-safe data serialization. It has many kinds of backends, such as SQL backends (persistent-mysql, persistent-postgresql, persistent-sqlite) and NoSQL backends (persistent-mongoDB). While persistent is a nice library for storing and retrieving records, including with filters, it does not try to support some of the features that are specific to SQL backends. In particular, esqueleto is the recommended library for type-safe JOINs on persistent SQL backends. (The alternative is using raw SQL, but that's error prone and does not offer any composability.) Currently, SELECTs, UPDATEs, INSERTs and DELETEs are supported. Not all SQL features are available, but most of them can be easily added (especially functions), so please open an issue or send a pull request if you need anything that is not covered by esqueleto on https://github.com/bitemyapp/esqueleto. The name of this library means "skeleton" in Portuguese and contains all three SQL letters in the correct order =). It was inspired by Scala's Squeryl but created from scratch.
Warning: This module will switch over to the Experimental syntax in an upcoming major version release. Please migrate to the Database.Esqueleto.Legacy module to continue using the old syntax, or translate to the new and improved syntax in Database.Esqueleto.Experimental.
This class is used to ensure that functions requring at least one unique key are not called with records that have 0 unique keys. The quasiquoter automatically writes working instances for appropriate entities, and generates TypeError instances for records that have 0 unique keys.
Specify the database name of the column.
User
blarghle     Int     sql="b_l_a_r_g_h_l_e"
Useful for performing phased migrations, where one column is renamed to another column over time.
Specify a custom SQL type for the column. Generally, you should define a custom datatype with a custom PersistFieldSql instance instead of using this.
User
uuid     Text    sqltype=UUID
A backend which is a wrapper around SqlBackend.
This is an error message. It is used when an entity has multiple unique keys, and the function expects a single unique key.
This is an error message. It is used when writing instances of OnlyOneUniqueKey for an entity that has no unique keys.
This class is used to ensure that upsert is only called on records that have a single Unique key. The quasiquoter automatically generates working instances for appropriate records, and generates TypeError instances for records that have 0 or multiple unique keys.
Tells Persistent what database column type should be used to store a Haskell type.

Examples

Simple Boolean Alternative
data Switch = On | Off
deriving (Show, Eq)

instance PersistField Switch where
toPersistValue s = case s of
On -> PersistBool True
Off -> PersistBool False
fromPersistValue (PersistBool b) = if b then Right On else Right Off
fromPersistValue x = Left $ "File.hs: When trying to deserialize a Switch: expected PersistBool, received: " <> T.pack (show x)

instance PersistFieldSql Switch where
sqlType _ = SqlBool
Non-Standard Database Types
If your database supports non-standard types, such as Postgres' uuid, you can use SqlOther to use them:
import qualified Data.UUID as UUID
instance PersistField UUID where
toPersistValue = PersistLiteralEncoded . toASCIIBytes
fromPersistValue (PersistLiteralEncoded uuid) =
case fromASCIIBytes uuid of
Nothing -> Left $ "Model/CustomTypes.hs: Failed to deserialize a UUID; received: " <> T.pack (show uuid)
Just uuid' -> Right uuid'
fromPersistValue x = Left $ "File.hs: When trying to deserialize a UUID: expected PersistLiteralEncoded, received: "-- >  <> T.pack (show x)

instance PersistFieldSql UUID where
sqlType _ = SqlOther "uuid"
User Created Database Types
Similarly, some databases support creating custom types, e.g. Postgres' DOMAIN and ENUM features. You can use SqlOther to specify a custom type:
CREATE DOMAIN ssn AS text
CHECK ( value ~ '^[0-9]{9}$');
instance PersistFieldSQL SSN where
sqlType _ = SqlOther "ssn"
CREATE TYPE rainbow_color AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet');
instance PersistFieldSQL RainbowColor where
sqlType _ = SqlOther "rainbow_color"
Backends supporting conditional read operations.
Backends supporting conditional write operations
A backwards-compatible alias for those that don't care about distinguishing between read and write queries. It signifies the assumption that, by default, a backend can write as well as read.
Queries against Unique keys (other than the id Key). Please read the general Persistent documentation to learn how to create Unique keys. Using this with an Entity without a Unique key leads to undefined behavior. A few of these functions require a single Unique, so using an Entity with multiple Uniques is also undefined. In these cases persistent's goal is to throw an exception as soon as possible, but persistent is still transitioning to that. SQL backends automatically create uniqueness constraints, but for MongoDB you must manually place a unique index on a field to have a uniqueness constraint.
Some functions in this module (insertUnique, insertBy, and replaceUnique) first query the unique indexes to check for conflicts. You could instead optimistically attempt to perform the operation (e.g. replace instead of replaceUnique). However,
  • there is some fragility to trying to catch the correct exception and determing the column of failure;
  • an exception will automatically abort the current SQL transaction.
Class for data types that may be retrived from a rawSql query.
A SqlBackend represents a handle or connection to a database. It contains functions and values that allow databases to have more optimized implementations, as well as references that benefit performance and sharing. Instead of using the SqlBackend constructor directly, use the mkSqlBackend function. A SqlBackend is *not* thread-safe. You should not assume that a SqlBackend can be shared among threads and run concurrent queries. This *will* result in problems. Instead, you should create a Pool SqlBackend, known as a ConnectionPool, and pass that around in multi-threaded applications. To run actions in the persistent library, you should use the runSqlConn function. If you're using a multithreaded application, use the runSqlPool function.
A constraint synonym which witnesses that a backend is SQL and can run read queries.
A constraint synonym which witnesses that a backend is SQL and can run read and write queries.