{-# LANGUAGE BangPatterns, TypeFamilies, DataKinds, PolyKinds, TypeApplications, ScopedTypeVariables, TypeInType, ConstraintKinds, TypeOperators, GADTs, UndecidableInstances, StandaloneDeriving, FunctionalDependencies, FlexibleContexts, InstanceSigs, AllowAmbiguousTypes, DeriveAnyClass #-}
{-|
Module: IHP.Fetch
Description: fetch, fetchOne, fetchOneOrNothing and friends
Copyright: (c) digitally induced GmbH, 2020

This modules builds on top of 'IHP.QueryBuilder' and provides functions to fetch a query builder.

For more complex sql queries, use 'IHP.ModelSupport.sqlQuery'.
-}
module IHP.Fetch
( findManyBy
, findMaybeBy
, findBy
, In (In)
, genericFetchId
, genericfetchIdOneOrNothing
, genericFetchIdOne
, Fetchable (..)
, genericFetchIds
, genericfetchIdsOneOrNothing
, genericFetchIdsOne
, fetchCount
, fetchExists
, fetchSQLQuery
, fetchLatest
, fetchLatestBy
)
where

import IHP.Prelude
import Database.PostgreSQL.Simple.Types (Query (Query))
import Database.PostgreSQL.Simple.FromField hiding (Field, name)
import Database.PostgreSQL.Simple.ToField
import qualified Database.PostgreSQL.Simple as PG
import IHP.ModelSupport
import IHP.QueryBuilder

class Fetchable fetchable model | fetchable -> model where
    type FetchResult fetchable model
    fetch :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => fetchable -> IO (FetchResult fetchable model)
    fetchOneOrNothing :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => fetchable -> IO (Maybe model)
    fetchOne :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => fetchable -> IO model

-- The instance declaration had to be split up because a type variable ranging over HasQueryBuilder instances is not allowed in the declaration of the associated type. The common*-functions reduce the redundancy to the necessary minimum.
instance (model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (QueryBuilder table) model where
    type instance FetchResult (QueryBuilder table) model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => QueryBuilder table -> IO [model]
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
QueryBuilder table -> IO [model]
fetch = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRow model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch 

    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => QueryBuilder table -> IO (Maybe model)
    fetchOneOrNothing :: (?modelContext::ModelContext, Table model, FromRow model) =>
QueryBuilder table -> IO (Maybe model)
fetchOneOrNothing = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => QueryBuilder table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRow model) =>
QueryBuilder table -> IO model
fetchOne = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO model
commonFetchOne

instance (model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (JoinQueryBuilderWrapper r table) model where
    type instance FetchResult (JoinQueryBuilderWrapper r table) model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => JoinQueryBuilderWrapper r table -> IO [model]
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
JoinQueryBuilderWrapper r table -> IO [model]
fetch = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRow model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch 

    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => JoinQueryBuilderWrapper r table -> IO (Maybe model)
    fetchOneOrNothing :: (?modelContext::ModelContext, Table model, FromRow model) =>
JoinQueryBuilderWrapper r table -> IO (Maybe model)
fetchOneOrNothing = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => JoinQueryBuilderWrapper r table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRow model) =>
JoinQueryBuilderWrapper r table -> IO model
fetchOne = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO model
commonFetchOne

instance (model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (NoJoinQueryBuilderWrapper table) model where
    type instance FetchResult (NoJoinQueryBuilderWrapper table) model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => NoJoinQueryBuilderWrapper table -> IO [model]
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
NoJoinQueryBuilderWrapper table -> IO [model]
fetch = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRow model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch 

    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => NoJoinQueryBuilderWrapper table -> IO (Maybe model)
    fetchOneOrNothing :: (?modelContext::ModelContext, Table model, FromRow model) =>
NoJoinQueryBuilderWrapper table -> IO (Maybe model)
fetchOneOrNothing = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => NoJoinQueryBuilderWrapper table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRow model) =>
NoJoinQueryBuilderWrapper table -> IO model
fetchOne = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO model
commonFetchOne

instance (model ~ GetModelByTableName table, KnownSymbol table, FromField value, KnownSymbol foreignTable, foreignModel ~ GetModelByTableName foreignTable, KnownSymbol columnName, HasField columnName foreignModel value, HasQueryBuilder (LabeledQueryBuilderWrapper foreignTable columnName value) NoJoins) => Fetchable (LabeledQueryBuilderWrapper foreignTable columnName value table) model where
    type instance FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model = [LabeledData value model]
    -- fetch needs to return a list of labeled data. The 
    {-# INLINE fetch #-}
    fetch :: (Table model, PG.FromRow model, ?modelContext :: ModelContext) => LabeledQueryBuilderWrapper foreignTable columnName value table -> IO [LabeledData value model]
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
LabeledQueryBuilderWrapper foreignTable columnName value table
-> IO [LabeledData value model]
fetch !LabeledQueryBuilderWrapper foreignTable columnName value table
queryBuilderProvider = do
        let !(ByteString
theQuery, [Action]
theParameters) = LabeledQueryBuilderWrapper foreignTable columnName value table
queryBuilderProvider
                forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> (ByteString, [Action])
toSQL
        (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall record. Table record => ByteString
tableNameByteString @model)
        forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery @_ @(LabeledData value model) (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs ByteString
theQuery) [Action]
theParameters

    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => LabeledQueryBuilderWrapper foreignTable columnName value table -> IO (Maybe model)
    fetchOneOrNothing :: (?modelContext::ModelContext, Table model, FromRow model) =>
LabeledQueryBuilderWrapper foreignTable columnName value table
-> IO (Maybe model)
fetchOneOrNothing = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, PG.FromRow model) => LabeledQueryBuilderWrapper foreignTable columnName value table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRow model) =>
LabeledQueryBuilderWrapper foreignTable columnName value table
-> IO model
fetchOne = forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO model
commonFetchOne



