{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiharg47kyx6uvj4giviq2qofndu5k64jgmoiip6hjav6lkihnz4q4",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mhop2au6j7m2"
  },
  "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"
}