h&WS<      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Clment Delafargue, 2018 Thophile Choutri, 2021MITtheophile@choutri.eustable Safe-Inferred"%&'/125;=?  pg-entityThis sum type is given to the ,   and  ! functions to help with logging. pg-entity8Create a Pool Connection with the appropriate parameters pg-entity1Run a DBT action with no explicit error handling.#This functions is suited for using  MonadError error handling.Example 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 pg-entityQuery wrapper that returns a  of results pg-entityQuery wrapper that returns a ) of results and does not take an argument  pg-entity&Query wrapper that returns one result.  pg-entityQuery wrapper that returns one result and does not take an argument  pg-entity5Query wrapper for SQL statements which do not return.  pg-entityQuery wrapper for SQL statements that operate on multiple rows which do not return.     Clment Delafargue, 2018 Thophile Choutri, 2021 Koz Ross, 2021MITtheophile@choutri.eu Experimental Safe-Inferred"%&'/125;=? P pg-entityA wrapper for table fields. pg-entityUsing the Overloaded String syntax for Field names is forbidden. Koz Ross, 2021MITkoz.ross@retro-freedom.nz Experimental Safe-Inferred"%&'/125;=?  pg-entity'A quasi-quoter for safely constructing s.Example: instance Entity BlogPost where tableName = "blogposts" primaryKey = [field| blogpost_id |] fields = [ [field| blogpost_id |] , [field| author_id |] , [field| uuid_list :: uuid[] |] -- C This is where we specify an optional PostgreSQL type annotation , [field| title |] , [field| content |] , [field| created_at |] ] Clment Delafargue, 2018 Thophile Choutri, 2021MITtheophile@choutri.eustable Safe-Inferred!"%&'/0125;<=? pg-entity pg-entityWrapper used by the update function in order to have the primary key as the last parameter passed, since it appears in the WHERE clause. pg-entity/The modifiers that you can apply to the fields: , and its variations pg-entityCamelCase to kebab-case pg-entityCamelCase to snake_case pg-entity FieldModifier: taking a separator Char when transforming from CamelCase.  pg-entity+ to remove a certain prefix from the fields! pg-entityContains a list of  TextModifiers modifiers% pg-entity#Type-level options for Deriving Via' pg-entityTerm-level options0 pg-entityAn 0 stores the following information about the structure of a database table:Its nameIts primary keyThe fields it containsExample 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.1 pg-entity1The name of the table in the PostgreSQL database.2 pg-entityThe name of the schema; will be appended to the table name: schema."tablename"3 pg-entity*The name of the primary key for the table.4 pg-entityThe fields of the table.6 pg-entityGet the name of a field.7 pg-entity Get the type of a field, if any.% !"#$%&'(+),*-./01234567%0123467'(+),*5-./%&#"$!  Clment Delafargue, 2018 Thophile Choutri, 2021MITtheophile@choutri.eustable Safe-Inferred"%&'/125;=?&gZ pg-entity'Wrap the given text between parenthesesExamplesinParens "wrap me!" "(wrap me!)"[ pg-entity)Wrap the given text between double quotesExamplesquoteName "meow." "\"meow.\""\ pg-entityWrap the given text between single quotes, for literal text in an SQL query.Examplesliteral "meow." "'meow.'"] pg-entity$Safe getter that quotes a table nameExamplesgetTableName @Author "\"authors\""getTableName @Tags"public.\"tags\""^ pg-entity-Safe getter that quotes a table's primary keyExamplesgetPrimaryKey @Author"\"author_id\""getPrimaryKey @Tags"\"category\""` pg-entity0Accessor to the name of a field, with quotation.#getFieldName ([field| author_id |])"\"author_id\""a pg-entity5Produce a comma-separated list of an entity's fields.ExamplesexpandFields @BlogPost"\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\""b pg-entityProduce a comma-separated list of an entity's fields, qualified with the table nameExamplesexpandQualifiedFields @BlogPost"blogposts.\"blogpost_id\", blogposts.\"author_id\", blogposts.\"uuid_list\", blogposts.\"title\", blogposts.\"content\", blogposts.\"created_at\""c pg-entity.Produce a comma-separated list of an entity's 4$, qualified with an arbitrary prefixExamples2expandQualifiedFields' (fields @BlogPost) "legacy""legacy.\"blogpost_id\", legacy.\"author_id\", legacy.\"uuid_list\", legacy.\"title\", legacy.\"content\", legacy.\"created_at\""d pg-entityTake a prefix and a vector of fields, and qualifies each field with the prefixExamples$qualifyField @Author [field| name |]"authors.\"name\""e pg-entityTake a prefix and a vector of fields, and qualifies each field with the prefixExamples)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]f pg-entity"Produce a placeholder of the form  "field" = ?" with an optional type annotation.Examplesplaceholder [field| id |] "\"id\" = ?"placeholder $ [field| ids |] "\"ids\" = ?"#fmap placeholder $ fields @BlogPost["\"blogpost_id\" = ?","\"author_id\" = ?","\"uuid_list\" = ?","\"title\" = ?","\"content\" = ?","\"created_at\" = ?"]g pg-entity"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\" = ?"h pg-entityGenerate an appropriate number of @?@ placeholders given a vector of fields. Used to generate INSERT queries.Examples'generatePlaceholders $ fields @BlogPost"?, ?, ?, ?, ?, ?"i pg-entity9Produce an IS NOT NULL statement given a vector of 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"j pg-entity5Produce 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 |]]9"\"possibly_empty\" IS NULL AND \"that_one_too\" IS NULL"l pg-entity Since the  type has an IsString* instance, the process of converting from  to  to  is factored into this functionM This may be dangerous and an unregulated usage of this function may expose to you SQL injection attacks @since 0.0.1.0m pg-entityFor cases where combinator composition is tricky, we can safely get back to a  string from a M This may be dangerous and an unregulated usage of this function may expose to you SQL injection attacks @since 0.0.1.0n pg-entityThe n function takes a Text and a Vector Text and concatenates the vector after interspersing the first argument between each element of the list.ExamplesintercalateVector "~" [][]intercalateVector "~" ["nyan"]["nyan"].intercalateVector "~" ["nyan", "nyan", "nyan"]["nyan","~","nyan","~","nyan"]o pg-entityExamples,renderSortExpression ([field| title |], ASC)"\"title\" ASC"Z[\]^_`abcdefghijklmnoijkZ[\]`^_abcdefghlmno Clment Delafargue, 2018 Thophile Choutri, 2021MITtheophile@choutri.eustable Safe-Inferred"#%&'/125;=?NW%p pg-entity$Select an entity by its primary key.q pg-entitySelect precisely one entity by a provided field.r pg-entity5Select potentially many entities by a provided field.s pg-entity*Select statement with a non-null conditionSee  for the generated query.t pg-entity&Select statement with a null conditionSee  for the generated query.u pg-entitySelect statement when for an entity where the field is one of the options passedv pg-entity)Perform a INNER JOIN between two entitiesw pg-entity Perform a )INNER JOIN ON field1 WHERE field2 = value between two entitiesx pg-entity.Perform a SELECT + ORDER BY query on an entityy pg-entityInsert an entity.z pg-entityInsert an entity with a "ON CONFLICT DO UPDATE" clause on the primary key as the conflict target{ pg-entity"Insert multiple rows of an entity.| pg-entityUpdate an entity.The Id of the entity is put at the end of the query automatically through the use of . Examples 5let newAuthor = oldAuthor{@} update @Author newAuthor} pg-entity1Update rows of an entity matching the given valueExample let newName = "Tiberus McElroy" :: Text let oldName = "Johnson McElroy" :: Text updateFieldsBy @Author [[field| name |]] ([field| name |], oldName) (Only newName)~ pg-entity.Delete an entity according to its primary key. pg-entity)Delete rows according to the given fieldsExample deleteByField @BlogPost [[field| title |]] (Only "Echoes from the other world") pg-entity.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\"" pg-entityProduce a SELECT statement with explicit fields for a given entityExamples_selectWithFields @BlogPost [ [field| blogpost_id |], [field| created_at |] ]"SELECT \"blogposts\".\"blogpost_id\", \"blogposts\".\"created_at\" FROM \"\"blogposts\"\"" pg-entity1Produce a WHERE clause, given a vector of fields."It is most useful composed with a  or , which is why these two combinations have their dedicated functions, but the user is free to compose their own queries.The 0 constraint is required for  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.Examples4_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\" = ?"4_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\" = ?" pg-entity9Produce 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\" = ?" pg-entityProduce a SELECT statement where the provided fields are checked for being non-null. r6_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" pg-entityProduce a SELECT statement where the provided fields are checked for being null.3_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" pg-entityProduce 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')" pg-entity*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)" pg-entity+Produce a "INNER JOIN @ USING(@)" fragment.Examples)_innerJoin @BlogPost [field| author_id |]," INNER JOIN \"blogposts\" USING(author_id)" pg-entityProduce 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)" pg-entity*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\" = ?" pg-entity1Produce an INSERT statement for the given entity.Examples_insert @BlogPost"INSERT INTO \"blogposts\" (\"blogpost_id\", \"author_id\", \"uuid_list\", \"title\", \"content\", \"created_at\") VALUES (?, ?, ?, ?, ?, ?)" pg-entity;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" pg-entity?Produce an UPDATE statement for the given entity by primary keyExamples_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\" = ?" pg-entityProduce 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\" = ?" pg-entityProduce an UPDATE statement for the given entity and fields, by primary key.)_updateFields @Author [ [field| name |] ]"UPDATE \"authors\" SET (\"name\") = ROW(?) WHERE \"author_id\" = ?" pg-entityProduce 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\" = ?" pg-entityProduce a DELETE statement for the given entity, with a match on the Primary KeyExamples_delete @BlogPost5"DELETE FROM \"blogposts\" WHERE \"blogpost_id\" = ?" pg-entity:Produce a DELETE statement for the given entity and fieldsExamples_deleteWhere @BlogPost [[field| title |], [field| created_at |]]"DELETE FROM \"blogposts\" WHERE \"title\" = ? AND \"created_at\" = ?" pg-entity?Produce an ORDER BY clause with one field and a sorting keywordExamples _orderBy ([field| title |], ASC)" ORDER BY \"title\" ASC" pg-entityProduce an ORDER BY clause with many fields and sorting keywordsExamples_orderByMany (V.fromList [([field| title |], ASC), ([field| created_at |], DESC)])." ORDER BY \"title\" ASC, \"created_at\" DESC"w pg-entity2The field over which the two tables will be joined pg-entityThe field in the where clause pg-entityThe value of the where clausez pg-entityEntity to insert pg-entity%Fields to replace in case of conflict} pg-entityFields to change pg-entity%Field on which to match and its value pg-entityNew values of those fields pg-entityField names to update pg-entityField on which to match+01234pqrstuvwxyz{|}~+01234pqrstuvwxy{z|}~ Clment Delafargue, 2018 Thophile Choutri, 2021 Koz Ross, 2021MITtheophile@choutri.eustable Safe-Inferred"#%&'/125;=?R  pg-entity$The BlogPost data-type. Look at its 0 instance declaration for how to handle a "uuid[]" PostgreSQL type. pg-entity Primary key pg-entity;Foreign keys, for which we need an explicit type annotation pg-entity?A type that will need an explicit type annotation in the schema pg-entityWrapper around the UUID type pg-entityAuthor data-type pg-entityWrapper around the UUID type pg-entityA specialisation of the y function. !insertBlogPost = insert @BlogPost pg-entity,A function to insert many blogposts at once. pg-entityA specialisation of the 'Database.PostgreSQL.Entity.insert function. insertAuthor = insert @Author pg-entity*A function to insert many authors at once.      !"#$%&'()*+,--./01223456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~(pg-entity-0.0.4.2-DNLRA6UcDBgKdxzm4fCfCcDatabase.PostgreSQL.Entity.DBT*Database.PostgreSQL.Entity.Internal.Unsafe&Database.PostgreSQL.Entity.Internal.QQ Database.PostgreSQL.Entity.Types#Database.PostgreSQL.Entity.InternalDatabase.PostgreSQL.Entity,Database.PostgreSQL.Entity.Internal.BlogPost QueryNatureSelectInsertUpdateDeletemkPoolwithPoolqueryquery_queryOne queryOne_execute executeMany$fEqQueryNature$fShowQueryNatureField$fIsStringField $fEqField $fShowFieldfield SortKeywordASCDESC UpdateRow$sel:getUpdate:UpdateRow TextModifiergetTextModifier CamelToKebab CamelToSnakeCamelTo StripPrefixFieldModifiersSchema PrimaryKey TableName EntityOptions entityOptionsOptions$sel:tableNameModifiers:Options$sel:schemaModifier:Options $sel:primaryKeyModifiers:Options$sel:fieldModifiers:Options GenericEntity#$sel:getGenericEntity:GenericEntityEntity tableNameschema primaryKeyfieldsdefaultEntityOptions fieldName fieldType $fGetFieldsM1$fGetFieldsM10$fGetFieldsM11$fGetFields:*: $fGetFieldsK1$fGetFields:+: $fGetFieldsU1 $fGetFieldsV1$fGetTableNameM1$fGetTableNameM10$fGetTableNameM11$fGetTableName:*:$fGetTableNameK1$fGetTableName:+:$fGetTableNameU1$fGetTableNameV1$fEntityOptions[][]$fEntityGenericEntity$fTextModifierTYPEStripPrefix$fTextModifier[]:$fTextModifier[][]$fEntityOptions[]:$fEntityOptions[]:0$fEntityOptions[]:1$fEntityOptions[]:2$fGetNameSymbolname$fTextModifierTYPECamelTo$fToRowUpdateRow$fEqSortKeyword$fShowSortKeyword$fDisplaySortKeyword $fEqUpdateRow$fShowUpdateRow$fEntityUpdateRowinParens quoteNameliteral getTableName getPrimaryKeyprefix getFieldName expandFieldsexpandQualifiedFieldsexpandQualifiedFields' qualifyField qualifyFields placeholder placeholder'generatePlaceholders isNotNullisNullisIn textToQuery queryToTextintercalateVectorrenderSortExpression selectByIdselectOneByFieldselectManyByFieldselectWhereNotNullselectWhereNullselectOneWhereInjoinSelectByIdjoinSelectOneByField selectOrderByinsertupsert insertManyupdateupdateFieldsBydelete deleteByField_select_selectWithFields_where _selectWhere_selectWhereNotNull_selectWhereNull_selectWhereIn _joinSelect _innerJoin_joinSelectWithFields_joinSelectOneByField_insert_onConflictDoUpdate_update _updateBy _updateFields_updateFieldsBy_delete _deleteWhere_orderBy _orderByManyTags$sel:category:Tags$sel:labels:TagsBlogPost$sel:blogPostId:BlogPost$sel:authorId:BlogPost$sel:uuidList:BlogPost$sel:title:BlogPost$sel:content:BlogPost$sel:createdAt:BlogPostUUIDList$sel:getUUIDList:UUIDList BlogPostId$sel:getBlogPostId:BlogPostIdAuthor$sel:authorId:Author$sel:name:Author$sel:createdAt:AuthorAuthorId$sel:getAuthorId:AuthorIdinsertBlogPostupsertBlogPostbulkInsertBlogPosts insertAuthorbulkInsertAuthors $fIsLabelxFUN$fToFieldUUIDList$fEntityBlogPost$fIsLabelxFUN0 $fEntityTags $fEqBlogPost$fGenericBlogPost $fOrdBlogPost$fShowBlogPost$fFromRowBlogPost$fToRowBlogPost$fGenericUUIDList$fShowUUIDList $fEqUUIDList$fFromFieldUUIDList $fOrdUUIDList$fEqBlogPostId$fFromFieldBlogPostId$fOrdBlogPostId$fShowBlogPostId$fToFieldBlogPostId $fEqAuthor$fGenericAuthor $fOrdAuthor $fShowAuthor$fFromRowAuthor $fToRowAuthor$fEntityAuthor $fEqAuthorId$fFromFieldAuthorId $fOrdAuthorId$fShowAuthorId$fToFieldAuthorId&vector-0.13.0.0-7U8pFThXyYFEKl1vrDAyiE Data.VectorVector.postgresql-simple-0.6.5-9lMCOAAz8h7E0gKB1ja5Mp Database.PostgreSQL.Simple.TypesQuery!text-2.0.1-7QprYqjHeGcJLVq8G3zLGrData.Text.InternalTextbaseGHC.BaseString