-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A pleasant PostgreSQL layer -- -- A PostgreSQL layer to safely expand your SQL queries with a -- lightweight eDSL. Read the tutorial at -- https://tchoutri.github.io/pg-entity/Tutorial @package pg-entity @version 0.0.4.2 -- | The DBT plumbing module to handle database queries and pools module Database.PostgreSQL.Entity.DBT -- | Create a Pool Connection with the appropriate parameters mkPool :: ConnectInfo -> Int -> NominalDiffTime -> Int -> IO (Pool Connection) -- | Run a DBT action with no explicit error handling. -- -- This functions is suited for using MonadError error handling. -- --
-- let e1 = E 1 True True -- result <- runExceptT @EntityError $ do -- withPool pool $ insertEntity e1 -- withPool pool $ markForProcessing 1 -- case result of -- Left err -> print err -- Right _ -> putStrLn "Everything went well" ---- -- See the code in the example/ directory on GitHub withPool :: MonadIO m => Pool Connection -> DBT IO a -> m a -- | Query wrapper for SQL statements which do not return. execute :: (ToRow params, MonadIO m) => QueryNature -> Query -> params -> DBT m Int64 -- | Query wrapper for SQL statements that operate on multiple rows which -- do not return. executeMany :: (ToRow params, MonadIO m) => QueryNature -> Query -> [params] -> DBT m Int64 -- | Query wrapper that returns a Vector of results query :: (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Vector result) -- | Query wrapper that returns a Vector of results and does not -- take an argument query_ :: (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Vector result) -- | Query wrapper that returns one result. queryOne :: (ToRow params, FromRow result, MonadIO m) => QueryNature -> Query -> params -> DBT m (Maybe result) -- | Query wrapper that returns one result and does not take an argument queryOne_ :: (FromRow result, MonadIO m) => QueryNature -> Query -> DBT m (Maybe result) -- | This sum type is given to the query, queryOne and -- execute functions to help with logging. data QueryNature Select :: QueryNature Insert :: QueryNature Update :: QueryNature Delete :: QueryNature instance GHC.Show.Show Database.PostgreSQL.Entity.DBT.QueryNature instance GHC.Classes.Eq Database.PostgreSQL.Entity.DBT.QueryNature -- | Contains the internals of several key types. -- --
-- instance Entity BlogPost where -- tableName = "blogposts" -- primaryKey = [field| blogpost_id |] -- fields = [ [field| blogpost_id |] -- , [field| author_id |] -- , [field| uuid_list :: uuid[] |] -- ← This is where we specify an optional PostgreSQL type annotation -- , [field| title |] -- , [field| content |] -- , [field| created_at |] -- ] --field :: QuasiQuoter -- | Types and classes module Database.PostgreSQL.Entity.Types -- | An Entity stores the following information about the structure -- of a database table: -- --
-- data ExampleEntity = E
-- { key :: Key
-- , field1 :: Int
-- , field2 :: Bool
-- }
-- deriving stock (Eq, Show, Generic)
-- deriving anyclass (FromRow, ToRow)
-- deriving Entity
-- via (GenericEntity '[TableName "entities"] ExampleEntity)
--
--
-- When using the functions provided by this library, you will sometimes
-- need to be explicit about the Entity you are referring to.
class Entity e
-- | The name of the table in the PostgreSQL database.
tableName :: Entity e => Text
-- | The name of the table in the PostgreSQL database.
tableName :: (Entity e, GetTableName (Rep e)) => Text
-- | The name of the schema; will be appended to the table name:
-- schema."tablename"
schema :: Entity e => Maybe Text
-- | The name of the primary key for the table.
primaryKey :: Entity e => Field
-- | The name of the primary key for the table.
primaryKey :: (Entity e, GetFields (Rep e)) => Field
-- | The fields of the table.
fields :: Entity e => Vector Field
-- | The fields of the table.
fields :: (Entity e, GetFields (Rep e)) => Vector Field
-- | A wrapper for table fields.
data Field
-- | A quasi-quoter for safely constructing Fields.
--
-- -- instance Entity BlogPost where -- tableName = "blogposts" -- primaryKey = [field| blogpost_id |] -- fields = [ [field| blogpost_id |] -- , [field| author_id |] -- , [field| uuid_list :: uuid[] |] -- ← This is where we specify an optional PostgreSQL type annotation -- , [field| title |] -- , [field| content |] -- , [field| created_at |] -- ] --field :: QuasiQuoter -- | Get the name of a field. fieldName :: Field -> Text -- | Get the type of a field, if any. fieldType :: Field -> Maybe Text -- | Wrapper used by the update function in order to have the primary key -- as the last parameter passed, since it appears in the WHERE clause. newtype UpdateRow a UpdateRow :: a -> UpdateRow a [$sel:getUpdate:UpdateRow] :: UpdateRow a -> a data SortKeyword ASC :: SortKeyword DESC :: SortKeyword -- | Term-level options data Options Options :: (Text -> Text) -> Maybe Text -> (Text -> Text) -> (Text -> Text) -> Options [$sel:tableNameModifiers:Options] :: Options -> Text -> Text [$sel:schemaModifier:Options] :: Options -> Maybe Text [$sel:primaryKeyModifiers:Options] :: Options -> Text -> Text [$sel:fieldModifiers:Options] :: Options -> Text -> Text defaultEntityOptions :: Options newtype GenericEntity t e GenericEntity :: e -> GenericEntity t e [$sel:getGenericEntity:GenericEntity] :: GenericEntity t e -> e -- | Type-level options for Deriving Via class EntityOptions xs entityOptions :: EntityOptions xs => Options data PrimaryKey (t :: Symbol) data Schema (t :: Symbol) data TableName (t :: Symbol) -- | Contains a list of TextModifiers modifiers data FieldModifiers ms -- | The modifiers that you can apply to the fields: -- --
-- >>> isNotNull [ [field| possibly_empty |] ] -- "\"possibly_empty\" IS NOT NULL" ---- --
-- >>> isNotNull [[field| possibly_empty |], [field| that_one_too |]] -- "\"possibly_empty\" IS NOT NULL AND \"that_one_too\" IS NOT NULL" --isNotNull :: Vector Field -> Text -- | Produce an IS NULL statement given a vector of fields -- --
-- >>> isNull [ [field| possibly_empty |] ] -- "\"possibly_empty\" IS NULL" ---- --
-- >>> isNull [[field| possibly_empty |], [field| that_one_too |]] -- "\"possibly_empty\" IS NULL AND \"that_one_too\" IS NULL" --isNull :: Vector Field -> Text isIn :: Field -> Vector Text -> Text -- | Wrap the given text between parentheses -- -- Examples -- --
-- >>> inParens "wrap me!" -- "(wrap me!)" --inParens :: Text -> Text -- | Wrap the given text between double quotes -- -- Examples -- --
-- >>> quoteName "meow." -- "\"meow.\"" --quoteName :: Text -> Text -- | Wrap the given text between single quotes, for literal text in an SQL -- query. -- -- Examples -- --
-- >>> literal "meow." -- "'meow.'" --literal :: Text -> Text -- | Safe getter that quotes a table name -- -- Examples -- --
-- >>> getTableName @Author -- "\"authors\"" -- -- >>> getTableName @Tags -- "public.\"tags\"" --getTableName :: forall e. Entity e => Text -- | Accessor to the name of a field, with quotation. -- --
-- >>> getFieldName ([field| author_id |]) -- "\"author_id\"" --getFieldName :: Field -> Text -- | Safe getter that quotes a table's primary key -- -- Examples -- --
-- >>> getPrimaryKey @Author -- "\"author_id\"" -- -- >>> getPrimaryKey @Tags -- "\"category\"" --getPrimaryKey :: forall e. Entity e => Text prefix :: Maybe Text -> Text -- | Produce a comma-separated list of an entity's fields. -- -- Examples -- --
-- >>> expandFields @BlogPost -- "\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\"" --expandFields :: forall e. Entity e => Text -- | Produce a comma-separated list of an entity's fields, qualified with -- the table name -- -- Examples -- --
-- >>> expandQualifiedFields @BlogPost -- "blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\"" --expandQualifiedFields :: forall e. Entity e => Text -- | Produce a comma-separated list of an entity's fields, qualified -- with an arbitrary prefix -- -- Examples -- --
-- >>> expandQualifiedFields' (fields @BlogPost) "legacy" -- "legacy.\"blogpost_id\", legacy.\"author_id\", legacy.\"uuid_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\"" --expandQualifiedFields' :: Vector Field -> Text -> Text -- | Take a prefix and a vector of fields, and qualifies each field with -- the prefix -- -- Examples -- --
-- >>> qualifyField @Author [field| name |] -- "authors.\"name\"" --qualifyField :: forall e. Entity e => Field -> Text -- | Take a prefix and a vector of fields, and qualifies each field with -- the prefix -- -- Examples -- --
-- >>> qualifyFields "legacy" (fields @BlogPost) -- [Field "legacy.\"blogpost_id\"" Nothing,Field "legacy.\"author_id\"" Nothing,Field "legacy.\"uuid_list\"" Nothing,Field "legacy.\"title\"" Nothing,Field "legacy.\"content\"" Nothing,Field "legacy.\"created_at\"" Nothing] --qualifyFields :: Text -> Vector Field -> Vector Field -- | Produce a placeholder of the form "field" = ? with an -- optional type annotation. -- -- Examples -- --
-- >>> placeholder [field| id |] -- "\"id\" = ?" ---- --
-- >>> placeholder $ [field| ids |] -- "\"ids\" = ?" ---- --
-- >>> fmap placeholder $ fields @BlogPost -- ["\"blogpost_id\" = ?","\"author_id\" = ?","\"uuid_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"] --placeholder :: Field -> Text -- | Produce a placeholder of the form table."field" = ? with an -- optional type annotation. -- -- Examples -- --
-- >>> placeholder' @BlogPost [field| id |] -- "blogposts.\"id\" = ?" ---- --
-- >>> placeholder' @BlogPost $ [field| ids |] -- "blogposts.\"ids\" = ?" --placeholder' :: forall e. Entity e => Field -> Text -- | Generate an appropriate number of “?” placeholders given a vector of -- fields. -- -- Used to generate INSERT queries. -- -- Examples -- --
-- >>> generatePlaceholders $ fields @BlogPost -- "?, ?, ?, ?, ?, ?" --generatePlaceholders :: Vector Field -> Text -- | Since the Query type has an IsString instance, the -- process of converting from Text to String to -- Query is factored into this function -- -- ⚠ This may be dangerous and an unregulated usage of this function may -- expose to you SQL injection attacks @since 0.0.1.0 textToQuery :: Text -> Query -- | For cases where combinator composition is tricky, we can safely get -- back to a Text string from a Query -- -- ⚠ This may be dangerous and an unregulated usage of this function may -- expose to you SQL injection attacks @since 0.0.1.0 queryToText :: Query -> Text -- | The intercalateVector function takes a Text and a Vector Text -- and concatenates the vector after interspersing the first argument -- between each element of the list. -- -- Examples -- --
-- >>> intercalateVector "~" [] -- [] ---- --
-- >>> intercalateVector "~" ["nyan"] -- ["nyan"] ---- --
-- >>> intercalateVector "~" ["nyan", "nyan", "nyan"] -- ["nyan","~","nyan","~","nyan"] --intercalateVector :: Text -> Vector Text -> Vector Text -- | Examples -- --
-- >>> renderSortExpression ([field| title |], ASC) -- "\"title\" ASC" --renderSortExpression :: (Field, SortKeyword) -> Text -- | A PostgreSQL database layer that does not get in your way. -- -- See the Database.PostgreSQL.Entity.Internal.BlogPost module for -- an example of a data-type implementing the Entity typeclass. module Database.PostgreSQL.Entity -- | An Entity stores the following information about the structure -- of a database table: -- --
-- data ExampleEntity = E
-- { key :: Key
-- , field1 :: Int
-- , field2 :: Bool
-- }
-- deriving stock (Eq, Show, Generic)
-- deriving anyclass (FromRow, ToRow)
-- deriving Entity
-- via (GenericEntity '[TableName "entities"] ExampleEntity)
--
--
-- When using the functions provided by this library, you will sometimes
-- need to be explicit about the Entity you are referring to.
class Entity e
-- | The name of the table in the PostgreSQL database.
tableName :: Entity e => Text
-- | The name of the table in the PostgreSQL database.
tableName :: (Entity e, GetTableName (Rep e)) => Text
-- | The name of the schema; will be appended to the table name:
-- schema."tablename"
schema :: Entity e => Maybe Text
-- | The name of the primary key for the table.
primaryKey :: Entity e => Field
-- | The name of the primary key for the table.
primaryKey :: (Entity e, GetFields (Rep e)) => Field
-- | The fields of the table.
fields :: Entity e => Vector Field
-- | The fields of the table.
fields :: (Entity e, GetFields (Rep e)) => Vector Field
-- | A wrapper for table fields.
data Field
-- | Select an entity by its primary key.
selectById :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => value -> DBT m (Maybe e)
-- | Select precisely one entity by a provided field.
selectOneByField :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Maybe e)
-- | Select potentially many entities by a provided field.
selectManyByField :: forall e value m. (Entity e, FromRow e, MonadIO m, ToRow value) => Field -> value -> DBT m (Vector e)
-- | Select statement with a non-null condition
--
-- See _selectWhereNotNull for the generated query.
selectWhereNotNull :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
-- | Select statement with a null condition
--
-- See _selectWhereNull for the generated query.
selectWhereNull :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector Field -> DBT m (Vector e)
-- | Select statement when for an entity where the field is one of the
-- options passed
selectOneWhereIn :: forall e m. (Entity e, FromRow e, MonadIO m) => Field -> Vector Text -> DBT m (Maybe e)
-- | Perform a INNER JOIN between two entities
joinSelectById :: forall e1 e2 m. (Entity e1, Entity e2, FromRow e1, MonadIO m) => DBT m (Vector e1)
-- | Perform a INNER JOIN ON field1 WHERE field2 = value between
-- two entities
joinSelectOneByField :: forall e1 e2 value m. (Entity e1, Entity e2, FromRow e1, MonadIO m, ToField value) => Field -> Field -> value -> DBT m (Vector e1)
-- | Perform a SELECT + ORDER BY query on an entity
selectOrderBy :: forall e m. (Entity e, FromRow e, MonadIO m) => Vector (Field, SortKeyword) -> DBT m (Vector e)
-- | Insert an entity.
insert :: forall e values m. (Entity e, ToRow values, MonadIO m) => values -> DBT m ()
-- | Insert multiple rows of an entity.
insertMany :: forall e values m. (Entity e, ToRow values, MonadIO m) => [values] -> DBT m ()
-- | Insert an entity with a "ON CONFLICT DO UPDATE" clause on the primary
-- key as the conflict target
upsert :: forall e values m. (Entity e, ToRow values, MonadIO m) => values -> Vector Field -> DBT m ()
-- | Update an entity.
--
-- The Id of the entity is put at the end of the query automatically
-- through the use of UpdateRow. Examples
--
--
-- let newAuthor = oldAuthor{…}
-- update @Author newAuthor
--
update :: forall e newValue m. (Entity e, ToRow newValue, MonadIO m) => newValue -> DBT m ()
-- | Update rows of an entity matching the given value
--
-- -- let newName = "Tiberus McElroy" :: Text -- let oldName = "Johnson McElroy" :: Text -- updateFieldsBy @Author [[field| name |]] ([field| name |], oldName) (Only newName) --updateFieldsBy :: forall e v1 v2 m. (Entity e, MonadIO m, ToRow v2, ToField v1) => Vector Field -> (Field, v1) -> v2 -> DBT m Int64 -- | Delete an entity according to its primary key. delete :: forall e value m. (Entity e, ToRow value, MonadIO m) => value -> DBT m () -- | Delete rows according to the given fields -- --
-- deleteByField @BlogPost [[field| title |]] (Only "Echoes from the other world") --deleteByField :: forall e values m. (Entity e, ToRow values, MonadIO m) => Vector Field -> values -> DBT m () -- | Produce a SELECT statement for a given entity. -- -- Examples -- --
-- >>> _select @BlogPost -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\"" --_select :: forall e. Entity e => Query -- | Produce a SELECT statement with explicit fields for a given entity -- -- Examples -- --
-- >>> _selectWithFields @BlogPost [ [field| blogpost_id |], [field| created_at |] ] -- "SELECT \"blogposts\".\"blogpost_id\", \"blogposts\".\"created_at\" FROM \"\"blogposts\"\"" --_selectWithFields :: forall e. Entity e => Vector Field -> Query -- | Produce a WHERE clause, given a vector of fields. -- -- It is most useful composed with a _select or _delete, -- which is why these two combinations have their dedicated functions, -- but the user is free to compose their own queries. -- -- The Entity constraint is required for _where in order to -- get any type annotation that was given in the schema. Fields that do -- not exist in the Entity will be kept so that PostgreSQL can report the -- error. -- -- Examples -- --
-- >>> _select @BlogPost <> _where [[field| blogpost_id |]] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"blogpost_id\" = ?" ---- --
-- >>> _select @BlogPost <> _where [ [field| uuid_list |] ] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"uuid_list\" = ?" --_where :: Vector Field -> Query -- | Produce a SELECT statement for a given entity and fields. -- -- Examples -- --
-- >>> _selectWhere @BlogPost [ [field| author_id |] ] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ?" ---- --
-- >>> _selectWhere @BlogPost [ [field| author_id |], [field| title |]] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" = ? AND \"title\" = ?" --_selectWhere :: forall e. Entity e => Vector Field -> Query -- | Produce a SELECT statement where the provided fields are checked for -- being non-null. r -- --
-- >>> _selectWhereNotNull @BlogPost [ [field| author_id |] ] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NOT NULL" --_selectWhereNotNull :: forall e. Entity e => Vector Field -> Query -- | Produce a SELECT statement where the provided fields are checked for -- being null. -- --
-- >>> _selectWhereNull @BlogPost [ [field| author_id |] ] -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"author_id\" IS NULL" --_selectWhereNull :: forall e. Entity e => Vector Field -> Query -- | Produce a SELECT statement where the given field is checked aginst the -- provided array of values . -- --
-- >>> _selectWhereIn @BlogPost [field| title |] [ "Unnamed", "Mordred's Song" ]
-- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" WHERE \"title\" IN ('Unnamed', 'Mordred''s Song')"
--
_selectWhereIn :: forall e. Entity e => Field -> Vector Text -> Query
-- | Produce a "SELECT FROM" over two entities.
--
-- Examples
--
-- -- >>> _joinSelect @BlogPost @Author -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\", authors.\"author_id\", authors.\"name\", authors.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)" --_joinSelect :: forall e1 e2. (Entity e1, Entity e2) => Query -- | Produce a "INNER JOIN … USING(…)" fragment. -- -- Examples -- --
-- >>> _innerJoin @BlogPost [field| author_id |] -- " INNER JOIN \"blogposts\" USING(author_id)" --_innerJoin :: forall e. Entity e => Field -> Query -- | Produce a "SELECT [table1_fields, table2_fields] FROM table1 INNER -- JOIN table2 USING(table2_pk)" statement. The primary is used as the -- join point between the two tables. -- -- Examples -- --
-- >>> _joinSelectWithFields @BlogPost @Author [ [field| title |] ] [ [field| name |] ] -- "SELECT \"blogposts\".\"title\", \"authors\".\"name\" FROM \"blogposts\" INNER JOIN \"authors\" USING(author_id)" --_joinSelectWithFields :: forall e1 e2. (Entity e1, Entity e2) => Vector Field -> Vector Field -> Query -- | Produce a "SELECT FROM" over two entities. -- -- Examples -- --
-- >>> _joinSelectOneByField @BlogPost @Author [field| author_id |] [field| name |] :: Query -- "SELECT blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\" FROM \"blogposts\" INNER JOIN \"authors\" ON \"blogposts\".\"author_id\" = \"authors\".\"author_id\" WHERE authors.\"name\" = ?" --_joinSelectOneByField :: forall e1 e2. (Entity e1, Entity e2) => Field -> Field -> Query -- | Produce an INSERT statement for the given entity. -- -- Examples -- --
-- >>> _insert @BlogPost -- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)" --_insert :: forall e. Entity e => Query -- | Produce a "ON CONFLICT (target) DO UPDATE SET …" statement. -- -- Examples -- --
-- >>> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]] -- " ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" ---- --
-- >>> _onConflictDoUpdate [[field| blogpost_id |], [field| author_id |]] [ [field| title |], [field| content |]] -- " ON CONFLICT (blogpost_id, author_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" ---- --
-- >>> _insert @BlogPost <> _onConflictDoUpdate [[field| blogpost_id |]] [ [field| title |], [field| content |]] -- "INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (blogpost_id) DO UPDATE SET title = EXCLUDED.title, content = EXCLUDED.content" --_onConflictDoUpdate :: Vector Field -> Vector Field -> Query -- | Produce an UPDATE statement for the given entity by primary key -- -- Examples -- --
-- >>> _update @Author -- "UPDATE \"authors\" SET (\"name\", \"created_at\") = ROW(?, ?) WHERE \"author_id\" = ?" ---- --
-- >>> _update @BlogPost -- "UPDATE \"blogposts\" SET (\"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") = ROW(?, ?, ?, ?, ?) WHERE \"blogpost_id\" = ?" --_update :: forall e. Entity e => Query -- | Produce an UPDATE statement for the given entity by the given field. -- -- Examples -- --
-- >>> _updateBy @Author [field| name |] -- "UPDATE \"authors\" SET (\"name\", \"created_at\") = ROW(?, ?) WHERE \"name\" = ?" --_updateBy :: forall e. Entity e => Field -> Query -- | Produce an UPDATE statement for the given entity and fields, by -- primary key. -- --
-- >>> _updateFields @Author [ [field| name |] ] -- "UPDATE \"authors\" SET (\"name\") = ROW(?) WHERE \"author_id\" = ?" --_updateFields :: forall e. Entity e => Vector Field -> Query -- | Produce an UPDATE statement for the given entity and fields, by the -- specified field. -- --
-- >>> _updateFieldsBy @Author [ [field| name |] ] [field| name |] -- "UPDATE \"authors\" SET (\"name\") = ROW(?) WHERE \"name\" = ?" ---- --
-- >>> _updateFieldsBy @BlogPost [[field| author_id |], [field| title |]] [field| title |] -- "UPDATE \"blogposts\" SET (\"author_id\", \"title\") = ROW(?, ?) WHERE \"title\" = ?" --_updateFieldsBy :: forall e. Entity e => Vector Field -> Field -> Query -- | Produce a DELETE statement for the given entity, with a match on the -- Primary Key -- -- Examples -- --
-- >>> _delete @BlogPost -- "DELETE FROM \"blogposts\" WHERE \"blogpost_id\" = ?" --_delete :: forall e. Entity e => Query -- | Produce a DELETE statement for the given entity and fields -- -- Examples -- --
-- >>> _deleteWhere @BlogPost [[field| title |], [field| created_at |]] -- "DELETE FROM \"blogposts\" WHERE \"title\" = ? AND \"created_at\" = ?" --_deleteWhere :: forall e. Entity e => Vector Field -> Query -- | Produce an ORDER BY clause with one field and a sorting keyword -- -- Examples -- --
-- >>> _orderBy ([field| title |], ASC) -- " ORDER BY \"title\" ASC" --_orderBy :: (Field, SortKeyword) -> Query -- | Produce an ORDER BY clause with many fields and sorting keywords -- -- Examples -- --
-- >>> _orderByMany (V.fromList [([field| title |], ASC), ([field| created_at |], DESC)]) -- " ORDER BY \"title\" ASC, \"created_at\" DESC" --_orderByMany :: Vector (Field, SortKeyword) -> Query -- | Adapted from Clément Delafargue's Yet Another Unsafe DB Layer -- article. -- -- The models described in this module are used throughout the library's -- tests and docspecs. module Database.PostgreSQL.Entity.Internal.BlogPost -- | Wrapper around the UUID type newtype AuthorId AuthorId :: UUID -> AuthorId [$sel:getAuthorId:AuthorId] :: AuthorId -> UUID -- | Author data-type data Author Author :: AuthorId -> Text -> UTCTime -> Author [$sel:authorId:Author] :: Author -> AuthorId [$sel:name:Author] :: Author -> Text [$sel:createdAt:Author] :: Author -> UTCTime -- | Wrapper around the UUID type newtype BlogPostId BlogPostId :: UUID -> BlogPostId [$sel:getBlogPostId:BlogPostId] :: BlogPostId -> UUID newtype UUIDList UUIDList :: Vector UUID -> UUIDList [$sel:getUUIDList:UUIDList] :: UUIDList -> Vector UUID -- | The BlogPost data-type. Look at its Entity instance declaration -- for how to handle a "uuid[]" PostgreSQL type. data BlogPost BlogPost :: BlogPostId -> AuthorId -> UUIDList -> Text -> Text -> UTCTime -> BlogPost -- | Primary key [$sel:blogPostId:BlogPost] :: BlogPost -> BlogPostId -- | Foreign keys, for which we need an explicit type annotation [$sel:authorId:BlogPost] :: BlogPost -> AuthorId -- | A type that will need an explicit type annotation in the schema [$sel:uuidList:BlogPost] :: BlogPost -> UUIDList [$sel:title:BlogPost] :: BlogPost -> Text [$sel:content:BlogPost] :: BlogPost -> Text [$sel:createdAt:BlogPost] :: BlogPost -> UTCTime -- | A specialisation of the insert function. insertBlogPost = -- insert @BlogPost insertBlogPost :: BlogPost -> DBT IO () upsertBlogPost :: BlogPost -> Vector Field -> DBT IO () -- | A function to insert many blogposts at once. bulkInsertBlogPosts :: [BlogPost] -> DBT IO () -- | A specialisation of the 'Database.PostgreSQL.Entity.insert function. -- insertAuthor = insert @Author insertAuthor :: Author -> DBT IO () -- | A function to insert many authors at once. bulkInsertAuthors :: [Author] -> DBT IO () data Tags Tags :: Text -> [Text] -> Tags [$sel:category:Tags] :: Tags -> Text [$sel:labels:Tags] :: Tags -> [Text] instance Database.PostgreSQL.Simple.ToField.ToField Database.PostgreSQL.Entity.Internal.BlogPost.AuthorId instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.BlogPost.AuthorId instance GHC.Classes.Ord Database.PostgreSQL.Entity.Internal.BlogPost.AuthorId instance Database.PostgreSQL.Simple.FromField.FromField Database.PostgreSQL.Entity.Internal.BlogPost.AuthorId instance GHC.Classes.Eq Database.PostgreSQL.Entity.Internal.BlogPost.AuthorId instance Database.PostgreSQL.Entity.Types.Entity Database.PostgreSQL.Entity.Internal.BlogPost.Author instance Database.PostgreSQL.Simple.ToRow.ToRow Database.PostgreSQL.Entity.Internal.BlogPost.Author instance Database.PostgreSQL.Simple.FromRow.FromRow Database.PostgreSQL.Entity.Internal.BlogPost.Author instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.BlogPost.Author instance GHC.Classes.Ord Database.PostgreSQL.Entity.Internal.BlogPost.Author instance GHC.Generics.Generic Database.PostgreSQL.Entity.Internal.BlogPost.Author instance GHC.Classes.Eq Database.PostgreSQL.Entity.Internal.BlogPost.Author instance Database.PostgreSQL.Simple.ToField.ToField Database.PostgreSQL.Entity.Internal.BlogPost.BlogPostId instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.BlogPost.BlogPostId instance GHC.Classes.Ord Database.PostgreSQL.Entity.Internal.BlogPost.BlogPostId instance Database.PostgreSQL.Simple.FromField.FromField Database.PostgreSQL.Entity.Internal.BlogPost.BlogPostId instance GHC.Classes.Eq Database.PostgreSQL.Entity.Internal.BlogPost.BlogPostId instance GHC.Classes.Ord Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance Database.PostgreSQL.Simple.FromField.FromField Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance GHC.Classes.Eq Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance GHC.Generics.Generic Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance Database.PostgreSQL.Simple.ToRow.ToRow Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance Database.PostgreSQL.Simple.FromRow.FromRow Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance GHC.Show.Show Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance GHC.Classes.Ord Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance GHC.Generics.Generic Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance GHC.Classes.Eq Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance Database.PostgreSQL.Entity.Types.Entity Database.PostgreSQL.Entity.Internal.BlogPost.Tags instance GHC.Records.HasField x Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost a => GHC.OverloadedLabels.IsLabel x (Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost -> a) instance Database.PostgreSQL.Entity.Types.Entity Database.PostgreSQL.Entity.Internal.BlogPost.BlogPost instance Database.PostgreSQL.Simple.ToField.ToField Database.PostgreSQL.Entity.Internal.BlogPost.UUIDList instance GHC.Records.HasField x Database.PostgreSQL.Entity.Internal.BlogPost.Author a => GHC.OverloadedLabels.IsLabel x (Database.PostgreSQL.Entity.Internal.BlogPost.Author -> a)