{-# INLINE commonFetch #-}
commonFetch :: forall model table queryBuilderProvider joinRegister. (Table model, HasQueryBuilder queryBuilderProvider joinRegister, model ~ GetModelByTableName table, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext) => queryBuilderProvider table -> IO [model]
commonFetch :: forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRow model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch !queryBuilderProvider table
queryBuilder = do
    let !(ByteString
theQuery, [Action]
theParameters) = queryBuilderProvider table
queryBuilder
            forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> (ByteString, [Action])
toSQL
    (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall record. Table record => ByteString
tableNameByteString @model)
    forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs ByteString
theQuery) [Action]
theParameters

{-# INLINE commonFetchOneOrNothing #-}
commonFetchOneOrNothing :: forall model table queryBuilderProvider joinRegister. (?modelContext :: ModelContext) => (Table model, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, PG.FromRow model) => queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing :: forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing !queryBuilderProvider table
queryBuilder = do
    let !(ByteString
theQuery, [Action]
theParameters) = queryBuilderProvider table
queryBuilder
            forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery
            forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall model (name :: Symbol) value.
(KnownSymbol name, SetField name model (Maybe value)) =>
Proxy name -> value -> model -> model
setJust forall a. IsLabel "limitClause" a => a
#limitClause ByteString
"LIMIT 1"
            forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> SQLQuery -> (ByteString, [Action])
toSQL'
    (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall record. Table record => ByteString
tableNameByteString @model)
    [model]
results <- forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs ByteString
theQuery) [Action]
theParameters
    forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Maybe a
listToMaybe [model]
results

{-# INLINE commonFetchOne #-}
commonFetchOne :: forall model table queryBuilderProvider joinRegister. (?modelContext :: ModelContext) => (Table model, KnownSymbol table, Fetchable (queryBuilderProvider table) model, HasQueryBuilder queryBuilderProvider joinRegister, PG.FromRow model) => queryBuilderProvider table -> IO model
commonFetchOne :: forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRow model) =>
queryBuilderProvider table -> IO model
commonFetchOne !queryBuilderProvider table
queryBuilder = do
    Maybe model
