Copyright | (c) digitally induced GmbH 2020 |
---|---|
Safe Haskell | None |
Language | Haskell2010 |
IHP.Fetch
Description
This modules builds on top of QueryBuilder
and provides functions to fetch a query builder.
For more complex sql queries, use sqlQuery
.
Synopsis
- findManyBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO (FetchResult (queryBuilderProvider table) model)
- findMaybeBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO (Maybe model)
- findBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO model
- newtype In a = In a
- genericFetchId :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO [model]
- genericfetchIdOneOrNothing :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO (Maybe model)
- genericFetchIdOne :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO model
- class Fetchable fetchable model | fetchable -> model where
- type FetchResult fetchable model
- fetch :: fetchable -> IO (FetchResult fetchable model)
- fetchOneOrNothing :: fetchable -> IO (Maybe model)
- fetchOne :: fetchable -> IO model
- genericFetchIds :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO [model]
- genericfetchIdsOneOrNothing :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO (Maybe model)
- genericFetchIdsOne :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO model
- fetchCount :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Int
- fetchExists :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Bool
- fetchSQLQuery :: (FromRow model, ?modelContext :: ModelContext) => SQLQuery -> IO [model]
- fetchLatest :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k) model. (?modelContext :: ModelContext, model ~ GetModelByTableName table, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, HasField "createdAt" model UTCTime, Fetchable (queryBuilderProvider table) model, Table model, FromRow model) => queryBuilderProvider table -> IO (Maybe model)
- fetchLatestBy :: forall {k} (table :: Symbol) (createdAt :: Symbol) queryBuilderProvider (joinRegister :: k) model. (?modelContext :: ModelContext, KnownSymbol createdAt, model ~ GetModelByTableName table, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, HasField createdAt model UTCTime, Fetchable (queryBuilderProvider table) model, Table model, FromRow model) => Proxy createdAt -> queryBuilderProvider table -> IO (Maybe model)
Documentation
findManyBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO (FetchResult (queryBuilderProvider table) model) Source #
findMaybeBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO (Maybe model) Source #
findBy :: forall {k} {value} {name :: Symbol} {table :: Symbol} {queryBuilderProvider} {joinRegister :: k} {model}. (ToField value, HasField name (GetModelByTableName table) value, EqOrIsOperator value, HasQueryBuilder queryBuilderProvider joinRegister, Fetchable (queryBuilderProvider table) model, Table model, Table (GetModelByTableName table), FromRow model, ?modelContext :: ModelContext, KnownSymbol table, KnownSymbol name) => Proxy name -> value -> queryBuilderProvider table -> IO model Source #
Wrap a list of values for use in an IN
clause. Replaces a
single "?
" character with a parenthesized list of rendered
values.
Example:
query c "select * from whatever where id in ?" (Only (In [3,4,5]))
Note that In []
expands to (null)
, which works as expected in
the query above, but evaluates to the logical null value on every
row instead of TRUE
. This means that changing the query above
to ... id NOT in ?
and supplying the empty list as the parameter
returns zero rows, instead of all of them as one would expect.
Since postgresql doesn't seem to provide a syntax for actually specifying an empty list, which could solve this completely, there are two workarounds particularly worth mentioning, namely:
Use postgresql-simple's
Values
type instead, which can handle the empty case correctly. Note however that while specifying the postgresql type"int4"
is mandatory in the empty case, specifying the haskell typeValues (Only Int)
would not normally be needed in realistic use cases.query c "select * from whatever where id not in ?" (Only (Values ["int4"] [] :: Values (Only Int)))
Use sql's
COALESCE
operator to turn a logicalnull
into the correct boolean. Note however that the correct boolean depends on the use case:query c "select * from whatever where coalesce(id NOT in ?, TRUE)" (Only (In [] :: In [Int]))
query c "select * from whatever where coalesce(id IN ?, FALSE)" (Only (In [] :: In [Int]))
Note that at as of PostgreSQL 9.4, the query planner cannot see inside the
COALESCE
operator, so if you have an index onid
then you probably don't want to write the last example withCOALESCE
, which would result in a table scan. There are further caveats ifid
can be null or you want null treated sensibly as a component ofIN
orNOT IN
.
Constructors
In a |
genericFetchId :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO [model] Source #
genericfetchIdOneOrNothing :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO (Maybe model) Source #
genericFetchIdOne :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO model Source #
class Fetchable fetchable model | fetchable -> model where Source #
Associated Types
type FetchResult fetchable model Source #
Methods
fetch :: fetchable -> IO (FetchResult fetchable model) Source #
fetchOneOrNothing :: fetchable -> IO (Maybe model) Source #
Instances
genericFetchIds :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO [model] Source #
genericfetchIdsOneOrNothing :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO (Maybe model) Source #
genericFetchIdsOne :: forall (table :: Symbol) model. (Table model, KnownSymbol table, FromRow model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table) => [Id model] -> IO model Source #
fetchCount :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Int Source #
Returns the count of records selected by the query builder.
Example: Counting all users.
allUsersCount <- query @User |> fetchCount -- SELECT COUNT(*) FROM users
Example: Counting all active projects
activeProjectsCount <- query @Project |> filterWhere (#isActive, True) |> fetchCount -- SELECT COUNT(*) FROM projects WHERE is_active = true
fetchExists :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Bool Source #
Checks whether the query has any results.
Returns True
when there is at least one row matching the conditions of the query. Returns False
otherwise.
Example: Checking whether there are unread messages
hasUnreadMessages <- query @Message |> filterWhere (#isUnread, True) |> fetchExists -- SELECT EXISTS (SELECT * FROM messages WHERE is_unread = true)
fetchSQLQuery :: (FromRow model, ?modelContext :: ModelContext) => SQLQuery -> IO [model] Source #
fetchLatest :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k) model. (?modelContext :: ModelContext, model ~ GetModelByTableName table, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, HasField "createdAt" model UTCTime, Fetchable (queryBuilderProvider table) model, Table model, FromRow model) => queryBuilderProvider table -> IO (Maybe model) Source #
Returns the latest record or Nothing
Example:
latestUser <- query @User |> fetchLatest
fetchLatest
is mainly a shortcut for code like this:
latestUser <- query @User |> orderByDesc #createdAt |> fetchOneOrNothing
fetchLatestBy :: forall {k} (table :: Symbol) (createdAt :: Symbol) queryBuilderProvider (joinRegister :: k) model. (?modelContext :: ModelContext, KnownSymbol createdAt, model ~ GetModelByTableName table, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, HasField createdAt model UTCTime, Fetchable (queryBuilderProvider table) model, Table model, FromRow model) => Proxy createdAt -> queryBuilderProvider table -> IO (Maybe model) Source #
Provided a field name, it returns the latest record or Nothing
See fetchLatest
if you're looking for the latest record by the createdAt timestamp.
Example:
latestTrialUser <- query @User |> fetchLatestBy #trialStartedAt
fetchLatestBy
is mainly a shortcut for code like this:
latestUser <- query @User |> orderByDesc #trialStartedAt |> fetchOneOrNothing