packages feed

esqueleto 3.4.0.0 → 3.4.0.1

raw patch · 17 files changed

+6601/−6448 lines, 17 filesdep ~persistentdep ~persistent-postgresqlPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: persistent, persistent-postgresql

API changes (from Hackage documentation)

- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToAlias a, a' GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT a, Database.Esqueleto.Experimental.ToAliasReference a', a'' GHC.Types.~ Database.Esqueleto.Experimental.ToAliasReferenceT a', Database.Esqueleto.Internal.Internal.SqlSelect a' r', Database.Esqueleto.Internal.Internal.SqlSelect a'' r') => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.SqlQuery a)
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a', Database.Esqueleto.Experimental.ToInnerJoin (Database.Esqueleto.Experimental.IsLateral b) a b b') => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.InnerJoin a (b, b' -> Database.Esqueleto.Internal.Internal.SqlExpr (Database.Esqueleto.Internal.Internal.Value GHC.Types.Bool)))
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a', Database.Esqueleto.Internal.Internal.SqlSelect bAlias r, Database.Esqueleto.Internal.Internal.SqlSelect bAliasRef r', Database.Esqueleto.Experimental.ToAlias b, bAlias GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT b, Database.Esqueleto.Experimental.ToAliasReference bAlias, bAliasRef GHC.Types.~ Database.Esqueleto.Experimental.ToAliasReferenceT bAlias) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.CrossJoin a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b))
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a', Database.Esqueleto.Internal.Internal.SqlSelect bAlias r, Database.Esqueleto.Internal.Internal.SqlSelect bAliasRef r', Database.Esqueleto.Experimental.ToAlias b, bAlias GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT b, Database.Esqueleto.Experimental.ToAliasReference bAlias, bAliasRef GHC.Types.~ Database.Esqueleto.Experimental.ToAliasReferenceT bAlias, Database.Esqueleto.Experimental.ToMaybe bAliasRef, mb GHC.Types.~ Database.Esqueleto.Experimental.ToMaybeT bAliasRef) => Database.Esqueleto.Experimental.ToLeftJoin Database.Esqueleto.Experimental.Lateral a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b) (a' Database.Esqueleto.Experimental.:& mb)
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect a' r, Database.Esqueleto.Internal.Internal.SqlSelect a'' r', Database.Esqueleto.Experimental.ToAlias a, a' GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT a, Database.Esqueleto.Experimental.ToAliasReference a', Database.Esqueleto.Experimental.ToAliasReferenceT a' GHC.Types.~ a'') => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.SqlSetOperation a)
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect bAlias r, Database.Esqueleto.Internal.Internal.SqlSelect bAliasRef r', Database.Esqueleto.Experimental.ToAlias b, bAlias GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT b, Database.Esqueleto.Experimental.ToAliasReference bAlias, bAliasRef GHC.Types.~ Database.Esqueleto.Experimental.ToAliasReferenceT bAlias, Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a') => Database.Esqueleto.Experimental.ToInnerJoin Database.Esqueleto.Experimental.Lateral a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b) (a' Database.Esqueleto.Experimental.:& bAliasRef)
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c' r, Database.Esqueleto.Internal.Internal.SqlSelect c'' r', Database.Esqueleto.Experimental.ToAlias c, c' GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT c, Database.Esqueleto.Experimental.ToAliasReference c', Database.Esqueleto.Experimental.ToAliasReferenceT c' GHC.Types.~ c'', Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.Union a b)
- Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c' r, Database.Esqueleto.Internal.Internal.SqlSelect c'' r', Database.Esqueleto.Experimental.ToAlias c, c' GHC.Types.~ Database.Esqueleto.Experimental.ToAliasT c, Database.Esqueleto.Experimental.ToAliasReference c', Database.Esqueleto.Experimental.ToAliasReferenceT c' GHC.Types.~ c'', Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.UnionAll a b)
- Database.Esqueleto.Experimental: instance (TypeError ...) => Database.Esqueleto.Experimental.ErrorOnLateral (a -> Database.Esqueleto.Internal.Internal.SqlQuery b)
- Database.Esqueleto.Experimental: instance (TypeError ...) => Database.Esqueleto.Experimental.ValidOnClauseValue a
- Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ErrorOnLateral a
- Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ValidOnClauseValue (Database.Esqueleto.Experimental.From a)
- Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ValidOnClauseValue (Database.Esqueleto.Experimental.SqlSetOperation a)
- Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ValidOnClauseValue (Database.Esqueleto.Internal.Internal.SqlQuery a)
- Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ValidOnClauseValue (a -> Database.Esqueleto.Internal.Internal.SqlQuery b)
+ Database.Esqueleto: --
+ Database.Esqueleto: -- <a>EntityField</a> values polymorphically. See the documentation on
+ Database.Esqueleto: -- <a>SymbolToField</a> for more information.
+ Database.Esqueleto: -- <tt>OverloadedLabels</tt> language extension to refer to
+ Database.Esqueleto: -- As of <tt>persistent-2.11.0.0</tt>, it's possible to use the
+ Database.Esqueleto: PersistLiteral :: ByteString -> PersistValue
+ Database.Esqueleto: PersistLiteralEscaped :: ByteString -> PersistValue
+ Database.Esqueleto: [cGenerated] :: Column -> !Maybe Text
+ Database.Esqueleto: [fieldCascade] :: FieldDef -> !FieldCascade
+ Database.Esqueleto: [fieldGenerated] :: FieldDef -> !Maybe Text
+ Database.Esqueleto: [foreignFieldCascade] :: ForeignDef -> !FieldCascade
+ Database.Esqueleto: [foreignToPrimary] :: ForeignDef -> Bool
+ Database.Esqueleto: keyFromRecordM :: PersistEntity record => Maybe (record -> Key record)
+ Database.Esqueleto.Experimental: --
+ Database.Esqueleto.Experimental: -- <a>EntityField</a> values polymorphically. See the documentation on
+ Database.Esqueleto.Experimental: -- <a>SymbolToField</a> for more information.
+ Database.Esqueleto.Experimental: -- <tt>OverloadedLabels</tt> language extension to refer to
+ Database.Esqueleto.Experimental: -- As of <tt>persistent-2.11.0.0</tt>, it's possible to use the
+ Database.Esqueleto.Experimental: PersistLiteral :: ByteString -> PersistValue
+ Database.Esqueleto.Experimental: PersistLiteralEscaped :: ByteString -> PersistValue
+ Database.Esqueleto.Experimental: [cGenerated] :: Column -> !Maybe Text
+ Database.Esqueleto.Experimental: [fieldCascade] :: FieldDef -> !FieldCascade
+ Database.Esqueleto.Experimental: [fieldGenerated] :: FieldDef -> !Maybe Text
+ Database.Esqueleto.Experimental: [foreignFieldCascade] :: ForeignDef -> !FieldCascade
+ Database.Esqueleto.Experimental: [foreignToPrimary] :: ForeignDef -> Bool
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToAlias a, Database.Esqueleto.Experimental.ToAliasReference a, Database.Esqueleto.Internal.Internal.SqlSelect a r) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.SqlQuery a)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a', Database.Esqueleto.Internal.Internal.SqlSelect b r, Database.Esqueleto.Experimental.ToAlias b, Database.Esqueleto.Experimental.ToAliasReference b) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.CrossJoin a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b))
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a', Database.Esqueleto.Internal.Internal.SqlSelect b r, Database.Esqueleto.Experimental.ToAlias b, Database.Esqueleto.Experimental.ToAliasReference b, Database.Esqueleto.Experimental.ToMaybe b, mb GHC.Types.~ Database.Esqueleto.Experimental.ToMaybeT b) => Database.Esqueleto.Experimental.ToLeftJoin Database.Esqueleto.Experimental.Lateral a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b) (a' Database.Esqueleto.Experimental.:& mb)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect a r, Database.Esqueleto.Experimental.ToAlias a, Database.Esqueleto.Experimental.ToAliasReference a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.SqlSetOperation a)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect b r, Database.Esqueleto.Experimental.ToAlias b, Database.Esqueleto.Experimental.ToAliasReference b, Database.Esqueleto.Experimental.ToFrom a, Database.Esqueleto.Experimental.ToFromT a GHC.Types.~ a') => Database.Esqueleto.Experimental.ToInnerJoin Database.Esqueleto.Experimental.Lateral a (a' -> Database.Esqueleto.Internal.Internal.SqlQuery b) (a' Database.Esqueleto.Experimental.:& b)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c r, Database.Esqueleto.Experimental.ToAlias c, Database.Esqueleto.Experimental.ToAliasReference c, Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.Except a b)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c r, Database.Esqueleto.Experimental.ToAlias c, Database.Esqueleto.Experimental.ToAliasReference c, Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.Intersect a b)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c r, Database.Esqueleto.Experimental.ToAlias c, Database.Esqueleto.Experimental.ToAliasReference c, Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.Union a b)
+ Database.Esqueleto.Experimental: instance (Database.Esqueleto.Internal.Internal.SqlSelect c r, Database.Esqueleto.Experimental.ToAlias c, Database.Esqueleto.Experimental.ToAliasReference c, Database.Esqueleto.Experimental.ToSetOperation a c, Database.Esqueleto.Experimental.ToSetOperation b c, c GHC.Types.~ Database.Esqueleto.Experimental.SetOperationT a) => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Experimental.UnionAll a b)
+ Database.Esqueleto.Experimental: instance Database.Esqueleto.Experimental.ToInnerJoin (Database.Esqueleto.Experimental.IsLateral b) a b b' => Database.Esqueleto.Experimental.ToFrom (Database.Esqueleto.Internal.Internal.InnerJoin a (b, b' -> Database.Esqueleto.Internal.Internal.SqlExpr (Database.Esqueleto.Internal.Internal.Value GHC.Types.Bool)))
+ Database.Esqueleto.Experimental: keyFromRecordM :: PersistEntity record => Maybe (record -> Key record)
+ Database.Esqueleto.Experimental: type ToAliasReferenceT a = a
+ Database.Esqueleto.Experimental: type ToAliasT a = a
- Database.Esqueleto: Column :: !DBName -> !Bool -> !SqlType -> !Maybe Text -> !Maybe DBName -> !Maybe Integer -> !Maybe (DBName, DBName) -> Column
+ Database.Esqueleto: Column :: !DBName -> !Bool -> !SqlType -> !Maybe Text -> !Maybe Text -> !Maybe DBName -> !Maybe Integer -> !Maybe ColumnReference -> Column
- Database.Esqueleto: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> !Maybe Text -> FieldDef
+ Database.Esqueleto: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![FieldAttr] -> !Bool -> !ReferenceDef -> !FieldCascade -> !Maybe Text -> !Maybe Text -> FieldDef
- Database.Esqueleto: ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> ForeignDef
+ Database.Esqueleto: ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> !FieldCascade -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> Bool -> ForeignDef
- Database.Esqueleto: SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend
+ Database.Esqueleto: SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty (HaskellName, DBName) -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend
- Database.Esqueleto: [cReference] :: Column -> !Maybe (DBName, DBName)
+ Database.Esqueleto: [cReference] :: Column -> !Maybe ColumnReference
- Database.Esqueleto: [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text)
+ Database.Esqueleto: [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty (HaskellName, DBName) -> Text -> Text)
- Database.Esqueleto: [fieldAttrs] :: FieldDef -> ![Attr]
+ Database.Esqueleto: [fieldAttrs] :: FieldDef -> ![FieldAttr]
- Database.Esqueleto: belongsTo :: forall backend ent1 ent2 (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2)
+ Database.Esqueleto: belongsTo :: forall ent1 ent2 backend (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2)
- Database.Esqueleto: belongsToJust :: forall backend ent1 ent2 (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2
+ Database.Esqueleto: belongsToJust :: forall ent1 ent2 backend (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2
- Database.Esqueleto: checkUnique :: forall (m :: Type -> Type) record backend. (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m (Maybe (Unique record))
+ Database.Esqueleto: checkUnique :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m (Maybe (Unique record))
- Database.Esqueleto: createSqlPool :: (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend)
+ Database.Esqueleto: createSqlPool :: forall backend m. (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend)
- Database.Esqueleto: defaultAttribute :: [Attr] -> Maybe Text
+ Database.Esqueleto: defaultAttribute :: [FieldAttr] -> Maybe Text
- Database.Esqueleto: deleteBy :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m ()
+ Database.Esqueleto: deleteBy :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m ()
- Database.Esqueleto: entityDef :: (PersistEntity record, Monad m) => m record -> EntityDef
+ Database.Esqueleto: entityDef :: PersistEntity record => proxy record -> EntityDef
- Database.Esqueleto: get :: forall (m :: Type -> Type) record. (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m (Maybe record)
+ Database.Esqueleto: get :: forall record (m :: Type -> Type). (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m (Maybe record)
- Database.Esqueleto: getBy :: forall (m :: Type -> Type) record. (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m (Maybe (Entity record))
+ Database.Esqueleto: getBy :: forall record (m :: Type -> Type). (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m (Maybe (Entity record))
- Database.Esqueleto: getEntity :: forall backend e (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m (Maybe (Entity e))
+ Database.Esqueleto: getEntity :: forall e backend (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m (Maybe (Entity e))
- Database.Esqueleto: getJust :: forall backend record (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
+ Database.Esqueleto: getJust :: forall record backend (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
- Database.Esqueleto: getMany :: forall (m :: Type -> Type) record. (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m (Map (Key record) record)
+ Database.Esqueleto: getMany :: forall record (m :: Type -> Type). (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m (Map (Key record) record)
- Database.Esqueleto: getMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m [Sql]
+ Database.Esqueleto: getMigration :: forall (m :: Type -> Type). (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql]
- Database.Esqueleto: insert :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Key record)
+ Database.Esqueleto: insert :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Key record)
- Database.Esqueleto: insertBy :: forall (m :: Type -> Type) backend record. (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record))
+ Database.Esqueleto: insertBy :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record))
- Database.Esqueleto: insertEntity :: forall backend e (m :: Type -> Type). (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m (Entity e)
+ Database.Esqueleto: insertEntity :: forall e backend (m :: Type -> Type). (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m (Entity e)
- Database.Esqueleto: insertEntityMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m ()
+ Database.Esqueleto: insertEntityMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m ()
- Database.Esqueleto: insertKey :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto: insertKey :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto: insertMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record]
+ Database.Esqueleto: insertMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record]
- Database.Esqueleto: insertMany_ :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Database.Esqueleto: insertMany_ :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
- Database.Esqueleto: insertUnique :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Key record))
+ Database.Esqueleto: insertUnique :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Key record))
- Database.Esqueleto: insertUniqueEntity :: forall (m :: Type -> Type) record backend. (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity record))
+ Database.Esqueleto: insertUniqueEntity :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity record))
- Database.Esqueleto: insert_ :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m ()
+ Database.Esqueleto: insert_ :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m ()
- Database.Esqueleto: liftSqlPersistMPool :: (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a
+ Database.Esqueleto: liftSqlPersistMPool :: forall backend m a. (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a
- Database.Esqueleto: mkColumns :: [EntityDef] -> EntityDef -> ([Column], [UniqueDef], [ForeignDef])
+ Database.Esqueleto: mkColumns :: [EntityDef] -> EntityDef -> BackendSpecificOverrides -> ([Column], [UniqueDef], [ForeignDef])
- Database.Esqueleto: onlyUnique :: forall (m :: Type -> Type) backend record. (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record)
+ Database.Esqueleto: onlyUnique :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record)
- Database.Esqueleto: parseMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
+ Database.Esqueleto: parseMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
- Database.Esqueleto: parseMigration' :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m CautiousMigration
+ Database.Esqueleto: parseMigration' :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration
- Database.Esqueleto: printMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m ()
+ Database.Esqueleto: printMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m ()
- Database.Esqueleto: putMany :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Database.Esqueleto: putMany :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
- Database.Esqueleto: replace :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto: replace :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto: replaceUnique :: forall (m :: Type -> Type) record backend. (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
+ Database.Esqueleto: replaceUnique :: forall record backend (m :: Type -> Type). (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
- Database.Esqueleto: repsert :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto: repsert :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto: repsertMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m ()
+ Database.Esqueleto: repsertMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m ()
- Database.Esqueleto: runSqlConn :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a
+ Database.Esqueleto: runSqlConn :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a
- Database.Esqueleto: runSqlPool :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a
+ Database.Esqueleto: runSqlPool :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a
- Database.Esqueleto: selectKeys :: forall backend (m :: Type -> Type) record. (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
+ Database.Esqueleto: selectKeys :: forall record backend (m :: Type -> Type). (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
- Database.Esqueleto: showMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m [Text]
+ Database.Esqueleto: showMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
- Database.Esqueleto: updateGet :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record
+ Database.Esqueleto: updateGet :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record
- Database.Esqueleto: upsert :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record)
+ Database.Esqueleto: upsert :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record)
- Database.Esqueleto: upsertBy :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record)
+ Database.Esqueleto: upsertBy :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record)
- Database.Esqueleto: withSqlConn :: (MonadUnliftIO m, MonadLogger m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a
+ Database.Esqueleto: withSqlConn :: forall backend m a. (MonadUnliftIO m, MonadLogger m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a
- Database.Esqueleto: withSqlPool :: (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
+ Database.Esqueleto: withSqlPool :: forall backend m a. (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
- Database.Esqueleto.Experimental: Column :: !DBName -> !Bool -> !SqlType -> !Maybe Text -> !Maybe DBName -> !Maybe Integer -> !Maybe (DBName, DBName) -> Column
+ Database.Esqueleto.Experimental: Column :: !DBName -> !Bool -> !SqlType -> !Maybe Text -> !Maybe Text -> !Maybe DBName -> !Maybe Integer -> !Maybe ColumnReference -> Column
- Database.Esqueleto.Experimental: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> !Maybe Text -> FieldDef
+ Database.Esqueleto.Experimental: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![FieldAttr] -> !Bool -> !ReferenceDef -> !FieldCascade -> !Maybe Text -> !Maybe Text -> FieldDef
- Database.Esqueleto.Experimental: ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> ForeignDef
+ Database.Esqueleto.Experimental: ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> !FieldCascade -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> Bool -> ForeignDef
- Database.Esqueleto.Experimental: SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend
+ Database.Esqueleto.Experimental: SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty (HaskellName, DBName) -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend
- Database.Esqueleto.Experimental: [CrossJoinFromLateral] :: (SqlSelect b' r, SqlSelect b'' r', ToAlias b, b' ~ ToAliasT b, ToAliasReference b', ToAliasReferenceT b' ~ b'') => From a -> (a -> SqlQuery b) -> From (a :& b'')
+ Database.Esqueleto.Experimental: [CrossJoinFromLateral] :: (SqlSelect b r, ToAlias b, ToAliasReference b) => From a -> (a -> SqlQuery b) -> From (a :& b)
- Database.Esqueleto.Experimental: [InnerJoinFromLateral] :: (SqlSelect b' r, SqlSelect b'' r', ToAlias b, b' ~ ToAliasT b, ToAliasReference b', ToAliasReferenceT b' ~ b'') => From a -> (a -> SqlQuery b, (a :& b'') -> SqlExpr (Value Bool)) -> From (a :& b'')
+ Database.Esqueleto.Experimental: [InnerJoinFromLateral] :: (SqlSelect b r, ToAlias b, ToAliasReference b) => From a -> (a -> SqlQuery b, (a :& b) -> SqlExpr (Value Bool)) -> From (a :& b)
- Database.Esqueleto.Experimental: [LeftJoinFromLateral] :: (SqlSelect b' r, SqlSelect b'' r', ToAlias b, b' ~ ToAliasT b, ToAliasReference b', ToAliasReferenceT b' ~ b'', ToMaybe b'') => From a -> (a -> SqlQuery b, (a :& ToMaybeT b'') -> SqlExpr (Value Bool)) -> From (a :& ToMaybeT b'')
+ Database.Esqueleto.Experimental: [LeftJoinFromLateral] :: (SqlSelect b r, ToAlias b, ToAliasReference b, ToMaybe b) => From a -> (a -> SqlQuery b, (a :& ToMaybeT b) -> SqlExpr (Value Bool)) -> From (a :& ToMaybeT b)
- Database.Esqueleto.Experimental: [SqlSetOperation] :: (SqlSelect a' r, ToAlias a, a' ~ ToAliasT a, ToAliasReference a', ToAliasReferenceT a' ~ a'') => SqlSetOperation a -> From a''
+ Database.Esqueleto.Experimental: [SqlSetOperation] :: (SqlSelect a r, ToAlias a, ToAliasReference a) => SqlSetOperation a -> From a
- Database.Esqueleto.Experimental: [SubQuery] :: (SqlSelect a' r, SqlSelect a'' r', ToAlias a, a' ~ ToAliasT a, ToAliasReference a', ToAliasReferenceT a' ~ a'') => SqlQuery a -> From a''
+ Database.Esqueleto.Experimental: [SubQuery] :: (SqlSelect a r, ToAlias a, ToAliasReference a) => SqlQuery a -> From a
- Database.Esqueleto.Experimental: [cReference] :: Column -> !Maybe (DBName, DBName)
+ Database.Esqueleto.Experimental: [cReference] :: Column -> !Maybe ColumnReference
- Database.Esqueleto.Experimental: [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text)
+ Database.Esqueleto.Experimental: [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty (HaskellName, DBName) -> Text -> Text)
- Database.Esqueleto.Experimental: [fieldAttrs] :: FieldDef -> ![Attr]
+ Database.Esqueleto.Experimental: [fieldAttrs] :: FieldDef -> ![FieldAttr]
- Database.Esqueleto.Experimental: belongsTo :: forall backend ent1 ent2 (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2)
+ Database.Esqueleto.Experimental: belongsTo :: forall ent1 ent2 backend (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2)
- Database.Esqueleto.Experimental: belongsToJust :: forall backend ent1 ent2 (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2
+ Database.Esqueleto.Experimental: belongsToJust :: forall ent1 ent2 backend (m :: Type -> Type). (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2
- Database.Esqueleto.Experimental: checkUnique :: forall (m :: Type -> Type) record backend. (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m (Maybe (Unique record))
+ Database.Esqueleto.Experimental: checkUnique :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m (Maybe (Unique record))
- Database.Esqueleto.Experimental: class ToFrom a
+ Database.Esqueleto.Experimental: class ToFrom a where {
- Database.Esqueleto.Experimental: class ToMaybe a
+ Database.Esqueleto.Experimental: class ToMaybe a where {
- Database.Esqueleto.Experimental: createSqlPool :: (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend)
+ Database.Esqueleto.Experimental: createSqlPool :: forall backend m. (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend)
- Database.Esqueleto.Experimental: defaultAttribute :: [Attr] -> Maybe Text
+ Database.Esqueleto.Experimental: defaultAttribute :: [FieldAttr] -> Maybe Text
- Database.Esqueleto.Experimental: deleteBy :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: deleteBy :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m ()
- Database.Esqueleto.Experimental: entityDef :: (PersistEntity record, Monad m) => m record -> EntityDef
+ Database.Esqueleto.Experimental: entityDef :: PersistEntity record => proxy record -> EntityDef
- Database.Esqueleto.Experimental: get :: forall (m :: Type -> Type) record. (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m (Maybe record)
+ Database.Esqueleto.Experimental: get :: forall record (m :: Type -> Type). (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m (Maybe record)
- Database.Esqueleto.Experimental: getBy :: forall (m :: Type -> Type) record. (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m (Maybe (Entity record))
+ Database.Esqueleto.Experimental: getBy :: forall record (m :: Type -> Type). (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m (Maybe (Entity record))
- Database.Esqueleto.Experimental: getEntity :: forall backend e (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m (Maybe (Entity e))
+ Database.Esqueleto.Experimental: getEntity :: forall e backend (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m (Maybe (Entity e))
- Database.Esqueleto.Experimental: getJust :: forall backend record (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
+ Database.Esqueleto.Experimental: getJust :: forall record backend (m :: Type -> Type). (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
- Database.Esqueleto.Experimental: getMany :: forall (m :: Type -> Type) record. (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m (Map (Key record) record)
+ Database.Esqueleto.Experimental: getMany :: forall record (m :: Type -> Type). (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m (Map (Key record) record)
- Database.Esqueleto.Experimental: getMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m [Sql]
+ Database.Esqueleto.Experimental: getMigration :: forall (m :: Type -> Type). (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql]
- Database.Esqueleto.Experimental: insert :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Key record)
+ Database.Esqueleto.Experimental: insert :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Key record)
- Database.Esqueleto.Experimental: insertBy :: forall (m :: Type -> Type) backend record. (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record))
+ Database.Esqueleto.Experimental: insertBy :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record))
- Database.Esqueleto.Experimental: insertEntity :: forall backend e (m :: Type -> Type). (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m (Entity e)
+ Database.Esqueleto.Experimental: insertEntity :: forall e backend (m :: Type -> Type). (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m (Entity e)
- Database.Esqueleto.Experimental: insertEntityMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: insertEntityMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m ()
- Database.Esqueleto.Experimental: insertKey :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: insertKey :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto.Experimental: insertMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record]
+ Database.Esqueleto.Experimental: insertMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record]
- Database.Esqueleto.Experimental: insertMany_ :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: insertMany_ :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
- Database.Esqueleto.Experimental: insertUnique :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Key record))
+ Database.Esqueleto.Experimental: insertUnique :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Key record))
- Database.Esqueleto.Experimental: insertUniqueEntity :: forall (m :: Type -> Type) record backend. (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity record))
+ Database.Esqueleto.Experimental: insertUniqueEntity :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity record))
- Database.Esqueleto.Experimental: insert_ :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: insert_ :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m ()
- Database.Esqueleto.Experimental: liftSqlPersistMPool :: (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a
+ Database.Esqueleto.Experimental: liftSqlPersistMPool :: forall backend m a. (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a
- Database.Esqueleto.Experimental: mkColumns :: [EntityDef] -> EntityDef -> ([Column], [UniqueDef], [ForeignDef])
+ Database.Esqueleto.Experimental: mkColumns :: [EntityDef] -> EntityDef -> BackendSpecificOverrides -> ([Column], [UniqueDef], [ForeignDef])
- Database.Esqueleto.Experimental: onlyUnique :: forall (m :: Type -> Type) backend record. (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record)
+ Database.Esqueleto.Experimental: onlyUnique :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record)
- Database.Esqueleto.Experimental: parseMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
+ Database.Esqueleto.Experimental: parseMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
- Database.Esqueleto.Experimental: parseMigration' :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m CautiousMigration
+ Database.Esqueleto.Experimental: parseMigration' :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration
- Database.Esqueleto.Experimental: printMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m ()
+ Database.Esqueleto.Experimental: printMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m ()
- Database.Esqueleto.Experimental: putMany :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: putMany :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
- Database.Esqueleto.Experimental: replace :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: replace :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto.Experimental: replaceUnique :: forall (m :: Type -> Type) record backend. (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
+ Database.Esqueleto.Experimental: replaceUnique :: forall record backend (m :: Type -> Type). (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
- Database.Esqueleto.Experimental: repsert :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: repsert :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
- Database.Esqueleto.Experimental: repsertMany :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m ()
+ Database.Esqueleto.Experimental: repsertMany :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m ()
- Database.Esqueleto.Experimental: runSqlConn :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a
+ Database.Esqueleto.Experimental: runSqlConn :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a
- Database.Esqueleto.Experimental: runSqlPool :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a
+ Database.Esqueleto.Experimental: runSqlPool :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a
- Database.Esqueleto.Experimental: selectKeys :: forall backend (m :: Type -> Type) record. (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
+ Database.Esqueleto.Experimental: selectKeys :: forall record backend (m :: Type -> Type). (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
- Database.Esqueleto.Experimental: showMigration :: forall (m :: Type -> Type). MonadIO m => Migration -> ReaderT SqlBackend m [Text]
+ Database.Esqueleto.Experimental: showMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
- Database.Esqueleto.Experimental: toAlias :: ToAlias a => a -> SqlQuery (ToAliasT a)
+ Database.Esqueleto.Experimental: toAlias :: ToAlias a => a -> SqlQuery a
- Database.Esqueleto.Experimental: toAliasReference :: ToAliasReference a => Ident -> a -> SqlQuery (ToAliasReferenceT a)
+ Database.Esqueleto.Experimental: toAliasReference :: ToAliasReference a => Ident -> a -> SqlQuery a
- Database.Esqueleto.Experimental: updateGet :: forall (m :: Type -> Type) record. (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record
+ Database.Esqueleto.Experimental: updateGet :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record
- Database.Esqueleto.Experimental: upsert :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record)
+ Database.Esqueleto.Experimental: upsert :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record)
- Database.Esqueleto.Experimental: upsertBy :: forall (m :: Type -> Type) record. (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record)
+ Database.Esqueleto.Experimental: upsertBy :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record)
- Database.Esqueleto.Experimental: with :: (ToAlias a, ToAliasReference (ToAliasT a), SqlSelect (ToAliasT a) r) => SqlQuery a -> SqlQuery (From (ToAliasReferenceT (ToAliasT a)))
+ Database.Esqueleto.Experimental: with :: (ToAlias a, ToAliasReference a, SqlSelect a r) => SqlQuery a -> SqlQuery (From a)
- Database.Esqueleto.Experimental: withRecursive :: (ToAlias a, ToAliasReference (ToAliasT a), SqlSelect a r, SqlSelect (ToAliasT a) r, ref ~ ToAliasReferenceT (ToAliasT a), RecursiveCteUnion unionKind) => SqlQuery a -> unionKind -> (From ref -> SqlQuery a) -> SqlQuery (From ref)
+ Database.Esqueleto.Experimental: withRecursive :: (ToAlias a, ToAliasReference a, SqlSelect a r, RecursiveCteUnion unionKind) => SqlQuery a -> unionKind -> (From a -> SqlQuery a) -> SqlQuery (From a)
- Database.Esqueleto.Experimental: withSqlConn :: (MonadUnliftIO m, MonadLogger m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a
+ Database.Esqueleto.Experimental: withSqlConn :: forall backend m a. (MonadUnliftIO m, MonadLogger m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a
- Database.Esqueleto.Experimental: withSqlPool :: (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
+ Database.Esqueleto.Experimental: withSqlPool :: forall backend m a. (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
- Database.Esqueleto.Internal.Internal: fromStart :: (PersistEntity a, BackendCompatible SqlBackend (PersistEntityBackend a)) => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a))))
+ Database.Esqueleto.Internal.Internal: fromStart :: forall a. (PersistEntity a, BackendCompatible SqlBackend (PersistEntityBackend a)) => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a))))

Files

changelog.md view
@@ -1,3 +1,16 @@+3.4.0.1+=======+- @arthurxavierx+  - [#221](https://github.com/bitemyapp/esqueleto/pull/221)+    - Deprecate `ToAliasT` and `ToAliasReferenceT`+- @parsonsmatt+  - [#226](https://github.com/bitemyapp/esqueleto/pull/226)+    - Support `persistent-2.11`+- @belevy+  - [#225](https://github.com/bitemyapp/esqueleto/pull/225)+    - Simplify `ToFromT` extracting the overlapping and type error instances+    - Make `ToFromT` and associated type family of `ToFrom`+ 3.4.0.0 ======= - @belevy, @charukiewicz
esqueleto.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12  name:           esqueleto-version:        3.4.0.0+version:        3.4.0.1 synopsis:       Type-safe EDSL for SQL queries on persistent backends. description:    @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends.  Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked @esqueleto@ queries that fail at runtime.                 .@@ -23,152 +23,160 @@     changelog.md  source-repository head-  type: git-  location: git://github.com/bitemyapp/esqueleto.git+    type: git+    location: git://github.com/bitemyapp/esqueleto.git  library-  exposed-modules:-      Database.Esqueleto-      Database.Esqueleto.Experimental-      Database.Esqueleto.Internal.Language-      Database.Esqueleto.Internal.Sql-      Database.Esqueleto.Internal.Internal-      Database.Esqueleto.Internal.ExprParser-      Database.Esqueleto.MySQL-      Database.Esqueleto.PostgreSQL-      Database.Esqueleto.PostgreSQL.JSON-      Database.Esqueleto.SQLite-  other-modules:-      Database.Esqueleto.Internal.PersistentImport-      Database.Esqueleto.PostgreSQL.JSON.Instances-      Paths_esqueleto-  hs-source-dirs:-      src/-  build-depends:-      base >=4.8 && <5.0-    , aeson >=1.0-    , attoparsec >= 0.13 && < 0.14-    , blaze-html-    , bytestring-    , conduit >=1.3-    , containers-    , monad-logger-    , persistent >=2.10.0 && <2.11-    , resourcet >=1.2-    , tagged >=0.2-    , text >=0.11 && <1.3-    , time >=1.5.0.1 && <=1.10-    , transformers >=0.2-    , unliftio-    , unordered-containers >=0.2-  if impl(ghc >=8.0)-    ghc-options: -Wall -Wno-redundant-constraints-  else-    ghc-options: -Wall-  default-language: Haskell2010+    exposed-modules:+        Database.Esqueleto+        Database.Esqueleto.Experimental+        Database.Esqueleto.Internal.Language+        Database.Esqueleto.Internal.Sql+        Database.Esqueleto.Internal.Internal+        Database.Esqueleto.Internal.ExprParser+        Database.Esqueleto.MySQL+        Database.Esqueleto.PostgreSQL+        Database.Esqueleto.PostgreSQL.JSON+        Database.Esqueleto.SQLite+    other-modules:+        Database.Esqueleto.Internal.PersistentImport+        Database.Esqueleto.PostgreSQL.JSON.Instances+        Paths_esqueleto+    hs-source-dirs:+        src/+    build-depends:+        base >=4.8 && <5.0+      , aeson >=1.0+      , attoparsec >= 0.13 && < 0.14+      , blaze-html+      , bytestring+      , conduit >=1.3+      , containers+      , monad-logger+      , persistent >=2.10.0 && <2.12+      , resourcet >=1.2+      , tagged >=0.2+      , text >=0.11 && <1.3+      , time >=1.5.0.1 && <=1.10+      , transformers >=0.2+      , unliftio+      , unordered-containers >=0.2+    ghc-options:+        -Wall+        -Wno-redundant-constraints+        -Wincomplete-uni-patterns+        -Wincomplete-record-updates+        -Wpartial-fields+        -Wmissing-home-modules+        -Widentities+        -Wredundant-constraints+        -Wcpp-undef+        -Wcpp-undef+        -Wmonomorphism-restriction+    default-language: Haskell2010  test-suite mysql-  type: exitcode-stdio-1.0-  main-is: MySQL/Test.hs-  other-modules:-      Common.Test-      Paths_esqueleto-  hs-source-dirs:-      test-  ghc-options: -Wall-  build-depends:-      base >=4.8 && <5.0-    , attoparsec-    , blaze-html-    , bytestring-    , conduit >=1.3-    , containers-    , esqueleto-    , exceptions-    , hspec-    , monad-logger-    , mtl-    , mysql-    , mysql-simple-    , persistent >=2.8.0 && <2.11-    , persistent-mysql-    , persistent-template-    , resourcet >=1.2-    , tagged >=0.2-    , text >=0.11 && <1.3-    , time-    , transformers >=0.2-    , unliftio-    , unordered-containers >=0.2-  default-language: Haskell2010+    type: exitcode-stdio-1.0+    main-is: MySQL/Test.hs+    other-modules:+        Common.Test+        Paths_esqueleto+    hs-source-dirs:+        test+    ghc-options: -Wall+    build-depends:+        base >=4.8 && <5.0+      , attoparsec+      , blaze-html+      , bytestring+      , conduit >=1.3+      , containers+      , esqueleto+      , exceptions+      , hspec+      , monad-logger+      , mtl+      , mysql+      , mysql-simple+      , persistent+      , persistent-mysql+      , persistent-template+      , resourcet >=1.2+      , tagged >=0.2+      , text >=0.11 && <1.3+      , time+      , transformers >=0.2+      , unliftio+      , unordered-containers >=0.2+    default-language: Haskell2010  test-suite postgresql-  type: exitcode-stdio-1.0-  main-is: PostgreSQL/Test.hs-  other-modules:-      Common.Test-      PostgreSQL.MigrateJSON-      Paths_esqueleto-  hs-source-dirs:-      test-  ghc-options: -Wall-  build-depends:-      base >=4.8 && <5.0-    , aeson-    , attoparsec-    , blaze-html-    , bytestring-    , conduit >=1.3-    , containers-    , esqueleto-    , exceptions-    , hspec-    , monad-logger-    , mtl-    , persistent >=2.10.0 && <2.11-    , persistent-postgresql >= 2.10.0 && <2.11-    , persistent-template-    , postgresql-libpq-    , postgresql-simple-    , resourcet >=1.2-    , tagged >=0.2-    , text >=0.11 && <1.3-    , time-    , transformers >=0.2-    , unliftio-    , unordered-containers >=0.2-    , vector-  default-language: Haskell2010+    type: exitcode-stdio-1.0+    main-is: PostgreSQL/Test.hs+    other-modules:+        Common.Test+        PostgreSQL.MigrateJSON+        Paths_esqueleto+    hs-source-dirs:+        test+    ghc-options: -Wall -threaded+    build-depends:+        base >=4.8 && <5.0+      , aeson+      , attoparsec+      , blaze-html+      , bytestring+      , conduit >=1.3+      , containers+      , esqueleto+      , exceptions+      , hspec+      , monad-logger+      , mtl+      , persistent+      , persistent-postgresql+      , persistent-template+      , postgresql-libpq+      , postgresql-simple+      , resourcet >=1.2+      , tagged >=0.2+      , text >=0.11 && <1.3+      , time+      , transformers >=0.2+      , unliftio+      , unordered-containers >=0.2+      , vector+    default-language: Haskell2010  test-suite sqlite-  type: exitcode-stdio-1.0-  main-is: SQLite/Test.hs-  other-modules:-      Common.Test-      Paths_esqueleto-  hs-source-dirs:-      test-  ghc-options: -Wall-  build-depends:-      base >=4.8 && <5.0-    , attoparsec-    , blaze-html-    , bytestring-    , conduit >=1.3-    , containers-    , esqueleto-    , exceptions-    , hspec-    , monad-logger-    , mtl-    , persistent >=2.8.0 && <2.11-    , persistent-sqlite-    , persistent-template-    , resourcet >=1.2-    , tagged >=0.2-    , text >=0.11 && <1.3-    , time-    , transformers >=0.2-    , unliftio-    , unordered-containers >=0.2-  default-language: Haskell2010+    type: exitcode-stdio-1.0+    main-is: SQLite/Test.hs+    other-modules:+        Common.Test+        Paths_esqueleto+    hs-source-dirs:+        test+    ghc-options: -Wall+    build-depends:+        base >=4.8 && <5.0+      , attoparsec+      , blaze-html+      , bytestring+      , conduit >=1.3+      , containers+      , esqueleto+      , exceptions+      , hspec+      , monad-logger+      , mtl+      , persistent+      , persistent-sqlite+      , persistent-template+      , resourcet >=1.2+      , tagged >=0.2+      , text >=0.11 && <1.3+      , time+      , transformers >=0.2+      , unliftio+      , unordered-containers >=0.2+    default-language: Haskell2010
src/Database/Esqueleto/Experimental.hs view
@@ -1,1385 +1,1424 @@-{-# LANGUAGE CPP-           , DataKinds-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , GADTs-           , MultiParamTypeClasses-           , TypeOperators-           , TypeFamilies-           , UndecidableInstances-           , OverloadedStrings-           , PatternSynonyms- #-}---- | This module contains a new way (introduced in 3.3.3.0) of using @FROM@ in--- Haskell. The old method was a bit finicky and could permit runtime errors,--- and this new way is both significantly safer and much more powerful.------ Esqueleto users are encouraged to migrate to this module, as it will become--- the default in a new major version @4.0.0.0@.-module Database.Esqueleto.Experimental-    ( -- * Setup-      -- $setup--      -- * Introduction-      -- $introduction--      -- * A New Syntax-      -- $new-syntax--      -- * Documentation--      From(..)-    , on-    , from-    , (:&)(..)--      -- ** Set Operations-      -- $sql-set-operations-    , union_-    , Union(..)-    , unionAll_-    , UnionAll(..)-    , except_-    , Except(..)-    , intersect_-    , Intersect(..)-    , pattern SelectQuery--      -- ** Common Table Expressions-    , with-    , withRecursive--      -- * Internals-    , ToFrom(..)-    , ToFromT-    , ToMaybe(..)-    , ToMaybeT-    , ToAlias(..)-    , ToAliasT-    , ToAliasReference(..)-    , ToAliasReferenceT-    -- * The Normal Stuff-    , where_, groupBy, orderBy, rand, asc, desc, limit, offset-             , distinct, distinctOn, don, distinctOnOrderBy, having, locking-             , sub_select, (^.), (?.)-             , val, isNothing, just, nothing, joinV, withNonNull-             , countRows, count, countDistinct-             , not_, (==.), (>=.), (>.), (<=.), (<.), (!=.), (&&.), (||.)-             , between, (+.), (-.), (/.), (*.)-             , random_, round_, ceiling_, floor_-             , min_, max_, sum_, avg_, castNum, castNumM-             , coalesce, coalesceDefault-             , lower_, upper_, trim_, ltrim_, rtrim_, length_, left_, right_-             , like, ilike, (%), concat_, (++.), castString-             , subList_select, valList, justList-             , in_, notIn, exists, notExists-             , set, (=.), (+=.), (-=.), (*=.), (/=.)-             , case_, toBaseId-  , subSelect-  , subSelectMaybe-  , subSelectCount-  , subSelectForeign-  , subSelectList-  , subSelectUnsafe-  , ToBaseId(..)-  , when_-  , then_-  , else_-  , Value(..)-  , ValueList(..)-  , OrderBy-  , DistinctOn-  , LockingKind(..)-  , SqlString-    -- ** Joins-  , InnerJoin(..)-  , CrossJoin(..)-  , LeftOuterJoin(..)-  , RightOuterJoin(..)-  , FullOuterJoin(..)-  , JoinKind(..)-  , OnClauseWithoutMatchingJoinException(..)-    -- * SQL backend-  , SqlQuery-  , SqlExpr-  , SqlEntity-  , select-  , selectSource-  , delete-  , deleteCount-  , update-  , updateCount-  , insertSelect-  , insertSelectCount-  , (<#)-  , (<&>)-  -- ** Rendering Queries-  , renderQueryToText-  , renderQuerySelect-  , renderQueryUpdate-  , renderQueryDelete-  , renderQueryInsertInto-    -- * Internal.Language-    -- * RDBMS-specific modules-    -- $rdbmsSpecificModules--    -- * Helpers-  , valkey-  , valJ-  , associateJoin--    -- * Re-exports-    -- $reexports-  , deleteKey-  , module Database.Esqueleto.Internal.PersistentImport-  )-    where--import qualified Control.Monad.Trans.Writer as W-import qualified Control.Monad.Trans.State as S-import Control.Monad.Trans.Class (lift)-#if __GLASGOW_HASKELL__ < 804-import Data.Semigroup-#endif-import Data.Proxy (Proxy(..))-import qualified Data.Text.Lazy.Builder as TLB-import Database.Esqueleto.Internal.PersistentImport-import Database.Esqueleto.Internal.Internal hiding (from, on, From)-import GHC.TypeLits----- $setup------ If you're already using "Database.Esqueleto", then you can get--- started using this module just by changing your imports slightly,--- as well as enabling the [TypeApplications](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-TypeApplications) extension.------ @--- {-\# LANGUAGE TypeApplications \#-}------ ...------ import Database.Esqueleto.Experimental--- @------ Note: Prior to @esqueleto-3.3.4.0@, the @Database.Esqueleto.Experimental@--- module did not reexport @Data.Esqueleto@.---------------------------------------------------------------------------- $introduction------ This module is fully backwards-compatible extension to the @esqueleto@--- EDSL that expands subquery functionality and enables--- [SQL set operations](https://en.wikipedia.org/wiki/Set_operations_(SQL\))--- to be written directly in Haskell. Specifically, this enables:------   * Subqueries in 'JOIN' statements---   * 'UNION'---   * 'UNION' 'ALL'---   * 'INTERSECT'---   * 'EXCEPT'------ As a consequence of this, several classes of runtime errors are now--- caught at compile time. This includes missing 'on' clauses and improper--- handling of @Maybe@ values in outer joins.------ This module can be used in conjunction with the main "Database.Esqueleto"--- module, but doing so requires qualified imports to avoid ambiguous--- definitions of 'on' and 'from', which are defined in both modules.------ Below we will give an overview of how to use this module and the--- features it enables.---------------------------------------------------------------------------- $new-syntax------ This module introduces a new syntax that serves to enable the aforementioned--- features. This new syntax also changes how joins written in the @esqueleto@--- EDSL to more closely resemble the underlying SQL.------ For our examples, we'll use a schema similar to the one in the Getting Started--- section of "Database.Esqueleto":------ @--- share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|---   Person---     name String---     age Int Maybe---     deriving Eq Show---   BlogPost---     title String---     authorId PersonId---     deriving Eq Show---   Follow---     follower PersonId---     followed PersonId---     deriving Eq Show--- |]--- @------ === Example 1: Simple select------ Let's select all people who are named \"John\".------ ==== "Database.Esqueleto":------ @--- select $--- from $ \\people -> do--- where_ (people ^. PersonName ==. val \"John\")--- pure people--- @------ ==== "Database.Esqueleto.Experimental":------ @--- select $ do--- people <- from $ Table \@Person--- where_ (people ^. PersonName ==. val \"John\")--- pure people--- @--------- === Example 2: Select with join------ Let's select all people and their blog posts who are over--- the age of 18.------ ==== "Database.Esqueleto":------ @--- select $--- from $ \\(people \`LeftOuterJoin\` blogPosts) -> do--- on (people ^. PersonId ==. blogPosts ?. BlogPostAuthorId)--- where_ (people ^. PersonAge >. val 18)--- pure (people, blogPosts)--- @------ ==== "Database.Esqueleto.Experimental":------ Here we use the ':&' operator to pattern match against the joined tables.------ @--- select $ do--- (people :& blogPosts) <----     from $ Table \@Person---     \`LeftOuterJoin\` Table \@BlogPost---     \`on\` (\\(people :& blogPosts) ->---             people ^. PersonId ==. blogPosts ?. BlogPostAuthorId)--- where_ (people ^. PersonAge >. val 18)--- pure (people, blogPosts)--- @------ === Example 3: Select with multi-table join------ Let's select all people who follow a person named \"John\", including--- the name of each follower.------ ==== "Database.Esqueleto":------ @--- select $--- from $ \\(---  people1---  \`InnerJoin\` followers---  \`InnerJoin\` people2--- ) -> do--- on (people1 ^. PersonId ==. followers ^. FollowFollowed)--- on (followers ^. FollowFollower ==. people2 ^. PersonId)--- where_ (people1 ^. PersonName ==. val \"John\")--- pure (followers, people2)--- @------ ==== "Database.Esqueleto.Experimental":------ In this version, with each successive 'on' clause, only the tables--- we have already joined into are in scope, so we must pattern match--- accordingly. In this case, in the second 'InnerJoin', we do not use--- the first `Person` reference, so we use @_@ as a placeholder to--- ignore it. This prevents a possible runtime error where a table--- is referenced before it appears in the sequence of 'JOIN's.------ @--- select $ do--- (people1 :& followers :& people2) <----     from $ Table \@Person---     \`InnerJoin` Table \@Follow---     \`on\` (\\(people1 :& followers) ->---             people1 ^. PersonId ==. followers ^. FollowFollowed)---     \`InnerJoin` Table \@Person---     \`on\` (\\(_ :& followers :& people2) ->---             followers ^. FollowFollower ==. people2 ^. PersonId)--- where_ (people1 ^. PersonName ==. val \"John\")--- pure (followers, people2)--- @------ === Example 4: Counting results of a subquery------ Let's count the number of people who have posted at least 10 posts------ ==== "Database.Esqueleto":------ @--- select $ pure $ subSelectCount $--- from $ \\(---   people---   \`InnerJoin\` blogPosts--- ) -> do--- on (people ^. PersonId ==. blogPosts ^. BlogPostAuthorId)--- groupBy (people ^. PersonId)--- having ((count $ blogPosts ^. BlogPostId) >. val 10)--- pure people--- @------ ==== "Database.Esqueleto.Experimental":------ @--- select $ do--- peopleWithPosts <----   from $ do---     (people :& blogPosts) <----       from $ Table \@Person---       \`InnerJoin\` Table \@BlogPost---       \`on\` (\\(p :& bP) ->---               p ^. PersonId ==. bP ^. BlogPostAuthorId)---     groupBy (people ^. PersonId)---     having ((count $ blogPosts ^. BlogPostId) >. val 10)---     pure people--- pure $ count (peopleWithPosts ^. PersonId)--- @------ We now have the ability to refactor this------ === Example 5: Sorting the results of a UNION with limits------ Out of all of the posts created by a person and the people they follow,--- generate a list of the first 25 posts, sorted alphabetically.------ ==== "Database.Esqueleto":------ Since 'UNION' is not supported, this requires using `Database.Esqueleto.rawSql`. (Not shown)------ ==== "Database.Esqueleto.Experimental":------ Since this module supports all set operations (see `SqlSetOperation`), we can use--- `Union` to write this query.------ @--- select $ do--- (authors, blogPosts) <- from $---   (do---     (author :& blogPost) <----       from $ Table \@Person---       \`InnerJoin\` Table \@BlogPost---       \`on\` (\\(a :& bP) ->---               a ^. PersonId ==. bP ^. BlogPostAuthorId)---     where_ (author ^. PersonId ==. val currentPersonId)---     pure (author, blogPost)---   )---   \`union_\`---   (do---     (follow :& blogPost :& author) <----       from $ Table \@Follow---       \`InnerJoin\` Table \@BlogPost---       \`on\` (\\(f :& bP) ->---               f ^. FollowFollowed ==. bP ^. BlogPostAuthorId)---       \`InnerJoin\` Table \@Person---       \`on\` (\\(_ :& bP :& a) ->---               bP ^. BlogPostAuthorId ==. a ^. PersonId)---     where_ (follow ^. FollowFollower ==. val currentPersonId)---     pure (author, blogPost)---   )--- orderBy [ asc (blogPosts ^. BlogPostTitle) ]--- limit 25--- pure (authors, blogPosts)--- @------ === Example 6: LATERAL JOIN------ As of version @3.4.0.0@, lateral subquery joins are supported.--------- @--- select $ do--- (salesPerson :& maxSaleAmount :& maxSaleCustomerName) <----   from $ Table \@SalesPerson---   \`CrossJoin\` (\\salesPerson -> do---         sales <- from $ Table \@Sale---         where_ $ sales ^. SaleSalesPersonId ==. salesPerson ^. SalesPersonId---         pure $ max_ (sales ^. SaleAmount)---         )---   \`CrossJoin\` (\\(salesPerson :& maxSaleAmount) -> do---         sales <- from $ Table \@Sale---         where_ $ sales ^. SaleSalesPersonId ==. salesPerson ^. SalesPersonId---              &&. sales ^. SaleAmount ==. maxSaleAmount---         pure $ sales ^. SaleCustomerName)---         )--- pure (salesPerson ^. SalesPersonName, maxSaleAmount, maxSaleCustomerName)--- @------ This is the equivalent to the following SQL (example taken from the--- [MySQL Lateral Derived Table](https://dev.mysql.com/doc/refman/8.0/en/lateral-derived-tables.html)--- documentation):------ @--- SELECT---   salesperson.name,---   max_sale.amount,---   max_sale_customer.customer_name--- FROM---   salesperson,---   -- calculate maximum size, cache it in transient derived table max_sale---   LATERAL---   (SELECT MAX(amount) AS amount---     FROM all_sales---     WHERE all_sales.salesperson_id = salesperson.id)---   AS max_sale,---   LATERAL---   (SELECT customer_name---     FROM all_sales---     WHERE all_sales.salesperson_id = salesperson.id---     AND all_sales.amount =---         -- the cached maximum size---         max_sale.amount)---   AS max_sale_customer;--- @---- | A left-precedence pair. Pronounced \"and\". Used to represent expressions--- that have been joined together.------ The precedence behavior can be demonstrated by:------ @--- a :& b :& c == ((a :& b) :& c)--- @------ See the examples at the beginning of this module to see how this--- operator is used in 'JOIN' operations.-data (:&) a b = a :& b-infixl 2 :&--data SqlSetOperation a =-    SqlSetUnion (SqlSetOperation a) (SqlSetOperation a)-  | SqlSetUnionAll (SqlSetOperation a) (SqlSetOperation a)-  | SqlSetExcept (SqlSetOperation a) (SqlSetOperation a)-  | SqlSetIntersect (SqlSetOperation a) (SqlSetOperation a)-  | SelectQueryP NeedParens (SqlQuery a)----- $sql-set-operations------ Data type that represents SQL set operations. This includes--- 'UNION', 'UNION' 'ALL', 'EXCEPT', and 'INTERSECT'. These types form--- a binary tree, with @SqlQuery@ values on the leaves.------ Each function corresponding to the aforementioned set operations--- can be used as an infix in a @from@ to help with readability--- and lead to code that closely resembles the underlying SQL. For example,------ @--- select $ from $---   (do---      a <- from Table @A---      pure $ a ^. ASomeCol---   )---   \`union_\`---   (do---      b <- from Table @B---      pure $ b ^. BSomeCol---   )--- @------ is translated into------ @--- SELECT * FROM (---   (SELECT a.some_col FROM a)---   UNION---   (SELECT b.some_col FROM b)--- )--- @-----{-# DEPRECATED Union "/Since: 3.4.0.0/ - \-    Use the 'union_' function instead of the 'Union' data constructor" #-}-data Union a b = a `Union` b---- | @UNION@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.-union_ :: a -> b -> Union a b-union_ = Union--{-# DEPRECATED UnionAll "/Since: 3.4.0.0/ - \-    Use the 'unionAll_' function instead of the 'UnionAll' data constructor" #-}-data UnionAll a b = a `UnionAll` b---- | @UNION@ @ALL@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.-unionAll_ :: a -> b -> UnionAll a b-unionAll_ = UnionAll--{-# DEPRECATED Except "/Since: 3.4.0.0/ - \-    Use the 'except_' function instead of the 'Except' data constructor" #-}-data Except a b = a `Except` b---- | @EXCEPT@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.-except_ :: a -> b -> Except a b-except_ = Except--{-# DEPRECATED Intersect "/Since: 3.4.0.0/ - \-    Use the 'intersect_' function instead of the 'Intersect' data constructor" #-}-data Intersect a b = a `Intersect` b---- | @INTERSECT@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.-intersect_ :: a -> b -> Intersect a b-intersect_ = Intersect--class SetOperationT a ~ b => ToSetOperation a b | a -> b where-  toSetOperation :: a -> SqlSetOperation b--instance ToSetOperation (SqlSetOperation a) a where-  toSetOperation = id-instance ToSetOperation (SqlQuery a) a where-  toSetOperation = SelectQueryP Never-instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Union a b) c where-  toSetOperation (Union a b) = SqlSetUnion (toSetOperation a) (toSetOperation b)-instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (UnionAll a b) c where-  toSetOperation (UnionAll a b) = SqlSetUnionAll (toSetOperation a) (toSetOperation b)-instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Except a b) c where-  toSetOperation (Except a b) = SqlSetExcept (toSetOperation a) (toSetOperation b)-instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Intersect a b) c where-  toSetOperation (Intersect a b) = SqlSetIntersect (toSetOperation a) (toSetOperation b)--type family SetOperationT a where-  SetOperationT (Union a b) = SetOperationT a-  SetOperationT (UnionAll a b) = SetOperationT a-  SetOperationT (Except a b) = SetOperationT a-  SetOperationT (Intersect a b) = SetOperationT a-  SetOperationT (SqlQuery a) = a-  SetOperationT (SqlSetOperation a) = a--{-# DEPRECATED SelectQuery "/Since: 3.4.0.0/ - \-    It is no longer necessary to tag 'SqlQuery' values with @SelectQuery@" #-}-pattern SelectQuery :: SqlQuery a -> SqlSetOperation a-pattern SelectQuery q = SelectQueryP Never q----- | Data type that represents the syntax of a 'JOIN' tree. In practice,--- only the @Table@ constructor is used directly when writing queries. For example,------ @--- select $ from $ Table \@People--- @-data From a where-  Table-    :: PersistEntity ent-    => From (SqlExpr (Entity ent))-  SubQuery-    :: ( SqlSelect a' r-       , SqlSelect a'' r'-       , ToAlias a-       , a' ~ ToAliasT a-       , ToAliasReference a'-       , ToAliasReferenceT a' ~ a''-       )-    => SqlQuery a-    -> From a''-  FromCte-    :: Ident-    -> a-    -> From a-  SqlSetOperation-    :: ( SqlSelect a' r-       , ToAlias a-       , a' ~ ToAliasT a-       , ToAliasReference a'-       , ToAliasReferenceT a' ~ a''-       )-    => SqlSetOperation a-    -> From a''-  InnerJoinFrom-    :: From a-    -> (From b, (a :& b) -> SqlExpr (Value Bool))-    -> From (a :& b)-  InnerJoinFromLateral-    :: ( SqlSelect b' r-       , SqlSelect b'' r'-       , ToAlias b-       , b' ~ ToAliasT b-       , ToAliasReference b'-       , ToAliasReferenceT b' ~ b''-       )-    => From a-    -> ((a -> SqlQuery b), (a :& b'') -> SqlExpr (Value Bool))-    -> From (a :& b'')-  CrossJoinFrom-    :: From a-    -> From b-    -> From (a :& b)-  CrossJoinFromLateral-    :: ( SqlSelect b' r-       , SqlSelect b'' r'-       , ToAlias b-       , b' ~ ToAliasT b-       , ToAliasReference b'-       , ToAliasReferenceT b' ~ b''-       )-    => From a-    -> (a -> SqlQuery b)-    -> From (a :& b'')-  LeftJoinFrom-    :: ToMaybe b-    => From a-    -> (From b, (a :& ToMaybeT b) -> SqlExpr (Value Bool))-    -> From (a :& ToMaybeT b)-  LeftJoinFromLateral-    :: ( SqlSelect b' r-       , SqlSelect b'' r'-       , ToAlias b-       , b' ~ ToAliasT b-       , ToAliasReference b'-       , ToAliasReferenceT b' ~ b''-       , ToMaybe b''-       )-    => From a-    -> ((a -> SqlQuery b), (a :& ToMaybeT b'') -> SqlExpr (Value Bool))-    -> From (a :& ToMaybeT b'')-  RightJoinFrom-    :: ToMaybe a-    => From a-    -> (From b, (ToMaybeT a :& b) -> SqlExpr (Value Bool))-    -> From (ToMaybeT a :& b)-  FullJoinFrom-    :: (ToMaybe a, ToMaybe b )-    => From a-    -> (From b, (ToMaybeT a :& ToMaybeT b) -> SqlExpr (Value Bool))-    -> From (ToMaybeT a :& ToMaybeT b)---- | Constraint for `on`. Ensures that only types that require an `on` can be used on--- the left hand side. This was previously reusing the ToFrom class which was actually--- a bit too lenient as it allowed to much. Expanding this class should not be needed.------ @since 3.4.0.0-class ValidOnClauseValue a where-instance ValidOnClauseValue (From a) where-instance ValidOnClauseValue (SqlQuery a) where-instance ValidOnClauseValue (SqlSetOperation a) where-instance ValidOnClauseValue (a -> SqlQuery b) where-instance {-# OVERLAPPABLE #-} (TypeError ('Text "Illegal use of ON")) => ValidOnClauseValue a where---- | An @ON@ clause that describes how two tables are related. This should be--- used as an infix operator after a 'JOIN'. For example,------ @--- select $--- from $ Table \@Person--- \`InnerJoin\` Table \@BlogPost--- \`on\` (\\(p :& bP) ->---         p ^. PersonId ==. bP ^. BlogPostAuthorId)--- @-on :: ValidOnClauseValue a => a -> (b -> SqlExpr (Value Bool)) -> (a, b -> SqlExpr (Value Bool))-on = (,)-infix 9 `on`--type JoinErrorMsg jk = 'Text "Missing on statement for " ':<>: 'Text jk--type family ToFromT a where-  ToFromT (From a) = a-  ToFromT (SqlQuery a) = ToAliasReferenceT (ToAliasT a)-  ToFromT (Union a b) = ToAliasReferenceT (ToAliasT (SetOperationT a))-  ToFromT (UnionAll a b) = ToAliasReferenceT (ToAliasT (SetOperationT a))-  ToFromT (Except a b) = ToAliasReferenceT (ToAliasT (SetOperationT a))-  ToFromT (Intersect a b) = ToAliasReferenceT (ToAliasT (SetOperationT a))-  ToFromT (SqlSetOperation a) = ToAliasReferenceT (ToAliasT a)-  ToFromT (InnerJoin a (b, c -> SqlExpr (Value Bool))) = c-  ToFromT (LeftOuterJoin a (b, c -> SqlExpr (Value Bool))) = c-  ToFromT (RightOuterJoin a (b, c -> SqlExpr (Value Bool))) = c-  ToFromT (FullOuterJoin a (b, c -> SqlExpr (Value Bool))) = c-  ToFromT (CrossJoin a (c -> SqlQuery b)) = ToFromT a :& ToAliasReferenceT (ToAliasT b)-  ToFromT (CrossJoin a b) = ToFromT a :& ToFromT b-  ToFromT (InnerJoin a b) = TypeError (JoinErrorMsg "InnerJoin")-  ToFromT (LeftOuterJoin a b) = TypeError (JoinErrorMsg "LeftOuterJoin")-  ToFromT (RightOuterJoin a b) = TypeError (JoinErrorMsg "RightOuterJoin")-  ToFromT (FullOuterJoin a b) = TypeError (JoinErrorMsg "FullOuterJoin")--data Lateral-data NotLateral--type family IsLateral a where-  IsLateral (a -> SqlQuery b) = Lateral-  IsLateral a = NotLateral--class ErrorOnLateral a where-instance (TypeError ('Text "LATERAL can only be used for INNER, LEFT, and CROSS join kinds.")) => ErrorOnLateral (a -> SqlQuery b) where-instance {-# OVERLAPPABLE #-} ErrorOnLateral a where--{-- Type class magic to allow the use of the `InnerJoin` family of data constructors in from --}-class ToFrom a where-  toFrom :: a -> From (ToFromT a)--instance ToFrom (From a) where-  toFrom = id--instance {-# OVERLAPPABLE #-} ToFrom (InnerJoin a b) where-  toFrom = undefined-instance {-# OVERLAPPABLE #-} ToFrom (LeftOuterJoin a b) where-  toFrom = undefined-instance {-# OVERLAPPABLE #-} ToFrom (RightOuterJoin a b) where-  toFrom = undefined-instance {-# OVERLAPPABLE #-} ToFrom (FullOuterJoin a b) where-  toFrom = undefined--instance ( ToAlias a-         , a' ~ ToAliasT a-         , ToAliasReference a'-         , a'' ~ ToAliasReferenceT a'-         , SqlSelect a' r'-         , SqlSelect a'' r'-         ) => ToFrom (SqlQuery a) where-  toFrom = SubQuery--instance ( SqlSelect c' r-         , SqlSelect c'' r'-         , ToAlias c-         , c' ~ ToAliasT c-         , ToAliasReference c'-         , ToAliasReferenceT c' ~ c''-         , ToSetOperation a c-         , ToSetOperation b c-         , c ~ SetOperationT a-         )  => ToFrom (Union a b) where-  toFrom u = SqlSetOperation $ toSetOperation u--instance ( SqlSelect c' r-         , SqlSelect c'' r'-         , ToAlias c-         , c' ~ ToAliasT c-         , ToAliasReference c'-         , ToAliasReferenceT c' ~ c''-         , ToSetOperation a c-         , ToSetOperation b c-         , c ~ SetOperationT a-         )  => ToFrom (UnionAll a b) where-  toFrom u = SqlSetOperation $ toSetOperation u--instance (SqlSelect a' r,SqlSelect a'' r', ToAlias a, a' ~ ToAliasT a, ToAliasReference a', ToAliasReferenceT a' ~ a'')  => ToFrom (SqlSetOperation a) where-  -- If someone uses just a plain SelectQuery it should behave like a normal subquery-  toFrom (SelectQueryP _ q) = SubQuery q-  -- Otherwise use the SqlSetOperation-  toFrom q = SqlSetOperation q--class ToInnerJoin lateral lhs rhs res where-  toInnerJoin :: Proxy lateral -> lhs -> rhs -> (res -> SqlExpr (Value Bool)) -> From res--instance ( SqlSelect bAlias r-         , SqlSelect bAliasRef r'-         , ToAlias b-         , bAlias ~ ToAliasT b-         , ToAliasReference bAlias-         , bAliasRef ~ ToAliasReferenceT bAlias-         , ToFrom a-         , ToFromT a ~ a'-         ) => ToInnerJoin Lateral a (a' -> SqlQuery b) (a' :& bAliasRef) where-  toInnerJoin _ lhs q on' = InnerJoinFromLateral (toFrom lhs) (q, on')--instance (ToFrom a, ToFromT a ~ a', ToFrom b, ToFromT b ~ b')-        => ToInnerJoin NotLateral a b (a' :& b') where-  toInnerJoin _ lhs rhs on' = InnerJoinFrom (toFrom lhs) (toFrom rhs, on')--instance ( ToFrom a-         , ToFromT a ~ a'-         , ToInnerJoin (IsLateral b) a b b'-         ) => ToFrom (InnerJoin a (b, b' -> SqlExpr (Value Bool))) where-         toFrom (InnerJoin lhs (rhs, on')) =-           let-            toProxy :: b -> Proxy (IsLateral b)-            toProxy _ = Proxy-           in toInnerJoin (toProxy rhs) lhs rhs on'--instance ( ToFrom a-         , ToFrom b-         , ToFromT (CrossJoin a b) ~ (ToFromT a :& ToFromT b)-         ) => ToFrom (CrossJoin a b) where-  toFrom (CrossJoin lhs rhs) = CrossJoinFrom (toFrom lhs) (toFrom rhs)--instance {-# OVERLAPPING #-}-         ( ToFrom a-         , ToFromT a ~ a'-         , SqlSelect bAlias r-         , SqlSelect bAliasRef r'-         , ToAlias b-         , bAlias ~ ToAliasT b-         , ToAliasReference bAlias-         , bAliasRef ~ ToAliasReferenceT bAlias-         )-       => ToFrom (CrossJoin a (a' -> SqlQuery b)) where-  toFrom (CrossJoin lhs q) = CrossJoinFromLateral (toFrom lhs) q--class ToLeftJoin lateral lhs rhs res where-  toLeftJoin :: Proxy lateral -> lhs -> rhs -> (res -> SqlExpr (Value Bool)) -> From res--instance ( ToFrom a-         , ToFromT a ~ a'-         , SqlSelect bAlias r-         , SqlSelect bAliasRef r'-         , ToAlias b-         , bAlias ~ ToAliasT b-         , ToAliasReference bAlias-         , bAliasRef ~ ToAliasReferenceT bAlias-         , ToMaybe bAliasRef-         , mb ~ ToMaybeT bAliasRef-         ) => ToLeftJoin Lateral a (a' -> SqlQuery b) (a' :& mb) where-  toLeftJoin _ lhs q on' = LeftJoinFromLateral (toFrom lhs) (q, on')--instance ( ToFrom a-         , ToFromT a ~ a'-         , ToFrom b-         , ToFromT b ~ b'-         , ToMaybe b'-         , mb ~ ToMaybeT b'-         ) => ToLeftJoin NotLateral a b (a' :& mb) where-  toLeftJoin _ lhs rhs on' = LeftJoinFrom (toFrom lhs) (toFrom rhs, on')--instance ( ToLeftJoin (IsLateral b) a b b'-         ) => ToFrom (LeftOuterJoin a (b, b' -> SqlExpr (Value Bool))) where-         toFrom (LeftOuterJoin lhs (rhs, on')) =-           let-            toProxy :: b -> Proxy (IsLateral b)-            toProxy _ = Proxy-           in toLeftJoin (toProxy rhs) lhs rhs on'--instance ( ToFrom a-         , ToFromT a ~ a'-         , ToFrom b-         , ToFromT b ~ b'-         , ToMaybe a'-         , ma ~ ToMaybeT a'-         , ToMaybe b'-         , mb ~ ToMaybeT b'-         , ErrorOnLateral b-         ) => ToFrom (FullOuterJoin a (b, (ma :& mb) -> SqlExpr (Value Bool))) where-  toFrom (FullOuterJoin lhs (rhs, on')) = FullJoinFrom (toFrom lhs) (toFrom rhs, on')--instance ( ToFrom a-         , ToFromT a ~ a'-         , ToMaybe a'-         , ma ~ ToMaybeT a'-         , ToFrom b-         , ToFromT b ~ b'-         , ErrorOnLateral b-         ) => ToFrom (RightOuterJoin a (b, (ma :& b') -> SqlExpr (Value Bool))) where-  toFrom (RightOuterJoin lhs (rhs, on')) = RightJoinFrom (toFrom lhs) (toFrom rhs,  on')--type family Nullable a where-  Nullable (Maybe a) = a-  Nullable a =  a--type family ToMaybeT a where-  ToMaybeT (SqlExpr (Maybe a)) = SqlExpr (Maybe a)-  ToMaybeT (SqlExpr (Entity a)) = SqlExpr (Maybe (Entity a))-  ToMaybeT (SqlExpr (Value a)) = SqlExpr (Value (Maybe (Nullable a)))-  ToMaybeT (a :& b) = (ToMaybeT a :& ToMaybeT b)-  ToMaybeT (a, b) = (ToMaybeT a, ToMaybeT b)-  ToMaybeT (a, b, c) = (ToMaybeT a, ToMaybeT b, ToMaybeT c)-  ToMaybeT (a, b, c, d) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d)-  ToMaybeT (a, b, c, d, e) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e)-  ToMaybeT (a, b, c, d, e, f) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f)-  ToMaybeT (a, b, c, d, e, f, g) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f, ToMaybeT g)-  ToMaybeT (a, b, c, d, e, f, g, h) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f, ToMaybeT g, ToMaybeT h)--class ToMaybe a where-  toMaybe :: a -> ToMaybeT a--instance ToMaybe (SqlExpr (Maybe a)) where-  toMaybe = id--instance ToMaybe (SqlExpr (Entity a)) where-  toMaybe = EMaybe--instance ToMaybe (SqlExpr (Value a)) where-  toMaybe = veryUnsafeCoerceSqlExprValue--instance (ToMaybe a, ToMaybe b) => ToMaybe (a :& b) where-  toMaybe (a :& b) = (toMaybe a :& toMaybe b)--instance (ToMaybe a, ToMaybe b) => ToMaybe (a,b) where-  toMaybe (a, b) = (toMaybe a, toMaybe b)--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         ) => ToMaybe (a,b,c) where-  toMaybe = to3 . toMaybe . from3--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         , ToMaybe d-         ) => ToMaybe (a,b,c,d) where-  toMaybe = to4 . toMaybe . from4--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         , ToMaybe d-         , ToMaybe e-         ) => ToMaybe (a,b,c,d,e) where-  toMaybe = to5 . toMaybe . from5--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         , ToMaybe d-         , ToMaybe e-         , ToMaybe f-         ) => ToMaybe (a,b,c,d,e,f) where-  toMaybe = to6 . toMaybe . from6--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         , ToMaybe d-         , ToMaybe e-         , ToMaybe f-         , ToMaybe g-         ) => ToMaybe (a,b,c,d,e,f,g) where-  toMaybe = to7 . toMaybe . from7--instance ( ToMaybe a-         , ToMaybe b-         , ToMaybe c-         , ToMaybe d-         , ToMaybe e-         , ToMaybe f-         , ToMaybe g-         , ToMaybe h-         ) => ToMaybe (a,b,c,d,e,f,g,h) where-  toMaybe = to8 . toMaybe . from8---- | 'FROM' clause, used to bring entities into scope.------ Internally, this function uses the `From` datatype and the--- `ToFrom` typeclass. Unlike the old `Database.Esqueleto.from`,--- this does not take a function as a parameter, but rather--- a value that represents a 'JOIN' tree constructed out of--- instances of `ToFrom`. This implementation eliminates certain--- types of runtime errors by preventing the construction of--- invalid SQL (e.g. illegal nested-@from@).-from :: ToFrom a  => a -> SqlQuery (ToFromT a)-from parts = do-  (a, clause) <- runFrom $ toFrom parts-  Q $ W.tell mempty{sdFromClause=[clause]}-  pure a-    where-      runFrom :: From a -> SqlQuery (a, FromClause)-      runFrom e@Table = do-        let ed = entityDef $ getVal e-        ident <- newIdentFor (entityDB ed)-        let entity = EEntity ident-        pure $ (entity, FromStart ident ed)-          where-            getVal :: PersistEntity ent => From (SqlExpr (Entity ent)) -> Proxy ent-            getVal = const Proxy-      runFrom (SubQuery subquery) =-        fromSubQuery NormalSubQuery subquery--      runFrom (FromCte ident ref) =-          pure (ref, FromIdent ident)--      runFrom (SqlSetOperation operation) = do-          (aliasedOperation, ret) <- aliasQueries operation-          ident <- newIdentFor (DBName "u")-          ref <- toAliasReference ident ret-          pure (ref, FromQuery ident (operationToSql aliasedOperation) NormalSubQuery)--          where-            aliasQueries o =-              case o of-                SelectQueryP p q -> do-                  (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ q-                  prevState <- Q $ lift S.get-                  aliasedRet <- toAlias ret-                  Q $ lift $ S.put prevState-                  let p' =-                        case p of-                          Parens -> Parens-                          Never ->-                            if (sdLimitClause sideData) /= mempty-                                || length (sdOrderByClause sideData) > 0 then-                              Parens-                            else-                              Never-                  pure (SelectQueryP p' $ Q $ W.WriterT $ pure (aliasedRet, sideData), aliasedRet)-                SqlSetUnion     o1 o2 -> do-                  (o1', ret) <- aliasQueries o1-                  (o2', _  ) <- aliasQueries o2-                  pure (SqlSetUnion o1' o2', ret)-                SqlSetUnionAll  o1 o2 -> do-                  (o1', ret) <- aliasQueries o1-                  (o2', _  ) <- aliasQueries o2-                  pure (SqlSetUnionAll o1' o2', ret)-                SqlSetExcept    o1 o2 -> do-                  (o1', ret) <- aliasQueries o1-                  (o2', _  ) <- aliasQueries o2-                  pure (SqlSetExcept o1' o2', ret)-                SqlSetIntersect o1 o2 -> do-                  (o1', ret) <- aliasQueries o1-                  (o2', _  ) <- aliasQueries o2-                  pure (SqlSetIntersect o1' o2', ret)--            operationToSql o info =-              case o of-                SelectQueryP p q  ->-                  let (builder, values) = toRawSql SELECT info q-                  in (parensM p builder, values)-                SqlSetUnion     o1 o2 -> doSetOperation "UNION"     info o1 o2-                SqlSetUnionAll  o1 o2 -> doSetOperation "UNION ALL" info o1 o2-                SqlSetExcept    o1 o2 -> doSetOperation "EXCEPT"    info o1 o2-                SqlSetIntersect o1 o2 -> doSetOperation "INTERSECT" info o1 o2--            doSetOperation operationText info o1 o2 =-                  let-                    (q1, v1) = operationToSql o1 info-                    (q2, v2) = operationToSql o2 info-                  in (q1 <> " " <> operationText <> " " <> q2, v1 <> v2)---      runFrom (InnerJoinFrom leftPart (rightPart, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- runFrom rightPart-        let ret = leftVal :& rightVal-        pure $ (ret, FromJoin leftFrom InnerJoinKind rightFrom (Just (on' ret)))-      runFrom (InnerJoinFromLateral leftPart (q, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)-        let ret = leftVal :& rightVal-        pure $ (ret, FromJoin leftFrom InnerJoinKind rightFrom (Just (on' ret)))-      runFrom (CrossJoinFrom leftPart rightPart) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- runFrom rightPart-        let ret = leftVal :& rightVal-        pure $ (ret, FromJoin leftFrom CrossJoinKind rightFrom Nothing)-      runFrom (CrossJoinFromLateral leftPart q) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)-        let ret = leftVal :& rightVal-        pure $ (ret, FromJoin leftFrom CrossJoinKind rightFrom Nothing)-      runFrom (LeftJoinFrom leftPart (rightPart, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- runFrom rightPart-        let ret = leftVal :& (toMaybe rightVal)-        pure $ (ret, FromJoin leftFrom LeftOuterJoinKind rightFrom (Just (on' ret)))-      runFrom (LeftJoinFromLateral leftPart (q, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)-        let ret = leftVal :& (toMaybe rightVal)-        pure $ (ret, FromJoin leftFrom LeftOuterJoinKind rightFrom (Just (on' ret)))-      runFrom (RightJoinFrom leftPart (rightPart, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- runFrom rightPart-        let ret = (toMaybe leftVal) :& rightVal-        pure $ (ret, FromJoin leftFrom RightOuterJoinKind rightFrom (Just (on' ret)))-      runFrom (FullJoinFrom leftPart (rightPart, on')) = do-        (leftVal, leftFrom) <- runFrom leftPart-        (rightVal, rightFrom) <- runFrom rightPart-        let ret = (toMaybe leftVal) :& (toMaybe rightVal)-        pure $ (ret, FromJoin leftFrom FullOuterJoinKind rightFrom (Just (on' ret)))--fromSubQuery :: ( SqlSelect a' r-                , SqlSelect a'' r'-                , ToAlias a-                , a' ~ ToAliasT a-                , ToAliasReference a'-                , ToAliasReferenceT a' ~ a''-                )-             => SubQueryType -> SqlQuery a -> SqlQuery (ToAliasReferenceT (ToAliasT a), FromClause)-fromSubQuery subqueryType subquery = do-    -- We want to update the IdentState without writing the query to side data-    (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ subquery-    aliasedValue <- toAlias ret-    -- Make a fake query with the aliased results, this allows us to ensure that the query is only run once-    let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)-    -- Add the FromQuery that renders the subquery to our side data-    subqueryAlias <- newIdentFor (DBName "q")-    -- Pass the aliased results of the subquery to the outer query-    -- create aliased references from the outer query results (e.g value from subquery will be `subquery`.`value`),-    -- this is probably overkill as the aliases should already be unique but seems to be good practice.-    ref <- toAliasReference subqueryAlias aliasedValue-    pure (ref , FromQuery subqueryAlias (\info -> toRawSql SELECT info aliasedQuery) subqueryType)------ | @WITH@ clause used to introduce a [Common Table Expression (CTE)](https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL#Common_table_expression).--- CTEs are supported in most modern SQL engines and can be useful--- in performance tuning. In Esqueleto, CTEs should be used as a--- subquery memoization tactic. While when writing plain SQL, CTEs--- are sometimes used to organize the SQL code, in Esqueleto, this--- is better achieved through function that return 'SqlQuery' values.------ @--- select $ do--- cte <- with subQuery--- cteResult <- from cte--- where_ $ cteResult ...--- pure cteResult--- @------ __WARNING__: In some SQL engines using a CTE can diminish performance.--- In these engines the CTE is treated as an optimization fence. You should--- always verify that using a CTE will in fact improve your performance--- over a regular subquery.------ /Since: 3.4.0.0/-with :: ( ToAlias a-        , ToAliasReference (ToAliasT a)-        , SqlSelect (ToAliasT a) r-        ) => SqlQuery a -> SqlQuery (From (ToAliasReferenceT (ToAliasT a)))-with query = do-  (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ query-  aliasedValue <- toAlias ret-  let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)-  ident <- newIdentFor (DBName "cte")-  let clause = CommonTableExpressionClause NormalCommonTableExpression ident (\info -> toRawSql SELECT info aliasedQuery)-  Q $ W.tell mempty{sdCteClause = [clause]}-  ref <- toAliasReference ident aliasedValue-  pure $ FromCte ident ref---- | @WITH@ @RECURSIVE@ allows one to make a recursive subquery, which can--- reference itself. Like @WITH@, this is supported in most modern SQL engines.--- Useful for hierarchical, self-referential data, like a tree of data.------ @--- select $ do--- cte <- withRecursive---          (do $---              person <- from $ Table \@Person---              where_ $ person ^. PersonId ==. val personId---              pure person---          )---          unionAll_---          (\\self -> do $---              (p :& f :& p2 :& pSelf) <- from self---                       \`InnerJoin\` $ Table \@Follow---                       \`on\` (\\(p :& f) ->---                               p ^. PersonId ==. f ^. FollowFollower)---                       \`InnerJoin\` $ Table \@Person---                       \`on\` (\\(p :& f :& p2) ->---                               f ^. FollowFollowed ==. p2 ^. PersonId)---                       \`LeftOuterJoin\` self---                       \`on\` (\\(_ :& _ :& p2 :& pSelf) ->---                               just (p2 ^. PersonId) ==. pSelf ?. PersonId)---              where_ $ isNothing (pSelf ?. PersonId)---              groupBy (p2 ^. PersonId)---              pure p2---          )--- from cte--- @------ /Since: 3.4.0.0/-withRecursive :: ( ToAlias a-                 , ToAliasReference (ToAliasT a)-                 , SqlSelect a r-                 , SqlSelect (ToAliasT a) r-                 , ref ~ ToAliasReferenceT (ToAliasT a)-                 , RecursiveCteUnion unionKind-                 )-              => SqlQuery a-              -> unionKind-              -> (From ref -> SqlQuery a)-              -> SqlQuery (From ref)-withRecursive baseCase unionKind recursiveCase = do-  (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ baseCase-  aliasedValue <- toAlias ret-  let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)-  ident <- newIdentFor (DBName "cte")-  ref <- toAliasReference ident aliasedValue-  let refFrom = FromCte ident ref-  let recursiveQuery = recursiveCase refFrom-  let clause = CommonTableExpressionClause RecursiveCommonTableExpression ident-               (\info -> (toRawSql SELECT info aliasedQuery)-                      <> (unionKeyword unionKind, mempty)-                      <> (toRawSql SELECT info recursiveQuery)-               )-  Q $ W.tell mempty{sdCteClause = [clause]}-  pure refFrom--type family ToAliasT a where-  ToAliasT (SqlExpr (Value a)) = SqlExpr (Value a)-  ToAliasT (SqlExpr (Entity a)) = SqlExpr (Entity a)-  ToAliasT (SqlExpr (Maybe (Entity a))) = SqlExpr (Maybe (Entity a))-  ToAliasT (a, b) = (ToAliasT a, ToAliasT b)-  ToAliasT (a, b, c) = (ToAliasT a, ToAliasT b, ToAliasT c)-  ToAliasT (a, b, c, d) = (ToAliasT a, ToAliasT b, ToAliasT c, ToAliasT d)-  ToAliasT (a, b, c, d, e) = (ToAliasT a, ToAliasT b, ToAliasT c, ToAliasT d, ToAliasT e)-  ToAliasT (a, b, c, d, e, f) = (ToAliasT a, ToAliasT b, ToAliasT c, ToAliasT d, ToAliasT e, ToAliasT f)-  ToAliasT (a, b, c, d, e, f, g) = (ToAliasT a, ToAliasT b, ToAliasT c, ToAliasT d, ToAliasT e, ToAliasT f, ToAliasT g)-  ToAliasT (a, b, c, d, e, f, g, h) = (ToAliasT a, ToAliasT b, ToAliasT c, ToAliasT d, ToAliasT e, ToAliasT f, ToAliasT g, ToAliasT h)---- Tedious tuple magic-class ToAlias a where-  toAlias :: a -> SqlQuery (ToAliasT a)--instance ToAlias (SqlExpr (Value a)) where-  toAlias v@(EAliasedValue _ _) = pure v-  toAlias v = do-    ident <- newIdentFor (DBName "v")-    pure $ EAliasedValue ident v--instance ToAlias (SqlExpr (Entity a)) where-  toAlias v@(EAliasedEntityReference _ _) = pure v-  toAlias v@(EAliasedEntity _ _) = pure v-  toAlias (EEntity tableIdent) = do-    ident <- newIdentFor (DBName "v")-    pure $ EAliasedEntity ident tableIdent--instance ToAlias (SqlExpr (Maybe (Entity a))) where-  toAlias (EMaybe e) = EMaybe <$> toAlias e--instance (ToAlias a, ToAlias b) => ToAlias (a,b) where-  toAlias (a,b) = (,) <$> toAlias a <*> toAlias b--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         ) => ToAlias (a,b,c) where-  toAlias x = to3 <$> (toAlias $ from3 x)--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         , ToAlias d-         ) => ToAlias (a,b,c,d) where-  toAlias x = to4 <$> (toAlias $ from4 x)--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         , ToAlias d-         , ToAlias e-         ) => ToAlias (a,b,c,d,e) where-  toAlias x = to5 <$> (toAlias $ from5 x)--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         , ToAlias d-         , ToAlias e-         , ToAlias f-         ) => ToAlias (a,b,c,d,e,f) where-  toAlias x = to6 <$> (toAlias $ from6 x)--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         , ToAlias d-         , ToAlias e-         , ToAlias f-         , ToAlias g-         ) => ToAlias (a,b,c,d,e,f,g) where-  toAlias x = to7 <$> (toAlias $ from7 x)--instance ( ToAlias a-         , ToAlias b-         , ToAlias c-         , ToAlias d-         , ToAlias e-         , ToAlias f-         , ToAlias g-         , ToAlias h-         ) => ToAlias (a,b,c,d,e,f,g,h) where-  toAlias x = to8 <$> (toAlias $ from8 x)---type family ToAliasReferenceT a where-  ToAliasReferenceT (SqlExpr (Value a)) = SqlExpr (Value a)-  ToAliasReferenceT (SqlExpr (Entity a)) = SqlExpr (Entity a)-  ToAliasReferenceT (SqlExpr (Maybe (Entity a))) = SqlExpr (Maybe (Entity a))-  ToAliasReferenceT (a,b) = (ToAliasReferenceT a, ToAliasReferenceT b)-  ToAliasReferenceT (a,b,c) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c)-  ToAliasReferenceT (a, b, c, d) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c, ToAliasReferenceT d)-  ToAliasReferenceT (a, b, c, d, e) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c, ToAliasReferenceT d, ToAliasReferenceT e)-  ToAliasReferenceT (a, b, c, d, e, f) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c, ToAliasReferenceT d, ToAliasReferenceT e, ToAliasReferenceT f)-  ToAliasReferenceT (a, b, c, d, e, f, g) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c, ToAliasReferenceT d, ToAliasReferenceT e, ToAliasReferenceT f, ToAliasReferenceT g)-  ToAliasReferenceT (a, b, c, d, e, f, g, h) = (ToAliasReferenceT a, ToAliasReferenceT b, ToAliasReferenceT c, ToAliasReferenceT d, ToAliasReferenceT e, ToAliasReferenceT f, ToAliasReferenceT g, ToAliasReferenceT h)---- more tedious tuple magic-class ToAliasReference a where-  toAliasReference :: Ident -> a -> SqlQuery (ToAliasReferenceT a)--instance ToAliasReference (SqlExpr (Value a)) where-  toAliasReference aliasSource (EAliasedValue aliasIdent _) = pure $ EValueReference aliasSource (\_ -> aliasIdent)-  toAliasReference _           v@(ERaw _ _)                 = toAlias v-  toAliasReference _           v@(ECompositeKey _)          = toAlias v-  toAliasReference s             (EValueReference _ b)      = pure $ EValueReference s b--instance ToAliasReference (SqlExpr (Entity a)) where-  toAliasReference aliasSource (EAliasedEntity ident _) = pure $ EAliasedEntityReference aliasSource ident-  toAliasReference _ e@(EEntity _) = toAlias e-  toAliasReference s   (EAliasedEntityReference _ b) = pure $ EAliasedEntityReference s b--instance ToAliasReference (SqlExpr (Maybe (Entity a))) where-  toAliasReference s (EMaybe e) = EMaybe <$> toAliasReference s e-instance (ToAliasReference a, ToAliasReference b) => ToAliasReference (a, b) where-  toAliasReference ident (a,b) = (,) <$> (toAliasReference ident a) <*> (toAliasReference ident b)--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         ) => ToAliasReference (a,b,c) where-  toAliasReference ident x = fmap to3 $ toAliasReference ident $ from3 x--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         , ToAliasReference d-         ) => ToAliasReference (a,b,c,d) where-  toAliasReference ident x = fmap to4 $ toAliasReference ident $ from4 x--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         , ToAliasReference d-         , ToAliasReference e-         ) => ToAliasReference (a,b,c,d,e) where-  toAliasReference ident x = fmap to5 $ toAliasReference ident $ from5 x--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         , ToAliasReference d-         , ToAliasReference e-         , ToAliasReference f-         ) => ToAliasReference (a,b,c,d,e,f) where-  toAliasReference ident x = to6 <$> (toAliasReference ident $ from6 x)--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         , ToAliasReference d-         , ToAliasReference e-         , ToAliasReference f-         , ToAliasReference g-         ) => ToAliasReference (a,b,c,d,e,f,g) where-  toAliasReference ident x = to7 <$> (toAliasReference ident $ from7 x)--instance ( ToAliasReference a-         , ToAliasReference b-         , ToAliasReference c-         , ToAliasReference d-         , ToAliasReference e-         , ToAliasReference f-         , ToAliasReference g-         , ToAliasReference h-         ) => ToAliasReference (a,b,c,d,e,f,g,h) where-  toAliasReference ident x = to8 <$> (toAliasReference ident $ from8 x)---class RecursiveCteUnion a where-  unionKeyword :: a -> TLB.Builder--instance RecursiveCteUnion (a -> b -> Union a b) where-  unionKeyword _ = "\nUNION\n"-instance RecursiveCteUnion (a -> b -> UnionAll a b) where-  unionKeyword _ = "\nUNION ALL\n"+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This module contains a new way (introduced in 3.3.3.0) of using @FROM@ in+-- Haskell. The old method was a bit finicky and could permit runtime errors,+-- and this new way is both significantly safer and much more powerful.+--+-- Esqueleto users are encouraged to migrate to this module, as it will become+-- the default in a new major version @4.0.0.0@.+module Database.Esqueleto.Experimental+    ( -- * Setup+      -- $setup++      -- * Introduction+      -- $introduction++      -- * A New Syntax+      -- $new-syntax++      -- * Documentation++      From(..)+    , on+    , from+    , (:&)(..)++      -- ** Set Operations+      -- $sql-set-operations+    , union_+    , Union(..)+    , unionAll_+    , UnionAll(..)+    , except_+    , Except(..)+    , intersect_+    , Intersect(..)+    , pattern SelectQuery++      -- ** Common Table Expressions+    , with+    , withRecursive++      -- * Internals+    , ToFrom(..)+    , ToMaybe(..)+    , ToAlias(..)+    , ToAliasT+    , ToAliasReference(..)+    , ToAliasReferenceT+    -- * The Normal Stuff++    , where_+    , groupBy+    , orderBy+    , rand+    , asc+    , desc+    , limit+    , offset++    , distinct+    , distinctOn+    , don+    , distinctOnOrderBy+    , having+    , locking++    , sub_select+    , (^.)+    , (?.)++    , val+    , isNothing+    , just+    , nothing+    , joinV+    , withNonNull++    , countRows+    , count+    , countDistinct++    , not_+    , (==.)+    , (>=.)+    , (>.)+    , (<=.)+    , (<.)+    , (!=.)+    , (&&.)+    , (||.)++    , between+    , (+.)+    , (-.)+    , (/.)+    , (*.)++    , random_+    , round_+    , ceiling_+    , floor_++    , min_+    , max_+    , sum_+    , avg_+    , castNum+    , castNumM++    , coalesce+    , coalesceDefault++    , lower_+    , upper_+    , trim_+    , ltrim_+    , rtrim_+    , length_+    , left_+    , right_++    , like+    , ilike+    , (%)+    , concat_+    , (++.)+    , castString++    , subList_select+    , valList+    , justList++    , in_+    , notIn+    , exists+    , notExists++    , set+    , (=.)+    , (+=.)+    , (-=.)+    , (*=.)+    , (/=.)++    , case_+    , toBaseId+    , subSelect+    , subSelectMaybe+    , subSelectCount+    , subSelectForeign+    , subSelectList+    , subSelectUnsafe+    , ToBaseId(..)+    , when_+    , then_+    , else_+    , Value(..)+    , ValueList(..)+    , OrderBy+    , DistinctOn+    , LockingKind(..)+    , SqlString+      -- ** Joins+    , InnerJoin(..)+    , CrossJoin(..)+    , LeftOuterJoin(..)+    , RightOuterJoin(..)+    , FullOuterJoin(..)+    , JoinKind(..)+    , OnClauseWithoutMatchingJoinException(..)+      -- * SQL backend+    , SqlQuery+    , SqlExpr+    , SqlEntity+    , select+    , selectSource+    , delete+    , deleteCount+    , update+    , updateCount+    , insertSelect+    , insertSelectCount+    , (<#)+    , (<&>)+    -- ** Rendering Queries+    , renderQueryToText+    , renderQuerySelect+    , renderQueryUpdate+    , renderQueryDelete+    , renderQueryInsertInto+    -- * Internal.Language+    -- * RDBMS-specific modules+    -- $rdbmsSpecificModules++    -- * Helpers+    , valkey+    , valJ+    , associateJoin++      -- * Re-exports+      -- $reexports+    , deleteKey+    , module Database.Esqueleto.Internal.PersistentImport+    ) where++import Control.Monad.Trans.Class (lift)+import qualified Control.Monad.Trans.State as S+import qualified Control.Monad.Trans.Writer as W+#if __GLASGOW_HASKELL__ < 804+import Data.Semigroup+#endif+import Data.Kind (Constraint)+import Data.Proxy (Proxy(..))+import qualified Data.Text.Lazy.Builder as TLB+import Database.Esqueleto.Internal.Internal hiding (From, from, on)+import Database.Esqueleto.Internal.PersistentImport+import GHC.TypeLits++-- $setup+--+-- If you're already using "Database.Esqueleto", then you can get+-- started using this module just by changing your imports slightly,+-- as well as enabling the [TypeApplications](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-TypeApplications) extension.+--+-- @+-- {-\# LANGUAGE TypeApplications \#-}+--+-- ...+--+-- import Database.Esqueleto.Experimental+-- @+--+-- Note: Prior to @esqueleto-3.3.4.0@, the @Database.Esqueleto.Experimental@+-- module did not reexport @Data.Esqueleto@.++----------------------------------------------------------------------++-- $introduction+--+-- This module is fully backwards-compatible extension to the @esqueleto@+-- EDSL that expands subquery functionality and enables+-- [SQL set operations](https://en.wikipedia.org/wiki/Set_operations_(SQL\))+-- to be written directly in Haskell. Specifically, this enables:+--+--   * Subqueries in 'JOIN' statements+--   * 'UNION'+--   * 'UNION' 'ALL'+--   * 'INTERSECT'+--   * 'EXCEPT'+--+-- As a consequence of this, several classes of runtime errors are now+-- caught at compile time. This includes missing 'on' clauses and improper+-- handling of @Maybe@ values in outer joins.+--+-- This module can be used in conjunction with the main "Database.Esqueleto"+-- module, but doing so requires qualified imports to avoid ambiguous+-- definitions of 'on' and 'from', which are defined in both modules.+--+-- Below we will give an overview of how to use this module and the+-- features it enables.++----------------------------------------------------------------------++-- $new-syntax+--+-- This module introduces a new syntax that serves to enable the aforementioned+-- features. This new syntax also changes how joins written in the @esqueleto@+-- EDSL to more closely resemble the underlying SQL.+--+-- For our examples, we'll use a schema similar to the one in the Getting Started+-- section of "Database.Esqueleto":+--+-- @+-- share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|+--   Person+--     name String+--     age Int Maybe+--     deriving Eq Show+--   BlogPost+--     title String+--     authorId PersonId+--     deriving Eq Show+--   Follow+--     follower PersonId+--     followed PersonId+--     deriving Eq Show+-- |]+-- @+--+-- === Example 1: Simple select+--+-- Let's select all people who are named \"John\".+--+-- ==== "Database.Esqueleto":+--+-- @+-- select $+-- from $ \\people -> do+-- where_ (people ^. PersonName ==. val \"John\")+-- pure people+-- @+--+-- ==== "Database.Esqueleto.Experimental":+--+-- @+-- select $ do+-- people <- from $ Table \@Person+-- where_ (people ^. PersonName ==. val \"John\")+-- pure people+-- @+--+--+-- === Example 2: Select with join+--+-- Let's select all people and their blog posts who are over+-- the age of 18.+--+-- ==== "Database.Esqueleto":+--+-- @+-- select $+-- from $ \\(people \`LeftOuterJoin\` blogPosts) -> do+-- on (people ^. PersonId ==. blogPosts ?. BlogPostAuthorId)+-- where_ (people ^. PersonAge >. val 18)+-- pure (people, blogPosts)+-- @+--+-- ==== "Database.Esqueleto.Experimental":+--+-- Here we use the ':&' operator to pattern match against the joined tables.+--+-- @+-- select $ do+-- (people :& blogPosts) <-+--     from $ Table \@Person+--     \`LeftOuterJoin\` Table \@BlogPost+--     \`on\` (\\(people :& blogPosts) ->+--             people ^. PersonId ==. blogPosts ?. BlogPostAuthorId)+-- where_ (people ^. PersonAge >. val 18)+-- pure (people, blogPosts)+-- @+--+-- === Example 3: Select with multi-table join+--+-- Let's select all people who follow a person named \"John\", including+-- the name of each follower.+--+-- ==== "Database.Esqueleto":+--+-- @+-- select $+-- from $ \\(+--  people1+--  \`InnerJoin\` followers+--  \`InnerJoin\` people2+-- ) -> do+-- on (people1 ^. PersonId ==. followers ^. FollowFollowed)+-- on (followers ^. FollowFollower ==. people2 ^. PersonId)+-- where_ (people1 ^. PersonName ==. val \"John\")+-- pure (followers, people2)+-- @+--+-- ==== "Database.Esqueleto.Experimental":+--+-- In this version, with each successive 'on' clause, only the tables+-- we have already joined into are in scope, so we must pattern match+-- accordingly. In this case, in the second 'InnerJoin', we do not use+-- the first `Person` reference, so we use @_@ as a placeholder to+-- ignore it. This prevents a possible runtime error where a table+-- is referenced before it appears in the sequence of 'JOIN's.+--+-- @+-- select $ do+-- (people1 :& followers :& people2) <-+--     from $ Table \@Person+--     \`InnerJoin` Table \@Follow+--     \`on\` (\\(people1 :& followers) ->+--             people1 ^. PersonId ==. followers ^. FollowFollowed)+--     \`InnerJoin` Table \@Person+--     \`on\` (\\(_ :& followers :& people2) ->+--             followers ^. FollowFollower ==. people2 ^. PersonId)+-- where_ (people1 ^. PersonName ==. val \"John\")+-- pure (followers, people2)+-- @+--+-- === Example 4: Counting results of a subquery+--+-- Let's count the number of people who have posted at least 10 posts+--+-- ==== "Database.Esqueleto":+--+-- @+-- select $ pure $ subSelectCount $+-- from $ \\(+--   people+--   \`InnerJoin\` blogPosts+-- ) -> do+-- on (people ^. PersonId ==. blogPosts ^. BlogPostAuthorId)+-- groupBy (people ^. PersonId)+-- having ((count $ blogPosts ^. BlogPostId) >. val 10)+-- pure people+-- @+--+-- ==== "Database.Esqueleto.Experimental":+--+-- @+-- select $ do+-- peopleWithPosts <-+--   from $ do+--     (people :& blogPosts) <-+--       from $ Table \@Person+--       \`InnerJoin\` Table \@BlogPost+--       \`on\` (\\(p :& bP) ->+--               p ^. PersonId ==. bP ^. BlogPostAuthorId)+--     groupBy (people ^. PersonId)+--     having ((count $ blogPosts ^. BlogPostId) >. val 10)+--     pure people+-- pure $ count (peopleWithPosts ^. PersonId)+-- @+--+-- We now have the ability to refactor this+--+-- === Example 5: Sorting the results of a UNION with limits+--+-- Out of all of the posts created by a person and the people they follow,+-- generate a list of the first 25 posts, sorted alphabetically.+--+-- ==== "Database.Esqueleto":+--+-- Since 'UNION' is not supported, this requires using `Database.Esqueleto.rawSql`. (Not shown)+--+-- ==== "Database.Esqueleto.Experimental":+--+-- Since this module supports all set operations (see `SqlSetOperation`), we can use+-- `Union` to write this query.+--+-- @+-- select $ do+-- (authors, blogPosts) <- from $+--   (do+--     (author :& blogPost) <-+--       from $ Table \@Person+--       \`InnerJoin\` Table \@BlogPost+--       \`on\` (\\(a :& bP) ->+--               a ^. PersonId ==. bP ^. BlogPostAuthorId)+--     where_ (author ^. PersonId ==. val currentPersonId)+--     pure (author, blogPost)+--   )+--   \`union_\`+--   (do+--     (follow :& blogPost :& author) <-+--       from $ Table \@Follow+--       \`InnerJoin\` Table \@BlogPost+--       \`on\` (\\(f :& bP) ->+--               f ^. FollowFollowed ==. bP ^. BlogPostAuthorId)+--       \`InnerJoin\` Table \@Person+--       \`on\` (\\(_ :& bP :& a) ->+--               bP ^. BlogPostAuthorId ==. a ^. PersonId)+--     where_ (follow ^. FollowFollower ==. val currentPersonId)+--     pure (author, blogPost)+--   )+-- orderBy [ asc (blogPosts ^. BlogPostTitle) ]+-- limit 25+-- pure (authors, blogPosts)+-- @+--+-- === Example 6: LATERAL JOIN+--+-- As of version @3.4.0.0@, lateral subquery joins are supported.+--+--+-- @+-- select $ do+-- (salesPerson :& maxSaleAmount :& maxSaleCustomerName) <-+--   from $ Table \@SalesPerson+--   \`CrossJoin\` (\\salesPerson -> do+--         sales <- from $ Table \@Sale+--         where_ $ sales ^. SaleSalesPersonId ==. salesPerson ^. SalesPersonId+--         pure $ max_ (sales ^. SaleAmount)+--         )+--   \`CrossJoin\` (\\(salesPerson :& maxSaleAmount) -> do+--         sales <- from $ Table \@Sale+--         where_ $ sales ^. SaleSalesPersonId ==. salesPerson ^. SalesPersonId+--              &&. sales ^. SaleAmount ==. maxSaleAmount+--         pure $ sales ^. SaleCustomerName)+--         )+-- pure (salesPerson ^. SalesPersonName, maxSaleAmount, maxSaleCustomerName)+-- @+--+-- This is the equivalent to the following SQL (example taken from the+-- [MySQL Lateral Derived Table](https://dev.mysql.com/doc/refman/8.0/en/lateral-derived-tables.html)+-- documentation):+--+-- @+-- SELECT+--   salesperson.name,+--   max_sale.amount,+--   max_sale_customer.customer_name+-- FROM+--   salesperson,+--   -- calculate maximum size, cache it in transient derived table max_sale+--   LATERAL+--   (SELECT MAX(amount) AS amount+--     FROM all_sales+--     WHERE all_sales.salesperson_id = salesperson.id)+--   AS max_sale,+--   LATERAL+--   (SELECT customer_name+--     FROM all_sales+--     WHERE all_sales.salesperson_id = salesperson.id+--     AND all_sales.amount =+--         -- the cached maximum size+--         max_sale.amount)+--   AS max_sale_customer;+-- @++-- | A left-precedence pair. Pronounced \"and\". Used to represent expressions+-- that have been joined together.+--+-- The precedence behavior can be demonstrated by:+--+-- @+-- a :& b :& c == ((a :& b) :& c)+-- @+--+-- See the examples at the beginning of this module to see how this+-- operator is used in 'JOIN' operations.+data (:&) a b = a :& b+infixl 2 :&++data SqlSetOperation a+    = SqlSetUnion (SqlSetOperation a) (SqlSetOperation a)+    | SqlSetUnionAll (SqlSetOperation a) (SqlSetOperation a)+    | SqlSetExcept (SqlSetOperation a) (SqlSetOperation a)+    | SqlSetIntersect (SqlSetOperation a) (SqlSetOperation a)+    | SelectQueryP NeedParens (SqlQuery a)++-- $sql-set-operations+--+-- Data type that represents SQL set operations. This includes+-- 'UNION', 'UNION' 'ALL', 'EXCEPT', and 'INTERSECT'. These types form+-- a binary tree, with @SqlQuery@ values on the leaves.+--+-- Each function corresponding to the aforementioned set operations+-- can be used as an infix in a @from@ to help with readability+-- and lead to code that closely resembles the underlying SQL. For example,+--+-- @+-- select $ from $+--   (do+--      a <- from Table @A+--      pure $ a ^. ASomeCol+--   )+--   \`union_\`+--   (do+--      b <- from Table @B+--      pure $ b ^. BSomeCol+--   )+-- @+--+-- is translated into+--+-- @+-- SELECT * FROM (+--   (SELECT a.some_col FROM a)+--   UNION+--   (SELECT b.some_col FROM b)+-- )+-- @+--++{-# DEPRECATED Union "/Since: 3.4.0.0/ - Use the 'union_' function instead of the 'Union' data constructor" #-}+data Union a b = a `Union` b++-- | @UNION@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.+union_ :: a -> b -> Union a b+union_ = Union++{-# DEPRECATED UnionAll "/Since: 3.4.0.0/ - Use the 'unionAll_' function instead of the 'UnionAll' data constructor" #-}+data UnionAll a b = a `UnionAll` b++-- | @UNION@ @ALL@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.+unionAll_ :: a -> b -> UnionAll a b+unionAll_ = UnionAll++{-# DEPRECATED Except "/Since: 3.4.0.0/ - Use the 'except_' function instead of the 'Except' data constructor" #-}+data Except a b = a `Except` b++-- | @EXCEPT@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.+except_ :: a -> b -> Except a b+except_ = Except++{-# DEPRECATED Intersect "/Since: 3.4.0.0/ - Use the 'intersect_' function instead of the 'Intersect' data constructor" #-}+data Intersect a b = a `Intersect` b++-- | @INTERSECT@ SQL set operation. Can be used as an infix function between 'SqlQuery' values.+intersect_ :: a -> b -> Intersect a b+intersect_ = Intersect++class SetOperationT a ~ b => ToSetOperation a b | a -> b where+    type SetOperationT a+    toSetOperation :: a -> SqlSetOperation b+instance ToSetOperation (SqlSetOperation a) a where+    type SetOperationT (SqlSetOperation a) = a+    toSetOperation = id+instance ToSetOperation (SqlQuery a) a where+    type SetOperationT (SqlQuery a) = a+    toSetOperation = SelectQueryP Never+instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Union a b) c where+    type SetOperationT (Union a b) = SetOperationT a+    toSetOperation (Union a b) = SqlSetUnion (toSetOperation a) (toSetOperation b)+instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (UnionAll a b) c where+    type SetOperationT (UnionAll a b) = SetOperationT a+    toSetOperation (UnionAll a b) = SqlSetUnionAll (toSetOperation a) (toSetOperation b)+instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Except a b) c where+    type SetOperationT (Except a b) = SetOperationT a+    toSetOperation (Except a b) = SqlSetExcept (toSetOperation a) (toSetOperation b)+instance (ToSetOperation a c, ToSetOperation b c) => ToSetOperation (Intersect a b) c where+    type SetOperationT (Intersect a b) = SetOperationT a+    toSetOperation (Intersect a b) = SqlSetIntersect (toSetOperation a) (toSetOperation b)++{-# DEPRECATED SelectQuery "/Since: 3.4.0.0/ - It is no longer necessary to tag 'SqlQuery' values with @SelectQuery@" #-}+pattern SelectQuery :: SqlQuery a -> SqlSetOperation a+pattern SelectQuery q = SelectQueryP Never q++-- | Data type that represents the syntax of a 'JOIN' tree. In practice,+-- only the @Table@ constructor is used directly when writing queries. For example,+--+-- @+-- select $ from $ Table \@People+-- @+data From a where+    Table+        :: PersistEntity ent+        => From (SqlExpr (Entity ent))+    SubQuery+        :: ( SqlSelect a r+           , ToAlias a+           , ToAliasReference a+           )+        => SqlQuery a+        -> From a+    FromCte+        :: Ident+        -> a+        -> From a+    SqlSetOperation+        :: ( SqlSelect a r+           , ToAlias a+           , ToAliasReference a+           )+        => SqlSetOperation a+        -> From a+    InnerJoinFrom+        :: From a+        -> (From b, (a :& b) -> SqlExpr (Value Bool))+        -> From (a :& b)+    InnerJoinFromLateral+        :: ( SqlSelect b r+           , ToAlias b+           , ToAliasReference b+           )+        => From a+        -> ((a -> SqlQuery b), (a :& b) -> SqlExpr (Value Bool))+        -> From (a :& b)+    CrossJoinFrom+        :: From a+        -> From b+        -> From (a :& b)+    CrossJoinFromLateral+        :: ( SqlSelect b r+           , ToAlias b+           , ToAliasReference b+           )+        => From a+        -> (a -> SqlQuery b)+        -> From (a :& b)+    LeftJoinFrom+        :: ToMaybe b+        => From a+        -> (From b, (a :& ToMaybeT b) -> SqlExpr (Value Bool))+        -> From (a :& ToMaybeT b)+    LeftJoinFromLateral+        :: ( SqlSelect b r+           , ToAlias b+           , ToAliasReference b+           , ToMaybe b+           )+        => From a+        -> ((a -> SqlQuery b), (a :& ToMaybeT b) -> SqlExpr (Value Bool))+        -> From (a :& ToMaybeT b)+    RightJoinFrom+        :: ToMaybe a+        => From a+        -> (From b, (ToMaybeT a :& b) -> SqlExpr (Value Bool))+        -> From (ToMaybeT a :& b)+    FullJoinFrom+        :: (ToMaybe a, ToMaybe b )+        => From a+        -> (From b, (ToMaybeT a :& ToMaybeT b) -> SqlExpr (Value Bool))+        -> From (ToMaybeT a :& ToMaybeT b)++-- | Constraint for `on`. Ensures that only types that require an `on` can be used on+-- the left hand side. This was previously reusing the ToFrom class which was actually+-- a bit too lenient as it allowed to much.+--+-- @since 3.4.0.0+type family ValidOnClauseValue a :: Constraint where+  ValidOnClauseValue (From a) = ()+  ValidOnClauseValue (SqlQuery a) = ()+  ValidOnClauseValue (SqlSetOperation a) = ()+  ValidOnClauseValue (a -> SqlQuery b) = ()+  ValidOnClauseValue _ = TypeError ('Text "Illegal use of ON")++-- | An @ON@ clause that describes how two tables are related. This should be+-- used as an infix operator after a 'JOIN'. For example,+--+-- @+-- select $+-- from $ Table \@Person+-- \`InnerJoin\` Table \@BlogPost+-- \`on\` (\\(p :& bP) ->+--         p ^. PersonId ==. bP ^. BlogPostAuthorId)+-- @+on :: ValidOnClauseValue a => a -> (b -> SqlExpr (Value Bool)) -> (a, b -> SqlExpr (Value Bool))+on = (,)+infix 9 `on`++data Lateral+data NotLateral++type family IsLateral a where+    IsLateral (a -> SqlQuery b) = Lateral+    IsLateral a = NotLateral++type family ErrorOnLateral a :: Constraint where+  ErrorOnLateral (a -> SqlQuery b) = TypeError ('Text "LATERAL can only be used for INNER, LEFT, and CROSS join kinds.")+  ErrorOnLateral _ = ()++{-- Type class magic to allow the use of the `InnerJoin` family of data constructors in from --}+class ToFrom a where+    type ToFromT a+    toFrom :: a -> From (ToFromT a)++-- @since 3.4.0.1+type family FromOnClause a where+    FromOnClause (a, b -> SqlExpr (Value Bool)) = b+    FromOnClause a = TypeError ('Text "Missing ON clause")++instance {-# OVERLAPPABLE #-} ToFrom (InnerJoin a b) where+    type ToFromT (InnerJoin a b) = FromOnClause b+    toFrom = undefined+instance {-# OVERLAPPABLE #-} ToFrom (LeftOuterJoin a b) where+    type ToFromT (LeftOuterJoin a b) = FromOnClause b+    toFrom = undefined+instance {-# OVERLAPPABLE #-} ToFrom (FullOuterJoin a b) where+    type ToFromT (FullOuterJoin a b) = FromOnClause b+    toFrom = undefined+instance {-# OVERLAPPABLE #-} ToFrom (RightOuterJoin a b) where+    type ToFromT (RightOuterJoin a b) = FromOnClause b+    toFrom = undefined++instance ToFrom (From a) where+    type ToFromT (From a) = a+    toFrom = id++instance+    ( ToAlias a+    , ToAliasReference a+    , SqlSelect a r+    )+  =>+    ToFrom (SqlQuery a)+  where+    type ToFromT (SqlQuery a) = a+    toFrom = SubQuery++instance+    ( SqlSelect c r+    , ToAlias c+    , ToAliasReference c+    , ToSetOperation a c+    , ToSetOperation b c+    , c ~ SetOperationT a+    )+  =>+    ToFrom (Union a b)+  where+    type ToFromT (Union a b) = SetOperationT a+    toFrom u = SqlSetOperation $ toSetOperation u++instance+    ( SqlSelect c r+    , ToAlias c+    , ToAliasReference c+    , ToSetOperation a c+    , ToSetOperation b c+    , c ~ SetOperationT a+    )+  =>+    ToFrom (UnionAll a b)+  where+    type ToFromT (UnionAll a b) = SetOperationT a+    toFrom u = SqlSetOperation $ toSetOperation u++instance+    ( SqlSelect c r+    , ToAlias c+    , ToAliasReference c+    , ToSetOperation a c+    , ToSetOperation b c+    , c ~ SetOperationT a+    )+  =>+    ToFrom (Intersect a b)+  where+    type ToFromT (Intersect a b) = SetOperationT a+    toFrom u = SqlSetOperation $ toSetOperation u++instance+    ( SqlSelect c r+    , ToAlias c+    , ToAliasReference c+    , ToSetOperation a c+    , ToSetOperation b c+    , c ~ SetOperationT a+    )+  =>+    ToFrom (Except a b)+  where+    type ToFromT (Except a b) = SetOperationT a+    toFrom u = SqlSetOperation $ toSetOperation u++instance (SqlSelect a r, ToAlias a, ToAliasReference a) => ToFrom (SqlSetOperation a) where+    type ToFromT (SqlSetOperation a) = a+    -- If someone uses just a plain SelectQuery it should behave like a normal subquery+    toFrom (SelectQueryP _ q) = SubQuery q+    -- Otherwise use the SqlSetOperation+    toFrom q = SqlSetOperation q++class ToInnerJoin lateral lhs rhs res where+    toInnerJoin :: Proxy lateral -> lhs -> rhs -> (res -> SqlExpr (Value Bool)) -> From res++instance ( SqlSelect b r+         , ToAlias b+         , ToAliasReference b+         , ToFrom a+         , ToFromT a ~ a'+         ) => ToInnerJoin Lateral a (a' -> SqlQuery b) (a' :& b) where+             toInnerJoin _ lhs q on' = InnerJoinFromLateral (toFrom lhs) (q, on')++instance (ToFrom a, ToFromT a ~ a', ToFrom b, ToFromT b ~ b')+  => ToInnerJoin NotLateral a b (a' :& b') where+      toInnerJoin _ lhs rhs on' = InnerJoinFrom (toFrom lhs) (toFrom rhs, on')++instance (ToInnerJoin (IsLateral b) a b b') => ToFrom (InnerJoin a (b, b' -> SqlExpr (Value Bool))) where+    type ToFromT (InnerJoin a (b, b' -> SqlExpr (Value Bool))) = FromOnClause (b, b' -> SqlExpr(Value Bool))+    toFrom (InnerJoin lhs (rhs, on')) = toInnerJoin (toProxy rhs) lhs rhs on'+        where+            toProxy :: b -> Proxy (IsLateral b)+            toProxy _ = Proxy++-- @since 3.4.0.1+type family FromCrossJoin a b where+    FromCrossJoin a (b -> SqlQuery c) = ToFromT a :& c+    FromCrossJoin a b = ToFromT a :& ToFromT b++instance ( ToFrom a+         , ToFrom b+         , ToFromT (CrossJoin a b) ~ (ToFromT a :& ToFromT b)+         ) => ToFrom (CrossJoin a b) where+    type ToFromT (CrossJoin a b) = FromCrossJoin a b+    toFrom (CrossJoin lhs rhs) = CrossJoinFrom (toFrom lhs) (toFrom rhs)++instance {-# OVERLAPPING #-}+         ( ToFrom a+         , ToFromT a ~ a'+         , SqlSelect b r+         , ToAlias b+         , ToAliasReference b+         ) => ToFrom (CrossJoin a (a' -> SqlQuery b)) where+    type ToFromT (CrossJoin a (a' -> SqlQuery b)) = FromCrossJoin a (a' -> SqlQuery b)+    toFrom (CrossJoin lhs q) = CrossJoinFromLateral (toFrom lhs) q++class ToLeftJoin lateral lhs rhs res where+    toLeftJoin :: Proxy lateral -> lhs -> rhs -> (res -> SqlExpr (Value Bool)) -> From res++instance ( ToFrom a+         , ToFromT a ~ a'+         , SqlSelect b r+         , ToAlias b+         , ToAliasReference b+         , ToMaybe b+         , mb ~ ToMaybeT b+         ) => ToLeftJoin Lateral a (a' -> SqlQuery b) (a' :& mb) where+            toLeftJoin _ lhs q on' = LeftJoinFromLateral (toFrom lhs) (q, on')++instance ( ToFrom a+         , ToFromT a ~ a'+         , ToFrom b+         , ToFromT b ~ b'+         , ToMaybe b'+         , mb ~ ToMaybeT b'+         ) => ToLeftJoin NotLateral a b (a' :& mb) where+            toLeftJoin _ lhs rhs on' = LeftJoinFrom (toFrom lhs) (toFrom rhs, on')++instance ( ToLeftJoin (IsLateral b) a b b'+         ) => ToFrom (LeftOuterJoin a (b, b' -> SqlExpr (Value Bool))) where+            type ToFromT (LeftOuterJoin a (b, b' -> SqlExpr (Value Bool))) = FromOnClause (b, b' -> SqlExpr(Value Bool))+            toFrom (LeftOuterJoin lhs (rhs, on')) =+                toLeftJoin (toProxy rhs) lhs rhs on'+              where+                toProxy :: b -> Proxy (IsLateral b)+                toProxy _ = Proxy++instance ( ToFrom a+         , ToFromT a ~ a'+         , ToFrom b+         , ToFromT b ~ b'+         , ToMaybe a'+         , ma ~ ToMaybeT a'+         , ToMaybe b'+         , mb ~ ToMaybeT b'+         , ErrorOnLateral b+         ) => ToFrom (FullOuterJoin a (b, (ma :& mb) -> SqlExpr (Value Bool))) where+            type ToFromT (FullOuterJoin a (b, (ma :& mb) -> SqlExpr (Value Bool))) = FromOnClause (b, (ma :& mb) -> SqlExpr(Value Bool))+            toFrom (FullOuterJoin lhs (rhs, on')) = FullJoinFrom (toFrom lhs) (toFrom rhs, on')++instance ( ToFrom a+         , ToFromT a ~ a'+         , ToMaybe a'+         , ma ~ ToMaybeT a'+         , ToFrom b+         , ToFromT b ~ b'+         , ErrorOnLateral b+         ) => ToFrom (RightOuterJoin a (b, (ma :& b') -> SqlExpr (Value Bool))) where+            type ToFromT (RightOuterJoin a (b, (ma :& b') -> SqlExpr (Value Bool))) = FromOnClause (b, (ma :& b') -> SqlExpr(Value Bool))+            toFrom (RightOuterJoin lhs (rhs, on')) = RightJoinFrom (toFrom lhs) (toFrom rhs,  on')++type family Nullable a where+    Nullable (Maybe a) = a+    Nullable a =  a++class ToMaybe a where+    type ToMaybeT a+    toMaybe :: a -> ToMaybeT a++instance ToMaybe (SqlExpr (Maybe a)) where+    type ToMaybeT (SqlExpr (Maybe a)) = SqlExpr (Maybe a)+    toMaybe = id++instance ToMaybe (SqlExpr (Entity a)) where+    type ToMaybeT (SqlExpr (Entity a)) = SqlExpr (Maybe (Entity a))+    toMaybe = EMaybe++instance ToMaybe (SqlExpr (Value a)) where+    type ToMaybeT (SqlExpr (Value a)) = SqlExpr (Value (Maybe (Nullable a)))+    toMaybe = veryUnsafeCoerceSqlExprValue++instance (ToMaybe a, ToMaybe b) => ToMaybe (a :& b) where+    type ToMaybeT (a :& b) = (ToMaybeT a :& ToMaybeT b)+    toMaybe (a :& b) = (toMaybe a :& toMaybe b)++instance (ToMaybe a, ToMaybe b) => ToMaybe (a,b) where+    type ToMaybeT (a, b) = (ToMaybeT a, ToMaybeT b)+    toMaybe (a, b) = (toMaybe a, toMaybe b)++instance ( ToMaybe a , ToMaybe b , ToMaybe c) => ToMaybe (a,b,c) where+    type ToMaybeT (a, b, c) = (ToMaybeT a, ToMaybeT b, ToMaybeT c)+    toMaybe = to3 . toMaybe . from3++instance ( ToMaybe a , ToMaybe b , ToMaybe c , ToMaybe d) => ToMaybe (a,b,c,d) where+    type ToMaybeT (a, b, c, d) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d)+    toMaybe = to4 . toMaybe . from4++instance ( ToMaybe a , ToMaybe b , ToMaybe c , ToMaybe d , ToMaybe e) => ToMaybe (a,b,c,d,e) where+    type ToMaybeT (a, b, c, d, e) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e)+    toMaybe = to5 . toMaybe . from5++instance ( ToMaybe a+         , ToMaybe b+         , ToMaybe c+         , ToMaybe d+         , ToMaybe e+         , ToMaybe f+         ) => ToMaybe (a,b,c,d,e,f) where+    type ToMaybeT (a, b, c, d, e, f) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f)+    toMaybe = to6 . toMaybe . from6++instance ( ToMaybe a+         , ToMaybe b+         , ToMaybe c+         , ToMaybe d+         , ToMaybe e+         , ToMaybe f+         , ToMaybe g+         ) => ToMaybe (a,b,c,d,e,f,g) where+    type ToMaybeT (a, b, c, d, e, f, g) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f, ToMaybeT g)+    toMaybe = to7 . toMaybe . from7++instance ( ToMaybe a+         , ToMaybe b+         , ToMaybe c+         , ToMaybe d+         , ToMaybe e+         , ToMaybe f+         , ToMaybe g+         , ToMaybe h+         ) => ToMaybe (a,b,c,d,e,f,g,h) where+     type ToMaybeT (a, b, c, d, e, f, g, h) = (ToMaybeT a, ToMaybeT b, ToMaybeT c, ToMaybeT d, ToMaybeT e, ToMaybeT f, ToMaybeT g, ToMaybeT h)+     toMaybe = to8 . toMaybe . from8++-- | 'FROM' clause, used to bring entities into scope.+--+-- Internally, this function uses the `From` datatype and the+-- `ToFrom` typeclass. Unlike the old `Database.Esqueleto.from`,+-- this does not take a function as a parameter, but rather+-- a value that represents a 'JOIN' tree constructed out of+-- instances of `ToFrom`. This implementation eliminates certain+-- types of runtime errors by preventing the construction of+-- invalid SQL (e.g. illegal nested-@from@).+from :: ToFrom a  => a -> SqlQuery (ToFromT a)+from parts = do+    (a, clause) <- runFrom $ toFrom parts+    Q $ W.tell mempty{sdFromClause=[clause]}+    pure a+  where+    runFrom :: From a -> SqlQuery (a, FromClause)+    runFrom e@Table = do+        let ed = entityDef $ getVal e+        ident <- newIdentFor (entityDB ed)+        let entity = EEntity ident+        pure $ (entity, FromStart ident ed)+          where+            getVal :: From (SqlExpr (Entity ent)) -> Proxy ent+            getVal = const Proxy+    runFrom (SubQuery subquery) =+        fromSubQuery NormalSubQuery subquery++    runFrom (FromCte ident ref) =+        pure (ref, FromIdent ident)++    runFrom (SqlSetOperation operation) = do+        (aliasedOperation, ret) <- aliasQueries operation+        ident <- newIdentFor (DBName "u")+        ref <- toAliasReference ident ret+        pure (ref, FromQuery ident (operationToSql aliasedOperation) NormalSubQuery)++      where+        aliasQueries o =+            case o of+                SelectQueryP p q -> do+                    (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ q+                    prevState <- Q $ lift S.get+                    aliasedRet <- toAlias ret+                    Q $ lift $ S.put prevState+                    let p' =+                          case p of+                            Parens -> Parens+                            Never ->+                              if (sdLimitClause sideData) /= mempty+                                  || length (sdOrderByClause sideData) > 0 then+                                Parens+                              else+                                Never+                    pure (SelectQueryP p' $ Q $ W.WriterT $ pure (aliasedRet, sideData), aliasedRet)+                SqlSetUnion     o1 o2 -> do+                    (o1', ret) <- aliasQueries o1+                    (o2', _  ) <- aliasQueries o2+                    pure (SqlSetUnion o1' o2', ret)+                SqlSetUnionAll  o1 o2 -> do+                    (o1', ret) <- aliasQueries o1+                    (o2', _  ) <- aliasQueries o2+                    pure (SqlSetUnionAll o1' o2', ret)+                SqlSetExcept    o1 o2 -> do+                    (o1', ret) <- aliasQueries o1+                    (o2', _  ) <- aliasQueries o2+                    pure (SqlSetExcept o1' o2', ret)+                SqlSetIntersect o1 o2 -> do+                    (o1', ret) <- aliasQueries o1+                    (o2', _  ) <- aliasQueries o2+                    pure (SqlSetIntersect o1' o2', ret)++        operationToSql o info =+            case o of+                SelectQueryP p q  ->+                    let (builder, values) = toRawSql SELECT info q+                    in (parensM p builder, values)+                SqlSetUnion     o1 o2 -> doSetOperation "UNION"     info o1 o2+                SqlSetUnionAll  o1 o2 -> doSetOperation "UNION ALL" info o1 o2+                SqlSetExcept    o1 o2 -> doSetOperation "EXCEPT"    info o1 o2+                SqlSetIntersect o1 o2 -> doSetOperation "INTERSECT" info o1 o2++        doSetOperation operationText info o1 o2 =+            let (q1, v1) = operationToSql o1 info+                (q2, v2) = operationToSql o2 info+            in (q1 <> " " <> operationText <> " " <> q2, v1 <> v2)++    runFrom (InnerJoinFrom leftPart (rightPart, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- runFrom rightPart+        let ret = leftVal :& rightVal+        pure $ (ret, FromJoin leftFrom InnerJoinKind rightFrom (Just (on' ret)))+    runFrom (InnerJoinFromLateral leftPart (q, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)+        let ret = leftVal :& rightVal+        pure $ (ret, FromJoin leftFrom InnerJoinKind rightFrom (Just (on' ret)))+    runFrom (CrossJoinFrom leftPart rightPart) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- runFrom rightPart+        let ret = leftVal :& rightVal+        pure $ (ret, FromJoin leftFrom CrossJoinKind rightFrom Nothing)+    runFrom (CrossJoinFromLateral leftPart q) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)+        let ret = leftVal :& rightVal+        pure $ (ret, FromJoin leftFrom CrossJoinKind rightFrom Nothing)+    runFrom (LeftJoinFrom leftPart (rightPart, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- runFrom rightPart+        let ret = leftVal :& (toMaybe rightVal)+        pure $ (ret, FromJoin leftFrom LeftOuterJoinKind rightFrom (Just (on' ret)))+    runFrom (LeftJoinFromLateral leftPart (q, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- fromSubQuery LateralSubQuery (q leftVal)+        let ret = leftVal :& (toMaybe rightVal)+        pure $ (ret, FromJoin leftFrom LeftOuterJoinKind rightFrom (Just (on' ret)))+    runFrom (RightJoinFrom leftPart (rightPart, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- runFrom rightPart+        let ret = (toMaybe leftVal) :& rightVal+        pure $ (ret, FromJoin leftFrom RightOuterJoinKind rightFrom (Just (on' ret)))+    runFrom (FullJoinFrom leftPart (rightPart, on')) = do+        (leftVal, leftFrom) <- runFrom leftPart+        (rightVal, rightFrom) <- runFrom rightPart+        let ret = (toMaybe leftVal) :& (toMaybe rightVal)+        pure $ (ret, FromJoin leftFrom FullOuterJoinKind rightFrom (Just (on' ret)))++fromSubQuery+    ::+    ( SqlSelect a r+    , ToAlias a+    , ToAliasReference a+    )+    => SubQueryType -> SqlQuery a -> SqlQuery (a, FromClause)+fromSubQuery subqueryType subquery = do+    -- We want to update the IdentState without writing the query to side data+    (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ subquery+    aliasedValue <- toAlias ret+    -- Make a fake query with the aliased results, this allows us to ensure that the query is only run once+    let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)+    -- Add the FromQuery that renders the subquery to our side data+    subqueryAlias <- newIdentFor (DBName "q")+    -- Pass the aliased results of the subquery to the outer query+    -- create aliased references from the outer query results (e.g value from subquery will be `subquery`.`value`),+    -- this is probably overkill as the aliases should already be unique but seems to be good practice.+    ref <- toAliasReference subqueryAlias aliasedValue+    pure (ref , FromQuery subqueryAlias (\info -> toRawSql SELECT info aliasedQuery) subqueryType)++-- | @WITH@ clause used to introduce a [Common Table Expression (CTE)](https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL#Common_table_expression).+-- CTEs are supported in most modern SQL engines and can be useful+-- in performance tuning. In Esqueleto, CTEs should be used as a+-- subquery memoization tactic. When writing plain SQL, CTEs+-- are sometimes used to organize the SQL code, in Esqueleto, this+-- is better achieved through function that return 'SqlQuery' values.+--+-- @+-- select $ do+-- cte <- with subQuery+-- cteResult <- from cte+-- where_ $ cteResult ...+-- pure cteResult+-- @+--+-- __WARNING__: In some SQL engines using a CTE can diminish performance.+-- In these engines the CTE is treated as an optimization fence. You should+-- always verify that using a CTE will in fact improve your performance+-- over a regular subquery.+--+-- /Since: 3.4.0.0/+with :: ( ToAlias a+        , ToAliasReference a+        , SqlSelect a r+        ) => SqlQuery a -> SqlQuery (From a)+with query = do+    (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ query+    aliasedValue <- toAlias ret+    let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)+    ident <- newIdentFor (DBName "cte")+    let clause = CommonTableExpressionClause NormalCommonTableExpression ident (\info -> toRawSql SELECT info aliasedQuery)+    Q $ W.tell mempty{sdCteClause = [clause]}+    ref <- toAliasReference ident aliasedValue+    pure $ FromCte ident ref++-- | @WITH@ @RECURSIVE@ allows one to make a recursive subquery, which can+-- reference itself. Like @WITH@, this is supported in most modern SQL engines.+-- Useful for hierarchical, self-referential data, like a tree of data.+--+-- @+-- select $ do+-- cte <- withRecursive+--          (do $+--              person <- from $ Table \@Person+--              where_ $ person ^. PersonId ==. val personId+--              pure person+--          )+--          unionAll_+--          (\\self -> do $+--              (p :& f :& p2 :& pSelf) <- from self+--                       \`InnerJoin\` $ Table \@Follow+--                       \`on\` (\\(p :& f) ->+--                               p ^. PersonId ==. f ^. FollowFollower)+--                       \`InnerJoin\` $ Table \@Person+--                       \`on\` (\\(p :& f :& p2) ->+--                               f ^. FollowFollowed ==. p2 ^. PersonId)+--                       \`LeftOuterJoin\` self+--                       \`on\` (\\(_ :& _ :& p2 :& pSelf) ->+--                               just (p2 ^. PersonId) ==. pSelf ?. PersonId)+--              where_ $ isNothing (pSelf ?. PersonId)+--              groupBy (p2 ^. PersonId)+--              pure p2+--          )+-- from cte+-- @+--+-- /Since: 3.4.0.0/+withRecursive :: ( ToAlias a+                 , ToAliasReference a+                 , SqlSelect a r+                 , RecursiveCteUnion unionKind+                 )+              => SqlQuery a+              -> unionKind+              -> (From a -> SqlQuery a)+              -> SqlQuery (From a)+withRecursive baseCase unionKind recursiveCase = do+    (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ baseCase+    aliasedValue <- toAlias ret+    let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData)+    ident <- newIdentFor (DBName "cte")+    ref <- toAliasReference ident aliasedValue+    let refFrom = FromCte ident ref+    let recursiveQuery = recursiveCase refFrom+    let clause = CommonTableExpressionClause RecursiveCommonTableExpression ident+                 (\info -> (toRawSql SELECT info aliasedQuery)+                        <> (unionKeyword unionKind, mempty)+                        <> (toRawSql SELECT info recursiveQuery)+                 )+    Q $ W.tell mempty{sdCteClause = [clause]}+    pure refFrom++{-# DEPRECATED ToAliasT "This type alias doesn't do anything. Please delete it. Will be removed in the next release." #-}+type ToAliasT a = a++-- Tedious tuple magic+class ToAlias a where+    toAlias :: a -> SqlQuery a++instance ToAlias (SqlExpr (Value a)) where+    toAlias v@(EAliasedValue _ _) = pure v+    toAlias v = do+        ident <- newIdentFor (DBName "v")+        pure $ EAliasedValue ident v++instance ToAlias (SqlExpr (Entity a)) where+    toAlias v@(EAliasedEntityReference _ _) = pure v+    toAlias v@(EAliasedEntity _ _) = pure v+    toAlias (EEntity tableIdent) = do+       ident <- newIdentFor (DBName "v")+       pure $ EAliasedEntity ident tableIdent++instance ToAlias (SqlExpr (Maybe (Entity a))) where+    toAlias (EMaybe e) = EMaybe <$> toAlias e++instance (ToAlias a, ToAlias b) => ToAlias (a,b) where+    toAlias (a,b) = (,) <$> toAlias a <*> toAlias b++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         ) => ToAlias (a,b,c) where+    toAlias x = to3 <$> (toAlias $ from3 x)++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         , ToAlias d+         ) => ToAlias (a,b,c,d) where+    toAlias x = to4 <$> (toAlias $ from4 x)++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         , ToAlias d+         , ToAlias e+         ) => ToAlias (a,b,c,d,e) where+    toAlias x = to5 <$> (toAlias $ from5 x)++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         , ToAlias d+         , ToAlias e+         , ToAlias f+         ) => ToAlias (a,b,c,d,e,f) where+    toAlias x = to6 <$> (toAlias $ from6 x)++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         , ToAlias d+         , ToAlias e+         , ToAlias f+         , ToAlias g+         ) => ToAlias (a,b,c,d,e,f,g) where+    toAlias x = to7 <$> (toAlias $ from7 x)++instance ( ToAlias a+         , ToAlias b+         , ToAlias c+         , ToAlias d+         , ToAlias e+         , ToAlias f+         , ToAlias g+         , ToAlias h+         ) => ToAlias (a,b,c,d,e,f,g,h) where+    toAlias x = to8 <$> (toAlias $ from8 x)++{-# DEPRECATED ToAliasReferenceT "This type alias doesn't do anything. Please delete it. Will be removed in the next release." #-}+type ToAliasReferenceT a = a++-- more tedious tuple magic+class ToAliasReference a where+    toAliasReference :: Ident -> a -> SqlQuery a++instance ToAliasReference (SqlExpr (Value a)) where+    toAliasReference aliasSource (EAliasedValue aliasIdent _) = pure $ EValueReference aliasSource (\_ -> aliasIdent)+    toAliasReference _           v@(ERaw _ _)                 = toAlias v+    toAliasReference _           v@(ECompositeKey _)          = toAlias v+    toAliasReference s             (EValueReference _ b)      = pure $ EValueReference s b++instance ToAliasReference (SqlExpr (Entity a)) where+    toAliasReference aliasSource (EAliasedEntity ident _) = pure $ EAliasedEntityReference aliasSource ident+    toAliasReference _ e@(EEntity _) = toAlias e+    toAliasReference s   (EAliasedEntityReference _ b) = pure $ EAliasedEntityReference s b++instance ToAliasReference (SqlExpr (Maybe (Entity a))) where+    toAliasReference s (EMaybe e) = EMaybe <$> toAliasReference s e+++instance (ToAliasReference a, ToAliasReference b) => ToAliasReference (a, b) where+    toAliasReference ident (a,b) = (,) <$> (toAliasReference ident a) <*> (toAliasReference ident b)++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         ) => ToAliasReference (a,b,c) where+    toAliasReference ident x = fmap to3 $ toAliasReference ident $ from3 x++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         , ToAliasReference d+         ) => ToAliasReference (a,b,c,d) where+    toAliasReference ident x = fmap to4 $ toAliasReference ident $ from4 x++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         , ToAliasReference d+         , ToAliasReference e+         ) => ToAliasReference (a,b,c,d,e) where+    toAliasReference ident x = fmap to5 $ toAliasReference ident $ from5 x++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         , ToAliasReference d+         , ToAliasReference e+         , ToAliasReference f+         ) => ToAliasReference (a,b,c,d,e,f) where+    toAliasReference ident x = to6 <$> (toAliasReference ident $ from6 x)++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         , ToAliasReference d+         , ToAliasReference e+         , ToAliasReference f+         , ToAliasReference g+         ) => ToAliasReference (a,b,c,d,e,f,g) where+    toAliasReference ident x = to7 <$> (toAliasReference ident $ from7 x)++instance ( ToAliasReference a+         , ToAliasReference b+         , ToAliasReference c+         , ToAliasReference d+         , ToAliasReference e+         , ToAliasReference f+         , ToAliasReference g+         , ToAliasReference h+         ) => ToAliasReference (a,b,c,d,e,f,g,h) where+    toAliasReference ident x = to8 <$> (toAliasReference ident $ from8 x)++class RecursiveCteUnion a where+    unionKeyword :: a -> TLB.Builder++instance RecursiveCteUnion (a -> b -> Union a b) where+    unionKeyword _ = "\nUNION\n"++instance RecursiveCteUnion (a -> b -> UnionAll a b) where+    unionKeyword _ = "\nUNION ALL\n"
src/Database/Esqueleto/Internal/ExprParser.hs view
@@ -1,21 +1,21 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE RecordWildCards #-}  -- | This is an internal module. This module may have breaking changes without -- a corresponding major version bump. If you use this module, please open an -- issue with your use-case so we can safely support it. module Database.Esqueleto.Internal.ExprParser where -import           Prelude              hiding (takeWhile)+import Prelude hiding (takeWhile) -import           Control.Applicative  ((<|>))-import           Control.Monad        (void)-import           Data.Attoparsec.Text-import           Data.Set             (Set)-import qualified Data.Set             as Set-import           Data.Text            (Text)-import qualified Data.Text            as Text-import           Database.Persist.Sql+import Control.Applicative ((<|>))+import Control.Monad (void)+import Data.Attoparsec.Text+import Data.Set (Set)+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as Text+import Database.Persist.Sql  -- | A type representing the access of a table value. In Esqueleto, we get -- a guarantee that the access will look something like:@@ -26,54 +26,54 @@ --             table name                            column name -- @ data TableAccess = TableAccess-  { tableAccessTable  :: Text-  , tableAccessColumn :: Text-  }-  deriving (Eq, Ord, Show)+    { tableAccessTable  :: Text+    , tableAccessColumn :: Text+    }+    deriving (Eq, Ord, Show)  -- | Parse a @SqlExpr (Value Bool)@'s textual representation into a list of -- 'TableAccess' parseOnExpr :: SqlBackend -> Text -> Either String (Set TableAccess) parseOnExpr sqlBackend text = do-  c <- mkEscapeChar sqlBackend-  parseOnly (onExpr c) text+    c <- mkEscapeChar sqlBackend+    parseOnly (onExpr c) text  -- | This function uses the 'connEscapeName' function in the 'SqlBackend' with an -- empty identifier to pull out an escape character. This implementation works -- with postgresql, mysql, and sqlite backends. mkEscapeChar :: SqlBackend -> Either String Char mkEscapeChar sqlBackend =-  case Text.uncons (connEscapeName sqlBackend (DBName "")) of-    Nothing ->-      Left "Failed to get an escape character from the SQL backend."-    Just (c, _) ->-      Right c+    case Text.uncons (connEscapeName sqlBackend (DBName "")) of+        Nothing ->+            Left "Failed to get an escape character from the SQL backend."+        Just (c, _) ->+            Right c  type ExprParser a = Char -> Parser a  onExpr :: ExprParser (Set TableAccess) onExpr e = Set.fromList <$> many' tableAccesses   where-   tableAccesses = do-     skipToEscape e <?> "Skipping to an escape char"-     parseTableAccess e <?> "Parsing a table access"+    tableAccesses = do+        skipToEscape e <?> "Skipping to an escape char"+        parseTableAccess e <?> "Parsing a table access"  skipToEscape :: ExprParser () skipToEscape escapeChar = void (takeWhile (/= escapeChar))  parseEscapedIdentifier :: ExprParser [Char] parseEscapedIdentifier escapeChar = do-  char escapeChar-  str <- parseEscapedChars escapeChar-  char escapeChar-  pure str+    char escapeChar+    str <- parseEscapedChars escapeChar+    char escapeChar+    pure str  parseTableAccess :: ExprParser TableAccess parseTableAccess ec = do-  tableAccessTable <- Text.pack <$> parseEscapedIdentifier ec-  _ <- char '.'-  tableAccessColumn <- Text.pack <$> parseEscapedIdentifier ec-  pure TableAccess {..}+    tableAccessTable <- Text.pack <$> parseEscapedIdentifier ec+    _ <- char '.'+    tableAccessColumn <- Text.pack <$> parseEscapedIdentifier ec+    pure TableAccess {..}  parseEscapedChars :: ExprParser [Char] parseEscapedChars escapeChar = go
src/Database/Esqueleto/Internal/Internal.hs view
@@ -1,3728 +1,3774 @@-{-# LANGUAGE DeriveDataTypeable-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , MultiParamTypeClasses-           , TypeFamilies-           , UndecidableInstances-           , GADTs- #-}-{-# LANGUAGE ConstraintKinds-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , GADTs-           , MultiParamTypeClasses-           , OverloadedStrings-           , UndecidableInstances-           , ScopedTypeVariables-           , InstanceSigs-           , Rank2Types-           , CPP- #-}--- | This is an internal module, anything exported by this module--- may change without a major version bump.  Please use only--- "Database.Esqueleto" if possible.------ If you use this module, please report what your use case is on the issue--- tracker so we can safely support it.-module Database.Esqueleto.Internal.Internal where--import Control.Applicative ((<|>))-import Control.Arrow ((***), first)-import Control.Exception (Exception, throw, throwIO)-import qualified Data.Maybe as Maybe-import Control.Monad (guard, ap, MonadPlus(..), void)-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Resource (MonadResource, release)-import Data.Acquire (with, allocateAcquire, Acquire)-import Data.Int (Int64)-import Data.List (intersperse)-#if __GLASGOW_HASKELL__ < 804-import Data.Semigroup-#endif-import qualified Data.Monoid as Monoid-import Data.Proxy (Proxy(..))-import Database.Esqueleto.Internal.PersistentImport-import qualified Database.Persist-import Database.Persist.Sql.Util (entityColumnNames, entityColumnCount, parseEntityValues, isIdField, hasCompositeKey)-import qualified Data.Set as Set-import Data.Set (Set)-import qualified Control.Monad.Trans.Reader as R-import qualified Control.Monad.Trans.State as S-import qualified Control.Monad.Trans.Writer as W-import qualified Data.ByteString as B-import qualified Data.Conduit as C-import qualified Data.Conduit.List as CL-import qualified Data.HashSet as HS-import qualified Data.Map.Strict as Map-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Builder as TLB--import Data.Typeable (Typeable)-import Text.Blaze.Html (Html)---import Database.Esqueleto.Internal.ExprParser (TableAccess(..), parseOnExpr)---- | (Internal) Start a 'from' query with an entity. 'from'--- does two kinds of magic using 'fromStart', 'fromJoin' and--- 'fromFinish':------   1.  The simple but tedious magic of allowing tuples to be---   used.------   2.  The more advanced magic of creating @JOIN@s.  The---   @JOIN@ is processed from right to left.  The rightmost---   entity of the @JOIN@ is created with 'fromStart'.  Each---   @JOIN@ step is then translated into a call to 'fromJoin'.---   In the end, 'fromFinish' is called to materialize the---   @JOIN@.-fromStart-  :: ( PersistEntity a-     , BackendCompatible SqlBackend (PersistEntityBackend a) )-  => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a))))-fromStart = x-  where-    x = do-      let ed = entityDef (getVal x)-      ident <- newIdentFor (entityDB ed)-      let ret   = EEntity ident-          f' = FromStart ident ed-      return (EPreprocessedFrom ret f')-    getVal :: SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a)))) -> Proxy a-    getVal = const Proxy---- | (Internal) Same as 'fromStart', but entity may be missing.-fromStartMaybe-  :: ( PersistEntity a-     , BackendCompatible SqlBackend (PersistEntityBackend a) )-  => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Maybe (Entity a)))))-fromStartMaybe = maybelize <$> fromStart-  where-    maybelize :: SqlExpr (PreprocessedFrom (SqlExpr (Entity a)))-              -> SqlExpr (PreprocessedFrom (SqlExpr (Maybe (Entity a))))-    maybelize (EPreprocessedFrom ret f') = EPreprocessedFrom (EMaybe ret) f'---- | (Internal) Do a @JOIN@.-fromJoin-  :: IsJoinKind join-  => SqlExpr (PreprocessedFrom a)-  -> SqlExpr (PreprocessedFrom b)-  -> SqlQuery (SqlExpr (PreprocessedFrom (join a b)))-fromJoin (EPreprocessedFrom lhsRet lhsFrom)-         (EPreprocessedFrom rhsRet rhsFrom) = Q $ do-  let ret   = smartJoin lhsRet rhsRet-      from' = FromJoin lhsFrom             -- LHS-                       (reifyJoinKind ret) -- JOIN-                       rhsFrom             -- RHS-                       Nothing             -- ON-  return (EPreprocessedFrom ret from')---- | (Internal) Finish a @JOIN@.-fromFinish-  :: SqlExpr (PreprocessedFrom a)-  -> SqlQuery a-fromFinish (EPreprocessedFrom ret f') = Q $ do-  W.tell mempty { sdFromClause = [f'] }-  return ret---- | @WHERE@ clause: restrict the query's result.-where_ :: SqlExpr (Value Bool) -> SqlQuery ()-where_ expr = Q $ W.tell mempty { sdWhereClause = Where expr }---- | An @ON@ clause, useful to describe how two tables are related. Cross joins--- and tuple-joins do not need an 'on' clause, but 'InnerJoin' and the various--- outer joins do.------ "Database.Esqueleto.Experimental" in version 4.0.0.0 of the library. The--- @Experimental@ module has a dramatically improved means for introducing--- tables and entities that provides more power and less potential for runtime--- errors.------ If you don't include an 'on' clause (or include too many!) then a runtime--- exception will be thrown.------ As an example, consider this simple join:------ @--- 'select' $--- 'from' $ \\(foo `'InnerJoin`` bar) -> do---   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)---   ...--- @------ We need to specify the clause for joining the two columns together. If we had--- this:------ @--- 'select' $--- 'from' $ \\(foo `'CrossJoin`` bar) -> do---   ...--- @------ Then we can safely omit the 'on' clause, because the cross join will make--- pairs of all records possible.------ You can do multiple 'on' clauses in a query. This query joins three tables,--- and has two 'on' clauses:------ @--- 'select' $--- 'from' $ \\(foo `'InnerJoin`` bar `'InnerJoin`` baz) -> do---   'on' (baz '^.' BazId '==.' bar '^.' BarBazId)---   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)---   ...--- @------ Old versions of esqueleto required that you provide the 'on' clauses in--- reverse order. This restriction has been lifted - you can now provide 'on'--- clauses in any order, and the SQL should work itself out. The above query is--- now totally equivalent to this:------ @--- 'select' $--- 'from' $ \\(foo `'InnerJoin`` bar `'InnerJoin`` baz) -> do---   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)---   'on' (baz '^.' BazId '==.' bar '^.' BarBazId)---   ...--- @-on :: SqlExpr (Value Bool) -> SqlQuery ()-on expr = Q $ W.tell mempty { sdFromClause = [OnClause expr] }---- | @GROUP BY@ clause. You can enclose multiple columns--- in a tuple.------ @--- select $ 'from' \\(foo `'InnerJoin`` bar) -> do---   'on' (foo '^.' FooBarId '==.' bar '^.' BarId)---   'groupBy' (bar '^.' BarId, bar '^.' BarName)---   return (bar '^.' BarId, bar '^.' BarName, countRows)--- @------ With groupBy you can sort by aggregate functions, like so--- (we used @let@ to restrict the more general 'countRows' to--- @SqlSqlExpr (Value Int)@ to avoid ambiguity---the second use of--- 'countRows' has its type restricted by the @:: Int@ below):------ @--- r \<- select $ 'from' \\(foo `'InnerJoin`` bar) -> do---   'on' (foo '^.' FooBarId '==.' bar '^.' BarId)---   'groupBy' $ bar '^.' BarName---   let countRows' = 'countRows'---   'orderBy' ['asc' countRows']---   return (bar '^.' BarName, countRows')--- forM_ r $ \\('Value' name, 'Value' count) -> do---   print name---   print (count :: Int)--- @------ === Need more columns?------ The 'ToSomeValues' class is defined for 'SqlExpr' and tuples of 'SqlExpr's.--- We only have definitions for up to 8 elements in a tuple right now, so it's--- possible that you may need to have more than 8 elements.------ For example, consider a query with a 'groupBy' call like this:------ @--- groupBy (e0, e1, e2, e3, e4, e5, e6, e7)--- @------ This is the biggest you can get with a single tuple. However, you can easily--- nest the tuples to add more:------ @--- groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9)--- @-groupBy :: (ToSomeValues a) => a -> SqlQuery ()-groupBy expr = Q $ W.tell mempty { sdGroupByClause = GroupBy $ toSomeValues expr }---- | @ORDER BY@ clause. See also 'asc' and 'desc'.------ Multiple calls to 'orderBy' get concatenated on the final--- query, including 'distinctOnOrderBy'.-orderBy :: [SqlExpr OrderBy] -> SqlQuery ()-orderBy exprs = Q $ W.tell mempty { sdOrderByClause = exprs }---- | Ascending order of this field or SqlExpression.-asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy-asc  = EOrderBy ASC---- | Descending order of this field or SqlExpression.-desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy-desc = EOrderBy DESC---- | @LIMIT@.  Limit the number of returned rows.-limit :: Int64 -> SqlQuery ()-limit  n = Q $ W.tell mempty { sdLimitClause = Limit (Just n) Nothing  }---- | @OFFSET@.  Usually used with 'limit'.-offset :: Int64 -> SqlQuery ()-offset n = Q $ W.tell mempty { sdLimitClause = Limit Nothing  (Just n) }---- | @DISTINCT@.  Change the current @SELECT@ into @SELECT--- DISTINCT@.  For example:------ @--- select $ distinct $---   'from' \\foo -> do---   ...--- @------ Note that this also has the same effect:------ @--- select $---   'from' \\foo -> do---   distinct (return ())---   ...--- @------ /Since: 2.2.4/-distinct :: SqlQuery a -> SqlQuery a-distinct act = Q (W.tell mempty { sdDistinctClause = DistinctStandard }) >> act---- | @DISTINCT ON@.  Change the current @SELECT@ into--- @SELECT DISTINCT ON (SqlExpressions)@.  For example:------ @--- select $---   'from' \\foo ->---   'distinctOn' ['don' (foo ^. FooName), 'don' (foo ^. FooState)] $ do---   ...--- @------ You can also chain different calls to 'distinctOn'.  The--- above is equivalent to:------ @--- select $---   'from' \\foo ->---   'distinctOn' ['don' (foo ^. FooName)] $---   'distinctOn' ['don' (foo ^. FooState)] $ do---   ...--- @------ Each call to 'distinctOn' adds more SqlExpressions.  Calls to--- 'distinctOn' override any calls to 'distinct'.------ Note that PostgreSQL requires the SqlExpressions on @DISTINCT--- ON@ to be the first ones to appear on a @ORDER BY@.  This is--- not managed automatically by esqueleto, keeping its spirit--- of trying to be close to raw SQL.------ Supported by PostgreSQL only.------ /Since: 2.2.4/-distinctOn :: [SqlExpr DistinctOn] -> SqlQuery a -> SqlQuery a-distinctOn exprs act = Q (W.tell mempty { sdDistinctClause = DistinctOn exprs }) >> act---- | Erase an SqlExpression's type so that it's suitable to--- be used by 'distinctOn'.------ /Since: 2.2.4/-don :: SqlExpr (Value a) -> SqlExpr DistinctOn-don = EDistinctOn---- | A convenience function that calls both 'distinctOn' and--- 'orderBy'.  In other words,------ @--- 'distinctOnOrderBy' [asc foo, desc bar, desc quux] $ do---   ...--- @------ is the same as:------ @--- 'distinctOn' [don foo, don  bar, don  quux] $ do---   'orderBy'  [asc foo, desc bar, desc quux]---   ...--- @------ /Since: 2.2.4/-distinctOnOrderBy :: [SqlExpr OrderBy] -> SqlQuery a -> SqlQuery a-distinctOnOrderBy exprs act =-  distinctOn (toDistinctOn <$> exprs) $ do-    orderBy exprs-    act-  where-    toDistinctOn :: SqlExpr OrderBy -> SqlExpr DistinctOn-    toDistinctOn (EOrderBy _ f) = EDistinctOn f-    toDistinctOn EOrderRandom =-      error "We can't select distinct by a random order!"---- | @ORDER BY random()@ clause.------ /Since: 1.3.10/-rand :: SqlExpr OrderBy-rand = EOrderRandom---- | @HAVING@.------ /Since: 1.2.2/-having :: SqlExpr (Value Bool) -> SqlQuery ()-having expr = Q $ W.tell mempty { sdHavingClause = Where expr }---- | Add a locking clause to the query.  Please read--- 'LockingKind' documentation and your RDBMS manual.------ If multiple calls to 'locking' are made on the same query,--- the last one is used.------ /Since: 2.2.7/-locking :: LockingKind -> SqlQuery ()-locking kind = Q $ W.tell mempty { sdLockingClause = Monoid.Last (Just kind) }--{-#-  DEPRECATED-    sub_select-    "sub_select \n \-sub_select is an unsafe function to use. If used with a SqlQuery that \n \-returns 0 results, then it may return NULL despite not mentioning Maybe \n \-in the return type. If it returns more than 1 result, then it will throw a \n \-SQL error.\n\n Instead, consider using one of the following alternatives: \n \-- subSelect: attaches a LIMIT 1 and the Maybe return type, totally safe.  \n \-- subSelectMaybe: Attaches a LIMIT 1, useful for a query that already \n \-  has a Maybe in the return type. \n \-- subSelectCount: Performs a count of the query - this is always safe. \n \-- subSelectUnsafe: Performs no checks or guarantees. Safe to use with \n \-  countRows and friends."-  #-}--- | Execute a subquery @SELECT@ in an SqlExpression.  Returns a--- simple value so should be used only when the @SELECT@ query--- is guaranteed to return just one row.------ Deprecated in 3.2.0.-sub_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)-sub_select         = sub SELECT---- | Execute a subquery @SELECT@ in a 'SqlExpr'. The query passed to this--- function will only return a single result - it has a @LIMIT 1@ passed in to--- the query to make it safe, and the return type is 'Maybe' to indicate that--- the subquery might result in 0 rows.------ If you find yourself writing @'joinV' . 'subSelect'@, then consider using--- 'subSelectMaybe'.------ If you're performing a 'countRows', then you can use 'subSelectCount' which--- is safe.------ If you know that the subquery will always return exactly one row (eg--- a foreign key constraint guarantees that you'll get exactly one row), then--- consider 'subSelectUnsafe', along with a comment explaining why it is safe.------ @since 3.2.0-subSelect-  :: PersistField a-  => SqlQuery (SqlExpr (Value a))-  -> SqlExpr (Value (Maybe a))-subSelect query = just (subSelectUnsafe (query <* limit 1))---- | Execute a subquery @SELECT@ in a 'SqlExpr'. This function is a shorthand--- for the common @'joinV' . 'subSelect'@ idiom, where you are calling--- 'subSelect' on an expression that would be 'Maybe' already.------ As an example, you would use this function when calling 'sum_' or 'max_',--- which have 'Maybe' in the result type (for a 0 row query).------ @since 3.2.0-subSelectMaybe-  :: PersistField a-  => SqlQuery (SqlExpr (Value (Maybe a)))-  -> SqlExpr (Value (Maybe a))-subSelectMaybe = joinV . subSelect---- | Performs a @COUNT@ of the given query in a @subSelect@ manner. This is--- always guaranteed to return a result value, and is completely safe.------ @since 3.2.0-subSelectCount-  :: (Num a, PersistField a)-  => SqlQuery ignored-  -> SqlExpr (Value a)-subSelectCount query = do-  subSelectUnsafe $ do-    _ <- query-    pure countRows---- | Execute a subquery @SELECT@ in a 'SqlExpr' that returns a list. This is an--- alias for 'subList_select' and is provided for symmetry with the other safe--- subselect functions.------ @since 3.2.0-subSelectList-  :: PersistField a-  => SqlQuery (SqlExpr (Value a))-  -> SqlExpr (ValueList a)-subSelectList = subList_select---- | Performs a sub-select using the given foreign key on the entity. This is--- useful to extract values that are known to be present by the database schema.------ As an example, consider the following persistent definition:------ @--- User---   profile ProfileId------ Profile---   name    Text--- @------ The following query will return the name of the user.------ @--- getUserWithName =---     'select' $---     'from' $ \user ->---     'pure' (user, 'subSelectForeign' user UserProfile (^. ProfileName)--- @------ @since 3.2.0-subSelectForeign-  ::-  ( BackendCompatible SqlBackend (PersistEntityBackend val1)-  , PersistEntity val1, PersistEntity val2, PersistField a-  )-  => SqlExpr (Entity val2)-  -- ^ An expression representing the table you have access to now.-  -> EntityField val2 (Key val1)-  -- ^ The foreign key field on the table.-  -> (SqlExpr (Entity val1) -> SqlExpr (Value a))-  -- ^ A function to extract a value from the foreign reference table.-  -> SqlExpr (Value a)-subSelectForeign expr foreignKey k =-  subSelectUnsafe $-  from $ \table -> do-  where_ $ expr ^. foreignKey ==. table ^. persistIdField-  pure (k table)---- | Execute a subquery @SELECT@ in a 'SqlExpr'. This function is unsafe,--- because it can throw runtime exceptions in two cases:------ 1. If the query passed has 0 result rows, then it will return a @NULL@ value.---    The @persistent@ parsing operations will fail on an unexpected @NULL@.--- 2. If the query passed returns more than one row, then the SQL engine will---    fail with an error like "More than one row returned by a subquery used as---    an expression".------ This function is safe if you guarantee that exactly one row will be returned,--- or if the result already has a 'Maybe' type for some reason.------ For variants with the safety encoded already, see 'subSelect' and--- 'subSelectMaybe'. For the most common safe use of this, see 'subSelectCount'.------ @since 3.2.0-subSelectUnsafe :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)-subSelectUnsafe = sub SELECT---- | Project a field of an entity.-(^.)-  :: forall typ val. (PersistEntity val, PersistField typ)-  => SqlExpr (Entity val)-  -> EntityField val typ-  -> SqlExpr (Value typ)-(EAliasedEntityReference source base) ^. field =-  EValueReference source (\_ -> aliasedEntityColumnIdent base fieldDef)-    where-      fieldDef =-        if isIdField field then-          -- TODO what about composite natural keys in a join this will ignore them-          head $ entityKeyFields ed-        else-          persistFieldDef field--      ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val)))--e ^. field-  | isIdField field = idFieldValue-  | otherwise = ERaw Never $ \info -> (dot info $ persistFieldDef field, [])-  where-    idFieldValue =-      case entityKeyFields ed of-        idField:[] ->-          ERaw Never    $ \info -> (dot info idField, [])--        idFields ->-          ECompositeKey $ \info ->  dot info <$> idFields---    ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val)))--    dot info fieldDef =-      useIdent info sourceIdent <> "." <> fieldIdent-        where-          sourceIdent =-            case e of-              EEntity ident -> ident-              EAliasedEntity baseI _ -> baseI-          fieldIdent =-            case e of-              EEntity _ -> fromDBName info (fieldDB fieldDef)-              EAliasedEntity baseI _ -> useIdent info $ aliasedEntityColumnIdent baseI fieldDef---- | Project an SqlExpression that may be null, guarding against null cases.-withNonNull :: PersistField typ-            => SqlExpr (Value (Maybe typ))-            -> (SqlExpr (Value typ) -> SqlQuery a)-            -> SqlQuery a-withNonNull field f = do-  where_ $ not_ $ isNothing field-  f $ veryUnsafeCoerceSqlExprValue field---- | Project a field of an entity that may be null.-(?.) :: (PersistEntity val, PersistField typ) =>-        SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe typ))-EMaybe r ?. field = just (r ^. field)---- | Lift a constant value from Haskell-land to the query.-val  :: PersistField typ => typ -> SqlExpr (Value typ)-val v = ERaw Never $ const ("?", [toPersistValue v])---- | @IS NULL@ comparison.------ For @IS NOT NULL@, you can negate this with 'not_', as in @not_ (isNothing (person ^. PersonAge))@------ Warning: Persistent and Esqueleto have different behavior for @!= Nothing@:------ +----------------+----------------------------------+---------------+--- |                | Haskell                          | SQL           |--- +================+==================================+===============+--- | __Persistent__ | @'Database.Persist.!=.' Nothing@ | @IS NOT NULL@ |--- +----------------+----------------------------------+---------------+--- | __Esqueleto__  | @'!=.' Nothing@                  | @!= NULL@     |--- +----------------+----------------------------------+---------------+------ In SQL, @= NULL@ and @!= NULL@ return NULL instead of true or false. For this reason, you very likely do not want to use @'!=.' Nothing@ in Esqueleto.--- You may find these @hlint@ rules helpful to enforce this:------ > - error: {lhs: v ==. nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}--- > - error: {lhs: v ==. val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}--- > - error: {lhs: v !=. nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}--- > - error: {lhs: v !=. val Nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}----isNothing :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool)-isNothing v =-    case v of-      ERaw p f             -> isNullExpr $ first (parensM p) . f-      EAliasedValue i _    -> isNullExpr $ aliasedValueIdentToRawSql i-      EValueReference i i' -> isNullExpr $ valueReferenceToRawSql i i'-      ECompositeKey f      -> ERaw Parens $ flip (,) [] . (intersperseB " AND " . map (<> " IS NULL")) . f-  where-    isNullExpr :: (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value Bool)-    isNullExpr g = ERaw Parens $ first ((<> " IS NULL")) . g---- | Analogous to 'Just', promotes a value of type @typ@ into--- one of type @Maybe typ@.  It should hold that @'val' . Just--- === just . 'val'@.-just :: SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ))-just (ERaw p f)             = ERaw p f-just (ECompositeKey f)      = ECompositeKey f-just (EAliasedValue i v)    = EAliasedValue i (just v)-just (EValueReference i i') = EValueReference i i'---- | @NULL@ value.-nothing :: SqlExpr (Value (Maybe typ))-nothing = unsafeSqlValue "NULL"---- | Join nested 'Maybe's in a 'Value' into one. This is useful when--- calling aggregate functions on nullable fields.-joinV :: SqlExpr (Value (Maybe (Maybe typ))) -> SqlExpr (Value (Maybe typ))-joinV (ERaw p f)             = ERaw p f-joinV (ECompositeKey f)      = ECompositeKey f-joinV (EAliasedValue i v)    = EAliasedValue i (joinV v)-joinV (EValueReference i i') = EValueReference i i'---countHelper :: Num a => TLB.Builder -> TLB.Builder -> SqlExpr (Value typ) -> SqlExpr (Value a)-countHelper open close v =-    case v of-        ERaw _ f -> countRawSql f-        EAliasedValue i _ -> countRawSql $ aliasedValueIdentToRawSql i-        EValueReference i i' -> countRawSql $ valueReferenceToRawSql i i'-        ECompositeKey _ -> countRows-  where-    countRawSql :: (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value a)-    countRawSql x = ERaw Never $ first (\b -> "COUNT" <> open <> parens b <> close) . x---- | @COUNT(*)@ value.-countRows :: Num a => SqlExpr (Value a)-countRows     = unsafeSqlValue "COUNT(*)"---- | @COUNT@.-count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a)-count         = countHelper ""           ""---- | @COUNT(DISTINCT x)@.------ /Since: 2.4.1/-countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a)-countDistinct = countHelper "(DISTINCT " ")"--not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool)-not_ v = ERaw Never (\info -> first ("NOT " <>) $ x info)-  where-    x info =-      case v of-        ERaw p f ->-          let (b, vals) = f info-          in (parensM p b, vals)-        ECompositeKey _      -> throw (CompositeKeyErr NotError)-        EAliasedValue i _    -> aliasedValueIdentToRawSql i info-        EValueReference i i' -> valueReferenceToRawSql i i' info--(==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(==.) = unsafeSqlBinOpComposite " = " " AND "--(>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(>=.) = unsafeSqlBinOp " >= "--(>.)  :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(>.)  = unsafeSqlBinOp " > "--(<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(<=.) = unsafeSqlBinOp " <= "--(<.)  :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(<.)  = unsafeSqlBinOp " < "-(!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)-(!=.) = unsafeSqlBinOpComposite " != " " OR "--(&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)-(&&.) = unsafeSqlBinOp " AND "--(||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)-(||.) = unsafeSqlBinOp " OR "--(+.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)-(+.)  = unsafeSqlBinOp " + "--(-.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)-(-.)  = unsafeSqlBinOp " - "--(/.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)-(/.)  = unsafeSqlBinOp " / "--(*.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)-(*.)  = unsafeSqlBinOp " * "---- | @BETWEEN@.------ @since: 3.1.0-between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool)-a `between` (b, c) = a >=. b &&. a <=. c--random_  :: (PersistField a, Num a) => SqlExpr (Value a)-random_  = unsafeSqlValue "RANDOM()"--round_   :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)-round_   = unsafeSqlFunction "ROUND"--ceiling_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)-ceiling_ = unsafeSqlFunction "CEILING"--floor_   :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)-floor_   = unsafeSqlFunction "FLOOR"--sum_     :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b))-sum_     = unsafeSqlFunction "SUM"-min_     :: (PersistField a) => SqlExpr (Value a) -> SqlExpr (Value (Maybe a))-min_     = unsafeSqlFunction "MIN"-max_     :: (PersistField a) => SqlExpr (Value a) -> SqlExpr (Value (Maybe a))-max_     = unsafeSqlFunction "MAX"-avg_     :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b))-avg_     = unsafeSqlFunction "AVG"---- | Allow a number of one type to be used as one of another--- type via an implicit cast.  An explicit cast is not made,--- this function changes only the types on the Haskell side.------ /Caveat/: Trying to use @castNum@ from @Double@ to @Int@--- will not result in an integer, the original fractional--- number will still be used!  Use 'round_', 'ceiling_' or--- 'floor_' instead.------ /Safety/: This operation is mostly safe due to the 'Num'--- constraint between the types and the fact that RDBMSs--- usually allow numbers of different types to be used--- interchangeably.  However, there may still be issues with--- the query not being accepted by the RDBMS or @persistent@--- not being able to parse it.------ /Since: 2.2.9/-castNum :: (Num a, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)-castNum  = veryUnsafeCoerceSqlExprValue---- | Same as 'castNum', but for nullable values.------ /Since: 2.2.9/-castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b))-castNumM = veryUnsafeCoerceSqlExprValue---- | @COALESCE@ function. Evaluates the arguments in order and--- returns the value of the first non-NULL SqlExpression, or NULL--- (Nothing) otherwise. Some RDBMSs (such as SQLite) require--- at least two arguments; please refer to the appropriate--- documentation.------ /Since: 1.4.3/-coalesce :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a))-coalesce              = unsafeSqlFunctionParens "COALESCE"---- | Like @coalesce@, but takes a non-nullable SqlExpression--- placed at the end of the SqlExpression list, which guarantees--- a non-NULL result.------ /Since: 1.4.3/-coalesceDefault :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value a) -> SqlExpr (Value a)-coalesceDefault exprs = unsafeSqlFunctionParens "COALESCE" . (exprs ++) . return . just---- | @LOWER@ function.-lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)-lower_  = unsafeSqlFunction "LOWER"---- | @UPPER@ function.--- /Since: 3.3.0/-upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)-upper_  = unsafeSqlFunction "UPPER"---- | @TRIM@ function.--- /Since: 3.3.0/-trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)-trim_  = unsafeSqlFunction "TRIM"---- | @RTRIM@ function.--- /Since: 3.3.0/-rtrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)-rtrim_  = unsafeSqlFunction "RTRIM"---- | @LTRIM@ function.--- /Since: 3.3.0/-ltrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)-ltrim_  = unsafeSqlFunction "LTRIM"---- | @LENGTH@ function.--- /Since: 3.3.0/-length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a)-length_ = unsafeSqlFunction "LENGTH"---- | @LEFT@ function.--- /Since: 3.3.0/-left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s)-left_ = unsafeSqlFunction "LEFT"---- | @RIGHT@ function.--- /Since: 3.3.0/-right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s)-right_ = unsafeSqlFunction "RIGHT"---- | @LIKE@ operator.-like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool)-like    = unsafeSqlBinOp    " LIKE "---- | @ILIKE@ operator (case-insensitive @LIKE@).------ Supported by PostgreSQL only.------ /Since: 2.2.3/-ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool)-ilike   = unsafeSqlBinOp    " ILIKE "---- | The string @'%'@.  May be useful while using 'like' and--- concatenation ('concat_' or '++.', depending on your--- database).  Note that you always have to type the parenthesis,--- for example:------ @--- name `'like`` (%) ++. 'val' \"John\" ++. (%)--- @-(%) :: SqlString s => SqlExpr (Value s)-(%)     = unsafeSqlValue    "'%'"---- | The @CONCAT@ function with a variable number of--- parameters.  Supported by MySQL and PostgreSQL.-concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s)-concat_ = unsafeSqlFunction "CONCAT"---- | The @||@ string concatenation operator (named after--- Haskell's '++' in order to avoid naming clash with '||.').--- Supported by SQLite and PostgreSQL.-(++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s)-(++.)   = unsafeSqlBinOp    " || "---- | Cast a string type into 'Text'.  This function--- is very useful if you want to use @newtype@s, or if you want--- to apply functions such as 'like' to strings of different--- types.------ /Safety:/ This is a slightly unsafe function, especially if--- you have defined your own instances of 'SqlString'.  Also,--- since 'Maybe' is an instance of 'SqlString', it's possible--- to turn a nullable value into a non-nullable one.  Avoid--- using this function if possible.-castString :: (SqlString s, SqlString r) => SqlExpr (Value s) -> SqlExpr (Value r)-castString = veryUnsafeCoerceSqlExprValue---- | Execute a subquery @SELECT@ in an SqlExpression.  Returns a--- list of values.-subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a)-subList_select         = EList . sub_select---- | Lift a list of constant value from Haskell-land to the query.-valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ)-valList []   = EEmptyList-valList vals = EList $ ERaw Parens $ const ( uncommas ("?" <$ vals)-                                           , map toPersistValue vals )---- | Same as 'just' but for 'ValueList'.  Most of the time you--- won't need it, though, because you can use 'just' from--- inside 'subList_select' or 'Just' from inside 'valList'.------ /Since: 2.2.12/-justList :: SqlExpr (ValueList typ) -> SqlExpr (ValueList (Maybe typ))-justList EEmptyList = EEmptyList-justList (EList v)  = EList (just v)---- | @IN@ operator. For example if you want to select all @Person@s by a list--- of IDs:------ @--- SELECT *--- FROM Person--- WHERE Person.id IN (?)--- @------ In @esqueleto@, we may write the same query above as:------ @--- select $--- 'from' $ \\person -> do--- 'where_' $ person '^.' PersonId `'in_`` 'valList' personIds--- return person--- @------ Where @personIds@ is of type @[Key Person]@.-in_ :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool)-v `in_`   e = ifNotEmptyList e False $ unsafeSqlBinOp     " IN " v (veryUnsafeCoerceSqlExprValueList e)---- | @NOT IN@ operator.-notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool)-v `notIn` e = ifNotEmptyList e True  $ unsafeSqlBinOp " NOT IN " v (veryUnsafeCoerceSqlExprValueList e)---- | @EXISTS@ operator.  For example:------ @--- select $--- 'from' $ \\person -> do--- 'where_' $ 'exists' $---          'from' $ \\post -> do---          'where_' (post '^.' BlogPostAuthorId '==.' person '^.' PersonId)--- return person--- @-exists :: SqlQuery () -> SqlExpr (Value Bool)-exists    = unsafeSqlFunction     "EXISTS " . existsHelper---- | @NOT EXISTS@ operator.-notExists :: SqlQuery () -> SqlExpr (Value Bool)-notExists = unsafeSqlFunction "NOT EXISTS " . existsHelper---- | @SET@ clause used on @UPDATE@s.  Note that while it's not--- a type error to use this function on a @SELECT@, it will--- most certainly result in a runtime error.-set :: PersistEntity val => SqlExpr (Entity val) -> [SqlExpr (Update val)] -> SqlQuery ()-set ent upds = Q $ W.tell mempty { sdSetClause = map apply upds }-  where-    apply (ESet f) = SetClause (f ent)--(=.)  :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> SqlExpr (Update val)-field  =. expr = setAux field (const expr)--(+=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)-field +=. expr = setAux field (\ent -> ent ^. field +. expr)--(-=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)-field -=. expr = setAux field (\ent -> ent ^. field -. expr)--(*=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)-field *=. expr = setAux field (\ent -> ent ^. field *. expr)--(/=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)-field /=. expr = setAux field (\ent -> ent ^. field /. expr)---- | Apply a 'PersistField' constructor to @SqlExpr Value@ arguments.-(<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b)-(<#) _ (ERaw _ f)        = EInsert Proxy f-(<#) _ (ECompositeKey _) = throw (CompositeKeyErr ToInsertionError)-(<#) _ (EAliasedValue i _) = EInsert Proxy $ aliasedValueIdentToRawSql i-(<#) _ (EValueReference i i') = EInsert Proxy $ valueReferenceToRawSql i i'----- | Apply extra @SqlExpr Value@ arguments to a 'PersistField' constructor-(<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b)-(EInsert _ f) <&> v = EInsert Proxy $ \x ->-  let (fb, fv) = f x-      (gb, gv) = g x-  in (fb <> ", " <> gb, fv ++ gv)- where-  g =-    case v of-      ERaw _ f' -> f'-      EAliasedValue i _ -> aliasedValueIdentToRawSql i-      EValueReference i i' -> valueReferenceToRawSql i i'-      ECompositeKey _ -> throw (CompositeKeyErr CombineInsertionError)---- | @CASE@ statement.  For example:------ @--- select $--- return $--- 'case_'---    [ 'when_'---        ('exists' $---        'from' $ \\p -> do---        'where_' (p '^.' PersonName '==.' 'val' \"Mike\"))---      'then_'---        ('sub_select' $---        'from' $ \\v -> do---        let sub =---                'from' $ \\c -> do---                'where_' (c '^.' PersonName '==.' 'val' \"Mike\")---                return (c '^.' PersonFavNum)---        'where_' (v '^.' PersonFavNum >. 'sub_select' sub)---        return $ 'count' (v '^.' PersonName) +. 'val' (1 :: Int)) ]---    ('else_' $ 'val' (-1))--- @------ This query is a bit complicated, but basically it checks if a person--- named @\"Mike\"@ exists, and if that person does, run the subquery to find--- out how many people have a ranking (by Fav Num) higher than @\"Mike\"@.------ __NOTE:__ There are a few things to be aware about this statement.------    * This only implements the full CASE statement, it does not---      implement the \"simple\" CASE statement.---------    * At least one 'when_' and 'then_' is mandatory otherwise it will---      emit an error.---------    * The 'else_' is also mandatory, unlike the SQL statement in which---      if the @ELSE@ is omitted it will return a @NULL@. You can---      reproduce this via 'nothing'.------ /Since: 2.1.2/-case_ :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a)-case_ = unsafeSqlCase---- | Convert an entity's key into another entity's.------ This function is to be used when you change an entity's @Id@ to be--- that of another entity. For example:------ @--- Bar---   barNum Int--- Foo---   bar BarId---   fooNum Int---   Primary bar--- @------ In this example, Bar is said to be the BaseEnt(ity), and Foo the child.--- To model this in Esqueleto, declare:------ @--- instance ToBaseId Foo where---   type BaseEnt Foo = Bar---   toBaseIdWitness barId = FooKey barId--- @------ Now you're able to write queries such as:------ @--- 'select' $--- 'from' $ \(bar `'InnerJoin`` foo) -> do--- 'on' ('toBaseId' (foo '^.' FooId) '==.' bar '^.' BarId)--- return (bar, foo)--- @------ Note: this function may be unsafe to use in conditions not like the--- one of the example above.------ /Since: 2.4.3/-toBaseId :: ToBaseId ent => SqlExpr (Value (Key ent)) -> SqlExpr (Value (Key (BaseEnt ent)))-toBaseId = veryUnsafeCoerceSqlExprValue--{-# DEPRECATED random_ "Since 2.6.0: `random_` is not uniform across all databases! Please use a specific one such as 'Database.Esqueleto.PostgreSQL.random_', 'Database.Esqueleto.MySQL.random_', or 'Database.Esqueleto.SQLite.random_'" #-}--{-# DEPRECATED rand "Since 2.6.0: `rand` ordering function is not uniform across all databases! To avoid accidental partiality it will be removed in the next major version." #-}---- Fixity declarations-infixl 9 ^.-infixl 7 *., /.-infixl 6 +., -.-infixr 5 ++.-infix  4 ==., >=., >., <=., <., !=.-infixr 3 &&., =., +=., -=., *=., /=.-infixr 2 ||., `like`, `ilike`-infixl 2 `InnerJoin`, `CrossJoin`, `LeftOuterJoin`, `RightOuterJoin`, `FullOuterJoin`---- | Syntax sugar for 'case_'.------ /Since: 2.1.2/-when_ :: expr (Value Bool) -> () -> expr a -> (expr (Value Bool), expr a)-when_ cond _ expr = (cond, expr)---- | Syntax sugar for 'case_'.------ /Since: 2.1.2/-then_ :: ()-then_ = ()---- | Syntax sugar for 'case_'.------ /Since: 2.1.2/-else_ :: expr a -> expr a-else_ = id----- | A single value (as opposed to a whole entity).  You may use--- @('^.')@ or @('?.')@ to get a 'Value' from an 'Entity'.-newtype Value a = Value { unValue :: a } deriving (Eq, Ord, Show, Typeable)----- | /Since: 1.4.4/-instance Functor Value where-  fmap f (Value a) = Value (f a)--instance Applicative Value where-  (<*>) (Value f) (Value a) = Value (f a)-  pure = Value--instance Monad Value where-  (>>=) x f = valueJoin $ fmap f x-    where valueJoin (Value v) = v---- | A list of single values.  There's a limited set of functions--- able to work with this data type (such as 'subList_select',--- 'valList', 'in_' and 'exists').-newtype ValueList a = ValueList a deriving (Eq, Ord, Show, Typeable)----- | A wrapper type for for any @expr (Value a)@ for all a.-data SomeValue where-  SomeValue :: SqlExpr (Value a) -> SomeValue---- | A class of things that can be converted into a list of SomeValue. It has--- instances for tuples and is the reason why 'groupBy' can take tuples, like--- @'groupBy' (foo '^.' FooId, foo '^.' FooName, foo '^.' FooType)@.-class ToSomeValues a where-  toSomeValues :: a -> [SomeValue]--instance ( ToSomeValues a-         , ToSomeValues b-         ) => ToSomeValues (a, b) where-  toSomeValues (a,b) = toSomeValues a ++ toSomeValues b--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         ) => ToSomeValues (a, b, c) where-  toSomeValues (a,b,c) = toSomeValues a ++ toSomeValues b ++ toSomeValues c--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         , ToSomeValues d-         ) => ToSomeValues (a, b, c, d) where-  toSomeValues (a,b,c,d) = toSomeValues a ++ toSomeValues b ++ toSomeValues c ++-    toSomeValues d--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         , ToSomeValues d-         , ToSomeValues e-         ) => ToSomeValues (a, b, c, d, e) where-  toSomeValues (a,b,c,d,e) = toSomeValues a ++ toSomeValues b ++-    toSomeValues c ++ toSomeValues d ++ toSomeValues e--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         , ToSomeValues d-         , ToSomeValues e-         , ToSomeValues f-         ) => ToSomeValues (a, b, c, d, e, f) where-  toSomeValues (a,b,c,d,e,f) = toSomeValues a ++ toSomeValues b ++-    toSomeValues c ++ toSomeValues d ++ toSomeValues e ++ toSomeValues f--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         , ToSomeValues d-         , ToSomeValues e-         , ToSomeValues f-         , ToSomeValues g-         ) => ToSomeValues (a, b, c, d, e, f, g) where-  toSomeValues (a,b,c,d,e,f,g) = toSomeValues a ++ toSomeValues b ++-    toSomeValues c ++ toSomeValues d ++ toSomeValues e ++ toSomeValues f ++-    toSomeValues g--instance ( ToSomeValues a-         , ToSomeValues b-         , ToSomeValues c-         , ToSomeValues d-         , ToSomeValues e-         , ToSomeValues f-         , ToSomeValues g-         , ToSomeValues h-         ) => ToSomeValues (a, b, c, d, e, f, g, h) where-  toSomeValues (a,b,c,d,e,f,g,h) = toSomeValues a ++ toSomeValues b ++-    toSomeValues c ++ toSomeValues d ++ toSomeValues e ++ toSomeValues f ++-    toSomeValues g ++ toSomeValues h--type family KnowResult a where-  KnowResult (i -> o) = KnowResult o-  KnowResult a = a---- | A class for constructors or function which result type is known.------ @since 3.1.3-class FinalResult a where-  finalR :: a -> KnowResult a--instance FinalResult (Unique val) where-  finalR = id--instance (FinalResult b) => FinalResult (a -> b) where-  finalR f = finalR (f undefined)---- | Convert a constructor for a 'Unique' key on a record to the 'UniqueDef' that defines it. You--- can supply just the constructor itself, or a value of the type - the library is capable of figuring--- it out from there.------ @since 3.1.3-toUniqueDef :: forall a val. (KnowResult a ~ (Unique val), PersistEntity val,FinalResult a) =>-  a -> UniqueDef-toUniqueDef uniqueConstructor = uniqueDef-  where-    proxy :: Proxy val-    proxy = Proxy-    unique :: Unique val-    unique = finalR uniqueConstructor-    -- there must be a better way to get the constrain name from a unique, make this not a list search-    filterF = (==) (persistUniqueToFieldNames unique) . uniqueFields-    uniqueDef = head . filter filterF . entityUniques . entityDef $ proxy---- | Render updates to be use in a SET clause for a given sql backend.------ @since 3.1.3-renderUpdates :: (BackendCompatible SqlBackend backend) =>-    backend-    -> [SqlExpr (Update val)]-    -> (TLB.Builder, [PersistValue])-renderUpdates conn = uncommas' . concatMap renderUpdate-    where-      mk :: SqlExpr (Value ()) -> [(TLB.Builder, [PersistValue])]-      mk (ERaw _ f)             = [f info]-      mk (ECompositeKey _)      = throw (CompositeKeyErr MakeSetError) -- FIXME-      mk (EAliasedValue i _)    = [aliasedValueIdentToRawSql i info]-      mk (EValueReference i i') = [valueReferenceToRawSql i i' info]--      renderUpdate :: SqlExpr (Update val) -> [(TLB.Builder, [PersistValue])]-      renderUpdate (ESet f) = mk (f undefined) -- second parameter of f is always unused-      info = (projectBackend conn, initialIdentState)---- | Data type that represents an @INNER JOIN@ (see 'LeftOuterJoin' for an example).-data InnerJoin a b = a `InnerJoin` b---- | Data type that represents a @CROSS JOIN@ (see 'LeftOuterJoin' for an example).-data CrossJoin a b = a `CrossJoin` b---- | Data type that represents a @LEFT OUTER JOIN@. For example,------ @--- select $--- 'from' $ \\(person `'LeftOuterJoin`` pet) ->---   ...--- @------ is translated into------ @--- SELECT ...--- FROM Person LEFT OUTER JOIN Pet--- ...--- @------ See also: 'from'.-data LeftOuterJoin a b = a `LeftOuterJoin` b---- | Data type that represents a @RIGHT OUTER JOIN@ (see 'LeftOuterJoin' for an example).-data RightOuterJoin a b = a `RightOuterJoin` b---- | Data type that represents a @FULL OUTER JOIN@ (see 'LeftOuterJoin' for an example).-data FullOuterJoin a b = a `FullOuterJoin` b----- | (Internal) A kind of @JOIN@.-data JoinKind =-    InnerJoinKind      -- ^ @INNER JOIN@-  | CrossJoinKind      -- ^ @CROSS JOIN@-  | LeftOuterJoinKind  -- ^ @LEFT OUTER JOIN@-  | RightOuterJoinKind -- ^ @RIGHT OUTER JOIN@-  | FullOuterJoinKind  -- ^ @FULL OUTER JOIN@-    deriving (Eq, Show)----- | (Internal) Functions that operate on types (that should be)--- of kind 'JoinKind'.-class IsJoinKind join where-  -- | (Internal) @smartJoin a b@ is a @JOIN@ of the correct kind.-  smartJoin :: a -> b -> join a b-  -- | (Internal) Reify a @JoinKind@ from a @JOIN@.  This-  -- function is non-strict.-  reifyJoinKind :: join a b -> JoinKind--instance IsJoinKind InnerJoin where-  smartJoin a b = a `InnerJoin` b-  reifyJoinKind _ = InnerJoinKind-instance IsJoinKind CrossJoin where-  smartJoin a b = a `CrossJoin` b-  reifyJoinKind _ = CrossJoinKind-instance IsJoinKind LeftOuterJoin where-  smartJoin a b = a `LeftOuterJoin` b-  reifyJoinKind _ = LeftOuterJoinKind-instance IsJoinKind RightOuterJoin where-  smartJoin a b = a `RightOuterJoin` b-  reifyJoinKind _ = RightOuterJoinKind-instance IsJoinKind FullOuterJoin where-  smartJoin a b = a `FullOuterJoin` b-  reifyJoinKind _ = FullOuterJoinKind----- | Exception thrown whenever 'on' is used to create an @ON@--- clause but no matching @JOIN@ is found.-data OnClauseWithoutMatchingJoinException =-  OnClauseWithoutMatchingJoinException String-  deriving (Eq, Ord, Show, Typeable)-instance Exception OnClauseWithoutMatchingJoinException where---- | (Internal) Phantom type used to process 'from' (see 'fromStart').-data PreprocessedFrom a------- | Phantom type used by 'orderBy', 'asc' and 'desc'.-data OrderBy----- | Phantom type used by 'distinctOn' and 'don'.-data DistinctOn----- | Phantom type for a @SET@ operation on an entity of the given--- type (see 'set' and '(=.)').-data Update typ----- | Phantom type used by 'insertSelect'.-data Insertion a----- | Different kinds of locking clauses supported by 'locking'.------ Note that each RDBMS has different locking support.  The--- constructors of this datatype specify only the /syntax/ of the--- locking mechanism, not its /semantics/.  For example, even--- though both MySQL and PostgreSQL support 'ForUpdate', there--- are no guarantees that they will behave the same.------ /Since: 2.2.7/-data LockingKind =-    ForUpdate-    -- ^ @FOR UPDATE@ syntax.  Supported by MySQL, Oracle and-    -- PostgreSQL.-    ---    -- /Since: 2.2.7/-  | ForUpdateSkipLocked-    -- ^ @FOR UPDATE SKIP LOCKED@ syntax.  Supported by MySQL, Oracle and-    -- PostgreSQL.-    ---    -- /Since: 2.2.7/-  | ForShare-    -- ^ @FOR SHARE@ syntax.  Supported by PostgreSQL.-    ---    -- /Since: 2.2.7/-  | LockInShareMode-    -- ^ @LOCK IN SHARE MODE@ syntax.  Supported by MySQL.-    ---    -- /Since: 2.2.7/----- | Phantom class of data types that are treated as strings by the--- RDBMS.  It has no methods because it's only used to avoid type--- errors such as trying to concatenate integers.------ If you have a custom data type or @newtype@, feel free to make--- it an instance of this class.------ /Since: 2.4.0/-class PersistField a => SqlString a where---- | /Since: 2.3.0/-instance (a ~ Char) => SqlString [a] where---- | /Since: 2.3.0/-instance SqlString T.Text where---- | /Since: 2.3.0/-instance SqlString TL.Text where---- | /Since: 2.3.0/-instance SqlString B.ByteString where---- | /Since: 2.3.0/-instance SqlString Html where---- | /Since: 2.4.0/-instance SqlString a => SqlString (Maybe a) where---- | Class that enables one to use 'toBaseId' to convert an entity's--- key on a query into another (cf. 'toBaseId').-class ToBaseId ent where-  -- | e.g. @type BaseEnt MyBase = MyChild@-  type BaseEnt ent :: *-  -- | Convert from the key of the BaseEnt(ity) to the key of the child entity.-  -- This function is not actually called, but that it typechecks proves this operation is safe.-  toBaseIdWitness :: Key (BaseEnt ent) -> Key ent----- | @FROM@ clause: bring entities into scope.------ Note that this function will be replaced by the one in--- "Database.Esqueleto.Experimental" in version 4.0.0.0 of the library. The--- @Experimental@ module has a dramatically improved means for introducing--- tables and entities that provides more power and less potential for runtime--- errors.------ This function internally uses two type classes in order to--- provide some flexibility of how you may call it.  Internally--- we refer to these type classes as the two different magics.------ The innermost magic allows you to use @from@ with the--- following types:------  * @expr (Entity val)@, which brings a single entity into---  scope.------  * @expr (Maybe (Entity val))@, which brings a single entity---  that may be @NULL@ into scope.  Used for @OUTER JOIN@s.------  * A @JOIN@ of any other two types allowed by the innermost---  magic, where a @JOIN@ may be an 'InnerJoin', a 'CrossJoin', a---  'LeftOuterJoin', a 'RightOuterJoin', or a 'FullOuterJoin'.---  The @JOINs@ have left fixity.------ The outermost magic allows you to use @from@ on any tuples of--- types supported by innermost magic (and also tuples of tuples,--- and so on), up to 8-tuples.------ Note that using @from@ for the same entity twice does work and--- corresponds to a self-join.  You don't even need to use two--- different calls to @from@, you may use a @JOIN@ or a tuple.------ The following are valid examples of uses of @from@ (the types--- of the arguments of the lambda are inside square brackets):------ @--- 'from' $ \\person -> ...--- 'from' $ \\(person, blogPost) -> ...--- 'from' $ \\(p `'LeftOuterJoin`` mb) -> ...--- 'from' $ \\(p1 `'InnerJoin`` f `'InnerJoin`` p2) -> ...--- 'from' $ \\((p1 `'InnerJoin`` f) `'InnerJoin`` p2) -> ...--- @------ The types of the arguments to the lambdas above are,--- respectively:------ @--- person---   :: ( Esqueleto query expr backend---      , PersistEntity Person---      , PersistEntityBackend Person ~ backend---      ) => expr (Entity Person)--- (person, blogPost)---   :: (...) => (expr (Entity Person), expr (Entity BlogPost))--- (p `'LeftOuterJoin`` mb)---   :: (...) => InnerJoin (expr (Entity Person)) (expr (Maybe (Entity BlogPost)))--- (p1 `'InnerJoin`` f `'InnerJoin`` p2)---   :: (...) => InnerJoin---                 (InnerJoin (expr (Entity Person))---                            (expr (Entity Follow)))---                 (expr (Entity Person))--- (p1 `'InnerJoin`` (f `'InnerJoin`` p2)) ::---   :: (...) => InnerJoin---                 (expr (Entity Person))---                 (InnerJoin (expr (Entity Follow))---                            (expr (Entity Person)))--- @------ Note that some backends may not support all kinds of @JOIN@s.-from :: From a => (a -> SqlQuery b) -> SqlQuery b-from = (from_ >>=)----- | (Internal) Class that implements the tuple 'from' magic (see--- 'fromStart').-class From a where-  from_ :: SqlQuery a--instance ( FromPreprocess (SqlExpr (Entity val))-         ) => From (SqlExpr (Entity val)) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (SqlExpr (Maybe (Entity val)))-         ) => From (SqlExpr (Maybe (Entity val))) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (InnerJoin a b)-         ) => From (InnerJoin a b) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (CrossJoin a b)-         ) => From (CrossJoin a b) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (LeftOuterJoin a b)-         ) => From (LeftOuterJoin a b) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (RightOuterJoin a b)-         ) => From (RightOuterJoin a b) where-  from_ = fromPreprocess >>= fromFinish--instance ( FromPreprocess (FullOuterJoin a b)-         ) => From (FullOuterJoin a b) where-  from_ = fromPreprocess >>= fromFinish--instance ( From a-         , From b-         ) => From (a, b) where-  from_ = (,) <$> from_ <*> from_--instance ( From a-         , From b-         , From c-         ) => From (a, b, c) where-  from_ = (,,) <$> from_ <*> from_ <*> from_--instance ( From a-         , From b-         , From c-         , From d-         ) => From (a, b, c, d) where-  from_ = (,,,) <$> from_ <*> from_ <*> from_ <*> from_--instance ( From a-         , From b-         , From c-         , From d-         , From e-         ) => From (a, b, c, d, e) where-  from_ = (,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_--instance ( From a-         , From b-         , From c-         , From d-         , From e-         , From f-         ) => From (a, b, c, d, e, f) where-  from_ = (,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_--instance ( From a-         , From b-         , From c-         , From d-         , From e-         , From f-         , From g-         ) => From (a, b, c, d, e, f, g) where-  from_ = (,,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_--instance ( From a-         , From b-         , From c-         , From d-         , From e-         , From f-         , From g-         , From h-         ) => From (a, b, c, d, e, f, g, h) where-  from_ = (,,,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_------ | (Internal) Class that implements the @JOIN@ 'from' magic--- (see 'fromStart').-class FromPreprocess a where-  fromPreprocess :: SqlQuery (SqlExpr (PreprocessedFrom a))--instance ( PersistEntity val-         , BackendCompatible SqlBackend (PersistEntityBackend val)-         ) => FromPreprocess (SqlExpr (Entity val)) where-  fromPreprocess = fromStart--instance ( PersistEntity val-         , BackendCompatible SqlBackend (PersistEntityBackend val)-         ) => FromPreprocess (SqlExpr (Maybe (Entity val))) where-  fromPreprocess = fromStartMaybe--instance ( FromPreprocess a-         , FromPreprocess b-         , IsJoinKind join-         ) => FromPreprocess (join a b) where-  fromPreprocess = do-    a <- fromPreprocess-    b <- fromPreprocess-    fromJoin a b---- | Exception data type for @esqueleto@ internal errors-data EsqueletoError =-    CompositeKeyErr CompositeKeyError-  | AliasedValueErr UnexpectedValueError-  | UnexpectedCaseErr UnexpectedCaseError-  | SqlBinOpCompositeErr SqlBinOpCompositeError-  deriving (Show)--instance Exception EsqueletoError--data UnexpectedValueError =-    NotError-  | ToInsertionError-  | CombineInsertionError-  | FoldHelpError-  | SqlCaseError-  | SqlCastAsError-  | SqlFunctionError-  | MakeOnClauseError-  | MakeExcError-  | MakeSetError-  | MakeWhereError-  | MakeHavingError-  | FilterWhereAggError-  | FilterWhereClauseError-  deriving (Show)--type CompositeKeyError = UnexpectedValueError--data UnexpectedCaseError =-    EmptySqlExprValueList-  | MakeFromError-  | UnsupportedSqlInsertIntoType-  | InsertionFinalError-  | NewIdentForError-  | UnsafeSqlCaseError-  | OperationNotSupported-  | NotImplemented-  deriving (Show)--data SqlBinOpCompositeError =-    MismatchingLengthsError-  | NullPlaceholdersError-  | DeconstructionError-  deriving (Show)------ | SQL backend for @esqueleto@ using 'SqlPersistT'.-newtype SqlQuery a =-  Q { unQ :: W.WriterT SideData (S.State IdentState) a }--instance Functor SqlQuery where-  fmap f = Q . fmap f . unQ--instance Monad SqlQuery where-  return  = Q . return-  m >>= f = Q (unQ m >>= unQ . f)--instance Applicative SqlQuery where-  pure  = return-  (<*>) = ap----- | Constraint synonym for @persistent@ entities whose backend--- is 'SqlPersistT'.-type SqlEntity ent = (PersistEntity ent, PersistEntityBackend ent ~ SqlBackend)------------------------------------------------------------------------------ | Side data written by 'SqlQuery'.-data SideData = SideData { sdDistinctClause :: !DistinctClause-                         , sdFromClause     :: ![FromClause]-                         , sdSetClause      :: ![SetClause]-                         , sdWhereClause    :: !WhereClause-                         , sdGroupByClause  :: !GroupByClause-                         , sdHavingClause   :: !HavingClause-                         , sdOrderByClause  :: ![OrderByClause]-                         , sdLimitClause    :: !LimitClause-                         , sdLockingClause  :: !LockingClause-                         , sdCteClause      :: ![CommonTableExpressionClause]-                         }--instance Semigroup SideData where-  SideData d f s w g h o l k c <> SideData d' f' s' w' g' h' o' l' k' c' =-    SideData (d <> d') (f <> f') (s <> s') (w <> w') (g <> g') (h <> h') (o <> o') (l <> l') (k <> k') (c <> c')--instance Monoid SideData where-  mempty = SideData mempty mempty mempty mempty mempty mempty mempty mempty mempty mempty-  mappend = (<>)---- | The @DISTINCT@ "clause".-data DistinctClause =-    DistinctAll                     -- ^ The default, everything.-  | DistinctStandard                -- ^ Only @DISTINCT@, SQL standard.-  | DistinctOn [SqlExpr DistinctOn] -- ^ @DISTINCT ON@, PostgreSQL extension.--instance Semigroup DistinctClause where-  DistinctOn a     <> DistinctOn b = DistinctOn (a <> b)-  DistinctOn a     <> _            = DistinctOn a-  DistinctStandard <> _            = DistinctStandard-  DistinctAll      <> b            = b--instance Monoid DistinctClause where-  mempty = DistinctAll-  mappend = (<>)---- | A part of a @FROM@ clause.-data FromClause =-    FromStart Ident EntityDef-  | FromJoin FromClause JoinKind FromClause (Maybe (SqlExpr (Value Bool)))-  | OnClause (SqlExpr (Value Bool))-  | FromQuery Ident (IdentInfo -> (TLB.Builder, [PersistValue])) SubQueryType-  | FromIdent Ident--data CommonTableExpressionKind-  = RecursiveCommonTableExpression-  | NormalCommonTableExpression-  deriving Eq--data CommonTableExpressionClause =-  CommonTableExpressionClause CommonTableExpressionKind Ident (IdentInfo -> (TLB.Builder, [PersistValue]))--data SubQueryType-  = NormalSubQuery-  | LateralSubQuery-  deriving Show--collectIdents :: FromClause -> Set Ident-collectIdents fc = case fc of-  FromStart i _ -> Set.singleton i-  FromJoin lhs _ rhs _ -> collectIdents lhs <> collectIdents rhs-  OnClause _ -> mempty-  FromQuery _ _ _ -> mempty-  FromIdent _ -> mempty--instance Show FromClause where-  show fc = case fc of-    FromStart i _ ->-      "(FromStart " <> show i <> ")"-    FromJoin lhs jk rhs mexpr ->-      mconcat-        [ "(FromJoin "-        , show lhs-        , " "-        , show jk-        , " "-        , case mexpr of-            Nothing -> "(no on clause)"-            Just expr -> "(" <> render' expr <> ")"-        , " "-        , show rhs-        , ")"-      ]-    OnClause expr ->-      "(OnClause " <> render' expr <> ")"-    FromQuery ident _ subQueryType ->-      "(FromQuery " <> show ident <> " " <> show subQueryType <> ")"-    FromIdent ident ->-      "(FromIdent " <> show ident <> ")"--    where-      dummy = SqlBackend-        { connEscapeName = \(DBName x) -> x-        }-      render' = T.unpack . renderExpr dummy----- | A part of a @SET@ clause.-newtype SetClause = SetClause (SqlExpr (Value ()))----- | Collect 'OnClause's on 'FromJoin's.  Returns the first--- unmatched 'OnClause's data on error.  Returns a list without--- 'OnClauses' on success.-collectOnClauses-  :: SqlBackend-  -> [FromClause]-  -> Either (SqlExpr (Value Bool)) [FromClause]-collectOnClauses sqlBackend = go Set.empty []- --  . (\fc -> Debug.trace ("From Clauses: " <> show fc) fc)-  where-    go is []  (f@(FromStart i _) : fs) =-      fmap (f:) (go (Set.insert i is) [] fs) -- fast path-    go idents acc (OnClause expr : fs) = do-      (idents', a) <- findMatching idents acc expr-      go idents' a fs-    go idents acc (f:fs) =-      go idents (f:acc) fs-    go _ acc [] =-      return $ reverse acc--    findMatching-      :: Set Ident-      -> [FromClause]-      -> SqlExpr (Value Bool)-      -> Either (SqlExpr (Value Bool)) (Set Ident, [FromClause])-    findMatching idents fromClauses expr =-      -- Debug.trace ("From Clause: " <> show fromClauses) $-      case fromClauses of-        f : acc ->-          let-            idents' =-              idents-              <> Set.fromList (Maybe.catMaybes [findLeftmostIdent f, findRightmostIdent f])-          in-            case tryMatch idents' expr f of-              Just (idents'', f') ->-                return (idents'', f' : acc)-              Nothing ->-                fmap (f:) <$> findMatching idents' acc expr-        [] ->-          Left expr--    findRightmostIdent (FromStart i _) = Just i-    findRightmostIdent (FromJoin _ _ r _) = findRightmostIdent r-    findRightmostIdent (OnClause {}) = Nothing-    findRightmostIdent (FromQuery _ _ _) = Nothing-    findRightmostIdent (FromIdent _) = Nothing--    findLeftmostIdent (FromStart i _) = Just i-    findLeftmostIdent (FromJoin l _ _ _) = findLeftmostIdent l-    findLeftmostIdent (OnClause {}) = Nothing-    findLeftmostIdent (FromQuery _ _ _) = Nothing-    findLeftmostIdent (FromIdent _) = Nothing--    tryMatch-      :: Set Ident-      -> SqlExpr (Value Bool)-      -> FromClause-      -> Maybe (Set Ident, FromClause)-    tryMatch idents expr fromClause =-      case fromClause of-        FromJoin l k r onClause ->-          matchTable <|> matchR <|> matchC <|> matchL <|> matchPartial -- right to left-            where-              matchR = fmap (\r' -> FromJoin l k r' onClause)-                <$> tryMatch idents expr r-              matchL = fmap (\l' -> FromJoin l' k r onClause)-                <$> tryMatch idents expr l--              matchPartial = do-                --Debug.traceM $ "matchPartial"-                --Debug.traceM $ "matchPartial: identsInOnClause: " <> show identsInOnClause-                i1 <- findLeftmostIdent l-                i2 <- findLeftmostIdent r-                let leftIdents = collectIdents l-                -- Debug.traceM $ "matchPartial: i1: " <> show i1-                -- Debug.traceM $ "matchPartial: i2: " <> show i2-                -- Debug.traceM $ "matchPartial: idents: " <> show idents-                guard $-                  Set.isSubsetOf-                    identsInOnClause-                    (Set.fromList [i1, i2] <> leftIdents)-                guard $ k /= CrossJoinKind-                guard $ Maybe.isNothing onClause-                pure (idents, FromJoin l k r (Just expr))--              matchC =-                case onClause of-                  Nothing-                    | "?" `T.isInfixOf` renderedExpr ->-                        return (idents, FromJoin l k r (Just expr))-                    | Set.null identsInOnClause ->-                        return (idents, FromJoin l k r (Just expr))-                    | otherwise ->-                        Nothing-                  Just _ ->-                    Nothing-              matchTable = do-                i1 <- findLeftmostIdent r-                i2 <- findRightmostIdent l-                guard $ Set.fromList [i1, i2] `Set.isSubsetOf` identsInOnClause-                guard $ k /= CrossJoinKind-                guard $ Maybe.isNothing onClause-                pure (Set.fromList [i1, i2] <> idents, FromJoin l k r (Just expr))--        _ ->-          Nothing-      where-        identsInOnClause =-          onExprToTableIdentifiers--        renderedExpr =-          renderExpr sqlBackend expr--        onExprToTableIdentifiers =-          Set.map (I . tableAccessTable)-          . either error id-          . parseOnExpr sqlBackend-          $ renderedExpr---- | A complete @WHERE@ clause.-data WhereClause = Where (SqlExpr (Value Bool))-                 | NoWhere--instance Semigroup WhereClause where-  NoWhere  <> w        = w-  w        <> NoWhere  = w-  Where e1 <> Where e2 = Where (e1 &&. e2)--instance Monoid WhereClause where-  mempty = NoWhere-  mappend = (<>)---- | A @GROUP BY@ clause.-newtype GroupByClause = GroupBy [SomeValue]--instance Semigroup GroupByClause where-  GroupBy fs <> GroupBy fs' = GroupBy (fs <> fs')--instance Monoid GroupByClause where-  mempty = GroupBy []-  mappend = (<>)---- | A @HAVING@ cause.-type HavingClause = WhereClause---- | A @ORDER BY@ clause.-type OrderByClause = SqlExpr OrderBy----- | A @LIMIT@ clause.-data LimitClause = Limit (Maybe Int64) (Maybe Int64)-  deriving Eq--instance Semigroup LimitClause where-  Limit l1 o1 <> Limit l2 o2 =-    Limit (l2 `mplus` l1) (o2 `mplus` o1)-    -- More than one 'limit' or 'offset' is issued, we want to-    -- keep the latest one.  That's why we use mplus with-    -- "reversed" arguments.--instance Monoid LimitClause where-  mempty = Limit mzero mzero-  mappend = (<>)---- | A locking clause.-type LockingClause = Monoid.Last LockingKind------------------------------------------------------------------------------ | Identifier used for table names.-newtype Ident = I T.Text-  deriving (Eq, Ord, Show)----- | List of identifiers already in use and supply of temporary--- identifiers.-newtype IdentState = IdentState { inUse :: HS.HashSet T.Text }--initialIdentState :: IdentState-initialIdentState = IdentState mempty----- | Create a fresh 'Ident'.  If possible, use the given--- 'DBName'.-newIdentFor :: DBName -> SqlQuery Ident-newIdentFor (DBName original) = Q $ lift $ findFree Nothing-  where-    findFree msuffix = do-      let-        withSuffix =-          maybe id (\suffix -> (<> T.pack (show suffix))) msuffix original-      isInUse <- S.gets (HS.member withSuffix . inUse)-      if isInUse-        then findFree (succ <$> (msuffix <|> Just (1 :: Int)))-        else do-          S.modify (\s -> s { inUse = HS.insert withSuffix (inUse s) })-          pure (I withSuffix)---- | Information needed to escape and use identifiers.-type IdentInfo = (SqlBackend, IdentState)----- | Use an identifier.-useIdent :: IdentInfo -> Ident -> TLB.Builder-useIdent info (I ident) = fromDBName info $ DBName ident------- | An expression on the SQL backend.------ There are many comments describing the constructors of this--- data type.  However, Haddock doesn't like GADTs, so you'll have to read them by hitting \"Source\".-data SqlExpr a where-  -- An entity, created by 'from' (cf. 'fromStart').-  EEntity  :: Ident -> SqlExpr (Entity val)-  --                Base     Table-  EAliasedEntity :: Ident -> Ident -> SqlExpr (Entity val)-  --                         Source   Base-  EAliasedEntityReference :: Ident -> Ident -> SqlExpr (Entity val)--  -- Just a tag stating that something is nullable.-  EMaybe   :: SqlExpr a -> SqlExpr (Maybe a)--  -- Raw expression: states whether parenthesis are needed-  -- around this expression, and takes information about the SQL-  -- connection (mainly for escaping names) and returns both an-  -- string ('TLB.Builder') and a list of values to be-  -- interpolated by the SQL backend.-  ERaw     :: NeedParens -> (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value a)---  -- A raw expression with an alias-  EAliasedValue :: Ident -> SqlExpr (Value a) -> SqlExpr (Value a)--  -- A reference to an aliased field in a table or subquery-  EValueReference :: Ident -> (IdentInfo -> Ident) -> SqlExpr (Value a)--  -- A composite key.-  ---  -- Persistent uses the same 'PersistList' constructor for both-  -- fields which are (homogeneous) lists of values and the-  -- (probably heterogeneous) values of a composite primary key.-  ---  -- We need to treat composite keys as fields.  For example, we-  -- have to support using ==., otherwise you wouldn't be able to-  -- join.  OTOH, lists of values should be treated exactly the-  -- same as any other scalar value.-  ---  -- In particular, this is valid for persistent via rawSql for-  -- an F field that is a list:-  ---  --   A.F in ?    -- [PersistList [foo, bar]]-  ---  -- However, this is not for a composite key entity:-  ---  --   A.ID = ?    -- [PersistList [foo, bar]]-  ---  -- The ID field doesn't exist on the DB for a composite key-  -- table, it exists only on the Haskell side.  Those variations-  -- also don't work:-  ---  --   (A.KeyA, A.KeyB) = ?    -- [PersistList [foo, bar]]-  --   [A.KeyA, A.KeyB] = ?    -- [PersistList [foo, bar]]-  ---  -- We have to generate:-  ---  --   A.KeyA = ? AND A.KeyB = ?      -- [foo, bar]-  ---  -- Note that the PersistList had to be deconstructed into its-  -- components.-  ---  -- In order to disambiguate behaviors, this constructor is used-  -- /only/ to represent a composite field access.  It does not-  -- represent a 'PersistList', not even if the 'PersistList' is-  -- used in the context of a composite key.  That's because it's-  -- impossible, e.g., for 'val' to disambiguate between these-  -- uses.-  ECompositeKey :: (IdentInfo -> [TLB.Builder]) -> SqlExpr (Value a)--  -- 'EList' and 'EEmptyList' are used by list operators.-  EList      :: SqlExpr (Value a) -> SqlExpr (ValueList a)-  EEmptyList :: SqlExpr (ValueList a)--  -- A 'SqlExpr' accepted only by 'orderBy'.-  EOrderBy :: OrderByType -> SqlExpr (Value a) -> SqlExpr OrderBy--  EOrderRandom :: SqlExpr OrderBy--  -- A 'SqlExpr' accepted only by 'distinctOn'.-  EDistinctOn :: SqlExpr (Value a) -> SqlExpr DistinctOn--  -- A 'SqlExpr' accepted only by 'set'.-  ESet :: (SqlExpr (Entity val) -> SqlExpr (Value ())) -> SqlExpr (Update val)--  -- An internal 'SqlExpr' used by the 'from' hack.-  EPreprocessedFrom :: a -> FromClause -> SqlExpr (PreprocessedFrom a)--  -- Used by 'insertSelect'.-  EInsert  :: Proxy a -> (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Insertion a)-  EInsertFinal :: PersistEntity a => SqlExpr (Insertion a) -> SqlExpr InsertFinal---- | Phantom type used to mark a @INSERT INTO@ query.-data InsertFinal--data NeedParens = Parens | Never-   deriving Eq--parensM :: NeedParens -> TLB.Builder -> TLB.Builder-parensM Never  = id-parensM Parens = parens--data OrderByType = ASC | DESC---instance ToSomeValues (SqlExpr (Value a)) where-  toSomeValues a = [SomeValue a]--fieldName :: (PersistEntity val, PersistField typ)-          => IdentInfo -> EntityField val typ -> TLB.Builder-fieldName info = fromDBName info . fieldDB . persistFieldDef---- FIXME: Composite/non-id pKS not supported on set-setAux :: (PersistEntity val, PersistField typ)-       => EntityField val typ-       -> (SqlExpr (Entity val) -> SqlExpr (Value typ))-       -> SqlExpr (Update val)-setAux field mkVal = ESet $ \ent -> unsafeSqlBinOp " = " name (mkVal ent)-  where name = ERaw Never $ \info -> (fieldName info field, mempty)--sub :: PersistField a => Mode -> SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)-sub mode query = ERaw Parens $ \info -> toRawSql mode info query--fromDBName :: IdentInfo -> DBName -> TLB.Builder-fromDBName (conn, _) = TLB.fromText . connEscapeName conn--existsHelper :: SqlQuery () -> SqlExpr (Value Bool)-existsHelper = sub SELECT . (>> return true)-  where-    true :: SqlExpr (Value Bool)-    true = val True--ifNotEmptyList :: SqlExpr (ValueList a) -> Bool -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)-ifNotEmptyList EEmptyList b _ = val b-ifNotEmptyList (EList _)  _ x = x------------------------------------------------------------------------------- | (Internal) Create a case statement.------ Since: 2.1.1-unsafeSqlCase :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a)-unsafeSqlCase when v = ERaw Never buildCase-  where-    buildCase :: IdentInfo -> (TLB.Builder, [PersistValue])-    buildCase info =-      let (elseText, elseVals) = valueToSql v info-          (whenText, whenVals) = mapWhen when info-      in ( "CASE" <> whenText <> " ELSE " <> elseText <> " END", whenVals <> elseVals)--    mapWhen :: [(SqlExpr (Value Bool), SqlExpr (Value a))] -> IdentInfo -> (TLB.Builder, [PersistValue])-    mapWhen []    _    = throw (UnexpectedCaseErr UnsafeSqlCaseError)-    mapWhen when' info = foldl (foldHelp info) (mempty, mempty) when'--    foldHelp :: IdentInfo -> (TLB.Builder, [PersistValue]) -> (SqlExpr (Value Bool), SqlExpr (Value a)) -> (TLB.Builder, [PersistValue])-    foldHelp _ _ (ECompositeKey _, _) = throw (CompositeKeyErr FoldHelpError)-    foldHelp _ _ (_, ECompositeKey _) = throw (CompositeKeyErr FoldHelpError)-    foldHelp info (b0, vals0) (v1, v2) =-        let (b1, vals1) = valueToSql v1 info-            (b2, vals2) = valueToSql v2 info-        in ( b0 <> " WHEN " <> b1 <> " THEN " <> b2, vals0 <> vals1 <> vals2 )--    valueToSql :: SqlExpr (Value a) -> IdentInfo -> (TLB.Builder, [PersistValue])-    valueToSql (ERaw p f) = (first (parensM p)) . f-    valueToSql (ECompositeKey _) = throw (CompositeKeyErr SqlCaseError)-    valueToSql (EAliasedValue i _) = aliasedValueIdentToRawSql i-    valueToSql (EValueReference i i') = valueReferenceToRawSql i i'---- | (Internal) Create a custom binary operator.  You /should/--- /not/ use this function directly since its type is very--- general, you should always use it with an explicit type--- signature.  For example:------ @--- (==.) :: SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value Bool)--- (==.) = unsafeSqlBinOp " = "--- @------ In the example above, we constraint the arguments to be of the--- same type and constraint the result to be a boolean value.-unsafeSqlBinOp :: TLB.Builder -> SqlExpr (Value a) -> SqlExpr (Value b) -> SqlExpr (Value c)-unsafeSqlBinOp op (ERaw p1 f1) (ERaw p2 f2) = ERaw Parens f-  where-    f info = let (b1, vals1) = f1 info-                 (b2, vals2) = f2 info-             in ( parensM p1 b1 <> op <> parensM p2 b2-                , vals1 <> vals2 )-unsafeSqlBinOp op a b = unsafeSqlBinOp op (construct a) (construct b)-    where construct :: SqlExpr (Value a) -> SqlExpr (Value a)-          construct (ERaw p f)        = ERaw (if p == Never then Parens else Never) $ \info ->-            let (b1, vals) = f info-                build ("?", [PersistList vals']) =-                  (uncommas $ replicate (length vals') "?", vals')-                build expr = expr-             in  build (parensM p b1, vals)-          construct (ECompositeKey f) =-            ERaw Parens $ \info -> (uncommas $ f info, mempty)-          construct (EAliasedValue i _) =-            ERaw Never $ aliasedValueIdentToRawSql i-          construct (EValueReference i i') =-            ERaw Never $ valueReferenceToRawSql i i'-{-# INLINE unsafeSqlBinOp #-}------- | Similar to 'unsafeSqlBinOp', but may also be applied to--- composite keys.  Uses the operator given as the second--- argument whenever applied to composite keys.------ Usage example:------ @--- (==.) :: SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value Bool)--- (==.) = unsafeSqlBinOpComposite " = " " AND "--- @------ Persistent has a hack for implementing composite keys (see--- 'ECompositeKey' doc for more details), so we're forced to use--- a hack here as well.  We deconstruct 'ERaw' values based on--- two rules:------   - If it is a single placeholder, then it's assumed to be---   coming from a 'PersistList' and thus its components are---   separated so that they may be applied to a composite key.------   - If it is not a single placeholder, then it's assumed to be---   a foreign (composite or not) key, so we enforce that it has---   no placeholders and split it on the commas.-unsafeSqlBinOpComposite :: TLB.Builder -> TLB.Builder -> SqlExpr (Value a) -> SqlExpr (Value b) -> SqlExpr (Value c)-unsafeSqlBinOpComposite op sep a b-    | isCompositeKey a || isCompositeKey b = ERaw Parens $ compose (listify a) (listify b)-    | otherwise = unsafeSqlBinOp op a b-  where-    isCompositeKey :: SqlExpr (Value x) -> Bool-    isCompositeKey (ECompositeKey _) = True-    isCompositeKey _ = False--    listify :: SqlExpr (Value x) -> IdentInfo -> ([TLB.Builder], [PersistValue])-    listify (ECompositeKey f)      = flip (,) [] . f-    listify (ERaw _ f)             = deconstruct . f-    listify (EAliasedValue i _)    = deconstruct . (aliasedValueIdentToRawSql i)-    listify (EValueReference i i') = deconstruct . (valueReferenceToRawSql i i')--    deconstruct :: (TLB.Builder, [PersistValue]) -> ([TLB.Builder], [PersistValue])-    deconstruct ("?", [PersistList vals]) = (replicate (length vals) "?", vals)-    deconstruct (b', []) = (TLB.fromLazyText <$> TL.splitOn "," (TLB.toLazyText b'), [])-    deconstruct _ = throw (SqlBinOpCompositeErr DeconstructionError)--    compose f1 f2 info-      | not (null v1 || null v2) = throw (SqlBinOpCompositeErr NullPlaceholdersError)-      | length b1 /= length b2   = throw (SqlBinOpCompositeErr MismatchingLengthsError)-      | otherwise                = (bc, vc)-      where-        (b1, v1) = f1 info-        (b2, v2) = f2 info-        bc = intersperseB sep [x <> op <> y | (x, y) <- zip b1 b2]-        vc = v1 <> v2---- | (Internal) A raw SQL value.  The same warning from--- 'unsafeSqlBinOp' applies to this function as well.-unsafeSqlValue :: TLB.Builder -> SqlExpr (Value a)-unsafeSqlValue v = ERaw Never $ const (v, mempty)-{-# INLINE unsafeSqlValue #-}--valueToFunctionArg :: IdentInfo -> SqlExpr (Value a) -> (TLB.Builder, [PersistValue])-valueToFunctionArg info v =-    case v of-      ERaw _ f             -> f info-      EAliasedValue i _    -> aliasedValueIdentToRawSql i info-      EValueReference i i' -> valueReferenceToRawSql i i' info-      ECompositeKey _      -> throw (CompositeKeyErr SqlFunctionError)---- | (Internal) A raw SQL function.  Once again, the same warning--- from 'unsafeSqlBinOp' applies to this function as well.-unsafeSqlFunction :: UnsafeSqlFunctionArgument a =>-                     TLB.Builder -> a -> SqlExpr (Value b)-unsafeSqlFunction name arg =-  ERaw Never $ \info ->-    let (argsTLB, argsVals) =-          uncommas' $ map (valueToFunctionArg info) $ toArgList arg-    in (name <> parens argsTLB, argsVals)---- | (Internal) An unsafe SQL function to extract a subfield from a compound--- field, e.g. datetime. See 'unsafeSqlBinOp' for warnings.------ Since: 1.3.6.-unsafeSqlExtractSubField :: UnsafeSqlFunctionArgument a =>-                     TLB.Builder -> a -> SqlExpr (Value b)-unsafeSqlExtractSubField subField arg =-  ERaw Never $ \info ->-    let (argsTLB, argsVals) =-          uncommas' $ map (valueToFunctionArg info) $ toArgList arg-    in ("EXTRACT" <> parens (subField <> " FROM " <> argsTLB), argsVals)---- | (Internal) A raw SQL function. Preserves parentheses around arguments.--- See 'unsafeSqlBinOp' for warnings.-unsafeSqlFunctionParens :: UnsafeSqlFunctionArgument a =>-                           TLB.Builder -> a -> SqlExpr (Value b)-unsafeSqlFunctionParens name arg =-  ERaw Never $ \info ->-    let-      valueToFunctionArgParens v =-        case v of-          ERaw p f             -> first (parensM p) (f info)-          EAliasedValue i _    -> aliasedValueIdentToRawSql i info-          EValueReference i i' -> valueReferenceToRawSql i i' info-          ECompositeKey _      -> throw (CompositeKeyErr SqlFunctionError)-      (argsTLB, argsVals) =-          uncommas' $ map valueToFunctionArgParens $ toArgList arg-    in (name <> parens argsTLB, argsVals)---- | (Internal) An explicit SQL type cast using CAST(value as type).--- See 'unsafeSqlBinOp' for warnings.-unsafeSqlCastAs :: T.Text -> SqlExpr (Value a) -> SqlExpr (Value b)-unsafeSqlCastAs t v = ERaw Never ((first (\value -> "CAST" <> parens (value <> " AS " <> TLB.fromText t))) . valueToText)-  where-    valueToText info =-      case v of-        (ERaw p f) ->-          let (b, vals) = f info-          in (parensM p b, vals)-        EAliasedValue i _ -> aliasedValueIdentToRawSql i info-        EValueReference i i' -> valueReferenceToRawSql i i' info-        ECompositeKey _ -> throw (CompositeKeyErr SqlCastAsError)--- | (Internal) This class allows 'unsafeSqlFunction' to work with different--- numbers of arguments; specifically it allows providing arguments to a sql--- function via an n-tuple of @SqlExpr (Value _)@ values, which are not all--- necessarily required to be the same type. There are instances for up to--- 10-tuples, but for sql functions which take more than 10 arguments, you can--- also nest tuples, as e.g. @toArgList ((a,b),(c,d))@ is the same as--- @toArgList (a,b,c,d)@.-class UnsafeSqlFunctionArgument a where-  toArgList :: a -> [SqlExpr (Value ())]---- | Useful for 0-argument functions, like @now@ in Postgresql.------ @since 3.2.1-instance UnsafeSqlFunctionArgument () where-  toArgList _ = []--instance (a ~ Value b) => UnsafeSqlFunctionArgument (SqlExpr a) where-  toArgList = (:[]) . veryUnsafeCoerceSqlExprValue-instance UnsafeSqlFunctionArgument a =>-         UnsafeSqlFunctionArgument [a] where-  toArgList = concatMap toArgList-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         ) => UnsafeSqlFunctionArgument (a, b) where-  toArgList (a, b) = toArgList a ++ toArgList b-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         ) => UnsafeSqlFunctionArgument (a, b, c) where-  toArgList = toArgList . from3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         ) => UnsafeSqlFunctionArgument (a, b, c, d) where-  toArgList = toArgList . from4--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e) where-  toArgList = toArgList . from5--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         , UnsafeSqlFunctionArgument f-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f) where-  toArgList = toArgList . from6--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         , UnsafeSqlFunctionArgument f-         , UnsafeSqlFunctionArgument g-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g) where-  toArgList = toArgList . from7--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         , UnsafeSqlFunctionArgument f-         , UnsafeSqlFunctionArgument g-         , UnsafeSqlFunctionArgument h-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h) where-  toArgList = toArgList . from8--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         , UnsafeSqlFunctionArgument f-         , UnsafeSqlFunctionArgument g-         , UnsafeSqlFunctionArgument h-         , UnsafeSqlFunctionArgument i-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h, i) where-  toArgList = toArgList . from9--- | @since 3.2.3-instance ( UnsafeSqlFunctionArgument a-         , UnsafeSqlFunctionArgument b-         , UnsafeSqlFunctionArgument c-         , UnsafeSqlFunctionArgument d-         , UnsafeSqlFunctionArgument e-         , UnsafeSqlFunctionArgument f-         , UnsafeSqlFunctionArgument g-         , UnsafeSqlFunctionArgument h-         , UnsafeSqlFunctionArgument i-         , UnsafeSqlFunctionArgument j-         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h, i, j) where-  toArgList = toArgList . from10----- | (Internal) Coerce a value's type from 'SqlExpr (Value a)' to--- 'SqlExpr (Value b)'.  You should /not/ use this function--- unless you know what you're doing!-veryUnsafeCoerceSqlExprValue :: SqlExpr (Value a) -> SqlExpr (Value b)-veryUnsafeCoerceSqlExprValue (ERaw p f)             = ERaw p f-veryUnsafeCoerceSqlExprValue (ECompositeKey f)      = ECompositeKey f-veryUnsafeCoerceSqlExprValue (EAliasedValue i v)    = EAliasedValue i (veryUnsafeCoerceSqlExprValue v)-veryUnsafeCoerceSqlExprValue (EValueReference i i') = EValueReference i i'----- | (Internal) Coerce a value's type from 'SqlExpr (ValueList--- a)' to 'SqlExpr (Value a)'.  Does not work with empty lists.-veryUnsafeCoerceSqlExprValueList :: SqlExpr (ValueList a) -> SqlExpr (Value a)-veryUnsafeCoerceSqlExprValueList (EList v)  = v-veryUnsafeCoerceSqlExprValueList EEmptyList = throw (UnexpectedCaseErr EmptySqlExprValueList)----------------------------------------------------------------------------- | (Internal) Execute an @esqueleto@ @SELECT@ 'SqlQuery' inside--- @persistent@'s 'SqlPersistT' monad.-rawSelectSource :: ( SqlSelect a r-                   , MonadIO m1-                   , MonadIO m2-                   )-                 => Mode-                 -> SqlQuery a-                 -> SqlReadT m1 (Acquire (C.ConduitT () r m2 ()))-rawSelectSource mode query =-      do-        conn <- projectBackend <$> R.ask-        let _ = conn :: SqlBackend-        res <- R.withReaderT (const conn) (run conn)-        return $ (C..| massage) `fmap` res-    where--      run conn =-        uncurry rawQueryRes $-        first builderToText $-        toRawSql mode (conn, initialIdentState) query--      massage = do-        mrow <- C.await-        case process <$> mrow of-          Just (Right r)  -> C.yield r >> massage-          Just (Left err) -> liftIO $ throwIO $ PersistMarshalError err-          Nothing         -> return ()--      process = sqlSelectProcessRow----- | Execute an @esqueleto@ @SELECT@ query inside @persistent@'s--- 'SqlPersistT' monad and return a 'C.Source' of rows.-selectSource :: ( SqlSelect a r-               , BackendCompatible SqlBackend backend-               , IsPersistBackend backend-               , PersistQueryRead backend-               , PersistStoreRead backend, PersistUniqueRead backend-               , MonadResource m )-             => SqlQuery a-             -> C.ConduitT () r (R.ReaderT backend m) ()-selectSource query = do-  res <- lift $ rawSelectSource SELECT query-  (key, src) <- lift $ allocateAcquire res-  src-  lift $ release key---- | Execute an @esqueleto@ @SELECT@ query inside @persistent@'s--- 'SqlPersistT' monad and return a list of rows.------ We've seen that 'from' has some magic about which kinds of--- things you may bring into scope.  This 'select' function also--- has some magic for which kinds of things you may bring back to--- Haskell-land by using @SqlQuery@'s @return@:------  * You may return a @SqlExpr ('Entity' v)@ for an entity @v@---  (i.e., like the @*@ in SQL), which is then returned to---  Haskell-land as just @Entity v@.------  * You may return a @SqlExpr (Maybe (Entity v))@ for an entity---  @v@ that may be @NULL@, which is then returned to---  Haskell-land as @Maybe (Entity v)@.  Used for @OUTER JOIN@s.------  * You may return a @SqlExpr ('Value' t)@ for a value @t@---  (i.e., a single column), where @t@ is any instance of---  'PersistField', which is then returned to Haskell-land as---  @Value t@.  You may use @Value@ to return projections of an---  @Entity@ (see @('^.')@ and @('?.')@) or to return any other---  value calculated on the query (e.g., 'countRows' or---  'subSelect').------ The @SqlSelect a r@ class has functional dependencies that--- allow type information to flow both from @a@ to @r@ and--- vice-versa.  This means that you'll almost never have to give--- any type signatures for @esqueleto@ queries.  For example, the--- query @'select' $ from $ \\p -> return p@ alone is ambiguous, but--- in the context of------ @--- do ps <- 'select' $---          'from' $ \\p ->---          return p---    liftIO $ mapM_ (putStrLn . personName . entityVal) ps--- @------ we are able to infer from that single @personName . entityVal@--- function composition that the @p@ inside the query is of type--- @SqlExpr (Entity Person)@.-select :: ( SqlSelect a r-          , MonadIO m-          )-       => SqlQuery a -> SqlReadT m [r]-select query = do-    res <- rawSelectSource SELECT query-    conn <- R.ask-    liftIO $ with res $ flip R.runReaderT conn . runSource---- | (Internal) Run a 'C.Source' of rows.-runSource :: Monad m =>-             C.ConduitT () r (R.ReaderT backend m) ()-          -> R.ReaderT backend m [r]-runSource src = C.runConduit $ src C..| CL.consume------------------------------------------------------------------------------ | (Internal) Execute an @esqueleto@ statement inside--- @persistent@'s 'SqlPersistT' monad.-rawEsqueleto :: ( MonadIO m, SqlSelect a r, BackendCompatible SqlBackend backend)-           => Mode-           -> SqlQuery a-           -> R.ReaderT backend m Int64-rawEsqueleto mode query = do-  conn <- R.ask-  uncurry rawExecuteCount $-    first builderToText $-    toRawSql mode (conn, initialIdentState) query----- | Execute an @esqueleto@ @DELETE@ query inside @persistent@'s--- 'SqlPersistT' monad.  Note that currently there are no type--- checks for statements that should not appear on a @DELETE@--- query.------ Example of usage:------ @--- 'delete' $--- 'from' $ \\appointment ->--- 'where_' (appointment '^.' AppointmentDate '<.' 'val' now)--- @------ Unlike 'select', there is a useful way of using 'delete' that--- will lead to type ambiguities.  If you want to delete all rows--- (i.e., no 'where_' clause), you'll have to use a type signature:------ @--- 'delete' $--- 'from' $ \\(appointment :: 'SqlExpr' ('Entity' Appointment)) ->--- return ()--- @-delete :: ( MonadIO m )-       => SqlQuery ()-       -> SqlWriteT m ()-delete = void . deleteCount---- | Same as 'delete', but returns the number of rows affected.-deleteCount :: ( MonadIO m )-            => SqlQuery ()-            -> SqlWriteT m Int64-deleteCount = rawEsqueleto DELETE----- | Execute an @esqueleto@ @UPDATE@ query inside @persistent@'s--- 'SqlPersistT' monad.  Note that currently there are no type--- checks for statements that should not appear on a @UPDATE@--- query.------ Example of usage:------ @--- 'update' $ \\p -> do--- 'set' p [ PersonAge '=.' 'just' ('val' thisYear) -. p '^.' PersonBorn ]--- 'where_' $ isNothing (p '^.' PersonAge)--- @-update-  ::-  ( MonadIO m, PersistEntity val-  , BackendCompatible SqlBackend (PersistEntityBackend val)-  )-  => (SqlExpr (Entity val) -> SqlQuery ())-  -> SqlWriteT m ()-update = void . updateCount---- | Same as 'update', but returns the number of rows affected.-updateCount-  ::-  ( MonadIO m, PersistEntity val-  , BackendCompatible SqlBackend (PersistEntityBackend val)-  )-  => (SqlExpr (Entity val) -> SqlQuery ())-  -> SqlWriteT m Int64-updateCount = rawEsqueleto UPDATE . from----------------------------------------------------------------------------builderToText :: TLB.Builder -> T.Text-builderToText = TL.toStrict . TLB.toLazyTextWith defaultChunkSize-  where-    defaultChunkSize = 1024 - 32----- | (Internal) Pretty prints a 'SqlQuery' into a SQL query.------ Note: if you're curious about the SQL query being generated by--- @esqueleto@, instead of manually using this function (which is--- possible but tedious), see the 'renderQueryToText' function (along with--- 'renderQuerySelect', 'renderQueryUpdate', etc).-toRawSql-  :: (SqlSelect a r, BackendCompatible SqlBackend backend)-  => Mode -> (backend, IdentState) -> SqlQuery a -> (TLB.Builder, [PersistValue])-toRawSql mode (conn, firstIdentState) query =-  let ((ret, sd), finalIdentState) =-        flip S.runState firstIdentState $-        W.runWriterT $-        unQ query-      SideData distinctClause-               fromClauses-               setClauses-               whereClauses-               groupByClause-               havingClause-               orderByClauses-               limitClause-               lockingClause-               cteClause = sd-      -- Pass the finalIdentState (containing all identifiers-      -- that were used) to the subsequent calls.  This ensures-      -- that no name clashes will occur on subqueries that may-      -- appear on the expressions below.-      info = (projectBackend conn, finalIdentState)-  in mconcat-      [ makeCte        info cteClause-      , makeInsertInto info mode ret-      , makeSelect     info mode distinctClause ret-      , makeFrom       info mode fromClauses-      , makeSet        info setClauses-      , makeWhere      info whereClauses-      , makeGroupBy    info groupByClause-      , makeHaving     info havingClause-      , makeOrderBy    info orderByClauses-      , makeLimit      info limitClause orderByClauses-      , makeLocking         lockingClause-      ]---- | Renders a 'SqlQuery' into a 'Text' value along with the list of--- 'PersistValue's that would be supplied to the database for @?@ placeholders.------ You must ensure that the 'Mode' you pass to this function corresponds with--- the actual 'SqlQuery'. If you pass a query that uses incompatible features--- (like an @INSERT@ statement with a @SELECT@ mode) then you'll get a weird--- result.------ @since 3.1.1-renderQueryToText-  :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)-  => Mode-  -- ^ Whether to render as an 'SELECT', 'DELETE', etc.-  -> SqlQuery a-  -- ^ The SQL query you want to render.-  -> R.ReaderT backend m (T.Text, [PersistValue])-renderQueryToText mode query = do-  backend <- R.ask-  let (builder, pvals) = toRawSql mode (backend, initialIdentState) query-  pure (builderToText builder, pvals)---- | Renders a 'SqlQuery' into a 'Text' value along with the list of--- 'PersistValue's that would be supplied to the database for @?@ placeholders.------ @since 3.1.1-renderQuerySelect-  :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)-  => SqlQuery a-  -- ^ The SQL query you want to render.-  -> R.ReaderT backend m (T.Text, [PersistValue])-renderQuerySelect = renderQueryToText SELECT---- | Renders a 'SqlQuery' into a 'Text' value along with the list of--- 'PersistValue's that would be supplied to the database for @?@ placeholders.------ @since 3.1.1-renderQueryDelete-  :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)-  => SqlQuery a-  -- ^ The SQL query you want to render.-  -> R.ReaderT backend m (T.Text, [PersistValue])-renderQueryDelete = renderQueryToText DELETE---- | Renders a 'SqlQuery' into a 'Text' value along with the list of--- 'PersistValue's that would be supplied to the database for @?@ placeholders.------ @since 3.1.1-renderQueryUpdate-  :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)-  => SqlQuery a-  -- ^ The SQL query you want to render.-  -> R.ReaderT backend m (T.Text, [PersistValue])-renderQueryUpdate = renderQueryToText UPDATE---- | Renders a 'SqlQuery' into a 'Text' value along with the list of--- 'PersistValue's that would be supplied to the database for @?@ placeholders.------ @since 3.1.1-renderQueryInsertInto-  :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)-  => SqlQuery a-  -- ^ The SQL query you want to render.-  -> R.ReaderT backend m (T.Text, [PersistValue])-renderQueryInsertInto = renderQueryToText INSERT_INTO---- | (Internal) Mode of query being converted by 'toRawSql'.-data Mode =-    SELECT-  | DELETE-  | UPDATE-  | INSERT_INTO---uncommas :: [TLB.Builder] -> TLB.Builder-uncommas = intersperseB ", "--intersperseB :: TLB.Builder -> [TLB.Builder] -> TLB.Builder-intersperseB a = mconcat . intersperse a . filter (/= mempty)--uncommas' :: Monoid a => [(TLB.Builder, a)] -> (TLB.Builder, a)-uncommas' = (uncommas *** mconcat) . unzip--makeCte :: IdentInfo -> [CommonTableExpressionClause] -> (TLB.Builder, [PersistValue])-makeCte info cteClauses =-  let-    withCteText-      | hasRecursive = "WITH RECURSIVE "-      | otherwise = "WITH "--      where-        hasRecursive =-          any (== RecursiveCommonTableExpression) $-            fmap (\(CommonTableExpressionClause cteKind _ _) -> cteKind) cteClauses--    cteClauseToText (CommonTableExpressionClause _ cteIdent cteFn) =-      first (\tlb ->-          useIdent info cteIdent <> " AS " <> parens tlb-      ) $ cteFn info--    cteBody =-      mconcat $-        intersperse (",\n", mempty) $-          fmap cteClauseToText cteClauses-  in-  if length cteClauses == 0 then-    mempty-  else-    first (\tlb -> withCteText <> tlb <> "\n") cteBody---makeInsertInto :: SqlSelect a r => IdentInfo -> Mode -> a -> (TLB.Builder, [PersistValue])-makeInsertInto info INSERT_INTO ret = sqlInsertInto info ret-makeInsertInto _    _           _   = mempty---makeSelect :: SqlSelect a r => IdentInfo -> Mode -> DistinctClause -> a -> (TLB.Builder, [PersistValue])-makeSelect info mode_ distinctClause ret = process mode_-  where-    process mode =-      case mode of-        SELECT      -> withCols selectKind-        DELETE      -> plain "DELETE "-        UPDATE      -> plain "UPDATE "-        INSERT_INTO -> process SELECT-    selectKind =-      case distinctClause of-        DistinctAll      -> ("SELECT ", [])-        DistinctStandard -> ("SELECT DISTINCT ", [])-        DistinctOn exprs -> first (("SELECT DISTINCT ON (" <>) . (<> ") ")) $-                            uncommas' (processExpr <$> exprs)-      where processExpr (EDistinctOn f) = materializeExpr info f-    withCols v = v <> sqlSelectCols info ret-    plain    v = (v, [])---makeFrom-  :: IdentInfo-  -> Mode-  -> [FromClause]-  -> (TLB.Builder, [PersistValue])-makeFrom _    _    [] = mempty-makeFrom info mode fs = ret-  where-    ret = case collectOnClauses (fst info) fs of-            Left expr -> throw $ mkExc expr-            Right fs' -> keyword $ uncommas' (map (mk Never) fs')-    keyword = case mode of-                UPDATE -> id-                _      -> first ("\nFROM " <>)--    mk _     (FromStart i def) = base i def-    mk paren (FromJoin lhs kind rhs monClause) =-      first (parensM paren) $-      mconcat [ mk Never lhs-              , (fromKind kind, mempty)-              , mk Parens rhs-              , maybe mempty makeOnClause monClause-              ]-    mk _ (OnClause _) = throw (UnexpectedCaseErr MakeFromError)-    mk _ (FromQuery ident f subqueryType) =-      let (queryText, queryVals) = f info-          lateralKeyword =-            case subqueryType of-              NormalSubQuery -> ""-              LateralSubQuery -> "LATERAL "-      in (lateralKeyword <> (parens queryText) <> " AS " <> useIdent info ident, queryVals)-    mk _ (FromIdent ident) =-      (useIdent info ident, mempty)--    base ident@(I identText) def =-      let db@(DBName dbText) = entityDB def-      in ( if dbText == identText-           then fromDBName info db-           else fromDBName info db <> (" AS " <> useIdent info ident)-         , mempty )--    fromKind InnerJoinKind      = " INNER JOIN "-    fromKind CrossJoinKind      = " CROSS JOIN "-    fromKind LeftOuterJoinKind  = " LEFT OUTER JOIN "-    fromKind RightOuterJoinKind = " RIGHT OUTER JOIN "-    fromKind FullOuterJoinKind  = " FULL OUTER JOIN "--    makeOnClause (ERaw _ f)        = first (" ON " <>) (f info)-    makeOnClause (ECompositeKey _) = throw (CompositeKeyErr MakeOnClauseError)-    makeOnClause (EAliasedValue _ _) = throw (AliasedValueErr MakeOnClauseError)-    makeOnClause (EValueReference _ _) = throw (AliasedValueErr MakeOnClauseError)--    mkExc :: SqlExpr (Value Bool) -> OnClauseWithoutMatchingJoinException-    mkExc (ERaw _ f) =-      OnClauseWithoutMatchingJoinException $-      TL.unpack $ TLB.toLazyText $ fst (f info)-    mkExc (ECompositeKey _) = throw (CompositeKeyErr MakeExcError)-    mkExc (EAliasedValue _ _) = throw (AliasedValueErr MakeExcError)-    mkExc (EValueReference _ _) = throw (AliasedValueErr MakeExcError)--makeSet :: IdentInfo -> [SetClause] -> (TLB.Builder, [PersistValue])-makeSet _    [] = mempty-makeSet info os = first ("\nSET " <>) . uncommas' $ concatMap mk os-  where-    mk (SetClause (ERaw _ f))             = [f info]-    mk (SetClause (ECompositeKey _))      = throw (CompositeKeyErr MakeSetError) -- FIXME-    mk (SetClause (EAliasedValue i _))    = [aliasedValueIdentToRawSql i info]-    mk (SetClause (EValueReference i i')) = [valueReferenceToRawSql i i' info]--makeWhere :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue])-makeWhere _    NoWhere                       = mempty-makeWhere info (Where v) = first ("\nWHERE " <>) $ x info-  where-    x =-      case v of-        ERaw _ f             -> f-        EAliasedValue i _    -> aliasedValueIdentToRawSql i-        EValueReference i i' -> valueReferenceToRawSql i i'-        ECompositeKey _      -> throw (CompositeKeyErr MakeWhereError)--makeGroupBy :: IdentInfo -> GroupByClause -> (TLB.Builder, [PersistValue])-makeGroupBy _ (GroupBy []) = (mempty, [])-makeGroupBy info (GroupBy fields) = first ("\nGROUP BY " <>) build-  where-    build :: (TLB.Builder, [PersistValue])-    build = uncommas' $ map match fields--    match :: SomeValue -> (TLB.Builder, [PersistValue])-    match (SomeValue (ERaw _ f)) = f info-    match (SomeValue (ECompositeKey f)) = (mconcat $ f info, mempty)-    match (SomeValue (EAliasedValue i _)) = aliasedValueIdentToRawSql i info-    match (SomeValue (EValueReference i i')) = valueReferenceToRawSql i i' info--makeHaving :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue])-makeHaving _    NoWhere   = mempty-makeHaving info (Where v) = first ("\nHAVING " <>) $ x info-  where-    x =-      case v of-        ERaw _ f             -> f-        EAliasedValue i _    -> aliasedValueIdentToRawSql i-        EValueReference i i' -> valueReferenceToRawSql i i'-        ECompositeKey _      -> throw (CompositeKeyErr MakeHavingError)---- makeHaving, makeWhere and makeOrderBy-makeOrderByNoNewline ::-     IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue])-makeOrderByNoNewline _    [] = mempty-makeOrderByNoNewline info os = first ("ORDER BY " <>) . uncommas' $ concatMap mk os-  where-    mk :: OrderByClause -> [(TLB.Builder, [PersistValue])]-    mk (EOrderBy t (ECompositeKey f)) =-      let fs = f info-          vals = repeat []-      in zip (map (<> orderByType t) fs) vals-    mk (EOrderBy t v) =-      let x = case v of-                ERaw p f -> (first (parensM p)) . f-                EAliasedValue i _ -> aliasedValueIdentToRawSql i-                EValueReference i i' -> valueReferenceToRawSql i i'-                ECompositeKey _ -> undefined -- defined above-      in [ first (<> orderByType t) $ x info ]-    mk EOrderRandom = [first (<> "RANDOM()") mempty]--    orderByType ASC  = " ASC"-    orderByType DESC = " DESC"--makeOrderBy :: IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue])-makeOrderBy _ [] = mempty-makeOrderBy info is =-  let (tlb, vals) = makeOrderByNoNewline info is-  in ("\n" <> tlb, vals)--{-# DEPRECATED EOrderRandom "Since 2.6.0: `rand` ordering function is not uniform across all databases! To avoid accidental partiality it will be removed in the next major version." #-}--makeLimit :: IdentInfo -> LimitClause -> [OrderByClause] -> (TLB.Builder, [PersistValue])-makeLimit (conn, _) (Limit ml mo) orderByClauses =-  let limitRaw = connLimitOffset conn (v ml, v mo) hasOrderClause "\n"-      hasOrderClause = not (null orderByClauses)-      v = maybe 0 fromIntegral-  in (TLB.fromText limitRaw, mempty)---makeLocking :: LockingClause -> (TLB.Builder, [PersistValue])-makeLocking = flip (,) [] . maybe mempty toTLB . Monoid.getLast-  where-    toTLB ForUpdate           = "\nFOR UPDATE"-    toTLB ForUpdateSkipLocked = "\nFOR UPDATE SKIP LOCKED"-    toTLB ForShare            = "\nFOR SHARE"-    toTLB LockInShareMode     = "\nLOCK IN SHARE MODE"----parens :: TLB.Builder -> TLB.Builder-parens b = "(" <> (b <> ")")--aliasedValueIdentToRawSql :: Ident -> IdentInfo -> (TLB.Builder, [PersistValue])-aliasedValueIdentToRawSql i info =-  (useIdent info i, mempty)--valueReferenceToRawSql ::  Ident -> (IdentInfo -> Ident) -> IdentInfo -> (TLB.Builder, [PersistValue])-valueReferenceToRawSql sourceIdent columnIdentF info =-  (useIdent info sourceIdent <> "." <> useIdent info (columnIdentF info), mempty)--aliasedEntityColumnIdent :: Ident -> FieldDef -> Ident-aliasedEntityColumnIdent (I baseIdent) field =-  I (baseIdent <> "_" <> (unDBName $ fieldDB field))--aliasedColumnName :: Ident -> IdentInfo -> T.Text -> TLB.Builder-aliasedColumnName (I baseIdent) info columnName =-  useIdent info (I (baseIdent <> "_" <> columnName))----------------------------------------------------------------------------- | (Internal) Class for mapping results coming from 'SqlQuery'--- into actual results.------ This looks very similar to @RawSql@, and it is!  However,--- there are some crucial differences and ultimately they're--- different classes.-class SqlSelect a r | a -> r, r -> a where-  -- | Creates the variable part of the @SELECT@ query and-  -- returns the list of 'PersistValue's that will be given to-  -- 'rawQuery'.-  sqlSelectCols :: IdentInfo -> a -> (TLB.Builder, [PersistValue])--  -- | Number of columns that will be consumed.-  sqlSelectColCount :: Proxy a -> Int--  -- | Transform a row of the result into the data type.-  sqlSelectProcessRow :: [PersistValue] -> Either T.Text r--  -- | Create @INSERT INTO@ clause instead.-  sqlInsertInto :: IdentInfo -> a -> (TLB.Builder, [PersistValue])-  sqlInsertInto = throw (UnexpectedCaseErr UnsupportedSqlInsertIntoType)----- | @INSERT INTO@ hack.-instance SqlSelect (SqlExpr InsertFinal) InsertFinal where-  sqlInsertInto info (EInsertFinal (EInsert p _)) =-    let fields = uncommas $-                 map (fromDBName info . fieldDB) $-                 entityFields $-                 entityDef p-        table  = fromDBName info . entityDB . entityDef $ p-    in ("INSERT INTO " <> table <> parens fields <> "\n", [])-  sqlSelectCols info (EInsertFinal (EInsert _ f)) = f info-  sqlSelectColCount   = const 0-  sqlSelectProcessRow =-    const (Right (throw (UnexpectedCaseErr InsertionFinalError)))----- | Not useful for 'select', but used for 'update' and 'delete'.-instance SqlSelect () () where-  sqlSelectCols _ _ = ("1", [])-  sqlSelectColCount _ = 1-  sqlSelectProcessRow _ = Right ()--unescapedColumnNames :: EntityDef -> [DBName]-unescapedColumnNames ent =-     (if hasCompositeKey ent-      then [] else [fieldDB (entityId ent)])-   <> map fieldDB (entityFields ent)---- | You may return an 'Entity' from a 'select' query.-instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where-  sqlSelectCols info expr@(EEntity ident) = ret-      where-        process ed = uncommas $-                     map ((name <>) . TLB.fromText) $-                     entityColumnNames ed (fst info)-        -- 'name' is the biggest difference between 'RawSql' and-        -- 'SqlSelect'.  We automatically create names for tables-        -- (since it's not the user who's writing the FROM-        -- clause), while 'rawSql' assumes that it's just the-        -- name of the table (which doesn't allow self-joins, for-        -- example).-        name = useIdent info ident <> "."-        ret = let ed = entityDef $ getEntityVal $ return expr-              in (process ed, mempty)-  sqlSelectCols info expr@(EAliasedEntity aliasIdent tableIdent) = ret-      where-        process ed = uncommas $-                     map ((name <>) . aliasName) $-                     unescapedColumnNames ed-        aliasName columnName = (fromDBName info columnName) <> " AS " <> aliasedColumnName aliasIdent info (unDBName columnName)-        name = useIdent info tableIdent <> "."-        ret = let ed = entityDef $ getEntityVal $ return expr-              in (process ed, mempty)-  sqlSelectCols info expr@(EAliasedEntityReference sourceIdent baseIdent) = ret-      where-        process ed = uncommas $-                     map ((name <>) . aliasedColumnName baseIdent info . unDBName) $-                     unescapedColumnNames ed-        name = useIdent info sourceIdent <> "."-        ret = let ed = entityDef $ getEntityVal $ return expr-              in (process ed, mempty)-  sqlSelectColCount = entityColumnCount . entityDef . getEntityVal-  sqlSelectProcessRow = parseEntityValues ed-    where ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity a)))---getEntityVal :: Proxy (SqlExpr (Entity a)) -> Proxy a-getEntityVal = const Proxy----- | You may return a possibly-@NULL@ 'Entity' from a 'select' query.-instance PersistEntity a => SqlSelect (SqlExpr (Maybe (Entity a))) (Maybe (Entity a)) where-  sqlSelectCols info (EMaybe ent) = sqlSelectCols info ent-  sqlSelectColCount = sqlSelectColCount . fromEMaybe-    where-      fromEMaybe :: Proxy (SqlExpr (Maybe e)) -> Proxy (SqlExpr e)-      fromEMaybe = const Proxy-  sqlSelectProcessRow cols-    | all (== PersistNull) cols = return Nothing-    | otherwise                 = Just <$> sqlSelectProcessRow cols----- | You may return any single value (i.e. a single column) from--- a 'select' query.-instance PersistField a => SqlSelect (SqlExpr (Value a)) (Value a) where-  sqlSelectCols = materializeExpr-  sqlSelectColCount = const 1-  sqlSelectProcessRow [pv] = Value <$> fromPersistValue pv-  sqlSelectProcessRow pvs  = Value <$> fromPersistValue (PersistList pvs)---- | Materialize a @SqlExpr (Value a)@.-materializeExpr :: IdentInfo -> SqlExpr (Value a) -> (TLB.Builder, [PersistValue])-materializeExpr info (ERaw p f) =-  let (b, vals) = f info-  in (parensM p b, vals)-materializeExpr info (ECompositeKey f) =-  let bs = f info-  in (uncommas $ map (parensM Parens) bs, [])-materializeExpr info (EAliasedValue ident x) =-  let (b, vals) = materializeExpr info x-  in (b <> " AS " <> (useIdent info ident), vals)-materializeExpr info (EValueReference sourceIdent columnIdent) =-  valueReferenceToRawSql sourceIdent columnIdent info---- | You may return tuples (up to 16-tuples) and tuples of tuples--- from a 'select' query.-instance ( SqlSelect a ra-         , SqlSelect b rb-         ) => SqlSelect (a, b) (ra, rb) where-  sqlSelectCols esc (a, b) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      ]-  sqlSelectColCount = uncurry (+) . (sqlSelectColCount *** sqlSelectColCount) . fromTuple-    where-      fromTuple :: Proxy (a,b) -> (Proxy a, Proxy b)-      fromTuple = const (Proxy, Proxy)-  sqlSelectProcessRow =-    let x = getType processRow-        getType :: SqlSelect a r => (z -> Either y (r,x)) -> Proxy a-        getType = const Proxy--        colCountFst = sqlSelectColCount x--        processRow row =-            let (rowFst, rowSnd) = splitAt colCountFst row-            in (,) <$> sqlSelectProcessRow rowFst-                   <*> sqlSelectProcessRow rowSnd--    in colCountFst `seq` processRow-       -- Avoids recalculating 'colCountFst'.---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         ) => SqlSelect (a, b, c) (ra, rb, rc) where-  sqlSelectCols esc (a, b, c) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      ]-  sqlSelectColCount   = sqlSelectColCount . from3P-  sqlSelectProcessRow = fmap to3 . sqlSelectProcessRow--from3P :: Proxy (a,b,c) -> Proxy ((a,b),c)-from3P = const Proxy--from3 :: (a,b,c) -> ((a,b),c)-from3 (a,b,c) = ((a,b),c)--to3 :: ((a,b),c) -> (a,b,c)-to3 ((a,b),c) = (a,b,c)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         ) => SqlSelect (a, b, c, d) (ra, rb, rc, rd) where-  sqlSelectCols esc (a, b, c, d) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      ]-  sqlSelectColCount   = sqlSelectColCount . from4P-  sqlSelectProcessRow = fmap to4 . sqlSelectProcessRow--from4P :: Proxy (a,b,c,d) -> Proxy ((a,b),(c,d))-from4P = const Proxy--from4 :: (a,b,c,d) -> ((a,b),(c,d))-from4 (a,b,c,d) = ((a,b),(c,d))--to4 :: ((a,b),(c,d)) -> (a,b,c,d)-to4 ((a,b),(c,d)) = (a,b,c,d)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         ) => SqlSelect (a, b, c, d, e) (ra, rb, rc, rd, re) where-  sqlSelectCols esc (a, b, c, d, e) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      ]-  sqlSelectColCount   = sqlSelectColCount . from5P-  sqlSelectProcessRow = fmap to5 . sqlSelectProcessRow--from5P :: Proxy (a,b,c,d,e) -> Proxy ((a,b),(c,d),e)-from5P = const Proxy--from5 :: (a,b,c,d,e) -> ((a,b),(c,d),e)-from5 (a,b,c,d,e) = ((a,b),(c,d),e)--to5 :: ((a,b),(c,d),e) -> (a,b,c,d,e)-to5 ((a,b),(c,d),e) = (a,b,c,d,e)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         ) => SqlSelect (a, b, c, d, e, f) (ra, rb, rc, rd, re, rf) where-  sqlSelectCols esc (a, b, c, d, e, f) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      ]-  sqlSelectColCount   = sqlSelectColCount . from6P-  sqlSelectProcessRow = fmap to6 . sqlSelectProcessRow--from6P :: Proxy (a,b,c,d,e,f) -> Proxy ((a,b),(c,d),(e,f))-from6P = const Proxy--from6 :: (a,b,c,d,e,f) -> ((a,b),(c,d),(e,f))-from6 (a,b,c,d,e,f) = ((a,b),(c,d),(e,f))--to6 :: ((a,b),(c,d),(e,f)) -> (a,b,c,d,e,f)-to6 ((a,b),(c,d),(e,f)) = (a,b,c,d,e,f)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         ) => SqlSelect (a, b, c, d, e, f, g) (ra, rb, rc, rd, re, rf, rg) where-  sqlSelectCols esc (a, b, c, d, e, f, g) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      ]-  sqlSelectColCount   = sqlSelectColCount . from7P-  sqlSelectProcessRow = fmap to7 . sqlSelectProcessRow--from7P :: Proxy (a,b,c,d,e,f,g) -> Proxy ((a,b),(c,d),(e,f),g)-from7P = const Proxy--from7 :: (a,b,c,d,e,f,g) -> ((a,b),(c,d),(e,f),g)-from7 (a,b,c,d,e,f,g) = ((a,b),(c,d),(e,f),g)--to7 :: ((a,b),(c,d),(e,f),g) -> (a,b,c,d,e,f,g)-to7 ((a,b),(c,d),(e,f),g) = (a,b,c,d,e,f,g)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         ) => SqlSelect (a, b, c, d, e, f, g, h) (ra, rb, rc, rd, re, rf, rg, rh) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      ]-  sqlSelectColCount   = sqlSelectColCount . from8P-  sqlSelectProcessRow = fmap to8 . sqlSelectProcessRow--from8P :: Proxy (a,b,c,d,e,f,g,h) -> Proxy ((a,b),(c,d),(e,f),(g,h))-from8P = const Proxy--from8 :: (a,b,c,d,e,f,g,h) -> ((a,b),(c,d),(e,f),(g,h))-from8 (a,b,c,d,e,f,g,h) = ((a,b),(c,d),(e,f),(g,h))--to8 :: ((a,b),(c,d),(e,f),(g,h)) -> (a,b,c,d,e,f,g,h)-to8 ((a,b),(c,d),(e,f),(g,h)) = (a,b,c,d,e,f,g,h)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         ) => SqlSelect (a, b, c, d, e, f, g, h, i) (ra, rb, rc, rd, re, rf, rg, rh, ri) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      ]-  sqlSelectColCount   = sqlSelectColCount . from9P-  sqlSelectProcessRow = fmap to9 . sqlSelectProcessRow--from9P :: Proxy (a,b,c,d,e,f,g,h,i) -> Proxy ((a,b),(c,d),(e,f),(g,h),i)-from9P = const Proxy--from9 :: (a,b,c,d,e,f,g,h,i) -> ((a,b),(c,d),(e,f),(g,h),i)-from9 (a,b,c,d,e,f,g,h,i) = ((a,b),(c,d),(e,f),(g,h),i)--to9 :: ((a,b),(c,d),(e,f),(g,h),i) -> (a,b,c,d,e,f,g,h,i)-to9 ((a,b),(c,d),(e,f),(g,h),i) = (a,b,c,d,e,f,g,h,i)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      ]-  sqlSelectColCount   = sqlSelectColCount . from10P-  sqlSelectProcessRow = fmap to10 . sqlSelectProcessRow--from10P :: Proxy (a,b,c,d,e,f,g,h,i,j) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j))-from10P = const Proxy--from10 :: (a,b,c,d,e,f,g,h,i,j) -> ((a,b),(c,d),(e,f),(g,h),(i,j))-from10 (a,b,c,d,e,f,g,h,i,j) = ((a,b),(c,d),(e,f),(g,h),(i,j))--to10 :: ((a,b),(c,d),(e,f),(g,h),(i,j)) -> (a,b,c,d,e,f,g,h,i,j)-to10 ((a,b),(c,d),(e,f),(g,h),(i,j)) = (a,b,c,d,e,f,g,h,i,j)---instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      ]-  sqlSelectColCount   = sqlSelectColCount . from11P-  sqlSelectProcessRow = fmap to11 . sqlSelectProcessRow--from11P :: Proxy (a,b,c,d,e,f,g,h,i,j,k) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),k)-from11P = const Proxy--to11 :: ((a,b),(c,d),(e,f),(g,h),(i,j),k) -> (a,b,c,d,e,f,g,h,i,j,k)-to11 ((a,b),(c,d),(e,f),(g,h),(i,j),k) = (a,b,c,d,e,f,g,h,i,j,k)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         , SqlSelect l rl-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      , sqlSelectCols esc l-      ]-  sqlSelectColCount   = sqlSelectColCount . from12P-  sqlSelectProcessRow = fmap to12 . sqlSelectProcessRow--from12P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l))-from12P = const Proxy--to12 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l)) -> (a,b,c,d,e,f,g,h,i,j,k,l)-to12 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l)) = (a,b,c,d,e,f,g,h,i,j,k,l)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         , SqlSelect l rl-         , SqlSelect m rm-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      , sqlSelectCols esc l-      , sqlSelectCols esc m-      ]-  sqlSelectColCount   = sqlSelectColCount . from13P-  sqlSelectProcessRow = fmap to13 . sqlSelectProcessRow--from13P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m)-from13P = const Proxy--to13 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m) -> (a,b,c,d,e,f,g,h,i,j,k,l,m)-to13 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m) = (a,b,c,d,e,f,g,h,i,j,k,l,m)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         , SqlSelect l rl-         , SqlSelect m rm-         , SqlSelect n rn-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      , sqlSelectCols esc l-      , sqlSelectCols esc m-      , sqlSelectCols esc n-      ]-  sqlSelectColCount   = sqlSelectColCount . from14P-  sqlSelectProcessRow = fmap to14 . sqlSelectProcessRow--from14P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n))-from14P = const Proxy--to14 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n)) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n)-to14 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n)) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         , SqlSelect l rl-         , SqlSelect m rm-         , SqlSelect n rn-         , SqlSelect o ro-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn, ro) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      , sqlSelectCols esc l-      , sqlSelectCols esc m-      , sqlSelectCols esc n-      , sqlSelectCols esc o-      ]-  sqlSelectColCount   = sqlSelectColCount . from15P-  sqlSelectProcessRow = fmap to15 . sqlSelectProcessRow--from15P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n, o) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o)-from15P = const Proxy--to15 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)-to15 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)--instance ( SqlSelect a ra-         , SqlSelect b rb-         , SqlSelect c rc-         , SqlSelect d rd-         , SqlSelect e re-         , SqlSelect f rf-         , SqlSelect g rg-         , SqlSelect h rh-         , SqlSelect i ri-         , SqlSelect j rj-         , SqlSelect k rk-         , SqlSelect l rl-         , SqlSelect m rm-         , SqlSelect n rn-         , SqlSelect o ro-         , SqlSelect p rp-         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn, ro, rp) where-  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =-    uncommas'-      [ sqlSelectCols esc a-      , sqlSelectCols esc b-      , sqlSelectCols esc c-      , sqlSelectCols esc d-      , sqlSelectCols esc e-      , sqlSelectCols esc f-      , sqlSelectCols esc g-      , sqlSelectCols esc h-      , sqlSelectCols esc i-      , sqlSelectCols esc j-      , sqlSelectCols esc k-      , sqlSelectCols esc l-      , sqlSelectCols esc m-      , sqlSelectCols esc n-      , sqlSelectCols esc o-      , sqlSelectCols esc p-      ]-  sqlSelectColCount   = sqlSelectColCount . from16P-  sqlSelectProcessRow = fmap to16 . sqlSelectProcessRow--from16P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p))-from16P = const Proxy--to16 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p)) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)-to16 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p)) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)----- | Insert a 'PersistField' for every selected value.------ /Since: 2.4.2/-insertSelect :: (MonadIO m, PersistEntity a) =>-  SqlQuery (SqlExpr (Insertion a)) -> SqlWriteT m ()-insertSelect = void . insertSelectCount---- | Insert a 'PersistField' for every selected value, return the count afterward-insertSelectCount :: (MonadIO m, PersistEntity a) =>-  SqlQuery (SqlExpr (Insertion a)) -> SqlWriteT m Int64-insertSelectCount = rawEsqueleto INSERT_INTO . fmap EInsertFinal---- | Renders an expression into 'Text'. Only useful for creating a textual--- representation of the clauses passed to an "On" clause.------ @since 3.2.0-renderExpr :: SqlBackend -> SqlExpr (Value Bool) -> T.Text-renderExpr sqlBackend e =-  case e of-    ERaw _ mkBuilderValues -> do-      let (builder, _) = mkBuilderValues (sqlBackend, initialIdentState)-       in (builderToText builder)-    ECompositeKey mkInfo ->-      throw-        . RenderExprUnexpectedECompositeKey-        . builderToText-        . mconcat-        . mkInfo-        $ (sqlBackend, initialIdentState)-    EAliasedValue i _   ->-      builderToText $ useIdent (sqlBackend, initialIdentState) i-    EValueReference i i' ->-      let (builder, _) = valueReferenceToRawSql i i' (sqlBackend, initialIdentState)-       in (builderToText builder)--- | An exception thrown by 'RenderExpr' - it's not designed to handle composite--- keys, and will blow up if you give it one.------ @since 3.2.0-data RenderExprException = RenderExprUnexpectedECompositeKey T.Text-  deriving Show---- |------ @since 3.2.0-instance Exception RenderExprException------------------------------------------------------------------------------ | @valkey i = 'val' . 'toSqlKey'@--- (<https://github.com/prowdsponsor/esqueleto/issues/9>).-valkey :: (ToBackendKey SqlBackend entity, PersistField (Key entity)) =>-          Int64 -> SqlExpr (Value (Key entity))-valkey = val . toSqlKey----- | @valJ@ is like @val@ but for something that is already a @Value@. The use--- case it was written for was, given a @Value@ lift the @Key@ for that @Value@--- into the query expression in a type safe way. However, the implementation is--- more generic than that so we call it @valJ@.------ Its important to note that the input entity and the output entity are--- constrained to be the same by the type signature on the function--- (<https://github.com/prowdsponsor/esqueleto/pull/69>).------ /Since: 1.4.2/-valJ :: (PersistField (Key entity)) =>-        Value (Key entity) -> SqlExpr (Value (Key entity))-valJ = val . unValue------------------------------------------------------------------------------ | Synonym for 'Database.Persist.Store.delete' that does not--- clash with @esqueleto@'s 'delete'.-deleteKey :: ( PersistStore backend-             , BaseBackend backend ~ PersistEntityBackend val-             , MonadIO m-             , PersistEntity val )-          => Key val -> R.ReaderT backend m ()-deleteKey = Database.Persist.delete---- | Avoid N+1 queries and join entities into a map structure--- @--- getFoosAndNestedBarsFromParent :: ParentId -> (Map (Key Foo) (Foo, [Maybe (Entity Bar)]))--- getFoosAndNestedBarsFromParent parentId = 'fmap' associateJoin $ 'select' $--- 'from' $ \\(foo `'LeftOuterJoin`` bar) -> do---   'on' (bar '?.' BarFooId '==.' foo '^.' FooId)---   'where_' (foo '^.' FooParentId '==.' 'val' parentId)---   'pure' (foo, bar)--- @------ @since 3.1.2-associateJoin-  :: forall e1 e0-   . Ord (Key e0)-  => [(Entity e0, e1)]-  -> Map.Map (Key e0) (e0, [e1])-associateJoin = foldr f start-  where-    start = Map.empty-    f (one, many) =-      Map.insertWith-        (\(oneOld, manyOld) (_, manyNew) -> (oneOld, manyNew ++ manyOld ))-        (entityKey one)-        (entityVal one, [many])+{-# LANGUAGE CPP #-}+{-# language DerivingStrategies, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This is an internal module, anything exported by this module+-- may change without a major version bump.  Please use only+-- "Database.Esqueleto" if possible.+--+-- If you use this module, please report what your use case is on the issue+-- tracker so we can safely support it.+module Database.Esqueleto.Internal.Internal where++import Control.Applicative ((<|>))+import Control.Arrow (first, (***))+import Control.Exception (Exception, throw, throwIO)+import Control.Monad (MonadPlus(..), guard, void)+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Resource (MonadResource, release)+import Data.Acquire (Acquire, allocateAcquire, with)+import Data.Int (Int64)+import Data.List (intersperse)+import qualified Data.Maybe as Maybe+#if __GLASGOW_HASKELL__ < 804+import Data.Semigroup+#endif+import qualified Control.Monad.Trans.Reader as R+import qualified Control.Monad.Trans.State as S+import qualified Control.Monad.Trans.Writer as W+import qualified Data.ByteString as B+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import qualified Data.HashSet as HS+import qualified Data.Map.Strict as Map+import qualified Data.Monoid as Monoid+import Data.Proxy (Proxy(..))+import Data.Set (Set)+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import Data.Typeable (Typeable)+import Database.Esqueleto.Internal.ExprParser (TableAccess(..), parseOnExpr)+import Database.Esqueleto.Internal.PersistentImport+import qualified Database.Persist+import Database.Persist.Sql.Util+       ( entityColumnCount+       , entityColumnNames+       , hasCompositeKey+       , isIdField+       , parseEntityValues+       )+import Text.Blaze.Html (Html)++-- | (Internal) Start a 'from' query with an entity. 'from'+-- does two kinds of magic using 'fromStart', 'fromJoin' and+-- 'fromFinish':+--+--   1.  The simple but tedious magic of allowing tuples to be+--   used.+--+--   2.  The more advanced magic of creating @JOIN@s.  The+--   @JOIN@ is processed from right to left.  The rightmost+--   entity of the @JOIN@ is created with 'fromStart'.  Each+--   @JOIN@ step is then translated into a call to 'fromJoin'.+--   In the end, 'fromFinish' is called to materialize the+--   @JOIN@.+fromStart+    :: forall a.+    ( PersistEntity a+    , BackendCompatible SqlBackend (PersistEntityBackend a)+    )+    => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a))))+fromStart = do+    let ed = entityDef (Proxy :: Proxy a)+    ident <- newIdentFor (entityDB ed)+    let ret = EEntity ident+        f' = FromStart ident ed+    return (EPreprocessedFrom ret f')++-- | (Internal) Same as 'fromStart', but entity may be missing.+fromStartMaybe+    :: ( PersistEntity a+       , BackendCompatible SqlBackend (PersistEntityBackend a)+       )+    => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Maybe (Entity a)))))+fromStartMaybe = maybelize <$> fromStart+  where+    maybelize+        :: SqlExpr (PreprocessedFrom (SqlExpr (Entity a)))+        -> SqlExpr (PreprocessedFrom (SqlExpr (Maybe (Entity a))))+    maybelize (EPreprocessedFrom ret f') = EPreprocessedFrom (EMaybe ret) f'++-- | (Internal) Do a @JOIN@.+fromJoin+    :: IsJoinKind join+    => SqlExpr (PreprocessedFrom a)+    -> SqlExpr (PreprocessedFrom b)+    -> SqlQuery (SqlExpr (PreprocessedFrom (join a b)))+fromJoin (EPreprocessedFrom lhsRet lhsFrom)+         (EPreprocessedFrom rhsRet rhsFrom) = Q $ do+    let ret = smartJoin lhsRet rhsRet+        from' =+            FromJoin+                lhsFrom             -- LHS+                (reifyJoinKind ret) -- JOIN+                rhsFrom             -- RHS+                Nothing             -- ON+    return (EPreprocessedFrom ret from')++-- | (Internal) Finish a @JOIN@.+fromFinish+  :: SqlExpr (PreprocessedFrom a)+  -> SqlQuery a+fromFinish (EPreprocessedFrom ret f') = Q $ do+    W.tell mempty { sdFromClause = [f'] }+    return ret++-- | @WHERE@ clause: restrict the query's result.+where_ :: SqlExpr (Value Bool) -> SqlQuery ()+where_ expr = Q $ W.tell mempty { sdWhereClause = Where expr }++-- | An @ON@ clause, useful to describe how two tables are related. Cross joins+-- and tuple-joins do not need an 'on' clause, but 'InnerJoin' and the various+-- outer joins do.+--+-- "Database.Esqueleto.Experimental" in version 4.0.0.0 of the library. The+-- @Experimental@ module has a dramatically improved means for introducing+-- tables and entities that provides more power and less potential for runtime+-- errors.+--+-- If you don't include an 'on' clause (or include too many!) then a runtime+-- exception will be thrown.+--+-- As an example, consider this simple join:+--+-- @+-- 'select' $+-- 'from' $ \\(foo `'InnerJoin`` bar) -> do+--   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)+--   ...+-- @+--+-- We need to specify the clause for joining the two columns together. If we had+-- this:+--+-- @+-- 'select' $+-- 'from' $ \\(foo `'CrossJoin`` bar) -> do+--   ...+-- @+--+-- Then we can safely omit the 'on' clause, because the cross join will make+-- pairs of all records possible.+--+-- You can do multiple 'on' clauses in a query. This query joins three tables,+-- and has two 'on' clauses:+--+-- @+-- 'select' $+-- 'from' $ \\(foo `'InnerJoin`` bar `'InnerJoin`` baz) -> do+--   'on' (baz '^.' BazId '==.' bar '^.' BarBazId)+--   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)+--   ...+-- @+--+-- Old versions of esqueleto required that you provide the 'on' clauses in+-- reverse order. This restriction has been lifted - you can now provide 'on'+-- clauses in any order, and the SQL should work itself out. The above query is+-- now totally equivalent to this:+--+-- @+-- 'select' $+-- 'from' $ \\(foo `'InnerJoin`` bar `'InnerJoin`` baz) -> do+--   'on' (foo '^.' FooId '==.' bar '^.' BarFooId)+--   'on' (baz '^.' BazId '==.' bar '^.' BarBazId)+--   ...+-- @+on :: SqlExpr (Value Bool) -> SqlQuery ()+on expr = Q $ W.tell mempty { sdFromClause = [OnClause expr] }++-- | @GROUP BY@ clause. You can enclose multiple columns+-- in a tuple.+--+-- @+-- select $ 'from' \\(foo `'InnerJoin`` bar) -> do+--   'on' (foo '^.' FooBarId '==.' bar '^.' BarId)+--   'groupBy' (bar '^.' BarId, bar '^.' BarName)+--   return (bar '^.' BarId, bar '^.' BarName, countRows)+-- @+--+-- With groupBy you can sort by aggregate functions, like so+-- (we used @let@ to restrict the more general 'countRows' to+-- @SqlSqlExpr (Value Int)@ to avoid ambiguity---the second use of+-- 'countRows' has its type restricted by the @:: Int@ below):+--+-- @+-- r \<- select $ 'from' \\(foo `'InnerJoin`` bar) -> do+--   'on' (foo '^.' FooBarId '==.' bar '^.' BarId)+--   'groupBy' $ bar '^.' BarName+--   let countRows' = 'countRows'+--   'orderBy' ['asc' countRows']+--   return (bar '^.' BarName, countRows')+-- forM_ r $ \\('Value' name, 'Value' count) -> do+--   print name+--   print (count :: Int)+-- @+--+-- === Need more columns?+--+-- The 'ToSomeValues' class is defined for 'SqlExpr' and tuples of 'SqlExpr's.+-- We only have definitions for up to 8 elements in a tuple right now, so it's+-- possible that you may need to have more than 8 elements.+--+-- For example, consider a query with a 'groupBy' call like this:+--+-- @+-- groupBy (e0, e1, e2, e3, e4, e5, e6, e7)+-- @+--+-- This is the biggest you can get with a single tuple. However, you can easily+-- nest the tuples to add more:+--+-- @+-- groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9)+-- @+groupBy :: (ToSomeValues a) => a -> SqlQuery ()+groupBy expr = Q $ W.tell mempty { sdGroupByClause = GroupBy $ toSomeValues expr }++-- | @ORDER BY@ clause. See also 'asc' and 'desc'.+--+-- Multiple calls to 'orderBy' get concatenated on the final+-- query, including 'distinctOnOrderBy'.+orderBy :: [SqlExpr OrderBy] -> SqlQuery ()+orderBy exprs = Q $ W.tell mempty { sdOrderByClause = exprs }++-- | Ascending order of this field or SqlExpression.+asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy+asc  = EOrderBy ASC++-- | Descending order of this field or SqlExpression.+desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy+desc = EOrderBy DESC++-- | @LIMIT@.  Limit the number of returned rows.+limit :: Int64 -> SqlQuery ()+limit  n = Q $ W.tell mempty { sdLimitClause = Limit (Just n) Nothing  }++-- | @OFFSET@.  Usually used with 'limit'.+offset :: Int64 -> SqlQuery ()+offset n = Q $ W.tell mempty { sdLimitClause = Limit Nothing  (Just n) }++-- | @DISTINCT@.  Change the current @SELECT@ into @SELECT+-- DISTINCT@.  For example:+--+-- @+-- select $ distinct $+--   'from' \\foo -> do+--   ...+-- @+--+-- Note that this also has the same effect:+--+-- @+-- select $+--   'from' \\foo -> do+--   distinct (return ())+--   ...+-- @+--+-- @since 2.2.4+distinct :: SqlQuery a -> SqlQuery a+distinct act = Q (W.tell mempty { sdDistinctClause = DistinctStandard }) >> act++-- | @DISTINCT ON@.  Change the current @SELECT@ into+-- @SELECT DISTINCT ON (SqlExpressions)@.  For example:+--+-- @+-- select $+--   'from' \\foo ->+--   'distinctOn' ['don' (foo ^. FooName), 'don' (foo ^. FooState)] $ do+--   ...+-- @+--+-- You can also chain different calls to 'distinctOn'.  The+-- above is equivalent to:+--+-- @+-- select $+--   'from' \\foo ->+--   'distinctOn' ['don' (foo ^. FooName)] $+--   'distinctOn' ['don' (foo ^. FooState)] $ do+--   ...+-- @+--+-- Each call to 'distinctOn' adds more SqlExpressions.  Calls to+-- 'distinctOn' override any calls to 'distinct'.+--+-- Note that PostgreSQL requires the SqlExpressions on @DISTINCT+-- ON@ to be the first ones to appear on a @ORDER BY@.  This is+-- not managed automatically by esqueleto, keeping its spirit+-- of trying to be close to raw SQL.+--+-- Supported by PostgreSQL only.+--+-- @since 2.2.4+distinctOn :: [SqlExpr DistinctOn] -> SqlQuery a -> SqlQuery a+distinctOn exprs act = Q (W.tell mempty { sdDistinctClause = DistinctOn exprs }) >> act++-- | Erase an SqlExpression's type so that it's suitable to+-- be used by 'distinctOn'.+--+-- @since 2.2.4+don :: SqlExpr (Value a) -> SqlExpr DistinctOn+don = EDistinctOn++-- | A convenience function that calls both 'distinctOn' and+-- 'orderBy'.  In other words,+--+-- @+-- 'distinctOnOrderBy' [asc foo, desc bar, desc quux] $ do+--   ...+-- @+--+-- is the same as:+--+-- @+-- 'distinctOn' [don foo, don  bar, don  quux] $ do+--   'orderBy'  [asc foo, desc bar, desc quux]+--   ...+-- @+--+-- @since 2.2.4+distinctOnOrderBy :: [SqlExpr OrderBy] -> SqlQuery a -> SqlQuery a+distinctOnOrderBy exprs act =+    distinctOn (toDistinctOn <$> exprs) $ do+        orderBy exprs+        act+  where+    toDistinctOn :: SqlExpr OrderBy -> SqlExpr DistinctOn+    toDistinctOn (EOrderBy _ f) = EDistinctOn f+    toDistinctOn EOrderRandom =+        error "We can't select distinct by a random order!"++-- | @ORDER BY random()@ clause.+--+-- @since 1.3.10+rand :: SqlExpr OrderBy+rand = EOrderRandom++-- | @HAVING@.+--+-- @since 1.2.2+having :: SqlExpr (Value Bool) -> SqlQuery ()+having expr = Q $ W.tell mempty { sdHavingClause = Where expr }++-- | Add a locking clause to the query.  Please read+-- 'LockingKind' documentation and your RDBMS manual.+--+-- If multiple calls to 'locking' are made on the same query,+-- the last one is used.+--+-- @since 2.2.7+locking :: LockingKind -> SqlQuery ()+locking kind = Q $ W.tell mempty { sdLockingClause = Monoid.Last (Just kind) }++{-#+  DEPRECATED+    sub_select+    "sub_select \n \+sub_select is an unsafe function to use. If used with a SqlQuery that \n \+returns 0 results, then it may return NULL despite not mentioning Maybe \n \+in the return type. If it returns more than 1 result, then it will throw a \n \+SQL error.\n\n Instead, consider using one of the following alternatives: \n \+- subSelect: attaches a LIMIT 1 and the Maybe return type, totally safe.  \n \+- subSelectMaybe: Attaches a LIMIT 1, useful for a query that already \n \+  has a Maybe in the return type. \n \+- subSelectCount: Performs a count of the query - this is always safe. \n \+- subSelectUnsafe: Performs no checks or guarantees. Safe to use with \n \+  countRows and friends."+  #-}+-- | Execute a subquery @SELECT@ in an SqlExpression.  Returns a+-- simple value so should be used only when the @SELECT@ query+-- is guaranteed to return just one row.+--+-- Deprecated in 3.2.0.+sub_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)+sub_select         = sub SELECT++-- | Execute a subquery @SELECT@ in a 'SqlExpr'. The query passed to this+-- function will only return a single result - it has a @LIMIT 1@ passed in to+-- the query to make it safe, and the return type is 'Maybe' to indicate that+-- the subquery might result in 0 rows.+--+-- If you find yourself writing @'joinV' . 'subSelect'@, then consider using+-- 'subSelectMaybe'.+--+-- If you're performing a 'countRows', then you can use 'subSelectCount' which+-- is safe.+--+-- If you know that the subquery will always return exactly one row (eg+-- a foreign key constraint guarantees that you'll get exactly one row), then+-- consider 'subSelectUnsafe', along with a comment explaining why it is safe.+--+-- @since 3.2.0+subSelect+  :: PersistField a+  => SqlQuery (SqlExpr (Value a))+  -> SqlExpr (Value (Maybe a))+subSelect query = just (subSelectUnsafe (query <* limit 1))++-- | Execute a subquery @SELECT@ in a 'SqlExpr'. This function is a shorthand+-- for the common @'joinV' . 'subSelect'@ idiom, where you are calling+-- 'subSelect' on an expression that would be 'Maybe' already.+--+-- As an example, you would use this function when calling 'sum_' or 'max_',+-- which have 'Maybe' in the result type (for a 0 row query).+--+-- @since 3.2.0+subSelectMaybe+    :: PersistField a+    => SqlQuery (SqlExpr (Value (Maybe a)))+    -> SqlExpr (Value (Maybe a))+subSelectMaybe = joinV . subSelect++-- | Performs a @COUNT@ of the given query in a @subSelect@ manner. This is+-- always guaranteed to return a result value, and is completely safe.+--+-- @since 3.2.0+subSelectCount+    :: (Num a, PersistField a)+    => SqlQuery ignored+    -> SqlExpr (Value a)+subSelectCount query =+    subSelectUnsafe $ do+        _ <- query+        pure countRows++-- | Execute a subquery @SELECT@ in a 'SqlExpr' that returns a list. This is an+-- alias for 'subList_select' and is provided for symmetry with the other safe+-- subselect functions.+--+-- @since 3.2.0+subSelectList+    :: PersistField a+    => SqlQuery (SqlExpr (Value a))+    -> SqlExpr (ValueList a)+subSelectList = subList_select++-- | Performs a sub-select using the given foreign key on the entity. This is+-- useful to extract values that are known to be present by the database schema.+--+-- As an example, consider the following persistent definition:+--+-- @+-- User+--   profile ProfileId+--+-- Profile+--   name    Text+-- @+--+-- The following query will return the name of the user.+--+-- @+-- getUserWithName =+--     'select' $+--     'from' $ \user ->+--     'pure' (user, 'subSelectForeign' user UserProfile (^. ProfileName)+-- @+--+-- @since 3.2.0+subSelectForeign+    ::+    ( BackendCompatible SqlBackend (PersistEntityBackend val1)+    , PersistEntity val1, PersistEntity val2, PersistField a+    )+    => SqlExpr (Entity val2)+    -- ^ An expression representing the table you have access to now.+    -> EntityField val2 (Key val1)+    -- ^ The foreign key field on the table.+    -> (SqlExpr (Entity val1) -> SqlExpr (Value a))+    -- ^ A function to extract a value from the foreign reference table.+    -> SqlExpr (Value a)+subSelectForeign expr foreignKey k =+    subSelectUnsafe $+    from $ \table -> do+    where_ $ expr ^. foreignKey ==. table ^. persistIdField+    pure (k table)++-- | Execute a subquery @SELECT@ in a 'SqlExpr'. This function is unsafe,+-- because it can throw runtime exceptions in two cases:+--+-- 1. If the query passed has 0 result rows, then it will return a @NULL@ value.+--    The @persistent@ parsing operations will fail on an unexpected @NULL@.+-- 2. If the query passed returns more than one row, then the SQL engine will+--    fail with an error like "More than one row returned by a subquery used as+--    an expression".+--+-- This function is safe if you guarantee that exactly one row will be returned,+-- or if the result already has a 'Maybe' type for some reason.+--+-- For variants with the safety encoded already, see 'subSelect' and+-- 'subSelectMaybe'. For the most common safe use of this, see 'subSelectCount'.+--+-- @since 3.2.0+subSelectUnsafe :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)+subSelectUnsafe = sub SELECT++-- | Project a field of an entity.+(^.)+    :: forall typ val. (PersistEntity val, PersistField typ)+    => SqlExpr (Entity val)+    -> EntityField val typ+    -> SqlExpr (Value typ)+(EAliasedEntityReference source base) ^. field =+    EValueReference source (\_ -> aliasedEntityColumnIdent base fieldDef)+  where+    fieldDef =+        if isIdField field then+            -- TODO what about composite natural keys in a join this will ignore them+            head $ entityKeyFields ed+        else+            persistFieldDef field++    ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val)))++e ^. field+    | isIdField field = idFieldValue+    | otherwise = ERaw Never $ \info -> (dot info $ persistFieldDef field, [])+  where+    idFieldValue =+        case entityKeyFields ed of+            idField:[] ->+                ERaw Never    $ \info -> (dot info idField, [])++            idFields ->+                ECompositeKey $ \info ->  dot info <$> idFields+++    ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val)))++    dot info fieldDef =+        useIdent info sourceIdent <> "." <> fieldIdent+      where+        sourceIdent =+            case e of+                EEntity ident -> ident+                EAliasedEntity baseI _ -> baseI+                EAliasedEntityReference a b ->+                    error $ unwords+                        [ "Used (^.) with an EAliasedEntityReference."+                        , "Please file this as an Esqueleto bug."+                        , "EAliasedEntityReference", show a, show b+                        ]+        fieldIdent =+            case e of+                EEntity _ -> fromDBName info (fieldDB fieldDef)+                EAliasedEntity baseI _ -> useIdent info $ aliasedEntityColumnIdent baseI fieldDef+                EAliasedEntityReference a b ->+                    error $ unwords+                        [ "Used (^.) with an EAliasedEntityReference."+                        , "Please file this as an Esqueleto bug."+                        , "EAliasedEntityReference", show a, show b+                        ]+++-- | Project an SqlExpression that may be null, guarding against null cases.+withNonNull+    :: PersistField typ+    => SqlExpr (Value (Maybe typ))+    -> (SqlExpr (Value typ) -> SqlQuery a)+    -> SqlQuery a+withNonNull field f = do+    where_ $ not_ $ isNothing field+    f $ veryUnsafeCoerceSqlExprValue field++-- | Project a field of an entity that may be null.+(?.)+    :: (PersistEntity val, PersistField typ)+    => SqlExpr (Maybe (Entity val))+    -> EntityField val typ+    -> SqlExpr (Value (Maybe typ))+EMaybe r ?. field = just (r ^. field)++-- | Lift a constant value from Haskell-land to the query.+val  :: PersistField typ => typ -> SqlExpr (Value typ)+val v = ERaw Never $ const ("?", [toPersistValue v])++-- | @IS NULL@ comparison.+--+-- For @IS NOT NULL@, you can negate this with 'not_', as in @not_ (isNothing (person ^. PersonAge))@+--+-- Warning: Persistent and Esqueleto have different behavior for @!= Nothing@:+--+-- +----------------+----------------------------------+---------------++-- |                | Haskell                          | SQL           |+-- +================+==================================+===============++-- | __Persistent__ | @'Database.Persist.!=.' Nothing@ | @IS NOT NULL@ |+-- +----------------+----------------------------------+---------------++-- | __Esqueleto__  | @'!=.' Nothing@                  | @!= NULL@     |+-- +----------------+----------------------------------+---------------++--+-- In SQL, @= NULL@ and @!= NULL@ return NULL instead of true or false. For this reason, you very likely do not want to use @'!=.' Nothing@ in Esqueleto.+-- You may find these @hlint@ rules helpful to enforce this:+--+-- > - error: {lhs: v ==. nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}+-- > - error: {lhs: v ==. val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}+-- > - error: {lhs: v !=. nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}+-- > - error: {lhs: v !=. val Nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}+isNothing :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool)+isNothing v =+    case v of+        ERaw p f ->+            isNullExpr $ first (parensM p) . f+        EAliasedValue i _ ->+            isNullExpr $ aliasedValueIdentToRawSql i+        EValueReference i i' ->+            isNullExpr $ valueReferenceToRawSql i i'+        ECompositeKey f ->+            ERaw Parens $ flip (,) [] . (intersperseB " AND " . map (<> " IS NULL")) . f+  where+    isNullExpr :: (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value Bool)+    isNullExpr g = ERaw Parens $ first ((<> " IS NULL")) . g++-- | Analogous to 'Just', promotes a value of type @typ@ into+-- one of type @Maybe typ@.  It should hold that @'val' . Just+-- === just . 'val'@.+just :: SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ))+just exprVal = case exprVal of+    ERaw p f -> ERaw p f+    ECompositeKey f -> ECompositeKey f+    EAliasedValue i v -> EAliasedValue i (just v)+    EValueReference i i' -> EValueReference i i'++-- | @NULL@ value.+nothing :: SqlExpr (Value (Maybe typ))+nothing = unsafeSqlValue "NULL"++-- | Join nested 'Maybe's in a 'Value' into one. This is useful when+-- calling aggregate functions on nullable fields.+joinV :: SqlExpr (Value (Maybe (Maybe typ))) -> SqlExpr (Value (Maybe typ))+joinV exprMM = case exprMM of+    ERaw p f -> ERaw p f+    ECompositeKey f -> ECompositeKey f+    EAliasedValue i v -> EAliasedValue i (joinV v)+    EValueReference i i' -> EValueReference i i'+++countHelper :: Num a => TLB.Builder -> TLB.Builder -> SqlExpr (Value typ) -> SqlExpr (Value a)+countHelper open close v =+    case v of+        ERaw _ f -> countRawSql f+        EAliasedValue i _ -> countRawSql $ aliasedValueIdentToRawSql i+        EValueReference i i' -> countRawSql $ valueReferenceToRawSql i i'+        ECompositeKey _ -> countRows+  where+    countRawSql :: (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value a)+    countRawSql x = ERaw Never $ first (\b -> "COUNT" <> open <> parens b <> close) . x++-- | @COUNT(*)@ value.+countRows :: Num a => SqlExpr (Value a)+countRows = unsafeSqlValue "COUNT(*)"++-- | @COUNT@.+count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a)+count = countHelper ""           ""++-- | @COUNT(DISTINCT x)@.+--+-- @since 2.4.1+countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a)+countDistinct = countHelper "(DISTINCT " ")"++not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool)+not_ v = ERaw Never (\info -> first ("NOT " <>) $ x info)+  where+    x info =+        case v of+            ERaw p f ->+                let (b, vals) = f info+                in (parensM p b, vals)+            ECompositeKey _      ->+                throw (CompositeKeyErr NotError)+            EAliasedValue i _    ->+                aliasedValueIdentToRawSql i info+            EValueReference i i' ->+                valueReferenceToRawSql i i' info++(==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(==.) = unsafeSqlBinOpComposite " = " " AND "++(>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(>=.) = unsafeSqlBinOp " >= "++(>.)  :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(>.)  = unsafeSqlBinOp " > "++(<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(<=.) = unsafeSqlBinOp " <= "++(<.)  :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(<.)  = unsafeSqlBinOp " < "+(!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool)+(!=.) = unsafeSqlBinOpComposite " != " " OR "++(&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)+(&&.) = unsafeSqlBinOp " AND "++(||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)+(||.) = unsafeSqlBinOp " OR "++(+.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)+(+.)  = unsafeSqlBinOp " + "++(-.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)+(-.)  = unsafeSqlBinOp " - "++(/.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)+(/.)  = unsafeSqlBinOp " / "++(*.)  :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)+(*.)  = unsafeSqlBinOp " * "++-- | @BETWEEN@.+--+-- @since: 3.1.0+between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool)+a `between` (b, c) = a >=. b &&. a <=. c++random_  :: (PersistField a, Num a) => SqlExpr (Value a)+random_  = unsafeSqlValue "RANDOM()"++round_   :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)+round_   = unsafeSqlFunction "ROUND"++ceiling_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)+ceiling_ = unsafeSqlFunction "CEILING"++floor_   :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)+floor_   = unsafeSqlFunction "FLOOR"++sum_     :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b))+sum_     = unsafeSqlFunction "SUM"+min_     :: (PersistField a) => SqlExpr (Value a) -> SqlExpr (Value (Maybe a))+min_     = unsafeSqlFunction "MIN"+max_     :: (PersistField a) => SqlExpr (Value a) -> SqlExpr (Value (Maybe a))+max_     = unsafeSqlFunction "MAX"+avg_     :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b))+avg_     = unsafeSqlFunction "AVG"++-- | Allow a number of one type to be used as one of another+-- type via an implicit cast.  An explicit cast is not made,+-- this function changes only the types on the Haskell side.+--+-- /Caveat/: Trying to use @castNum@ from @Double@ to @Int@+-- will not result in an integer, the original fractional+-- number will still be used!  Use 'round_', 'ceiling_' or+-- 'floor_' instead.+--+-- /Safety/: This operation is mostly safe due to the 'Num'+-- constraint between the types and the fact that RDBMSs+-- usually allow numbers of different types to be used+-- interchangeably.  However, there may still be issues with+-- the query not being accepted by the RDBMS or @persistent@+-- not being able to parse it.+--+-- @since 2.2.9+castNum :: (Num a, Num b) => SqlExpr (Value a) -> SqlExpr (Value b)+castNum  = veryUnsafeCoerceSqlExprValue++-- | Same as 'castNum', but for nullable values.+--+-- @since 2.2.9+castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b))+castNumM = veryUnsafeCoerceSqlExprValue++-- | @COALESCE@ function. Evaluates the arguments in order and+-- returns the value of the first non-NULL SqlExpression, or NULL+-- (Nothing) otherwise. Some RDBMSs (such as SQLite) require+-- at least two arguments; please refer to the appropriate+-- documentation.+--+-- @since 1.4.3+coalesce :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a))+coalesce              = unsafeSqlFunctionParens "COALESCE"++-- | Like @coalesce@, but takes a non-nullable SqlExpression+-- placed at the end of the SqlExpression list, which guarantees+-- a non-NULL result.+--+-- @since 1.4.3+coalesceDefault :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value a) -> SqlExpr (Value a)+coalesceDefault exprs = unsafeSqlFunctionParens "COALESCE" . (exprs ++) . return . just++-- | @LOWER@ function.+lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)+lower_  = unsafeSqlFunction "LOWER"++-- | @UPPER@ function.+-- @since 3.3.0+upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)+upper_  = unsafeSqlFunction "UPPER"++-- | @TRIM@ function.+-- @since 3.3.0+trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)+trim_  = unsafeSqlFunction "TRIM"++-- | @RTRIM@ function.+-- @since 3.3.0+rtrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)+rtrim_  = unsafeSqlFunction "RTRIM"++-- | @LTRIM@ function.+-- @since 3.3.0+ltrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s)+ltrim_  = unsafeSqlFunction "LTRIM"++-- | @LENGTH@ function.+-- @since 3.3.0+length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a)+length_ = unsafeSqlFunction "LENGTH"++-- | @LEFT@ function.+-- @since 3.3.0+left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s)+left_ = unsafeSqlFunction "LEFT"++-- | @RIGHT@ function.+-- @since 3.3.0+right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s)+right_ = unsafeSqlFunction "RIGHT"++-- | @LIKE@ operator.+like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool)+like    = unsafeSqlBinOp    " LIKE "++-- | @ILIKE@ operator (case-insensitive @LIKE@).+--+-- Supported by PostgreSQL only.+--+-- @since 2.2.3+ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool)+ilike   = unsafeSqlBinOp    " ILIKE "++-- | The string @'%'@.  May be useful while using 'like' and+-- concatenation ('concat_' or '++.', depending on your+-- database).  Note that you always have to type the parenthesis,+-- for example:+--+-- @+-- name `'like`` (%) ++. 'val' \"John\" ++. (%)+-- @+(%) :: SqlString s => SqlExpr (Value s)+(%)     = unsafeSqlValue    "'%'"++-- | The @CONCAT@ function with a variable number of+-- parameters.  Supported by MySQL and PostgreSQL.+concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s)+concat_ = unsafeSqlFunction "CONCAT"++-- | The @||@ string concatenation operator (named after+-- Haskell's '++' in order to avoid naming clash with '||.').+-- Supported by SQLite and PostgreSQL.+(++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s)+(++.)   = unsafeSqlBinOp    " || "++-- | Cast a string type into 'Text'.  This function+-- is very useful if you want to use @newtype@s, or if you want+-- to apply functions such as 'like' to strings of different+-- types.+--+-- /Safety:/ This is a slightly unsafe function, especially if+-- you have defined your own instances of 'SqlString'.  Also,+-- since 'Maybe' is an instance of 'SqlString', it's possible+-- to turn a nullable value into a non-nullable one.  Avoid+-- using this function if possible.+castString :: (SqlString s, SqlString r) => SqlExpr (Value s) -> SqlExpr (Value r)+castString = veryUnsafeCoerceSqlExprValue++-- | Execute a subquery @SELECT@ in an SqlExpression.  Returns a+-- list of values.+subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a)+subList_select         = EList . sub_select++-- | Lift a list of constant value from Haskell-land to the query.+valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ)+valList []   = EEmptyList+valList vals = EList $ ERaw Parens $ const ( uncommas ("?" <$ vals)+                                           , map toPersistValue vals )++-- | Same as 'just' but for 'ValueList'.  Most of the time you+-- won't need it, though, because you can use 'just' from+-- inside 'subList_select' or 'Just' from inside 'valList'.+--+-- @since 2.2.12+justList :: SqlExpr (ValueList typ) -> SqlExpr (ValueList (Maybe typ))+justList EEmptyList = EEmptyList+justList (EList v)  = EList (just v)++-- | @IN@ operator. For example if you want to select all @Person@s by a list+-- of IDs:+--+-- @+-- SELECT *+-- FROM Person+-- WHERE Person.id IN (?)+-- @+--+-- In @esqueleto@, we may write the same query above as:+--+-- @+-- select $+-- 'from' $ \\person -> do+-- 'where_' $ person '^.' PersonId `'in_`` 'valList' personIds+-- return person+-- @+--+-- Where @personIds@ is of type @[Key Person]@.+in_ :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool)+v `in_`   e = ifNotEmptyList e False $ unsafeSqlBinOp     " IN " v (veryUnsafeCoerceSqlExprValueList e)++-- | @NOT IN@ operator.+notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool)+v `notIn` e = ifNotEmptyList e True  $ unsafeSqlBinOp " NOT IN " v (veryUnsafeCoerceSqlExprValueList e)++-- | @EXISTS@ operator.  For example:+--+-- @+-- select $+-- 'from' $ \\person -> do+-- 'where_' $ 'exists' $+--          'from' $ \\post -> do+--          'where_' (post '^.' BlogPostAuthorId '==.' person '^.' PersonId)+-- return person+-- @+exists :: SqlQuery () -> SqlExpr (Value Bool)+exists    = unsafeSqlFunction     "EXISTS " . existsHelper++-- | @NOT EXISTS@ operator.+notExists :: SqlQuery () -> SqlExpr (Value Bool)+notExists = unsafeSqlFunction "NOT EXISTS " . existsHelper++-- | @SET@ clause used on @UPDATE@s.  Note that while it's not+-- a type error to use this function on a @SELECT@, it will+-- most certainly result in a runtime error.+set :: PersistEntity val => SqlExpr (Entity val) -> [SqlExpr (Update val)] -> SqlQuery ()+set ent upds = Q $ W.tell mempty { sdSetClause = map apply upds }+  where+    apply (ESet f) = SetClause (f ent)++(=.)  :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> SqlExpr (Update val)+field  =. expr = setAux field (const expr)++(+=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)+field +=. expr = setAux field (\ent -> ent ^. field +. expr)++(-=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)+field -=. expr = setAux field (\ent -> ent ^. field -. expr)++(*=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)+field *=. expr = setAux field (\ent -> ent ^. field *. expr)++(/=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Update val)+field /=. expr = setAux field (\ent -> ent ^. field /. expr)++-- | Apply a 'PersistField' constructor to @SqlExpr Value@ arguments.+(<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b)+(<#) _ (ERaw _ f)        = EInsert Proxy f+(<#) _ (ECompositeKey _) = throw (CompositeKeyErr ToInsertionError)+(<#) _ (EAliasedValue i _) = EInsert Proxy $ aliasedValueIdentToRawSql i+(<#) _ (EValueReference i i') = EInsert Proxy $ valueReferenceToRawSql i i'+++-- | Apply extra @SqlExpr Value@ arguments to a 'PersistField' constructor+(<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b)+(EInsert _ f) <&> v =+    EInsert Proxy $ \x ->+        let (fb, fv) = f x+            (gb, gv) = g x+        in+            (fb <> ", " <> gb, fv ++ gv)+  where+    g =+        case v of+            ERaw _ f' -> f'+            EAliasedValue i _ -> aliasedValueIdentToRawSql i+            EValueReference i i' -> valueReferenceToRawSql i i'+            ECompositeKey _ -> throw (CompositeKeyErr CombineInsertionError)++-- | @CASE@ statement.  For example:+--+-- @+-- select $+-- return $+-- 'case_'+--    [ 'when_'+--        ('exists' $+--        'from' $ \\p -> do+--        'where_' (p '^.' PersonName '==.' 'val' \"Mike\"))+--      'then_'+--        ('sub_select' $+--        'from' $ \\v -> do+--        let sub =+--                'from' $ \\c -> do+--                'where_' (c '^.' PersonName '==.' 'val' \"Mike\")+--                return (c '^.' PersonFavNum)+--        'where_' (v '^.' PersonFavNum >. 'sub_select' sub)+--        return $ 'count' (v '^.' PersonName) +. 'val' (1 :: Int)) ]+--    ('else_' $ 'val' (-1))+-- @+--+-- This query is a bit complicated, but basically it checks if a person+-- named @\"Mike\"@ exists, and if that person does, run the subquery to find+-- out how many people have a ranking (by Fav Num) higher than @\"Mike\"@.+--+-- __NOTE:__ There are a few things to be aware about this statement.+--+--    * This only implements the full CASE statement, it does not+--      implement the \"simple\" CASE statement.+--+--+--    * At least one 'when_' and 'then_' is mandatory otherwise it will+--      emit an error.+--+--+--    * The 'else_' is also mandatory, unlike the SQL statement in which+--      if the @ELSE@ is omitted it will return a @NULL@. You can+--      reproduce this via 'nothing'.+--+-- @since 2.1.2+case_ :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a)+case_ = unsafeSqlCase++-- | Convert an entity's key into another entity's.+--+-- This function is to be used when you change an entity's @Id@ to be+-- that of another entity. For example:+--+-- @+-- Bar+--   barNum Int+-- Foo+--   bar BarId+--   fooNum Int+--   Primary bar+-- @+--+-- In this example, Bar is said to be the BaseEnt(ity), and Foo the child.+-- To model this in Esqueleto, declare:+--+-- @+-- instance ToBaseId Foo where+--   type BaseEnt Foo = Bar+--   toBaseIdWitness barId = FooKey barId+-- @+--+-- Now you're able to write queries such as:+--+-- @+-- 'select' $+-- 'from' $ \(bar `'InnerJoin`` foo) -> do+-- 'on' ('toBaseId' (foo '^.' FooId) '==.' bar '^.' BarId)+-- return (bar, foo)+-- @+--+-- Note: this function may be unsafe to use in conditions not like the+-- one of the example above.+--+-- @since 2.4.3+toBaseId :: ToBaseId ent => SqlExpr (Value (Key ent)) -> SqlExpr (Value (Key (BaseEnt ent)))+toBaseId = veryUnsafeCoerceSqlExprValue++{-# DEPRECATED random_ "Since 2.6.0: `random_` is not uniform across all databases! Please use a specific one such as 'Database.Esqueleto.PostgreSQL.random_', 'Database.Esqueleto.MySQL.random_', or 'Database.Esqueleto.SQLite.random_'" #-}++{-# DEPRECATED rand "Since 2.6.0: `rand` ordering function is not uniform across all databases! To avoid accidental partiality it will be removed in the next major version." #-}++-- Fixity declarations+infixl 9 ^.+infixl 7 *., /.+infixl 6 +., -.+infixr 5 ++.+infix  4 ==., >=., >., <=., <., !=.+infixr 3 &&., =., +=., -=., *=., /=.+infixr 2 ||., `like`, `ilike`+infixl 2 `InnerJoin`, `CrossJoin`, `LeftOuterJoin`, `RightOuterJoin`, `FullOuterJoin`++-- | Syntax sugar for 'case_'.+--+-- @since 2.1.2+when_ :: expr (Value Bool) -> () -> expr a -> (expr (Value Bool), expr a)+when_ cond _ expr = (cond, expr)++-- | Syntax sugar for 'case_'.+--+-- @since 2.1.2+then_ :: ()+then_ = ()++-- | Syntax sugar for 'case_'.+--+-- @since 2.1.2+else_ :: expr a -> expr a+else_ = id++-- | A single value (as opposed to a whole entity).  You may use+-- @('^.')@ or @('?.')@ to get a 'Value' from an 'Entity'.+newtype Value a = Value { unValue :: a } deriving (Eq, Ord, Show, Typeable)++-- | @since 1.4.4+instance Functor Value where+    fmap f (Value a) = Value (f a)++instance Applicative Value where+  (<*>) (Value f) (Value a) = Value (f a)+  pure = Value++instance Monad Value where+  (>>=) x f = valueJoin $ fmap f x+    where valueJoin (Value v) = v++-- | A list of single values.  There's a limited set of functions+-- able to work with this data type (such as 'subList_select',+-- 'valList', 'in_' and 'exists').+newtype ValueList a = ValueList a deriving (Eq, Ord, Show, Typeable)++-- | A wrapper type for for any @expr (Value a)@ for all a.+data SomeValue where+    SomeValue :: SqlExpr (Value a) -> SomeValue++-- | A class of things that can be converted into a list of SomeValue. It has+-- instances for tuples and is the reason why 'groupBy' can take tuples, like+-- @'groupBy' (foo '^.' FooId, foo '^.' FooName, foo '^.' FooType)@.+class ToSomeValues a where+    toSomeValues :: a -> [SomeValue]++instance+    ( ToSomeValues a+    , ToSomeValues b+    )+  =>+    ToSomeValues (a, b)+  where+    toSomeValues (a,b) = toSomeValues a ++ toSomeValues b++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    )+  =>+    ToSomeValues (a, b, c)+  where+    toSomeValues (a,b,c) = toSomeValues a ++ toSomeValues b ++ toSomeValues c++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    , ToSomeValues d+    )+  =>+    ToSomeValues (a, b, c, d)+  where+    toSomeValues (a,b,c,d) =+        toSomeValues a ++ toSomeValues b ++ toSomeValues c ++ toSomeValues d++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    , ToSomeValues d+    , ToSomeValues e+    )+  =>+    ToSomeValues (a, b, c, d, e)+  where+    toSomeValues (a,b,c,d,e) = concat+        [ toSomeValues a, toSomeValues b, toSomeValues c , toSomeValues d+        , toSomeValues e+        ]++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    , ToSomeValues d+    , ToSomeValues e+    , ToSomeValues f+    )+  =>+    ToSomeValues (a, b, c, d, e, f)+  where+    toSomeValues (a,b,c,d,e,f) = concat+        [ toSomeValues a, toSomeValues b, toSomeValues c, toSomeValues d+        , toSomeValues e , toSomeValues f+        ]++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    , ToSomeValues d+    , ToSomeValues e+    , ToSomeValues f+    , ToSomeValues g+    )+  =>+    ToSomeValues (a, b, c, d, e, f, g)+  where+    toSomeValues (a,b,c,d,e,f,g) = concat+        [ toSomeValues a,  toSomeValues b, toSomeValues c,  toSomeValues d+        , toSomeValues e,  toSomeValues f, toSomeValues g+        ]++instance+    ( ToSomeValues a+    , ToSomeValues b+    , ToSomeValues c+    , ToSomeValues d+    , ToSomeValues e+    , ToSomeValues f+    , ToSomeValues g+    , ToSomeValues h+    )+  =>+    ToSomeValues (a, b, c, d, e, f, g, h)+  where+    toSomeValues (a,b,c,d,e,f,g,h) = concat+        [ toSomeValues a, toSomeValues b, toSomeValues c, toSomeValues d+        , toSomeValues e, toSomeValues f, toSomeValues g, toSomeValues h+        ]++type family KnowResult a where+    KnowResult (i -> o) = KnowResult o+    KnowResult a = a++-- | A class for constructors or function which result type is known.+--+-- @since 3.1.3+class FinalResult a where+  finalR :: a -> KnowResult a++instance FinalResult (Unique val) where+  finalR = id++instance (FinalResult b) => FinalResult (a -> b) where+  finalR f = finalR (f undefined)++-- | Convert a constructor for a 'Unique' key on a record to the 'UniqueDef'+-- that defines it. You can supply just the constructor itself, or a value of+-- the type - the library is capable of figuring it out from there.+--+-- @since 3.1.3+toUniqueDef+    :: forall a val.+    ( KnowResult a ~ Unique val+    , PersistEntity val+    , FinalResult a+    )+    => a+    -> UniqueDef+toUniqueDef uniqueConstructor = uniqueDef+  where+    proxy :: Proxy val+    proxy = Proxy+    unique :: Unique val+    unique = finalR uniqueConstructor+    -- there must be a better way to get the constrain name from a unique, make this not a list search+    filterF = (==) (persistUniqueToFieldNames unique) . uniqueFields+    uniqueDef = head . filter filterF . entityUniques . entityDef $ proxy++-- | Render updates to be use in a SET clause for a given sql backend.+--+-- @since 3.1.3+renderUpdates+    :: (BackendCompatible SqlBackend backend)+    => backend+    -> [SqlExpr (Update val)]+    -> (TLB.Builder, [PersistValue])+renderUpdates conn = uncommas' . concatMap renderUpdate+  where+    mk :: SqlExpr (Value ()) -> [(TLB.Builder, [PersistValue])]+    mk (ERaw _ f)             = [f info]+    mk (ECompositeKey _)      = throw (CompositeKeyErr MakeSetError) -- FIXME+    mk (EAliasedValue i _)    = [aliasedValueIdentToRawSql i info]+    mk (EValueReference i i') = [valueReferenceToRawSql i i' info]++    renderUpdate :: SqlExpr (Update val) -> [(TLB.Builder, [PersistValue])]+    renderUpdate (ESet f) = mk (f undefined) -- second parameter of f is always unused+    info = (projectBackend conn, initialIdentState)++-- | Data type that represents an @INNER JOIN@ (see 'LeftOuterJoin' for an example).+data InnerJoin a b = a `InnerJoin` b++-- | Data type that represents a @CROSS JOIN@ (see 'LeftOuterJoin' for an example).+data CrossJoin a b = a `CrossJoin` b++-- | Data type that represents a @LEFT OUTER JOIN@. For example,+--+-- @+-- select $+-- 'from' $ \\(person `'LeftOuterJoin`` pet) ->+--   ...+-- @+--+-- is translated into+--+-- @+-- SELECT ...+-- FROM Person LEFT OUTER JOIN Pet+-- ...+-- @+--+-- See also: 'from'.+data LeftOuterJoin a b = a `LeftOuterJoin` b++-- | Data type that represents a @RIGHT OUTER JOIN@ (see 'LeftOuterJoin' for an example).+data RightOuterJoin a b = a `RightOuterJoin` b++-- | Data type that represents a @FULL OUTER JOIN@ (see 'LeftOuterJoin' for an example).+data FullOuterJoin a b = a `FullOuterJoin` b+++-- | (Internal) A kind of @JOIN@.+data JoinKind+    = InnerJoinKind      -- ^ @INNER JOIN@+    | CrossJoinKind      -- ^ @CROSS JOIN@+    | LeftOuterJoinKind  -- ^ @LEFT OUTER JOIN@+    | RightOuterJoinKind -- ^ @RIGHT OUTER JOIN@+    | FullOuterJoinKind  -- ^ @FULL OUTER JOIN@+    deriving (Eq, Show)+++-- | (Internal) Functions that operate on types (that should be)+-- of kind 'JoinKind'.+class IsJoinKind join where+    -- | (Internal) @smartJoin a b@ is a @JOIN@ of the correct kind.+    smartJoin :: a -> b -> join a b+    -- | (Internal) Reify a @JoinKind@ from a @JOIN@.  This+    -- function is non-strict.+    reifyJoinKind :: join a b -> JoinKind++instance IsJoinKind InnerJoin where+    smartJoin a b = a `InnerJoin` b+    reifyJoinKind _ = InnerJoinKind+instance IsJoinKind CrossJoin where+    smartJoin a b = a `CrossJoin` b+    reifyJoinKind _ = CrossJoinKind+instance IsJoinKind LeftOuterJoin where+    smartJoin a b = a `LeftOuterJoin` b+    reifyJoinKind _ = LeftOuterJoinKind+instance IsJoinKind RightOuterJoin where+    smartJoin a b = a `RightOuterJoin` b+    reifyJoinKind _ = RightOuterJoinKind+instance IsJoinKind FullOuterJoin where+    smartJoin a b = a `FullOuterJoin` b+    reifyJoinKind _ = FullOuterJoinKind+++-- | Exception thrown whenever 'on' is used to create an @ON@+-- clause but no matching @JOIN@ is found.+data OnClauseWithoutMatchingJoinException =+    OnClauseWithoutMatchingJoinException String+    deriving (Eq, Ord, Show, Typeable)++instance Exception OnClauseWithoutMatchingJoinException++-- | (Internal) Phantom type used to process 'from' (see 'fromStart').+data PreprocessedFrom a++-- | Phantom type used by 'orderBy', 'asc' and 'desc'.+data OrderBy++-- | Phantom type used by 'distinctOn' and 'don'.+data DistinctOn++-- | Phantom type for a @SET@ operation on an entity of the given+-- type (see 'set' and '(=.)').+data Update typ++-- | Phantom type used by 'insertSelect'.+data Insertion a++-- | Different kinds of locking clauses supported by 'locking'.+--+-- Note that each RDBMS has different locking support.  The+-- constructors of this datatype specify only the /syntax/ of the+-- locking mechanism, not its /semantics/.  For example, even+-- though both MySQL and PostgreSQL support 'ForUpdate', there+-- are no guarantees that they will behave the same.+--+-- @since 2.2.7+data LockingKind+    = ForUpdate+      -- ^ @FOR UPDATE@ syntax.  Supported by MySQL, Oracle and+      -- PostgreSQL.+      --+      -- @since 2.2.7+    | ForUpdateSkipLocked+      -- ^ @FOR UPDATE SKIP LOCKED@ syntax.  Supported by MySQL, Oracle and+      -- PostgreSQL.+      --+      -- @since 2.2.7+    | ForShare+      -- ^ @FOR SHARE@ syntax.  Supported by PostgreSQL.+      --+      -- @since 2.2.7+    | LockInShareMode+      -- ^ @LOCK IN SHARE MODE@ syntax.  Supported by MySQL.+      --+      -- @since 2.2.7++-- | Phantom class of data types that are treated as strings by the+-- RDBMS.  It has no methods because it's only used to avoid type+-- errors such as trying to concatenate integers.+--+-- If you have a custom data type or @newtype@, feel free to make+-- it an instance of this class.+--+-- @since 2.4.0+class PersistField a => SqlString a where++-- | @since 2.3.0+instance (a ~ Char) => SqlString [a] where++-- | @since 2.3.0+instance SqlString T.Text where++-- | @since 2.3.0+instance SqlString TL.Text where++-- | @since 2.3.0+instance SqlString B.ByteString where++-- | @since 2.3.0+instance SqlString Html where++-- | @since 2.4.0+instance SqlString a => SqlString (Maybe a) where++-- | Class that enables one to use 'toBaseId' to convert an entity's+-- key on a query into another (cf. 'toBaseId').+class ToBaseId ent where+    -- | e.g. @type BaseEnt MyBase = MyChild@+    type BaseEnt ent :: *+    -- | Convert from the key of the BaseEnt(ity) to the key of the child entity.+    -- This function is not actually called, but that it typechecks proves this operation is safe.+    toBaseIdWitness :: Key (BaseEnt ent) -> Key ent+++-- | @FROM@ clause: bring entities into scope.+--+-- Note that this function will be replaced by the one in+-- "Database.Esqueleto.Experimental" in version 4.0.0.0 of the library. The+-- @Experimental@ module has a dramatically improved means for introducing+-- tables and entities that provides more power and less potential for runtime+-- errors.+--+-- This function internally uses two type classes in order to+-- provide some flexibility of how you may call it.  Internally+-- we refer to these type classes as the two different magics.+--+-- The innermost magic allows you to use @from@ with the+-- following types:+--+--  * @expr (Entity val)@, which brings a single entity into+--  scope.+--+--  * @expr (Maybe (Entity val))@, which brings a single entity+--  that may be @NULL@ into scope.  Used for @OUTER JOIN@s.+--+--  * A @JOIN@ of any other two types allowed by the innermost+--  magic, where a @JOIN@ may be an 'InnerJoin', a 'CrossJoin', a+--  'LeftOuterJoin', a 'RightOuterJoin', or a 'FullOuterJoin'.+--  The @JOINs@ have left fixity.+--+-- The outermost magic allows you to use @from@ on any tuples of+-- types supported by innermost magic (and also tuples of tuples,+-- and so on), up to 8-tuples.+--+-- Note that using @from@ for the same entity twice does work and+-- corresponds to a self-join.  You don't even need to use two+-- different calls to @from@, you may use a @JOIN@ or a tuple.+--+-- The following are valid examples of uses of @from@ (the types+-- of the arguments of the lambda are inside square brackets):+--+-- @+-- 'from' $ \\person -> ...+-- 'from' $ \\(person, blogPost) -> ...+-- 'from' $ \\(p `'LeftOuterJoin`` mb) -> ...+-- 'from' $ \\(p1 `'InnerJoin`` f `'InnerJoin`` p2) -> ...+-- 'from' $ \\((p1 `'InnerJoin`` f) `'InnerJoin`` p2) -> ...+-- @+--+-- The types of the arguments to the lambdas above are,+-- respectively:+--+-- @+-- person+--   :: ( Esqueleto query expr backend+--      , PersistEntity Person+--      , PersistEntityBackend Person ~ backend+--      ) => expr (Entity Person)+-- (person, blogPost)+--   :: (...) => (expr (Entity Person), expr (Entity BlogPost))+-- (p `'LeftOuterJoin`` mb)+--   :: (...) => InnerJoin (expr (Entity Person)) (expr (Maybe (Entity BlogPost)))+-- (p1 `'InnerJoin`` f `'InnerJoin`` p2)+--   :: (...) => InnerJoin+--                 (InnerJoin (expr (Entity Person))+--                            (expr (Entity Follow)))+--                 (expr (Entity Person))+-- (p1 `'InnerJoin`` (f `'InnerJoin`` p2)) ::+--   :: (...) => InnerJoin+--                 (expr (Entity Person))+--                 (InnerJoin (expr (Entity Follow))+--                            (expr (Entity Person)))+-- @+--+-- Note that some backends may not support all kinds of @JOIN@s.+from :: From a => (a -> SqlQuery b) -> SqlQuery b+from = (from_ >>=)+++-- | (Internal) Class that implements the tuple 'from' magic (see+-- 'fromStart').+class From a where+    from_ :: SqlQuery a++instance+    ( FromPreprocess (SqlExpr (Entity val))+    )+  =>+    From (SqlExpr (Entity val))+  where+    from_ = fromPreprocess >>= fromFinish++instance+    ( FromPreprocess (SqlExpr (Maybe (Entity val)))+    )+  =>+    From (SqlExpr (Maybe (Entity val)))+  where+    from_ = fromPreprocess >>= fromFinish++instance+    ( FromPreprocess (InnerJoin a b)+    )+  =>+    From (InnerJoin a b)+  where+    from_ = fromPreprocess >>= fromFinish++instance+    ( FromPreprocess (CrossJoin a b)+    )+  =>+    From (CrossJoin a b)+  where+    from_ = fromPreprocess >>= fromFinish++instance (FromPreprocess (LeftOuterJoin a b)) => From (LeftOuterJoin a b) where+    from_ = fromPreprocess >>= fromFinish++instance (FromPreprocess (RightOuterJoin a b)) => From (RightOuterJoin a b) where+    from_ = fromPreprocess >>= fromFinish++instance (FromPreprocess (FullOuterJoin a b)) => From (FullOuterJoin a b) where+    from_ = fromPreprocess >>= fromFinish++instance (From a, From b) => From (a, b) where+    from_ = (,) <$> from_ <*> from_++instance (From a, From b, From c) => From (a, b, c) where+    from_ = (,,) <$> from_ <*> from_ <*> from_++instance (From a, From b, From c, From d) => From (a, b, c, d) where+    from_ = (,,,) <$> from_ <*> from_ <*> from_ <*> from_++instance (From a, From b, From c, From d, From e) => From (a, b, c, d, e) where+    from_ = (,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_++instance+    (From a, From b, From c, From d, From e, From f)+  =>+    From (a, b, c, d, e, f)+  where+    from_ = (,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_++instance+    (From a, From b, From c, From d, From e, From f, From g)+  =>+    From (a, b, c, d, e, f, g)+  where+    from_ =+        (,,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_++instance+    (From a, From b, From c, From d, From e, From f, From g, From h)+  =>+    From (a, b, c, d, e, f, g, h)+  where+    from_ =+        (,,,,,,,) <$> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_ <*> from_++++-- | (Internal) Class that implements the @JOIN@ 'from' magic+-- (see 'fromStart').+class FromPreprocess a where+    fromPreprocess :: SqlQuery (SqlExpr (PreprocessedFrom a))++instance+    (PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val))+  =>+    FromPreprocess (SqlExpr (Entity val))+  where+    fromPreprocess = fromStart++instance+    (PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val))+  =>+    FromPreprocess (SqlExpr (Maybe (Entity val)))+  where+    fromPreprocess = fromStartMaybe++instance+    (FromPreprocess a, FromPreprocess b, IsJoinKind join)+  =>+    FromPreprocess (join a b)+  where+    fromPreprocess = do+        a <- fromPreprocess+        b <- fromPreprocess+        fromJoin a b++-- | Exception data type for @esqueleto@ internal errors+data EsqueletoError+    = CompositeKeyErr CompositeKeyError+    | AliasedValueErr UnexpectedValueError+    | UnexpectedCaseErr UnexpectedCaseError+    | SqlBinOpCompositeErr SqlBinOpCompositeError+    deriving (Show)++instance Exception EsqueletoError++data UnexpectedValueError+    = NotError+    | ToInsertionError+    | CombineInsertionError+    | FoldHelpError+    | SqlCaseError+    | SqlCastAsError+    | SqlFunctionError+    | MakeOnClauseError+    | MakeExcError+    | MakeSetError+    | MakeWhereError+    | MakeHavingError+    | FilterWhereAggError+    | FilterWhereClauseError+    deriving (Show)++type CompositeKeyError = UnexpectedValueError++data UnexpectedCaseError+    = EmptySqlExprValueList+    | MakeFromError+    | UnsupportedSqlInsertIntoType+    | InsertionFinalError+    | NewIdentForError+    | UnsafeSqlCaseError+    | OperationNotSupported+    | NotImplemented+    deriving (Show)++data SqlBinOpCompositeError+    = MismatchingLengthsError+    | NullPlaceholdersError+    | DeconstructionError+    deriving (Show)++-- | SQL backend for @esqueleto@ using 'SqlPersistT'.+newtype SqlQuery a = Q { unQ :: W.WriterT SideData (S.State IdentState) a }+    deriving newtype (Functor, Applicative, Monad)++-- | Constraint synonym for @persistent@ entities whose backend+-- is 'SqlBackend'.+type SqlEntity ent = (PersistEntity ent, PersistEntityBackend ent ~ SqlBackend)+++----------------------------------------------------------------------+++-- | Side data written by 'SqlQuery'.+data SideData = SideData+    { sdDistinctClause :: !DistinctClause+    , sdFromClause     :: ![FromClause]+    , sdSetClause      :: ![SetClause]+    , sdWhereClause    :: !WhereClause+    , sdGroupByClause  :: !GroupByClause+    , sdHavingClause   :: !HavingClause+    , sdOrderByClause  :: ![OrderByClause]+    , sdLimitClause    :: !LimitClause+    , sdLockingClause  :: !LockingClause+    , sdCteClause      :: ![CommonTableExpressionClause]+    }++instance Semigroup SideData where+    SideData d f s w g h o l k c <> SideData d' f' s' w' g' h' o' l' k' c' =+        SideData (d <> d') (f <> f') (s <> s') (w <> w') (g <> g') (h <> h') (o <> o') (l <> l') (k <> k') (c <> c')++instance Monoid SideData where+    mempty = SideData mempty mempty mempty mempty mempty mempty mempty mempty mempty mempty+    mappend = (<>)++-- | The @DISTINCT@ "clause".+data DistinctClause+    = DistinctAll+    -- ^ The default, everything.+    | DistinctStandard+    -- ^ Only @DISTINCT@, SQL standard.+    | DistinctOn [SqlExpr DistinctOn]+    -- ^ @DISTINCT ON@, PostgreSQL extension.++instance Semigroup DistinctClause where+    DistinctOn a     <> DistinctOn b = DistinctOn (a <> b)+    DistinctOn a     <> _            = DistinctOn a+    DistinctStandard <> _            = DistinctStandard+    DistinctAll      <> b            = b++instance Monoid DistinctClause where+    mempty = DistinctAll+    mappend = (<>)++-- | A part of a @FROM@ clause.+data FromClause+    = FromStart Ident EntityDef+    | FromJoin FromClause JoinKind FromClause (Maybe (SqlExpr (Value Bool)))+    | OnClause (SqlExpr (Value Bool))+    | FromQuery Ident (IdentInfo -> (TLB.Builder, [PersistValue])) SubQueryType+    | FromIdent Ident++data CommonTableExpressionKind+    = RecursiveCommonTableExpression+    | NormalCommonTableExpression+    deriving Eq++data CommonTableExpressionClause =+    CommonTableExpressionClause CommonTableExpressionKind Ident (IdentInfo -> (TLB.Builder, [PersistValue]))++data SubQueryType+    = NormalSubQuery+    | LateralSubQuery+    deriving Show++collectIdents :: FromClause -> Set Ident+collectIdents fc = case fc of+    FromStart i _ -> Set.singleton i+    FromJoin lhs _ rhs _ -> collectIdents lhs <> collectIdents rhs+    OnClause _ -> mempty+    FromQuery _ _ _ -> mempty+    FromIdent _ -> mempty++instance Show FromClause where+    show fc = case fc of+        FromStart i _ ->+            "(FromStart " <> show i <> ")"+        FromJoin lhs jk rhs mexpr ->+            mconcat+            [ "(FromJoin "+            , show lhs+            , " "+            , show jk+            , " "+            , case mexpr of+                Nothing -> "(no on clause)"+                Just expr -> "(" <> render' expr <> ")"+            , " "+            , show rhs+            , ")"+            ]+        OnClause expr ->+            "(OnClause " <> render' expr <> ")"+        FromQuery ident _ subQueryType ->+            "(FromQuery " <> show ident <> " " <> show subQueryType <> ")"+        FromIdent ident ->+            "(FromIdent " <> show ident <> ")"++      where+        dummy = SqlBackend+            { connEscapeName = \(DBName x) -> x+            }+        render' = T.unpack . renderExpr dummy++-- | A part of a @SET@ clause.+newtype SetClause = SetClause (SqlExpr (Value ()))++-- | Collect 'OnClause's on 'FromJoin's.  Returns the first+-- unmatched 'OnClause's data on error.  Returns a list without+-- 'OnClauses' on success.+collectOnClauses+    :: SqlBackend+    -> [FromClause]+    -> Either (SqlExpr (Value Bool)) [FromClause]+collectOnClauses sqlBackend = go Set.empty []+  where+    go is []  (f@(FromStart i _) : fs) =+        fmap (f:) (go (Set.insert i is) [] fs) -- fast path+    go idents acc (OnClause expr : fs) = do+        (idents', a) <- findMatching idents acc expr+        go idents' a fs+    go idents acc (f:fs) =+        go idents (f:acc) fs+    go _ acc [] =+        return $ reverse acc++    findMatching+        :: Set Ident+        -> [FromClause]+        -> SqlExpr (Value Bool)+        -> Either (SqlExpr (Value Bool)) (Set Ident, [FromClause])+    findMatching idents fromClauses expr =+        case fromClauses of+            f : acc ->+              let idents' =+                      idents+                      <> Set.fromList+                          (Maybe.catMaybes [findLeftmostIdent f, findRightmostIdent f])+              in+                  case tryMatch idents' expr f of+                      Just (idents'', f') ->+                          return (idents'', f' : acc)+                      Nothing ->+                          fmap (f:) <$> findMatching idents' acc expr+            [] ->+                Left expr++    findRightmostIdent (FromStart i _) = Just i+    findRightmostIdent (FromJoin _ _ r _) = findRightmostIdent r+    findRightmostIdent (OnClause {}) = Nothing+    findRightmostIdent (FromQuery _ _ _) = Nothing+    findRightmostIdent (FromIdent _) = Nothing++    findLeftmostIdent (FromStart i _) = Just i+    findLeftmostIdent (FromJoin l _ _ _) = findLeftmostIdent l+    findLeftmostIdent (OnClause {}) = Nothing+    findLeftmostIdent (FromQuery _ _ _) = Nothing+    findLeftmostIdent (FromIdent _) = Nothing++    tryMatch+        :: Set Ident+        -> SqlExpr (Value Bool)+        -> FromClause+        -> Maybe (Set Ident, FromClause)+    tryMatch idents expr fromClause =+      case fromClause of+        FromJoin l k r onClause ->+          matchTable <|> matchR <|> matchC <|> matchL <|> matchPartial -- right to left+            where+              matchR = fmap (\r' -> FromJoin l k r' onClause)+                <$> tryMatch idents expr r+              matchL = fmap (\l' -> FromJoin l' k r onClause)+                <$> tryMatch idents expr l++              matchPartial = do+                --Debug.traceM $ "matchPartial"+                --Debug.traceM $ "matchPartial: identsInOnClause: " <> show identsInOnClause+                i1 <- findLeftmostIdent l+                i2 <- findLeftmostIdent r+                let leftIdents = collectIdents l+                -- Debug.traceM $ "matchPartial: i1: " <> show i1+                -- Debug.traceM $ "matchPartial: i2: " <> show i2+                -- Debug.traceM $ "matchPartial: idents: " <> show idents+                guard $+                  Set.isSubsetOf+                    identsInOnClause+                    (Set.fromList [i1, i2] <> leftIdents)+                guard $ k /= CrossJoinKind+                guard $ Maybe.isNothing onClause+                pure (idents, FromJoin l k r (Just expr))++              matchC =+                case onClause of+                  Nothing+                    | "?" `T.isInfixOf` renderedExpr ->+                        return (idents, FromJoin l k r (Just expr))+                    | Set.null identsInOnClause ->+                        return (idents, FromJoin l k r (Just expr))+                    | otherwise ->+                        Nothing+                  Just _ ->+                    Nothing+              matchTable = do+                i1 <- findLeftmostIdent r+                i2 <- findRightmostIdent l+                guard $ Set.fromList [i1, i2] `Set.isSubsetOf` identsInOnClause+                guard $ k /= CrossJoinKind+                guard $ Maybe.isNothing onClause+                pure (Set.fromList [i1, i2] <> idents, FromJoin l k r (Just expr))++        _ ->+          Nothing+      where+        identsInOnClause =+          onExprToTableIdentifiers++        renderedExpr =+          renderExpr sqlBackend expr++        onExprToTableIdentifiers =+          Set.map (I . tableAccessTable)+          . either error id+          . parseOnExpr sqlBackend+          $ renderedExpr++-- | A complete @WHERE@ clause.+data WhereClause = Where (SqlExpr (Value Bool))+                 | NoWhere++instance Semigroup WhereClause where+  NoWhere  <> w        = w+  w        <> NoWhere  = w+  Where e1 <> Where e2 = Where (e1 &&. e2)++instance Monoid WhereClause where+  mempty = NoWhere+  mappend = (<>)++-- | A @GROUP BY@ clause.+newtype GroupByClause = GroupBy [SomeValue]++instance Semigroup GroupByClause where+  GroupBy fs <> GroupBy fs' = GroupBy (fs <> fs')++instance Monoid GroupByClause where+  mempty = GroupBy []+  mappend = (<>)++-- | A @HAVING@ cause.+type HavingClause = WhereClause++-- | A @ORDER BY@ clause.+type OrderByClause = SqlExpr OrderBy++-- | A @LIMIT@ clause.+data LimitClause = Limit (Maybe Int64) (Maybe Int64)+  deriving Eq++instance Semigroup LimitClause where+  Limit l1 o1 <> Limit l2 o2 =+    Limit (l2 `mplus` l1) (o2 `mplus` o1)+    -- More than one 'limit' or 'offset' is issued, we want to+    -- keep the latest one.  That's why we use mplus with+    -- "reversed" arguments.++instance Monoid LimitClause where+  mempty = Limit mzero mzero+  mappend = (<>)++-- | A locking clause.+type LockingClause = Monoid.Last LockingKind++----------------------------------------------------------------------++-- | Identifier used for table names.+newtype Ident = I T.Text+  deriving (Eq, Ord, Show)++-- | List of identifiers already in use and supply of temporary+-- identifiers.+newtype IdentState = IdentState { inUse :: HS.HashSet T.Text }++initialIdentState :: IdentState+initialIdentState = IdentState mempty++-- | Create a fresh 'Ident'.  If possible, use the given+-- 'DBName'.+newIdentFor :: DBName -> SqlQuery Ident+newIdentFor (DBName original) = Q $ lift $ findFree Nothing+  where+    findFree msuffix = do+      let+        withSuffix =+          maybe id (\suffix -> (<> T.pack (show suffix))) msuffix original+      isInUse <- S.gets (HS.member withSuffix . inUse)+      if isInUse+        then findFree (succ <$> (msuffix <|> Just (1 :: Int)))+        else do+          S.modify (\s -> s { inUse = HS.insert withSuffix (inUse s) })+          pure (I withSuffix)++-- | Information needed to escape and use identifiers.+type IdentInfo = (SqlBackend, IdentState)++-- | Use an identifier.+useIdent :: IdentInfo -> Ident -> TLB.Builder+useIdent info (I ident) = fromDBName info $ DBName ident++-- | An expression on the SQL backend.+--+-- There are many comments describing the constructors of this+-- data type.  However, Haddock doesn't like GADTs, so you'll have to read them by hitting \"Source\".+data SqlExpr a where+    -- An entity, created by 'from' (cf. 'fromStart').+    EEntity  :: Ident -> SqlExpr (Entity val)+    --                Base     Table+    EAliasedEntity :: Ident -> Ident -> SqlExpr (Entity val)+    --                         Source   Base+    EAliasedEntityReference :: Ident -> Ident -> SqlExpr (Entity val)++    -- Just a tag stating that something is nullable.+    EMaybe   :: SqlExpr a -> SqlExpr (Maybe a)++    -- Raw expression: states whether parenthesis are needed+    -- around this expression, and takes information about the SQL+    -- connection (mainly for escaping names) and returns both an+    -- string ('TLB.Builder') and a list of values to be+    -- interpolated by the SQL backend.+    ERaw     :: NeedParens -> (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Value a)+++    -- A raw expression with an alias+    EAliasedValue :: Ident -> SqlExpr (Value a) -> SqlExpr (Value a)++    -- A reference to an aliased field in a table or subquery+    EValueReference :: Ident -> (IdentInfo -> Ident) -> SqlExpr (Value a)++    -- A composite key.+    --+    -- Persistent uses the same 'PersistList' constructor for both+    -- fields which are (homogeneous) lists of values and the+    -- (probably heterogeneous) values of a composite primary key.+    --+    -- We need to treat composite keys as fields.  For example, we+    -- have to support using ==., otherwise you wouldn't be able to+    -- join.  OTOH, lists of values should be treated exactly the+    -- same as any other scalar value.+    --+    -- In particular, this is valid for persistent via rawSql for+    -- an F field that is a list:+    --+    --   A.F in ?    -- [PersistList [foo, bar]]+    --+    -- However, this is not for a composite key entity:+    --+    --   A.ID = ?    -- [PersistList [foo, bar]]+    --+    -- The ID field doesn't exist on the DB for a composite key+    -- table, it exists only on the Haskell side.  Those variations+    -- also don't work:+    --+    --   (A.KeyA, A.KeyB) = ?    -- [PersistList [foo, bar]]+    --   [A.KeyA, A.KeyB] = ?    -- [PersistList [foo, bar]]+    --+    -- We have to generate:+    --+    --   A.KeyA = ? AND A.KeyB = ?      -- [foo, bar]+    --+    -- Note that the PersistList had to be deconstructed into its+    -- components.+    --+    -- In order to disambiguate behaviors, this constructor is used+    -- /only/ to represent a composite field access.  It does not+    -- represent a 'PersistList', not even if the 'PersistList' is+    -- used in the context of a composite key.  That's because it's+    -- impossible, e.g., for 'val' to disambiguate between these+    -- uses.+    ECompositeKey :: (IdentInfo -> [TLB.Builder]) -> SqlExpr (Value a)++    -- 'EList' and 'EEmptyList' are used by list operators.+    EList      :: SqlExpr (Value a) -> SqlExpr (ValueList a)+    EEmptyList :: SqlExpr (ValueList a)++    -- A 'SqlExpr' accepted only by 'orderBy'.+    EOrderBy :: OrderByType -> SqlExpr (Value a) -> SqlExpr OrderBy++    EOrderRandom :: SqlExpr OrderBy++    -- A 'SqlExpr' accepted only by 'distinctOn'.+    EDistinctOn :: SqlExpr (Value a) -> SqlExpr DistinctOn++    -- A 'SqlExpr' accepted only by 'set'.+    ESet :: (SqlExpr (Entity val) -> SqlExpr (Value ())) -> SqlExpr (Update val)++    -- An internal 'SqlExpr' used by the 'from' hack.+    EPreprocessedFrom :: a -> FromClause -> SqlExpr (PreprocessedFrom a)++    -- Used by 'insertSelect'.+    EInsert  :: Proxy a -> (IdentInfo -> (TLB.Builder, [PersistValue])) -> SqlExpr (Insertion a)+    EInsertFinal :: PersistEntity a => SqlExpr (Insertion a) -> SqlExpr InsertFinal++-- | Phantom type used to mark a @INSERT INTO@ query.+data InsertFinal++data NeedParens = Parens | Never+    deriving Eq++parensM :: NeedParens -> TLB.Builder -> TLB.Builder+parensM Never  = id+parensM Parens = parens++data OrderByType = ASC | DESC++instance ToSomeValues (SqlExpr (Value a)) where+  toSomeValues a = [SomeValue a]++fieldName+    :: (PersistEntity val, PersistField typ)+    => IdentInfo -> EntityField val typ -> TLB.Builder+fieldName info = fromDBName info . fieldDB . persistFieldDef++-- FIXME: Composite/non-id pKS not supported on set+setAux+    :: (PersistEntity val, PersistField typ)+    => EntityField val typ+    -> (SqlExpr (Entity val) -> SqlExpr (Value typ))+    -> SqlExpr (Update val)+setAux field mkVal = ESet $ \ent -> unsafeSqlBinOp " = " name (mkVal ent)+  where+    name = ERaw Never $ \info -> (fieldName info field, mempty)++sub :: PersistField a => Mode -> SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a)+sub mode query = ERaw Parens $ \info -> toRawSql mode info query++fromDBName :: IdentInfo -> DBName -> TLB.Builder+fromDBName (conn, _) = TLB.fromText . connEscapeName conn++existsHelper :: SqlQuery () -> SqlExpr (Value Bool)+existsHelper = sub SELECT . (>> return true)+  where+    true :: SqlExpr (Value Bool)+    true = val True++ifNotEmptyList :: SqlExpr (ValueList a) -> Bool -> SqlExpr (Value Bool) -> SqlExpr (Value Bool)+ifNotEmptyList EEmptyList b _ = val b+ifNotEmptyList (EList _)  _ x = x++-- | (Internal) Create a case statement.+--+-- Since: 2.1.1+unsafeSqlCase :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a)+unsafeSqlCase when v = ERaw Never buildCase+  where+    buildCase :: IdentInfo -> (TLB.Builder, [PersistValue])+    buildCase info =+        let (elseText, elseVals) = valueToSql v info+            (whenText, whenVals) = mapWhen when info+        in ( "CASE" <> whenText <> " ELSE " <> elseText <> " END", whenVals <> elseVals)++    mapWhen :: [(SqlExpr (Value Bool), SqlExpr (Value a))] -> IdentInfo -> (TLB.Builder, [PersistValue])+    mapWhen []    _    = throw (UnexpectedCaseErr UnsafeSqlCaseError)+    mapWhen when' info = foldl (foldHelp info) (mempty, mempty) when'++    foldHelp :: IdentInfo -> (TLB.Builder, [PersistValue]) -> (SqlExpr (Value Bool), SqlExpr (Value a)) -> (TLB.Builder, [PersistValue])+    foldHelp _ _ (ECompositeKey _, _) = throw (CompositeKeyErr FoldHelpError)+    foldHelp _ _ (_, ECompositeKey _) = throw (CompositeKeyErr FoldHelpError)+    foldHelp info (b0, vals0) (v1, v2) =+        let (b1, vals1) = valueToSql v1 info+            (b2, vals2) = valueToSql v2 info+        in ( b0 <> " WHEN " <> b1 <> " THEN " <> b2, vals0 <> vals1 <> vals2 )++    valueToSql :: SqlExpr (Value a) -> IdentInfo -> (TLB.Builder, [PersistValue])+    valueToSql (ERaw p f) = (first (parensM p)) . f+    valueToSql (ECompositeKey _) = throw (CompositeKeyErr SqlCaseError)+    valueToSql (EAliasedValue i _) = aliasedValueIdentToRawSql i+    valueToSql (EValueReference i i') = valueReferenceToRawSql i i'++-- | (Internal) Create a custom binary operator.  You /should/+-- /not/ use this function directly since its type is very+-- general, you should always use it with an explicit type+-- signature.  For example:+--+-- @+-- (==.) :: SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value Bool)+-- (==.) = unsafeSqlBinOp " = "+-- @+--+-- In the example above, we constraint the arguments to be of the+-- same type and constraint the result to be a boolean value.+unsafeSqlBinOp :: TLB.Builder -> SqlExpr (Value a) -> SqlExpr (Value b) -> SqlExpr (Value c)+unsafeSqlBinOp op (ERaw p1 f1) (ERaw p2 f2) = ERaw Parens f+  where+    f info =+        let (b1, vals1) = f1 info+            (b2, vals2) = f2 info+        in+            ( parensM p1 b1 <> op <> parensM p2 b2+            , vals1 <> vals2+            )+unsafeSqlBinOp op a b = unsafeSqlBinOp op (construct a) (construct b)+  where+    construct :: SqlExpr (Value a) -> SqlExpr (Value a)+    construct (ERaw p f) =+        ERaw (if p == Never then Parens else Never) $ \info ->+            let (b1, vals) = f info+                build ("?", [PersistList vals']) =+                    (uncommas $ replicate (length vals') "?", vals')+                build expr = expr+             in+                build (parensM p b1, vals)+    construct (ECompositeKey f) =+        ERaw Parens $ \info -> (uncommas $ f info, mempty)+    construct (EAliasedValue i _) =+        ERaw Never $ aliasedValueIdentToRawSql i+    construct (EValueReference i i') =+        ERaw Never $ valueReferenceToRawSql i i'+{-# INLINE unsafeSqlBinOp #-}++-- | Similar to 'unsafeSqlBinOp', but may also be applied to+-- composite keys.  Uses the operator given as the second+-- argument whenever applied to composite keys.+--+-- Usage example:+--+-- @+-- (==.) :: SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value Bool)+-- (==.) = unsafeSqlBinOpComposite " = " " AND "+-- @+--+-- Persistent has a hack for implementing composite keys (see+-- 'ECompositeKey' doc for more details), so we're forced to use+-- a hack here as well.  We deconstruct 'ERaw' values based on+-- two rules:+--+--   - If it is a single placeholder, then it's assumed to be+--   coming from a 'PersistList' and thus its components are+--   separated so that they may be applied to a composite key.+--+--   - If it is not a single placeholder, then it's assumed to be+--   a foreign (composite or not) key, so we enforce that it has+--   no placeholders and split it on the commas.+unsafeSqlBinOpComposite :: TLB.Builder -> TLB.Builder -> SqlExpr (Value a) -> SqlExpr (Value b) -> SqlExpr (Value c)+unsafeSqlBinOpComposite op sep a b+    | isCompositeKey a || isCompositeKey b = ERaw Parens $ compose (listify a) (listify b)+    | otherwise = unsafeSqlBinOp op a b+  where+    isCompositeKey :: SqlExpr (Value x) -> Bool+    isCompositeKey (ECompositeKey _) = True+    isCompositeKey _ = False++    listify :: SqlExpr (Value x) -> IdentInfo -> ([TLB.Builder], [PersistValue])+    listify (ECompositeKey f)      = flip (,) [] . f+    listify (ERaw _ f)             = deconstruct . f+    listify (EAliasedValue i _)    = deconstruct . (aliasedValueIdentToRawSql i)+    listify (EValueReference i i') = deconstruct . (valueReferenceToRawSql i i')++    deconstruct :: (TLB.Builder, [PersistValue]) -> ([TLB.Builder], [PersistValue])+    deconstruct ("?", [PersistList vals]) = (replicate (length vals) "?", vals)+    deconstruct (b', []) = (TLB.fromLazyText <$> TL.splitOn "," (TLB.toLazyText b'), [])+    deconstruct _ = throw (SqlBinOpCompositeErr DeconstructionError)++    compose f1 f2 info+        | not (null v1 || null v2) = throw (SqlBinOpCompositeErr NullPlaceholdersError)+        | length b1 /= length b2   = throw (SqlBinOpCompositeErr MismatchingLengthsError)+        | otherwise                = (bc, vc)+      where+        (b1, v1) = f1 info+        (b2, v2) = f2 info+        bc = intersperseB sep [x <> op <> y | (x, y) <- zip b1 b2]+        vc = v1 <> v2++-- | (Internal) A raw SQL value.  The same warning from+-- 'unsafeSqlBinOp' applies to this function as well.+unsafeSqlValue :: TLB.Builder -> SqlExpr (Value a)+unsafeSqlValue v = ERaw Never $ const (v, mempty)+{-# INLINE unsafeSqlValue #-}++valueToFunctionArg :: IdentInfo -> SqlExpr (Value a) -> (TLB.Builder, [PersistValue])+valueToFunctionArg info v =+    case v of+        ERaw _ f             -> f info+        EAliasedValue i _    -> aliasedValueIdentToRawSql i info+        EValueReference i i' -> valueReferenceToRawSql i i' info+        ECompositeKey _      -> throw (CompositeKeyErr SqlFunctionError)++-- | (Internal) A raw SQL function.  Once again, the same warning+-- from 'unsafeSqlBinOp' applies to this function as well.+unsafeSqlFunction+    :: UnsafeSqlFunctionArgument a+    => TLB.Builder -> a -> SqlExpr (Value b)+unsafeSqlFunction name arg =+    ERaw Never $ \info ->+        let (argsTLB, argsVals) =+              uncommas' $ map (valueToFunctionArg info) $ toArgList arg+        in+            (name <> parens argsTLB, argsVals)++-- | (Internal) An unsafe SQL function to extract a subfield from a compound+-- field, e.g. datetime. See 'unsafeSqlBinOp' for warnings.+--+-- Since: 1.3.6.+unsafeSqlExtractSubField+    :: UnsafeSqlFunctionArgument a+    => TLB.Builder -> a -> SqlExpr (Value b)+unsafeSqlExtractSubField subField arg =+    ERaw Never $ \info ->+        let (argsTLB, argsVals) =+                uncommas' $ map (valueToFunctionArg info) $ toArgList arg+        in+            ("EXTRACT" <> parens (subField <> " FROM " <> argsTLB), argsVals)++-- | (Internal) A raw SQL function. Preserves parentheses around arguments.+-- See 'unsafeSqlBinOp' for warnings.+unsafeSqlFunctionParens+    :: UnsafeSqlFunctionArgument a+    => TLB.Builder -> a -> SqlExpr (Value b)+unsafeSqlFunctionParens name arg =+    ERaw Never $ \info ->+        let valueToFunctionArgParens v =+                case v of+                    ERaw p f             -> first (parensM p) (f info)+                    EAliasedValue i _    -> aliasedValueIdentToRawSql i info+                    EValueReference i i' -> valueReferenceToRawSql i i' info+                    ECompositeKey _      -> throw (CompositeKeyErr SqlFunctionError)+            (argsTLB, argsVals) =+                uncommas' $ map valueToFunctionArgParens $ toArgList arg+        in+            (name <> parens argsTLB, argsVals)++-- | (Internal) An explicit SQL type cast using CAST(value as type).+-- See 'unsafeSqlBinOp' for warnings.+unsafeSqlCastAs :: T.Text -> SqlExpr (Value a) -> SqlExpr (Value b)+unsafeSqlCastAs t v = ERaw Never ((first (\value -> "CAST" <> parens (value <> " AS " <> TLB.fromText t))) . valueToText)+  where+    valueToText info =+        case v of+            (ERaw p f) ->+              let (b, vals) = f info+              in (parensM p b, vals)+            EAliasedValue i _ -> aliasedValueIdentToRawSql i info+            EValueReference i i' -> valueReferenceToRawSql i i' info+            ECompositeKey _ -> throw (CompositeKeyErr SqlCastAsError)++-- | (Internal) This class allows 'unsafeSqlFunction' to work with different+-- numbers of arguments; specifically it allows providing arguments to a sql+-- function via an n-tuple of @SqlExpr (Value _)@ values, which are not all+-- necessarily required to be the same type. There are instances for up to+-- 10-tuples, but for sql functions which take more than 10 arguments, you can+-- also nest tuples, as e.g. @toArgList ((a,b),(c,d))@ is the same as+-- @toArgList (a,b,c,d)@.+class UnsafeSqlFunctionArgument a where+    toArgList :: a -> [SqlExpr (Value ())]++-- | Useful for 0-argument functions, like @now@ in Postgresql.+--+-- @since 3.2.1+instance UnsafeSqlFunctionArgument () where+    toArgList _ = []++instance (a ~ Value b) => UnsafeSqlFunctionArgument (SqlExpr a) where+    toArgList = (:[]) . veryUnsafeCoerceSqlExprValue++instance UnsafeSqlFunctionArgument a => UnsafeSqlFunctionArgument [a] where+  toArgList = concatMap toArgList++instance+    (UnsafeSqlFunctionArgument a , UnsafeSqlFunctionArgument b)+  =>+    UnsafeSqlFunctionArgument (a, b)+  where+    toArgList (a, b) = toArgList a ++ toArgList b++instance+    ( UnsafeSqlFunctionArgument a+    , UnsafeSqlFunctionArgument b+    , UnsafeSqlFunctionArgument c+    )+  =>+    UnsafeSqlFunctionArgument (a, b, c)+  where+    toArgList = toArgList . from3++instance+    ( UnsafeSqlFunctionArgument a+    , UnsafeSqlFunctionArgument b+    , UnsafeSqlFunctionArgument c+    , UnsafeSqlFunctionArgument d+    )+  =>+    UnsafeSqlFunctionArgument (a, b, c, d)+  where+    toArgList = toArgList . from4++-- | @since 3.2.3+instance+    ( UnsafeSqlFunctionArgument a+    , UnsafeSqlFunctionArgument b+    , UnsafeSqlFunctionArgument c+    , UnsafeSqlFunctionArgument d+    , UnsafeSqlFunctionArgument e+    )+  =>+    UnsafeSqlFunctionArgument (a, b, c, d, e)+  where+    toArgList = toArgList . from5++-- | @since 3.2.3+instance+    ( UnsafeSqlFunctionArgument a+    , UnsafeSqlFunctionArgument b+    , UnsafeSqlFunctionArgument c+    , UnsafeSqlFunctionArgument d+    , UnsafeSqlFunctionArgument e+    , UnsafeSqlFunctionArgument f+    )+  =>+    UnsafeSqlFunctionArgument (a, b, c, d, e, f)+  where+    toArgList = toArgList . from6++-- | @since 3.2.3+instance ( UnsafeSqlFunctionArgument a+         , UnsafeSqlFunctionArgument b+         , UnsafeSqlFunctionArgument c+         , UnsafeSqlFunctionArgument d+         , UnsafeSqlFunctionArgument e+         , UnsafeSqlFunctionArgument f+         , UnsafeSqlFunctionArgument g+         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g) where+  toArgList = toArgList . from7+-- | @since 3.2.3+instance ( UnsafeSqlFunctionArgument a+         , UnsafeSqlFunctionArgument b+         , UnsafeSqlFunctionArgument c+         , UnsafeSqlFunctionArgument d+         , UnsafeSqlFunctionArgument e+         , UnsafeSqlFunctionArgument f+         , UnsafeSqlFunctionArgument g+         , UnsafeSqlFunctionArgument h+         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h) where+  toArgList = toArgList . from8+-- | @since 3.2.3+instance ( UnsafeSqlFunctionArgument a+         , UnsafeSqlFunctionArgument b+         , UnsafeSqlFunctionArgument c+         , UnsafeSqlFunctionArgument d+         , UnsafeSqlFunctionArgument e+         , UnsafeSqlFunctionArgument f+         , UnsafeSqlFunctionArgument g+         , UnsafeSqlFunctionArgument h+         , UnsafeSqlFunctionArgument i+         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h, i) where+  toArgList = toArgList . from9+-- | @since 3.2.3+instance ( UnsafeSqlFunctionArgument a+         , UnsafeSqlFunctionArgument b+         , UnsafeSqlFunctionArgument c+         , UnsafeSqlFunctionArgument d+         , UnsafeSqlFunctionArgument e+         , UnsafeSqlFunctionArgument f+         , UnsafeSqlFunctionArgument g+         , UnsafeSqlFunctionArgument h+         , UnsafeSqlFunctionArgument i+         , UnsafeSqlFunctionArgument j+         ) => UnsafeSqlFunctionArgument (a, b, c, d, e, f, g, h, i, j) where+  toArgList = toArgList . from10+++-- | (Internal) Coerce a value's type from 'SqlExpr (Value a)' to+-- 'SqlExpr (Value b)'.  You should /not/ use this function+-- unless you know what you're doing!+veryUnsafeCoerceSqlExprValue :: SqlExpr (Value a) -> SqlExpr (Value b)+veryUnsafeCoerceSqlExprValue (ERaw p f)             = ERaw p f+veryUnsafeCoerceSqlExprValue (ECompositeKey f)      = ECompositeKey f+veryUnsafeCoerceSqlExprValue (EAliasedValue i v)    = EAliasedValue i (veryUnsafeCoerceSqlExprValue v)+veryUnsafeCoerceSqlExprValue (EValueReference i i') = EValueReference i i'+++-- | (Internal) Coerce a value's type from 'SqlExpr (ValueList+-- a)' to 'SqlExpr (Value a)'.  Does not work with empty lists.+veryUnsafeCoerceSqlExprValueList :: SqlExpr (ValueList a) -> SqlExpr (Value a)+veryUnsafeCoerceSqlExprValueList (EList v)  = v+veryUnsafeCoerceSqlExprValueList EEmptyList = throw (UnexpectedCaseErr EmptySqlExprValueList)+++----------------------------------------------------------------------++-- | (Internal) Execute an @esqueleto@ @SELECT@ 'SqlQuery' inside+-- @persistent@'s 'SqlPersistT' monad.+rawSelectSource+    ::+    ( SqlSelect a r+    , MonadIO m1+    , MonadIO m2+    )+    => Mode+    -> SqlQuery a+    -> SqlReadT m1 (Acquire (C.ConduitT () r m2 ()))+rawSelectSource mode query = do+    conn <- projectBackend <$> R.ask+    let _ = conn :: SqlBackend+    res <- R.withReaderT (const conn) (run conn)+    return $ (C..| massage) `fmap` res+  where+    run conn =+        uncurry rawQueryRes $+        first builderToText $+        toRawSql mode (conn, initialIdentState) query++    massage = do+        mrow <- C.await+        case sqlSelectProcessRow <$> mrow of+            Just (Right r)  -> C.yield r >> massage+            Just (Left err) -> liftIO $ throwIO $ PersistMarshalError err+            Nothing         -> return ()++-- | Execute an @esqueleto@ @SELECT@ query inside @persistent@'s+-- 'SqlPersistT' monad and return a 'C.Source' of rows.+selectSource+    ::+    ( SqlSelect a r+    , BackendCompatible SqlBackend backend+    , IsPersistBackend backend+    , PersistQueryRead backend+    , PersistStoreRead backend, PersistUniqueRead backend+    , MonadResource m+    )+    => SqlQuery a+    -> C.ConduitT () r (R.ReaderT backend m) ()+selectSource query = do+    res <- lift $ rawSelectSource SELECT query+    (key, src) <- lift $ allocateAcquire res+    src+    lift $ release key++-- | Execute an @esqueleto@ @SELECT@ query inside @persistent@'s+-- 'SqlPersistT' monad and return a list of rows.+--+-- We've seen that 'from' has some magic about which kinds of+-- things you may bring into scope.  This 'select' function also+-- has some magic for which kinds of things you may bring back to+-- Haskell-land by using @SqlQuery@'s @return@:+--+--  * You may return a @SqlExpr ('Entity' v)@ for an entity @v@+--  (i.e., like the @*@ in SQL), which is then returned to+--  Haskell-land as just @Entity v@.+--+--  * You may return a @SqlExpr (Maybe (Entity v))@ for an entity+--  @v@ that may be @NULL@, which is then returned to+--  Haskell-land as @Maybe (Entity v)@.  Used for @OUTER JOIN@s.+--+--  * You may return a @SqlExpr ('Value' t)@ for a value @t@+--  (i.e., a single column), where @t@ is any instance of+--  'PersistField', which is then returned to Haskell-land as+--  @Value t@.  You may use @Value@ to return projections of an+--  @Entity@ (see @('^.')@ and @('?.')@) or to return any other+--  value calculated on the query (e.g., 'countRows' or+--  'subSelect').+--+-- The @SqlSelect a r@ class has functional dependencies that+-- allow type information to flow both from @a@ to @r@ and+-- vice-versa.  This means that you'll almost never have to give+-- any type signatures for @esqueleto@ queries.  For example, the+-- query @'select' $ from $ \\p -> return p@ alone is ambiguous, but+-- in the context of+--+-- @+-- do ps <- 'select' $+--          'from' $ \\p ->+--          return p+--    liftIO $ mapM_ (putStrLn . personName . entityVal) ps+-- @+--+-- we are able to infer from that single @personName . entityVal@+-- function composition that the @p@ inside the query is of type+-- @SqlExpr (Entity Person)@.+select+    ::+    ( SqlSelect a r+    , MonadIO m+    )+    => SqlQuery a+    -> SqlReadT m [r]+select query = do+    res <- rawSelectSource SELECT query+    conn <- R.ask+    liftIO $ with res $ flip R.runReaderT conn . runSource++-- | (Internal) Run a 'C.Source' of rows.+runSource+    :: Monad m+    => C.ConduitT () r (R.ReaderT backend m) ()+    -> R.ReaderT backend m [r]+runSource src = C.runConduit $ src C..| CL.consume++-- | (Internal) Execute an @esqueleto@ statement inside+-- @persistent@'s 'SqlPersistT' monad.+rawEsqueleto+    :: (MonadIO m, SqlSelect a r, BackendCompatible SqlBackend backend)+    => Mode+    -> SqlQuery a+    -> R.ReaderT backend m Int64+rawEsqueleto mode query = do+    conn <- R.ask+    uncurry rawExecuteCount $+        first builderToText $+        toRawSql mode (conn, initialIdentState) query++-- | Execute an @esqueleto@ @DELETE@ query inside @persistent@'s+-- 'SqlPersistT' monad.  Note that currently there are no type+-- checks for statements that should not appear on a @DELETE@+-- query.+--+-- Example of usage:+--+-- @+-- 'delete' $+-- 'from' $ \\appointment ->+-- 'where_' (appointment '^.' AppointmentDate '<.' 'val' now)+-- @+--+-- Unlike 'select', there is a useful way of using 'delete' that+-- will lead to type ambiguities.  If you want to delete all rows+-- (i.e., no 'where_' clause), you'll have to use a type signature:+--+-- @+-- 'delete' $+-- 'from' $ \\(appointment :: 'SqlExpr' ('Entity' Appointment)) ->+-- return ()+-- @+delete+    :: (MonadIO m)+    => SqlQuery ()+    -> SqlWriteT m ()+delete = void . deleteCount++-- | Same as 'delete', but returns the number of rows affected.+deleteCount+    :: (MonadIO m)+    => SqlQuery ()+    -> SqlWriteT m Int64+deleteCount = rawEsqueleto DELETE++-- | Execute an @esqueleto@ @UPDATE@ query inside @persistent@'s+-- 'SqlPersistT' monad.  Note that currently there are no type+-- checks for statements that should not appear on a @UPDATE@+-- query.+--+-- Example of usage:+--+-- @+-- 'update' $ \\p -> do+-- 'set' p [ PersonAge '=.' 'just' ('val' thisYear) -. p '^.' PersonBorn ]+-- 'where_' $ isNothing (p '^.' PersonAge)+-- @+update+    ::+    ( MonadIO m, PersistEntity val+    , BackendCompatible SqlBackend (PersistEntityBackend val)+    )+    => (SqlExpr (Entity val) -> SqlQuery ())+    -> SqlWriteT m ()+update = void . updateCount++-- | Same as 'update', but returns the number of rows affected.+updateCount+    ::+    ( MonadIO m, PersistEntity val+    , BackendCompatible SqlBackend (PersistEntityBackend val)+    )+    => (SqlExpr (Entity val) -> SqlQuery ())+    -> SqlWriteT m Int64+updateCount = rawEsqueleto UPDATE . from++builderToText :: TLB.Builder -> T.Text+builderToText = TL.toStrict . TLB.toLazyTextWith defaultChunkSize+  where+    defaultChunkSize = 1024 - 32++-- | (Internal) Pretty prints a 'SqlQuery' into a SQL query.+--+-- Note: if you're curious about the SQL query being generated by+-- @esqueleto@, instead of manually using this function (which is+-- possible but tedious), see the 'renderQueryToText' function (along with+-- 'renderQuerySelect', 'renderQueryUpdate', etc).+toRawSql+  :: (SqlSelect a r, BackendCompatible SqlBackend backend)+  => Mode -> (backend, IdentState) -> SqlQuery a -> (TLB.Builder, [PersistValue])+toRawSql mode (conn, firstIdentState) query =+    let ((ret, sd), finalIdentState) =+            flip S.runState firstIdentState $+            W.runWriterT $+            unQ query+        SideData distinctClause+                 fromClauses+                 setClauses+                 whereClauses+                 groupByClause+                 havingClause+                 orderByClauses+                 limitClause+                 lockingClause+                 cteClause = sd+        -- Pass the finalIdentState (containing all identifiers+        -- that were used) to the subsequent calls.  This ensures+        -- that no name clashes will occur on subqueries that may+        -- appear on the expressions below.+        info = (projectBackend conn, finalIdentState)+    in mconcat+        [ makeCte        info cteClause+        , makeInsertInto info mode ret+        , makeSelect     info mode distinctClause ret+        , makeFrom       info mode fromClauses+        , makeSet        info setClauses+        , makeWhere      info whereClauses+        , makeGroupBy    info groupByClause+        , makeHaving     info havingClause+        , makeOrderBy    info orderByClauses+        , makeLimit      info limitClause orderByClauses+        , makeLocking         lockingClause+        ]++-- | Renders a 'SqlQuery' into a 'Text' value along with the list of+-- 'PersistValue's that would be supplied to the database for @?@ placeholders.+--+-- You must ensure that the 'Mode' you pass to this function corresponds with+-- the actual 'SqlQuery'. If you pass a query that uses incompatible features+-- (like an @INSERT@ statement with a @SELECT@ mode) then you'll get a weird+-- result.+--+-- @since 3.1.1+renderQueryToText+    :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)+    => Mode+    -- ^ Whether to render as an 'SELECT', 'DELETE', etc.+    -> SqlQuery a+    -- ^ The SQL query you want to render.+    -> R.ReaderT backend m (T.Text, [PersistValue])+renderQueryToText mode query = do+    backend <- R.ask+    let (builder, pvals) = toRawSql mode (backend, initialIdentState) query+    pure (builderToText builder, pvals)++-- | Renders a 'SqlQuery' into a 'Text' value along with the list of+-- 'PersistValue's that would be supplied to the database for @?@ placeholders.+--+-- @since 3.1.1+renderQuerySelect+    :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)+    => SqlQuery a+    -- ^ The SQL query you want to render.+    -> R.ReaderT backend m (T.Text, [PersistValue])+renderQuerySelect = renderQueryToText SELECT++-- | Renders a 'SqlQuery' into a 'Text' value along with the list of+-- 'PersistValue's that would be supplied to the database for @?@ placeholders.+--+-- @since 3.1.1+renderQueryDelete+    :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)+    => SqlQuery a+    -- ^ The SQL query you want to render.+    -> R.ReaderT backend m (T.Text, [PersistValue])+renderQueryDelete = renderQueryToText DELETE++-- | Renders a 'SqlQuery' into a 'Text' value along with the list of+-- 'PersistValue's that would be supplied to the database for @?@ placeholders.+--+-- @since 3.1.1+renderQueryUpdate+    :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)+    => SqlQuery a+    -- ^ The SQL query you want to render.+    -> R.ReaderT backend m (T.Text, [PersistValue])+renderQueryUpdate = renderQueryToText UPDATE++-- | Renders a 'SqlQuery' into a 'Text' value along with the list of+-- 'PersistValue's that would be supplied to the database for @?@ placeholders.+--+-- @since 3.1.1+renderQueryInsertInto+    :: (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m)+    => SqlQuery a+    -- ^ The SQL query you want to render.+    -> R.ReaderT backend m (T.Text, [PersistValue])+renderQueryInsertInto = renderQueryToText INSERT_INTO++-- | (Internal) Mode of query being converted by 'toRawSql'.+data Mode+    = SELECT+    | DELETE+    | UPDATE+    | INSERT_INTO++uncommas :: [TLB.Builder] -> TLB.Builder+uncommas = intersperseB ", "++intersperseB :: TLB.Builder -> [TLB.Builder] -> TLB.Builder+intersperseB a = mconcat . intersperse a . filter (/= mempty)++uncommas' :: Monoid a => [(TLB.Builder, a)] -> (TLB.Builder, a)+uncommas' = (uncommas *** mconcat) . unzip++makeCte :: IdentInfo -> [CommonTableExpressionClause] -> (TLB.Builder, [PersistValue])+makeCte info cteClauses =+  let+    withCteText+        | hasRecursive = "WITH RECURSIVE "+        | otherwise = "WITH "+      where+        hasRecursive =+            elem RecursiveCommonTableExpression+            $ fmap (\(CommonTableExpressionClause cteKind _ _) -> cteKind)+            $ cteClauses++    cteClauseToText (CommonTableExpressionClause _ cteIdent cteFn) =+        first+            (\tlb -> useIdent info cteIdent <> " AS " <> parens tlb)+            (cteFn info)++    cteBody =+        mconcat+        $ intersperse (",\n", mempty)+        $ fmap cteClauseToText cteClauses+  in+    case cteClauses of+        [] ->+            mempty+        _ ->+          first (\tlb -> withCteText <> tlb <> "\n") cteBody++makeInsertInto :: SqlSelect a r => IdentInfo -> Mode -> a -> (TLB.Builder, [PersistValue])+makeInsertInto info INSERT_INTO ret = sqlInsertInto info ret+makeInsertInto _    _           _   = mempty++makeSelect :: SqlSelect a r => IdentInfo -> Mode -> DistinctClause -> a -> (TLB.Builder, [PersistValue])+makeSelect info mode_ distinctClause ret = process mode_+  where+    process mode =+        case mode of+            SELECT      -> withCols selectKind+            DELETE      -> plain "DELETE "+            UPDATE      -> plain "UPDATE "+            INSERT_INTO -> process SELECT+    selectKind =+        case distinctClause of+            DistinctAll      -> ("SELECT ", [])+            DistinctStandard -> ("SELECT DISTINCT ", [])+            DistinctOn exprs ->+                first (("SELECT DISTINCT ON (" <>) . (<> ") "))+                $ uncommas' (processExpr <$> exprs)+      where+        processExpr (EDistinctOn f) = materializeExpr info f+    withCols v = v <> sqlSelectCols info ret+    plain    v = (v, [])++makeFrom+    :: IdentInfo+    -> Mode+    -> [FromClause]+    -> (TLB.Builder, [PersistValue])+makeFrom _    _    [] = mempty+makeFrom info mode fs = ret+  where+    ret =+        case collectOnClauses (fst info) fs of+            Left expr -> throw $ mkExc expr+            Right fs' -> keyword $ uncommas' (map (mk Never) fs')+    keyword =+        case mode of+            UPDATE -> id+            _      -> first ("\nFROM " <>)++    mk _     (FromStart i def) = base i def+    mk paren (FromJoin lhs kind rhs monClause) =+        first (parensM paren) $+        mconcat [ mk Never lhs+                , (fromKind kind, mempty)+                , mk Parens rhs+                , maybe mempty makeOnClause monClause+                ]+    mk _ (OnClause _) = throw (UnexpectedCaseErr MakeFromError)+    mk _ (FromQuery ident f subqueryType) =+        let (queryText, queryVals) = f info+            lateralKeyword =+              case subqueryType of+                NormalSubQuery -> ""+                LateralSubQuery -> "LATERAL "+        in+            ( lateralKeyword <> (parens queryText) <> " AS " <> useIdent info ident+            , queryVals+            )+    mk _ (FromIdent ident) =+        (useIdent info ident, mempty)++    base ident@(I identText) def =+        let db@(DBName dbText) = entityDB def+        in ( fromDBName info db <>+                 if dbText == identText+                 then mempty+                 else " AS " <> useIdent info ident+           , mempty+           )++    fromKind InnerJoinKind      = " INNER JOIN "+    fromKind CrossJoinKind      = " CROSS JOIN "+    fromKind LeftOuterJoinKind  = " LEFT OUTER JOIN "+    fromKind RightOuterJoinKind = " RIGHT OUTER JOIN "+    fromKind FullOuterJoinKind  = " FULL OUTER JOIN "++    makeOnClause (ERaw _ f)        = first (" ON " <>) (f info)+    makeOnClause (ECompositeKey _) = throw (CompositeKeyErr MakeOnClauseError)+    makeOnClause (EAliasedValue _ _) = throw (AliasedValueErr MakeOnClauseError)+    makeOnClause (EValueReference _ _) = throw (AliasedValueErr MakeOnClauseError)++    mkExc :: SqlExpr (Value Bool) -> OnClauseWithoutMatchingJoinException+    mkExc (ERaw _ f) =+        OnClauseWithoutMatchingJoinException $+            TL.unpack $ TLB.toLazyText $ fst (f info)+    mkExc (ECompositeKey _) = throw (CompositeKeyErr MakeExcError)+    mkExc (EAliasedValue _ _) = throw (AliasedValueErr MakeExcError)+    mkExc (EValueReference _ _) = throw (AliasedValueErr MakeExcError)++makeSet :: IdentInfo -> [SetClause] -> (TLB.Builder, [PersistValue])+makeSet _    [] = mempty+makeSet info os = first ("\nSET " <>) . uncommas' $ concatMap mk os+  where+    mk (SetClause (ERaw _ f))             = [f info]+    mk (SetClause (ECompositeKey _))      = throw (CompositeKeyErr MakeSetError) -- FIXME+    mk (SetClause (EAliasedValue i _))    = [aliasedValueIdentToRawSql i info]+    mk (SetClause (EValueReference i i')) = [valueReferenceToRawSql i i' info]++makeWhere :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue])+makeWhere _    NoWhere                       = mempty+makeWhere info (Where v) = first ("\nWHERE " <>) $ x info+  where+    x =+        case v of+            ERaw _ f             -> f+            EAliasedValue i _    -> aliasedValueIdentToRawSql i+            EValueReference i i' -> valueReferenceToRawSql i i'+            ECompositeKey _      -> throw (CompositeKeyErr MakeWhereError)++makeGroupBy :: IdentInfo -> GroupByClause -> (TLB.Builder, [PersistValue])+makeGroupBy _ (GroupBy []) = (mempty, [])+makeGroupBy info (GroupBy fields) = first ("\nGROUP BY " <>) build+  where+    build :: (TLB.Builder, [PersistValue])+    build = uncommas' $ map match fields++    match :: SomeValue -> (TLB.Builder, [PersistValue])+    match (SomeValue (ERaw _ f)) = f info+    match (SomeValue (ECompositeKey f)) = (mconcat $ f info, mempty)+    match (SomeValue (EAliasedValue i _)) = aliasedValueIdentToRawSql i info+    match (SomeValue (EValueReference i i')) = valueReferenceToRawSql i i' info++makeHaving :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue])+makeHaving _    NoWhere   = mempty+makeHaving info (Where v) = first ("\nHAVING " <>) $ x info+  where+    x =+        case v of+            ERaw _ f             -> f+            EAliasedValue i _    -> aliasedValueIdentToRawSql i+            EValueReference i i' -> valueReferenceToRawSql i i'+            ECompositeKey _      -> throw (CompositeKeyErr MakeHavingError)++-- makeHaving, makeWhere and makeOrderBy+makeOrderByNoNewline+    :: IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue])+makeOrderByNoNewline _    [] = mempty+makeOrderByNoNewline info os = first ("ORDER BY " <>) . uncommas' $ concatMap mk os+  where+    mk :: OrderByClause -> [(TLB.Builder, [PersistValue])]+    mk (EOrderBy t (ECompositeKey f)) =+        let fs = f info+            vals = repeat []+        in zip (map (<> orderByType t) fs) vals+    mk (EOrderBy t v) =+        let x =+                case v of+                    ERaw p f -> (first (parensM p)) . f+                    EAliasedValue i _ -> aliasedValueIdentToRawSql i+                    EValueReference i i' -> valueReferenceToRawSql i i'+                    ECompositeKey _ -> undefined -- defined above+        in [ first (<> orderByType t) $ x info ]+    mk EOrderRandom = [first (<> "RANDOM()") mempty]++    orderByType ASC  = " ASC"+    orderByType DESC = " DESC"++makeOrderBy :: IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue])+makeOrderBy _ [] = mempty+makeOrderBy info is =+    let (tlb, vals) = makeOrderByNoNewline info is+    in ("\n" <> tlb, vals)++{-# DEPRECATED EOrderRandom "Since 2.6.0: `rand` ordering function is not uniform across all databases! To avoid accidental partiality it will be removed in the next major version." #-}++makeLimit :: IdentInfo -> LimitClause -> [OrderByClause] -> (TLB.Builder, [PersistValue])+makeLimit (conn, _) (Limit ml mo) orderByClauses =+    let limitRaw = connLimitOffset conn (v ml, v mo) hasOrderClause "\n"+        hasOrderClause = not (null orderByClauses)+        v = maybe 0 fromIntegral+    in (TLB.fromText limitRaw, mempty)++makeLocking :: LockingClause -> (TLB.Builder, [PersistValue])+makeLocking = flip (,) [] . maybe mempty toTLB . Monoid.getLast+  where+    toTLB ForUpdate           = "\nFOR UPDATE"+    toTLB ForUpdateSkipLocked = "\nFOR UPDATE SKIP LOCKED"+    toTLB ForShare            = "\nFOR SHARE"+    toTLB LockInShareMode     = "\nLOCK IN SHARE MODE"++parens :: TLB.Builder -> TLB.Builder+parens b = "(" <> (b <> ")")++aliasedValueIdentToRawSql :: Ident -> IdentInfo -> (TLB.Builder, [PersistValue])+aliasedValueIdentToRawSql i info = (useIdent info i, mempty)++valueReferenceToRawSql ::  Ident -> (IdentInfo -> Ident) -> IdentInfo -> (TLB.Builder, [PersistValue])+valueReferenceToRawSql sourceIdent columnIdentF info =+    (useIdent info sourceIdent <> "." <> useIdent info (columnIdentF info), mempty)++aliasedEntityColumnIdent :: Ident -> FieldDef -> Ident+aliasedEntityColumnIdent (I baseIdent) field =+    I (baseIdent <> "_" <> (unDBName $ fieldDB field))++aliasedColumnName :: Ident -> IdentInfo -> T.Text -> TLB.Builder+aliasedColumnName (I baseIdent) info columnName =+    useIdent info (I (baseIdent <> "_" <> columnName))++-- | (Internal) Class for mapping results coming from 'SqlQuery'+-- into actual results.+--+-- This looks very similar to @RawSql@, and it is!  However,+-- there are some crucial differences and ultimately they're+-- different classes.+class SqlSelect a r | a -> r, r -> a where+    -- | Creates the variable part of the @SELECT@ query and+    -- returns the list of 'PersistValue's that will be given to+    -- 'rawQuery'.+    sqlSelectCols :: IdentInfo -> a -> (TLB.Builder, [PersistValue])++    -- | Number of columns that will be consumed.+    sqlSelectColCount :: Proxy a -> Int++    -- | Transform a row of the result into the data type.+    sqlSelectProcessRow :: [PersistValue] -> Either T.Text r++    -- | Create @INSERT INTO@ clause instead.+    sqlInsertInto :: IdentInfo -> a -> (TLB.Builder, [PersistValue])+    sqlInsertInto = throw (UnexpectedCaseErr UnsupportedSqlInsertIntoType)+++-- | @INSERT INTO@ hack.+instance SqlSelect (SqlExpr InsertFinal) InsertFinal where+    sqlInsertInto info (EInsertFinal (EInsert p _)) =+        let fields =+                uncommas $+                map (fromDBName info . fieldDB) $+                entityFields $+                entityDef p+            table  =+                fromDBName info . entityDB . entityDef $ p+        in+            ("INSERT INTO " <> table <> parens fields <> "\n", [])+    sqlSelectCols info (EInsertFinal (EInsert _ f)) = f info+    sqlSelectColCount   = const 0+    sqlSelectProcessRow =+      const (Right (throw (UnexpectedCaseErr InsertionFinalError)))++-- | Not useful for 'select', but used for 'update' and 'delete'.+instance SqlSelect () () where+    sqlSelectCols _ _ = ("1", [])+    sqlSelectColCount _ = 1+    sqlSelectProcessRow _ = Right ()++unescapedColumnNames :: EntityDef -> [DBName]+unescapedColumnNames ent =+    (if hasCompositeKey ent then id else ( fieldDB (entityId ent) :))+    $ map fieldDB (entityFields ent)++-- | You may return an 'Entity' from a 'select' query.+instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where+    sqlSelectCols info expr@(EEntity ident) = ret+      where+        process ed = uncommas $+                     map ((name <>) . TLB.fromText) $+                     entityColumnNames ed (fst info)+        -- 'name' is the biggest difference between 'RawSql' and+        -- 'SqlSelect'.  We automatically create names for tables+        -- (since it's not the user who's writing the FROM+        -- clause), while 'rawSql' assumes that it's just the+        -- name of the table (which doesn't allow self-joins, for+        -- example).+        name = useIdent info ident <> "."+        ret = let ed = entityDef $ getEntityVal $ return expr+              in (process ed, mempty)+    sqlSelectCols info expr@(EAliasedEntity aliasIdent tableIdent) = ret+      where+        process ed = uncommas $+                     map ((name <>) . aliasName) $+                     unescapedColumnNames ed+        aliasName columnName = (fromDBName info columnName) <> " AS " <> aliasedColumnName aliasIdent info (unDBName columnName)+        name = useIdent info tableIdent <> "."+        ret = let ed = entityDef $ getEntityVal $ return expr+              in (process ed, mempty)+    sqlSelectCols info expr@(EAliasedEntityReference sourceIdent baseIdent) = ret+      where+        process ed = uncommas $+                     map ((name <>) . aliasedColumnName baseIdent info . unDBName) $+                     unescapedColumnNames ed+        name = useIdent info sourceIdent <> "."+        ret = let ed = entityDef $ getEntityVal $ return expr+              in (process ed, mempty)+    sqlSelectColCount = entityColumnCount . entityDef . getEntityVal+    sqlSelectProcessRow = parseEntityValues ed+      where+        ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity a)))++getEntityVal :: Proxy (SqlExpr (Entity a)) -> Proxy a+getEntityVal = const Proxy++-- | You may return a possibly-@NULL@ 'Entity' from a 'select' query.+instance PersistEntity a => SqlSelect (SqlExpr (Maybe (Entity a))) (Maybe (Entity a)) where+    sqlSelectCols info (EMaybe ent) = sqlSelectCols info ent+    sqlSelectColCount = sqlSelectColCount . fromEMaybe+      where+        fromEMaybe :: Proxy (SqlExpr (Maybe e)) -> Proxy (SqlExpr e)+        fromEMaybe = const Proxy+    sqlSelectProcessRow cols+        | all (== PersistNull) cols = return Nothing+        | otherwise                 = Just <$> sqlSelectProcessRow cols+++-- | You may return any single value (i.e. a single column) from+-- a 'select' query.+instance PersistField a => SqlSelect (SqlExpr (Value a)) (Value a) where+    sqlSelectCols = materializeExpr+    sqlSelectColCount = const 1+    sqlSelectProcessRow [pv] = Value <$> fromPersistValue pv+    sqlSelectProcessRow pvs  = Value <$> fromPersistValue (PersistList pvs)++-- | Materialize a @SqlExpr (Value a)@.+materializeExpr :: IdentInfo -> SqlExpr (Value a) -> (TLB.Builder, [PersistValue])+materializeExpr info (ERaw p f) =+    let (b, vals) = f info+    in (parensM p b, vals)+materializeExpr info (ECompositeKey f) =+    let bs = f info+    in (uncommas $ map (parensM Parens) bs, [])+materializeExpr info (EAliasedValue ident x) =+    let (b, vals) = materializeExpr info x+    in (b <> " AS " <> (useIdent info ident), vals)+materializeExpr info (EValueReference sourceIdent columnIdent) =+    valueReferenceToRawSql sourceIdent columnIdent info++-- | You may return tuples (up to 16-tuples) and tuples of tuples+-- from a 'select' query.+instance (SqlSelect a ra, SqlSelect b rb) => SqlSelect (a, b) (ra, rb) where+    sqlSelectCols esc (a, b) =+        uncommas'+            [ sqlSelectCols esc a+            , sqlSelectCols esc b+            ]+    sqlSelectColCount = uncurry (+) . (sqlSelectColCount *** sqlSelectColCount) . fromTuple+      where+        fromTuple :: Proxy (a,b) -> (Proxy a, Proxy b)+        fromTuple = const (Proxy, Proxy)+    sqlSelectProcessRow =+      let x = getType processRow+          getType :: SqlSelect a r => (z -> Either y (r,x)) -> Proxy a+          getType = const Proxy++          colCountFst = sqlSelectColCount x++          processRow row =+              let (rowFst, rowSnd) = splitAt colCountFst row+              in (,) <$> sqlSelectProcessRow rowFst+                     <*> sqlSelectProcessRow rowSnd++      in colCountFst `seq` processRow+         -- Avoids recalculating 'colCountFst'.++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         ) => SqlSelect (a, b, c) (ra, rb, rc) where+  sqlSelectCols esc (a, b, c) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      ]+  sqlSelectColCount   = sqlSelectColCount . from3P+  sqlSelectProcessRow = fmap to3 . sqlSelectProcessRow++from3P :: Proxy (a,b,c) -> Proxy ((a,b),c)+from3P = const Proxy++from3 :: (a,b,c) -> ((a,b),c)+from3 (a,b,c) = ((a,b),c)++to3 :: ((a,b),c) -> (a,b,c)+to3 ((a,b),c) = (a,b,c)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         ) => SqlSelect (a, b, c, d) (ra, rb, rc, rd) where+  sqlSelectCols esc (a, b, c, d) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      ]+  sqlSelectColCount   = sqlSelectColCount . from4P+  sqlSelectProcessRow = fmap to4 . sqlSelectProcessRow++from4P :: Proxy (a,b,c,d) -> Proxy ((a,b),(c,d))+from4P = const Proxy++from4 :: (a,b,c,d) -> ((a,b),(c,d))+from4 (a,b,c,d) = ((a,b),(c,d))++to4 :: ((a,b),(c,d)) -> (a,b,c,d)+to4 ((a,b),(c,d)) = (a,b,c,d)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         ) => SqlSelect (a, b, c, d, e) (ra, rb, rc, rd, re) where+  sqlSelectCols esc (a, b, c, d, e) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      ]+  sqlSelectColCount   = sqlSelectColCount . from5P+  sqlSelectProcessRow = fmap to5 . sqlSelectProcessRow++from5P :: Proxy (a,b,c,d,e) -> Proxy ((a,b),(c,d),e)+from5P = const Proxy++from5 :: (a,b,c,d,e) -> ((a,b),(c,d),e)+from5 (a,b,c,d,e) = ((a,b),(c,d),e)++to5 :: ((a,b),(c,d),e) -> (a,b,c,d,e)+to5 ((a,b),(c,d),e) = (a,b,c,d,e)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         ) => SqlSelect (a, b, c, d, e, f) (ra, rb, rc, rd, re, rf) where+  sqlSelectCols esc (a, b, c, d, e, f) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      ]+  sqlSelectColCount   = sqlSelectColCount . from6P+  sqlSelectProcessRow = fmap to6 . sqlSelectProcessRow++from6P :: Proxy (a,b,c,d,e,f) -> Proxy ((a,b),(c,d),(e,f))+from6P = const Proxy++from6 :: (a,b,c,d,e,f) -> ((a,b),(c,d),(e,f))+from6 (a,b,c,d,e,f) = ((a,b),(c,d),(e,f))++to6 :: ((a,b),(c,d),(e,f)) -> (a,b,c,d,e,f)+to6 ((a,b),(c,d),(e,f)) = (a,b,c,d,e,f)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         ) => SqlSelect (a, b, c, d, e, f, g) (ra, rb, rc, rd, re, rf, rg) where+  sqlSelectCols esc (a, b, c, d, e, f, g) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      ]+  sqlSelectColCount   = sqlSelectColCount . from7P+  sqlSelectProcessRow = fmap to7 . sqlSelectProcessRow++from7P :: Proxy (a,b,c,d,e,f,g) -> Proxy ((a,b),(c,d),(e,f),g)+from7P = const Proxy++from7 :: (a,b,c,d,e,f,g) -> ((a,b),(c,d),(e,f),g)+from7 (a,b,c,d,e,f,g) = ((a,b),(c,d),(e,f),g)++to7 :: ((a,b),(c,d),(e,f),g) -> (a,b,c,d,e,f,g)+to7 ((a,b),(c,d),(e,f),g) = (a,b,c,d,e,f,g)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         ) => SqlSelect (a, b, c, d, e, f, g, h) (ra, rb, rc, rd, re, rf, rg, rh) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      ]+  sqlSelectColCount   = sqlSelectColCount . from8P+  sqlSelectProcessRow = fmap to8 . sqlSelectProcessRow++from8P :: Proxy (a,b,c,d,e,f,g,h) -> Proxy ((a,b),(c,d),(e,f),(g,h))+from8P = const Proxy++from8 :: (a,b,c,d,e,f,g,h) -> ((a,b),(c,d),(e,f),(g,h))+from8 (a,b,c,d,e,f,g,h) = ((a,b),(c,d),(e,f),(g,h))++to8 :: ((a,b),(c,d),(e,f),(g,h)) -> (a,b,c,d,e,f,g,h)+to8 ((a,b),(c,d),(e,f),(g,h)) = (a,b,c,d,e,f,g,h)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         ) => SqlSelect (a, b, c, d, e, f, g, h, i) (ra, rb, rc, rd, re, rf, rg, rh, ri) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      ]+  sqlSelectColCount   = sqlSelectColCount . from9P+  sqlSelectProcessRow = fmap to9 . sqlSelectProcessRow++from9P :: Proxy (a,b,c,d,e,f,g,h,i) -> Proxy ((a,b),(c,d),(e,f),(g,h),i)+from9P = const Proxy++from9 :: (a,b,c,d,e,f,g,h,i) -> ((a,b),(c,d),(e,f),(g,h),i)+from9 (a,b,c,d,e,f,g,h,i) = ((a,b),(c,d),(e,f),(g,h),i)++to9 :: ((a,b),(c,d),(e,f),(g,h),i) -> (a,b,c,d,e,f,g,h,i)+to9 ((a,b),(c,d),(e,f),(g,h),i) = (a,b,c,d,e,f,g,h,i)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      ]+  sqlSelectColCount   = sqlSelectColCount . from10P+  sqlSelectProcessRow = fmap to10 . sqlSelectProcessRow++from10P :: Proxy (a,b,c,d,e,f,g,h,i,j) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j))+from10P = const Proxy++from10 :: (a,b,c,d,e,f,g,h,i,j) -> ((a,b),(c,d),(e,f),(g,h),(i,j))+from10 (a,b,c,d,e,f,g,h,i,j) = ((a,b),(c,d),(e,f),(g,h),(i,j))++to10 :: ((a,b),(c,d),(e,f),(g,h),(i,j)) -> (a,b,c,d,e,f,g,h,i,j)+to10 ((a,b),(c,d),(e,f),(g,h),(i,j)) = (a,b,c,d,e,f,g,h,i,j)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      ]+  sqlSelectColCount   = sqlSelectColCount . from11P+  sqlSelectProcessRow = fmap to11 . sqlSelectProcessRow++from11P :: Proxy (a,b,c,d,e,f,g,h,i,j,k) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),k)+from11P = const Proxy++to11 :: ((a,b),(c,d),(e,f),(g,h),(i,j),k) -> (a,b,c,d,e,f,g,h,i,j,k)+to11 ((a,b),(c,d),(e,f),(g,h),(i,j),k) = (a,b,c,d,e,f,g,h,i,j,k)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         , SqlSelect l rl+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      , sqlSelectCols esc l+      ]+  sqlSelectColCount   = sqlSelectColCount . from12P+  sqlSelectProcessRow = fmap to12 . sqlSelectProcessRow++from12P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l))+from12P = const Proxy++to12 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l)) -> (a,b,c,d,e,f,g,h,i,j,k,l)+to12 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l)) = (a,b,c,d,e,f,g,h,i,j,k,l)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         , SqlSelect l rl+         , SqlSelect m rm+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      , sqlSelectCols esc l+      , sqlSelectCols esc m+      ]+  sqlSelectColCount   = sqlSelectColCount . from13P+  sqlSelectProcessRow = fmap to13 . sqlSelectProcessRow++from13P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m)+from13P = const Proxy++to13 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m) -> (a,b,c,d,e,f,g,h,i,j,k,l,m)+to13 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),m) = (a,b,c,d,e,f,g,h,i,j,k,l,m)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         , SqlSelect l rl+         , SqlSelect m rm+         , SqlSelect n rn+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      , sqlSelectCols esc l+      , sqlSelectCols esc m+      , sqlSelectCols esc n+      ]+  sqlSelectColCount   = sqlSelectColCount . from14P+  sqlSelectProcessRow = fmap to14 . sqlSelectProcessRow++from14P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n))+from14P = const Proxy++to14 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n)) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n)+to14 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n)) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         , SqlSelect l rl+         , SqlSelect m rm+         , SqlSelect n rn+         , SqlSelect o ro+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn, ro) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      , sqlSelectCols esc l+      , sqlSelectCols esc m+      , sqlSelectCols esc n+      , sqlSelectCols esc o+      ]+  sqlSelectColCount   = sqlSelectColCount . from15P+  sqlSelectProcessRow = fmap to15 . sqlSelectProcessRow++from15P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n, o) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o)+from15P = const Proxy++to15 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)+to15 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),o) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)++instance ( SqlSelect a ra+         , SqlSelect b rb+         , SqlSelect c rc+         , SqlSelect d rd+         , SqlSelect e re+         , SqlSelect f rf+         , SqlSelect g rg+         , SqlSelect h rh+         , SqlSelect i ri+         , SqlSelect j rj+         , SqlSelect k rk+         , SqlSelect l rl+         , SqlSelect m rm+         , SqlSelect n rn+         , SqlSelect o ro+         , SqlSelect p rp+         ) => SqlSelect (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn, ro, rp) where+  sqlSelectCols esc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =+    uncommas'+      [ sqlSelectCols esc a+      , sqlSelectCols esc b+      , sqlSelectCols esc c+      , sqlSelectCols esc d+      , sqlSelectCols esc e+      , sqlSelectCols esc f+      , sqlSelectCols esc g+      , sqlSelectCols esc h+      , sqlSelectCols esc i+      , sqlSelectCols esc j+      , sqlSelectCols esc k+      , sqlSelectCols esc l+      , sqlSelectCols esc m+      , sqlSelectCols esc n+      , sqlSelectCols esc o+      , sqlSelectCols esc p+      ]+  sqlSelectColCount   = sqlSelectColCount . from16P+  sqlSelectProcessRow = fmap to16 . sqlSelectProcessRow++from16P :: Proxy (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) -> Proxy ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p))+from16P = const Proxy++to16 :: ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p)) -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)+to16 ((a,b),(c,d),(e,f),(g,h),(i,j),(k,l),(m,n),(o,p)) = (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)++-- | Insert a 'PersistField' for every selected value.+--+-- @since 2.4.2+insertSelect+    :: (MonadIO m, PersistEntity a)+    => SqlQuery (SqlExpr (Insertion a))+    -> SqlWriteT m ()+insertSelect = void . insertSelectCount++-- | Insert a 'PersistField' for every selected value, return the count afterward+insertSelectCount+    :: (MonadIO m, PersistEntity a)+    => SqlQuery (SqlExpr (Insertion a))+    -> SqlWriteT m Int64+insertSelectCount = rawEsqueleto INSERT_INTO . fmap EInsertFinal++-- | Renders an expression into 'Text'. Only useful for creating a textual+-- representation of the clauses passed to an "On" clause.+--+-- @since 3.2.0+renderExpr :: SqlBackend -> SqlExpr (Value Bool) -> T.Text+renderExpr sqlBackend e = case e of+    ERaw _ mkBuilderValues -> do+        let (builder, _) = mkBuilderValues (sqlBackend, initialIdentState)+         in (builderToText builder)+    ECompositeKey mkInfo ->+        throw+          . RenderExprUnexpectedECompositeKey+          . builderToText+          . mconcat+          . mkInfo+          $ (sqlBackend, initialIdentState)+    EAliasedValue i _   ->+        builderToText $ useIdent (sqlBackend, initialIdentState) i+    EValueReference i i' ->+        let (builder, _) = valueReferenceToRawSql i i' (sqlBackend, initialIdentState)+         in (builderToText builder)++-- | An exception thrown by 'RenderExpr' - it's not designed to handle composite+-- keys, and will blow up if you give it one.+--+-- @since 3.2.0+data RenderExprException = RenderExprUnexpectedECompositeKey T.Text+    deriving Show++-- |+--+-- @since 3.2.0+instance Exception RenderExprException++-- | @valkey i = 'val' . 'toSqlKey'@+-- (<https://github.com/prowdsponsor/esqueleto/issues/9>).+valkey+    :: (ToBackendKey SqlBackend entity, PersistField (Key entity))+    => Int64 -> SqlExpr (Value (Key entity))+valkey = val . toSqlKey++-- | @valJ@ is like @val@ but for something that is already a @Value@. The use+-- case it was written for was, given a @Value@ lift the @Key@ for that @Value@+-- into the query expression in a type safe way. However, the implementation is+-- more generic than that so we call it @valJ@.+--+-- Its important to note that the input entity and the output entity are+-- constrained to be the same by the type signature on the function+-- (<https://github.com/prowdsponsor/esqueleto/pull/69>).+--+-- @since 1.4.2+valJ+    :: (PersistField (Key entity))+    => Value (Key entity)+    -> SqlExpr (Value (Key entity))+valJ = val . unValue+++-- | Synonym for 'Database.Persist.Store.delete' that does not+-- clash with @esqueleto@'s 'delete'.+deleteKey+    ::+    ( PersistStore backend+    , BaseBackend backend ~ PersistEntityBackend val+    , MonadIO m+    , PersistEntity val+    )+    => Key val+    -> R.ReaderT backend m ()+deleteKey = Database.Persist.delete++-- | Avoid N+1 queries and join entities into a map structure+-- @+-- getFoosAndNestedBarsFromParent :: ParentId -> (Map (Key Foo) (Foo, [Maybe (Entity Bar)]))+-- getFoosAndNestedBarsFromParent parentId = 'fmap' associateJoin $ 'select' $+-- 'from' $ \\(foo `'LeftOuterJoin`` bar) -> do+--   'on' (bar '?.' BarFooId '==.' foo '^.' FooId)+--   'where_' (foo '^.' FooParentId '==.' 'val' parentId)+--   'pure' (foo, bar)+-- @+--+-- @since 3.1.2+associateJoin+    :: forall e1 e0.  Ord (Key e0)+    => [(Entity e0, e1)]+    -> Map.Map (Key e0) (e0, [e1])+associateJoin = foldr f start+  where+    start = Map.empty+    f (one, many) =+        Map.insertWith+            (\(oneOld, manyOld) (_, manyNew) -> (oneOld, manyNew ++ manyOld ))+            (entityKey one)+            (entityVal one, [many])
src/Database/Esqueleto/Internal/Language.hs view
@@ -1,69 +1,140 @@-{-# LANGUAGE DeriveDataTypeable-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , MultiParamTypeClasses-           , TypeFamilies-           , UndecidableInstances-           , GADTs- #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+ -- | This is an internal module, anything exported by this module -- may change without a major version bump.  Please use only -- "Database.Esqueleto" if possible.+--+-- This module is deprecated as of 3.4.0.1, and will be removed in 3.5.0.0. module Database.Esqueleto.Internal.Language-  ( -- * The pretty face-    from-  , Value(..)-  , ValueList(..)-  , SomeValue(..)-  , ToSomeValues(..)-  , InnerJoin(..)-  , CrossJoin(..)-  , LeftOuterJoin(..)-  , RightOuterJoin(..)-  , FullOuterJoin(..)-  , OnClauseWithoutMatchingJoinException(..)-  , OrderBy-  , DistinctOn-  , Update-  , Insertion-  , LockingKind(..)-  , SqlString-  , ToBaseId(..)-    -- * The guts-  , JoinKind(..)-  , IsJoinKind(..)-  , BackendCompatible(..)-  , PreprocessedFrom-  , From-  , FromPreprocess-  , when_-  , then_-  , else_-  , where_, on, groupBy, orderBy, rand, asc, desc, limit, offset-             , distinct, distinctOn, don, distinctOnOrderBy, having, locking-             , sub_select, (^.), (?.)-             , val, isNothing, just, nothing, joinV, withNonNull-             , countRows, count, countDistinct-             , not_, (==.), (>=.), (>.), (<=.), (<.), (!=.), (&&.), (||.)-             , between, (+.), (-.), (/.), (*.)-             , random_, round_, ceiling_, floor_-             , min_, max_, sum_, avg_, castNum, castNumM-             , coalesce, coalesceDefault-             , lower_, upper_, trim_, ltrim_, rtrim_, length_, left_, right_-             , like, ilike, (%), concat_, (++.), castString-             , subList_select, valList, justList-             , in_, notIn, exists, notExists-             , set, (=.), (+=.), (-=.), (*=.), (/=.)-             , case_, toBaseId, (<#), (<&>)-  , subSelect-  , subSelectMaybe-  , subSelectCount-  , subSelectList-  , subSelectForeign-  , subSelectUnsafe-  ) where+    {-# DEPRECATED "Use Database.Esqueleto.Internal.Internal instead. This module will be removed in 3.5.0.0 " #-}+    ( -- * The pretty face+      from+    , Value(..)+    , ValueList(..)+    , SomeValue(..)+    , ToSomeValues(..)+    , InnerJoin(..)+    , CrossJoin(..)+    , LeftOuterJoin(..)+    , RightOuterJoin(..)+    , FullOuterJoin(..)+    , OnClauseWithoutMatchingJoinException(..)+    , OrderBy+    , DistinctOn+    , Update+    , Insertion+    , LockingKind(..)+    , SqlString+    , ToBaseId(..)+      -- * The guts+    , JoinKind(..)+    , IsJoinKind(..)+    , BackendCompatible(..)+    , PreprocessedFrom+    , From+    , FromPreprocess+    , when_+    , then_+    , else_+    , where_+    , on+    , groupBy+    , orderBy+    , rand+    , asc+    , desc+    , limit+    , offset+    , distinct+    , distinctOn+    , don+    , distinctOnOrderBy+    , having+    , locking+    , sub_select+    , (^.)+    , (?.)+    , val+    , isNothing+    , just+    , nothing+    , joinV+    , withNonNull+    , countRows+    , count+    , countDistinct+    , not_+    , (==.)+    , (>=.)+    , (>.)+    , (<=.)+    , (<.)+    , (!=.)+    , (&&.)+    , (||.)+    , between+    , (+.)+    , (-.)+    , (/.)+    , (*.)+    , random_+    , round_+    , ceiling_+    , floor_+    , min_+    , max_+    , sum_+    , avg_+    , castNum+    , castNumM+    , coalesce+    , coalesceDefault+    , lower_+    , upper_+    , trim_+    , ltrim_+    , rtrim_+    , length_+    , left_+    , right_+    , like+    , ilike+    , (%)+    , concat_+    , (++.)+    , castString+    , subList_select+    , valList+    , justList+    , in_+    , notIn+    , exists+    , notExists+    , set+    , (=.)+    , (+=.)+    , (-=.)+    , (*=.)+    , (/=.)+    , case_+    , toBaseId+    , (<#)+    , (<&>)+    , subSelect+    , subSelectMaybe+    , subSelectCount+    , subSelectList+    , subSelectForeign+    , subSelectUnsafe+    ) where -import Database.Esqueleto.Internal.PersistentImport import Database.Esqueleto.Internal.Internal+import Database.Esqueleto.Internal.PersistentImport
src/Database/Esqueleto/Internal/PersistentImport.hs view
@@ -3,148 +3,176 @@ module Database.Esqueleto.Internal.PersistentImport -- NOTE: switch back to a module export once https://gitlab.haskell.org/ghc/ghc/merge_requests/276 -- has been merged. See https://github.com/bitemyapp/esqueleto/issues/110 for more details-  ( toJsonText,-  entityIdFromJSON,-  entityIdToJSON,-  entityValues,-  fromPersistValueJSON,-  keyValueEntityFromJSON,-  keyValueEntityToJSON,-  toPersistValueJSON,-  selectKeys,-  belongsTo,-  belongsToJust,-  getEntity,-  getJust,-  getJustEntity,-  insertEntity,-  insertRecord,-  liftPersist,-  checkUnique,-  getByValue,-  insertBy,-  insertUniqueEntity,-  onlyUnique,-  replaceUnique,-  transactionSave,-  transactionUndo,-  defaultAttribute,-  mkColumns,-  getMigration,-  migrate,-  parseMigration,-  parseMigration',-  printMigration,-  runMigration,-  runMigrationSilent,-  runMigrationUnsafe,-  showMigration,-  decorateSQLWithLimitOffset,-  fieldDBName,-  fromSqlKey,-  getFieldName,-  getTableName,-  tableDBName,-  toSqlKey,-  withRawQuery,-  getStmtConn,-  rawExecute,-  rawExecuteCount,-  rawQuery,-  rawQueryRes,-  rawSql,-  askLogFunc,-  close',-  createSqlPool,-  liftSqlPersistMPool,-  runSqlConn,-  runSqlPersistM,-  runSqlPersistMPool,-  runSqlPool,-  withSqlConn,-  withSqlPool,-  readToUnknown,-  readToWrite,-  writeToUnknown,-  entityKeyFields,-  entityPrimary,-  fromPersistValueText,-  keyAndEntityFields,-  toEmbedEntityDef,-  PersistStore,-  PersistUnique,-  DeleteCascade(..),-  PersistConfig(..),-  BackendSpecificUpdate,-  Entity(..),-  PersistEntity(..),-  PersistField(..),-  SomePersistField(..),-  PersistQueryRead(..),-  PersistQueryWrite(..),-  BackendCompatible(..),-  BackendKey(..),-  HasPersistBackend(..),-  IsPersistBackend,-  PersistCore(..),-  PersistRecordBackend,-  PersistStoreRead(..),-  PersistStoreWrite(..),-  ToBackendKey(..),-  PersistUniqueRead(..),-  PersistUniqueWrite(..),-  PersistFieldSql(..),-  RawSql(..),-  CautiousMigration,-  Column(..),-  ConnectionPool,-  Migration,-  PersistentSqlException(..),-  Single(..),-  Sql,-  SqlPersistM,-  SqlPersistT,-  InsertSqlResult(..),-  IsSqlBackend,-  LogFunc,-  SqlBackend(..),-  SqlBackendCanRead,-  SqlBackendCanWrite,-  SqlReadBackend(..),-  SqlReadT,-  SqlWriteBackend(..),-  SqlWriteT,-  Statement(..),-  Attr,-  Checkmark(..),-  CompositeDef(..),-  DBName(..),-  EmbedEntityDef(..),-  EmbedFieldDef(..),-  EntityDef(..),-  ExtraLine,-  FieldDef(..),-  FieldType(..),-  ForeignDef(..),-  ForeignFieldDef,-  HaskellName(..),-  IsNullable(..),-  OnlyUniqueException(..),-  PersistException(..),-  PersistFilter(..),-  PersistUpdate(..),-  PersistValue(..),-  ReferenceDef(..),-  SqlType(..),-  UniqueDef(..),-  UpdateException(..),-  WhyNullable(..)-  ) where+    ( toJsonText,+    entityIdFromJSON,+    entityIdToJSON,+    entityValues,+    fromPersistValueJSON,+    keyValueEntityFromJSON,+    keyValueEntityToJSON,+    toPersistValueJSON,+    selectKeys,+    belongsTo,+    belongsToJust,+    getEntity,+    getJust,+    getJustEntity,+    insertEntity,+    insertRecord,+    liftPersist,+    checkUnique,+    getByValue,+    insertBy,+    insertUniqueEntity,+    onlyUnique,+    replaceUnique,+    transactionSave,+    transactionUndo,+    defaultAttribute,+    mkColumns,+    getMigration,+    migrate,+    parseMigration,+    parseMigration',+    printMigration,+    runMigration,+    runMigrationSilent,+    runMigrationUnsafe,+    showMigration,+    decorateSQLWithLimitOffset,+    fieldDBName,+    fromSqlKey,+    getFieldName,+    getTableName,+    tableDBName,+    toSqlKey,+    withRawQuery,+    getStmtConn,+    rawExecute,+    rawExecuteCount,+    rawQuery,+    rawQueryRes,+    rawSql,+    askLogFunc,+    close',+    createSqlPool,+    liftSqlPersistMPool,+    runSqlConn,+    runSqlPersistM,+    runSqlPersistMPool,+    runSqlPool,+    withSqlConn,+    withSqlPool,+    readToUnknown,+    readToWrite,+    writeToUnknown,+    entityKeyFields,+    entityPrimary,+    fromPersistValueText,+    keyAndEntityFields,+    toEmbedEntityDef,+    PersistStore,+    PersistUnique,+    DeleteCascade(..),+    PersistConfig(..),+    BackendSpecificUpdate,+    Entity(..),+    PersistEntity(..),+    PersistField(..),+    SomePersistField(..),+    PersistQueryRead(..),+    PersistQueryWrite(..),+    BackendCompatible(..),+    BackendKey(..),+    HasPersistBackend(..),+    IsPersistBackend,+    PersistCore(..),+    PersistRecordBackend,+    PersistStoreRead(..),+    PersistStoreWrite(..),+    ToBackendKey(..),+    PersistUniqueRead(..),+    PersistUniqueWrite(..),+    PersistFieldSql(..),+    RawSql(..),+    CautiousMigration,+    Column(..),+    ConnectionPool,+    Migration,+    PersistentSqlException(..),+    Single(..),+    Sql,+    SqlPersistM,+    SqlPersistT,+    InsertSqlResult(..),+    IsSqlBackend,+    LogFunc,+    SqlBackend(..),+    SqlBackendCanRead,+    SqlBackendCanWrite,+    SqlReadBackend(..),+    SqlReadT,+    SqlWriteBackend(..),+    SqlWriteT,+    Statement(..),+    Attr,+    Checkmark(..),+    CompositeDef(..),+    DBName(..),+    EmbedEntityDef(..),+    EmbedFieldDef(..),+    EntityDef(..),+    ExtraLine,+    FieldDef(..),+    FieldType(..),+    ForeignDef(..),+    ForeignFieldDef,+    HaskellName(..),+    IsNullable(..),+    OnlyUniqueException(..),+    PersistException(..),+    PersistFilter(..),+    PersistUpdate(..),+    PersistValue(..),+    ReferenceDef(..),+    SqlType(..),+    UniqueDef(..),+    UpdateException(..),+    WhyNullable(..)+    ) where  import Database.Persist.Sql hiding-  ( BackendSpecificFilter, Filter(..), PersistQuery, SelectOpt(..)-  , Update(..), delete, deleteWhereCount, updateWhereCount, selectList-  , selectKeysList, deleteCascadeWhere, (=.), (+=.), (-=.), (*=.), (/=.)-  , (==.), (!=.), (<.), (>.), (<=.), (>=.), (<-.), (/<-.), (||.)-  , listToJSON, mapToJSON, getPersistMap, limitOffsetOrder, selectSource-  , update , count )+       ( BackendSpecificFilter+       , Filter(..)+       , PersistQuery+       , SelectOpt(..)+       , Update(..)+       , count+       , delete+       , deleteCascadeWhere+       , deleteWhereCount+       , getPersistMap+       , limitOffsetOrder+       , listToJSON+       , mapToJSON+       , selectKeysList+       , selectList+       , selectSource+       , update+       , updateWhereCount+       , (!=.)+       , (*=.)+       , (+=.)+       , (-=.)+       , (/<-.)+       , (/=.)+       , (<-.)+       , (<.)+       , (<=.)+       , (=.)+       , (==.)+       , (>.)+       , (>=.)+       , (||.)+       , exists+       )
src/Database/Esqueleto/Internal/Sql.hs view
@@ -1,82 +1,78 @@-{-# LANGUAGE DeriveDataTypeable-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , MultiParamTypeClasses-           , TypeFamilies-           , UndecidableInstances-           , GADTs- #-}-{-# LANGUAGE ConstraintKinds-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , FunctionalDependencies-           , GADTs-           , MultiParamTypeClasses-           , OverloadedStrings-           , UndecidableInstances-           , ScopedTypeVariables-           , InstanceSigs-           , Rank2Types-           , CPP- #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++ -- | This is an internal module, anything exported by this module -- may change without a major version bump.  Please use only -- "Database.Esqueleto" if possible.+--+-- This module is deprecated as of 3.4.0.1, and will be removed in 3.5.0.0. module Database.Esqueleto.Internal.Sql-  ( -- * The pretty face-    SqlQuery-  , SqlExpr(..)-  , SqlEntity-  , select-  , selectSource-  , delete-  , deleteCount-  , update-  , updateCount-  , insertSelect-  , insertSelectCount-    -- * The guts-  , unsafeSqlCase-  , unsafeSqlBinOp-  , unsafeSqlBinOpComposite-  , unsafeSqlValue-  , unsafeSqlCastAs-  , unsafeSqlFunction-  , unsafeSqlExtractSubField-  , UnsafeSqlFunctionArgument-  , OrderByClause-  , rawSelectSource-  , runSource-  , rawEsqueleto-  , toRawSql-  , Mode(..)-  , NeedParens(..)-  , IdentState-  , renderExpr-  , initialIdentState-  , IdentInfo-  , SqlSelect(..)-  , veryUnsafeCoerceSqlExprValue-  , veryUnsafeCoerceSqlExprValueList-  -- * Helper functions-  , renderQueryToText-  , renderQuerySelect-  , renderQueryUpdate-  , renderQueryDelete-  , renderQueryInsertInto-  , makeOrderByNoNewline-  , uncommas'-  , parens-  , toArgList-  , builderToText-  , Ident(..)-  , valkey-  , valJ-  , deleteKey-  , associateJoin-  ) where+    {-# DEPRECATED "Use Database.Esqueleto.Internal.Internal instead. This module will be removed in 3.5.0.0 " #-}+    ( -- * The pretty face+      SqlQuery+    , SqlExpr(..)+    , SqlEntity+    , select+    , selectSource+    , delete+    , deleteCount+    , update+    , updateCount+    , insertSelect+    , insertSelectCount+      -- * The guts+    , unsafeSqlCase+    , unsafeSqlBinOp+    , unsafeSqlBinOpComposite+    , unsafeSqlValue+    , unsafeSqlCastAs+    , unsafeSqlFunction+    , unsafeSqlExtractSubField+    , UnsafeSqlFunctionArgument+    , OrderByClause+    , rawSelectSource+    , runSource+    , rawEsqueleto+    , toRawSql+    , Mode(..)+    , NeedParens(..)+    , IdentState+    , renderExpr+    , initialIdentState+    , IdentInfo+    , SqlSelect(..)+    , veryUnsafeCoerceSqlExprValue+    , veryUnsafeCoerceSqlExprValueList+    -- * Helper functions+    , renderQueryToText+    , renderQuerySelect+    , renderQueryUpdate+    , renderQueryDelete+    , renderQueryInsertInto+    , makeOrderByNoNewline+    , uncommas'+    , parens+    , toArgList+    , builderToText+    , Ident(..)+    , valkey+    , valJ+    , deleteKey+    , associateJoin+    ) where  import Database.Esqueleto.Internal.Internal
src/Database/Esqueleto/MySQL.hs view
@@ -1,14 +1,14 @@ {-# LANGUAGE OverloadedStrings #-}+ -- | This module contain MySQL-specific functions. ----- /Since: 2.2.8/+-- @since 2.2.8 module Database.Esqueleto.MySQL-  ( random_-  ) where+    ( random_+    ) where -import Database.Esqueleto.Internal.Language hiding (random_)+import Database.Esqueleto.Internal.Internal hiding (random_) import Database.Esqueleto.Internal.PersistentImport-import Database.Esqueleto.Internal.Sql  -- | (@random()@) Split out into database specific modules -- because MySQL uses `rand()`.
src/Database/Esqueleto/PostgreSQL.hs view
@@ -1,59 +1,57 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings-           , GADTs, CPP, Rank2Types-           , ScopedTypeVariables- #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+ -- | This module contain PostgreSQL-specific functions. ----- /Since: 2.2.8/+-- @since: 2.2.8 module Database.Esqueleto.PostgreSQL-  ( AggMode(..)-  , arrayAggDistinct-  , arrayAgg-  , arrayAggWith-  , arrayRemove-  , arrayRemoveNull-  , stringAgg-  , stringAggWith-  , maybeArray-  , chr-  , now_-  , random_-  , upsert-  , upsertBy-  , insertSelectWithConflict-  , insertSelectWithConflictCount-  , filterWhere-  -- * Internal-  , unsafeSqlAggregateFunction-  ) where+    ( AggMode(..)+    , arrayAggDistinct+    , arrayAgg+    , arrayAggWith+    , arrayRemove+    , arrayRemoveNull+    , stringAgg+    , stringAggWith+    , maybeArray+    , chr+    , now_+    , random_+    , upsert+    , upsertBy+    , insertSelectWithConflict+    , insertSelectWithConflictCount+    , filterWhere+    -- * Internal+    , unsafeSqlAggregateFunction+    ) where  #if __GLASGOW_HASKELL__ < 804-import           Data.Semigroup+import Data.Semigroup #endif-import qualified Data.Text.Internal.Builder                   as TLB-import           Data.Time.Clock                              (UTCTime)-import           Database.Esqueleto.Internal.Language         hiding (random_)-import           Database.Esqueleto.Internal.PersistentImport hiding (upsert, upsertBy)-import           Database.Esqueleto.Internal.Sql-import           Database.Esqueleto.Internal.Internal         (EsqueletoError(..), CompositeKeyError(..),-                                                              UnexpectedCaseError(..), SetClause, Ident(..),-                                                              uncommas, FinalResult(..), toUniqueDef,-                                                              KnowResult, renderUpdates, UnexpectedValueError(..))-import           Database.Persist.Class                       (OnlyOneUniqueKey)-import           Data.List.NonEmpty                           ( NonEmpty( (:|) ) )-import           Data.Int                                     (Int64)-import           Data.Proxy                                   (Proxy(..))-import           Control.Arrow                                ((***), first)-import           Control.Exception                            (throw)-import           Control.Monad                                (void)-import           Control.Monad.IO.Class                       (MonadIO (..))-import qualified Control.Monad.Trans.Reader                   as R+import Control.Arrow (first, (***))+import Control.Exception (throw)+import Control.Monad (void)+import Control.Monad.IO.Class (MonadIO(..))+import qualified Control.Monad.Trans.Reader as R+import Data.Int (Int64)+import Data.List.NonEmpty (NonEmpty((:|)))+import qualified Data.List.NonEmpty as NonEmpty+import Data.Proxy (Proxy(..))+import qualified Data.Text.Internal.Builder as TLB+import Data.Time.Clock (UTCTime)+import Database.Esqueleto.Internal.Internal hiding (random_)+import Database.Esqueleto.Internal.PersistentImport hiding (upsert, upsertBy)+import Database.Persist.Class (OnlyOneUniqueKey)  -- | (@random()@) Split out into database specific modules -- because MySQL uses `rand()`. ----- /Since: 2.6.0/+-- @since 2.6.0 random_ :: (PersistField a, Num a) => SqlExpr (Value a) random_ = unsafeSqlValue "RANDOM()" @@ -69,45 +67,48 @@ maybeArray x = coalesceDefault [x] (emptyArray)  -- | Aggregate mode-data AggMode = AggModeAll -- ^ ALL-             | AggModeDistinct -- ^ DISTINCT-  deriving (Show)+data AggMode+    = AggModeAll -- ^ ALL+    | AggModeDistinct -- ^ DISTINCT+    deriving (Show)  -- | (Internal) Create a custom aggregate functions with aggregate mode -- -- /Do/ /not/ use this function directly, instead define a new function and give -- it a type (see `unsafeSqlBinOp`)-unsafeSqlAggregateFunction ::-     UnsafeSqlFunctionArgument a-  => TLB.Builder-  -> AggMode-  -> a-  -> [OrderByClause]-  -> SqlExpr (Value b)-unsafeSqlAggregateFunction name mode args orderByClauses =-  ERaw Never $ \info ->+unsafeSqlAggregateFunction+    :: UnsafeSqlFunctionArgument a+    => TLB.Builder+    -> AggMode+    -> a+    -> [OrderByClause]+    -> SqlExpr (Value b)+unsafeSqlAggregateFunction name mode args orderByClauses = ERaw Never $ \info ->     let (orderTLB, orderVals) = makeOrderByNoNewline info orderByClauses         -- Don't add a space if we don't have order by clauses-        orderTLBSpace = case orderByClauses of-                          [] -> ""-                          (_:_) -> " "+        orderTLBSpace =+            case orderByClauses of+                [] -> ""+                (_:_) -> " "         (argsTLB, argsVals) =-          uncommas' $ map (\(ERaw _ f) -> f info) $ toArgList args-        aggMode = case mode of-                    AggModeAll -> "" -- ALL is the default, so we don't need to-                                     -- specify it-                    AggModeDistinct -> "DISTINCT "+            uncommas' $ map (\(ERaw _ f) -> f info) $ toArgList args+        aggMode =+            case mode of+                AggModeAll -> ""+                -- ALL is the default, so we don't need to+                -- specify it+                AggModeDistinct -> "DISTINCT "     in ( name <> parens (aggMode <> argsTLB <> orderTLBSpace <> orderTLB)        , argsVals <> orderVals        )  --- | (@array_agg@) Concatenate input values, including @NULL@s, --- into an array.-arrayAggWith ::-     AggMode-  -> SqlExpr (Value a)-  -> [OrderByClause]-  -> SqlExpr (Value (Maybe [a]))+arrayAggWith+    :: AggMode+    -> SqlExpr (Value a)+    -> [OrderByClause]+    -> SqlExpr (Value (Maybe [a])) arrayAggWith = unsafeSqlAggregateFunction "array_agg"  --- | (@array_agg@) Concatenate input values, including @NULL@s,@@ -118,18 +119,17 @@ -- | (@array_agg@) Concatenate distinct input values, including @NULL@s, into -- an array. ----- /Since: 2.5.3/-arrayAggDistinct ::-     (PersistField a, PersistField [a])-  => SqlExpr (Value a)-  -> SqlExpr (Value (Maybe [a]))+-- @since 2.5.3+arrayAggDistinct+    :: (PersistField a, PersistField [a])+    => SqlExpr (Value a)+    -> SqlExpr (Value (Maybe [a])) arrayAggDistinct x = arrayAggWith AggModeDistinct x [] - -- | (@array_remove@) Remove all elements equal to the given value from the -- array. ----- /Since: 2.5.3/+-- @since 2.5.3 arrayRemove :: SqlExpr (Value [a]) -> SqlExpr (Value a) -> SqlExpr (Value [a]) arrayRemove arr elem' = unsafeSqlFunction "array_remove" (arr, elem') @@ -154,7 +154,7 @@ -- | (@string_agg@) Concatenate input values separated by a -- delimiter. ----- /Since: 2.2.8/+-- @since 2.2.8 stringAgg ::      SqlString s   => SqlExpr (Value s) -- ^ Input values.@@ -165,18 +165,21 @@ -- | (@chr@) Translate the given integer to a character. (Note the result will -- depend on the character set of your database.) ----- /Since: 2.2.11/+-- @since 2.2.11 chr :: SqlString s => SqlExpr (Value Int) -> SqlExpr (Value s) chr = unsafeSqlFunction "chr"  now_ :: SqlExpr (Value UTCTime) now_ = unsafeSqlFunction "NOW" () -upsert :: (MonadIO m,-      PersistEntity record,-      OnlyOneUniqueKey record,-      PersistRecordBackend record SqlBackend,-      IsPersistBackend (PersistEntityBackend record))+upsert+    ::+    ( MonadIO m+    , PersistEntity record+    , OnlyOneUniqueKey record+    , PersistRecordBackend record SqlBackend+    , IsPersistBackend (PersistEntityBackend record)+    )     => record     -- ^ new record to insert     -> [SqlExpr (Update record)]@@ -187,30 +190,49 @@     uniqueKey <- onlyUnique record     upsertBy uniqueKey record updates -upsertBy :: (MonadIO m,-    PersistEntity record,-    IsPersistBackend (PersistEntityBackend record))-  => Unique record-  -- ^ uniqueness constraint to find by-  -> record-  -- ^ new record to insert-  -> [SqlExpr (Update record)]-  -- ^ updates to perform if the record already exists-  -> R.ReaderT SqlBackend m (Entity record)-  -- ^ the record in the database after the operation+upsertBy+    ::+    (MonadIO m+    , PersistEntity record+    , IsPersistBackend (PersistEntityBackend record)+    )+    => Unique record+    -- ^ uniqueness constraint to find by+    -> record+    -- ^ new record to insert+    -> [SqlExpr (Update record)]+    -- ^ updates to perform if the record already exists+    -> R.ReaderT SqlBackend m (Entity record)+    -- ^ the record in the database after the operation upsertBy uniqueKey record updates = do-  sqlB <- R.ask-  maybe-    (throw (UnexpectedCaseErr OperationNotSupported)) -- Postgres backend should have connUpsertSql, if this error is thrown, check changes on persistent-    (handler sqlB)-    (connUpsertSql sqlB)+    sqlB <- R.ask+    case connUpsertSql sqlB of+        Nothing ->+            -- Postgres backend should have connUpsertSql, if this error is+            -- thrown, check changes on persistent+            throw (UnexpectedCaseErr OperationNotSupported)+        Just upsertSql ->+            handler sqlB upsertSql   where     addVals l = map toPersistValue (toPersistFields record) ++ l ++ persistUniqueToValues uniqueKey     entDef = entityDef (Just record)-    uDef = toUniqueDef uniqueKey     updatesText conn = first builderToText $ renderUpdates conn updates+#if MIN_VERSION_persistent(2,11,0)+    uniqueFields = NonEmpty.fromList (persistUniqueToFieldNames uniqueKey)+    handler sqlB upsertSql = do+        let (updateText, updateVals) =+                updatesText sqlB+            queryText =+                upsertSql entDef uniqueFields updateText+            queryVals =+                addVals updateVals+        xs <- rawSql queryText queryVals+        pure (head xs)+#else+    uDef = toUniqueDef uniqueKey     handler conn f = fmap head $ uncurry rawSql $-      (***) (f entDef (uDef :| [])) addVals $ updatesText conn+        (***) (f entDef (uDef :| [])) addVals $ updatesText conn+#endif  -- | Inserts into a table the results of a query similar to 'insertSelect' but allows -- to update values that violate a constraint during insertions.@@ -245,38 +267,39 @@ -- the conflicting value is updated to the current plus the excluded. -- -- @since 3.1.3-insertSelectWithConflict :: forall a m val. (-    FinalResult a,-    KnowResult a ~ (Unique val),-    MonadIO m,-    PersistEntity val) =>-  a-  -- ^ Unique constructor or a unique, this is used just to get the name of the postgres constraint, the value(s) is(are) never used, so if you have a unique "MyUnique 0", "MyUnique undefined" would work as well.-  -> SqlQuery (SqlExpr (Insertion val))-  -- ^ Insert query.-  -> (SqlExpr (Entity val) -> SqlExpr (Entity val) -> [SqlExpr (Update val)])-  -- ^ A list of updates to be applied in case of the constraint being violated. The expression takes the current and excluded value to produce the updates.-  -> SqlWriteT m ()-insertSelectWithConflict unique query = void . insertSelectWithConflictCount unique query+insertSelectWithConflict+    :: forall a m val+     . (FinalResult a, KnowResult a ~ Unique val, MonadIO m, PersistEntity val)+    => a+    -- ^ Unique constructor or a unique, this is used just to get the name of+    -- the postgres constraint, the value(s) is(are) never used, so if you have+    -- a unique "MyUnique 0", "MyUnique undefined" would work as well.+    -> SqlQuery (SqlExpr (Insertion val))+    -- ^ Insert query.+    -> (SqlExpr (Entity val) -> SqlExpr (Entity val) -> [SqlExpr (Update val)])+    -- ^ A list of updates to be applied in case of the constraint being+    -- violated. The expression takes the current and excluded value to produce+    -- the updates.+    -> SqlWriteT m ()+insertSelectWithConflict unique query =+    void . insertSelectWithConflictCount unique query  -- | Same as 'insertSelectWithConflict' but returns the number of rows affected. -- -- @since 3.1.3-insertSelectWithConflictCount :: forall a val m. (-    FinalResult a,-    KnowResult a ~ (Unique val),-    MonadIO m,-    PersistEntity val) =>-  a-  -> SqlQuery (SqlExpr (Insertion val))-  -> (SqlExpr (Entity val) -> SqlExpr (Entity val) -> [SqlExpr (Update val)])-  -> SqlWriteT m Int64+insertSelectWithConflictCount+    :: forall a val m+     . (FinalResult a, KnowResult a ~ Unique val, MonadIO m, PersistEntity val)+    => a+    -> SqlQuery (SqlExpr (Insertion val))+    -> (SqlExpr (Entity val) -> SqlExpr (Entity val) -> [SqlExpr (Update val)])+    -> SqlWriteT m Int64 insertSelectWithConflictCount unique query conflictQuery = do-  conn <- R.ask-  uncurry rawExecuteCount $-    combine-      (toRawSql INSERT_INTO (conn, initialIdentState) (fmap EInsertFinal query))-      (conflict conn)+    conn <- R.ask+    uncurry rawExecuteCount $+        combine+            (toRawSql INSERT_INTO (conn, initialIdentState) (fmap EInsertFinal query))+            (conflict conn)   where     proxy :: Proxy val     proxy = Proxy@@ -289,7 +312,7 @@     constraint = TLB.fromText . unDBName . uniqueDBName $ uniqueDef     renderedUpdates :: (BackendCompatible SqlBackend backend) => backend -> (TLB.Builder, [PersistValue])     renderedUpdates conn = renderUpdates conn updates-    conflict conn = (foldr1 mappend ([+    conflict conn = (mconcat ([         TLB.fromText "ON CONFLICT ON CONSTRAINT \"",         constraint,         TLB.fromText "\" DO "@@ -327,18 +350,18 @@ -- -- @since 3.3.3.3 filterWhere-  :: SqlExpr (Value a)-  -- ^ Aggregate function-  -> SqlExpr (Value Bool)-  -- ^ Filter clause-  -> SqlExpr (Value a)+    :: SqlExpr (Value a)+    -- ^ Aggregate function+    -> SqlExpr (Value Bool)+    -- ^ Filter clause+    -> SqlExpr (Value a) filterWhere aggExpr clauseExpr = ERaw Never $ \info ->-  let (aggBuilder, aggValues) = case aggExpr of-        ERaw _ aggF     -> aggF info-        ECompositeKey _ -> throw $ CompositeKeyErr FilterWhereAggError-      (clauseBuilder, clauseValues) = case clauseExpr of-        ERaw _ clauseF  -> clauseF info-        ECompositeKey _ -> throw $ CompositeKeyErr FilterWhereClauseError-  in ( aggBuilder <> " FILTER (WHERE " <> clauseBuilder <> ")"-     , aggValues <> clauseValues-     )+    let (aggBuilder, aggValues) = case aggExpr of+            ERaw _ aggF     -> aggF info+            ECompositeKey _ -> throw $ CompositeKeyErr FilterWhereAggError+        (clauseBuilder, clauseValues) = case clauseExpr of+            ERaw _ clauseF  -> clauseF info+            ECompositeKey _ -> throw $ CompositeKeyErr FilterWhereClauseError+    in ( aggBuilder <> " FILTER (WHERE " <> clauseBuilder <> ")"+       , aggValues <> clauseValues+       )
src/Database/Esqueleto/PostgreSQL/JSON.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+ {-|   This module contains PostgreSQL-specific JSON functions. @@ -22,129 +23,127 @@   @since 3.1.0 -} module Database.Esqueleto.PostgreSQL.JSON-  ( -- * JSONB Newtype+    ( -- * JSONB Newtype+      --+      -- | With 'JSONB', you can use your Haskell types in your+      -- database table models as long as your type has 'FromJSON'+      -- and 'ToJSON' instances.+      --+      -- @+      -- import Database.Persist.TH+      --+      -- share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase|+      --   Example+      --     json (JSONB MyType)+      -- |]+      -- @+      --+      -- CAUTION: Remember that changing the 'FromJSON' instance+      -- of your type might result in old data becoming unparsable!+      -- You can use (@JSONB Data.Aeson.Value@) for unstructured/variable JSON.+      JSONB(..)+    , JSONBExpr+    , jsonbVal+    -- * JSONAccessor+    , JSONAccessor(..)+    -- * Arrow operators     ---    -- | With 'JSONB', you can use your Haskell types in your-    -- database table models as long as your type has 'FromJSON'-    -- and 'ToJSON' instances.+    -- | /Better documentation included with individual functions/     --+    -- The arrow operators are selection functions to select values+    -- from JSON arrays or objects.+    --+    -- === PostgreSQL Documentation+    --+    -- /Requires PostgreSQL version >= 9.3/+    --     -- @-    -- import Database.Persist.TH+    --      | Type   | Description                                |  Example                                         | Example Result+    -- -----+--------+--------------------------------------------+--------------------------------------------------+----------------+    --  ->  | int    | Get JSON array element (indexed from zero, | '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 | {"c":"baz"}+    --      |        | negative integers count from the end)      |                                                  |+    --  ->  | text   | Get JSON object field by key               | '{"a": {"b":"foo"}}'::json->'a'                  | {"b":"foo"}+    --  ->> | int    | Get JSON array element as text             | '[1,2,3]'::json->>2                              | 3+    --  ->> | text   | Get JSON object field as text              | '{"a":1,"b":2}'::json->>'b'                      | 2+    --  \#>  | text[] | Get JSON object at specified path          | '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}'       | {"c": "foo"}+    --  \#>> | text[] | Get JSON object at specified path as text  | '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}'      | 3+    -- @+    , (->.)+    , (->>.)+    , (#>.)+    , (#>>.)+    -- * Filter operators     ---    -- share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase|-    --   Example-    --     json (JSONB MyType)-    -- |]+    -- | /Better documentation included with individual functions/+    --+    -- These functions test certain properties of JSON values+    -- and return booleans, so are mainly used in WHERE clauses.+    --+    -- === PostgreSQL Documentation+    --+    -- /Requires PostgreSQL version >= 9.4/+    --     -- @+    --     | Type   | Description                                                     |  Example+    -- ----+--------+-----------------------------------------------------------------+---------------------------------------------------+    --  \@> | jsonb  | Does the left JSON value contain within it the right value?     | '{"a":1, "b":2}'::jsonb \@> '{"b":2}'::jsonb+    --  <\@ | jsonb  | Is the left JSON value contained within the right value?        | '{"b":2}'::jsonb <\@ '{"a":1, "b":2}'::jsonb+    --  ?  | text   | Does the string exist as a top-level key within the JSON value? | '{"a":1, "b":2}'::jsonb ? 'b'+    --  ?| | text[] | Do any of these array strings exist as top-level keys?          | '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c']+    --  ?& | text[] | Do all of these array strings exist as top-level keys?          | '["a", "b"]'::jsonb ?& array['a', 'b']+    -- @+    , (@>.)+    , (<@.)+    , (?.)+    , (?|.)+    , (?&.)+    -- * Deletion and concatenation operators     ---    -- CAUTION: Remember that changing the 'FromJSON' instance-    -- of your type might result in old data becoming unparsable!-    -- You can use (@JSONB Data.Aeson.Value@) for unstructured/variable JSON.-    JSONB(..)-  , JSONBExpr-  , jsonbVal-  -- * JSONAccessor-  , JSONAccessor(..)-  -- * Arrow operators-  ---  -- | /Better documentation included with individual functions/-  ---  -- The arrow operators are selection functions to select values-  -- from JSON arrays or objects.-  ---  -- === PostgreSQL Documentation-  ---  -- /Requires PostgreSQL version >= 9.3/-  ---  -- @-  --      | Type   | Description                                |  Example                                         | Example Result-  -- -----+--------+--------------------------------------------+--------------------------------------------------+-----------------  --  ->  | int    | Get JSON array element (indexed from zero, | '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 | {"c":"baz"}-  --      |        | negative integers count from the end)      |                                                  |-  --  ->  | text   | Get JSON object field by key               | '{"a": {"b":"foo"}}'::json->'a'                  | {"b":"foo"}-  --  ->> | int    | Get JSON array element as text             | '[1,2,3]'::json->>2                              | 3-  --  ->> | text   | Get JSON object field as text              | '{"a":1,"b":2}'::json->>'b'                      | 2-  --  \#>  | text[] | Get JSON object at specified path          | '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}'       | {"c": "foo"}-  --  \#>> | text[] | Get JSON object at specified path as text  | '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}'      | 3-  -- @-  , (->.)-  , (->>.)-  , (#>.)-  , (#>>.)-  -- * Filter operators-  ---  -- | /Better documentation included with individual functions/-  ---  -- These functions test certain properties of JSON values-  -- and return booleans, so are mainly used in WHERE clauses.-  ---  -- === PostgreSQL Documentation-  ---  -- /Requires PostgreSQL version >= 9.4/-  ---  -- @-  --     | Type   | Description                                                     |  Example-  -- ----+--------+-----------------------------------------------------------------+----------------------------------------------------  --  \@> | jsonb  | Does the left JSON value contain within it the right value?     | '{"a":1, "b":2}'::jsonb \@> '{"b":2}'::jsonb-  --  <\@ | jsonb  | Is the left JSON value contained within the right value?        | '{"b":2}'::jsonb <\@ '{"a":1, "b":2}'::jsonb-  --  ?  | text   | Does the string exist as a top-level key within the JSON value? | '{"a":1, "b":2}'::jsonb ? 'b'-  --  ?| | text[] | Do any of these array strings exist as top-level keys?          | '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c']-  --  ?& | text[] | Do all of these array strings exist as top-level keys?          | '["a", "b"]'::jsonb ?& array['a', 'b']-  -- @-  , (@>.)-  , (<@.)-  , (?.)-  , (?|.)-  , (?&.)-  -- * Deletion and concatenation operators-  ---  -- | /Better documentation included with individual functions/-  ---  -- These operators change the shape of the JSON value and-  -- also have the highest risk of throwing an exception.-  -- Please read the descriptions carefully before using these functions.-  ---  -- === PostgreSQL Documentation-  ---  -- /Requires PostgreSQL version >= 9.5/-  ---  -- @-  --     | Type    | Description                                                            |  Example-  -- ----+---------+------------------------------------------------------------------------+--------------------------------------------------  --  || | jsonb   | Concatenate two jsonb values into a new jsonb value                    | '["a", "b"]'::jsonb || '["c", "d"]'::jsonb-  --  -  | text    | Delete key/value pair or string element from left operand.             | '{"a": "b"}'::jsonb - 'a'-  --     |         | Key/value pairs are matched based on their key value.                  |-  --  -  | integer | Delete the array element with specified index (Negative integers count | '["a", "b"]'::jsonb - 1-  --     |         | from the end). Throws an error if top level container is not an array. |-  --  \#- | text[]  | Delete the field or element with specified path                        | '["a", {"b":1}]'::jsonb \#- '{1,b}'-  --     |         | (for JSON arrays, negative integers count from the end)                |-  -- @-  ---  -- /Requires PostgreSQL version >= 10/-  ---  -- @-  --     | Type    | Description                                                            |  Example-  -- ----+---------+------------------------------------------------------------------------+--------------------------------------------------  --  -  | text[]  | Delete multiple key/value pairs or string elements from left operand.  | '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]-  --     |         | Key/value pairs are matched based on their key value.                  |-  -- @-  , (-.)-  , (--.)-  , (#-.)-  , (||.)-  ) where+    -- | /Better documentation included with individual functions/+    --+    -- These operators change the shape of the JSON value and+    -- also have the highest risk of throwing an exception.+    -- Please read the descriptions carefully before using these functions.+    --+    -- === PostgreSQL Documentation+    --+    -- /Requires PostgreSQL version >= 9.5/+    --+    -- @+    --     | Type    | Description                                                            |  Example+    -- ----+---------+------------------------------------------------------------------------+-------------------------------------------------+    --  || | jsonb   | Concatenate two jsonb values into a new jsonb value                    | '["a", "b"]'::jsonb || '["c", "d"]'::jsonb+    --  -  | text    | Delete key/value pair or string element from left operand.             | '{"a": "b"}'::jsonb - 'a'+    --     |         | Key/value pairs are matched based on their key value.                  |+    --  -  | integer | Delete the array element with specified index (Negative integers count | '["a", "b"]'::jsonb - 1+    --     |         | from the end). Throws an error if top level container is not an array. |+    --  \#- | text[]  | Delete the field or element with specified path                        | '["a", {"b":1}]'::jsonb \#- '{1,b}'+    --     |         | (for JSON arrays, negative integers count from the end)                |+    -- @+    --+    -- /Requires PostgreSQL version >= 10/+    --+    -- @+    --     | Type    | Description                                                            |  Example+    -- ----+---------+------------------------------------------------------------------------+-------------------------------------------------+    --  -  | text[]  | Delete multiple key/value pairs or string elements from left operand.  | '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]+    --     |         | Key/value pairs are matched based on their key value.                  |+    -- @+    , (-.)+    , (--.)+    , (#-.)+    , (||.)+    ) where  import Data.Text (Text)-import Database.Esqueleto.Internal.Language hiding ((?.), (-.), (||.))+import Database.Esqueleto.Internal.Language hiding ((-.), (?.), (||.)) import Database.Esqueleto.Internal.PersistentImport import Database.Esqueleto.Internal.Sql import Database.Esqueleto.PostgreSQL.JSON.Instances - infixl 6 ->., ->>., #>., #>>. infixl 6 @>., <@., ?., ?|., ?&. infixl 6 ||., -., --., #-.-  -- | /Requires PostgreSQL version >= 9.3/ --
src/Database/Esqueleto/PostgreSQL/JSON/Instances.hs view
@@ -4,6 +4,8 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-}+{-# language DerivingStrategies #-}+ module Database.Esqueleto.PostgreSQL.JSON.Instances where  import Data.Aeson (FromJSON(..), ToJSON(..), encode, eitherDecodeStrict)@@ -18,23 +20,24 @@ import Database.Esqueleto.Internal.Sql (SqlExpr) import GHC.Generics (Generic) - -- | Newtype wrapper around any type with a JSON representation. -- -- @since 3.1.0 newtype JSONB a = JSONB { unJSONB :: a }-  deriving-    ( Generic-    , FromJSON-    , ToJSON-    , Eq-    , Foldable-    , Functor-    , Ord-    , Read-    , Show-    , Traversable-    )+    deriving stock+        ( Generic+        , Eq+        , Foldable+        , Functor+        , Ord+        , Read+        , Show+        , Traversable+        )+    deriving newtype+        ( FromJSON+        , ToJSON+        )  -- | 'SqlExpr' of a NULL-able 'JSONB' value. Hence the 'Maybe'. --@@ -60,48 +63,49 @@ -- JSONKey "name" -- -- NOTE: DO NOT USE ANY OF THE 'Num' METHODS ON THIS TYPE!-data JSONAccessor = JSONIndex Int-                  | JSONKey Text-  deriving (Generic, Eq, Show)+data JSONAccessor+    = JSONIndex Int+    | JSONKey Text+    deriving (Generic, Eq, Show)  -- | I repeat, DO NOT use any method other than 'fromInteger'! instance Num JSONAccessor where-  fromInteger = JSONIndex . fromInteger-  negate (JSONIndex i) = JSONIndex $ negate i-  negate (JSONKey _) = error "Can not negate a JSONKey"-  (+) = numErr-  (-) = numErr-  (*) = numErr-  abs = numErr-  signum = numErr+    fromInteger = JSONIndex . fromInteger+    negate (JSONIndex i) = JSONIndex $ negate i+    negate (JSONKey _) = error "Can not negate a JSONKey"+    (+) = numErr+    (-) = numErr+    (*) = numErr+    abs = numErr+    signum = numErr  numErr :: a numErr = error "Do not use 'Num' methods on JSONAccessors"  instance IsString JSONAccessor where-  fromString = JSONKey . T.pack+    fromString = JSONKey . T.pack  -- | @since 3.1.0 instance (FromJSON a, ToJSON a) => PersistField (JSONB a) where-  toPersistValue = PersistDbSpecific . BSL.toStrict . encode . unJSONB-  fromPersistValue pVal = fmap JSONB $ case pVal of-      PersistByteString bs -> first (badParse $ TE.decodeUtf8 bs) $ eitherDecodeStrict bs-      PersistText t -> first (badParse t) $ eitherDecodeStrict (TE.encodeUtf8 t)-      x -> Left $ fromPersistValueError "string or bytea" x+    toPersistValue = PersistDbSpecific . BSL.toStrict . encode . unJSONB+    fromPersistValue pVal = fmap JSONB $ case pVal of+        PersistByteString bs -> first (badParse $ TE.decodeUtf8 bs) $ eitherDecodeStrict bs+        PersistText t -> first (badParse t) $ eitherDecodeStrict (TE.encodeUtf8 t)+        x -> Left $ fromPersistValueError "string or bytea" x  -- | jsonb -- -- @since 3.1.0 instance (FromJSON a, ToJSON a) => PersistFieldSql (JSONB a) where-  sqlType _ = SqlOther "JSONB"+    sqlType _ = SqlOther "JSONB"  badParse :: Text -> String -> Text badParse t = fromPersistValueParseError t . T.pack  fromPersistValueError-  :: Text -- ^ Database type(s), should appear different from Haskell name, e.g. "integer" or "INT", not "Int".-  -> PersistValue -- ^ Incorrect value-  -> Text -- ^ Error message+    :: Text -- ^ Database type(s), should appear different from Haskell name, e.g. "integer" or "INT", not "Int".+    -> PersistValue -- ^ Incorrect value+    -> Text -- ^ Error message fromPersistValueError databaseType received = T.concat     [ "Failed to parse Haskell newtype `JSONB a`; "     , "expected ", databaseType@@ -110,9 +114,9 @@     ]  fromPersistValueParseError-  :: Text -- ^ Received value-  -> Text -- ^ Additional error-  -> Text -- ^ Error message+    :: Text -- ^ Received value+    -> Text -- ^ Additional error+    -> Text -- ^ Error message fromPersistValueParseError received err = T.concat     [ "Failed to parse Haskell type `JSONB a`, "     , "but received ", received
src/Database/Esqueleto/SQLite.hs view
@@ -1,14 +1,14 @@ {-# LANGUAGE OverloadedStrings #-}+ -- | This module contain SQLite-specific functions. ----- /Since: 2.2.8/+-- @since 2.2.8 module Database.Esqueleto.SQLite   ( random_   ) where -import Database.Esqueleto.Internal.Language hiding (random_)+import Database.Esqueleto.Internal.Internal hiding (random_) import Database.Esqueleto.Internal.PersistentImport-import Database.Esqueleto.Internal.Sql  -- | (@random()@) Split out into database specific modules -- because MySQL uses `rand()`.
test/Common/Test.hs view
@@ -1,26 +1,28 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}+ {-# OPTIONS_GHC -fno-warn-unused-binds #-} {-# OPTIONS_GHC -fno-warn-deprecations #-}-{-# LANGUAGE ConstraintKinds-           , CPP, DerivingStrategies, StandaloneDeriving-           , TypeApplications-           , PartialTypeSignatures-           , UndecidableInstances-           , EmptyDataDecls-           , FlexibleContexts-           , FlexibleInstances-           , DeriveGeneric-           , GADTs-           , GeneralizedNewtypeDeriving-           , MultiParamTypeClasses-           , OverloadedStrings-           , QuasiQuotes-           , Rank2Types-           , TemplateHaskell-           , TypeFamilies-           , ScopedTypeVariables-           , TypeSynonymInstances- #-}- module Common.Test     ( tests     , testLocking@@ -60,17 +62,18 @@     , Key(..)     ) where -import Data.Either-import Data.Time import Control.Monad (forM_, replicateM, replicateM_, void)-import Control.Monad.Reader (ask) import Control.Monad.Catch (MonadCatch)+import Control.Monad.Reader (ask)+import Data.Either+import Data.Time #if __GLASGOW_HASKELL__ >= 806 import Control.Monad.Fail (MonadFail) #endif import Control.Monad.IO.Class (MonadIO(liftIO))-import Control.Monad.Logger (MonadLogger (..), NoLoggingT, runNoLoggingT)+import Control.Monad.Logger (MonadLogger(..), NoLoggingT, runNoLoggingT) import Control.Monad.Trans.Reader (ReaderT)+import qualified Data.Attoparsec.Text as AP import Data.Char (toLower, toUpper) import Data.Monoid ((<>)) import Database.Esqueleto@@ -79,18 +82,17 @@ import Database.Persist.TH import Test.Hspec import UnliftIO-import qualified Data.Attoparsec.Text as AP -import Data.Conduit (ConduitT, (.|), runConduit)+import Data.Conduit (ConduitT, runConduit, (.|)) import qualified Data.Conduit.List as CL import qualified Data.List as L import qualified Data.Set as S import qualified Data.Text as Text-import qualified Data.Text.Lazy.Builder as TLB import qualified Data.Text.Internal.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Database.Esqueleto.Internal.ExprParser as P import qualified Database.Esqueleto.Internal.Sql as EI import qualified UnliftIO.Resource as R-import qualified Database.Esqueleto.Internal.ExprParser as P  -- Test schema share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase|@@ -250,8 +252,8 @@   instance ToBaseId ArticleMetadata where-  type BaseEnt ArticleMetadata = Article-  toBaseIdWitness articleId = ArticleMetadataKey articleId+    type BaseEnt ArticleMetadata = Article+    toBaseIdWitness articleId = ArticleMetadataKey articleId  -- | this could be achieved with S.fromList, but not all lists --   have Ord instances@@ -263,7 +265,7 @@ --   [12.0, 12.3, 12.35, 12.346, 12.3456, 12.3456] roundTo :: (Fractional a, RealFrac a1, Integral b) => b -> a1 -> a roundTo n f =-  (fromInteger $ round $ f * (10^n)) / (10.0^^n)+    (fromInteger $ round $ f * (10^n)) / (10.0^^n)  p1 :: Person p1 = Person "John"   (Just 36) Nothing   1@@ -303,355 +305,347 @@  testSelect :: Run -> Spec testSelect run = do-  describe "select" $ do-    it "works for a single value" $-      run $ do-        ret <- select $ return $ val (3 :: Int)-        liftIO $ ret `shouldBe` [ Value 3 ]+    describe "select" $ do+        it "works for a single value" $+            run $ do+                ret <- select $ return $ val (3 :: Int)+                liftIO $ ret `shouldBe` [ Value 3 ] -    it "works for a pair of a single value and ()" $-      run $ do-        ret <- select $ return (val (3 :: Int), ())-        liftIO $ ret `shouldBe` [ (Value 3, ()) ]+        it "works for a pair of a single value and ()" $+            run $ do+                ret <- select $ return (val (3 :: Int), ())+                liftIO $ ret `shouldBe` [ (Value 3, ()) ] -    it "works for a single ()" $-      run $ do-        ret <- select $ return ()-        liftIO $ ret `shouldBe` [ () ]+        it "works for a single ()" $+            run $ do+                ret <- select $ return ()+                liftIO $ ret `shouldBe` [ () ] -    it "works for a single NULL value" $-      run $ do-        ret <- select $ return nothing-        liftIO $ ret `shouldBe` [ Value (Nothing :: Maybe Int) ]+        it "works for a single NULL value" $+            run $ do+                ret <- select $ return nothing+                liftIO $ ret `shouldBe` [ Value (Nothing :: Maybe Int) ]  testSubSelect :: Run -> Spec testSubSelect run = do-  let-    setup :: MonadIO m => SqlPersistT m ()-    setup = do-      _ <- insert $ Numbers 1 2-      _ <- insert $ Numbers 2 4-      _ <- insert $ Numbers 3 5-      _ <- insert $ Numbers 6 7-      pure ()-  describe "subSelect" $ do-    it "is safe for queries that may return multiple results" $ do-      let-        query =-          from $ \n -> do-          orderBy [asc (n ^. NumbersInt)]-          pure (n ^. NumbersInt)-      res <- run $ do-        setup-        select $ pure $ subSelect query-      res `shouldBe` [Value (Just 1)]+    let setup :: MonadIO m => SqlPersistT m ()+        setup = do+            _ <- insert $ Numbers 1 2+            _ <- insert $ Numbers 2 4+            _ <- insert $ Numbers 3 5+            _ <- insert $ Numbers 6 7+            pure () -      eres <- try $ run $ do-        setup-        select $ pure $ sub_select query-      case eres of-        Left (SomeException _) ->-          -- We should receive an exception, but the different database-          -- libraries throw different exceptions. Hooray.-          pure ()-        Right v ->-          -- This shouldn't happen, but in sqlite land, many things are-          -- possible.-          v `shouldBe` [Value 1]+    describe "subSelect" $ do+        it "is safe for queries that may return multiple results" $ do+            let query =+                  from $ \n -> do+                  orderBy [asc (n ^. NumbersInt)]+                  pure (n ^. NumbersInt)+            res <- run $ do+                setup+                select $ pure $ subSelect query+            res `shouldBe` [Value (Just 1)] -    it "is safe for queries that may not return anything" $ do-      let-        query =-          from $ \n -> do-          orderBy [asc (n ^. NumbersInt)]-          limit 1-          pure (n ^. NumbersInt)-      res <- run $ select $ pure $ subSelect query-      res `shouldBe` [Value Nothing]+            eres <- try $ run $ do+                setup+                select $ pure $ sub_select query+            case eres of+                Left (SomeException _) ->+                    -- We should receive an exception, but the different database+                    -- libraries throw different exceptions. Hooray.+                    pure ()+                Right v ->+                    -- This shouldn't happen, but in sqlite land, many things are+                    -- possible.+                    v `shouldBe` [Value 1] -      eres <- try $ run $ do-        setup-        select $ pure $ sub_select query+        it "is safe for queries that may not return anything" $ do+            let query =+                    from $ \n -> do+                    orderBy [asc (n ^. NumbersInt)]+                    limit 1+                    pure (n ^. NumbersInt)+            res <- run $ select $ pure $ subSelect query+            res `shouldBe` [Value Nothing] -      case eres of-        Left (_ :: PersistException) ->-          -- We expect to receive this exception. However, sqlite evidently has-          -- no problems with it, so we can't *require* that the exception is-          -- thrown. Sigh.-          pure ()-        Right v ->-          -- This shouldn't happen, but in sqlite land, many things are-          -- possible.-          v `shouldBe` [Value 1]+            eres <- try $ run $ do+                setup+                select $ pure $ sub_select query -  describe "subSelectList" $ do-    it "is safe on empty databases as well as good databases" $ do-      let-        query =-          from $ \n -> do-          where_ $ n ^. NumbersInt `in_` do-            subSelectList $-              from $ \n' -> do-              where_ $ n' ^. NumbersInt >=. val 3-              pure (n' ^. NumbersInt)-          pure n+            case eres of+                Left (_ :: PersistException) ->+                    -- We expect to receive this exception. However, sqlite evidently has+                    -- no problems with it, so we can't *require* that the exception is+                    -- thrown. Sigh.+                    pure ()+                Right v ->+                    -- This shouldn't happen, but in sqlite land, many things are+                    -- possible.+                    v `shouldBe` [Value 1] -      empty <- run $ do-        select query+    describe "subSelectList" $ do+        it "is safe on empty databases as well as good databases" $ do+            let query =+                    from $ \n -> do+                    where_ $ n ^. NumbersInt `in_` do+                        subSelectList $+                            from $ \n' -> do+                            where_ $ n' ^. NumbersInt >=. val 3+                            pure (n' ^. NumbersInt)+                    pure n -      full <- run $ do-        setup-        select query+            empty <- run $ do+                select query -      empty `shouldBe` []-      full `shouldSatisfy` (not . null)+            full <- run $ do+                setup+                select query -  describe "subSelectMaybe" $ do-    it "is equivalent to joinV . subSelect" $ do-      let-        query-          :: ( SqlQuery (SqlExpr (Value (Maybe Int)))-            -> SqlExpr (Value (Maybe Int))-            )-          -> SqlQuery (SqlExpr (Value (Maybe Int)))-        query selector =-          from $ \n -> do-          pure $-            selector $-            from $ \n' -> do-            where_ $ n' ^. NumbersDouble >=. n ^. NumbersDouble-            pure (max_ (n' ^. NumbersInt))+            empty `shouldBe` []+            full `shouldSatisfy` (not . null) -      a <- run $ do-        setup-        select (query subSelectMaybe)-      b <- run $ do-        setup-        select (query (joinV . subSelect))-      a `shouldBe` b+    describe "subSelectMaybe" $ do+        it "is equivalent to joinV . subSelect" $ do+            let query+                    :: (SqlQuery (SqlExpr (Value (Maybe Int))) -> SqlExpr (Value (Maybe Int)))+                    -> SqlQuery (SqlExpr (Value (Maybe Int)))+                query selector =+                    from $ \n -> do+                    pure $+                        selector $+                        from $ \n' -> do+                        where_ $ n' ^. NumbersDouble >=. n ^. NumbersDouble+                        pure (max_ (n' ^. NumbersInt)) -  describe "subSelectCount" $ do-    it "is a safe way to do a countRows" $ do-      xs0 <- run $ do-        setup-        select $-          from $ \n -> do-          pure $ (,) n $-            subSelectCount @Int $-            from $ \n' -> do-            where_ $ n' ^. NumbersInt >=. n ^. NumbersInt+            a <- run $ do+                setup+                select (query subSelectMaybe)+            b <- run $ do+                setup+                select (query (joinV . subSelect))+            a `shouldBe` b -      xs1 <- run $ do-        setup-        select $-          from $ \n -> do-          pure $ (,) n $-            subSelectUnsafe $-            from $ \n' -> do-            where_ $ n' ^. NumbersInt >=. n ^. NumbersInt-            pure (countRows :: SqlExpr (Value Int))+    describe "subSelectCount" $ do+        it "is a safe way to do a countRows" $ do+            xs0 <- run $ do+                setup+                select $+                    from $ \n -> do+                    pure $ (,) n $+                        subSelectCount @Int $+                        from $ \n' -> do+                        where_ $ n' ^. NumbersInt >=. n ^. NumbersInt -      let getter (Entity _ a, b) = (a, b)-      map getter xs0 `shouldBe` map getter xs1+            xs1 <- run $ do+                setup+                select $+                    from $ \n -> do+                    pure $ (,) n $+                        subSelectUnsafe $+                        from $ \n' -> do+                        where_ $ n' ^. NumbersInt >=. n ^. NumbersInt+                        pure (countRows :: SqlExpr (Value Int)) -  describe "subSelectUnsafe" $ do-    it "throws exceptions on multiple results" $ do-      eres <- try $ run $ do-        setup-        bad <- select $-          from $ \n -> do-          pure $ (,) (n ^. NumbersInt) $-            subSelectUnsafe $-            from $ \n' -> do-            pure (just (n' ^. NumbersDouble))-        good <- select $-          from $ \n -> do-          pure $ (,) (n ^. NumbersInt) $-            subSelect $-            from $ \n' -> do-            pure (n' ^. NumbersDouble)-        pure (bad, good)-      case eres of-        Left (SomeException _) ->-          -- Must use SomeException because the database libraries throw their-          -- own errors.-          pure ()-        Right (bad, good) -> do-          -- SQLite just takes the first element of the sub-select. lol.-          ---          bad `shouldBe` good+            let getter (Entity _ a, b) = (a, b)+            map getter xs0 `shouldBe` map getter xs1 -    it "throws exceptions on null results" $ do-      eres <- try $ run $ do-        setup-        select $-          from $ \n -> do-          pure $ (,) (n ^. NumbersInt) $-            subSelectUnsafe $-            from $ \n' -> do-            where_ $ val False-            pure (n' ^. NumbersDouble)-      case eres of-        Left (_ :: PersistException) ->-          pure ()-        Right xs ->-          xs `shouldBe` []+    describe "subSelectUnsafe" $ do+        it "throws exceptions on multiple results" $ do+            eres <- try $ run $ do+                setup+                bad <- select $+                    from $ \n -> do+                    pure $ (,) (n ^. NumbersInt) $+                        subSelectUnsafe $+                        from $ \n' -> do+                        pure (just (n' ^. NumbersDouble))+                good <- select $+                    from $ \n -> do+                    pure $ (,) (n ^. NumbersInt) $+                        subSelect $+                        from $ \n' -> do+                        pure (n' ^. NumbersDouble)+                pure (bad, good)+            case eres of+                Left (SomeException _) ->+                    -- Must use SomeException because the database libraries throw their+                    -- own errors.+                    pure ()+                Right (bad, good) -> do+                    -- SQLite just takes the first element of the sub-select. lol.+                    --+                    bad `shouldBe` good +        it "throws exceptions on null results" $ do+            eres <- try $ run $ do+                setup+                select $+                    from $ \n -> do+                    pure $ (,) (n ^. NumbersInt) $+                        subSelectUnsafe $+                        from $ \n' -> do+                        where_ $ val False+                        pure (n' ^. NumbersDouble)+            case eres of+                Left (_ :: PersistException) ->+                    pure ()+                Right xs ->+                    xs `shouldBe` []  testSelectSource :: Run -> Spec testSelectSource run = do-  describe "selectSource" $ do-    it "works for a simple example" $-      run $ do-        let query = selectSource $-                    from $ \person ->-                    return person-        p1e <- insert' p1-        ret <- runConduit $ query .| CL.consume-        liftIO $ ret `shouldBe` [ p1e ]--    it "can run a query many times" $-      run $ do-        let query = selectSource $-                    from $ \person ->-                    return person-        p1e <- insert' p1-        ret0 <- runConduit $ query .| CL.consume-        ret1 <- runConduit $ query .| CL.consume-        liftIO $ ret0 `shouldBe` [ p1e ]-        liftIO $ ret1 `shouldBe` [ p1e ]--    it "works on repro" $ do-      let selectPerson :: R.MonadResource m => String -> ConduitT () (Key Person) (SqlPersistT m) ()-          selectPerson name = do-            let source = selectSource $ from $ \person -> do-                         where_ $ person ^. PersonName ==. val name-                         return $ person ^. PersonId-            source .| CL.map unValue-      run $ do-        p1e <- insert' p1-        p2e <- insert' p2-        r1 <- runConduit $-          selectPerson (personName p1) .| CL.consume-        r2 <- runConduit $-          selectPerson (personName p2) .| CL.consume-        liftIO $ do-          r1 `shouldBe` [ entityKey p1e ]-          r2 `shouldBe` [ entityKey p2e ]+    describe "selectSource" $ do+        it "works for a simple example" $ run $ do+            let query = selectSource $+                        from $ \person ->+                        return person+            p1e <- insert' p1+            ret <- runConduit $ query .| CL.consume+            liftIO $ ret `shouldBe` [ p1e ] +        it "can run a query many times" $ run $ do+            let query = selectSource $+                        from $ \person ->+                        return person+            p1e <- insert' p1+            ret0 <- runConduit $ query .| CL.consume+            ret1 <- runConduit $ query .| CL.consume+            liftIO $ ret0 `shouldBe` [ p1e ]+            liftIO $ ret1 `shouldBe` [ p1e ] +        it "works on repro" $ do+            let selectPerson :: R.MonadResource m => String -> ConduitT () (Key Person) (SqlPersistT m) ()+                selectPerson name = do+                    let source =+                            selectSource $ from $ \person -> do+                            where_ $ person ^. PersonName ==. val name+                            return $ person ^. PersonId+                    source .| CL.map unValue+            run $ do+                p1e <- insert' p1+                p2e <- insert' p2+                r1 <- runConduit $ selectPerson (personName p1) .| CL.consume+                r2 <- runConduit $ selectPerson (personName p2) .| CL.consume+                liftIO $ do+                  r1 `shouldBe` [ entityKey p1e ]+                  r2 `shouldBe` [ entityKey p2e ]  testSelectFrom :: Run -> Spec testSelectFrom run = do-  describe "select/from" $ do-    it "works for a simple example" $-      run $ do-        p1e <- insert' p1-        ret <- select $-               from $ \person ->-               return person-        liftIO $ ret `shouldBe` [ p1e ]--    it "works for a simple self-join (one entity)" $-      run $ do-        p1e <- insert' p1-        ret <- select $-               from $ \(person1, person2) ->-               return (person1, person2)-        liftIO $ ret `shouldBe` [ (p1e, p1e) ]+    describe "select/from" $ do+        it "works for a simple example" $ run $ do+            p1e <- insert' p1+            ret <-+                select $+                from $ \person ->+                return person+            liftIO $ ret `shouldBe` [ p1e ] -    it "works for a simple self-join (two entities)" $-      run $ do-        p1e <- insert' p1-        p2e <- insert' p2-        ret <- select $-               from $ \(person1, person2) ->-               return (person1, person2)-        liftIO $ ret `shouldSatisfy` sameElementsAs [ (p1e, p1e)-                                                    , (p1e, p2e)-                                                    , (p2e, p1e)-                                                    , (p2e, p2e) ]+        it "works for a simple self-join (one entity)" $ run $ do+            p1e <- insert' p1+            ret <-+                select $+                from $ \(person1, person2) ->+                return (person1, person2)+            liftIO $ ret `shouldBe` [ (p1e, p1e) ] +        it "works for a simple self-join (two entities)" $ run $ do+            p1e <- insert' p1+            p2e <- insert' p2+            ret <-+                select $+                from $ \(person1, person2) ->+                return (person1, person2)+            liftIO $+                ret+                    `shouldSatisfy`+                        sameElementsAs+                            [ (p1e, p1e)+                            , (p1e, p2e)+                            , (p2e, p1e)+                            , (p2e, p2e)+                            ] -    it "works for a self-join via sub_select" $-      run $ do-        p1k <- insert p1-        p2k <- insert p2-        _f1k <- insert (Follow p1k p2k)-        _f2k <- insert (Follow p2k p1k)-        ret <- select $-               from $ \followA -> do-               let subquery =-                     from $ \followB -> do-                     where_ $ followA ^. FollowFollower ==. followB ^. FollowFollowed-                     return $ followB ^. FollowFollower-               where_ $ followA ^. FollowFollowed ==. sub_select subquery-               return followA-        liftIO $ length ret `shouldBe` 2+        it "works for a self-join via sub_select" $ run $ do+            p1k <- insert p1+            p2k <- insert p2+            _f1k <- insert (Follow p1k p2k)+            _f2k <- insert (Follow p2k p1k)+            ret <- select $+                   from $ \followA -> do+                   let subquery =+                         from $ \followB -> do+                         where_ $ followA ^. FollowFollower ==. followB ^. FollowFollowed+                         return $ followB ^. FollowFollower+                   where_ $ followA ^. FollowFollowed ==. sub_select subquery+                   return followA+            liftIO $ length ret `shouldBe` 2 -    it "works for a self-join via exists" $-      run $ do-        p1k <- insert p1-        p2k <- insert p2-        _f1k <- insert (Follow p1k p2k)-        _f2k <- insert (Follow p2k p1k)-        ret <- select $-               from $ \followA -> do-               where_ $ exists $-                        from $ \followB ->-                        where_ $ followA ^. FollowFollower ==. followB ^. FollowFollowed-               return followA-        liftIO $ length ret `shouldBe` 2+        it "works for a self-join via exists" $ run $ do+            p1k <- insert p1+            p2k <- insert p2+            _f1k <- insert (Follow p1k p2k)+            _f2k <- insert (Follow p2k p1k)+            ret <- select $+                   from $ \followA -> do+                   where_ $ exists $+                            from $ \followB ->+                            where_ $ followA ^. FollowFollower ==. followB ^. FollowFollowed+                   return followA+            liftIO $ length ret `shouldBe` 2  -    it "works for a simple projection" $-      run $ do-        p1k <- insert p1-        p2k <- insert p2-        ret <- select $-               from $ \p ->-               return (p ^. PersonId, p ^. PersonName)-        liftIO $ ret `shouldBe` [ (Value p1k, Value (personName p1))-                                , (Value p2k, Value (personName p2)) ]+        it "works for a simple projection" $ run $ do+            p1k <- insert p1+            p2k <- insert p2+            ret <- select $+                   from $ \p ->+                   return (p ^. PersonId, p ^. PersonName)+            liftIO $ ret `shouldBe` [ (Value p1k, Value (personName p1))+                                    , (Value p2k, Value (personName p2)) ] -    it "works for a simple projection with a simple implicit self-join" $-      run $ do-        _ <- insert p1-        _ <- insert p2-        ret <- select $-               from $ \(pa, pb) ->-               return (pa ^. PersonName, pb ^. PersonName)-        liftIO $ ret `shouldSatisfy` sameElementsAs-                                [ (Value (personName p1), Value (personName p1))-                                , (Value (personName p1), Value (personName p2))-                                , (Value (personName p2), Value (personName p1))-                                , (Value (personName p2), Value (personName p2)) ]+        it "works for a simple projection with a simple implicit self-join" $ run $ do+            _ <- insert p1+            _ <- insert p2+            ret <- select $+                   from $ \(pa, pb) ->+                   return (pa ^. PersonName, pb ^. PersonName)+            liftIO $ ret `shouldSatisfy` sameElementsAs+                                    [ (Value (personName p1), Value (personName p1))+                                    , (Value (personName p1), Value (personName p2))+                                    , (Value (personName p2), Value (personName p1))+                                    , (Value (personName p2), Value (personName p2)) ] -    it "works with many kinds of LIMITs and OFFSETs" $-      run $ do-        [p1e, p2e, p3e, p4e] <- mapM insert' [p1, p2, p3, p4]-        let people = from $ \p -> do-                     orderBy [asc (p ^. PersonName)]-                     return p-        ret1 <- select $ do+        it "works with many kinds of LIMITs and OFFSETs" $ run $ do+            [p1e, p2e, p3e, p4e] <- mapM insert' [p1, p2, p3, p4]+            let people =+                    from $ \p -> do+                    orderBy [asc (p ^. PersonName)]+                    return p+            ret1 <-+                select $ do                 p <- people                 limit 2                 limit 1                 return p-        liftIO $ ret1 `shouldBe` [ p1e ]-        ret2 <- select $ do+            liftIO $ ret1 `shouldBe` [ p1e ]+            ret2 <-+                select $ do                 p <- people                 limit 1                 limit 2                 return p-        liftIO $ ret2 `shouldBe` [ p1e, p4e ]-        ret3 <- select $ do+            liftIO $ ret2 `shouldBe` [ p1e, p4e ]+            ret3 <-+                select $ do                 p <- people                 offset 3                 offset 2                 return p-        liftIO $ ret3 `shouldBe` [ p3e, p2e ]-        ret4 <- select $ do+            liftIO $ ret3 `shouldBe` [ p3e, p2e ]+            ret4 <-+                select $ do                 p <- people                 offset 3                 limit 5@@ -660,46 +654,42 @@                 offset 1                 limit 2                 return p-        liftIO $ ret4 `shouldBe` [ p4e, p3e ]-        ret5 <- select $ do+            liftIO $ ret4 `shouldBe` [ p4e, p3e ]+            ret5 <-+                select $ do                 p <- people                 offset 1000                 limit  1                 limit  1000                 offset 0                 return p-        liftIO $ ret5 `shouldBe` [ p1e, p4e, p3e, p2e ]--    it "works with non-id primary key" $-      run $ do-        let fc = Frontcover number ""-            number = 101-            Right thePk = keyFromValues [toPersistValue number]-        fcPk <- insert fc-        [Entity _ ret] <- select $ from return-        liftIO $ do-          ret `shouldBe` fc-          fcPk `shouldBe` thePk--    it "works when returning a custom non-composite primary key from a query" $-      run $ do-        let name = "foo"-            t = Tag name-            Right thePk = keyFromValues [toPersistValue name]-        tagPk <- insert t-        [Value ret] <- select $ from $ \t' -> return (t'^.TagId)-        liftIO $ do-          ret `shouldBe` thePk-          thePk `shouldBe` tagPk+            liftIO $ ret5 `shouldBe` [ p1e, p4e, p3e, p2e ] -    it "works when returning a composite primary key from a query" $-      run $ do-        let p = Point 10 20 ""-        thePk <- insert p-        [Value ppk] <- select $ from $ \p' -> return (p'^.PointId)-        liftIO $ ppk `shouldBe` thePk+        it "works with non-id primary key" $ run $ do+            let fc = Frontcover number ""+                number = 101+                Right thePk = keyFromValues [toPersistValue number]+            fcPk <- insert fc+            [Entity _ ret] <- select $ from return+            liftIO $ do+                ret `shouldBe` fc+                fcPk `shouldBe` thePk +        it "works when returning a custom non-composite primary key from a query" $ run $ do+            let name = "foo"+                t = Tag name+                Right thePk = keyFromValues [toPersistValue name]+            tagPk <- insert t+            [Value ret] <- select $ from $ \t' -> return (t'^.TagId)+            liftIO $ do+                ret `shouldBe` thePk+                thePk `shouldBe` tagPk +        it "works when returning a composite primary key from a query" $ run $ do+            let p = Point 10 20 ""+            thePk <- insert p+            [Value ppk] <- select $ from $ \p' -> return (p'^.PointId)+            liftIO $ ppk `shouldBe` thePk  testSelectJoin :: Run -> Spec testSelectJoin run = do@@ -883,10 +873,8 @@           liftIO $ (entityVal <$> ps) `shouldBe` [p1]  testSelectSubQuery :: Run -> Spec-testSelectSubQuery run = do-  describe "select subquery" $ do-    it "works" $ do-      run $ do+testSelectSubQuery run = describe "select subquery" $ do+    it "works" $ run $ do         _ <- insert' p1         let q = do                 p <- Experimental.from $ Table @Person@@ -894,8 +882,7 @@         ret <- select $ Experimental.from q         liftIO $ ret `shouldBe` [ (Value $ personName p1, Value $ personAge p1) ] -    it "supports sub-selecting Maybe entities" $ do-      run $ do+    it "supports sub-selecting Maybe entities" $ run $ do         l1e <- insert' l1         l3e <- insert' l3         l1Deeds <- mapM (\k -> insert' $ Deed k (entityKey l1e)) (map show [1..3 :: Int])@@ -909,8 +896,7 @@           pure (lords, deeds)         liftIO $ ret `shouldMatchList` ((l3e, Nothing) : l1WithDeeds) -    it "lets you order by alias" $ do-      run $ do+    it "lets you order by alias" $ run $ do         _ <- insert' p1         _ <- insert' p3         let q = do@@ -923,8 +909,7 @@         ret <- select q         liftIO $ ret `shouldBe` [ Value $ personName p3, Value $ personName p1 ] -    it "supports groupBy" $ do-      run $ do+    it "supports groupBy" $ run $ do         l1k <- insert l1         l3k <- insert l3         mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int])@@ -945,8 +930,7 @@         liftIO $ ret `shouldMatchList` [ (Value l3k, Value 7)                                        , (Value l1k, Value 3) ] -    it "Can count results of aggregate query" $ do-      run $ do+    it "Can count results of aggregate query" $ run $ do         l1k <- insert l1         l3k <- insert l3         mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int])@@ -967,8 +951,7 @@          liftIO $ ret `shouldMatchList` [ (Value 1) ] -    it "joins on subqueries" $ do-      run $ do+    it "joins on subqueries" $ run $ do         l1k <- insert l1         l3k <- insert l3         mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int])@@ -985,8 +968,7 @@         liftIO $ ret `shouldMatchList` [ (Value l3k, Value 7)                                        , (Value l1k, Value 3) ] -    it "flattens maybe values" $ do-      run $ do+    it "flattens maybe values" $ run $ do         l1k <- insert l1         l3k <- insert l3         let q = do@@ -1001,8 +983,7 @@         (ret :: [(Value (Key Lord), Value (Maybe Int))]) <- select q         liftIO $ ret `shouldMatchList` [ (Value l3k, Value (lordDogs l3))                                        , (Value l1k, Value (lordDogs l1)) ]-    it "unions" $ do-        run $ do+    it "unions" $ run $ do           _ <- insert p1           _ <- insert p2           let q = Experimental.from $@@ -1024,10 +1005,8 @@           liftIO $ names `shouldMatchList` [ (Value $ personName p1)                                            , (Value $ personName p2) ] testSelectWhere :: Run -> Spec-testSelectWhere run = do-  describe "select where_" $ do-    it "works for a simple example with (==.)" $-      run $ do+testSelectWhere run = describe "select where_" $ do+    it "works for a simple example with (==.)" $ run $ do         p1e <- insert' p1         _   <- insert' p2         _   <- insert' p3@@ -1037,8 +1016,7 @@                return p         liftIO $ ret `shouldBe` [ p1e ] -    it "works for a simple example with (==.) and (||.)" $-      run $ do+    it "works for a simple example with (==.) and (||.)" $ run $ do         p1e <- insert' p1         p2e <- insert' p2         _   <- insert' p3@@ -1048,8 +1026,7 @@                return p         liftIO $ ret `shouldBe` [ p1e, p2e ] -    it "works for a simple example with (>.) [uses val . Just]" $-      run $ do+    it "works for a simple example with (>.) [uses val . Just]" $ run $ do         p1e <- insert' p1         _   <- insert' p2         _   <- insert' p3@@ -1059,8 +1036,7 @@                return p         liftIO $ ret `shouldBe` [ p1e ] -    it "works for a simple example with (>.) and not_ [uses just . val]" $-      run $ do+    it "works for a simple example with (>.) and not_ [uses just . val]" $ run $ do         _   <- insert' p1         _   <- insert' p2         p3e <- insert' p3@@ -1071,55 +1047,50 @@         liftIO $ ret `shouldBe` [ p3e ]      describe "when using between" $ do-      it "works for a simple example with [uses just . val]" $-        run $ do-          p1e  <- insert' p1-          _    <- insert' p2-          _    <- insert' p3-          ret  <- select $-            from $ \p -> do-              where_ ((p ^. PersonAge) `between` (just $ val 20, just $ val 40))-              return p-          liftIO $ ret `shouldBe` [ p1e ]-      it "works for a proyected fields value" $-        run $ do-          _ <- insert' p1 >> insert' p2 >> insert' p3-          ret <--            select $-            from $ \p -> do-            where_ $-              just (p ^. PersonFavNum)-                `between`-                  (p ^. PersonAge, p ^.  PersonWeight)-          liftIO $ ret `shouldBe` []-      describe "when projecting composite keys" $ do-        it "works when using composite keys with val" $-          run $ do-            insert_ $ Point 1 2 ""-            ret <--              select $+        it "works for a simple example with [uses just . val]" $ run $ do+            p1e  <- insert' p1+            _    <- insert' p2+            _    <- insert' p3+            ret  <- select $               from $ \p -> do-              where_ $-                p ^. PointId-                  `between`-                    ( val $ PointKey 1 2-                    , val $ PointKey 5 6 )-            liftIO $ ret `shouldBe` [()]-        it "works when using ECompositeKey constructor" $-          run $ do-            insert_ $ Point 1 2 ""+                where_ ((p ^. PersonAge) `between` (just $ val 20, just $ val 40))+                return p+            liftIO $ ret `shouldBe` [ p1e ]+        it "works for a proyected fields value" $ run $ do+            _ <- insert' p1 >> insert' p2 >> insert' p3             ret <-               select $               from $ \p -> do               where_ $-                p ^. PointId+                just (p ^. PersonFavNum)                   `between`-                    ( EI.ECompositeKey $ const ["3", "4"]-                    , EI.ECompositeKey $ const ["5", "6"] )+                    (p ^. PersonAge, p ^.  PersonWeight)             liftIO $ ret `shouldBe` []+        describe "when projecting composite keys" $ do+            it "works when using composite keys with val" $ run $ do+                insert_ $ Point 1 2 ""+                ret <-+                  select $+                  from $ \p -> do+                  where_ $+                    p ^. PointId+                      `between`+                        ( val $ PointKey 1 2+                        , val $ PointKey 5 6 )+                liftIO $ ret `shouldBe` [()]+            it "works when using ECompositeKey constructor" $ run $ do+                insert_ $ Point 1 2 ""+                ret <-+                  select $+                  from $ \p -> do+                  where_ $+                    p ^. PointId+                      `between`+                        ( EI.ECompositeKey $ const ["3", "4"]+                        , EI.ECompositeKey $ const ["5", "6"] )+                liftIO $ ret `shouldBe` [] -    it "works with avg_" $-      run $ do+    it "works with avg_" $ run $ do         _ <- insert' p1         _ <- insert' p2         _ <- insert' p3@@ -1145,8 +1116,7 @@                return $ joinV $ min_ (p ^. PersonAge)         liftIO $ ret `shouldBe` [ Value $ Just (17 :: Int) ] -    it "works with max_" $-      run $ do+    it "works with max_" $ run $ do         _ <- insert' p1         _ <- insert' p2         _ <- insert' p3@@ -1156,8 +1126,7 @@                return $ joinV $ max_ (p ^. PersonAge)         liftIO $ ret `shouldBe` [ Value $ Just (36 :: Int) ] -    it "works with lower_" $-      run $ do+    it "works with lower_" $ run $ do         p1e <- insert' p1         p2e@(Entity _ bob) <- insert' $ Person "bob" (Just 36) Nothing   1 @@ -1175,13 +1144,11 @@                 return p         liftIO $ ret2 `shouldBe` [ p2e ] -    it "works with round_" $-      run $ do+    it "works with round_" $ run $ do         ret <- select $ return $ round_ (val (16.2 :: Double))         liftIO $ ret `shouldBe` [ Value (16 :: Double) ] -    it "works with isNothing" $-      run $ do+    it "works with isNothing" $ run $ do         _   <- insert' p1         p2e <- insert' p2         _   <- insert' p3@@ -1191,8 +1158,7 @@                return p         liftIO $ ret `shouldBe` [ p2e ] -    it "works with not_ . isNothing" $-      run $ do+    it "works with not_ . isNothing" $ run $ do         p1e <- insert' p1         _   <- insert' p2         ret <- select $@@ -1223,8 +1189,7 @@                                 , (p4e, f42, p2e)                                 , (p2e, f21, p1e) ] -    it "works for a many-to-many explicit join" $-      run $ do+    it "works for a many-to-many explicit join" $ run $ do         p1e@(Entity p1k _) <- insert' p1         p2e@(Entity p2k _) <- insert' p2         _                  <- insert' p3@@ -1256,8 +1221,7 @@       -- we only care that we don't have a SQL error       True `shouldBe` True -    it "works for a many-to-many explicit join with LEFT OUTER JOINs" $-      run $ do+    it "works for a many-to-many explicit join with LEFT OUTER JOINs" $ run $ do         p1e@(Entity p1k _) <- insert' p1         p2e@(Entity p2k _) <- insert' p2         p3e                <- insert' p3@@ -1279,8 +1243,7 @@                                 , (p3e, Nothing,  Nothing)                                 , (p2e, Just f21, Just p1e) ] -    it "works with a composite primary key" $-      run $ do+    it "works with a composite primary key" $ run $ do         let p = Point x y ""             x = 10             y = 15@@ -1293,13 +1256,9 @@           ret `shouldBe` p           pPk `shouldBe` thePk -- testSelectOrderBy :: Run -> Spec-testSelectOrderBy run = do-  describe "select/orderBy" $ do-    it "works with a single ASC field" $-      run $ do+testSelectOrderBy run = describe "select/orderBy" $ do+    it "works with a single ASC field" $ run $ do         p1e <- insert' p1         p2e <- insert' p2         p3e <- insert' p3@@ -1309,8 +1268,7 @@                return p         liftIO $ ret `shouldBe` [ p1e, p3e, p2e ] -    it "works with a sub_select" $-      run $ do+    it "works with a sub_select" $ run $ do         [p1k, p2k, p3k, p4k] <- mapM insert [p1, p2, p3, p4]         [b1k, b2k, b3k, b4k] <- mapM (insert . BlogPost "") [p1k, p2k, p3k, p4k]         ret <- select $@@ -1323,8 +1281,7 @@                return (b ^. BlogPostId)         liftIO $ ret `shouldBe` (Value <$> [b2k, b3k, b4k, b1k]) -    it "works on a composite primary key" $-      run $ do+    it "works on a composite primary key" $ run $ do         let ps = [Point 2 1 "", Point 1 2 ""]         mapM_ insert ps         eps <- select $@@ -1334,10 +1291,8 @@         liftIO $ map entityVal eps `shouldBe` reverse ps  testAscRandom :: SqlExpr (Value Double) -> Run -> Spec-testAscRandom rand' run =-  describe "random_" $-    it "asc random_ works" $-      run $ do+testAscRandom rand' run = describe "random_" $+    it "asc random_ works" $ run $ do         _p1e <- insert' p1         _p2e <- insert' p2         _p3e <- insert' p3@@ -1382,10 +1337,8 @@   testCoasleceDefault :: Run -> Spec-testCoasleceDefault run = do-  describe "coalesce/coalesceDefault" $ do-    it "works on a simple example" $-      run $ do+testCoasleceDefault run = describe "coalesce/coalesceDefault" $ do+    it "works on a simple example" $ run $ do         mapM_ insert' [p1, p2, p3, p4, p5]         ret1 <- select $                 from $ \p -> do@@ -1409,8 +1362,7 @@                                  , Value 5                                  ] -    it "works with sub-queries" $-      run $ do+    it "works with sub-queries" $ run $ do         p1id <- insert p1         p2id <- insert p2         p3id <- insert p3@@ -1432,12 +1384,9 @@                                 ]  - testDelete :: Run -> Spec-testDelete run = do-  describe "delete" $-    it "works on a simple example" $-      run $ do+testDelete run = describe "delete" $ do+    it "works on a simple example" $ run $ do         p1e <- insert' p1         p2e <- insert' p2         p3e <- insert' p3@@ -1458,14 +1407,9 @@         ret3 <- getAll         liftIO $ (n, ret3) `shouldBe` (2, []) -- testUpdate :: Run -> Spec-testUpdate run = do-  describe "update" $ do--    it "works with a subexpression having COUNT(*)" $-      run $ do+testUpdate run = describe "update" $ do+    it "works with a subexpression having COUNT(*)" $ run $ do         p1k <- insert p1         p2k <- insert p2         p3k <- insert p3@@ -1486,7 +1430,7 @@                                 , Entity p2k p2 { personAge = Just 0 } ]      it "works with a composite primary key" $-      pendingWith "Need refactor to support composite pks on ESet"+        pendingWith "Need refactor to support composite pks on ESet"       {-       run $ do         let p = Point x y ""@@ -1503,8 +1447,7 @@           ret `shouldBe` Point newX newY []       -} -    it "GROUP BY works with COUNT" $-      run $ do+    it "GROUP BY works with COUNT" $ run $ do         p1k <- insert p1         p2k <- insert p2         p3k <- insert p3@@ -1521,8 +1464,7 @@                                 , (Entity p1k p1, Value 3)                                 , (Entity p3k p3, Value 7) ] -    it "GROUP BY works with COUNT and InnerJoin" $-      run $ do+    it "GROUP BY works with COUNT and InnerJoin" $ run $ do         l1k <- insert l1         l3k <- insert l3         mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int])@@ -1537,8 +1479,7 @@         liftIO $ ret `shouldMatchList` [ (Value l3k, Value 7)                                        , (Value l1k, Value 3) ] -    it "GROUP BY works with nested tuples" $ do-      run $ do+    it "GROUP BY works with nested tuples" $ run $ do         l1k <- insert l1         l3k <- insert l3         mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int])@@ -1551,8 +1492,8 @@           groupBy ((lord ^. LordId, lord ^. LordDogs), deed ^. DeedContract)           return (lord ^. LordId, count $ deed ^. DeedId)         liftIO $ length ret `shouldBe` 10-    it "GROUP BY works with HAVING" $-      run $ do++    it "GROUP BY works with HAVING" $ run $ do         p1k <- insert p1         _p2k <- insert p2         p3k <- insert p3@@ -1569,7 +1510,6 @@         liftIO $ ret `shouldBe` [ (Entity p1k p1, Value (3 :: Int))                                 , (Entity p3k p3, Value 7) ] - -- we only care that this compiles. check that SqlWriteT doesn't fail on -- updates. testSqlWriteT :: MonadIO m => SqlWriteT m ()@@ -1597,10 +1537,8 @@   return (lord ^. LordId, count $ deed ^. DeedId)  testListOfValues :: Run -> Spec-testListOfValues run = do-  describe "lists of values" $ do-    it "IN works for valList" $-      run $ do+testListOfValues run = describe "lists of values" $ do+    it "IN works for valList" $ run $ do         p1k <- insert p1         p2k <- insert p2         _p3k <- insert p3@@ -1611,8 +1549,7 @@         liftIO $ ret `shouldBe` [ Entity p1k p1                                 , Entity p2k p2 ] -    it "IN works for valList (null list)" $-      run $ do+    it "IN works for valList (null list)" $ run $ do         _p1k <- insert p1         _p2k <- insert p2         _p3k <- insert p3@@ -1622,8 +1559,7 @@                return p         liftIO $ ret `shouldBe` [] -    it "IN works for subList_select" $-      run $ do+    it "IN works for subList_select" $ run $ do         p1k <- insert p1         _p2k <- insert p2         p3k <- insert p3@@ -1639,8 +1575,7 @@                return p         liftIO $ L.sort ret `shouldBe` L.sort [Entity p1k p1, Entity p3k p3] -    it "NOT IN works for subList_select" $-      run $ do+    it "NOT IN works for subList_select" $ run $ do         p1k <- insert p1         p2k <- insert p2         p3k <- insert p3@@ -1655,8 +1590,7 @@                return p         liftIO $ ret `shouldBe` [ Entity p2k p2 ] -    it "EXISTS works for subList_select" $-      run $ do+    it "EXISTS works for subList_select" $ run $ do         p1k <- insert p1         _p2k <- insert p2         p3k <- insert p3@@ -1672,8 +1606,7 @@         liftIO $ ret `shouldBe` [ Entity p1k p1                                 , Entity p3k p3 ] -    it "EXISTS works for subList_select" $-      run $ do+    it "EXISTS works for subList_select" $ run $ do         p1k <- insert p1         p2k <- insert p2         p3k <- insert p3@@ -1687,24 +1620,14 @@                return p         liftIO $ ret `shouldBe` [ Entity p2k p2 ] ---- testListFields :: Run -> Spec-testListFields run = do-  describe "list fields" $ do+testListFields run = describe "list fields" $ do     -- <https://github.com/prowdsponsor/esqueleto/issues/100>-    it "can update list fields" $-      run $ do+    it "can update list fields" $ run $ do         cclist <- insert $ CcList []         update $ \p -> do-          set p [ CcListNames =. val ["fred"]]-          where_ (p ^. CcListId ==. val cclist)----+            set p [ CcListNames =. val ["fred"]]+            where_ (p ^. CcListId ==. val cclist)  testInsertsBySelect :: Run -> Spec testInsertsBySelect run = do@@ -1943,21 +1866,21 @@       expr `shouldBe` "? = ?"    describe "EEntity Ident behavior" $ do-    let-      render :: SqlExpr (Entity val) -> Text.Text-      render (EI.EEntity (EI.I ident)) = ident-    it "renders sensibly" $ do-      results <- run $ do-        _ <- insert $ Foo 2-        _ <- insert $ Foo 3-        _ <- insert $ Person "hello" Nothing Nothing 3-        select $-          from $ \(a `LeftOuterJoin` b) -> do-          on $ a ^. FooName ==. b ^. PersonFavNum-          pure (val (render a), val (render b))-      head results-        `shouldBe`-          (Value "Foo", Value "Person")+      let render :: SqlExpr (Entity val) -> Text.Text+          render (EI.EEntity (EI.I ident)) = ident+          render _ = error "guess we gotta handle this in the test suite now"+      it "renders sensibly" $ run $ do+          _ <- insert $ Foo 2+          _ <- insert $ Foo 3+          _ <- insert $ Person "hello" Nothing Nothing 3+          results <- select $+              from $ \(a `LeftOuterJoin` b) -> do+              on $ a ^. FooName ==. b ^. PersonFavNum+              pure (val (render a), val (render b))+          liftIO $+              head results+              `shouldBe`+              (Value "Foo", Value "Person")    describe "ExprParser" $ do     let parse parser = AP.parseOnly (parser '#')
test/MySQL/Test.hs view
@@ -16,6 +16,7 @@                               , connectDatabase                               , connectUser                               , connectPassword+                              , connectPort                               , defaultConnectInfo) import Database.Esqueleto import Database.Esqueleto.Experimental hiding (from, on)@@ -239,8 +240,9 @@ withConn =   R.runResourceT .   withMySQLConn defaultConnectInfo-    { connectHost     = "localhost"+    { connectHost     = "127.0.0.1"     , connectUser     = "travis"-    , connectPassword = ""+    , connectPassword = "esqutest"     , connectDatabase = "esqutest"+    , connectPort     = 33306     }
test/PostgreSQL/MigrateJSON.hs view
@@ -1,17 +1,19 @@-{-# LANGUAGE FlexibleContexts-           , GADTs-           , GeneralizedNewtypeDeriving-           , DerivingStrategies-           , StandaloneDeriving-           , MultiParamTypeClasses-           , OverloadedStrings-           , QuasiQuotes-           , RankNTypes-           , ScopedTypeVariables-           , TemplateHaskell-           , TypeFamilies-           , UndecidableInstances- #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+ module PostgreSQL.MigrateJSON where  import Control.Monad.Trans.Resource (ResourceT)
test/PostgreSQL/Test.hs view
@@ -559,7 +559,7 @@       run $ do         nowDb <- select $ return EP.now_         nowUtc <- liftIO getCurrentTime-        let halfSecond = realToFrac (0.5 :: Double)+        let oneSecond = realToFrac (1 :: Double)          -- | Check the result is not null         liftIO $ nowDb `shouldSatisfy` (not . null)@@ -567,8 +567,8 @@         -- | Unpack the now value         let (Value now: _) = nowDb -        -- | Get the time diff and check it's less than half a second-        liftIO $ diffUTCTime nowUtc now `shouldSatisfy` (< halfSecond)+        -- | Get the time diff and check it's less than a second+        liftIO $ diffUTCTime nowUtc now `shouldSatisfy` (< oneSecond)   --------------- JSON --------------- JSON --------------- JSON ---------------@@ -1346,39 +1346,38 @@  main :: IO () main = do-  hspec $ do-    tests run--    describe "Test PostgreSQL locking" $ do-      testLocking withConn+    hspec $ do+        tests run -    describe "PostgreSQL specific tests" $ do-      testAscRandom random_ run-      testRandomMath run-      testSelectDistinctOn-      testPostgresModule-      testPostgresqlOneAscOneDesc-      testPostgresqlTwoAscFields-      testPostgresqlSum-      testPostgresqlRandom-      testPostgresqlUpdate-      testPostgresqlCoalesce-      testPostgresqlTextFunctions-      testInsertUniqueViolation-      testUpsert-      testInsertSelectWithConflict-      testFilterWhere-      testCommonTableExpressions-      describe "PostgreSQL JSON tests" $ do-        -- NOTE: We only clean the table once, so we-        -- can use its contents across all JSON tests-        it "MIGRATE AND CLEAN JSON TABLE" $ run $ do-          void $ runMigrationSilent migrateJSON-          cleanJSON-        testJSONInsertions-        testJSONOperators-      testLateralQuery+        describe "Test PostgreSQL locking" $ do+            testLocking withConn +        describe "PostgreSQL specific tests" $ do+            testAscRandom random_ run+            testRandomMath run+            testSelectDistinctOn+            testPostgresModule+            testPostgresqlOneAscOneDesc+            testPostgresqlTwoAscFields+            testPostgresqlSum+            testPostgresqlRandom+            testPostgresqlUpdate+            testPostgresqlCoalesce+            testPostgresqlTextFunctions+            testInsertUniqueViolation+            testUpsert+            testInsertSelectWithConflict+            testFilterWhere+            testCommonTableExpressions+            describe "PostgreSQL JSON tests" $ do+                -- NOTE: We only clean the table once, so we+                -- can use its contents across all JSON tests+                it "MIGRATE AND CLEAN JSON TABLE" $ run $ do+                    void $ runMigrationSilent migrateJSON+                    cleanJSON+                testJSONInsertions+                testJSONOperators+            testLateralQuery  run, runSilent, runVerbose :: Run runSilent  act = runNoLoggingT     $ run_worker act