maybeModel <- forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing queryBuilderProvider table
queryBuilder
    case Maybe model
maybeModel of
        Just model
model -> forall (f :: * -> *) a. Applicative f => a -> f a
pure model
model
        Maybe model
Nothing -> forall e a. Exception e => e -> IO a
throwIO RecordNotFoundException { $sel:queryAndParams:RecordNotFoundException :: (ByteString, [Action])
queryAndParams = forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> (ByteString, [Action])
toSQL queryBuilderProvider table
queryBuilder }


-- | 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
fetchCount :: forall table queryBuilderProvider joinRegister. (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Int
fetchCount :: forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(?modelContext::ModelContext, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> IO Int
fetchCount !queryBuilderProvider table
queryBuilder = do
    let !(ByteString
theQuery', [Action]
theParameters) = SQLQuery -> (ByteString, [Action])
toSQL' (forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery queryBuilderProvider table
queryBuilder)
    let theQuery :: ByteString
theQuery = ByteString
"SELECT COUNT(*) FROM (" forall a. Semigroup a => a -> a -> a
<> ByteString
theQuery' forall a. Semigroup a => a -> a -> a
<> ByteString
") AS _count_values"
    (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall (symbol :: Symbol). KnownSymbol symbol => ByteString
symbolToByteString @table)
    [PG.Only Int
count] <- forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$! forall a b. ConvertibleStrings a b => a -> b
cs ByteString
theQuery) [Action]
theParameters
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
count
{-# INLINE fetchCount #-}

-- | 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)
fetchExists :: forall table queryBuilderProvider joinRegister. (?modelContext :: ModelContext, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> IO Bool
fetchExists :: forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(?modelContext::ModelContext, KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> IO Bool
fetchExists !queryBuilderProvider table
queryBuilder = do
    let !(ByteString
theQuery', [Action]
theParameters) = SQLQuery -> (ByteString, [Action])
toSQL' (forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery queryBuilderProvider table
queryBuilder)
    let theQuery :: ByteString
theQuery = ByteString
"SELECT EXISTS (" forall a. Semigroup a => a -> a -> a
<> ByteString
theQuery' forall a. Semigroup a => a -> a -> a
<> ByteString
") AS _exists_values"
    (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall (symbol :: Symbol). KnownSymbol symbol => ByteString
symbolToByteString @table)
    [PG.Only Bool
exists] <- forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$! forall a b. ConvertibleStrings a b => a -> b
cs ByteString
theQuery) [Action]
theParameters
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
exists
{-# INLINE fetchExists #-}

{-# INLINE genericFetchId #-}
genericFetchId :: forall table model. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO [model]
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]
genericFetchId !Id' table
id = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (table :: Symbol).
FilterPrimaryKey table =>
Id' table -> QueryBuilder table -> QueryBuilder table
filterWhereId Id' table
id forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (FetchResult fetchable model)
fetch

{-# INLINE genericfetchIdOneOrNothing #-}
genericfetchIdOneOrNothing :: forall table model. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO (Maybe 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)
genericfetchIdOneOrNothing !Id' table
id = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (table :: Symbol).
FilterPrimaryKey table =>
Id' table -> QueryBuilder table -> QueryBuilder table
filterWhereId Id' table
id forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing

{-# INLINE genericFetchIdOne #-}
genericFetchIdOne :: forall table model. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO 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
genericFetchIdOne !Id' table
id = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (table :: Symbol).
FilterPrimaryKey table =>
Id' table -> QueryBuilder table -> QueryBuilder table
filterWhereId Id' table
id forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO model
fetchOne

{-# INLINE genericFetchIds #-}
genericFetchIds :: forall table model value. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, ToField value, EqOrIsOperator value, HasField "id" model value, model ~ GetModelByTableName table, GetTableName model ~ table) => [value] -> IO [model]
genericFetchIds :: forall (table :: Symbol) model value.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO [model]
genericFetchIds ![value]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 EqOrIsOperator value, Table model) =>
(Proxy name, [value])
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIn (forall a. IsLabel "id" a => a
#id, [value]
ids) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (FetchResult fetchable model)
fetch

{-# INLINE genericfetchIdsOneOrNothing #-}
genericfetchIdsOneOrNothing :: forall model value table. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, ToField value, EqOrIsOperator value, HasField "id" model value, model ~ GetModelByTableName table, GetTableName model ~ table) => [value] -> IO (Maybe model)
genericfetchIdsOneOrNothing :: forall model value (table :: Symbol).
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO (Maybe model)
genericfetchIdsOneOrNothing ![value]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 EqOrIsOperator value, Table model) =>
(Proxy name, [value])
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIn (forall a. IsLabel "id" a => a
#id, [value]
ids) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing

{-# INLINE genericFetchIdsOne #-}
genericFetchIdsOne :: forall model value table. (Table model, KnownSymbol table, PG.FromRow model, ?modelContext :: ModelContext, ToField value, EqOrIsOperator value, HasField "id" model value, model ~ GetModelByTableName table, GetTableName model ~ table) => [value] -> IO model
genericFetchIdsOne :: forall model value (table :: Symbol).
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO model
genericFetchIdsOne ![value]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 EqOrIsOperator value, Table model) =>
(Proxy name, [value])
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIn (forall a. IsLabel "id" a => a
#id, [value]
ids) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO model
fetchOne

{-# INLINE findBy #-}
findBy :: Proxy name -> value -> queryBuilderProvider table -> IO model
findBy !Proxy name
field !value
value !queryBuilderProvider table
queryBuilder = queryBuilderProvider table
queryBuilder forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister, Table model) =>
(Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhere (Proxy name
field, value
value) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO model
fetchOne

{-# INLINE findMaybeBy #-}
findMaybeBy :: Proxy name
-> value -> queryBuilderProvider table -> IO (Maybe model)
findMaybeBy !Proxy name
field !value
value !queryBuilderProvider table
queryBuilder = queryBuilderProvider table
queryBuilder forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister, Table model) =>
(Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhere (Proxy name
field, value
value) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing

--findManyBy :: (?modelContext :: ModelContext, PG.FromRow model, KnownSymbol name, ToField value, HasField name value model) => Proxy name -> value -> QueryBuilder model -> IO [model]
{-# INLINE findManyBy #-}
findManyBy :: Proxy name
-> value
-> queryBuilderProvider table
-> IO (FetchResult (queryBuilderProvider table) model)
findManyBy !Proxy name
field !value
value !queryBuilderProvider table
queryBuilder = queryBuilderProvider table
queryBuilder forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, ToField value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister, Table model) =>
(Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhere (Proxy name
field, value
value) forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (FetchResult fetchable model)
fetch
-- Step.findOneByWorkflowId id    ==    queryBuilder |> findBy #templateId id

instance (model ~ GetModelById (Id' table), GetTableName model ~ table, FilterPrimaryKey table) => Fetchable (Id' table) model where
    type FetchResult (Id' table) model = model
    {-# INLINE fetch #-}
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Id' table -> IO (FetchResult (Id' table) model)
fetch = forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO model
genericFetchIdOne
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Id' table -> IO (Maybe model)
fetchOneOrNothing = 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)
genericfetchIdOneOrNothing
    {-# INLINE fetchOne #-}
    fetchOne :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Id' table -> IO model
fetchOne = forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO model
genericFetchIdOne

instance (model ~ GetModelById (Id' table), GetTableName model ~ table, FilterPrimaryKey table) => Fetchable (Maybe (Id' table)) model where
    type FetchResult (Maybe (Id' table)) model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO (FetchResult (Maybe (Id' table)) model)
fetch (Just Id' table
a) = forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO [model]
genericFetchId Id' table
a
    fetch Maybe (Id' table)
Nothing = forall (f :: * -> *) a. Applicative f => a -> f a
pure []
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO (Maybe model)
fetchOneOrNothing Maybe (Id' table)
Nothing = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
    fetchOneOrNothing (Just Id' table
a) = 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)
genericfetchIdOneOrNothing Id' table
a
    {-# INLINE fetchOne #-}
    fetchOne :: (Table model, FromRow model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO model
fetchOne (Just Id' table
a) = forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO model
genericFetchIdOne Id' table
a
    fetchOne Maybe (Id' table)
Nothing = forall a. Text -> a
error Text
"Fetchable (Maybe Id): Failed to fetch because given id is 'Nothing', 'Just id' was expected"

instance (model ~ GetModelById (Id' table), value ~ Id' table, HasField "id" model value, ToField (PrimaryKey table), GetModelByTableName (GetTableName model) ~ model) => Fetchable [Id' table] model where
    type FetchResult [Id' table] model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, FromRow model, ?modelContext::ModelContext) =>
[Id' table] -> IO (FetchResult [Id' table] model)
fetch = forall (table :: Symbol) model value.
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO [model]
genericFetchIds
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRow model, ?modelContext::ModelContext) =>
[Id' table] -> IO (Maybe model)
fetchOneOrNothing = forall model value (table :: Symbol).
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO (Maybe model)
genericfetchIdsOneOrNothing
    {-# INLINE fetchOne #-}
    fetchOne :: (Table model, FromRow model, ?modelContext::ModelContext) =>
[Id' table] -> IO model
fetchOne = forall model value (table :: Symbol).
(Table model, KnownSymbol table, FromRow model,
 ?modelContext::ModelContext, ToField value, EqOrIsOperator value,
 HasField "id" model value, model ~ GetModelByTableName table,
 GetTableName model ~ table) =>
[value] -> IO model
genericFetchIdsOne

fetchSQLQuery :: (PG.FromRow model, ?modelContext :: ModelContext) => SQLQuery -> IO [model]
fetchSQLQuery :: forall model.
(FromRow model, ?modelContext::ModelContext) =>
SQLQuery -> IO [model]
fetchSQLQuery SQLQuery
theQuery = do
    let (ByteString
sql, [Action]
theParameters) = SQLQuery -> (ByteString, [Action])
toSQL' SQLQuery
theQuery
    (?modelContext::ModelContext) => ByteString -> IO ()
trackTableRead (forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "selectFrom" a => a
#selectFrom SQLQuery
theQuery)
    forall q r.
(?modelContext::ModelContext, ToRow q, FromRow r) =>
Query -> q -> IO [r]
sqlQuery (ByteString -> Query
Query forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs ByteString
sql) [Action]
theParameters

-- | 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
--
fetchLatest :: forall table queryBuilderProvider joinRegister 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)
fetchLatest :: forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (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)
fetchLatest queryBuilderProvider table
queryBuilder = queryBuilderProvider table
queryBuilder forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (table :: Symbol) (createdAt :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (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)
fetchLatestBy forall a. IsLabel "createdAt" a => a
#createdAt

-- | 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
--
fetchLatestBy :: forall table createdAt queryBuilderProvider joinRegister 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)
fetchLatestBy :: forall {k} (table :: Symbol) (createdAt :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (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)
fetchLatestBy Proxy createdAt
field queryBuilderProvider table
queryBuilder =
    queryBuilderProvider table
queryBuilder
    forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall {k} (name :: Symbol) model (table :: Symbol) value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, HasField name model value,
 model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister, Table model) =>
Proxy name
-> queryBuilderProvider table -> queryBuilderProvider table
orderByDesc Proxy createdAt
field
    forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing