Safe Haskell | None |
---|
Database.Persist.GenericSql
Contents
Description
This is a helper module for creating SQL backends. Regular users do not need to use this module.
- newtype SqlPersist m a = SqlPersist {
- unSqlPersist :: ReaderT Connection m a
- data Connection
- type ConnectionPool = Pool Connection
- data Statement
- runSqlConn :: (MonadBaseControl IO m, MonadIO m) => SqlPersist m a -> Connection -> m a
- runSqlPool :: (MonadBaseControl IO m, MonadIO m) => SqlPersist m a -> Pool Connection -> m a
- newtype Key backend entity = Key {}
- rawSql :: (RawSql a, MonadUnsafeIO m, MonadThrow m, MonadIO m, MonadBaseControl IO m, MonadLogger m) => Text -> [PersistValue] -> SqlPersist m [a]
- data Entity entity = Entity {
- entityKey :: Key (PersistEntityBackend entity) entity
- entityVal :: entity
- newtype Single a = Single {
- unSingle :: a
- class RawSql a
- type Migration m = WriterT [Text] (WriterT CautiousMigration m) ()
- parseMigration :: Monad m => Migration m -> m (Either [Text] CautiousMigration)
- parseMigration' :: Monad m => Migration m -> m CautiousMigration
- printMigration :: (MonadBaseControl IO m, MonadIO m) => Migration (SqlPersist m) -> SqlPersist m ()
- getMigration :: (MonadBaseControl IO m, MonadIO m) => Migration (SqlPersist m) -> SqlPersist m [Sql]
- runMigration :: (MonadIO m, MonadBaseControl IO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m ()
- runMigrationSilent :: (MonadBaseControl IO m, MonadIO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m [Text]
- runMigrationUnsafe :: (MonadBaseControl IO m, MonadIO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m ()
- migrate :: (MonadIO m, MonadBaseControl IO m, PersistEntity val) => [EntityDef] -> val -> Migration (SqlPersist m)
- commit :: MonadIO m => SqlPersist m ()
- rollback :: MonadIO m => SqlPersist m ()
Documentation
newtype SqlPersist m a Source
Constructors
SqlPersist | |
Fields
|
Instances
data Connection Source
type ConnectionPool = Pool ConnectionSource
runSqlConn :: (MonadBaseControl IO m, MonadIO m) => SqlPersist m a -> Connection -> m aSource
runSqlPool :: (MonadBaseControl IO m, MonadIO m) => SqlPersist m a -> Pool Connection -> m aSource
Get a connection from the pool, run the given action, and then return the connection to the pool.
Raw SQL queries
Although it covers most of the useful cases, persistent
's
API may not be enough for some of your tasks. May be you need
some complex JOIN
query, or a database-specific command
needs to be issued.
To issue raw SQL queries you could use withStmt
, which
allows you to do anything you need. However, its API is
low-level and you need to parse each row yourself. However,
most of your complex queries will have simple results -- some
of your entities and maybe a couple of derived columns.
This is where rawSql
comes in. Like withStmt
, you may
issue any SQL query. However, it does all the hard work for
you and automatically parses the rows of the result. It may
return:
- An
Entity
, that whichselectList
returns. All of your entity's fields are automatically parsed. - A
, which is a single, raw column of typeSingle
aa
. You may use a Haskell type (such as in your entity definitions), for exampleSingle Text
orSingle Int
, or you may get the raw column value withSingle
.PersistValue
- A tuple combining any of these (including other tuples). Using tuples allows you to return many entities in one query.
The only difference between issuing SQL queries with rawSql
and using other means is that we have an entity selection
placeholder, the double question mark ??
. It must be
used whenever you want to SELECT
an Entity
from your
query. Here's a sample SQL query sampleStmt
that may be
issued:
SELECT ??, ?? FROM "Person", "Likes", "Object" WHERE "Person".id = "Likes"."personId" AND "Object".id = "Likes"."objectId" AND "Person".name LIKE ?
To use that query, you could say
do results <- rawSql
sampleStmt ["%Luke%"]
forM_ results $
\( Entity personKey person
, Entity objectKey object
) -> do ...
Note that rawSql
knows how to replace the double question
marks ??
because of the type of the results
.
Arguments
:: (RawSql a, MonadUnsafeIO m, MonadThrow m, MonadIO m, MonadBaseControl IO m, MonadLogger m) | |
=> Text | SQL statement, possibly with placeholders. |
-> [PersistValue] | Values to fill the placeholders. |
-> SqlPersist m [a] |
Execute a raw SQL statement and return its results as a list.
If you're using Entity
s
(which is quite likely), then you
must use entity selection placeholders (double question
mark, ??
). These ??
placeholders are then replaced for
the names of the columns that we need for your entities.
You'll receive an error if you don't use the placeholders.
Please see the Entity
s
documentation for more details.
You may put value placeholders (question marks, ?
) in your
SQL query. These placeholders are then replaced by the values
you pass on the second parameter, already correctly escaped.
You may want to use toPersistValue
to help you constructing
the placeholder values.
Since you're giving a raw SQL statement, you don't get any
guarantees regarding safety. If rawSql
is not able to parse
the results of your query back, then an exception is raised.
However, most common problems are mitigated by using the
entity selection placeholder ??
, and you shouldn't see any
error at all if you're not using Single
.
Datatype that represents an entity, with both its key and its Haskell representation.
When using the an SQL-based backend (such as SQLite or
PostgreSQL), an Entity
may take any number of columns
depending on how many fields it has. In order to reconstruct
your entity on the Haskell side, persistent
needs all of
your entity columns and in the right order. Note that you
don't need to worry about this when using persistent
's API
since everything is handled correctly behind the scenes.
However, if you want to issue a raw SQL command that returns
an Entity
, then you have to be careful with the column
order. While you could use SELECT Entity.* WHERE ...
and
that would work most of the time, there are times when the
order of the columns on your database is different from the
order that persistent
expects (for example, if you add a new
field in the middle of you entity definition and then use the
migration code -- persistent
will expect the column to be in
the middle, but your DBMS will put it as the last column).
So, instead of using a query like the one above, you may use
rawSql
(from the
Database.Persist.GenericSql module) with its /entity
selection placeholder/ (a double question mark ??
). Using
rawSql
the query above must be written as SELECT ?? WHERE
..
. Then rawSql
will replace ??
with the list of all
columns that we need from your entity in the right order. If
your query returns two entities (i.e. (Entity backend a,
Entity backend b)
), then you must you use SELECT ??, ??
WHERE ...
, and so on.
Constructors
Entity | |
Fields
|
A single column (see rawSql
). Any PersistField
may be
used here, including PersistValue
(which does not do any
processing).
Class for data types that may be retrived from a rawSql
query.
Instances
RawSql a => RawSql (Maybe a) | Since 1.0.1. |
PersistEntity a => RawSql (Entity a) | |
PersistField a => RawSql (Single a) | |
(RawSql a, RawSql b) => RawSql (a, b) | |
(RawSql a, RawSql b, RawSql c) => RawSql (a, b, c) | |
(RawSql a, RawSql b, RawSql c, RawSql d) => RawSql (a, b, c, d) | |
(RawSql a, RawSql b, RawSql c, RawSql d, RawSql e) => RawSql (a, b, c, d, e) | |
(RawSql a, RawSql b, RawSql c, RawSql d, RawSql e, RawSql f) => RawSql (a, b, c, d, e, f) | |
(RawSql a, RawSql b, RawSql c, RawSql d, RawSql e, RawSql f, RawSql g) => RawSql (a, b, c, d, e, f, g) | |
(RawSql a, RawSql b, RawSql c, RawSql d, RawSql e, RawSql f, RawSql g, RawSql h) => RawSql (a, b, c, d, e, f, g, h) |
Migrations
parseMigration' :: Monad m => Migration m -> m CautiousMigrationSource
printMigration :: (MonadBaseControl IO m, MonadIO m) => Migration (SqlPersist m) -> SqlPersist m ()Source
getMigration :: (MonadBaseControl IO m, MonadIO m) => Migration (SqlPersist m) -> SqlPersist m [Sql]Source
runMigration :: (MonadIO m, MonadBaseControl IO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m ()Source
runMigrationSilent :: (MonadBaseControl IO m, MonadIO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m [Text]Source
Same as runMigration
, but returns a list of the SQL commands executed
instead of printing them to stderr.
runMigrationUnsafe :: (MonadBaseControl IO m, MonadIO m, MonadLogger m) => Migration (SqlPersist m) -> SqlPersist m ()Source
migrate :: (MonadIO m, MonadBaseControl IO m, PersistEntity val) => [EntityDef] -> val -> Migration (SqlPersist m)Source
commit :: MonadIO m => SqlPersist m ()Source
Perform a database commit.
rollback :: MonadIO m => SqlPersist m ()Source
Perform a database rollback.