{-# LANGUAGE BangPatterns, TypeFamilies, DataKinds, PolyKinds, TypeApplications, ScopedTypeVariables, 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
, genericFetchId
, genericfetchIdOneOrNothing
, genericFetchIdOne
, Fetchable (..)
, genericFetchIds
, genericfetchIdsOneOrNothing
, genericFetchIdsOne
, fetchCount
, fetchExists
, fetchLatest
, fetchLatestBy
)
where

import IHP.Prelude
import IHP.ModelSupport
import IHP.QueryBuilder
import IHP.Hasql.FromRow (FromRowHasql(..), HasqlDecodeColumn(..))
import IHP.QueryBuilder.HasqlCompiler (buildSnippet)
import qualified Hasql.Decoders as Decoders
import qualified Hasql.DynamicStatements.Snippet as Snippet
import Hasql.Implicits.Encoders (DefaultParamEncoder)

class Fetchable fetchable model | fetchable -> model where
    type FetchResult fetchable model
    fetch :: (Table model, FromRowHasql model, ?modelContext :: ModelContext) => fetchable -> IO (FetchResult fetchable model)
    fetchOneOrNothing :: (Table model, FromRowHasql model, ?modelContext :: ModelContext) => fetchable -> IO (Maybe model)
    fetchOne :: (Table model, FromRowHasql 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, FromRowHasql model, ?modelContext :: ModelContext) => QueryBuilder table -> IO [model]
    fetch :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
QueryBuilder table -> IO [model]
fetch = QueryBuilder table -> IO [model]
forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRowHasql model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch

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

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, FromRowHasql model) => QueryBuilder table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRowHasql model) =>
QueryBuilder table -> IO model
fetchOne = QueryBuilder table -> IO model
forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRowHasql 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, FromRowHasql model, ?modelContext :: ModelContext) => JoinQueryBuilderWrapper r table -> IO [model]
    fetch :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
