-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for two forms of PostgreSQL
WITH
syntax; loop
and `ma…
…terialize`
- Loading branch information
1 parent
fef9064
commit 1f61962
Showing
7 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{-# language FlexibleContexts #-} | ||
|
||
module Rel8.Query.Loop | ||
( loop | ||
) where | ||
|
||
-- base | ||
import Prelude | ||
|
||
-- opaleye | ||
import Opaleye.With ( withRecursiveExplicit ) | ||
|
||
-- rel8 | ||
import Rel8.Expr ( Expr ) | ||
import Rel8.Query ( Query ) | ||
import Rel8.Query.Opaleye ( fromOpaleye, toOpaleye ) | ||
import Rel8.Table ( Table ) | ||
import Rel8.Table.Opaleye ( binaryspec ) | ||
|
||
|
||
-- | 'loop' allows the construction of recursive queries, using Postgres' | ||
-- [@WITH RECURSIVE@](https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-RECURSIVE) | ||
-- under the hood. The first argument to 'loop' is what the Postgres | ||
-- documentation refers to as the \"non-recursive term\" and the second | ||
-- argument is the \"recursive term\", which is defined in terms of the result | ||
-- of the \"non-recursive term\". | ||
loop :: Table Expr a => Query a -> (a -> Query a) -> Query a | ||
loop base recurse = | ||
fromOpaleye $ withRecursiveExplicit binaryspec base' recurse' | ||
where | ||
base' = toOpaleye base | ||
recurse' = toOpaleye . recurse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{-# language FlexibleContexts #-} | ||
|
||
module Rel8.Query.Materialize | ||
( materialize | ||
) where | ||
|
||
-- base | ||
import Prelude | ||
|
||
-- opaleye | ||
import Opaleye.With ( withExplicit ) | ||
|
||
-- rel8 | ||
import Rel8.Expr ( Expr ) | ||
import Rel8.Query ( Query ) | ||
import Rel8.Query.Opaleye ( fromOpaleye, toOpaleye ) | ||
import Rel8.Table ( Table ) | ||
import Rel8.Table.Opaleye ( unpackspec ) | ||
|
||
|
||
-- | 'materialize' takes a 'Query' and fully evaluates it and caches the | ||
-- results thereof, and returns a new 'Query' that simply looks up these | ||
-- cached results. It's usually best not to use this and to let the Postgres | ||
-- optimizer decide for itself what's best, but if you know what 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. | ||
materialize :: Table Expr a => Query a -> Query (Query a) | ||
materialize query = fromOpaleye $ | ||
withExplicit unpackspec (toOpaleye query) (pure . fromOpaleye) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{-# language LambdaCase #-} | ||
|
||
module Rel8.Statement.Create | ||
( Create(..) | ||
, ppCreate | ||
) | ||
where | ||
|
||
-- base | ||
import Prelude () | ||
|
||
-- pretty | ||
import Text.PrettyPrint ( Doc, text ) | ||
|
||
|
||
data Create = Create | CreateOrReplace | ||
|
||
|
||
ppCreate :: Create -> Doc | ||
ppCreate = \case | ||
Create -> text "CREATE" | ||
CreateOrReplace -> text "CREATE OR REPLACE" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
{-# language FlexibleContexts #-} | ||
{-# language MonoLocalBinds #-} | ||
|
||
module Rel8.Statement.Index | ||
( createIndex | ||
, createOrReplaceIndex | ||
) | ||
where | ||
|
||
-- base | ||
import Prelude | ||
|
||
-- hasql | ||
import qualified Hasql.Decoders as Hasql | ||
import qualified Hasql.Encoders as Hasql | ||
import qualified Hasql.Statement as Hasql | ||
|
||
-- rel8 | ||
import Rel8.Query ( Query ) | ||
import Rel8.Schema.Name ( Name ) | ||
import Rel8.Schema.Table ( TableSchema ) | ||
import Rel8.Statement.Create ( Create(..), ppCreate ) | ||
import Rel8.Statement.Insert ( ppInto ) | ||
import Rel8.Statement.Select ( ppSelect ) | ||
import Rel8.Table (Table) | ||
import Rel8.Table.Projection (Projecting, Projection) | ||
|
||
-- pretty | ||
import Text.PrettyPrint ( Doc, (<+>), ($$), text ) | ||
|
||
-- text | ||
import qualified Data.Text as Text | ||
import Data.Text.Encoding ( encodeUtf8 ) | ||
|
||
|
||
createIndex :: (Table Name names, Projecting names index) | ||
=> TableSchema names -> Projection names index -> Hasql.Statement () () | ||
createIndex = | ||
createIndexGeneric Create | ||
|
||
|
||
createOrReplaceIndex :: (Table Name names, Projecting names index) | ||
=> TableSchema names -> Projection names index -> Hasql.Statement () () | ||
createOrReplaceIndex = | ||
createIndexGeneric CreateOrReplace | ||
|
||
|
||
createIndexGeneric :: (Table Name names, Projecting names index) | ||
=> Create -> TableSchema names -> Projection names index -> Hasql.Statement () () | ||
createIndexGeneric create table index = undefined | ||
|
||
|
||
|
||
|
||
{- | ||
createIndexGeneric :: Selects names exprs | ||
=> Create -> TableSchema names -> Query exprs -> Hasql.Statement () () | ||
createIndexGeneric create schema query = | ||
Hasql.Statement bytes params decode prepare | ||
where | ||
bytes = encodeUtf8 (Text.pack sql) | ||
params = Hasql.noParams | ||
decode = Hasql.noResult | ||
prepare = False | ||
sql = show doc | ||
doc = ppCreate schema query create materialization | ||
ppCreate :: Selects names exprs | ||
=> TableSchema names -> Query exprs -> Create -> Materialization -> Doc | ||
ppCreate schema query create materialization = | ||
ppCreate create <+> materialized <+> text "VIEW" <+> | ||
ppInto schema $$ | ||
text "AS" <+> | ||
ppSelect query | ||
where | ||
materialized = case materialization of | ||
Materialized -> text "MATERIALIZED" | ||
NonMaterialized -> mempty | ||
-} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters