{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreiharg47kyx6uvj4giviq2qofndu5k64jgmoiip6hjav6lkihnz4q4",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mhpl4hxwej32"
},
"path": "/t/ann-pg-schema-0-5-0-a-new-library-for-type-safe-postgresql-operation/13835#post_1",
"publishedAt": "2026-03-22T17:06:31.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"https://hackage.haskell.org/package/pg-schema"
],
"textContent": "Hi everyone!\n\nI’m pleased to announce the initial release of **pg-schema** , a Haskell library designed for a **database-first** workflow with PostgreSQL.\n\n**Hackage:** https://hackage.haskell.org/package/pg-schema\n\n### How it works\n\nThe library introspects your existing PostgreSQL database and **generates type-level descriptions** within your Haskell modules. These descriptions then serve as a single source of truth for generating type-safe DML operations.\n\nUnlike full-blown SQL DSLs that try to cover every possible query, **pg-schema** focuses on providing a compact and safe way to handle common patterns, especially when dealing with **nested data**.\n\n### Key Features:\n\n * **Schema Introspection:** Automatically generate Haskell type-level definitions from your live database.\n\n * **Type-Safe DML including Nested Data Support:** Generate `SELECT`, `INSERT`, and `UPDATE` operations with compile-time checks for table names, columns, types, relations between tables.\n\n * **Clean interface:** Two ways of describing input/output data: as an ordinal Haskell record or as labelled values.\n\n\n\n\n### Code example:\n\n\n data Order = Order { num :: Text, createdAt :: Day, items :: \\[OrdPos\\] } deriving Generic\n data OrdPos = OrdPos { id :: Int32, num :: Int32, article :: Article, price :: Double } deriving Generic\n data Article = Article { id :: Int32, name :: Text } deriving Generic\n type MyAnn tabName = 'Ann 5 CamelToSnake MySch (\"dbSchema\" ->> tabName)\n ...\n do\n\n void $ insertJSON_ (MyAnn \"orders\") conn\n [ \"num\" =: \"num1\" :. \"ord__ord_pos\" =:\n [ \"num\" =: 1 :. \"articleId\" =: 42 :. \"price\" =: 10\n , \"num\" =: 2 :. \"articleId\" =: 41 :. \"price\" =: 15 ] ]\n\n\n (xs :: \\[Order\\]) <- selectSch (MyAnn \"orders\") conn $ qRoot do\n qWhere $ \"created_at\" >? someDay\n &&& pchild \"ord__ord_pos\" defTabParam\n (pparent \"ord_pos__article\" $ \"name\" \\~\\~? \"%pencil%\")\n qOrderBy \\[descf \"created_at\", descf \"num\"\\]\n qPath \"ord__ord_pos\" do\n qWhere $ pparent \"ord_pos__article\" $ \"name\" \\~\\~? \"%pencil%\"\n qOrderBy \\[ascf \"num\"\\]\n qLimit 20\n",
"title": "[ANN] pg-schema-0.5.0. A new library for type-safe PostgreSql operation"
}