JoinQueryBuilderWrapper r table -> IO [model]
fetch = JoinQueryBuilderWrapper r table -> IO [model]
forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRowHasql model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch

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

    {-# INLINE fetchOne #-}
    fetchOne :: (?modelContext :: ModelContext) => (Table model, FromRowHasql model) => JoinQueryBuilderWrapper r table -> IO model
    fetchOne :: (?modelContext::ModelContext, Table model, FromRowHasql model) =>
JoinQueryBuilderWrapper r table -> IO model
fetchOne = JoinQueryBuilderWrapper r table -> IO model
forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(?modelContext::ModelContext, Table model, KnownSymbol table,
 Fetchable (queryBuilderProvider table) model,
 HasQueryBuilder queryBuilderProvider joinRegister,
 FromRowHasql 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, FromRowHasql model, ?modelContext :: ModelContext) => NoJoinQueryBuilderWrapper table -> IO [model]
    fetch :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
NoJoinQueryBuilderWrapper table -> IO [model]
fetch = NoJoinQueryBuilderWrapper table -> IO [model]
forall {k} model (table :: Symbol)
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(Table model, HasQueryBuilder queryBuilderProvider joinRegister,
 model ~ GetModelByTableName table, KnownSymbol table,
 FromRowHasql model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch

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

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

instance (model ~ GetModelByTableName table, KnownSymbol table, HasqlDecodeColumn 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]
    {-# INLINE fetch #-}
    fetch :: (Table model, FromRowHasql model, ?modelContext :: ModelContext) => LabeledQueryBuilderWrapper foreignTable columnName value table -> IO [LabeledData value model]
    fetch :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
LabeledQueryBuilderWrapper foreignTable columnName value table
-> IO [LabeledData value model]
fetch !LabeledQueryBuilderWrapper foreignTable columnName value table
queryBuilderProvider = do
        (?modelContext::ModelContext) => Text -> IO ()
Text -> IO ()
trackTableRead (forall record. Table record => Text
tableName @model)
        let pool :: Pool
pool = ?modelContext::ModelContext
ModelContext
?modelContext.hasqlPool
        let snippet :: Snippet
snippet = SQLQuery -> Snippet
buildSnippet (LabeledQueryBuilderWrapper foreignTable columnName value table
-> SQLQuery
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery LabeledQueryBuilderWrapper foreignTable columnName value table
queryBuilderProvider)
        Pool
-> Snippet
-> Result [LabeledData value model]
-> IO [LabeledData value model]
forall a.
(?modelContext::ModelContext) =>
Pool -> Snippet -> Result a -> IO a
sqlQueryHasql Pool
pool Snippet
snippet (Row (LabeledData value model) -> Result [LabeledData value model]
forall a. Row a -> Result [a]
Decoders.rowList (forall a. FromRowHasql a => Row a
hasqlRowDecoder @(LabeledData value model)))

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

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



{-# INLINE commonFetch #-}
commonFetch :: forall model table queryBuilderProvider joinRegister. (Table model, HasQueryBuilder queryBuilderProvider joinRegister, model ~ GetModelByTableName table, KnownSymbol table, FromRowHasql 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,
 FromRowHasql model, ?modelContext::ModelContext) =>
queryBuilderProvider table -> IO [model]
commonFetch !queryBuilderProvider table
queryBuilder = do
    (?modelContext::ModelContext) => Text -> IO ()
Text -> IO ()
trackTableRead (forall record. Table record => Text
tableName @model)
    let !sqlQuery' :: SQLQuery
sqlQuery' = queryBuilderProvider table -> SQLQuery
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery queryBuilderProvider table
queryBuilder
    let pool :: Pool
pool = ?modelContext::ModelContext
ModelContext
?modelContext.hasqlPool
    let snippet :: Snippet
snippet = SQLQuery -> Snippet
buildSnippet SQLQuery
sqlQuery'
    let decoder :: Result [model]
decoder = Row model -> Result [model]
forall a. Row a -> Result [a]
Decoders.rowList (forall a. FromRowHasql a => Row a
hasqlRowDecoder @model)
    Pool -> Snippet -> Result [model] -> IO [model]
forall a.
(?modelContext::ModelContext) =>
Pool -> Snippet -> Result a -> IO a
sqlQueryHasql Pool
pool Snippet
snippet Result [model]
decoder

{-# INLINE commonFetchOneOrNothing #-}
commonFetchOneOrNothing :: forall model table queryBuilderProvider joinRegister. (?modelContext :: ModelContext) => (Table model, KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister, FromRowHasql 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,
 FromRowHasql model) =>
queryBuilderProvider table -> IO (Maybe model)
commonFetchOneOrNothing !queryBuilderProvider table
queryBuilder = do
    (?modelContext::ModelContext) => Text -> IO ()
Text -> IO ()
trackTableRead (forall record. Table record => Text
tableName @model)
    let !limitedQuery :: SQLQuery
limitedQuery = queryBuilderProvider table
queryBuilder queryBuilderProvider table
-> (queryBuilderProvider table -> SQLQuery) -> SQLQuery
forall a b. a -> (a -> b) -> b
|> queryBuilderProvider table -> SQLQuery
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery SQLQuery -> (SQLQuery -> SQLQuery) -> SQLQuery
forall a b. a -> (a -> b) -> b
|> Proxy "limitClause" -> Int -> SQLQuery -> SQLQuery
forall model (name :: Symbol) value.
(KnownSymbol name, SetField name model (Maybe value)) =>
Proxy name -> value -> model -> model
setJust Proxy "limitClause"
#limitClause Int
1
    let pool :: Pool
pool = ?modelContext::ModelContext
ModelContext
?modelContext.hasqlPool
    let snippet :: Snippet
snippet = SQLQuery -> Snippet
buildSnippet SQLQuery
limitedQuery
    let decoder :: Result (Maybe model)
decoder = Row model -> Result (Maybe model)
forall a. Row a -> Result (Maybe a)
Decoders.rowMaybe (forall a. FromRowHasql a => Row a
hasqlRowDecoder @model)
    Pool -> Snippet -> Result (Maybe model) -> IO (Maybe model)
forall a.
(?modelContext::ModelContext) =>
Pool -> Snippet -> Result a -> IO a
sqlQueryHasql Pool
pool Snippet
snippet Result (Maybe model)
decoder

{-# INLINE commonFetchOne #-}
commonFetchOne :: forall model table queryBuilderProvider joinRegister. (?modelContext :: ModelContext) => (Table model, KnownSymbol table, Fetchable (queryBuilderProvider table) model, HasQueryBuilder queryBuilderProvider joinRegister, FromRowHasql 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,
 FromRowHasql model) =>
queryBuilderProvider table -> IO model
commonFetchOne !queryBuilderProvider table
queryBuilder = do
    maybeModel <- queryBuilderProvider table -> IO (Maybe model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing queryBuilderProvider table
queryBuilder
    case maybeModel of
        Just model
model -> model -> IO model
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure model
model
        Maybe model
Nothing -> RecordNotFoundException -> IO model
forall (m :: * -> *) e a.
(HasCallStack, MonadThrow m, Exception e) =>
e -> m a
throwIO RecordNotFoundException { queryAndParams :: Text
queryAndParams = Snippet -> Text
snippetToSQL (queryBuilderProvider table -> Snippet
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> Snippet
toSnippet 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 snippet :: Snippet
snippet = Text -> Snippet
Snippet.sql Text
"SELECT COUNT(*) FROM (" Snippet -> Snippet -> Snippet
forall a. Semigroup a => a -> a -> a
<> SQLQuery -> Snippet
buildSnippet (queryBuilderProvider table -> SQLQuery
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery queryBuilderProvider table
queryBuilder) Snippet -> Snippet -> Snippet
forall a. Semigroup a => a -> a -> a
<> Text -> Snippet
Snippet.sql Text
") AS _count_values"
    (?modelContext::ModelContext) => Text -> IO ()
Text -> IO ()
trackTableRead (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @table)
    let pool :: Pool
pool = ?modelContext::ModelContext
ModelContext
?modelContext.hasqlPool
    Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> IO Int64 -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pool -> Snippet -> Result Int64 -> IO Int64
forall a.
(?modelContext::ModelContext) =>
Pool -> Snippet -> Result a -> IO a
sqlQueryHasql Pool
pool Snippet
snippet (Row Int64 -> Result Int64
forall a. Row a -> Result a
Decoders.singleRow (NullableOrNot Value Int64 -> Row Int64
forall a. NullableOrNot Value a -> Row a
Decoders.column (Value Int64 -> NullableOrNot Value Int64
forall (decoder :: * -> *) a. decoder a -> NullableOrNot decoder a
Decoders.nonNullable Value Int64
Decoders.int8)))
{-# 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 snippet :: Snippet
snippet = Text -> Snippet
Snippet.sql Text
"SELECT EXISTS (" Snippet -> Snippet -> Snippet
forall a. Semigroup a => a -> a -> a
<> SQLQuery -> Snippet
buildSnippet (queryBuilderProvider table -> SQLQuery
forall {k} (table :: Symbol) (queryBuilderProvider :: Symbol -> *)
       (joinRegister :: k).
(KnownSymbol table,
 HasQueryBuilder queryBuilderProvider joinRegister) =>
queryBuilderProvider table -> SQLQuery
buildQuery queryBuilderProvider table
queryBuilder) Snippet -> Snippet -> Snippet
forall a. Semigroup a => a -> a -> a
<> Text -> Snippet
Snippet.sql Text
") AS _exists_values"
    (?modelContext::ModelContext) => Text -> IO ()
Text -> IO ()
trackTableRead (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @table)
    let pool :: Pool
pool = ?modelContext::ModelContext
ModelContext
?modelContext.hasqlPool
    Pool -> Snippet -> Result Bool -> IO Bool
forall a.
(?modelContext::ModelContext) =>
Pool -> Snippet -> Result a -> IO a
sqlQueryHasql Pool
pool Snippet
snippet (Row Bool -> Result Bool
forall a. Row a -> Result a
Decoders.singleRow (NullableOrNot Value Bool -> Row Bool
forall a. NullableOrNot Value a -> Row a
Decoders.column (Value Bool -> NullableOrNot Value Bool
forall (decoder :: * -> *) a. decoder a -> NullableOrNot decoder a
Decoders.nonNullable Value Bool
Decoders.bool)))
{-# INLINE fetchExists #-}

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

{-# INLINE genericfetchIdOneOrNothing #-}
genericfetchIdOneOrNothing :: forall table model. (Table model, KnownSymbol table, FromRowHasql 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, FromRowHasql 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 QueryBuilder table
-> (QueryBuilder table -> QueryBuilder table) -> QueryBuilder table
forall a b. a -> (a -> b) -> b
|> Id' table -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
FilterPrimaryKey table =>
Id' table -> QueryBuilder table -> QueryBuilder table
filterWhereId Id' table
id QueryBuilder table
-> (QueryBuilder table -> IO (Maybe model)) -> IO (Maybe model)
forall a b. a -> (a -> b) -> b
|> QueryBuilder table -> IO (Maybe model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing

{-# INLINE genericFetchIdOne #-}
genericFetchIdOne :: forall table model. (Table model, KnownSymbol table, FromRowHasql model, ?modelContext :: ModelContext, FilterPrimaryKey table, model ~ GetModelByTableName table, GetTableName model ~ table) => Id' table -> IO model
genericFetchIdOne :: forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql 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 QueryBuilder table
-> (QueryBuilder table -> QueryBuilder table) -> QueryBuilder table
forall a b. a -> (a -> b) -> b
|> Id' table -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
FilterPrimaryKey table =>
Id' table -> QueryBuilder table -> QueryBuilder table
filterWhereId Id' table
id QueryBuilder table -> (QueryBuilder table -> IO model) -> IO model
forall a b. a -> (a -> b) -> b
|> QueryBuilder table -> IO model
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO model
fetchOne

{-# INLINE genericFetchIds #-}
genericFetchIds :: forall table model. (Table model, KnownSymbol table, FromRowHasql model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table, DefaultParamEncoder [PrimaryKey (GetTableName model)]) => [Id model] -> IO [model]
genericFetchIds :: forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO [model]
genericFetchIds ![Id model]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model QueryBuilder table
-> (QueryBuilder table -> QueryBuilder table) -> QueryBuilder table
forall a b. a -> (a -> b) -> b
|> [Id model] -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol) model
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, Table model, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model]
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIdIn [Id model]
ids QueryBuilder table
-> (QueryBuilder table -> IO [model]) -> IO [model]
forall a b. a -> (a -> b) -> b
|> QueryBuilder table -> IO [model]
QueryBuilder table -> IO (FetchResult (QueryBuilder table) model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO (FetchResult fetchable model)
fetch

{-# INLINE genericfetchIdsOneOrNothing #-}
genericfetchIdsOneOrNothing :: forall table model. (Table model, KnownSymbol table, FromRowHasql model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table, DefaultParamEncoder [PrimaryKey (GetTableName model)]) => [Id model] -> IO (Maybe model)
genericfetchIdsOneOrNothing :: forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO (Maybe model)
genericfetchIdsOneOrNothing ![Id model]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model QueryBuilder table
-> (QueryBuilder table -> QueryBuilder table) -> QueryBuilder table
forall a b. a -> (a -> b) -> b
|> [Id model] -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol) model
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, Table model, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model]
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIdIn [Id model]
ids QueryBuilder table
-> (QueryBuilder table -> IO (Maybe model)) -> IO (Maybe model)
forall a b. a -> (a -> b) -> b
|> QueryBuilder table -> IO (Maybe model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing

{-# INLINE genericFetchIdsOne #-}
genericFetchIdsOne :: forall table model. (Table model, KnownSymbol table, FromRowHasql model, ?modelContext :: ModelContext, model ~ GetModelByTableName table, GetTableName model ~ table, DefaultParamEncoder [PrimaryKey (GetTableName model)]) => [Id model] -> IO model
genericFetchIdsOne :: forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO model
genericFetchIdsOne ![Id model]
ids = forall model (table :: Symbol).
(table ~ GetTableName model, Table model, DefaultScope table) =>
QueryBuilder table
query @model QueryBuilder table
-> (QueryBuilder table -> QueryBuilder table) -> QueryBuilder table
forall a b. a -> (a -> b) -> b
|> [Id model] -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol) model
       (queryBuilderProvider :: Symbol -> *) joinRegister.
(KnownSymbol table, Table model, model ~ GetModelByTableName table,
 HasQueryBuilder queryBuilderProvider joinRegister,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model]
-> queryBuilderProvider table -> queryBuilderProvider table
filterWhereIdIn [Id model]
ids QueryBuilder table -> (QueryBuilder table -> IO model) -> IO model
forall a b. a -> (a -> b) -> b
|> QueryBuilder table -> IO model
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql 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 queryBuilderProvider table
-> (queryBuilderProvider table -> queryBuilderProvider table)
-> queryBuilderProvider table
forall a b. a -> (a -> b) -> b
|> (Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder 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) queryBuilderProvider table
-> (queryBuilderProvider table -> IO model) -> IO model
forall a b. a -> (a -> b) -> b
|> queryBuilderProvider table -> IO model
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql 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 queryBuilderProvider table
-> (queryBuilderProvider table -> queryBuilderProvider table)
-> queryBuilderProvider table
forall a b. a -> (a -> b) -> b
|> (Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder 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) queryBuilderProvider table
-> (queryBuilderProvider table -> IO (Maybe model))
-> IO (Maybe model)
forall a b. a -> (a -> b) -> b
|> queryBuilderProvider table -> IO (Maybe model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql 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 queryBuilderProvider table
-> (queryBuilderProvider table -> queryBuilderProvider table)
-> queryBuilderProvider table
forall a b. a -> (a -> b) -> b
|> (Proxy name, value)
-> queryBuilderProvider table -> queryBuilderProvider table
forall {k} (name :: Symbol) (table :: Symbol) model value
       (queryBuilderProvider :: Symbol -> *) (joinRegister :: k).
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder 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) queryBuilderProvider table
-> (queryBuilderProvider table
    -> IO (FetchResult (queryBuilderProvider table) model))
-> IO (FetchResult (queryBuilderProvider table) model)
forall a b. a -> (a -> b) -> b
|> queryBuilderProvider table
-> IO (FetchResult (queryBuilderProvider table) model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql 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, FromRowHasql model, ?modelContext::ModelContext) =>
Id' table -> IO (FetchResult (Id' table) model)
fetch = Id' table -> IO model
Id' table -> IO (FetchResult (Id' table) model)
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO model
genericFetchIdOne
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
Id' table -> IO (Maybe model)
fetchOneOrNothing = Id' table -> IO (Maybe model)
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO (Maybe model)
genericfetchIdOneOrNothing
    {-# INLINE fetchOne #-}
    fetchOne :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
Id' table -> IO model
fetchOne = Id' table -> IO model
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql 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, FromRowHasql model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO (FetchResult (Maybe (Id' table)) model)
fetch (Just Id' table
a) = Id' table -> IO [model]
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO [model]
genericFetchId Id' table
a
    fetch Maybe (Id' table)
Nothing = [model] -> IO [model]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO (Maybe model)
fetchOneOrNothing Maybe (Id' table)
Nothing = Maybe model -> IO (Maybe model)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe model
forall a. Maybe a
Nothing
    fetchOneOrNothing (Just Id' table
a) = Id' table -> IO (Maybe model)
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql 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, FromRowHasql model, ?modelContext::ModelContext) =>
Maybe (Id' table) -> IO model
fetchOne (Just Id' table
a) = Id' table -> IO model
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, FilterPrimaryKey table,
 model ~ GetModelByTableName table, GetTableName model ~ table) =>
Id' table -> IO model
genericFetchIdOne Id' table
a
    fetchOne Maybe (Id' table)
Nothing = Text -> IO model
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), GetModelByTableName table ~ model, GetTableName model ~ table, DefaultParamEncoder [PrimaryKey table]) => Fetchable [Id' table] model where
    type FetchResult [Id' table] model = [model]
    {-# INLINE fetch #-}
    fetch :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
[Id' table] -> IO (FetchResult [Id' table] model)
fetch = [Id' table] -> IO (FetchResult [Id' table] model)
[Id (GetModelByTableName table)] -> IO [GetModelByTableName table]
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO [model]
genericFetchIds
    {-# INLINE fetchOneOrNothing #-}
    fetchOneOrNothing :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
[Id' table] -> IO (Maybe model)
fetchOneOrNothing = [Id' table] -> IO (Maybe model)
[Id model] -> IO (Maybe model)
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO (Maybe model)
genericfetchIdsOneOrNothing
    {-# INLINE fetchOne #-}
    fetchOne :: (Table model, FromRowHasql model, ?modelContext::ModelContext) =>
[Id' table] -> IO model
fetchOne = [Id' table] -> IO model
[Id model] -> IO model
forall (table :: Symbol) model.
(Table model, KnownSymbol table, FromRowHasql model,
 ?modelContext::ModelContext, model ~ GetModelByTableName table,
 GetTableName model ~ table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> IO model
genericFetchIdsOne

-- | 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
    , FromRowHasql 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,
 FromRowHasql model) =>
queryBuilderProvider table -> IO (Maybe model)
fetchLatest queryBuilderProvider table
queryBuilder = queryBuilderProvider table
queryBuilder queryBuilderProvider table
-> (queryBuilderProvider table -> IO (Maybe model))
-> IO (Maybe model)
forall a b. a -> (a -> b) -> b
|> Proxy "createdAt" -> queryBuilderProvider table -> IO (Maybe model)
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,
 FromRowHasql model) =>
Proxy createdAt -> queryBuilderProvider table -> IO (Maybe model)
fetchLatestBy Proxy "createdAt"
#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
    , FromRowHasql 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,
 FromRowHasql model) =>
Proxy createdAt -> queryBuilderProvider table -> IO (Maybe model)
fetchLatestBy Proxy createdAt
field queryBuilderProvider table
queryBuilder =
    queryBuilderProvider table
queryBuilder
    queryBuilderProvider table
-> (queryBuilderProvider table -> queryBuilderProvider table)
-> queryBuilderProvider table
forall a b. a -> (a -> b) -> b
|> Proxy createdAt
-> queryBuilderProvider table -> queryBuilderProvider table
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
    queryBuilderProvider table
-> (queryBuilderProvider table -> IO (Maybe model))
-> IO (Maybe model)
forall a b. a -> (a -> b) -> b
|> queryBuilderProvider table -> IO (Maybe model)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRowHasql model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing