From 91c2d5e60f7b335478b19471ae886d3074a4bfec Mon Sep 17 00:00:00 2001 From: Shane O'Brien Date: Mon, 16 Oct 2023 08:45:04 +0100 Subject: [PATCH] Switch to `WITH _ AS MATERIALIZED (_)` for `materialize` --- changelog.d/20230707_183519_ollie_scriv.md | 2 +- rel8.cabal | 2 +- src/Rel8/Query/Materialize.hs | 20 +++++++++----------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/changelog.d/20230707_183519_ollie_scriv.md b/changelog.d/20230707_183519_ollie_scriv.md index 93f8ab58..203d8890 100644 --- a/changelog.d/20230707_183519_ollie_scriv.md +++ b/changelog.d/20230707_183519_ollie_scriv.md @@ -1,3 +1,3 @@ ### Added -- `Rel8.materialize` and `Rel8.Tabulate.materialize`, which add a materialization/optimisation fence to `SELECT` statements by binding a query to a `WITH` subquery. Note that Rel8 doesn't currently add `MATERIALIZE` to this, but may in the future. ([#180](https://github.com/circuithub/rel8/pull/180)) +- `Rel8.materialize` and `Rel8.Tabulate.materialize`, which add a materialization/optimisation fence to `SELECT` statements by binding a query to a `WITH` subquery. Note that explicitly materialized common table expressions are only supported in PostgreSQL 12 an higher. diff --git a/rel8.cabal b/rel8.cabal index 1876f057..9783d136 100644 --- a/rel8.cabal +++ b/rel8.cabal @@ -33,7 +33,7 @@ library , data-textual , hasql ^>= 1.6.1.2 , network-ip - , opaleye ^>= 0.10.1.0 + , opaleye ^>= 0.10.2.0 , pretty , profunctors , product-profunctors diff --git a/src/Rel8/Query/Materialize.hs b/src/Rel8/Query/Materialize.hs index 618d2d2a..64502711 100644 --- a/src/Rel8/Query/Materialize.hs +++ b/src/Rel8/Query/Materialize.hs @@ -2,13 +2,14 @@ module Rel8.Query.Materialize ( materialize - ) where + ) +where -- base import Prelude -- opaleye -import Opaleye.With ( withExplicit ) +import Opaleye.With ( withMaterializedExplicit ) -- rel8 import Rel8.Expr ( Expr ) @@ -26,19 +27,16 @@ import Rel8.Table.Opaleye ( unpackspec ) -- you're doing this can sometimes help to nudge it in a particular direction. -- -- 'materialize' is currently implemented in terms of Postgres' --- [@WITH](https://www.postgresql.org/docs/current/queries-with.html) syntax. --- Note that on newer versions of PostgreSQL starting with version 12, @WITH@ --- doesn't always automatically materialize if the results of the query aren't --- used more than once. We reserve the right to change the implementation of --- 'materialize' to use the newer @WITH foo AS MATERIALIZED bar@ syntax --- introduced in PostgreSQL 12 in the future. Currently Rel8 does not use --- @AS MATERIALIZED@ to support earlier PostgreSQL versions. +-- [@WITH](https://www.postgresql.org/docs/current/queries-with.html) syntax, +-- specifically the @WITH _ AS MATERIALIZED (_)@ form introduced in PostgreSQL +-- 12. This means that 'materialize' can only be used with PostgreSQL 12 or +-- newer. materialize :: (Table Expr a, Table Expr b) => Query a -> (Query a -> Query b) -> Query b materialize query f = (>>= rebind "with") . fromOpaleye $ - withExplicit unpackspec + withMaterializedExplicit unpackspec (toOpaleye query') (toOpaleye . f . fromOpaleye) where - query' = query >>= rebind "materialize" + query' = query