Safe Haskell | None |
---|---|
Language | Haskell2010 |
Statements
Quasiquoters in this category produce Hasql Statement
s,
checking the correctness of SQL at compile-time.
To extract the information about parameters and results of the statement, the quoter requires you to explicitly specify the Postgres types for placeholders and results.
Here's an example of how to use it:
selectUserDetails :: Statement Int32 (Maybe (Text, Text, Maybe Text)) selectUserDetails = [maybeStatement| select name :: text, email :: text, phone :: text? from "user" where id = $1 :: int4 |]
As you can see, it completely eliminates the need to mess with codecs.
The quasiquoters directly produce Statement
,
which you can then dimap
over using its Profunctor
instance to get to your domain types.
Type mappings
Primitives
Following is a list of supported Postgres types and their according types on the Haskell end.
bool
-Bool
int2
-Int16
int4
-Int32
int8
-Int64
float4
-Float
float8
-Double
numeric
-Scientific
char
-Char
text
-Text
bytea
-ByteString
date
-Day
timestamp
-LocalTime
timestamptz
-UTCTime
time
-TimeOfDay
timetz
-(
TimeOfDay
,TimeZone
)interval
-DiffTime
uuid
-UUID
inet
-(
NetAddr
IP
)json
-Value
jsonb
-Value
Arrays
Array mappings are also supported.
They are specified according to Postgres syntax: by appending one or more []
to the primitive type,
depending on how many dimensions the array has.
On the Haskell end array is mapped to generic Vector
,
allowing you to choose which particular vector implementation to map to.
Nulls
As you might have noticed in the example, we introduce one change to the Postgres syntax in the way the typesignatures are parsed: we interpret question-marks in them as specification of nullability. Here's more examples of that:
>>>
:t [singletonStatement| select a :: int4? |]
... :: Statement () (Maybe Int32)
You can use it to specify the nullability of array elements:
>>>
:t [singletonStatement| select a :: int4?[] |]
... :: Data.Vector.Generic.Base.Vector v (Maybe Int32) => Statement () (v (Maybe Int32))
And of arrays themselves:
>>>
:t [singletonStatement| select a :: int4?[]? |]
... :: Data.Vector.Generic.Base.Vector v (Maybe Int32) => Statement () (Maybe (v (Maybe Int32)))
Row-parsing statements
singletonStatement :: QuasiQuoter Source #
:: Statement
params row
Statement producing exactly one result row.
Will cause the running session to fail with the
UnexpectedAmountOfRows
error if it's any other.
Examples
>>>
:t [singletonStatement|select 1 :: int2|]
... :: Statement () Int16
>>>
:{
:t [singletonStatement| insert into "user" (email, name) values ($1 :: text, $2 :: text) returning id :: int4 |] :} ... ... :: Statement (Text, Text) Int32
Incorrect SQL:
>>>
:t [singletonStatement|elect 1|]
... | 1 | elect 1 | ^ ...
maybeStatement :: QuasiQuoter Source #
:: Statement
params (Maybe row)
Statement producing one row or none.
Examples
>>>
:t [maybeStatement|select 1 :: int2|]
... :: Statement () (Maybe Int16)
vectorStatement :: QuasiQuoter Source #
::Statement
params (Vector
row)
Statement producing a vector of rows.
Examples
>>>
:t [vectorStatement|select 1 :: int2|]
... :: Statement () (Vector Int16)
Row-ignoring statements
resultlessStatement :: QuasiQuoter Source #
:: Statement
params ()
Statement producing no results.
Examples
>>>
:t [resultlessStatement|insert into "user" (name, email) values ($1 :: text, $2 :: text)|]
... ... :: Statement (Text, Text) ()
rowsAffectedStatement :: QuasiQuoter Source #
:: Statement
params Int64
Statement counting the rows it affects.
Examples
>>>
:t [rowsAffectedStatement|delete from "user" where password is null|]
... ... :: Statement () Int64
SQL ByteStrings
ByteString-producing quasiquoters.
For now they perform no compile-time checking.
uncheckedSql :: QuasiQuoter Source #
Quoter of a multiline Unicode SQL string, which gets converted into a format ready to be used for declaration of statements.
uncheckedSqlFile :: QuasiQuoter Source #
Read an SQL-file, containing multiple statements,
and produce an expression of type ByteString
.
Allows to store plain SQL in external files and read it at compile time.
E.g.,
migration1 :: Hasql.Session.Session () migration1 = Hasql.Session.sql [uncheckedSqlFile|migrations/1.sql|]